Anastasia Klimchuk has submitted this change. ( https://review.coreboot.org/c/flashrom/+/74157 )
Change subject: tests: Emulate multithreading environment for unit tests ......................................................................
tests: Emulate multithreading environment for unit tests
The main purpose of this patch is to run unit tests on BSD family of OSes. The root cause is `fileno` syscall which is a macro that can be expanded to either a function call (for multi-threaded environment) or to inline code (for single-threaded environment). Said inline code accesses private field of file descriptor, and this construction is impossible to mock in unit tests. Multi- threaded environment has `fileno` as a function, which can be mocked in unit tests.
On other OSes the patch just creates a thread which is doing nothing. We avoid adding pre-processor conditionals since the cost is small.
Tested on FreeBSD 13.1-RELEASE-p6 GENERIC amd64 NetBSD 9.2 (GENERIC) amd64 OpenBSD 7.2 GENERIC#7 amd64 DragonFly v6.4.0-RELEASE x86_64 Ubuntu 22.04.1 x86_64
Change-Id: I3d65c125183e60037ad07b9d54b8fffdece5a4e8 Signed-off-by: Anastasia Klimchuk aklm@chromium.org Reviewed-on: https://review.coreboot.org/c/flashrom/+/74157 Tested-by: build bot (Jenkins) no-reply@coreboot.org Reviewed-by: Peter Marheine pmarheine@chromium.org Reviewed-by: Thomas Heijligen src@posteo.de --- M tests/meson.build M tests/tests.c 2 files changed, 54 insertions(+), 12 deletions(-)
Approvals: build bot (Jenkins): Verified Thomas Heijligen: Looks good to me, approved Peter Marheine: Looks good to me, approved
diff --git a/tests/meson.build b/tests/meson.build index df866d7..94f60e2 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -113,6 +113,8 @@ '-Wl,--gc-sections', ]
+threads_dep = dependency('threads') + flashrom_tests = executable('flashrom_unit_tests', test_srcs, c_args : [ @@ -123,7 +125,7 @@ ], export_dynamic : true, link_args : mocks + link_args, - dependencies : [cmocka_dep, flashrom_test_dep], + dependencies : [cmocka_dep, flashrom_test_dep, threads_dep], ) test('cmocka test flashrom', flashrom_tests)
diff --git a/tests/tests.c b/tests/tests.c index 159b79f..8b4ad03 100644 --- a/tests/tests.c +++ b/tests/tests.c @@ -22,6 +22,7 @@ #include <stdio.h> #include <string.h> #include <stdint.h> +#include <pthread.h>
void *not_null(void) { @@ -385,26 +386,32 @@ return 0; }
+static void *doing_nothing(void *vargp) { + return NULL; +} + int main(int argc, char *argv[]) { int ret = 0;
-#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) - /* - * Pretending to be a multithreaded environment so that `fileno` - * is called as a function (and not as a macro). - * fileno macro in FreeBSD is expanded into inline access of - * private field of file descriptor, which is impossible to mock. - * Calling fileno as a function allows the test to mock it. - */ - __isthreaded = 1; -#endif - if (argc > 1) cmocka_set_test_filter(argv[1]);
cmocka_set_message_output(CM_OUTPUT_STDOUT);
+ /* + * Creating new thread which is doing nothing, to trigger __isthreaded being 1. + * This is a workaround for BSD family. In multi-threaded environment fileno + * macro is expanded into a function which is possible to mock in unit tests. + * Without this workaround, on a single-thread environment, fileno macro is + * expanded into an inline access of a private field of a file descriptor, + * which is impossible to mock. + * + * In other OSes this is just creating a thread which is doing nothing. + */ + pthread_t thread_id; + pthread_create(&thread_id, NULL, doing_nothing, NULL); + const struct CMUnitTest helpers_tests[] = { cmocka_unit_test(address_to_bits_test_success), cmocka_unit_test(bitcount_test_success),