Skip to content

Commit

Permalink
Checkmk support (#4)
Browse files Browse the repository at this point in the history
* set test-related makefile templates with more proper name

* added checkmk tests

* described checkmk in Demo

* update gcovr string
  • Loading branch information
aodinokov authored May 27, 2024
1 parent cb10ffd commit 515b72c
Show file tree
Hide file tree
Showing 8 changed files with 212 additions and 12 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
*.test.cpp
*.dummy.cpp
*_test
*_checkmk
*_checkmk.*
_meta_*
metac
coverage_*.css
Expand Down
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
"iterator.h": "c",
"reqresp.h": "c",
"complex.h": "c",
"stdint.h": "c"
"stdint.h": "c",
"test.h": "c"
}
}
6 changes: 4 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,17 @@ ifneq ($(M),)
include $(M)/Makefile
# include all make-modules. target.mk is entypoint
include mk/*.mk
$(foreach t,$(subst ./,,$(shell cd $(M) && find . -name '*_test.c')),$(call test_rules,$(M),$(t),rules))
$(foreach t,$(subst ./,,$(shell cd $(M) && find . -name '*_test.c')),$(call test_c_rules,$(M),$(t),rules))
$(foreach t,$(subst ./,,$(shell cd $(M) && find . -name '*.checkmk')),$(call test_checkmk_rules,$(M),$(t),rules))
$(foreach t,$(rules),$(call meta_rules,$(M),$(t)))
$(foreach t,$(rules),$(call meta_rules_clean,$(M),$(t)))
else
# include all make-modules. target.mk is entypoint
include mk/*.mk
# this test dones't need meta-information - disable it explicitly
REFLECT-src/inherit_test=n
$(foreach t,$(shell find src -name '*_test.c'),$(call test_rules,$(shell pwd),$(t),gl_rules))
$(foreach t,$(shell find src -name '*_test.c'),$(call test_c_rules,$(shell pwd),$(t),gl_rules))
$(foreach t,$(shell find src -name '*.checkmk'),$(call test_checkmk_rules,$(shell pwd),$(t),gl_rules))
$(foreach m,$(wildcard modules/*),$(foreach t,$(subst $(m)/,,$(shell find $(m) -name '*_test.c.yaml')),$(call modules_test,$(m),$(t))))
$(foreach m,$(wildcard modules/*),$(foreach t,$(subst $(m)/,,$(shell find $(m) -name '*_test.c.yaml')),$(call modules_test_clean,$(m),$(t))))
test: go_test
Expand Down
10 changes: 9 additions & 1 deletion doc/demo/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ int main(int argc, char **argv) {
```
As you can see - it uses `check` library under the hood, but it's not necessary to write this entrypoint manually. To generate this file [metac-test-gen](/modules/metac-test-gen) go-template module was used.
Unit-tests are always built with coverage information. For our simple case we can run `make METAC_ROOT=../../.. test RUNMODE=coverage`, and we'll see the coverage for this particular file. But for more complex cases where we have many tests for many C-files and we need to get complete coverage information for each of the files - please install gcovr and use `gcovr -p ./ -e '.*_test\.c|.*\.h'` or similar. It may even build html files and show coverage for each line.
Unit-tests are always built with coverage information. For our simple case we can run `make METAC_ROOT=../../.. test RUNMODE=coverage`, and we'll see the coverage for this particular file. But for more complex cases where we have many tests for many C-files and we need to get complete coverage information for each of the files - please install gcovr and use `gcovr -p ./ -e '.*_test\.c|.*_checkmk\.c|.*\.h'` or similar. It may even build html files and show coverage for each line.
Since C requires the developer to manage dynamic memory it's very useful to check test for memory leaks. On Linux it's possible to install `valgrind` package and after that run the test with the following command: `make METAC_ROOT=../../.. test RUNMODE=valgrind`. This will show if the test has any leakage.
Expand Down Expand Up @@ -314,6 +314,14 @@ REFLECT-demodb_alt_test:=n

Here we're building a library .a file and linking it to this test. The last line is - not to generate reflection meta-information.

Check library has an utility called `checkmk`, which accepts a [special file format](https://github.com/libcheck/check/blob/master/checkmk/test/multiple_everything/in) as input and generates test that inludes tests. We also support that: such files must have name pattern `*.checkmk`. Metac will generate test binary with the name `*_checkmk` for such file. Here is the [converted example](step_02/demodb_alt.checkmk). And we need to make the corresponding changes in Makefile:

```Makefile
DEPS-demodb_alt_checkmk:=$(M)/libdemodb.a
LDFLAGS-demodb_alt_checkmk:=-L$(M) -ldemodb
REFLECT-demodb_alt_checkmk:=n
```

To make sure that this works ok - just run `make METAC_ROOT=../../.. test` or `make METAC_ROOT=../../..` in the folder [step_02](step_02/)

### Reflection
Expand Down
4 changes: 4 additions & 0 deletions doc/demo/step_02/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,8 @@ DEPS-demodb_alt_test:=$(M)/libdemodb.a
LDFLAGS-demodb_alt_test:=-L$(M) -ldemodb
REFLECT-demodb_alt_test:=n

DEPS-demodb_alt_checkmk:=$(M)/libdemodb.a
LDFLAGS-demodb_alt_checkmk:=-L$(M) -ldemodb
REFLECT-demodb_alt_checkmk:=n

REFLECT-demodb_test:=n
47 changes: 47 additions & 0 deletions doc/demo/step_02/demodb_alt.checkmk
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#include "demodb.h"

# suite Demo Suite
# tcase Demo Test Case
# test append_test
struct {
person_t * p_in;
int expected_err;
}tcs[] = {
{
.p_in = NULL,
.expected_err = 1,
},
{
.p_in = (person_t[]){{
.firstname="Joe",
.lastname="Doe",
.age = 43,
.marital_status = msMarried,
}},
.expected_err = 0,
},
{
.p_in = (person_t[]){{
.firstname="Jane",
.lastname="Doe",
.age = 34,
.marital_status = msMarried,
}},
.expected_err = 0,
},
{
.p_in = (person_t[]){{
.firstname="Jack",
.lastname="Doe",
.age = 3,
.marital_status = msSingle,
}},
.expected_err = 0,
},
};
db_t * p_db = new_db();
for (int tc_inx = 0; tc_inx < sizeof(tcs)/sizeof(tcs[0]); tc_inx++) {
int res = db_append(&p_db, tcs[tc_inx].p_in);
fail_unless((res != 0) == (tcs[tc_inx].expected_err != 0), "unexpected err result %i, expected %i", res, tcs[tc_inx].expected_err);
}
db_delete(p_db);
62 changes: 54 additions & 8 deletions mk/test.mk
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
# extra template to dummy entrypoint and remove coverage files on cleanup
define test_extra_tpl
define test_c_dummy_main_tpl
$$(addprefix $1/,$2.dummy.c):
@echo "int main(int argc, char **argv ){return 0;}" > $$@
endef
test_extra = $(eval $(call test_extra_tpl,$1,$2))
test_c_dummy_main = $(eval $(call test_c_dummy_main_tpl,$1,$2))

define test_extra_clean_tpl
define test_c_dummy_main_clean_tpl
clean: RMFLAGS+=$$(addprefix $1/,$2.gcda) $$(addprefix $1/,$2.gcno) $$(addprefix $1/,$2.dummy.c)
endef
test_extra_clean = $(eval $(call test_extra_clean_tpl,$1,$2))
test_c_dummy_main_clean = $(eval $(call test_c_dummy_main_clean_tpl,$1,$2))

define test_meta_rules_tpl
define test_c_meta_rules_tpl
$(3)+= \
$(2:.c=) \
$(2:.c=.reflect.c) \
$(2:.c=.test.c) \
$$(dir $(2:.c=))_meta_$$(notdir $(2:.c=))

TPL-$(2:.c=):=bin_target test_extra
TPL-$(2:.c=):=bin_target test_c_dummy_main
IN-$(2:.c=)=$(2:.c=.o) $(2:.c=.test.o)
LDFLAGS-$(2:.c=)+=--coverage $$(METAC_CHECK_LDFLAGS)
$$(addprefix $1/,$(2:.c=.test.o)):CFLAGS+=-g3 $$(METAC_CHECK_CFLAGS)
Expand All @@ -43,8 +43,54 @@ POST-$$(dir $(2:.c=))_meta_$$(notdir $(2:.c=))=$$(METAC_POST_META)

bin_test: $$(addprefix $1/,$(2:.c=))

endef # test_meta_rules_tpl
test_rules = $(eval $(call test_meta_rules_tpl,$1,$2,$3))
endef # test_c_meta_rules_tpl
test_c_rules = $(eval $(call test_c_meta_rules_tpl,$1,$2,$3))

# checkmk support
# extra template to convert checkmk to c using checkmk
define test_checkmk_c_tpl
$$(addprefix $1/,$2.c): $$(addprefix $1/,$(subst _checkmk,.checkmk,$2))
checkmk $$^ > $$@
endef
test_checkmk_c = $(eval $(call test_checkmk_c_tpl,$1,$2))

define test_checkmk_c_clean_tpl
clean: RMFLAGS+=$$(addprefix $1/,$2.gcda) $$(addprefix $1/,$2.gcno) $$(addprefix $1/,$2.c)
endef
test_checkmk_c_clean = $(eval $(call test_checkmk_c_clean_tpl,$1,$2))

define test_checkmk_meta_rules_tpl
$(3)+= \
$(2:.checkmk=_checkmk)

TPL-$(2:.checkmk=_checkmk):=bin_target test_checkmk_c
IN-$(2:.checkmk=_checkmk)=$(2:.checkmk=_checkmk.o)
LDFLAGS-$(2:.checkmk=_checkmk)+=--coverage $$(METAC_CHECK_LDFLAGS)
$$(addprefix $1/,$(2:.checkmk=_checkmk.o)):CFLAGS+=-g3 -Wno-format-extra-args --coverage $$(METAC_CHECK_CFLAGS)
$$(addprefix $1/,$(2:.checkmk=_checkmk.meta.o)):CFLAGS+=-Wno-format-extra-args $$(METAC_CHECK_CFLAGS)

ifneq ($$(REFLECT-$(2:.checkmk=_checkmk)),n)
IN-$(2:.checkmk=_checkmk)+=$(2:.checkmk=_checkmk.reflect.o)

TPL-$(2:.checkmk=_checkmk.reflect.c):=metac_target
METACFLAGS-$(2:.checkmk=_checkmk.reflect.c)+=run metac-reflect-gen $(METAC_OVERRIDE_IN_TYPE)
IN-$(2:.checkmk=_checkmk.reflect.c)=$$(dir $(2:.c=))_meta_$$(notdir $(2:.checkmk=_checkmk))

TPL-$$(dir $(2:.checkmk=_checkmk))_meta_$$(notdir $(2:.checkmk=_checkmk)):=bin_target
IN-$$(dir $(2:.checkmk=_checkmk))_meta_$$(notdir $(2:.checkmk=_checkmk))=$(2:.checkmk=_checkmk.meta.o)
LDFLAGS-$$(dir $(2:.checkmk=_checkmk))_meta_$$(notdir $(2:.checkmk=_checkmk))=$$(LDFLAGS-$(2:.checkmk=))
DEPS-$$(dir $(2:.checkmk=_checkmk))_meta_$$(notdir $(2:.checkmk=_checkmk))=$$(DEPS-$(2:.checkmk=))
POST-$$(dir $(2:.checkmk=_checkmk))_meta_$$(notdir $(2:.checkmk=_checkmk))=$$(METAC_POST_META)

$(3)+= \
$(2:.checkmk=_checkmk.reflect.c) \
$$(dir $(2:.checkmk=_checkmk))_meta_$$(notdir $(2:.checkmk=_checkmk))
endif

bin_test: $$(addprefix $1/,$(2:.checkmk=_checkmk))

endef # test_checkmk_meta_rules_tpl
test_checkmk_rules = $(eval $(call test_checkmk_meta_rules_tpl,$1,$2,$3))

ifneq ($(INCLUDE),)
RUNFILTERFN:=filter
Expand Down
90 changes: 90 additions & 0 deletions src/value_enum.checkmk
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#include "entry.c"
#include "iterator.c"
#include "value.c"
#include "value_base_type.c"

enum t1 {
t1_a = 0,
t1_b = 1,
t1_z = -1,
t1_c,
t1_d,
}test1 = t1_c;
METAC_GSYM_LINK(test1);

struct {
enum t1 t2_fld;
}test2 = {.t2_fld = t1_c};
METAC_GSYM_LINK(test2);

# suite A Suite 1
# tcase A Test Case 1
# test test1_sanity
metac_value_t * p_val = METAC_VALUE_FROM_LINK(test1);

metac_num_t sz = metac_value_enumeration_info_size(p_val);
fail_unless(sz == 5, "expected 5 possible values, got %d", (int)sz);

struct metac_type_enumerator_info const * p_i = metac_value_enumeration_info(p_val, 2);
fail_unless(p_i != NULL, "got NULL istead of info");
fail_unless(strcmp(p_i->name, "t1_z") == 0, "expect t1_z on the 2nd place, got %s", p_i->name);
fail_unless(p_i->const_value == t1_z, "expected values to be equal t1_z");

metac_name_t n = metac_value_enumeration_to_name(p_val, -1);
fail_unless(n != NULL, "expected -1(t1_z) is in rage");
fail_unless(strcmp(n, "t1_z") == 0 , "expected 't1_z' for -1");
fail_unless(metac_value_enumeration_to_name(p_val, -2) == NULL, "expected -2 isn't in rage");

metac_const_value_t var;
fail_unless(metac_value_enumeration(p_val, &var) == 0, "couldn't read enum");
fail_unless(var == test1, "expected var to be equal t1_c");

var = t1_z;
fail_unless(metac_value_set_enumeration(p_val, var) == 0, "couldn't write enum");
fail_unless(var == test1, "expected var to be equal t1_z");

var = -2;
fail_unless(metac_value_set_enumeration(p_val, var) == 0, "couldn't write enum");
fail_unless(var == test1, "expected var to be equal -2 (though it's not in range of enum)");

metac_value_delete(p_val);

# suite A Suite 2
# tcase A Test Case 2
# test test2_sanity
metac_value_t * p_sval = METAC_VALUE_FROM_LINK(test2);
fail_unless(metac_value_has_members(p_sval) == 1, "must be entity with members");
metac_num_t nm = metac_value_member_count(p_sval);
fail_unless(nm == 1, "expected 1 memeber, got %d", (int)nm);

metac_value_t * p_val = metac_new_value_by_member_id(p_sval, 0);
fail_unless(p_val != NULL, "expected 1st memeber non NULL");

metac_num_t sz = metac_value_enumeration_info_size(p_val);
fail_unless(sz == 5, "expected 5 possible values, got %d", (int)sz);

struct metac_type_enumerator_info const * p_i = metac_value_enumeration_info(p_val, 2);
fail_unless(p_i != NULL, "got NULL istead of info");
fail_unless(strcmp(p_i->name, "t1_z") == 0, "expect t1_z on the 2nd place, got %s", p_i->name);
fail_unless(p_i->const_value == t1_z, "expected values to be equal t1_z");

metac_name_t n = metac_value_enumeration_to_name(p_val, -1);
fail_unless(n != NULL, "expected -1(t1_z) is in rage");
fail_unless(strcmp(n, "t1_z") == 0 , "expected 't1_z' for -1");
fail_unless(metac_value_enumeration_to_name(p_val, -2) == NULL, "expected -2 isn't in rage");


metac_const_value_t var;
fail_unless(metac_value_enumeration(p_val, &var) == 0, "couldn't read enum");
fail_unless(var == test2.t2_fld, "expected var to be equal t1_c");

var = t1_z;
fail_unless(metac_value_set_enumeration(p_val, var) == 0, "couldn't write enum");
fail_unless(var == test2.t2_fld, "expected var to be equal t1_z");

var = -2;
fail_unless(metac_value_set_enumeration(p_val, var) == 0, "couldn't write enum");
fail_unless(var == test2.t2_fld, "expected var to be equal -2 (though it's not in range of enum)");

metac_value_delete(p_val);
metac_value_delete(p_sval);

0 comments on commit 515b72c

Please sign in to comment.