Git fork

Makefile: wire up the clar unit testing framework

Wire up the clar unit testing framework by introducing a new
"unit-tests" executable. In contrast to the existing framework, this
will result in a single executable for all test suites. The ability to
pick specific tests to execute is retained via functionality built into
the clar itself.

Note that we need to be a bit careful about how we need to invalidate
our Makefile rules. While we obviously have to regenerate the clar suite
when our test suites change, we also have to invalidate it in case any
of the test suites gets removed. We do so by using our typical pattern
of creating a `GIT-TEST-SUITES` file that gets updated whenever the set
of test suites changes, so that we can easily depend on that file.

Another specialty is that we generate a "clar-decls.h" file. The test
functions are neither static, nor do they have external declarations.
This is because they are getting parsed via "generate.py", which then
creates the external generations that get populated into an array. These
declarations are only seen by the main function though.

The consequence is that we will get a bunch of "missing prototypes"
errors from our compiler for each of these test functions. To fix those
errors, we extract the `extern` declarations from "clar.suite" and put
them into a standalone header that then gets included by each of our
unit tests. This gets rid of compiler warnings for every function which
has been extracted by "generate.py". More importantly though, it does
_not_ get rid of warnings in case a function really isn't being used by
anything. Thus, it would cause a compiler error if a function name was
mistyped and thus not picked up by "generate.py".

The test driver "unit-test.c" is an empty stub for now. It will get
implemented in the next commit.

Signed-off-by: Patrick Steinhardt <ps@pks.im>
Signed-off-by: Junio C Hamano <gitster@pobox.com>

authored by

Patrick Steinhardt and committed by
Junio C Hamano
8bc5d33b 416f4585

+95 -4
+1
.gitignore
··· 9 /GIT-PYTHON-VARS 10 /GIT-SCRIPT-DEFINES 11 /GIT-SPATCH-DEFINES 12 /GIT-USER-AGENT 13 /GIT-VERSION-FILE 14 /bin-wrappers/
··· 9 /GIT-PYTHON-VARS 10 /GIT-SCRIPT-DEFINES 11 /GIT-SPATCH-DEFINES 12 + /GIT-TEST-SUITES 13 /GIT-USER-AGENT 14 /GIT-VERSION-FILE 15 /bin-wrappers/
+32 -4
Makefile
··· 914 GENERATED_H += command-list.h 915 GENERATED_H += config-list.h 916 GENERATED_H += hook-list.h 917 918 .PHONY: generated-hdrs 919 generated-hdrs: $(GENERATED_H) ··· 1333 THIRD_PARTY_SOURCES += sha1dc/% 1334 THIRD_PARTY_SOURCES += $(UNIT_TEST_DIR)/clar/% 1335 THIRD_PARTY_SOURCES += $(UNIT_TEST_DIR)/clar/clar/% 1336 1337 UNIT_TEST_PROGRAMS += t-ctype 1338 UNIT_TEST_PROGRAMS += t-example-decorate ··· 2714 OBJECTS += $(FUZZ_OBJS) 2715 OBJECTS += $(REFTABLE_OBJS) $(REFTABLE_TEST_OBJS) 2716 OBJECTS += $(UNIT_TEST_OBJS) 2717 2718 ifndef NO_CURL 2719 OBJECTS += http.o http-walker.o remote-curl.o ··· 3216 3217 test_bindir_programs := $(patsubst %,bin-wrappers/%,$(BINDIR_PROGRAMS_NEED_X) $(BINDIR_PROGRAMS_NO_X) $(TEST_PROGRAMS_NEED_X)) 3218 3219 - all:: $(TEST_PROGRAMS) $(test_bindir_programs) $(UNIT_TEST_PROGS) 3220 3221 bin-wrappers/%: wrap-for-bin.sh 3222 $(call mkdir_p_parent_template) ··· 3648 3649 artifacts-tar:: $(ALL_COMMANDS_TO_INSTALL) $(SCRIPT_LIB) $(OTHER_PROGRAMS) \ 3650 GIT-BUILD-OPTIONS $(TEST_PROGRAMS) $(test_bindir_programs) \ 3651 - $(UNIT_TEST_PROGS) $(MOFILES) 3652 $(QUIET_SUBDIR0)templates $(QUIET_SUBDIR1) \ 3653 SHELL_PATH='$(SHELL_PATH_SQ)' PERL_PATH='$(PERL_PATH_SQ)' 3654 test -n "$(ARTIFACTS_DIRECTORY)" ··· 3704 3705 clean: profile-clean coverage-clean cocciclean 3706 $(RM) -r .build $(UNIT_TEST_BIN) 3707 $(RM) po/git.pot po/git-core.pot 3708 $(RM) git.res 3709 $(RM) $(OBJECTS) ··· 3863 $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \ 3864 $(filter %.o,$^) $(filter %.a,$^) $(LIBS) 3865 3866 .PHONY: build-unit-tests unit-tests 3867 - build-unit-tests: $(UNIT_TEST_PROGS) 3868 - unit-tests: $(UNIT_TEST_PROGS) t/helper/test-tool$X 3869 $(MAKE) -C t/ unit-tests
··· 914 GENERATED_H += command-list.h 915 GENERATED_H += config-list.h 916 GENERATED_H += hook-list.h 917 + GENERATED_H += $(UNIT_TEST_DIR)/clar-decls.h 918 + GENERATED_H += $(UNIT_TEST_DIR)/clar.suite 919 920 .PHONY: generated-hdrs 921 generated-hdrs: $(GENERATED_H) ··· 1335 THIRD_PARTY_SOURCES += sha1dc/% 1336 THIRD_PARTY_SOURCES += $(UNIT_TEST_DIR)/clar/% 1337 THIRD_PARTY_SOURCES += $(UNIT_TEST_DIR)/clar/clar/% 1338 + 1339 + UNIT_TESTS_PROG = $(UNIT_TEST_BIN)/unit-tests$(X) 1340 + UNIT_TESTS_OBJS = $(patsubst %,$(UNIT_TEST_DIR)/%.o,$(UNIT_TESTS_SUITES)) 1341 + UNIT_TESTS_OBJS += $(UNIT_TEST_DIR)/clar/clar.o 1342 + UNIT_TESTS_OBJS += $(UNIT_TEST_DIR)/unit-test.o 1343 1344 UNIT_TEST_PROGRAMS += t-ctype 1345 UNIT_TEST_PROGRAMS += t-example-decorate ··· 2721 OBJECTS += $(FUZZ_OBJS) 2722 OBJECTS += $(REFTABLE_OBJS) $(REFTABLE_TEST_OBJS) 2723 OBJECTS += $(UNIT_TEST_OBJS) 2724 + OBJECTS += $(UNIT_TESTS_OBJS) 2725 2726 ifndef NO_CURL 2727 OBJECTS += http.o http-walker.o remote-curl.o ··· 3224 3225 test_bindir_programs := $(patsubst %,bin-wrappers/%,$(BINDIR_PROGRAMS_NEED_X) $(BINDIR_PROGRAMS_NO_X) $(TEST_PROGRAMS_NEED_X)) 3226 3227 + all:: $(TEST_PROGRAMS) $(test_bindir_programs) $(UNIT_TEST_PROGS) $(UNIT_TESTS_PROG) 3228 3229 bin-wrappers/%: wrap-for-bin.sh 3230 $(call mkdir_p_parent_template) ··· 3656 3657 artifacts-tar:: $(ALL_COMMANDS_TO_INSTALL) $(SCRIPT_LIB) $(OTHER_PROGRAMS) \ 3658 GIT-BUILD-OPTIONS $(TEST_PROGRAMS) $(test_bindir_programs) \ 3659 + $(UNIT_TEST_PROGS) $(UNIT_TESTS_PROG) $(MOFILES) 3660 $(QUIET_SUBDIR0)templates $(QUIET_SUBDIR1) \ 3661 SHELL_PATH='$(SHELL_PATH_SQ)' PERL_PATH='$(PERL_PATH_SQ)' 3662 test -n "$(ARTIFACTS_DIRECTORY)" ··· 3712 3713 clean: profile-clean coverage-clean cocciclean 3714 $(RM) -r .build $(UNIT_TEST_BIN) 3715 + $(RM) GIT-TEST-SUITES 3716 $(RM) po/git.pot po/git-core.pot 3717 $(RM) git.res 3718 $(RM) $(OBJECTS) ··· 3872 $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \ 3873 $(filter %.o,$^) $(filter %.a,$^) $(LIBS) 3874 3875 + GIT-TEST-SUITES: FORCE 3876 + @FLAGS='$(UNIT_TESTS_SUITES)'; \ 3877 + if test x"$$FLAGS" != x"`cat GIT-TEST-SUITES 2>/dev/null`" ; then \ 3878 + echo >&2 " * new test suites"; \ 3879 + echo "$$FLAGS" >GIT-TEST-SUITES; \ 3880 + fi 3881 + 3882 + $(UNIT_TEST_DIR)/clar-decls.h: $(patsubst %,$(UNIT_TEST_DIR)/%.c,$(UNIT_TESTS_SUITES)) GIT-TEST-SUITES 3883 + $(QUIET_GEN)for suite in $(UNIT_TESTS_SUITES); do \ 3884 + sed -ne "s/^\(void test_$${suite}__[a-zA-Z_0-9][a-zA-Z_0-9]*(void)$$\)/extern \1;/p" $(UNIT_TEST_DIR)/$$suite.c; \ 3885 + done >$@ 3886 + $(UNIT_TEST_DIR)/clar.suite: $(UNIT_TEST_DIR)/clar-decls.h 3887 + $(QUIET_GEN)awk -f $(UNIT_TEST_DIR)/clar-generate.awk $< >$(UNIT_TEST_DIR)/clar.suite 3888 + $(UNIT_TESTS_OBJS): $(UNIT_TEST_DIR)/clar-decls.h 3889 + $(UNIT_TESTS_OBJS): EXTRA_CPPFLAGS = -I$(UNIT_TEST_DIR) 3890 + $(UNIT_TESTS_PROG): $(UNIT_TEST_DIR)/clar.suite $(UNIT_TESTS_OBJS) $(GITLIBS) GIT-LDFLAGS 3891 + $(call mkdir_p_parent_template) 3892 + $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS) 3893 + 3894 .PHONY: build-unit-tests unit-tests 3895 + build-unit-tests: $(UNIT_TEST_PROGS) $(UNIT_TESTS_PROG) 3896 + unit-tests: $(UNIT_TEST_PROGS) $(UNIT_TESTS_PROG) t/helper/test-tool$X 3897 $(MAKE) -C t/ unit-tests
+1
t/Makefile
··· 48 CHAINLINT = '$(PERL_PATH_SQ)' chainlint.pl 49 UNIT_TEST_SOURCES = $(wildcard unit-tests/t-*.c) 50 UNIT_TEST_PROGRAMS = $(patsubst unit-tests/%.c,unit-tests/bin/%$(X),$(UNIT_TEST_SOURCES)) 51 UNIT_TESTS = $(sort $(UNIT_TEST_PROGRAMS)) 52 UNIT_TESTS_NO_DIR = $(notdir $(UNIT_TESTS)) 53
··· 48 CHAINLINT = '$(PERL_PATH_SQ)' chainlint.pl 49 UNIT_TEST_SOURCES = $(wildcard unit-tests/t-*.c) 50 UNIT_TEST_PROGRAMS = $(patsubst unit-tests/%.c,unit-tests/bin/%$(X),$(UNIT_TEST_SOURCES)) 51 + UNIT_TEST_PROGRAMS += unit-tests/bin/unit-tests$(X) 52 UNIT_TESTS = $(sort $(UNIT_TEST_PROGRAMS)) 53 UNIT_TESTS_NO_DIR = $(notdir $(UNIT_TESTS)) 54
+2
t/unit-tests/.gitignore
··· 1 /bin
··· 1 /bin 2 + /clar.suite 3 + /clar-decls.h
+50
t/unit-tests/clar-generate.awk
···
··· 1 + function add_suite(suite, initialize, cleanup, count) { 2 + if (!suite) return 3 + suite_count++ 4 + callback_count += count 5 + suites = suites " {\n" 6 + suites = suites " \"" suite "\",\n" 7 + suites = suites " " initialize ",\n" 8 + suites = suites " " cleanup ",\n" 9 + suites = suites " _clar_cb_" suite ", " count ", 1\n" 10 + suites = suites " },\n" 11 + } 12 + 13 + BEGIN { 14 + suites = "static struct clar_suite _clar_suites[] = {\n" 15 + } 16 + 17 + { 18 + print 19 + name = $3; sub(/\(.*$/, "", name) 20 + suite = name; sub(/^test_/, "", suite); sub(/__.*$/, "", suite) 21 + short_name = name; sub(/^.*__/, "", short_name) 22 + cb = "{ \"" short_name "\", &" name " }" 23 + if (suite != prev_suite) { 24 + add_suite(prev_suite, initialize, cleanup, count) 25 + if (callbacks) callbacks = callbacks "};\n" 26 + callbacks = callbacks "static const struct clar_func _clar_cb_" suite "[] = {\n" 27 + initialize = "{ NULL, NULL }" 28 + cleanup = "{ NULL, NULL }" 29 + count = 0 30 + prev_suite = suite 31 + } 32 + if (short_name == "initialize") { 33 + initialize = cb 34 + } else if (short_name == "cleanup") { 35 + cleanup = cb 36 + } else { 37 + callbacks = callbacks " " cb ",\n" 38 + count++ 39 + } 40 + } 41 + 42 + END { 43 + add_suite(suite, initialize, cleanup, count) 44 + suites = suites "};" 45 + if (callbacks) callbacks = callbacks "};" 46 + print callbacks 47 + print suites 48 + print "static const size_t _clar_suite_count = " suite_count ";" 49 + print "static const size_t _clar_callback_count = " callback_count ";" 50 + }
+6
t/unit-tests/unit-test.c
···
··· 1 + #include "unit-test.h" 2 + 3 + int cmd_main(int argc UNUSED, const char **argv UNUSED) 4 + { 5 + return 0; 6 + }
+3
t/unit-tests/unit-test.h
···
··· 1 + #include "git-compat-util.h" 2 + #include "clar/clar.h" 3 + #include "clar-decls.h"