On Tue, 2017-10-24 at 14:26 +0200, Andreas J. Reichel wrote: > From: Andreas Reichel <[email protected]> > > The new testcode initially provides tests for > * internal userspace API core functions > * external userspace API functions (libebgenv.a) > > They are devided into the following test-suits: > > * test_bgenv_init_retval.c, where partition probing must be > faked and disks must be simualted. > * test_probe_config_file.c, where the existence of environment > data is faked for simulated config partitions > * test_ebgenv_api_internal.c, core functions for userspace API > * test_ebgenv_api.c, library API functions for userspace
This is a pretty large patch. Maybe split this patch up a bit? One patch for the empty test setup (test_main and Makefile.am), one for utility functions (fake_devices), and then one patch for each set of tests. Not sure about the removal of the static. I see two options, one patch that removes all the 'static' or remove the 'static' within the patches that use those functions. Makes it easier to review. > > Signed-off-by: Andreas Reichel <[email protected]> > --- > .travis-build.sh | 3 + > env/env_api_fat.c | 6 +- > include/test-interface.h | 4 + > tools/tests/Makefile.am | 56 ++- > tools/tests/fake_devices.c | 94 +++++ > tools/tests/fake_devices.h | 28 ++ > tools/tests/test_bgenv_init_retval.c | 100 +++++ > tools/tests/test_ebgenv_api.c | 641 > +++++++++++++++++++++++++++++ > tools/tests/test_ebgenv_api_internal.c | 416 +++++++++++++++++++ > tools/tests/test_main.c | 34 ++ > tools/tests/test_probe_config_file.c | 202 +++++++++ > tools/tests/test_probe_config_partitions.c | 99 +++++ > 12 files changed, 1673 insertions(+), 10 deletions(-) > create mode 100644 tools/tests/fake_devices.c > create mode 100644 tools/tests/fake_devices.h > create mode 100644 tools/tests/test_bgenv_init_retval.c > create mode 100644 tools/tests/test_ebgenv_api.c > create mode 100644 tools/tests/test_ebgenv_api_internal.c > create mode 100644 tools/tests/test_main.c > create mode 100644 tools/tests/test_probe_config_file.c > create mode 100644 tools/tests/test_probe_config_partitions.c > > diff --git a/.travis-build.sh b/.travis-build.sh > index a7e6beb..d977385 100755 > --- a/.travis-build.sh > +++ b/.travis-build.sh > @@ -115,6 +115,9 @@ case "$TARGET_EFFECTIVE" in > suppress+=" --suppress=unusedFunction:env/fatvars.c" > suppress+=" -- > suppress=unusedFunction:tools/tests/test_environment.c" > suppress+=" --suppress=unusedFunction:env/env_api_fat.c" > + # Some functions are used by linker wrapping > + suppress+=" -- > suppress=unusedFunction:tools/tests/test_probe_config_file.c" > + suppress+=" -- > suppress=unusedFunction:tools/tests/test_ebgenv_api.c" > # EFI uses void* as ImageBase needed for further > calculations > suppress+=" --suppress=arithOperationsOnVoidPointer:main.c" > > diff --git a/env/env_api_fat.c b/env/env_api_fat.c > index a344fcb..8eb1454 100644 > --- a/env/env_api_fat.c > +++ b/env/env_api_fat.c > @@ -20,7 +20,7 @@ > > bool bgenv_verbosity = false; > > -static EBGENVKEY bgenv_str2enum(char *key) > +EBGENVKEY bgenv_str2enum(char *key) > { > if (strncmp(key, "kernelfile", strlen("kernelfile") + 1) == > 0) { > return EBGENV_KERNELFILE; > @@ -120,8 +120,8 @@ bool write_env(CONFIG_PART *part, BG_ENVDATA > *env) > return result; > } > > -static CONFIG_PART config_parts[ENV_NUM_CONFIG_PARTS]; > -static BG_ENVDATA envdata[ENV_NUM_CONFIG_PARTS]; > +CONFIG_PART config_parts[ENV_NUM_CONFIG_PARTS]; > +BG_ENVDATA envdata[ENV_NUM_CONFIG_PARTS]; > > bool bgenv_init() > { > diff --git a/include/test-interface.h b/include/test-interface.h > index 36b0a62..c220d14 100644 > --- a/include/test-interface.h > +++ b/include/test-interface.h > @@ -15,11 +15,15 @@ > > #include "env_api.h" > > +extern CONFIG_PART config_parts[ENV_NUM_CONFIG_PARTS]; > +extern BG_ENVDATA envdata[ENV_NUM_CONFIG_PARTS]; > + > bool read_env(CONFIG_PART *part, BG_ENVDATA *env); > bool write_env(CONFIG_PART *part, BG_ENVDATA *env); > > bool probe_config_file(CONFIG_PART *cfgpart); > bool probe_config_partitions(CONFIG_PART *cfgparts); > bool mount_partition(CONFIG_PART *cfgpart); > +EBGENVKEY bgenv_str2enum(char *key); > > #endif // __TEST_INTERFACE_H__ > diff --git a/tools/tests/Makefile.am b/tools/tests/Makefile.am > index 30dbb85..fd49e06 100644 > --- a/tools/tests/Makefile.am > +++ b/tools/tests/Makefile.am > @@ -12,13 +12,12 @@ > > OBJCOPY ?= objcopy > > -AM_CPPFLAGS = \ > +AM_CFLAGS = \ > -I$(top_srcdir)/include \ > -I$(top_srcdir)/swupdate-adapter \ > -I$(top_srcdir)/tools \ > - -I$(top_srcdir)/fff > - > -AM_CFLAGS = \ > + -I$(top_srcdir)/tools/tests \ > + -I$(top_srcdir)/fff \ Why is that needed? What has changed that CPPFLAGS are now CFLAGS? I don't suppose anything in this patch changed this, so maybe move this change into one of previous patches of this patch set. > -Wno-unused-parameter \ > -Wmissing-prototypes \ > -fshort-wchar \ > @@ -26,11 +25,54 @@ AM_CFLAGS = \ > -D_GNU_SOURCE \ > -g > > +libtest_env_api_fat_a_SRC = \ > + ../../env/env_api.c \ > + ../../env/env_api_fat.c \ > + ../../tools/ebgpart.c \ > + ../../env/env_config_file.c \ > + ../../env/env_config_partitions.c \ > + ../../env/env_disk_utils.c \ > + ../../env/uservars.c > + If i understand it correctly, you are compiling the env api static library with the fat backend here and then link to it via the test cases. I thought about your argument that you want to support the check of multiple different configurations (backends) with one 'make check' and I currently think that you should not bother about this at this level. The intention of 'make check' is to test if the current configuration is working and not if any other configuration works, so this should be delegated to the CI tool. Were there any other arguments for this? > CLEANFILES = > > -test_api: > - ln -sf /bin/true test_api > +noinst_LIBRARIES = libtest_env_api_fat.a > +libtest_env_api_fat_a_SOURCES = $(libtest_env_api_fat_a_SRC) > + > +libenvapi_testlib_fat.a: libtest_env_api_fat.a > + $(OBJCOPY) --weaken $^ $@ ;) So libenvapi_testlib_fat.a is the same as libtest_env_api_fat.a but with weakend symbols right? Why not call it libtest_env_api_fat.weakend.a ? (Or if you remove the build of 'libtest_env_api_fat.a' call it 'libebgenv.weakend.a'. > + > +check_PROGRAMS = test_bgenv_init_retval \ > + test_probe_config_partitions \ > + test_probe_config_file \ > + test_ebgenv_api_internal \ > + test_ebgenv_api > + > +FAT_TESTLIB=libenvapi_testlib_fat.a > + > +SRC_TEST_COMMON=test_main.c > + > +test_bgenv_init_retval_CFLAGS = $(AM_CFLAGS) > +test_bgenv_init_retval_SOURCES = test_bgenv_init_retval.c > $(SRC_TEST_COMMON) > +test_bgenv_init_retval_LDADD = $(FAT_TESTLIB) $(LIBCHECK_LIBS) > + > +test_probe_config_partitions_CFLAGS = $(AM_CFLAGS) > +test_probe_config_partitions_SOURCES = > test_probe_config_partitions.c \ > + fake_devices.c \ > + $(SRC_TEST_COMMON) > +test_probe_config_partitions_LDADD = $(FAT_TESTLIB) $(LIBCHECK_LIBS) > + > +test_probe_config_file_CFLAGS = $(AM_CFLAGS) -Wl, > --wrap=probe_config_file > +test_probe_config_file_SOURCES = test_probe_config_file.c > fake_devices.c \ > + $(SRC_TEST_COMMON) > +test_probe_config_file_LDADD = $(FAT_TESTLIB) $(LIBCHECK_LIBS) > + > +test_ebgenv_api_internal_CFLAGS = $(AM_CFLAGS) > +test_ebgenv_api_internal_SOURCES = test_ebgenv_api_internal.c > $(SRC_TEST_COMMON) > +test_ebgenv_api_internal_LDADD = $(FAT_TESTLIB) $(LIBCHECK_LIBS) > > -check_PROGRAMS = test_api > +test_ebgenv_api_CFLAGS = $(AM_CFLAGS) -Wl,--wrap=bgenv_set -Wl, > --wrap=bgenv_get > +test_ebgenv_api_SOURCES = test_ebgenv_api.c $(SRC_TEST_COMMON) > +test_ebgenv_api_LDADD = $(FAT_TESTLIB) $(LIBCHECK_LIBS) > > TESTS = $(check_PROGRAMS) > diff --git a/tools/tests/fake_devices.c b/tools/tests/fake_devices.c > new file mode 100644 > index 0000000..58a47bd > --- /dev/null > +++ b/tools/tests/fake_devices.c > @@ -0,0 +1,94 @@ > +/* > + * EFI Boot Guard > + * > + * Copyright (c) Siemens AG, 2017 > + * > + * Authors: > + * Andreas Reichel <[email protected]> > + * > + * This work is licensed under the terms of the GNU GPL, version > 2. See > + * the COPYING file in the top-level directory. > + */ > + > +#include <stdlib.h> > +#include <env_api.h> > +#include <env_config_file.h> > +#include <env_config_partitions.h> Hmm... Now when I read this I occurs to me that you should maybe put includes for those other 'env_config*' stuff into the 'env_api.h'. Not really good if you need to import 3 files just to have the complete ebg api. Thats it for now. Will look at the rest later. Cheers, Claudius > +#include <fake_devices.h> > + > +PedDevice *fake_devices; > +int num_fake_devices; > + > +void allocate_fake_devices(int n) > +{ > + fake_devices = (PedDevice *)malloc(n * sizeof(PedDevice)); > + for (char i = 0; i < n; i++) { > + asprintf(&fake_devices[i].model, "%s", "Fake > Device"); > + asprintf(&fake_devices[i].path, "/dev/nobrain_%c", > 'a' + i); > + fake_devices[i].part_list = NULL; > + fake_devices[i].next = NULL; > + } > + num_fake_devices = n; > + for (char i = n - 1; i > 0; i--) { > + fake_devices[i-1].next = &fake_devices[i]; > + } > +} > + > +void add_fake_partition(int devnum) > +{ > + PedPartition **pp = &fake_devices[devnum].part_list; > + > + int16_t num = 0; > + while (*pp) { > + pp = &(*pp)->next; > + num++; > + } > + *pp = (PedPartition *)malloc(sizeof(PedPartition)); > + (*pp)->num = num; > + (*pp)->fs_type = (PedFileSystemType > *)malloc(sizeof(PedFileSystemType)); > + asprintf(&(*pp)->fs_type->name, "%s", "fat16"); > + (*pp)->next = NULL; > +} > + > +void remove_fake_partitions(int n) > +{ > + PedPartition *pp = fake_devices[n].part_list; > + PedPartition *next; > + while(pp) { > + next = pp->next; > + if (!pp->fs_type) > + goto skip_fstype; > + if (pp->fs_type->name) > + free(pp->fs_type->name); > + free(pp->fs_type); > +skip_fstype: > + free(pp); > + pp = next; > + } > +} > + > +void free_fake_devices() > +{ > + if (!fake_devices) { > + return; > + } > + > + for (int i = 0; i < num_fake_devices; i++) { > + if (fake_devices[i].model) > + free(fake_devices[i].model); > + if (fake_devices[i].path) > + free(fake_devices[i].path); > + if (fake_devices[i].part_list) > + remove_fake_partitions(i); > + } > + > + free(fake_devices); > +} > + > +PedDevice *ped_device_get_next_custom_fake(const PedDevice *dev) > +{ > + if (!dev) > + return fake_devices; > + > + return dev->next; > +} > diff --git a/tools/tests/fake_devices.h b/tools/tests/fake_devices.h > new file mode 100644 > index 0000000..aa5f423 > --- /dev/null > +++ b/tools/tests/fake_devices.h > @@ -0,0 +1,28 @@ > +/* > + * EFI Boot Guard > + * > + * Copyright (c) Siemens AG, 2017 > + * > + * Authors: > + * Andreas Reichel <[email protected]> > + * > + * This work is licensed under the terms of the GNU GPL, version > 2. See > + * the COPYING file in the top-level directory. > + */ > + > +#ifndef __FAKE_DEVICES_H__ > +#define __FAKE_DEVICES_H__ > + > +#include <ebgpart.h> > + > +extern PedDevice *fake_devices; > +extern int num_fake_devices; > + > +void allocate_fake_devices(int n); > +void add_fake_partition(int devnum); > +void remove_fake_partitions(int n); > +void free_fake_devices(void); > + > +PedDevice *ped_device_get_next_custom_fake(const PedDevice *dev); > + > +#endif // __FAKE_DEVICES_H__ > diff --git a/tools/tests/test_bgenv_init_retval.c > b/tools/tests/test_bgenv_init_retval.c > new file mode 100644 > index 0000000..76ec253 > --- /dev/null > +++ b/tools/tests/test_bgenv_init_retval.c > @@ -0,0 +1,100 @@ > +/* > + * EFI Boot Guard > + * > + * Copyright (c) Siemens AG, 2017 > + * > + * Authors: > + * Andreas Reichel <[email protected]> > + * > + * This work is licensed under the terms of the GNU GPL, version > 2. See > + * the COPYING file in the top-level directory. > + */ > + > +#ifndef ENV_NUM_CONFIG_PARTITIONS > +# define ENV_NUM_CONFIG_PARTITIONS 2 > +#endif > + > +#include <stdlib.h> > +#include <check.h> > +#include <fff.h> > +#include <env_api.h> > +#include <env_config_file.h> > +#include <env_config_partitions.h> > + > +DEFINE_FFF_GLOBALS; > + > +static char *devpath = "/dev/nobrain"; > + > +bool read_env(CONFIG_PART *part, BG_ENVDATA *env); > + > +Suite *env_api_fat_suite(void); > +bool probe_config_partitions_custom_fake(CONFIG_PART *cfgpart); > +bool read_env_custom_fake(CONFIG_PART *cp, BG_ENVDATA *env); > + > +Suite *ebg_test_suite(void); > + > +bool probe_config_partitions_custom_fake(CONFIG_PART *cfgpart) > +{ > + for (int i = 0; i < ENV_NUM_CONFIG_PARTS; i++) { > + cfgpart[i].devpath = devpath; > + } > + return true; > +} > + > +bool read_env_custom_fake(CONFIG_PART *cp, BG_ENVDATA *env) > +{ > + if (!env) { > + return false; > + } > + memset(env, 0, sizeof(BG_ENVDATA)); > + return true; > +} > + > +FAKE_VALUE_FUNC(bool, probe_config_partitions, CONFIG_PART *); > +FAKE_VALUE_FUNC(bool, read_env, CONFIG_PART *, BG_ENVDATA *); > + > +START_TEST(env_api_fat_test_bgenv_init_retval) > +{ > + bool result; > + /* In this unit test, contents of environment data are > + * faked to be all zero > + */ > + > + /* Test if bgenv_init fails if no config partitions are > found > + */ > + RESET_FAKE(probe_config_partitions); > + > + probe_config_partitions_fake.return_val = false; > + > + result = bgenv_init(); > + > + ck_assert(probe_config_partitions_fake.call_count == 1); > + ck_assert(result == false); > + > + /* Test if bgenv_init succeeds if config partitions are > found > + */ > + RESET_FAKE(probe_config_partitions); > + > + probe_config_partitions_fake.custom_fake = > probe_config_partitions_custom_fake; > + read_env_fake.custom_fake = read_env_custom_fake; > + result = bgenv_init(); > + > + ck_assert(probe_config_partitions_fake.call_count == 1); > + ck_assert(read_env_fake.call_count == ENV_NUM_CONFIG_PARTS); > + ck_assert(result == true); > +} > +END_TEST > + > +Suite *ebg_test_suite(void) > +{ > + Suite *s; > + TCase *tc_core; > + > + s = suite_create("env_api_fat"); > + > + tc_core = tcase_create("Core"); > + tcase_add_test(tc_core, env_api_fat_test_bgenv_init_retval); > + suite_add_tcase(s, tc_core); > + > + return s; > +} > diff --git a/tools/tests/test_ebgenv_api.c > b/tools/tests/test_ebgenv_api.c > new file mode 100644 > index 0000000..530f338 > --- /dev/null > +++ b/tools/tests/test_ebgenv_api.c > @@ -0,0 +1,641 @@ > +/* > + * EFI Boot Guard > + * > + * Copyright (c) Siemens AG, 2017 > + * > + * Authors: > + * Andreas Reichel <[email protected]> > + * > + * This work is licensed under the terms of the GNU GPL, version > 2. See > + * the COPYING file in the top-level directory. > + */ > + > +#include <config.h> > + > +#ifndef ENV_NUM_CONFIG_PARTITIONS > +# define ENV_NUM_CONFIG_PARTITIONS 2 > +#endif > + > +#include <stdlib.h> > +#include <check.h> > +#include <fff.h> > +#include <env_api.h> > +#include <ebgenv.h> > +#include <env_config_file.h> > +#include <env_config_partitions.h> > + > +DEFINE_FFF_GLOBALS; > + > +static char *devpath = "/dev/nobrain"; > + > +Suite *ebg_test_suite(void); > + > +extern bool write_env(CONFIG_PART *part, BG_ENVDATA *env); > +extern bool bgenv_write(BGENV *); > +extern bool bgenv_init(void); > +extern bool bgenv_close(BGENV *); > +extern BGENV *bgenv_create_new(void); > + > +FAKE_VALUE_FUNC(bool, bgenv_init); > +FAKE_VALUE_FUNC(bool, bgenv_write, BGENV *); > +FAKE_VALUE_FUNC(bool, bgenv_close, BGENV *); > + > +int __real_bgenv_set(BGENV *, char *, char *, void *, uint32_t); > +int __wrap_bgenv_set(BGENV *, char *, char *, void *, uint32_t); > +int __real_bgenv_get(BGENV *, char *, char *, void *, uint32_t); > +int __wrap_bgenv_get(BGENV *, char *, char *, void *, uint32_t); > + > +BGENV *bgenv_getset_arg0; > +char *bgenv_getset_arg1; > +char *bgenv_getset_arg2; > +void *bgenv_getset_arg3; > +uint32_t bgenv_getset_arg4; > +int bgenv_get_call_count; > +int bgenv_set_call_count; > + > +/* FFF does not provide calls to the original function, so in this > case > + * we need to use the linker wrapping method and reimplement some of > FFFs > + * functionality. > + */ > +int __wrap_bgenv_get(BGENV *env, char *key, char *type, void > *buffer, uint32_t len) > +{ > + bgenv_get_call_count++; > + bgenv_getset_arg0 = env; > + bgenv_getset_arg1 = key; > + bgenv_getset_arg2 = type; > + bgenv_getset_arg3 = buffer; > + bgenv_getset_arg4 = len; > + return __real_bgenv_get(env, key, type, buffer, len); > +} > + > +int __wrap_bgenv_set(BGENV *env, char *key, char *type, void > *buffer, uint32_t len) > +{ > + bgenv_set_call_count++; > + bgenv_getset_arg0 = env; > + bgenv_getset_arg1 = key; > + bgenv_getset_arg2 = type; > + bgenv_getset_arg3 = buffer; > + bgenv_getset_arg4 = len; > + return __real_bgenv_set(env, key, type, buffer, len); > +} > + > +/* These variables substitute weakened symbols in the ebgenv library > code > + * so that all environment functions use these as data sources > + */ > +CONFIG_PART config_parts[ENV_NUM_CONFIG_PARTS]; > +BG_ENVDATA envdata[ENV_NUM_CONFIG_PARTS]; > + > +START_TEST(ebgenv_api_ebg_env_create_new) > +{ > + ebgenv_t e; > + int ret; > + wchar_t bufferw[10]; > + char buffer[10]; > + char *kernelfile = "kernel123"; > + char *kernelparams = "param456"; > + > + memset(&e, 0, sizeof(e)); > + > + /* Test if ebg_env_create_new returns EIO if bgenv_init > + * returns false > + */ > + bgenv_init_fake.return_val = false; > + ret = ebg_env_create_new(&e); > + ck_assert_int_eq(ret, EIO); > + > + /* Test if errno is returned by ebg_env_created, if the > bgenv pointer > + * is NULL but ebg_new_env_created is true, which is > contradictory. > + * Also, ebg_new_env_created must be reset to false. > + */ > + bgenv_init_fake.return_val = true; > + bgenv_close_fake.return_val = true; > + for (int i = 0; i < ENV_NUM_CONFIG_PARTS; i++) > + { > + envdata[i].revision = i; > + } > + e.ebg_new_env_created = true; > + e.bgenv = NULL; > + errno = 3044; > + > + ret = ebg_env_create_new(&e); > + > + ck_assert_int_eq(ret, 3044); > + ck_assert(e.ebg_new_env_created == false); > + > + /* Check if values of the latest environment are copied if a > new > + * environment is created. The new environment must > overwrite the > + * oldest environment and revision and ustate must be set > correctly. > + */ > + envdata[ENV_NUM_CONFIG_PARTS-1].watchdog_timeout_sec = 44; > + (void)str8to16(bufferw, kernelfile); > + memcpy(envdata[ENV_NUM_CONFIG_PARTS-1].kernelfile, bufferw, > + strlen(kernelfile) * 2 + 2); > + (void)str8to16(bufferw, kernelparams); > + memcpy(envdata[ENV_NUM_CONFIG_PARTS-1].kernelparams, > bufferw, > + strlen(kernelparams) * 2 + 2); > + errno = 0; > + > + ret = ebg_env_create_new(&e); > + > + ck_assert_int_eq(errno, 0); > + ck_assert_int_eq(ret, 0); > + ck_assert(((BGENV *)e.bgenv)->data == &envdata[0]); > + ck_assert_int_eq( > + ((BGENV *)e.bgenv)->data->revision, > ENV_NUM_CONFIG_PARTS); > + ck_assert_int_eq(((BGENV *)e.bgenv)->data->ustate, > USTATE_INSTALLED); > + ck_assert_int_eq(((BGENV *)e.bgenv)->data- > >watchdog_timeout_sec, 44); > + (void)str16to8(buffer, ((BGENV *)e.bgenv)->data- > >kernelfile); > + ck_assert_int_eq( > + strncmp(buffer, kernelfile, strlen(kernelfile) + 1), > 0); > + (void)str16to8(buffer, ((BGENV *)e.bgenv)->data- > >kernelparams); > + ck_assert_int_eq( > + strncmp(buffer, kernelparams, strlen(kernelparams) + > 1), 0); > +} > +END_TEST > + > +START_TEST(ebgenv_api_ebg_env_open_current) > +{ > + ebgenv_t e; > + int ret; > + memset(&e, 0, sizeof(e)); > + > + /* Test if ebg_env_open_current returns EIO if bgenv_init > returns false > + */ > + bgenv_init_fake.return_val = false; > + ret = ebg_env_open_current(&e); > + > + ck_assert_int_eq(ret, EIO); > + > +#if ENV_NUM_CONFIG_PARTS > 1 > + > + /* Test if ebg_env_open_current opens the environment with > the highest > + * revision > + */ > + for (int i = 0; i < ENV_NUM_CONFIG_PARTS; i++) { > + envdata[i].revision = i + 1; > + } > + > + bgenv_init_fake.return_val = true; > + ret = ebg_env_open_current(&e); > + > + ck_assert_int_eq(ret, 0); > + ck_assert(((BGENV *)e.bgenv)->data == > &envdata[ENV_NUM_CONFIG_PARTS-1]); > + > + (void)ebg_env_close(&e); > + > + envdata[0].revision = 0xFFFF; > + > + ret = ebg_env_open_current(&e); > + > + ck_assert_int_eq(ret, 0); > + ck_assert(((BGENV *)e.bgenv)->data == &envdata[0]); > + > + (void)ebg_env_close(&e); > +#endif > + > +} > +END_TEST > + > +START_TEST(ebgenv_api_ebg_env_get) > +{ > + ebgenv_t e; > + memset(&e, 0, sizeof(e)); > + int ret; > + char buffer[1]; > + > + /* Test if ebg_env_get calls bg_env_get correctly and that > it returns > + * -EINVAL if no key is provided > + */ > + bgenv_get_call_count = 0; > + > + ret = ebg_env_get(&e, NULL, NULL); > + ck_assert_int_eq(ret, -EINVAL); > + > + ck_assert(bgenv_get_call_count == 1); > + ck_assert(bgenv_getset_arg0 == e.bgenv); > + ck_assert(bgenv_getset_arg1 == NULL); > + ck_assert(bgenv_getset_arg2 == NULL); > + > + /* Test if ebg_env_get retrieves correct data if given a > valid > + * environment handle. > + */ > + e.bgenv = (BGENV *)calloc(1, sizeof(BGENV)); > + ck_assert(e.bgenv != NULL); > + > + ((BGENV *)e.bgenv)->data = (BG_ENVDATA *)calloc(1, > sizeof(BG_ENVDATA)); > + ck_assert(((BGENV *)e.bgenv)->data != NULL); > + > + bgenv_get_call_count = 0; > + > + (void)ebg_env_get(&e, "kernelfile", buffer); > + > + ck_assert(bgenv_get_call_count == 1); > + ck_assert(bgenv_getset_arg0 == e.bgenv); > + ck_assert_int_eq(strcmp(bgenv_getset_arg1, "kernelfile"), > 0); > + ck_assert(bgenv_getset_arg3 == buffer); > + > + free(((BGENV *)e.bgenv)->data); > + free(e.bgenv); > + > +} > +END_TEST > + > +START_TEST(ebgenv_api_ebg_env_set) > +{ > + ebgenv_t e; > + memset(&e, 0, sizeof(e)); > + char *value = "dummy"; > + > + /* Check if ebg_env_set correctly calls bgenv_set > + */ > + bgenv_set_call_count = 0; > + > + e.bgenv = (BGENV *)calloc(1, sizeof(BGENV)); > + ck_assert(e.bgenv != NULL); > + > + ((BGENV *)e.bgenv)->data = (BG_ENVDATA *)calloc(1, > sizeof(BG_ENVDATA)); > + ck_assert(((BGENV *)e.bgenv)->data != NULL); > + > + (void)ebg_env_set(&e, "kernelfile", value); > + > + ck_assert(bgenv_set_call_count == 1); > + ck_assert(bgenv_getset_arg0 == e.bgenv); > + ck_assert_int_eq(strcmp(bgenv_getset_arg1, "kernelfile"), > 0); > + ck_assert(bgenv_getset_arg3 == value); > + ck_assert(bgenv_getset_arg4 == strlen(value) + 1); > + > + free(((BGENV *)e.bgenv)->data); > + free(e.bgenv); > +} > +END_TEST > + > +START_TEST(ebgenv_api_ebg_env_set_ex) > +{ > + > + ebgenv_t e; > + memset(&e, 0, sizeof(e)); > + char *key = "mykey"; > + char *value = "dummy"; > + char *usertype = "mytype"; > + int32_t datalen = 5; > + > + /* Check if ebg_env_set_ex correctly calls bgenv_set > + */ > + bgenv_set_call_count = 0; > + > + e.bgenv = (BGENV *)calloc(1, sizeof(BGENV)); > + ck_assert(e.bgenv != NULL); > + > + ((BGENV *)e.bgenv)->data = (BG_ENVDATA *)calloc(1, > sizeof(BG_ENVDATA)); > + ck_assert(((BGENV *)e.bgenv)->data != NULL); > + > + bgenv_set_call_count = 0; > + > + (void)ebg_env_set_ex(&e, key, usertype, (uint8_t *)value, > datalen); > + > + ck_assert(bgenv_set_call_count == 1); > + ck_assert(bgenv_getset_arg0 == e.bgenv); > + ck_assert_int_eq(strcmp(bgenv_getset_arg1, key), 0); > + ck_assert_int_eq(strcmp(bgenv_getset_arg2, usertype), 0); > + ck_assert(bgenv_getset_arg3 == value); > + ck_assert(bgenv_getset_arg4 == datalen); > + > + free(((BGENV *)e.bgenv)->data); > + free(e.bgenv); > +} > +END_TEST > + > +START_TEST(ebgenv_api_ebg_env_get_ex) > +{ > + ebgenv_t e; > + memset(&e, 0, sizeof(e)); > + char *key = "mykey"; > + char buffer[5]; > + char type[7]; > + int32_t datalen = 5; > + > + /* Check if ebg_env_get_ex correctly calls bgenv_get > + */ > + bgenv_get_call_count = 0; > + > + e.bgenv = (BGENV *)calloc(1, sizeof(BGENV)); > + ck_assert(e.bgenv != NULL); > + > + ((BGENV *)e.bgenv)->data = (BG_ENVDATA *)calloc(1, > sizeof(BG_ENVDATA)); > + ck_assert(((BGENV *)e.bgenv)->data != NULL); > + > + bgenv_get_call_count = 0; > + > + (void)ebg_env_get_ex(&e, key, type, (uint8_t *)buffer, > datalen); > + > + ck_assert(bgenv_get_call_count == 1); > + ck_assert(bgenv_getset_arg0 == e.bgenv); > + ck_assert_int_eq(strcmp(bgenv_getset_arg1, key), 0); > + ck_assert(bgenv_getset_arg2 == type); > + ck_assert(bgenv_getset_arg3 == buffer); > + ck_assert(bgenv_getset_arg4 == datalen); > + > + free(((BGENV *)e.bgenv)->data); > + free(e.bgenv); > +} > +END_TEST > + > +START_TEST(ebgenv_api_ebg_env_user_free) > +{ > + ebgenv_t e; > + uint32_t ret; > + memset(&e, 0, sizeof(e)); > + > + /* Check if ebg_env_user_free returns 0 if no environment > handle > + * is available (invalid context). > + */ > + ret = ebg_env_user_free(&e); > + ck_assert_int_eq(ret, 0); > + > + /* Check if ebg_env_user_free returns 0 if no environment > data > + * is available (NULL environment). > + */ > + e.bgenv = (BGENV *)calloc(1, sizeof(BGENV)); > + ck_assert(e.bgenv != NULL); > + > + ret = ebg_env_user_free(&e); > + ck_assert_int_eq(ret, 0); > + > + /* Check if ebg_env_user_free returns ENV_MEM_USERVARS if > environment > + * user space is empty > + */ > + ((BGENV *)e.bgenv)->data = (BG_ENVDATA *)calloc(1, > sizeof(BG_ENVDATA)); > + ck_assert(((BGENV *)e.bgenv)->data != NULL); > + > + ret = ebg_env_user_free(&e); > + ck_assert_int_eq(ret, ENV_MEM_USERVARS); > + > + free(((BGENV *)e.bgenv)->data); > + free(e.bgenv); > +} > +END_TEST > + > +START_TEST(ebgenv_api_ebg_env_getglobalstate) > +{ > +#if ENV_NUM_CONFIG_PARTS > 1 > + ebgenv_t e; > + uint16_t state; > + memset(&e, 0, sizeof(e)); > + > + /* Test if ebg_env_getglobalstate returns OK if current > environment > + * is set to OK > + */ > + e.bgenv = (BGENV *)calloc(1, sizeof(BGENV)); > + ck_assert(e.bgenv != NULL); > + > + for (int i = 0; i < ENV_NUM_CONFIG_PARTS; i++) { > + envdata[i].revision = i + 1; > + } > + > + envdata[1].revision = 0; > + envdata[1].ustate = USTATE_OK; > + > + state = ebg_env_getglobalstate(&e); > + ck_assert_int_eq(state, USTATE_OK); > + > + /* Test if ebg_env_getglobalstate returns FAILED if current > environment > + * is set to FAILED with revision 0 > + */ > + envdata[1].revision = 0; > + envdata[1].ustate = USTATE_FAILED; > + > + state = ebg_env_getglobalstate(&e); > + ck_assert_int_eq(state, USTATE_FAILED); > + > + /* Test if ebg_env_getglobalstate returns FAILED if current > environment > + * is set to FAILED with non-zero revision > + */ > + envdata[1].revision = 15; > + > + state = ebg_env_getglobalstate(&e); > + ck_assert_int_eq(state, USTATE_FAILED); > + > + /* Test if ebg_env_getglobalstate returns INSTALLED if > current > + * environment is set to INSTALLED > + */ > + envdata[1].revision = 15; > + envdata[1].ustate = USTATE_INSTALLED; > + > + state = ebg_env_getglobalstate(&e); > + ck_assert_int_eq(state, USTATE_INSTALLED); > + > + /* Test if ebg_env_getglobalstate returns FAILED if current > environment > + * is set to OK and any other is set to FAILED > + */ > + envdata[1].ustate = USTATE_OK; > + envdata[0].revision = 0; > + envdata[0].ustate = USTATE_FAILED; > + > + state = ebg_env_getglobalstate(&e); > + ck_assert_int_eq(state, USTATE_FAILED); > + > + /* Test if ebg_env_getglobalstate returns OK if current > environment is > + * set to OK and any other is set to INSTALLED > + */ > + envdata[0].ustate = USTATE_INSTALLED; > + > + state = ebg_env_getglobalstate(&e); > + ck_assert_int_eq(state, USTATE_OK); > + > + /* Test if ebg_env_getglobalstate returns TESTING if current > + * environment is set to TESTING and none is FAILED > + */ > + envdata[0].ustate = USTATE_OK; > + envdata[1].ustate = USTATE_TESTING; > + > + state = ebg_env_getglobalstate(&e); > + ck_assert_int_eq(state, USTATE_TESTING); > + > + /* Test if ebg_env_getglobalstate returns OK if current > environment is > + * set to OK and none is TESTING > + */ > + envdata[0].ustate = USTATE_TESTING; > + envdata[1].ustate = USTATE_OK; > + > + state = ebg_env_getglobalstate(&e); > + ck_assert_int_eq(state, USTATE_OK); > + > + free(e.bgenv); > +#endif > +} > +END_TEST > + > +START_TEST(ebgenv_api_ebg_env_setglobalstate) > +{ > +#if ENV_NUM_CONFIG_PARTS > 1 > + ebgenv_t e; > + int ret; > + memset(&e, 0, sizeof(e)); > + > + /* Test if ebg_env_setglobalstate sets only current to > FAILED > + */ > + for (int i = 0; i < ENV_NUM_CONFIG_PARTS; i++) { > + envdata[i].revision = i + 1; > + } > + > + bgenv_init_fake.return_val = true; > + > + ret = ebg_env_open_current(&e); > + > + ck_assert_int_eq(ret, 0); > + ck_assert(((BGENV *)e.bgenv)->data == > &envdata[ENV_NUM_CONFIG_PARTS-1]); > + > + envdata[0].ustate = USTATE_OK; > + envdata[1].ustate = USTATE_OK; > + > + ret = ebg_env_setglobalstate(&e, 0xFFF); > + ck_assert_int_eq(ret, EINVAL); > + > + ret = ebg_env_setglobalstate(&e, USTATE_FAILED); > + > + ck_assert_int_eq(ret, 0); > + > + ck_assert_int_eq(envdata[0].ustate, USTATE_OK); > + ck_assert_int_eq(envdata[ENV_NUM_CONFIG_PARTS-1].ustate, > USTATE_FAILED); > + > + envdata[1].ustate = USTATE_OK; > + envdata[0].ustate = USTATE_OK; > + > + (void)ebg_env_close(&e); > + > + envdata[0].revision = 1313; > + > + ret = ebg_env_open_current(&e); > + ck_assert_int_eq(ret, 0); > + > + ret = ebg_env_setglobalstate(&e, USTATE_FAILED); > + ck_assert_int_eq(ret, 0); > + ck_assert_int_eq(envdata[0].ustate, USTATE_FAILED); > + ck_assert_int_eq(envdata[1].ustate, USTATE_OK); > + > + /* Test if ebg_env_setglobalstate sets ALL environments to > OK > + */ > + envdata[0].ustate = USTATE_FAILED; > + envdata[1].ustate = USTATE_FAILED; > + > + bgenv_write_fake.return_val = true; > + bgenv_close_fake.return_val = true; > + > + ret = ebg_env_setglobalstate(&e, USTATE_OK); > + > + ck_assert_int_eq(ret, 0); > + ck_assert_int_eq(envdata[0].ustate, USTATE_OK); > + ck_assert_int_eq(envdata[1].ustate, USTATE_OK); > + > + /* Test if ebg_env_setglobalstate sets current environment > to TESTING > + */ > + envdata[0].ustate = USTATE_INSTALLED; > + envdata[1].ustate = USTATE_INSTALLED; > + > + ret = ebg_env_setglobalstate(&e, USTATE_TESTING); > + > + ck_assert_int_eq(ret, 0); > + ck_assert_int_eq(envdata[0].ustate, USTATE_TESTING); > + ck_assert_int_eq(envdata[1].ustate, USTATE_INSTALLED); > + > + /* Test if ebg_env_setglobalstate fails and returns EIO if > bgenv_write > + * fails > + */ > + bgenv_write_fake.return_val = false; > + bgenv_close_fake.return_val = true; > + > + ret = ebg_env_setglobalstate(&e, USTATE_OK); > + > + ck_assert_int_eq(ret, EIO); > + > + /* Test if ebg_env_setglobalstate fails and returns EIO if > bgenv_close > + * fails > + */ > + bgenv_write_fake.return_val = true; > + bgenv_close_fake.return_val = false; > + > + ret = ebg_env_setglobalstate(&e, USTATE_OK); > + > + ck_assert_int_eq(ret, EIO); > + > + (void)ebg_env_close(&e); > +#endif > +} > +END_TEST > + > +START_TEST(ebgenv_api_ebg_env_close) > +{ > + ebgenv_t e; > + int ret; > + memset(&e, 0, sizeof(e)); > + > + /* Test if ebg_env_close fails with invalid context and > returns EIO > + */ > + ret = ebg_env_close(&e); > + ck_assert_int_eq(ret, EIO); > + > + /* Test if ebg_env_close fails and returns EIO if > bgenv_write fails > + */ > + e.bgenv = calloc(1, sizeof(BGENV)); > + ck_assert(e.bgenv != NULL); > + > + ((BGENV *)e.bgenv)->data = calloc(1, sizeof(BG_ENVDATA)); > + bgenv_write_fake.return_val = false; > + bgenv_close_fake.return_val = true; > + ret = ebg_env_close(&e); > + > + ck_assert_int_eq(ret, EIO); > + > + /* Test if ebg_env_close fails and returns EIO if > bgenv_close fails. > + */ > + bgenv_write_fake.return_val = true; > + bgenv_close_fake.return_val = false; > + ret = ebg_env_close(&e); > + > + ck_assert_int_eq(ret, EIO); > + > + /* Test if ebg_env_close is successful if all prerequisites > are met > + */ > + bgenv_write_fake.return_val = true; > + bgenv_close_fake.return_val = true; > + BGENV *save_ptr = e.bgenv; > + ret = ebg_env_close(&e); > + > + ck_assert_int_eq(ret, 0); > + ck_assert(e.bgenv == NULL); > + > + free(save_ptr->data); > + free(save_ptr); > +} > +END_TEST > + > +Suite *ebg_test_suite(void) > +{ > + Suite *s; > + TCase *tc_core; > + > + s = suite_create("ebgenv_api"); > + > + TFun tfuncs[] = { > + ebgenv_api_ebg_env_create_new, > + ebgenv_api_ebg_env_open_current, > + ebgenv_api_ebg_env_get, > + ebgenv_api_ebg_env_set, > + ebgenv_api_ebg_env_set_ex, > + ebgenv_api_ebg_env_get_ex, > + ebgenv_api_ebg_env_user_free, > + ebgenv_api_ebg_env_getglobalstate, > + ebgenv_api_ebg_env_setglobalstate, > + ebgenv_api_ebg_env_close > + }; > + > + tc_core = tcase_create("Core"); > + > + for (int i = 0; i < sizeof(tfuncs)/sizeof(void *); i++) { > + tcase_add_test(tc_core, tfuncs[i]); > + } > + > + suite_add_tcase(s, tc_core); > + > + return s; > +} > diff --git a/tools/tests/test_ebgenv_api_internal.c > b/tools/tests/test_ebgenv_api_internal.c > new file mode 100644 > index 0000000..1f5ce93 > --- /dev/null > +++ b/tools/tests/test_ebgenv_api_internal.c > @@ -0,0 +1,416 @@ > +/* > + * EFI Boot Guard > + * > + * Copyright (c) Siemens AG, 2017 > + * > + * Authors: > + * Andreas Reichel <[email protected]> > + * > + * This work is licensed under the terms of the GNU GPL, version > 2. See > + * the COPYING file in the top-level directory. > + */ > + > +#ifndef ENV_NUM_CONFIG_PARTITIONS > +# define ENV_NUM_CONFIG_PARTITIONS 2 > +#endif > + > +#include <stdlib.h> > +#include <check.h> > +#include <fff.h> > +#include <env_api.h> > +#include <env_config_file.h> > +#include <env_config_partitions.h> > + > +DEFINE_FFF_GLOBALS; > + > +static char *devpath = "/dev/nobrain"; > + > +Suite *ebg_test_suite(void); > + > +extern bool write_env(CONFIG_PART *part, BG_ENVDATA *env); > +extern EBGENVKEY bgenv_str2enum(char *); > +extern BGENV *bgenv_open_by_index(uint32_t index); > + > +bool write_env_custom_fake(CONFIG_PART *part, BG_ENVDATA *env); > + > +bool write_env_custom_fake(CONFIG_PART *part, BG_ENVDATA *env) > +{ > + return true; > +} > + > +FAKE_VALUE_FUNC(bool, write_env, CONFIG_PART *, BG_ENVDATA *); > + > +CONFIG_PART config_parts[ENV_NUM_CONFIG_PARTS]; > +BG_ENVDATA envdata[ENV_NUM_CONFIG_PARTS]; > + > +START_TEST(ebgenv_api_internal_strXtoY) > +{ > + wchar_t *exp_res = L"This is a test"; > + wchar_t bufferw[16]; > + char buffer[16]; > + char *input = "This is a test"; > + wchar_t *resw; > + char *res; > + > + /* Test conversion from ASCII bits to 16 bit encoding > + */ > + resw = str8to16(bufferw, input); > + > + /* cannot use glibc for 16-bit wchar_t > + * string compare since glibc has 32-bit wchar_t > + */ > + for (int i = 0; i < strlen(input); i++) { > + ck_assert(resw[i] == exp_res[i]); > + } > + > + /* Test conversion from 16 bit encoding to ASCII > + */ > + res = str16to8(buffer, exp_res); > + > + ck_assert(strcmp(res, input) == 0); > +} > +END_TEST > + > +START_TEST(ebgenv_api_internal_bgenv_str2enum) > +{ > + EBGENVKEY e; > + > + /* Test bgenv_str2enum for correct key conversion > + */ > + e = bgenv_str2enum("kernelfile"); > + ck_assert(e == EBGENV_KERNELFILE); > + > + e = bgenv_str2enum("kernelparams"); > + ck_assert(e == EBGENV_KERNELPARAMS); > + > + e = bgenv_str2enum("watchdog_timeout_sec"); > + ck_assert(e == EBGENV_WATCHDOG_TIMEOUT_SEC); > + > + e = bgenv_str2enum("revision"); > + ck_assert(e == EBGENV_REVISION); > + > + e = bgenv_str2enum("ustate"); > + ck_assert(e == EBGENV_USTATE); > + > + /* Test if bgenv_str2enum returns EBGENV_UNKNOWN for empty > and invalid > + * keys > + */ > + e = bgenv_str2enum("XZXOOZOOZIOFZOFZ"); > + ck_assert(e == EBGENV_UNKNOWN); > + > + e = bgenv_str2enum(""); > + ck_assert(e == EBGENV_UNKNOWN); > + > +} > +END_TEST > + > +START_TEST(ebgenv_api_internal_bgenv_open_by_index) > +{ > + BGENV *handle; > + > + handle = bgenv_open_by_index(0); > + ck_assert(handle != NULL); > + ck_assert(handle->desc == &config_parts[0]); > + ck_assert(handle->data == &envdata[0]); > + free(handle); > + > + handle = bgenv_open_by_index(ENV_NUM_CONFIG_PARTS-1); > + ck_assert(handle != NULL); > + ck_assert(handle->desc == > &config_parts[ENV_NUM_CONFIG_PARTS-1]); > + ck_assert(handle->data == &envdata[ENV_NUM_CONFIG_PARTS-1]); > + free(handle); > + > + /* Test if bgenv_open_by_index returns NULL if parameter is > out of > + * range > + */ > + handle = bgenv_open_by_index(ENV_NUM_CONFIG_PARTS); > + ck_assert(handle == NULL); > +} > +END_TEST > + > +START_TEST(ebgenv_api_internal_bgenv_open_oldest) > +{ > + BGENV *handle; > + > + /* Test if bgenv_open_oldest returns a handle for the > environment with > + * the lowest revision > + */ > + for (int i = 0; i < ENV_NUM_CONFIG_PARTS; i++) > + { > + envdata[i].revision = ENV_NUM_CONFIG_PARTS - i; > + } > + handle = bgenv_open_oldest(); > + ck_assert(handle != NULL); > + ck_assert(handle->desc == > &config_parts[ENV_NUM_CONFIG_PARTS-1]); > + ck_assert(handle->data == &envdata[ENV_NUM_CONFIG_PARTS-1]); > + free(handle); > +} > +END_TEST > + > +START_TEST(ebgenv_api_internal_bgenv_open_latest) > +{ > + BGENV *handle; > + > + /* Test if bgenv_open_latest returns a handle for the > environment with > + * the highest revision > + */ > + for (int i = 0; i < ENV_NUM_CONFIG_PARTS; i++) > + { > + envdata[i].revision = ENV_NUM_CONFIG_PARTS - i; > + } > + handle = bgenv_open_latest(); > + ck_assert(handle != NULL); > + ck_assert(handle->desc == &config_parts[0]); > + ck_assert(handle->data == &envdata[0]); > + free(handle); > +} > +END_TEST > + > +START_TEST(ebgenv_api_internal_bgenv_write) > +{ > + bool res; > + BGENV *dummy_env; > + > + dummy_env = calloc(1, sizeof(BGENV)); > + if (!dummy_env) > + goto bgew_error; > + > + RESET_FAKE(write_env); > + write_env_fake.custom_fake = write_env_custom_fake; > + > + /* Test if writing with a NULL-handle fails > + */ > + res = bgenv_write(NULL); > + ck_assert(write_env_fake.call_count == 0); > + ck_assert(res == false); > + > + /* Test if writing with a handle describing no partition > + * and no environment data fails > + */ > + res = bgenv_write(dummy_env); > + ck_assert(write_env_fake.call_count == 0); > + ck_assert(res == false); > + > + /* Test if writing with a handle describing both partition > + * and envrionment data succeeds > + */ > + dummy_env->desc = calloc(1, sizeof(CONFIG_PART)); > + if (!dummy_env->desc) > + goto bgew_error; > + > + dummy_env->data = calloc(1, sizeof(BG_ENVDATA)); > + if (!dummy_env->data) > + goto bgew_error; > + > + res = bgenv_write(dummy_env); > + ck_assert(write_env_fake.call_count == 1); > + ck_assert(res == true); > + > + return; > + > +bgew_error: > + free(dummy_env->data); > + free(dummy_env->desc); > + free(dummy_env); > + exit(errno); > +} > +END_TEST > + > +START_TEST(ebgenv_api_internal_bgenv_read) > +{ > + BGENV env; > + BG_ENVDATA data; > + > + env.data = &data; > + > + /* Test if bgenv_read returns a pointer to the environment > data > + */ > + BG_ENVDATA *res = bgenv_read(&env); > + ck_assert(res == env.data); > +} > +END_TEST > + > +START_TEST(ebgenv_api_internal_bgenv_create_new) > +{ > + BGENV *handle; > + int max = ENV_NUM_CONFIG_PARTS; > + > + for (int i = 0; i < max; i++) > + { > + envdata[i].revision = max - i; > + } > + > + /* Test if bgenv_create_new updates the oldest environment > with default > + * values and sets its revision to revision(latest)+1 > + */ > + handle = bgenv_create_new(); > + > + ck_assert(handle != NULL); > + ck_assert(handle->data == &envdata[max-1]); > + ck_assert(envdata[max-1].revision == max+1); > + ck_assert(envdata[max-1].watchdog_timeout_sec == 30); > + > + free(handle); > +} > +END_TEST > + > +START_TEST(ebgenv_api_internal_bgenv_get) > +{ > + BGENV *handle = bgenv_open_latest(); > + ck_assert(handle != NULL); > + > + wchar_t buffer[ENV_STRING_LENGTH]; > + char *test_strings[] = { > + "kernelfile_test123", > + "kernelparams_test123", > + }; > + void *dests[] = { > + &handle->data->kernelfile, > + &handle->data->kernelparams, > + }; > + > + for (int i = 0; i < sizeof(test_strings)/sizeof(void*); i++) > + { > + memcpy(dests[i], str8to16(buffer, test_strings[i]), > + strlen(test_strings[i]) * 2 + 2); > + } > + handle->data->watchdog_timeout_sec = 44; > + handle->data->revision = 10000; > + handle->data->ustate = USTATE_INSTALLED; > + > + char *type = NULL, *data = NULL; > + char buffera[22]; > + int res; > + > + /* Test if bgenv_get fails if maxlen is set to 0 > + */ > + res = bgenv_get(handle, "kernelfile", type, data, 0); > + ck_assert_int_eq(res, -EINVAL); > + > + /* Test if bgenv_get fails if key is NULL > + */ > + res = bgenv_get(handle, NULL, type, data, 1000); > + ck_assert_int_eq(res, -EINVAL); > + > + /* Test if bgenv_get fails if no environment is provided > + */ > + res = bgenv_get(NULL, "kernelfile", type, NULL, 1000); > + ck_assert_int_eq(res, -EPERM); > + > + /* Test if bgenv_get returns the correct size of the needed > + * buffer if provided with a NULL buffer > + */ > + res = bgenv_get(handle, "kernelfile", type, NULL, 1000); > + ck_assert_int_eq(res, strlen(test_strings[0]) + 1); > + > + /* Test if bgenv_get returns the correct value > + */ > + res = bgenv_get(handle, "kernelfile", type, buffera, res); > + ck_assert_int_eq(strcmp(buffera, test_strings[0]), 0); > + > + res = bgenv_get(handle, "kernelparams", type, NULL, 1000); > + res = bgenv_get(handle, "kernelparams", type, buffera, res); > + ck_assert_int_eq(strcmp(buffera, test_strings[1]), 0); > + > + free(handle); > +} > +END_TEST > + > +START_TEST(ebgenv_api_internal_bgenv_set) > +{ > + int res; > + > + BGENV *handle = bgenv_open_latest(); > + ck_assert(handle != NULL); > + ck_assert(handle->data != NULL); > + > + /* Test if bgenv_set returns -EINVAL if the handle is > invalid > + */ > + res = bgenv_set(NULL, "kernelfile", NULL, NULL, 0); > + ck_assert_int_eq(res, -EINVAL); > + > + /* Test if bgenv_set returns -EINVAL if the key is invalid > + */ > + res = bgenv_set(handle, "AOFIJAOEGIHA", NULL, NULL, 0); > + ck_assert_int_eq(res, -EINVAL); > + > + /* Test if bgenv_set works correctly for valid parameters > + */ > + res = bgenv_set(handle, "kernelfile", NULL, "vmlinuz", 8); > + ck_assert_int_eq(res, 0); > + > + char buffer[8]; > + char *kfile = str16to8(buffer, handle->data->kernelfile); > + > + ck_assert(strcmp(kfile, "vmlinuz") == 0); > + > + res = bgenv_set(handle, "watchdog_timeout_sec", NULL, "-0", > 2); > + ck_assert_int_eq(res, 0); > + ck_assert_int_eq(handle->data->watchdog_timeout_sec, 0); > + > + res = bgenv_set(handle, "watchdog_timeout_sec", NULL, "311", > 4); > + ck_assert_int_eq(res, 0); > + ck_assert_int_eq(handle->data->watchdog_timeout_sec, 311); > + > + res = bgenv_set(handle, "kernelparams", NULL, "root=", 6); > + ck_assert_int_eq(res, 0); > + > + char *kparm = str16to8(buffer, handle->data->kernelparams); > + > + ck_assert(strcmp(kparm, "root=") == 0); > + > + res = bgenv_set(handle, "ustate", NULL, "2", 2); > + ck_assert_int_eq(res, 0); > + > + ck_assert_int_eq(handle->data->ustate, 2); > + > + res = bgenv_set(handle, "revision", NULL, "0", 2); > + ck_assert_int_eq(res, 0); > + ck_assert_int_eq(handle->data->revision, 0); > + > + res = bgenv_set(handle, "revision", NULL, "10301", 6); > + ck_assert_int_eq(res, 0); > + ck_assert_int_eq(handle->data->revision, 10301); > + > + free(handle); > +} > +END_TEST > + > +START_TEST(ebgenv_api_internal_uservars) > +{ > + > + > +} > +END_TEST > + > +Suite *ebg_test_suite(void) > +{ > + Suite *s; > + TCase *tc_core; > + > + s = suite_create("ebgenv_api"); > + > + TFun tfuncs[] = { > + ebgenv_api_internal_strXtoY, > + ebgenv_api_internal_bgenv_str2enum, > + ebgenv_api_internal_bgenv_open_by_index, > + ebgenv_api_internal_bgenv_open_oldest, > + ebgenv_api_internal_bgenv_open_latest, > + ebgenv_api_internal_bgenv_write, > + ebgenv_api_internal_bgenv_read, > + ebgenv_api_internal_bgenv_create_new, > + ebgenv_api_internal_bgenv_get, > + ebgenv_api_internal_bgenv_set, > + ebgenv_api_internal_uservars > + }; > + > + tc_core = tcase_create("Core"); > + > + for (int i = 0; i < sizeof(tfuncs)/sizeof(void *); i++) { > + tcase_add_test(tc_core, tfuncs[i]); > + } > + > + suite_add_tcase(s, tc_core); > + > + return s; > +} > diff --git a/tools/tests/test_main.c b/tools/tests/test_main.c > new file mode 100644 > index 0000000..a25e092 > --- /dev/null > +++ b/tools/tests/test_main.c > @@ -0,0 +1,34 @@ > +/* > + * EFI Boot Guard > + * > + * Copyright (c) Siemens AG, 2017 > + * > + * Authors: > + * Andreas Reichel <[email protected]> > + * > + * This work is licensed under the terms of the GNU GPL, version > 2. See > + * the COPYING file in the top-level directory. > + */ > + > +#include <stdlib.h> > +#include <check.h> > +#include <fff.h> > + > +extern Suite *ebg_test_suite(void); > + > +int main(void) > +{ > + int number_failed; > + > + Suite *s; > + SRunner *sr; > + > + s = ebg_test_suite(); > + sr = srunner_create(s); > + > + srunner_run_all(sr, CK_NORMAL); > + number_failed = srunner_ntests_failed(sr); > + srunner_free(sr); > + > + return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE; > +} > diff --git a/tools/tests/test_probe_config_file.c > b/tools/tests/test_probe_config_file.c > new file mode 100644 > index 0000000..edc8f6a > --- /dev/null > +++ b/tools/tests/test_probe_config_file.c > @@ -0,0 +1,202 @@ > +/* > + * EFI Boot Guard > + * > + * Copyright (c) Siemens AG, 2017 > + * > + * Authors: > + * Andreas Reichel <[email protected]> > + * > + * This work is licensed under the terms of the GNU GPL, version > 2. See > + * the COPYING file in the top-level directory. > + */ > + > +#ifndef ENV_NUM_CONFIG_PARTITIONS > +# define ENV_NUM_CONFIG_PARTITIONS 2 > +#endif > + > +#include <stdlib.h> > +#include <errno.h> > +#include <sys/queue.h> > +#include <check.h> > +#include <fff.h> > +#include <env_api.h> > +#include <env_config_file.h> > +#include <env_config_partitions.h> > +#include <ebgpart.h> > +#include <stdio.h> > +#include <env_disk_utils.h> > +#include <fake_devices.h> > + > +DEFINE_FFF_GLOBALS; > + > +Suite *ebg_test_suite(void); > + > +char *get_mountpoint_custom_fake(char *devpath); > +void delete_temp_files(void); > + > +bool __wrap_probe_config_file(CONFIG_PART *); > +bool __real_probe_config_file(CONFIG_PART *); > +int probe_config_file_call_count; > + > +char *fake_mountpoint = "/tmp/tmp.XXXXXX"; > + > +struct stailhead *headp; > +struct fake_env_file_path { > + char *path; > + STAILQ_ENTRY(fake_env_file_path) fake_env_file_paths; > +}; > +STAILQ_HEAD(stailhead, fake_env_file_path) head = > STAILQ_HEAD_INITIALIZER(head); > + > +char *get_mountpoint_custom_fake(char *devpath) > +{ > + char *buff = NULL; > + char *tmpdir = NULL; > + char *tmpfile = NULL; > + > + if (asprintf(&tmpdir, "%s", fake_mountpoint) == -1) > + { > + tmpdir = NULL; > + goto fake_mountpoint_error; > + } > + > + tmpdir = mkdtemp(tmpdir); > + if (!tmpdir) > + goto fake_mountpoint_error; > + > + if (asprintf(&buff, "%s", tmpdir) == -1) { > + buff = NULL; > + goto fake_mountpoint_error; > + } > + > + if (asprintf(&tmpfile, "%s/%s", tmpdir, FAT_ENV_FILENAME) == > -1) { > + tmpfile = NULL; > + goto fake_mountpoint_error; > + } > + > + /* create a fake environment file > + */ > + FILE *temp_env_file = fopen(tmpfile, "w"); > + > + BG_ENVDATA env_data; > + memset(&env_data, 0, sizeof(BG_ENVDATA)); > + fwrite(&env_data, sizeof(BG_ENVDATA), 1, temp_env_file); > + fclose(temp_env_file); > + > + free(tmpfile); > + free(tmpdir); > + > + struct fake_env_file_path *fefp; > + fefp = malloc(sizeof(struct fake_env_file_path)); > + > + /* If possibly store created temporary files and paths in a > list to > + * tidy up later. If not, the test should not fail because > of this. > + */ > + char *buffer_copy; > + asprintf(&buffer_copy, "%s", buff); > + > + if (fefp && buffer_copy) { > + fefp->path = buffer_copy; > + STAILQ_INSERT_TAIL(&head, fefp, > fake_env_file_paths); > + } > + return buff; > + > +fake_mountpoint_error: > + free(buff); > + free(tmpdir); > + return NULL; > +} > + > +bool __wrap_probe_config_file(CONFIG_PART *cp) > +{ > + bool ret; > + probe_config_file_call_count++; > + > + FILE *test_file = fopen("./test.txt", "a+"); > + if (!test_file) > + return true; > + > + fprintf(test_file, "probe_config_file(%s)\n", cp->devpath); > + fclose(test_file); > + > + if (asprintf(&cp->mountpoint, "tmpdir") == -1) > + { > + cp->not_mounted = true; > + cp->mountpoint = NULL; > + return false; > + } > + cp->not_mounted = false; > + ret = __real_probe_config_file(cp); > + > + free(cp->mountpoint); > + return ret; > +} > + > +void delete_temp_files(void) > +{ > + char *buffer; > + while (!STAILQ_EMPTY(&head)) { > + struct fake_env_file_path *fefp = > STAILQ_FIRST(&head); > + > + if (asprintf(&buffer, "%s/BGENV.DAT", fefp->path) != > -1) { > + remove(buffer); > + free(buffer); > + } > + rmdir(fefp->path); > + free(fefp->path); > + > + STAILQ_REMOVE_HEAD(&head, fake_env_file_paths); > + free(fefp); > + } > +} > + > +FAKE_VOID_FUNC(ped_device_probe_all); > +FAKE_VALUE_FUNC(PedDevice *, ped_device_get_next, const PedDevice > *); > +FAKE_VALUE_FUNC(char *, get_mountpoint, char *); > + > +START_TEST(env_api_fat_test_probe_config_file) > +{ > + bool result; > + > + RESET_FAKE(ped_device_probe_all); > + RESET_FAKE(ped_device_get_next); > + RESET_FAKE(get_mountpoint); > + > + allocate_fake_devices(1); > + > + for (int i = 0; i < ENV_NUM_CONFIG_PARTS; i++) { > + add_fake_partition(0); > + } > + > + ped_device_get_next_fake.custom_fake = > ped_device_get_next_custom_fake; > + get_mountpoint_fake.custom_fake = > get_mountpoint_custom_fake; > + probe_config_file_call_count = 0; > + > + STAILQ_INIT(&head); > + > + result = bgenv_init(); > + > + delete_temp_files(); > + > + free_fake_devices(); > + > + ck_assert_int_eq(ped_device_probe_all_fake.call_count, 1); > + ck_assert_int_eq(ped_device_get_next_fake.call_count, 2); > + ck_assert_int_eq(probe_config_file_call_count, > ENV_NUM_CONFIG_PARTS); > + ck_assert_int_eq(get_mountpoint_fake.call_count, > ENV_NUM_CONFIG_PARTS); > + ck_assert(result == true); > +} > +END_TEST > + > +Suite *ebg_test_suite(void) > +{ > + Suite *s; > + TCase *tc_core; > + > + s = suite_create("env_api_fat"); > + > + tc_core = tcase_create("Core"); > + tcase_add_test(tc_core, env_api_fat_test_probe_config_file); > + suite_add_tcase(s, tc_core); > + > + return s; > +} > diff --git a/tools/tests/test_probe_config_partitions.c > b/tools/tests/test_probe_config_partitions.c > new file mode 100644 > index 0000000..8dacf14 > --- /dev/null > +++ b/tools/tests/test_probe_config_partitions.c > @@ -0,0 +1,99 @@ > +/* > + * EFI Boot Guard > + * > + * Copyright (c) Siemens AG, 2017 > + * > + * Authors: > + * Andreas Reichel <[email protected]> > + * > + * This work is licensed under the terms of the GNU GPL, version > 2. See > + * the COPYING file in the top-level directory. > + */ > + > +#ifndef ENV_NUM_CONFIG_PARTITIONS > +# define ENV_NUM_CONFIG_PARTITIONS 2 > +#endif > + > +#include <stdlib.h> > +#include <check.h> > +#include <fff.h> > +#include <env_api.h> > +#include <env_config_file.h> > +#include <env_config_partitions.h> > +#include <fake_devices.h> > + > +DEFINE_FFF_GLOBALS; > + > +Suite *ebg_test_suite(void); > + > +bool read_env_custom_fake(CONFIG_PART *cp, BG_ENVDATA *env); > +bool read_env(CONFIG_PART *part, BG_ENVDATA *env); > + > +bool read_env_custom_fake(CONFIG_PART *cp, BG_ENVDATA *env) > +{ > + if (!env) { > + return false; > + } > + memset(env, 0, sizeof(BG_ENVDATA)); > + return true; > +} > + > +FAKE_VALUE_FUNC(bool, read_env, CONFIG_PART *, BG_ENVDATA *); > +FAKE_VOID_FUNC(ped_device_probe_all); > +FAKE_VALUE_FUNC(PedDevice *, ped_device_get_next, const PedDevice > *); > + > +START_TEST(env_api_fat_test_probe_config_partitions) > +{ > + bool result; > + /* In this unit test, contents of environment data are > + * faked to be all zero > + */ > + > + /* Test if bgenv_init fails if no block devices are found > + */ > + RESET_FAKE(ped_device_probe_all); > + RESET_FAKE(ped_device_get_next); > + > + ped_device_get_next_fake.return_val = NULL; > + > + result = bgenv_init(); > + > + ck_assert(ped_device_probe_all_fake.call_count == 1); > + ck_assert(result == false); > + > + /* Test if bgenv_init fails if a device with two partitions > is found > + * but now config file is there > + */ > + RESET_FAKE(ped_device_probe_all); > + RESET_FAKE(ped_device_get_next); > + > + allocate_fake_devices(1); > + > + for (int i = 0; i < ENV_NUM_CONFIG_PARTS; i++) { > + add_fake_partition(0); > + } > + > + ped_device_get_next_fake.custom_fake = > ped_device_get_next_custom_fake; > + result = bgenv_init(); > + > + free_fake_devices(); > + > + ck_assert(ped_device_probe_all_fake.call_count == 1); > + ck_assert(ped_device_get_next_fake.call_count == 2); > + ck_assert(result == false); > +} > +END_TEST > + > +Suite *ebg_test_suite(void) > +{ > + Suite *s; > + TCase *tc_core; > + > + s = suite_create("env_api_fat"); > + > + tc_core = tcase_create("Core"); > + tcase_add_test(tc_core, > env_api_fat_test_probe_config_partitions); > + suite_add_tcase(s, tc_core); > + > + return s; > +} > -- > 2.14.2 > -- DENX Software Engineering GmbH, Managing Director: Wolfgang Denk HRB 165235 Munich, Office: Kirchenstr.5, D-82194 Groebenzell, Germany Phone: (+49)-8142-66989-54 Fax: (+49)-8142-66989-80 Email: [email protected] PGP key: 6FF2 E59F 00C6 BC28 31D8 64C1 1173 CB19 9808 B153 Keyserver: hkp://pool.sks-keyservers.net -- You received this message because you are subscribed to the Google Groups "EFI Boot Guard" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. To view this discussion on the web visit https://groups.google.com/d/msgid/efibootguard-dev/1508858587.13007.78.camel%40denx.de. For more options, visit https://groups.google.com/d/optout.
signature.asc
Description: This is a digitally signed message part
