Anastasia Klimchuk has uploaded this change for review. ( https://review.coreboot.org/c/flashrom/+/51487 )
Change subject: Add unit test to run init/shutdown for enabled drivers ......................................................................
Add unit test to run init/shutdown for enabled drivers
I want to do this for all drivers in programmer table, this patch has 3 of them as a proof of concept. There is no hardware in unit test environment, all operations with hardware need to be mocked/redefined.
Calls to __wrap functions are now logged to stdout, makes it easier to understand what’s happening and I find it really helps when writing tests (and can be useful when debugging tests).
Extract from meson-logs/testlog.txt for new test:
[ RUN ] linux_spi_init_and_shutdown_test_success Testing programmer_init for programmer=25 ... __wrap_open64 is called __wrap_ioctl is called __wrap_ioctl is called __wrap_ioctl is called __wrap_fopen64 is called ... programmer_init for programmer=25 successful Testing programmer_shutdown for programmer=25 ... ... programmer_shutdown for programmer=25 successful [ OK ] linux_spi_init_and_shutdown_test_success
BUG=b:181803212 TEST=builds and ninja test
Change-Id: I3af612defe1af3850dfc1626a208d873e3a3eddc Signed-off-by: Anastasia Klimchuk aklm@chromium.org --- M mec1308.c A tests/init_shutdown.c M tests/meson.build M tests/tests.c M tests/tests.h 5 files changed, 139 insertions(+), 2 deletions(-)
git pull ssh://review.coreboot.org:29418/flashrom refs/changes/87/51487/1
diff --git a/mec1308.c b/mec1308.c index c4b34f5..0d81a60 100644 --- a/mec1308.c +++ b/mec1308.c @@ -100,6 +100,20 @@ #define MEC1308_CMD_PASSTHRU_SEND 0xf2 /* send byte from data0 */ #define MEC1308_CMD_PASSTHRU_READ 0xf3 /* read byte, place in data0 */
+#ifdef UNIT_TEST_ENV +/* No hardware in unit test environment. + * So outb and inb need to be redefined, to pretend they work. */ +static uint8_t outb_val = 0; +#undef OUTB +#undef INB +#define OUTB(x, y) outb_val = x; +#define INB(x) (((x) == MEC1308_SIO_PORT1 || (x) == MEC1308_SIO_PORT2) \ + ? MEC1308_DEVICE_ID_REG \ + : ((outb_val == MEC1308_MBX_DATA_START) \ + ? MEC1308_CMD_PASSTHRU_SUCCESS \ + : 0)) +#endif /* UNIT_TEST_ENV */ + typedef struct { unsigned int in_sio_cfgmode; diff --git a/tests/init_shutdown.c b/tests/init_shutdown.c new file mode 100644 index 0000000..e057f64 --- /dev/null +++ b/tests/init_shutdown.c @@ -0,0 +1,48 @@ +/* + * This file is part of the flashrom project. + * + * Copyright 2021 Google LLC + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#include <include/test.h> +#include <string.h> + +#include "programmer.h" + +static void run_lifecycle(void **state, enum programmer prog, const char *param) +{ + (void) state; /* unused */ + + printf("Testing programmer_init for programmer=%u ...\n", prog); + assert_int_equal(0, programmer_init(prog, strdup(param))); + printf("... programmer_init for programmer=%u successful\n", prog); + + printf("Testing programmer_shutdown for programmer=%u ...\n", prog); + assert_int_equal(0, programmer_shutdown()); + printf("... programmer_shutdown for programmer=%u successful\n", prog); +} + +void dummy_init_and_shutdown_test_success(void **state) +{ + run_lifecycle(state, PROGRAMMER_DUMMY, ""); +} + +void mec1308_init_and_shutdown_test_success(void **state) +{ + will_return_always(__wrap_sio_read, 0x4d); /* MEC1308_DEVICE_ID_VAL */ + run_lifecycle(state, PROGRAMMER_MEC1308, ""); +} + +void linux_spi_init_and_shutdown_test_success(void **state) +{ + run_lifecycle(state, PROGRAMMER_LINUX_SPI, "dev=/dev/null"); +} diff --git a/tests/meson.build b/tests/meson.build index f0cb76d..2b21602 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -18,12 +18,21 @@ 'helpers.c', 'flashrom.c', 'spi25.c', + 'init_shutdown.c', ]
mocks = [ '-Wl,--wrap=physunmap', '-Wl,--wrap=physmap', '-Wl,--wrap=spi_send_command', + '-Wl,--wrap=sio_write', + '-Wl,--wrap=sio_read', + '-Wl,--wrap=open', + '-Wl,--wrap=open64', + '-Wl,--wrap=ioctl', + '-Wl,--wrap=fopen', + '-Wl,--wrap=fopen64', + '-Wl,--wrap=rget_io_perms', '-Wl,--gc-sections', ]
@@ -35,6 +44,7 @@ '-ffunction-sections', '-fdata-sections', # '-DSTANDALONE', + '-DUNIT_TEST_ENV', '-DCONFIG_DEFAULT_PROGRAMMER=PROGRAMMER_DUMMY', '-DCONFIG_DEFAULT_PROGRAMMER_ARGS=""', ], diff --git a/tests/tests.c b/tests/tests.c index 3124607..86e5959 100644 --- a/tests/tests.c +++ b/tests/tests.c @@ -17,22 +17,75 @@ #include "tests.h"
#include <stdio.h> +#include <stdint.h>
/* redefinitions/wrapping */ +#define LOG_ME printf("%s is called\n", __func__) + void __wrap_physunmap(void *virt_addr, size_t len) { - fprintf(stderr, "%s\n", __func__); + LOG_ME; } + void *__wrap_physmap(const char *descr, uintptr_t phys_addr, size_t len) { - fprintf(stderr, "%s\n", __func__); + LOG_ME; return NULL; }
+void __wrap_sio_write(uint16_t port, uint8_t reg, uint8_t data) +{ + LOG_ME; +} + +uint8_t __wrap_sio_read(uint16_t port, uint8_t reg) +{ + LOG_ME; + return (uint8_t)mock(); +} + +int __wrap_open(const char *pathname, int flags) +{ + LOG_ME; + return 2021; +} + +int __wrap_open64(const char *pathname, int flags) +{ + LOG_ME; + return 2021; +} + +int __wrap_ioctl(int fd, unsigned long int request, ...) +{ + LOG_ME; + return 2021; +} + +FILE *__wrap_fopen(const char *pathname, const char *mode) +{ + LOG_ME; + return NULL; +} + +FILE *__wrap_fopen64(const char *pathname, const char *mode) +{ + LOG_ME; + return NULL; +} + +int __wrap_rget_io_perms(void) +{ + LOG_ME; + return 0; +} + int main(void) { int ret = 0;
+ cmocka_set_message_output(CM_OUTPUT_STDOUT); + const struct CMUnitTest helpers_tests[] = { cmocka_unit_test(address_to_bits_test_success), cmocka_unit_test(bitcount_test_success), @@ -63,5 +116,12 @@ }; ret |= cmocka_run_group_tests_name("spi25.c tests", spi25_tests, NULL, NULL);
+ const struct CMUnitTest init_shutdown_tests[] = { + cmocka_unit_test(dummy_init_and_shutdown_test_success), + cmocka_unit_test(linux_spi_init_and_shutdown_test_success), + cmocka_unit_test(mec1308_init_and_shutdown_test_success), + }; + ret |= cmocka_run_group_tests_name("init_shutdown.c tests", init_shutdown_tests, NULL, NULL); + return ret; } diff --git a/tests/tests.h b/tests/tests.h index cb905fd..97cae7c 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -40,4 +40,9 @@ void probe_spi_at25f_test_success(void **state); void probe_spi_st95_test_success(void **state); /* spi95.c */
+/* init_shutdown.c */ +void dummy_init_and_shutdown_test_success(void **state); +void linux_spi_init_and_shutdown_test_success(void **state); +void mec1308_init_and_shutdown_test_success(void **state); + #endif /* TESTS_H */