Skip to content

Commit 5d55832

Browse files
committed
Merge branch 'ps/clar-unit-test'
Import clar unit tests framework libgit2 folks invented for our use. * ps/clar-unit-test: Makefile: rename clar-related variables to avoid confusion clar: add CMake support t/unit-tests: convert ctype tests to use clar t/unit-tests: convert strvec tests to use clar t/unit-tests: implement test driver Makefile: wire up the clar unit testing framework Makefile: do not use sparse on third-party sources Makefile: make hdr-check depend on generated headers Makefile: fix sparse dependency on GENERATED_H clar: stop including `shellapi.h` unnecessarily clar(win32): avoid compile error due to unused `fs_copy()` clar: avoid compile error with mingw-w64 t/clar: fix compatibility with NonStop t: import the clar unit testing framework t: do not pass GIT_TEST_OPTS to unit tests with prove
2 parents 3fb7452 + c3de556 commit 5d55832

File tree

31 files changed

+3459
-234
lines changed

31 files changed

+3459
-234
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
/GIT-PYTHON-VARS
1010
/GIT-SCRIPT-DEFINES
1111
/GIT-SPATCH-DEFINES
12+
/GIT-TEST-SUITES
1213
/GIT-USER-AGENT
1314
/GIT-VERSION-FILE
1415
/bin-wrappers/

Documentation/technical/unit-tests.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,7 @@ GitHub / GitLab stars to estimate this.
203203
:criterion: https://github.com/Snaipe/Criterion[Criterion]
204204
:c-tap: https://github.com/rra/c-tap-harness/[C TAP]
205205
:check: https://libcheck.github.io/check/[Check]
206+
:clar: https://github.com/clar-test/clar[Clar]
206207

207208
[format="csv",options="header",width="33%",subs="specialcharacters,attributes,quotes,macros"]
208209
|=====
@@ -212,6 +213,7 @@ Framework,"<<license,License>>","<<vendorable-or-ubiquitous,Vendorable or ubiqui
212213
{criterion},{mit},{false},{partial},{true},{true},{true},{true},{true},{false},{true},19,1800
213214
{c-tap},{expat},{true},{partial},{partial},{true},{false},{true},{false},{false},{false},4,33
214215
{check},{lgpl},{false},{partial},{true},{true},{true},{false},{false},{false},{true},17,973
216+
{clar},{isc},{false},{partial},{true},{true},{true},{true},{false},{false},{true},1,192
215217
|=====
216218

217219
=== Additional framework candidates

Makefile

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -915,6 +915,8 @@ REFTABLE_LIB = reftable/libreftable.a
915915
GENERATED_H += command-list.h
916916
GENERATED_H += config-list.h
917917
GENERATED_H += hook-list.h
918+
GENERATED_H += $(UNIT_TEST_DIR)/clar-decls.h
919+
GENERATED_H += $(UNIT_TEST_DIR)/clar.suite
918920

919921
.PHONY: generated-hdrs
920922
generated-hdrs: $(GENERATED_H)
@@ -1332,8 +1334,16 @@ THIRD_PARTY_SOURCES += compat/poll/%
13321334
THIRD_PARTY_SOURCES += compat/regex/%
13331335
THIRD_PARTY_SOURCES += sha1collisiondetection/%
13341336
THIRD_PARTY_SOURCES += sha1dc/%
1337+
THIRD_PARTY_SOURCES += $(UNIT_TEST_DIR)/clar/%
1338+
THIRD_PARTY_SOURCES += $(UNIT_TEST_DIR)/clar/clar/%
1339+
1340+
CLAR_TEST_SUITES += ctype
1341+
CLAR_TEST_SUITES += strvec
1342+
CLAR_TEST_PROG = $(UNIT_TEST_BIN)/unit-tests$(X)
1343+
CLAR_TEST_OBJS = $(patsubst %,$(UNIT_TEST_DIR)/%.o,$(CLAR_TEST_SUITES))
1344+
CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/clar/clar.o
1345+
CLAR_TEST_OBJS += $(UNIT_TEST_DIR)/unit-test.o
13351346

1336-
UNIT_TEST_PROGRAMS += t-ctype
13371347
UNIT_TEST_PROGRAMS += t-example-decorate
13381348
UNIT_TEST_PROGRAMS += t-hash
13391349
UNIT_TEST_PROGRAMS += t-hashmap
@@ -1352,7 +1362,6 @@ UNIT_TEST_PROGRAMS += t-reftable-stack
13521362
UNIT_TEST_PROGRAMS += t-reftable-tree
13531363
UNIT_TEST_PROGRAMS += t-strbuf
13541364
UNIT_TEST_PROGRAMS += t-strcmp-offset
1355-
UNIT_TEST_PROGRAMS += t-strvec
13561365
UNIT_TEST_PROGRAMS += t-trailer
13571366
UNIT_TEST_PROGRAMS += t-urlmatch-normalization
13581367
UNIT_TEST_PROGS = $(patsubst %,$(UNIT_TEST_BIN)/%$X,$(UNIT_TEST_PROGRAMS))
@@ -2715,6 +2724,7 @@ OBJECTS += $(XDIFF_OBJS)
27152724
OBJECTS += $(FUZZ_OBJS)
27162725
OBJECTS += $(REFTABLE_OBJS) $(REFTABLE_TEST_OBJS)
27172726
OBJECTS += $(UNIT_TEST_OBJS)
2727+
OBJECTS += $(CLAR_TEST_OBJS)
27182728

27192729
ifndef NO_CURL
27202730
OBJECTS += http.o http-walker.o remote-curl.o
@@ -3214,7 +3224,7 @@ endif
32143224

32153225
test_bindir_programs := $(patsubst %,bin-wrappers/%,$(BINDIR_PROGRAMS_NEED_X) $(BINDIR_PROGRAMS_NO_X) $(TEST_PROGRAMS_NEED_X))
32163226

3217-
all:: $(TEST_PROGRAMS) $(test_bindir_programs) $(UNIT_TEST_PROGS)
3227+
all:: $(TEST_PROGRAMS) $(test_bindir_programs) $(UNIT_TEST_PROGS) $(CLAR_TEST_PROG)
32183228

32193229
bin-wrappers/%: wrap-for-bin.sh
32203230
$(call mkdir_p_parent_template)
@@ -3250,9 +3260,10 @@ t/helper/test-%$X: t/helper/test-%.o GIT-LDFLAGS $(GITLIBS)
32503260
check-sha1:: t/helper/test-tool$X
32513261
t/helper/test-sha1.sh
32523262

3253-
SP_OBJ = $(patsubst %.o,%.sp,$(OBJECTS))
3263+
SP_SRC = $(filter-out $(THIRD_PARTY_SOURCES),$(patsubst %.o,%.c,$(OBJECTS)))
3264+
SP_OBJ = $(patsubst %.c,%.sp,$(SP_SRC))
32543265

3255-
$(SP_OBJ): %.sp: %.c %.o
3266+
$(SP_OBJ): %.sp: %.c %.o $(GENERATED_H)
32563267
$(QUIET_SP)cgcc -no-compile $(ALL_CFLAGS) $(EXTRA_CPPFLAGS) \
32573268
-Wsparse-error \
32583269
$(SPARSE_FLAGS) $(SP_EXTRA_FLAGS) $< && \
@@ -3261,7 +3272,7 @@ $(SP_OBJ): %.sp: %.c %.o
32613272
.PHONY: sparse
32623273
sparse: $(SP_OBJ)
32633274

3264-
EXCEPT_HDRS := $(GENERATED_H) unicode-width.h compat/% xdiff/%
3275+
EXCEPT_HDRS := $(GENERATED_H) unicode-width.h compat/% xdiff/% $(UNIT_TEST_DIR)/clar/% $(UNIT_TEST_DIR)/clar/clar/%
32653276
ifndef OPENSSL_SHA1
32663277
EXCEPT_HDRS += sha1/openssl.h
32673278
endif
@@ -3282,7 +3293,7 @@ HCC = $(HCO:hco=hcc)
32823293
@echo '#include "git-compat-util.h"' >$@
32833294
@echo '#include "$<"' >>$@
32843295

3285-
$(HCO): %.hco: %.hcc FORCE
3296+
$(HCO): %.hco: %.hcc $(GENERATED_H) FORCE
32863297
$(QUIET_HDR)$(CC) $(ALL_CFLAGS) -o /dev/null -c -xc $<
32873298

32883299
.PHONY: hdr-check $(HCO)
@@ -3293,7 +3304,7 @@ style:
32933304
git clang-format --style file --diff --extensions c,h
32943305

32953306
.PHONY: check
3296-
check: $(GENERATED_H)
3307+
check:
32973308
@if sparse; \
32983309
then \
32993310
echo >&2 "Use 'make sparse' instead"; \
@@ -3645,7 +3656,7 @@ endif
36453656

36463657
artifacts-tar:: $(ALL_COMMANDS_TO_INSTALL) $(SCRIPT_LIB) $(OTHER_PROGRAMS) \
36473658
GIT-BUILD-OPTIONS $(TEST_PROGRAMS) $(test_bindir_programs) \
3648-
$(UNIT_TEST_PROGS) $(MOFILES)
3659+
$(UNIT_TEST_PROGS) $(CLAR_TEST_PROG) $(MOFILES)
36493660
$(QUIET_SUBDIR0)templates $(QUIET_SUBDIR1) \
36503661
SHELL_PATH='$(SHELL_PATH_SQ)' PERL_PATH='$(PERL_PATH_SQ)'
36513662
test -n "$(ARTIFACTS_DIRECTORY)"
@@ -3701,6 +3712,7 @@ cocciclean:
37013712

37023713
clean: profile-clean coverage-clean cocciclean
37033714
$(RM) -r .build $(UNIT_TEST_BIN)
3715+
$(RM) GIT-TEST-SUITES
37043716
$(RM) po/git.pot po/git-core.pot
37053717
$(RM) git.res
37063718
$(RM) $(OBJECTS)
@@ -3860,7 +3872,26 @@ $(UNIT_TEST_PROGS): $(UNIT_TEST_BIN)/%$X: $(UNIT_TEST_DIR)/%.o \
38603872
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \
38613873
$(filter %.o,$^) $(filter %.a,$^) $(LIBS)
38623874

3875+
GIT-TEST-SUITES: FORCE
3876+
@FLAGS='$(CLAR_TEST_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,$(CLAR_TEST_SUITES)) GIT-TEST-SUITES
3883+
$(QUIET_GEN)for suite in $(CLAR_TEST_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+
$(CLAR_TEST_OBJS): $(UNIT_TEST_DIR)/clar-decls.h
3889+
$(CLAR_TEST_OBJS): EXTRA_CPPFLAGS = -I$(UNIT_TEST_DIR)
3890+
$(CLAR_TEST_PROG): $(UNIT_TEST_DIR)/clar.suite $(CLAR_TEST_OBJS) $(GITLIBS) GIT-LDFLAGS
3891+
$(call mkdir_p_parent_template)
3892+
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS)
3893+
38633894
.PHONY: build-unit-tests unit-tests
3864-
build-unit-tests: $(UNIT_TEST_PROGS)
3865-
unit-tests: $(UNIT_TEST_PROGS) t/helper/test-tool$X
3895+
build-unit-tests: $(UNIT_TEST_PROGS) $(CLAR_TEST_PROG)
3896+
unit-tests: $(UNIT_TEST_PROGS) $(CLAR_TEST_PROG) t/helper/test-tool$X
38663897
$(MAKE) -C t/ unit-tests

contrib/buildsystems/CMakeLists.txt

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,6 +1004,59 @@ foreach(unit_test ${unit_test_PROGRAMS})
10041004
endif()
10051005
endforeach()
10061006

1007+
parse_makefile_for_scripts(unit_tests_SUITES "UNIT_TESTS_SUITES" "")
1008+
1009+
set(clar_decls "")
1010+
set(clar_cbs "")
1011+
set(clar_cbs_count 0)
1012+
set(clar_suites "static struct clar_suite _clar_suites[] = {\n")
1013+
list(LENGTH unit_tests_SUITES clar_suites_count)
1014+
foreach(suite ${unit_tests_SUITES})
1015+
file(STRINGS "${CMAKE_SOURCE_DIR}/t/unit-tests/${suite}.c" decls
1016+
REGEX "^void test_${suite}__[a-zA-Z_0-9][a-zA-Z_0-9]*\\(void\\)$")
1017+
1018+
list(LENGTH decls decls_count)
1019+
string(REGEX REPLACE "void (test_${suite}__([a-zA-Z_0-9]*))\\(void\\)" " { \"\\2\", &\\1 },\n" cbs ${decls})
1020+
string(JOIN "" cbs ${cbs})
1021+
list(TRANSFORM decls PREPEND "extern ")
1022+
string(JOIN ";\n" decls ${decls})
1023+
1024+
string(APPEND clar_decls "${decls};\n")
1025+
string(APPEND clar_cbs
1026+
"static const struct clar_func _clar_cb_${suite}[] = {\n"
1027+
${cbs}
1028+
"};\n")
1029+
string(APPEND clar_suites
1030+
" {\n"
1031+
" \"${suite}\",\n"
1032+
" { NULL, NULL },\n"
1033+
" { NULL, NULL },\n"
1034+
" _clar_cb_${suite}, ${decls_count}, 1\n"
1035+
" },\n")
1036+
math(EXPR clar_cbs_count "${clar_cbs_count}+${decls_count}")
1037+
endforeach()
1038+
string(APPEND clar_suites
1039+
"};\n"
1040+
"static const size_t _clar_suite_count = ${clar_suites_count};\n"
1041+
"static const size_t _clar_callback_count = ${clar_cbs_count};\n")
1042+
file(WRITE "${CMAKE_BINARY_DIR}/t/unit-tests/clar-decls.h" "${clar_decls}")
1043+
file(WRITE "${CMAKE_BINARY_DIR}/t/unit-tests/clar.suite" "${clar_decls}" "${clar_cbs}" "${clar_suites}")
1044+
1045+
list(TRANSFORM unit_tests_SUITES PREPEND "${CMAKE_SOURCE_DIR}/t/unit-tests/")
1046+
list(TRANSFORM unit_tests_SUITES APPEND ".c")
1047+
add_library(unit-tests-lib ${unit_tests_SUITES} "${CMAKE_SOURCE_DIR}/t/unit-tests/clar/clar.c")
1048+
target_include_directories(unit-tests-lib PRIVATE "${CMAKE_SOURCE_DIR}/t/unit-tests")
1049+
add_executable(unit-tests "${CMAKE_SOURCE_DIR}/t/unit-tests/unit-test.c")
1050+
target_link_libraries(unit-tests unit-tests-lib common-main)
1051+
set_target_properties(unit-tests
1052+
PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/t/unit-tests/bin)
1053+
if(MSVC)
1054+
set_target_properties(unit-tests
1055+
PROPERTIES RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR}/t/unit-tests/bin)
1056+
set_target_properties(unit-tests
1057+
PROPERTIES RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR}/t/unit-tests/bin)
1058+
endif()
1059+
10071060
#test-tool
10081061
parse_makefile_for_sources(test-tool_SOURCES "TEST_BUILTINS_OBJS")
10091062
add_library(test-lib OBJECT ${CMAKE_SOURCE_DIR}/t/unit-tests/test-lib.c)

t/Makefile

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ CHAINLINTTESTS = $(sort $(patsubst chainlint/%.test,%,$(wildcard chainlint/*.tes
4848
CHAINLINT = '$(PERL_PATH_SQ)' chainlint.pl
4949
UNIT_TEST_SOURCES = $(wildcard unit-tests/t-*.c)
5050
UNIT_TEST_PROGRAMS = $(patsubst unit-tests/%.c,unit-tests/bin/%$(X),$(UNIT_TEST_SOURCES))
51+
UNIT_TEST_PROGRAMS += unit-tests/bin/unit-tests$(X)
5152
UNIT_TESTS = $(sort $(UNIT_TEST_PROGRAMS))
5253
UNIT_TESTS_NO_DIR = $(notdir $(UNIT_TESTS))
5354

@@ -68,7 +69,8 @@ failed:
6869
test -z "$$failed" || $(MAKE) $$failed
6970

7071
prove: pre-clean check-chainlint $(TEST_LINT)
71-
@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)
72+
@echo "*** prove (shell & unit tests) ***"
73+
@$(CHAINLINTSUPPRESS) TEST_OPTIONS='$(GIT_TEST_OPTS)' TEST_SHELL_PATH='$(TEST_SHELL_PATH_SQ)' $(PROVE) --exec ./run-test.sh $(GIT_PROVE_OPTS) $(T) $(UNIT_TESTS)
7274
$(MAKE) clean-except-prove-cache
7375

7476
$(T):

t/run-test.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ case "$1" in
1010
echo >&2 "ERROR: TEST_SHELL_PATH is empty or not set"
1111
exit 1
1212
fi
13-
exec "${TEST_SHELL_PATH}" "$@"
13+
exec "${TEST_SHELL_PATH}" "$@" ${TEST_OPTIONS}
1414
;;
1515
*)
1616
exec "$@"

t/unit-tests/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
11
/bin
2+
/clar.suite
3+
/clar-decls.h

t/unit-tests/clar-generate.awk

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
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+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
pull_request:
7+
branches: [ main ]
8+
9+
jobs:
10+
build:
11+
strategy:
12+
matrix:
13+
os: [ ubuntu-latest, macos-latest ]
14+
15+
runs-on: ${{ matrix.os }}
16+
17+
steps:
18+
- name: Check out
19+
uses: actions/checkout@v2
20+
- name: Build
21+
run: |
22+
cd test
23+
make

t/unit-tests/clar/COPYING

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
ISC License
2+
3+
Copyright (c) 2011-2015 Vicent Marti
4+
5+
Permission to use, copy, modify, and/or distribute this software for any
6+
purpose with or without fee is hereby granted, provided that the above
7+
copyright notice and this permission notice appear in all copies.
8+
9+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15+
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

0 commit comments

Comments
 (0)