mirror of
https://github.com/git/git
synced 2024-11-04 16:17:49 +00:00
Merge branch 'js/unit-test-suite-runner'
The "test-tool" has been taught to run testsuite tests in parallel, bypassing the need to use the "prove" tool. * js/unit-test-suite-runner: cmake: let `test-tool` run the unit tests, too ci: use test-tool as unit test runner on Windows t/Makefile: run unit tests alongside shell tests unit tests: add rule for running with test-tool test-tool run-command testsuite: support unit tests test-tool run-command testsuite: remove hardcoded filter test-tool run-command testsuite: get shell from env t0080: turn t-basic unit test into a helper
This commit is contained in:
commit
b7a1d47ba5
11 changed files with 74 additions and 30 deletions
6
Makefile
6
Makefile
|
@ -794,6 +794,7 @@ TEST_BUILTINS_OBJS += test-dump-split-index.o
|
|||
TEST_BUILTINS_OBJS += test-dump-untracked-cache.o
|
||||
TEST_BUILTINS_OBJS += test-env-helper.o
|
||||
TEST_BUILTINS_OBJS += test-example-decorate.o
|
||||
TEST_BUILTINS_OBJS += test-example-tap.o
|
||||
TEST_BUILTINS_OBJS += test-find-pack.o
|
||||
TEST_BUILTINS_OBJS += test-fsmonitor-client.o
|
||||
TEST_BUILTINS_OBJS += test-genrandom.o
|
||||
|
@ -1333,7 +1334,6 @@ THIRD_PARTY_SOURCES += compat/regex/%
|
|||
THIRD_PARTY_SOURCES += sha1collisiondetection/%
|
||||
THIRD_PARTY_SOURCES += sha1dc/%
|
||||
|
||||
UNIT_TEST_PROGRAMS += t-basic
|
||||
UNIT_TEST_PROGRAMS += t-mem-pool
|
||||
UNIT_TEST_PROGRAMS += t-strbuf
|
||||
UNIT_TEST_PROGRAMS += t-ctype
|
||||
|
@ -3235,7 +3235,7 @@ perf: all
|
|||
|
||||
.PRECIOUS: $(TEST_OBJS)
|
||||
|
||||
t/helper/test-tool$X: $(patsubst %,t/helper/%,$(TEST_BUILTINS_OBJS))
|
||||
t/helper/test-tool$X: $(patsubst %,t/helper/%,$(TEST_BUILTINS_OBJS)) $(UNIT_TEST_DIR)/test-lib.o
|
||||
|
||||
t/helper/test-%$X: t/helper/test-%.o GIT-LDFLAGS $(GITLIBS) $(REFTABLE_TEST_LIB)
|
||||
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(filter %.a,$^) $(LIBS)
|
||||
|
@ -3888,5 +3888,5 @@ $(UNIT_TEST_PROGS): $(UNIT_TEST_BIN)/%$X: $(UNIT_TEST_DIR)/%.o $(UNIT_TEST_DIR)/
|
|||
|
||||
.PHONY: build-unit-tests unit-tests
|
||||
build-unit-tests: $(UNIT_TEST_PROGS)
|
||||
unit-tests: $(UNIT_TEST_PROGS)
|
||||
unit-tests: $(UNIT_TEST_PROGS) t/helper/test-tool$X
|
||||
$(MAKE) -C t/ unit-tests
|
||||
|
|
|
@ -53,8 +53,6 @@ if test -n "$run_tests"
|
|||
then
|
||||
group "Run tests" make test ||
|
||||
handle_failed_tests
|
||||
group "Run unit tests" \
|
||||
make DEFAULT_UNIT_TEST_TARGET=unit-tests-prove unit-tests
|
||||
fi
|
||||
check_unignored_build_artifacts
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ handle_failed_tests
|
|||
|
||||
# We only have one unit test at the moment, so run it in the first slice
|
||||
if [ "$1" == "0" ] ; then
|
||||
group "Run unit tests" make --quiet -C t unit-tests-prove
|
||||
group "Run unit tests" make --quiet -C t unit-tests-test-tool
|
||||
fi
|
||||
|
||||
check_unignored_build_artifacts
|
||||
|
|
|
@ -1005,10 +1005,11 @@ endforeach()
|
|||
|
||||
#test-tool
|
||||
parse_makefile_for_sources(test-tool_SOURCES "TEST_BUILTINS_OBJS")
|
||||
add_library(test-lib OBJECT ${CMAKE_SOURCE_DIR}/t/unit-tests/test-lib.c)
|
||||
|
||||
list(TRANSFORM test-tool_SOURCES PREPEND "${CMAKE_SOURCE_DIR}/t/helper/")
|
||||
add_executable(test-tool ${CMAKE_SOURCE_DIR}/t/helper/test-tool.c ${test-tool_SOURCES} ${test-reftable_SOURCES})
|
||||
target_link_libraries(test-tool common-main)
|
||||
target_link_libraries(test-tool test-lib common-main)
|
||||
|
||||
set_target_properties(test-fake-ssh test-tool
|
||||
PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/t/helper)
|
||||
|
|
14
t/Makefile
14
t/Makefile
|
@ -48,7 +48,8 @@ CHAINLINTTESTS = $(sort $(patsubst chainlint/%.test,%,$(wildcard chainlint/*.tes
|
|||
CHAINLINT = '$(PERL_PATH_SQ)' chainlint.pl
|
||||
UNIT_TEST_SOURCES = $(wildcard unit-tests/t-*.c)
|
||||
UNIT_TEST_PROGRAMS = $(patsubst unit-tests/%.c,unit-tests/bin/%$(X),$(UNIT_TEST_SOURCES))
|
||||
UNIT_TESTS = $(sort $(filter-out unit-tests/bin/t-basic%,$(UNIT_TEST_PROGRAMS)))
|
||||
UNIT_TESTS = $(sort $(UNIT_TEST_PROGRAMS))
|
||||
UNIT_TESTS_NO_DIR = $(notdir $(UNIT_TESTS))
|
||||
|
||||
# `test-chainlint` (which is a dependency of `test-lint`, `test` and `prove`)
|
||||
# checks all tests in all scripts via a single invocation, so tell individual
|
||||
|
@ -67,7 +68,7 @@ failed:
|
|||
test -z "$$failed" || $(MAKE) $$failed
|
||||
|
||||
prove: pre-clean check-chainlint $(TEST_LINT)
|
||||
@echo "*** prove ***"; $(CHAINLINTSUPPRESS) $(PROVE) --exec '$(TEST_SHELL_PATH_SQ)' $(GIT_PROVE_OPTS) $(T) :: $(GIT_TEST_OPTS)
|
||||
@echo "*** prove (shell & unit tests) ***"; $(CHAINLINTSUPPRESS) TEST_SHELL_PATH='$(TEST_SHELL_PATH_SQ)' $(PROVE) --exec ./run-test.sh $(GIT_PROVE_OPTS) $(T) $(UNIT_TESTS) :: $(GIT_TEST_OPTS)
|
||||
$(MAKE) clean-except-prove-cache
|
||||
|
||||
$(T):
|
||||
|
@ -76,7 +77,7 @@ $(T):
|
|||
$(UNIT_TESTS):
|
||||
@echo "*** $@ ***"; $@
|
||||
|
||||
.PHONY: unit-tests unit-tests-raw unit-tests-prove
|
||||
.PHONY: unit-tests unit-tests-raw unit-tests-prove unit-tests-test-tool
|
||||
unit-tests: $(DEFAULT_UNIT_TEST_TARGET)
|
||||
|
||||
unit-tests-raw: $(UNIT_TESTS)
|
||||
|
@ -84,6 +85,13 @@ unit-tests-raw: $(UNIT_TESTS)
|
|||
unit-tests-prove:
|
||||
@echo "*** prove - unit tests ***"; $(PROVE) $(GIT_PROVE_OPTS) $(UNIT_TESTS)
|
||||
|
||||
unit-tests-test-tool:
|
||||
@echo "*** test-tool - unit tests **"
|
||||
( \
|
||||
cd unit-tests/bin && \
|
||||
../../helper/test-tool$X run-command testsuite $(UNIT_TESTS_NO_DIR)\
|
||||
)
|
||||
|
||||
pre-clean:
|
||||
$(RM) -r '$(TEST_RESULTS_DIRECTORY_SQ)'
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "test-lib.h"
|
||||
#include "test-tool.h"
|
||||
#include "t/unit-tests/test-lib.h"
|
||||
|
||||
/*
|
||||
* The purpose of this "unit test" is to verify a few invariants of the unit
|
||||
|
@ -69,7 +70,7 @@ static void t_empty(void)
|
|||
; /* empty */
|
||||
}
|
||||
|
||||
int cmd_main(int argc, const char **argv)
|
||||
int cmd__example_tap(int argc, const char **argv)
|
||||
{
|
||||
test_res = TEST(check_res = check_int(1, ==, 1), "passing test");
|
||||
TEST(t_res(1), "passing test and assertion return 1");
|
|
@ -65,6 +65,7 @@ struct testsuite {
|
|||
struct string_list tests, failed;
|
||||
int next;
|
||||
int quiet, immediate, verbose, verbose_log, trace, write_junit_xml;
|
||||
const char *shell_path;
|
||||
};
|
||||
#define TESTSUITE_INIT { \
|
||||
.tests = STRING_LIST_INIT_DUP, \
|
||||
|
@ -80,7 +81,9 @@ static int next_test(struct child_process *cp, struct strbuf *err, void *cb,
|
|||
return 0;
|
||||
|
||||
test = suite->tests.items[suite->next++].string;
|
||||
strvec_pushl(&cp->args, "sh", test, NULL);
|
||||
if (suite->shell_path)
|
||||
strvec_push(&cp->args, suite->shell_path);
|
||||
strvec_push(&cp->args, test);
|
||||
if (suite->quiet)
|
||||
strvec_push(&cp->args, "--quiet");
|
||||
if (suite->immediate)
|
||||
|
@ -155,6 +158,8 @@ static int testsuite(int argc, const char **argv)
|
|||
.task_finished = test_finished,
|
||||
.data = &suite,
|
||||
};
|
||||
struct strbuf progpath = STRBUF_INIT;
|
||||
size_t path_prefix_len;
|
||||
|
||||
argc = parse_options(argc, argv, NULL, options,
|
||||
testsuite_usage, PARSE_OPT_STOP_AT_NON_OPTION);
|
||||
|
@ -162,26 +167,36 @@ static int testsuite(int argc, const char **argv)
|
|||
if (max_jobs <= 0)
|
||||
max_jobs = online_cpus();
|
||||
|
||||
/*
|
||||
* If we run without a shell, execute the programs directly from CWD.
|
||||
*/
|
||||
suite.shell_path = getenv("TEST_SHELL_PATH");
|
||||
if (!suite.shell_path)
|
||||
strbuf_addstr(&progpath, "./");
|
||||
path_prefix_len = progpath.len;
|
||||
|
||||
dir = opendir(".");
|
||||
if (!dir)
|
||||
die("Could not open the current directory");
|
||||
while ((d = readdir(dir))) {
|
||||
const char *p = d->d_name;
|
||||
|
||||
if (*p != 't' || !isdigit(p[1]) || !isdigit(p[2]) ||
|
||||
!isdigit(p[3]) || !isdigit(p[4]) || p[5] != '-' ||
|
||||
!ends_with(p, ".sh"))
|
||||
if (!strcmp(p, ".") || !strcmp(p, ".."))
|
||||
continue;
|
||||
|
||||
/* No pattern: match all */
|
||||
if (!argc) {
|
||||
string_list_append(&suite.tests, p);
|
||||
strbuf_setlen(&progpath, path_prefix_len);
|
||||
strbuf_addstr(&progpath, p);
|
||||
string_list_append(&suite.tests, progpath.buf);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (i = 0; i < argc; i++)
|
||||
if (!wildmatch(argv[i], p, 0)) {
|
||||
string_list_append(&suite.tests, p);
|
||||
strbuf_setlen(&progpath, path_prefix_len);
|
||||
strbuf_addstr(&progpath, p);
|
||||
string_list_append(&suite.tests, progpath.buf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -208,6 +223,7 @@ static int testsuite(int argc, const char **argv)
|
|||
|
||||
string_list_clear(&suite.tests, 0);
|
||||
string_list_clear(&suite.failed, 0);
|
||||
strbuf_release(&progpath);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ static struct test_cmd cmds[] = {
|
|||
{ "dump-untracked-cache", cmd__dump_untracked_cache },
|
||||
{ "env-helper", cmd__env_helper },
|
||||
{ "example-decorate", cmd__example_decorate },
|
||||
{ "example-tap", cmd__example_tap },
|
||||
{ "find-pack", cmd__find_pack },
|
||||
{ "fsmonitor-client", cmd__fsmonitor_client },
|
||||
{ "genrandom", cmd__genrandom },
|
||||
|
|
|
@ -24,6 +24,7 @@ int cmd__dump_untracked_cache(int argc, const char **argv);
|
|||
int cmd__dump_reftable(int argc, const char **argv);
|
||||
int cmd__env_helper(int argc, const char **argv);
|
||||
int cmd__example_decorate(int argc, const char **argv);
|
||||
int cmd__example_tap(int argc, const char **argv);
|
||||
int cmd__find_pack(int argc, const char **argv);
|
||||
int cmd__fsmonitor_client(int argc, const char **argv);
|
||||
int cmd__genrandom(int argc, const char **argv);
|
||||
|
|
18
t/run-test.sh
Executable file
18
t/run-test.sh
Executable file
|
@ -0,0 +1,18 @@
|
|||
#!/bin/sh
|
||||
|
||||
# A simple wrapper to run shell tests via TEST_SHELL_PATH,
|
||||
# or exec unit tests directly.
|
||||
|
||||
case "$1" in
|
||||
*.sh)
|
||||
if test -z "${TEST_SHELL_PATH}"
|
||||
then
|
||||
echo >&2 "ERROR: TEST_SHELL_PATH is empty or not set"
|
||||
exit 1
|
||||
fi
|
||||
exec "${TEST_SHELL_PATH}" "$@"
|
||||
;;
|
||||
*)
|
||||
exec "$@"
|
||||
;;
|
||||
esac
|
|
@ -9,50 +9,50 @@ test_expect_success 'TAP output from unit tests' '
|
|||
cat >expect <<-EOF &&
|
||||
ok 1 - passing test
|
||||
ok 2 - passing test and assertion return 1
|
||||
# check "1 == 2" failed at t/unit-tests/t-basic.c:76
|
||||
# check "1 == 2" failed at t/helper/test-example-tap.c:77
|
||||
# left: 1
|
||||
# right: 2
|
||||
not ok 3 - failing test
|
||||
ok 4 - failing test and assertion return 0
|
||||
not ok 5 - passing TEST_TODO() # TODO
|
||||
ok 6 - passing TEST_TODO() returns 1
|
||||
# todo check ${SQ}check(x)${SQ} succeeded at t/unit-tests/t-basic.c:25
|
||||
# todo check ${SQ}check(x)${SQ} succeeded at t/helper/test-example-tap.c:26
|
||||
not ok 7 - failing TEST_TODO()
|
||||
ok 8 - failing TEST_TODO() returns 0
|
||||
# check "0" failed at t/unit-tests/t-basic.c:30
|
||||
# check "0" failed at t/helper/test-example-tap.c:31
|
||||
# skipping test - missing prerequisite
|
||||
# skipping check ${SQ}1${SQ} at t/unit-tests/t-basic.c:32
|
||||
# skipping check ${SQ}1${SQ} at t/helper/test-example-tap.c:33
|
||||
ok 9 - test_skip() # SKIP
|
||||
ok 10 - skipped test returns 1
|
||||
# skipping test - missing prerequisite
|
||||
ok 11 - test_skip() inside TEST_TODO() # SKIP
|
||||
ok 12 - test_skip() inside TEST_TODO() returns 1
|
||||
# check "0" failed at t/unit-tests/t-basic.c:48
|
||||
# check "0" failed at t/helper/test-example-tap.c:49
|
||||
not ok 13 - TEST_TODO() after failing check
|
||||
ok 14 - TEST_TODO() after failing check returns 0
|
||||
# check "0" failed at t/unit-tests/t-basic.c:56
|
||||
# check "0" failed at t/helper/test-example-tap.c:57
|
||||
not ok 15 - failing check after TEST_TODO()
|
||||
ok 16 - failing check after TEST_TODO() returns 0
|
||||
# check "!strcmp("\thello\\\\", "there\"\n")" failed at t/unit-tests/t-basic.c:61
|
||||
# check "!strcmp("\thello\\\\", "there\"\n")" failed at t/helper/test-example-tap.c:62
|
||||
# left: "\011hello\\\\"
|
||||
# right: "there\"\012"
|
||||
# check "!strcmp("NULL", NULL)" failed at t/unit-tests/t-basic.c:62
|
||||
# check "!strcmp("NULL", NULL)" failed at t/helper/test-example-tap.c:63
|
||||
# left: "NULL"
|
||||
# right: NULL
|
||||
# check "${SQ}a${SQ} == ${SQ}\n${SQ}" failed at t/unit-tests/t-basic.c:63
|
||||
# check "${SQ}a${SQ} == ${SQ}\n${SQ}" failed at t/helper/test-example-tap.c:64
|
||||
# left: ${SQ}a${SQ}
|
||||
# right: ${SQ}\012${SQ}
|
||||
# check "${SQ}\\\\${SQ} == ${SQ}\\${SQ}${SQ}" failed at t/unit-tests/t-basic.c:64
|
||||
# check "${SQ}\\\\${SQ} == ${SQ}\\${SQ}${SQ}" failed at t/helper/test-example-tap.c:65
|
||||
# left: ${SQ}\\\\${SQ}
|
||||
# right: ${SQ}\\${SQ}${SQ}
|
||||
not ok 17 - messages from failing string and char comparison
|
||||
# BUG: test has no checks at t/unit-tests/t-basic.c:91
|
||||
# BUG: test has no checks at t/helper/test-example-tap.c:92
|
||||
not ok 18 - test with no checks
|
||||
ok 19 - test with no checks returns 0
|
||||
1..19
|
||||
EOF
|
||||
|
||||
! "$GIT_BUILD_DIR"/t/unit-tests/bin/t-basic >actual &&
|
||||
! test-tool example-tap >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
|
|
Loading…
Reference in a new issue