Anastasia Klimchuk has uploaded this change for review. ( https://review.coreboot.org/c/flashrom/+/56413 )
Change subject: tests: Mock file i/o for linux_mtd and linux_spi tests ......................................................................
tests: Mock file i/o for linux_mtd and linux_spi tests
This patch adds an init-shutdown test for linux_mtd. Since linux_mtd is using file i/o operations, those are added to the framework and mocked.
Another driver linux_spi which is also using file i/o, got an upgrade in this patch, and it is now reading pagesize from sysfs (using mocked file i/o).
A good side-effect is that linux_mtd is the first test for opaque masters, which is great to have in preparation for a change like CB:56103 but for opaque masters.
BUG=b:181803212 TEST=builds and ninja test
Change-Id: I73f0d6ff2ad5074add7a721ed3416230d3647e3f Signed-off-by: Anastasia Klimchuk aklm@chromium.org --- M tests/init_shutdown.c M tests/io_mock.h M tests/meson.build M tests/tests.c M tests/tests.h 5 files changed, 169 insertions(+), 4 deletions(-)
git pull ssh://review.coreboot.org:29418/flashrom refs/changes/13/56413/1
diff --git a/tests/init_shutdown.c b/tests/init_shutdown.c index 8469902..29ca06d 100644 --- a/tests/init_shutdown.c +++ b/tests/init_shutdown.c @@ -182,16 +182,103 @@ #endif }
+struct linux_mtd_io_state { + const char *fopen_path; +}; + +FILE *linux_mtd_fopen(void *state, const char *pathname, const char *mode) +{ + struct linux_mtd_io_state *io_state = state; + + io_state->fopen_path = pathname; + + return (void *)2021; +} + +size_t linux_mtd_fread(void *state, void *buf, size_t size, size_t len, FILE *fp) +{ + struct linux_mtd_io_state *io_state = state; + int num_bytes = 0; + + if (!io_state->fopen_path) + return 0; + + if (!strcmp(io_state->fopen_path, "/sys/class/mtd/mtd0//type")) { + num_bytes = 3; + memcpy(buf, "nor", num_bytes); + } + + if (!strcmp(io_state->fopen_path, "/sys/class/mtd/mtd0//name")) { + num_bytes = 6; + memcpy(buf, "Device", num_bytes); + } + + if (!strcmp(io_state->fopen_path, "/sys/class/mtd/mtd0//flags")) { + num_bytes = 0; + memcpy(buf, "", num_bytes); + } + + if (!strcmp(io_state->fopen_path, "/sys/class/mtd/mtd0//size")) { + num_bytes = 4; + memcpy(buf, "1024", num_bytes); + } + + if (!strcmp(io_state->fopen_path, "/sys/class/mtd/mtd0//erasesize")) { + num_bytes = 3; + memcpy(buf, "512", num_bytes); + } + + if (!strcmp(io_state->fopen_path, "/sys/class/mtd/mtd0//numeraseregions")) { + num_bytes = 1; + memcpy(buf, "0", num_bytes); + } + + return num_bytes; +} + +void linux_mtd_init_and_shutdown_test_success(void **state) +{ +#if CONFIG_LINUX_MTD == 1 + struct linux_mtd_io_state linux_mtd_io_state = { NULL }; + const struct io_mock linux_mtd_io = { + .state = &linux_mtd_io_state, + .fopen = linux_mtd_fopen, + .fread = linux_mtd_fread, + }; + + io_mock_register(&linux_mtd_io); + + run_lifecycle(state, &programmer_linux_mtd, ""); + + io_mock_register(NULL); +#else + skip(); +#endif +} + +char *linux_spi_fgets(void *state, char *buf, int len, FILE *fp) +{ + /* Provide pagesize into buf. */ + memcpy(buf, "1048576", len); + return buf; +} + void linux_spi_init_and_shutdown_test_success(void **state) { /* * Current implementation tests a particular path of the init procedure. - * There are two ways for it to succeed: reading the buffer size from sysfs - * and the fallback to getpagesize(). This test does the latter (fallback to - * getpagesize). + * Specifically, it is reading the buffer size from sysfs. */ #if CONFIG_LINUX_SPI == 1 + const struct io_mock linux_spi_io = { + .fgets = linux_spi_fgets, + }; + + io_mock_register(&linux_spi_io); + run_lifecycle(state, &programmer_linux_spi, "dev=/dev/null"); + + io_mock_register(NULL); #else skip(); #endif diff --git a/tests/io_mock.h b/tests/io_mock.h index 72d89c5..4b54516 100644 --- a/tests/io_mock.h +++ b/tests/io_mock.h @@ -37,6 +37,8 @@ struct libusb_context; typedef struct libusb_context libusb_context;
+#include <stdio.h> + struct io_mock { void *state;
@@ -60,6 +62,10 @@ unsigned char *data, uint16_t wLength, unsigned int timeout); + /* File I/O */ + FILE* (*fopen)(void *state, const char *pathname, const char *mode); + char* (*fgets)(void *state, char *buf, int len, FILE *fp); + size_t (*fread)(void *state, void *buf, size_t size, size_t len, FILE *fp); };
void io_mock_register(const struct io_mock *io); diff --git a/tests/meson.build b/tests/meson.build index a18bc45..7206296 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -32,6 +32,15 @@ '-Wl,--wrap=ioctl', '-Wl,--wrap=fopen', '-Wl,--wrap=fopen64', + '-Wl,--wrap=stat', + '-Wl,--wrap=stat64', + '-Wl,--wrap=fread', + '-Wl,--wrap=fgets', + '-Wl,--wrap=fclose', + '-Wl,--wrap=feof', + '-Wl,--wrap=ferror', + '-Wl,--wrap=clearerr', + '-Wl,--wrap=setvbuf', '-Wl,--wrap=rget_io_perms', '-Wl,--wrap=test_outb', '-Wl,--wrap=test_inb', diff --git a/tests/tests.c b/tests/tests.c index cde696f..93c3490 100644 --- a/tests/tests.c +++ b/tests/tests.c @@ -74,15 +74,76 @@ FILE *__wrap_fopen(const char *pathname, const char *mode) { LOG_ME; - return NULL; + if (current_io && current_io->fopen) + return current_io->fopen(current_io->state, pathname, mode); + return (void *)MOCK_HANDLE; }
FILE *__wrap_fopen64(const char *pathname, const char *mode) { LOG_ME; + if (current_io && current_io->fopen) + return current_io->fopen(current_io->state, pathname, mode); + return (void *)MOCK_HANDLE; +} + +int __wrap_stat(const char *path, void *buf) +{ + LOG_ME; + return 0; +} + +int __wrap_stat64(const char *path, void *buf) +{ + LOG_ME; + return 0; +} + +char *__wrap_fgets(char *buf, int len, FILE *fp) +{ + LOG_ME; + if (current_io && current_io->fgets) + return current_io->fgets(current_io->state, buf, len, fp); return NULL; }
+size_t __wrap_fread(void *ptr, size_t size, size_t len, FILE *fp) +{ + LOG_ME; + if (current_io && current_io->fread) + return current_io->fread(current_io->state, ptr, size, len, fp); + return 0; +} + +int __wrap_setvbuf(FILE *fp, char *buf, int type, size_t size) +{ + LOG_ME; + return 0; +} + +int __wrap_fclose(FILE *fp) +{ + LOG_ME; + return 0; +} + +int __wrap_feof(FILE *fp) +{ + /* LOG_ME; */ + return 0; +} + +int __wrap_ferror(FILE *fp) +{ + /* LOG_ME; */ + return 0; +} +void __wrap_clearerr(FILE *fp) +{ + /* LOG_ME; */ + return; +} + int __wrap_rget_io_perms(void) { LOG_ME; @@ -221,6 +282,7 @@ cmocka_unit_test(mec1308_init_and_shutdown_test_success), cmocka_unit_test(dediprog_init_and_shutdown_test_success), cmocka_unit_test(ene_lpc_init_and_shutdown_test_success), + cmocka_unit_test(linux_mtd_init_and_shutdown_test_success), cmocka_unit_test(linux_spi_init_and_shutdown_test_success), }; ret |= cmocka_run_group_tests_name("init_shutdown.c tests", init_shutdown_tests, NULL, NULL); diff --git a/tests/tests.h b/tests/tests.h index 2007695..95b6cc3 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -45,6 +45,7 @@ void mec1308_init_and_shutdown_test_success(void **state); void dediprog_init_and_shutdown_test_success(void **state); void ene_lpc_init_and_shutdown_test_success(void **state); +void linux_mtd_init_and_shutdown_test_success(void **state); void linux_spi_init_and_shutdown_test_success(void **state);
#endif /* TESTS_H */