From 1a197d4d86ba50012d7808773fa5b361017f658b Mon Sep 17 00:00:00 2001 From: Adrian Reber Date: Tue, 22 Jun 2021 14:52:09 +0000 Subject: [PATCH] criu: add unit testing for config file parser This tries to add a unit test for the configuration file parser. Signed-off-by: Adrian Reber --- .gitignore | 1 + Makefile | 5 ++ criu/Makefile | 21 ++++++++ criu/unittest/Makefile | 6 +++ criu/unittest/mock.c | 99 ++++++++++++++++++++++++++++++++++ criu/unittest/unit.c | 107 +++++++++++++++++++++++++++++++++++++ scripts/ci/run-ci-tests.sh | 4 ++ 7 files changed, 243 insertions(+) create mode 100644 criu/unittest/Makefile create mode 100644 criu/unittest/mock.c create mode 100644 criu/unittest/unit.c diff --git a/.gitignore b/.gitignore index 3b3da545c..d5135f5f8 100644 --- a/.gitignore +++ b/.gitignore @@ -24,6 +24,7 @@ images/google/protobuf/*.c images/google/protobuf/*.h .gitid criu/criu +criu/unittest/unittest crit/crit criu/arch/*/sys-exec-tbl*.c # x86 syscalls-table is not generated diff --git a/Makefile b/Makefile index 3eb202eea..a8d14ca00 100644 --- a/Makefile +++ b/Makefile @@ -257,6 +257,10 @@ crit: criu $(Q) $(MAKE) $(build)=crit all .PHONY: crit +unittest: $(criu-deps) + $(Q) $(MAKE) $(build)=criu unittest +.PHONY: unittest + # # Libraries next once crit it ready @@ -393,6 +397,7 @@ help: @echo ' cscope - Generate cscope database' @echo ' test - Run zdtm test-suite' @echo ' gcov - Make code coverage report' + @echo ' unittest - Run unit tests' .PHONY: help lint: diff --git a/criu/Makefile b/criu/Makefile index 11d454c81..b92a3f7e9 100644 --- a/criu/Makefile +++ b/criu/Makefile @@ -87,6 +87,26 @@ $(obj)/criu: $(PROGRAM-BUILTINS) $(call msg-link, $@) $(Q) $(CC) $(CFLAGS) $^ $(LIBS) $(WRAPFLAGS) $(LDFLAGS) $(GMONLDOPT) -rdynamic -o $@ +UNIT-BUILTINS += $(obj)/config.o +UNIT-BUILTINS += $(obj)/log.o +UNIT-BUILTINS += $(obj)/string.o +UNIT-BUILTINS += $(obj)/unittest/built-in.o + +$(obj)/unittest/Makefile: ; + +$(obj)/unittest/%: .FORCE + +$(obj)/unittest/built-in.o: .FORCE + $(Q) $(MAKE) $(call build-as,Makefile,criu/unittest) all + +$(obj)/unittest/unittest: $(UNIT-BUILTINS) + $(call msg-link, $@) + $(Q) $(CC) $(CFLAGS) $^ $(LIBS) $(WRAPFLAGS) $(LDFLAGS) -rdynamic -o $@ + +unittest: $(obj)/unittest/unittest + $(Q) $(obj)/unittest/$@ + +.PHONY: unittest # # Clean the most, except generated c files @@ -97,6 +117,7 @@ subclean: $(Q) $(MAKE) $(build)=$(ARCH_DIR) clean $(Q) $(MAKE) $(call build-as,Makefile.library,$(PIE_DIR)) clean $(Q) $(MAKE) $(call build-as,Makefile.crtools,criu) clean + $(Q) $(MAKE) $(call build-as,Makefile,criu/unittest) clean $(Q) $(MAKE) $(build)=$(PIE_DIR) clean .PHONY: subclean cleanup-y += $(obj)/criu diff --git a/criu/unittest/Makefile b/criu/unittest/Makefile new file mode 100644 index 000000000..17bbecf19 --- /dev/null +++ b/criu/unittest/Makefile @@ -0,0 +1,6 @@ +ldflags-y += -r + +obj-y += unit.o +obj-y += mock.o + +cleanup-y += $(obj)/unittest diff --git a/criu/unittest/mock.c b/criu/unittest/mock.c new file mode 100644 index 000000000..fb9d38494 --- /dev/null +++ b/criu/unittest/mock.c @@ -0,0 +1,99 @@ +/* This file contains dummy functions to make the unittest compile */ + +#include +#include +#include + +int add_external(char *key) +{ + return 0; +} + +int irmap_scan_path_add(char *path) +{ + return 0; +} + +bool add_fsname_auto(const char *names) +{ + return true; +} + +bool add_skip_mount(const char *mountpoint) +{ + return true; +} + +int check_add_feature(char *feat) +{ + return 0; +} + +int inherit_fd_parse(char *optarg) +{ + return 0; +} + +int new_cg_root_add(char *controller, char *newroot) +{ + return 0; +} + +int add_script(char *path) +{ + return 0; +} + +int veth_pair_add(char *in, char *out) +{ + return 0; +} + +int unix_sk_ids_parse(char *optarg) +{ + return 0; +} + +bool cgp_add_dump_controller(const char *name) +{ + return 0; +} + +int join_ns_add(const char *type, char *ns_file, char *extra_opts) +{ + return 0; +} + +int ext_mount_add(char *key, char *val) +{ + return 0; +} + +int check_namespace_opts(void) +{ + return 0; +} + +int get_service_fd(int type) +{ + return -1; +} + +void *shmalloc(size_t bytes) +{ + return malloc(bytes); +} + +int install_service_fd(int type, int fd) +{ + return 0; +} + +int close_service_fd(int type) +{ + return 0; +} + +void compel_log_init(int log_fn, unsigned int level) +{ +} diff --git a/criu/unittest/unit.c b/criu/unittest/unit.c new file mode 100644 index 000000000..41eacbffe --- /dev/null +++ b/criu/unittest/unit.c @@ -0,0 +1,107 @@ +#include +#include +#include + + +#include "log.h" +#include "criu-log.h" + +int parse_statement(int i, char *line, char **configuration); + +int main(int argc, char *argv[], char *envp[]) +{ + char **configuration; + int i; + + configuration = malloc(10 * sizeof(char *)); + log_init(NULL); + + i = parse_statement(0, "", configuration); + assert(i == 0); + + i = parse_statement(0, "\n", configuration); + assert(i == 0); + + i = parse_statement(0, "# comment\n", configuration); + assert(i == 0); + + i = parse_statement(0, "#comment\n", configuration); + assert(i == 0); + + i = parse_statement(0, "tcp-close #comment\n", configuration); + assert(i == 1); + assert(!strcmp(configuration[0], "--tcp-close")); + + i = parse_statement(0, " tcp-close #comment\n", configuration); + assert(i == 1); + assert(!strcmp(configuration[0], "--tcp-close")); + + i = parse_statement(0, "test \"test\"\n", configuration); + assert(i == 2); + assert(!strcmp(configuration[0], "--test")); + assert(!strcmp(configuration[1], "test")); + + i = parse_statement(0, "dsfa \"aaaaa \\\"bbbbbb\\\"\"\n", configuration); + assert(i == 2); + assert(!strcmp(configuration[0], "--dsfa")); + assert(!strcmp(configuration[1], "aaaaa \"bbbbbb\"")); + + + i = parse_statement(0, "verbosity 4\n", configuration); + assert(i == 2); + assert(!strcmp(configuration[0], "--verbosity")); + assert(!strcmp(configuration[1], "4")); + + i = parse_statement(0, "verbosity \"\n", configuration); + assert(i == -1); + + i = parse_statement(0, "verbosity 4#comment\n", configuration); + assert(i == 2); + assert(!strcmp(configuration[0], "--verbosity")); + assert(!strcmp(configuration[1], "4")); + + i = parse_statement(0, "verbosity 4 #comment\n", configuration); + assert(i == 2); + assert(!strcmp(configuration[0], "--verbosity")); + assert(!strcmp(configuration[1], "4")); + + i = parse_statement(0, "verbosity 4 #comment\n", configuration); + assert(i == 2); + assert(!strcmp(configuration[0], "--verbosity")); + assert(!strcmp(configuration[1], "4")); + + i = parse_statement(0, "verbosity 4 no-comment\n", configuration); + assert(i == -1); + + i = parse_statement(0, "lsm-profile \"\" # more comments\n", configuration); + assert(i == 2); + assert(!strcmp(configuration[0], "--lsm-profile")); + assert(!strcmp(configuration[1], "")); + + i = parse_statement(0, "lsm-profile \"something\"# comment\n", configuration); + assert(i == 2); + assert(!strcmp(configuration[0], "--lsm-profile")); + assert(!strcmp(configuration[1], "something")); + + i = parse_statement(0, "#\n", configuration); + assert(i == 0); + + i = parse_statement(0, "lsm-profile \"selinux:something\\\"with\\\"quotes\"\n", configuration); + assert(i == 2); + assert(!strcmp(configuration[0], "--lsm-profile")); + assert(!strcmp(configuration[1], "selinux:something\"with\"quotes")); + + i = parse_statement(0, "work-dir \"/tmp with spaces\" no-comment\n", configuration); + assert(i == -1); + + i = parse_statement(0, "work-dir \"/tmp with spaces\"\n", configuration); + assert(i == 2); + assert(!strcmp(configuration[0], "--work-dir")); + assert(!strcmp(configuration[1], "/tmp with spaces")); + + i = parse_statement(0, "a b c d e f g h i\n", configuration); + assert(i == -1); + + pr_msg("OK\n"); + return 0; +} diff --git a/scripts/ci/run-ci-tests.sh b/scripts/ci/run-ci-tests.sh index b0446219e..7a177b67b 100755 --- a/scripts/ci/run-ci-tests.sh +++ b/scripts/ci/run-ci-tests.sh @@ -126,6 +126,10 @@ if [ "$WIDTH" -gt 80 ]; then exit 1 fi +# Unit tests at this point do not require any kernel or hardware capabilities. +# Just try to run it everywhere for now. +time make unittest + [ -n "$SKIP_CI_TEST" ] && exit 0 ulimit -c unlimited