From patchwork Tue Aug 6 14:14:30 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Patrick Steinhardt X-Patchwork-Id: 13754948 Received: from fout2-smtp.messagingengine.com (fout2-smtp.messagingengine.com [103.168.172.145]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id BCC4118D627 for ; Tue, 6 Aug 2024 14:14:37 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=103.168.172.145 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722953680; cv=none; b=sUlakm8SuLIFbsIsS4OSpSRf7U9ULbx4XnlKBx+Tp8HDa4pAGHb0ZONj59X8k+0LJGwmGWTyeDCoeSpf2jXbLznkwPJQvQspsnUgwqLnGyN4zUHvdlIYzT3NP7ny7oO5FVuBK6kiWh5+/pyDrU/e1L3LNSjpuSwGExTgklSu4g8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1722953680; c=relaxed/simple; bh=haizOnMb/uv6pbCK4tzkfpysiWTKbaIe6/uLAnC+Baw=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=VBhL4WL4g4UqAQ9CRbkJkZuobZPH4Vu9dPA1KeXo3KroL/tlOEaQMIVj+vc5py6bKYhHFXfgf2hW3k4DhvPYPAMVMewh87DlvJD7ldq8OMPD92/F1DrVEtdsYZDlgsKCIjRX5PNwVHnTPIlDnDMyp0/SLNWvCsr82pJndtTHhvg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=pks.im; spf=pass smtp.mailfrom=pks.im; dkim=pass (2048-bit key) header.d=pks.im header.i=@pks.im header.b=IjcF0had; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b=iufj8QGB; arc=none smtp.client-ip=103.168.172.145 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=pks.im Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=pks.im Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=pks.im header.i=@pks.im header.b="IjcF0had"; dkim=pass (2048-bit key) header.d=messagingengine.com header.i=@messagingengine.com header.b="iufj8QGB" Received: from compute7.internal (compute7.nyi.internal [10.202.2.48]) by mailfout.nyi.internal (Postfix) with ESMTP id B7A38138DD0D; Tue, 6 Aug 2024 10:14:36 -0400 (EDT) Received: from mailfrontend2 ([10.202.2.163]) by compute7.internal (MEProxy); Tue, 06 Aug 2024 10:14:36 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=pks.im; h=cc:cc :content-type:content-type:date:date:from:from:in-reply-to :in-reply-to:message-id:mime-version:references:reply-to:subject :subject:to:to; s=fm3; t=1722953676; x=1723040076; bh=261S/zjrdp om+LQC37Ts+Qoatct3bUP0JPiZmXlDsgw=; b=IjcF0hadgJ+4OIlTcPL1Ma4XNj CRyOYmhWLUudk1eNLQEZuEb3UBGWdu47UhTWVdw2gGWnVb0n0NdBTeu7Wzu+k3mh +32EUpVg5cPmfuNEwqdXUJCuE/6yVF+XpASgtnHhGUUVylTBaX19Dble+IUM1hkq Y2XkabTQw1zr9tYfPKtwp8dI0gVuNuv/6AJacRqo1DS+dD2Kcf/mBp/y5iF49RQ/ AxvNhokQf1IAC87aJCBrjB/R0QRUU0HIx7llfbcZ0x8QeFerukCgQjY0zJWaKx4/ DtF8JbM3q41+S8wn66QBf0a5COQrMy/4uKX2Subih4/Hb1Rjq1WOlsMW9ong== DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=cc:cc:content-type:content-type:date:date :feedback-id:feedback-id:from:from:in-reply-to:in-reply-to :message-id:mime-version:references:reply-to:subject:subject:to :to:x-me-proxy:x-me-proxy:x-me-sender:x-me-sender:x-sasl-enc; s= fm3; t=1722953676; x=1723040076; bh=261S/zjrdpom+LQC37Ts+Qoatct3 bUP0JPiZmXlDsgw=; b=iufj8QGB+nDUM2hVNY0V+BGnqryXFC1/R9XjkfsX1rRG 5bAyiQC9wbSLJc/+yoY9IemrfjRZGyxZ6/JvS0pvfM0in1ycTMzEe6kzLuCu4cYV /GYl68Nz3PBtyaTRz8cx/GyTawtFxdfy4+BTXXPklEEN/bjV7VrxK+n9c11oU24s KtJIZ41TrNmBE2EF+8ORevHeY9hVY/L13IdpRltSV6a1Tts0A5vw3Gdcr6Sjc/X3 9HZ6+8j6m8UbQkldyWCgk5QI6H4m98Ta286AQy1Hi2HNJZE9DRO3KwmWskxPaShv s6Y9o18M4P9X/dbEqqU3RSvHSMHleUG1ZY0qSEo7Mw== X-ME-Sender: X-ME-Received: X-ME-Proxy-Cause: gggruggvucftvghtrhhoucdtuddrgeeftddrkeekgdejgecutefuodetggdotefrodftvf curfhrohhfihhlvgemucfhrghsthforghilhdpqfgfvfdpuffrtefokffrpgfnqfghnecu uegrihhlohhuthemuceftddtnecusecvtfgvtghiphhivghnthhsucdlqddutddtmdenog fuuhhsphgvtghtffhomhgrihhnucdlgeelmdenucfjughrpeffhffvvefukfhfgggtuggj sehgtderredttdejnecuhfhrohhmpefrrghtrhhitghkucfuthgvihhnhhgrrhguthcuoe hpshesphhkshdrihhmqeenucggtffrrghtthgvrhhnpedtledtjeeijedtkedvtdelleek jeduleetiefgledvudekkeekuedvgffhhfelfeenucffohhmrghinhepghhithhhuhgsrd gtohhmpdhgihhthhhusgdrihhopdgtlhgrrhdquggvtghlshdrhhhtnecuvehluhhsthgv rhfuihiivgeptdenucfrrghrrghmpehmrghilhhfrhhomhepphhssehpkhhsrdhimhdpnh gspghrtghpthhtoheptd X-ME-Proxy: Feedback-ID: i197146af:Fastmail Received: by mail.messagingengine.com (Postfix) with ESMTPA; Tue, 6 Aug 2024 10:14:34 -0400 (EDT) Received: by vm-mail (OpenSMTPD) with ESMTPSA id d13c447d (TLSv1.3:TLS_AES_256_GCM_SHA384:256:NO); Tue, 6 Aug 2024 14:14:29 +0000 (UTC) Date: Tue, 6 Aug 2024 16:14:30 +0200 From: Patrick Steinhardt To: git@vger.kernel.org Cc: =?utf-8?b?UmVuw6k=?= Scharfe , Junio C Hamano , Kyle Lippincott , Phillip Wood , Josh Steadmon , rsbecker@nexbridge.com, Edward Thomson Subject: [RFC PATCH v2 0/7] Introduce clar testing framework Message-ID: References: Precedence: bulk X-Mailing-List: git@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: Hi, this is the second version of my RFC patch series that introduces the clar testing framework into our unit tests. The intent is to not have to hand-craft all features of a proper unit testing framework, while still not painting us into a corner. As such, the clar itself is small and extensible while still bringing some nice features to the table. Changes compared to v1: - Convert the ctypes unit tests to use clar, as I had it lying around anyway and René was asking for it. - Adopt the AWK-based script by René, replacing the Python-based one. This gets rid of the mandatory Python dependency and at the same time also allows us to be more flexible going forward. - Wire up the third party sources in our Makefiles such that they do not get linted via hdr-check or Coccinelle. - Fix t/Makefile to not pass GIT_TEST_OPTS to our unit tests. They don't know how to handle those options, and clar-based tests error out when they see unknown options. - Adapt Documentation/technical/unit-tests.txt to mention the clar. - Rebase the series onto the latest master at 406f326d27 (The second batch, 2024-08-01) to avoid some conflicts. - Cherry-pick a whitespace fix that otherwise makes git-apply(1) unhappy. The CI job is still broken because the first patch that imports clar continues to be broken. I've created an upstream PR. - Cherry-pick a fix by Randall to make clar work on HP NonStop. The fix has been proposed upstream in a PR. With these changes, the CI jobs at GitLab all pass, except for the whitespace and clang-format checks. I've also Cc'd Ed, one of the maintainers of clar. I also noticed that I'm a maintainer of that project back from my libgit2 times, so I think it should be relatively easy to land changes upstream. Thanks! Patrick Patrick Steinhardt (7): t: do not pass GIT_TEST_OPTS to unit tests with prove t: import the clar unit testing framework t/clar: fix whitespace errors t/clar: fix compatibility with NonStop Makefile: wire up the clar unit testing framework t/unit-tests: convert strvec tests to use clar t/unit-tests: convert ctype tests to use clar .gitignore | 1 + Documentation/technical/unit-tests.txt | 2 + Makefile | 42 +- t/Makefile | 4 +- t/run-test.sh | 2 +- t/unit-tests/.gitignore | 2 + t/unit-tests/clar-generate.awk | 50 ++ t/unit-tests/clar/.github/workflows/ci.yml | 23 + t/unit-tests/clar/COPYING | 15 + t/unit-tests/clar/README.md | 329 ++++++++ t/unit-tests/clar/clar.c | 842 +++++++++++++++++++++ t/unit-tests/clar/clar.h | 173 +++++ t/unit-tests/clar/clar/fixtures.h | 50 ++ t/unit-tests/clar/clar/fs.h | 522 +++++++++++++ t/unit-tests/clar/clar/print.h | 211 ++++++ t/unit-tests/clar/clar/sandbox.h | 159 ++++ t/unit-tests/clar/clar/summary.h | 143 ++++ t/unit-tests/clar/generate.py | 266 +++++++ t/unit-tests/clar/test/.gitignore | 4 + t/unit-tests/clar/test/Makefile | 39 + t/unit-tests/clar/test/clar_test.h | 16 + t/unit-tests/clar/test/main.c | 40 + t/unit-tests/clar/test/main.c.sample | 27 + t/unit-tests/clar/test/resources/test/file | 1 + t/unit-tests/clar/test/sample.c | 84 ++ t/unit-tests/{t-ctype.c => ctype.c} | 71 +- t/unit-tests/{t-strvec.c => strvec.c} | 119 ++- t/unit-tests/unit-test.c | 17 + t/unit-tests/unit-test.h | 3 + 29 files changed, 3159 insertions(+), 98 deletions(-) create mode 100644 t/unit-tests/clar-generate.awk create mode 100644 t/unit-tests/clar/.github/workflows/ci.yml create mode 100644 t/unit-tests/clar/COPYING create mode 100644 t/unit-tests/clar/README.md create mode 100644 t/unit-tests/clar/clar.c create mode 100644 t/unit-tests/clar/clar.h create mode 100644 t/unit-tests/clar/clar/fixtures.h create mode 100644 t/unit-tests/clar/clar/fs.h create mode 100644 t/unit-tests/clar/clar/print.h create mode 100644 t/unit-tests/clar/clar/sandbox.h create mode 100644 t/unit-tests/clar/clar/summary.h create mode 100755 t/unit-tests/clar/generate.py create mode 100644 t/unit-tests/clar/test/.gitignore create mode 100644 t/unit-tests/clar/test/Makefile create mode 100644 t/unit-tests/clar/test/clar_test.h create mode 100644 t/unit-tests/clar/test/main.c create mode 100644 t/unit-tests/clar/test/main.c.sample create mode 100644 t/unit-tests/clar/test/resources/test/file create mode 100644 t/unit-tests/clar/test/sample.c rename t/unit-tests/{t-ctype.c => ctype.c} (71%) rename t/unit-tests/{t-strvec.c => strvec.c} (54%) create mode 100644 t/unit-tests/unit-test.c create mode 100644 t/unit-tests/unit-test.h Range-diff against v1: -: ---------- > 1: 78a9cc1162 t: do not pass GIT_TEST_OPTS to unit tests with prove 1: 4e3862991a ! 2: 6a88cf22a5 t: import the clar unit testing framework @@ Commit message Signed-off-by: Patrick Steinhardt + ## Documentation/technical/unit-tests.txt ## +@@ Documentation/technical/unit-tests.txt: GitHub / GitLab stars to estimate this. + :criterion: https://github.com/Snaipe/Criterion[Criterion] + :c-tap: https://github.com/rra/c-tap-harness/[C TAP] + :check: https://libcheck.github.io/check/[Check] ++:clar: https://github.com/clar-test/clar[Clar] + + [format="csv",options="header",width="33%",subs="specialcharacters,attributes,quotes,macros"] + |===== +@@ Documentation/technical/unit-tests.txt: Framework,"<>","< 3: a52ee59bf4 t/clar: fix whitespace errors -: ---------- > 4: 02fb86dfbc t/clar: fix compatibility with NonStop 2: 7a5dfd5065 ! 5: 848dc673c4 Makefile: wire up the clar unit testing framework @@ .gitignore /bin-wrappers/ ## Makefile ## -@@ Makefile: THIRD_PARTY_SOURCES += compat/regex/% - THIRD_PARTY_SOURCES += sha1collisiondetection/% - THIRD_PARTY_SOURCES += sha1dc/% +@@ Makefile: THIRD_PARTY_SOURCES += sha1dc/% + THIRD_PARTY_SOURCES += $(UNIT_TEST_DIR)/clar/% + THIRD_PARTY_SOURCES += $(UNIT_TEST_DIR)/clar/clar/% +UNIT_TESTS_PROG = $(UNIT_TEST_BIN)/unit-tests$(X) +UNIT_TESTS_OBJS = $(patsubst %,$(UNIT_TEST_DIR)/%.o,$(UNIT_TESTS_SUITES)) @@ Makefile: endif bin-wrappers/%: wrap-for-bin.sh $(call mkdir_p_parent_template) +@@ Makefile: $(SP_OBJ): %.sp: %.c %.o + .PHONY: sparse + sparse: $(SP_OBJ) + +-EXCEPT_HDRS := $(GENERATED_H) unicode-width.h compat/% xdiff/% $(UNIT_TEST_DIR)/clar/% $(UNIT_TEST_DIR)/clar/clar/% ++EXCEPT_HDRS := $(GENERATED_H) unicode-width.h compat/% xdiff/% $(UNIT_TEST_DIR)/unit-test.h $(UNIT_TEST_DIR)/clar/% $(UNIT_TEST_DIR)/clar/clar/% + ifndef OPENSSL_SHA1 + EXCEPT_HDRS += sha1/openssl.h + endif @@ Makefile: endif artifacts-tar:: $(ALL_COMMANDS_TO_INSTALL) $(SCRIPT_LIB) $(OTHER_PROGRAMS) \ @@ Makefile: cocciclean: clean: profile-clean coverage-clean cocciclean $(RM) -r .build $(UNIT_TEST_BIN) -+ $(RM) $(UNIT_TEST_DIR)/clar.suite $(UNIT_TEST_DIR)/.clarcache ++ $(RM) GIT-TEST-SUITES $(UNIT_TEST_DIR)/clar.suite $(UNIT_TEST_DIR)/clar-decls.h $(RM) po/git.pot po/git-core.pot $(RM) git.res $(RM) $(OBJECTS) @@ Makefile: $(UNIT_TEST_PROGS): $(UNIT_TEST_BIN)/%$X: $(UNIT_TEST_DIR)/%.o \ + if test x"$$FLAGS" != x"`cat GIT-TEST-SUITES 2>/dev/null`" ; then \ + echo >&2 " * new test suites"; \ + echo "$$FLAGS" >GIT-TEST-SUITES; \ -+ rm -f $(UNIT_TESTS_DIR)/.clarcache; \ + fi + -+$(UNIT_TEST_DIR)/clar.suite: $(patsubst %,$(UNIT_TEST_DIR)/%.c,$(UNIT_TESTS_SUITES)) GIT-TEST-SUITES -+ $(QUIET_GEN)$(UNIT_TEST_DIR)/clar/generate.py $(UNIT_TEST_DIR) >/dev/null -+ @touch $@ -+$(UNIT_TEST_DIR)/clar-decls.h: $(UNIT_TEST_DIR)/clar.suite -+ $(QUIET_GEN)grep '^extern void' $^ >$@ ++$(UNIT_TEST_DIR)/clar-decls.h: $(patsubst %,$(UNIT_TEST_DIR)/%.c,$(UNIT_TESTS_SUITES)) GIT-TEST-SUITES ++ $(QUIET_GEN)for suite in $(UNIT_TESTS_SUITES); do \ ++ 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; \ ++ done >$@ ++$(UNIT_TEST_DIR)/clar.suite: $(UNIT_TEST_DIR)/clar-decls.h ++ $(QUIET_GEN)awk -f $(UNIT_TEST_DIR)/clar-generate.awk $< >$(UNIT_TEST_DIR)/clar.suite +$(UNIT_TESTS_OBJS): $(UNIT_TEST_DIR)/clar-decls.h +$(UNIT_TESTS_OBJS): EXTRA_CPPFLAGS = -I$(UNIT_TEST_DIR) -I$(UNIT_TEST_DIR)/clar +$(UNIT_TESTS_PROG): $(UNIT_TEST_DIR)/clar.suite $(UNIT_TESTS_OBJS) $(GITLIBS) GIT-LDFLAGS @@ t/Makefile: CHAINLINTTESTS = $(sort $(patsubst chainlint/%.test,%,$(wildcard cha ## t/unit-tests/.gitignore ## @@ /bin -+/.clarcache +/clar.suite +/clar-decls.h + ## t/unit-tests/clar-generate.awk (new) ## +@@ ++function add_suite(suite, initialize, cleanup, count) { ++ if (!suite) return ++ suite_count++ ++ callback_count += count ++ suites = suites " {\n" ++ suites = suites " \"" suite "\",\n" ++ suites = suites " " initialize ",\n" ++ suites = suites " " cleanup ",\n" ++ suites = suites " _clar_cb_" suite ", " count ", 1\n" ++ suites = suites " },\n" ++} ++ ++BEGIN { ++ suites = "static struct clar_suite _clar_suites[] = {\n" ++} ++ ++{ ++ print ++ name = $3; sub(/\(.*$/, "", name) ++ suite = name; sub(/^test_/, "", suite); sub(/__.*$/, "", suite) ++ short_name = name; sub(/^.*__/, "", short_name) ++ cb = "{ \"" short_name "\", &" name " }" ++ if (suite != prev_suite) { ++ add_suite(prev_suite, initialize, cleanup, count) ++ if (callbacks) callbacks = callbacks "};\n" ++ callbacks = callbacks "static const struct clar_func _clar_cb_" suite "[] = {\n" ++ initialize = "{ NULL, NULL }" ++ cleanup = "{ NULL, NULL }" ++ count = 0 ++ prev_suite = suite ++ } ++ if (short_name == "initialize") { ++ initialize = cb ++ } else if (short_name == "cleanup") { ++ cleanup = cb ++ } else { ++ callbacks = callbacks " " cb ",\n" ++ count++ ++ } ++} ++ ++END { ++ add_suite(suite, initialize, cleanup, count) ++ suites = suites "};" ++ if (callbacks) callbacks = callbacks "};" ++ print callbacks ++ print suites ++ print "static const size_t _clar_suite_count = " suite_count ";" ++ print "static const size_t _clar_callback_count = " callback_count ";" ++} + ## t/unit-tests/unit-test.c (new) ## @@ +#include "unit-test.h" + +int cmd_main(int argc, const char **argv) +{ -+ const char **args; ++ const char **argv_copy; + int ret; + + /* Append the "-t" flag such that the tests generate TAP output. */ -+ DUP_ARRAY(args, argv, argc + 1); -+ args[argc++] = "-t"; ++ ALLOC_ARRAY(argv_copy, argc + 2); ++ COPY_ARRAY(argv_copy, argv, argc); ++ argv_copy[argc++] = "-t"; ++ argv_copy[argc] = NULL; + -+ ret = clar_test(argc, (char **) args); ++ ret = clar_test(argc, (char **) argv_copy); + -+ free(args); ++ free(argv_copy); + return ret; +} 3: 1c2a510547 ! 6: 578e657269 t/unit-tests: convert strvec tests to use clar @@ Commit message Signed-off-by: Patrick Steinhardt ## Makefile ## -@@ Makefile: THIRD_PARTY_SOURCES += compat/regex/% - THIRD_PARTY_SOURCES += sha1collisiondetection/% - THIRD_PARTY_SOURCES += sha1dc/% +@@ Makefile: THIRD_PARTY_SOURCES += sha1dc/% + THIRD_PARTY_SOURCES += $(UNIT_TEST_DIR)/clar/% + THIRD_PARTY_SOURCES += $(UNIT_TEST_DIR)/clar/clar/% +UNIT_TESTS_SUITES += strvec UNIT_TESTS_PROG = $(UNIT_TEST_BIN)/unit-tests$(X) UNIT_TESTS_OBJS = $(patsubst %,$(UNIT_TEST_DIR)/%.o,$(UNIT_TESTS_SUITES)) UNIT_TESTS_OBJS += $(UNIT_TEST_DIR)/clar/clar.o -@@ Makefile: UNIT_TEST_PROGRAMS += t-reftable-basics +@@ Makefile: UNIT_TEST_PROGRAMS += t-reftable-merged UNIT_TEST_PROGRAMS += t-reftable-record UNIT_TEST_PROGRAMS += t-strbuf UNIT_TEST_PROGRAMS += t-strcmp-offset @@ t/unit-tests/t-strvec.c => t/unit-tests/strvec.c #include "strvec.h" #define check_strvec(vec, ...) \ -- check_strvec_loc(TEST_LOCATION(), vec, __VA_ARGS__) -+ check_strvec_loc(__FILE__, __func__, __LINE__, vec, __VA_ARGS__) - LAST_ARG_MUST_BE_NULL --static void check_strvec_loc(const char *loc, struct strvec *vec, ...) -+static void check_strvec_loc(const char *file, const char *func, size_t line, struct strvec *vec, ...) - { - va_list ap; - size_t nr = 0; -@@ t/unit-tests/strvec.c: static void check_strvec_loc(const char *loc, struct strvec *vec, ...) - if (!str) - break; - -- if (!check_uint(vec->nr, >, nr) || -- !check_uint(vec->alloc, >, nr) || -- !check_str(vec->v[nr], str)) { -- struct strbuf msg = STRBUF_INIT; -- strbuf_addf(&msg, "strvec index %"PRIuMAX, (uintmax_t) nr); -- test_assert(loc, msg.buf, 0); -- strbuf_release(&msg); -- va_end(ap); -- return; -- } -+ clar__assert(vec->nr > nr, file, func, line, "Vector size too small", NULL, 1); -+ clar__assert(vec->alloc > nr, file, func, line, "Vector allocation too small", NULL, 1); -+ cl_assert_equal_s(vec->v[nr], str); - - nr++; - } - va_end(ap); - -- check_uint(vec->nr, ==, nr); -- check_uint(vec->alloc, >=, nr); -- check_pointer_eq(vec->v[nr], NULL); -+ cl_assert(vec->nr == nr); -+ cl_assert(vec->alloc >= nr); -+ cl_assert_equal_p(vec->v[nr], NULL); - } + do { \ + const char *expect[] = { __VA_ARGS__ }; \ +- if (check_uint(ARRAY_SIZE(expect), >, 0) && \ +- check_pointer_eq(expect[ARRAY_SIZE(expect) - 1], NULL) && \ +- check_uint((vec)->nr, ==, ARRAY_SIZE(expect) - 1) && \ +- check_uint((vec)->nr, <=, (vec)->alloc)) { \ +- for (size_t i = 0; i < ARRAY_SIZE(expect); i++) { \ +- if (!check_str((vec)->v[i], expect[i])) { \ +- test_msg(" i: %"PRIuMAX, \ +- (uintmax_t)i); \ +- break; \ +- } \ +- } \ +- } \ ++ cl_assert(ARRAY_SIZE(expect) > 0); \ ++ cl_assert_equal_p(expect[ARRAY_SIZE(expect) - 1], NULL); \ ++ cl_assert_equal_i((vec)->nr, ARRAY_SIZE(expect) - 1); \ ++ cl_assert((vec)->nr <= (vec)->alloc); \ ++ for (size_t i = 0; i < ARRAY_SIZE(expect); i++) \ ++ cl_assert_equal_s((vec)->v[i], expect[i]); \ + } while (0) -static void t_static_init(void) +void test_strvec__init(void) @@ t/unit-tests/strvec.c: static void t_push(void) } -static void t_pushf(void) -+void test_strvec__pushft_pushf(void) ++void test_strvec__pushf(void) { struct strvec vec = STRVEC_INIT; strvec_pushf(&vec, "foo: %d", 1); @@ t/unit-tests/strvec.c: static void t_detach(void) - TEST(t_detach(), "detach"); - return test_done(); -} + + ## t/unit-tests/unit-test.c ## +@@ t/unit-tests/unit-test.c: int cmd_main(int argc, const char **argv) + int ret; + + /* Append the "-t" flag such that the tests generate TAP output. */ +- ALLOC_ARRAY(argv_copy, argc + 2); ++ ALLOC_ARRAY(argv_copy, argc + 1); + COPY_ARRAY(argv_copy, argv, argc); + argv_copy[argc++] = "-t"; +- argv_copy[argc] = NULL; + + ret = clar_test(argc, (char **) argv_copy); + -: ---------- > 7: 238de33b93 t/unit-tests: convert ctype tests to use clar