Anastasia Klimchuk has uploaded this change for review. ( https://review.coreboot.org/c/flashrom/+/57326 )
Change subject: tests: Add tests to read from chip ......................................................................
tests: Add tests to read from chip
Two tests cover the code which performs do_read operation.
First one works with fake chip and dummy programmer. Fake chip has all operations defined, and a buffer to emulate chip memory.
Second one uses the chip which is closer to the real one, because read/write/unlock/erase operations are real. The tests takes the advantage of dummyflasher's capability of emulating a W25Q128.V chip.
BUG=b:181803212 TEST=builds and ninja test
Change-Id: Ia57781ebc670c7bd6197e56fe8a20651a425c756 Signed-off-by: Anastasia Klimchuk aklm@chromium.org --- M tests/chip.c M tests/io_mock.h M tests/meson.build M tests/tests.c M tests/tests.h 5 files changed, 197 insertions(+), 54 deletions(-)
git pull ssh://review.coreboot.org:29418/flashrom refs/changes/26/57326/1
diff --git a/tests/chip.c b/tests/chip.c index 0cb05ad..8b254e4 100644 --- a/tests/chip.c +++ b/tests/chip.c @@ -86,6 +86,50 @@ return 0; }
+static void reset_global_chip_state() +{ + g_chip_state.unlock_calls = 0; +} + +static void setup_for_chip(struct flashrom_flashctx *flash, struct flashrom_layout **layout, + struct flashchip *chip, const char *programmer_param) +{ + flash->chip = chip; + + reset_global_chip_state(); + + printf("Creating layout with one included region... "); + assert_int_equal(0, flashrom_layout_new(layout)); + /* One region which covers total size of chip. */ + assert_int_equal(0, flashrom_layout_add_region(*layout, 0, chip->total_size * 1024 - 1, "region")); + assert_int_equal(0, flashrom_layout_include_region(*layout, "region")); + + flashrom_layout_set(flash, *layout); + printf("done\n"); + + /* + * We need some programmer (any), and dummy is a very good one, + * because it doesn't need any mocking. So no extra complexity + * from a programmer side, and test can focus on working with the chip. + */ + printf("Dummyflasher initialising with param="%s"... ", programmer_param); + assert_int_equal(0, programmer_init(&programmer_dummy, programmer_param)); + /* Assignment below normally happens while probing, but this test is not probing. */ + flash->mst = ®istered_masters[0]; + printf("done\n"); +} + +static void teardown(struct flashrom_layout **layout) +{ + printf("Dummyflasher shutdown... "); + assert_int_equal(0, programmer_shutdown()); + printf("done\n"); + + printf("Releasing layout... "); + flashrom_layout_release(*layout); + printf("done\n"); +} + void erase_chip_test_success(void **state) { (void) state; /* unused */ @@ -108,43 +152,17 @@ .block_erase = block_erase_chip, }}, }; - struct flashrom_flashctx flash = { - .chip = &chip, - }; - + struct flashrom_flashctx flash = { 0 }; struct flashrom_layout *layout; + const char *param = ""; /* Default values for all params. */
- printf("Creating layout with one included region... "); - assert_int_equal(0, flashrom_layout_new(&layout)); - /* One region which covers total size of chip. */ - assert_int_equal(0, flashrom_layout_add_region(layout, 0, chip.total_size * 1024 - 1, "region")); - assert_int_equal(0, flashrom_layout_include_region(layout, "region")); - - flashrom_layout_set(&flash, layout); - printf("done\n"); - - /* - * We need some programmer (any), and dummy is a very good one, - * because it doesn't need any mocking. So no extra complexity - * from a programmer side, and test can focus on the code which - * erases the chip. - */ - const char *param = ""; /* default values for all params */ - printf("Dummyflasher initialising... "); - assert_int_equal(0, programmer_init(&programmer_dummy, param)); - printf("done\n"); + setup_for_chip(&flash, &layout, &chip, param);
printf("Erase chip operation started.\n"); assert_int_equal(0, do_erase(&flash)); printf("Erase chip operation done.\n");
- printf("Dummyflasher shutdown... "); - assert_int_equal(0, programmer_shutdown()); - printf("done\n"); - - printf("Releasing layout... "); - flashrom_layout_release(layout); - printf("done\n"); + teardown(&layout); }
void erase_chip_with_dummyflasher_test_success(void **state) @@ -184,43 +202,119 @@ } }, }; - struct flashrom_flashctx flash = { - .chip = &chip, - };
+ struct flashrom_flashctx flash = { 0 }; struct flashrom_layout *layout; - - printf("Creating layout with one included region... "); - assert_int_equal(0, flashrom_layout_new(&layout)); - /* One region which covers total size of chip. */ - assert_int_equal(0, flashrom_layout_add_region(layout, 0, chip.total_size * 1024 - 1, "region")); - assert_int_equal(0, flashrom_layout_include_region(layout, "region")); - - flashrom_layout_set(&flash, layout); - printf("done\n"); - /* * Dummyflasher is capable to emulate a chip, so we ask it to do this. * Nothing to mock, dummy is taking care of this already. */ char *param_dup = strdup("bus=spi,emulate=W25Q128FV"); - printf("Dummyflasher initialising to emulate W25Q128FV... "); - assert_int_equal(0, programmer_init(&programmer_dummy, param_dup)); - /* Assignment below normally happens while probing, but this test is not probing. */ - flash.mst = ®istered_masters[0]; - printf("done\n"); + + setup_for_chip(&flash, &layout, &chip, param_dup);
printf("Erase chip operation started.\n"); assert_int_equal(0, do_erase(&flash)); printf("Erase chip operation done.\n");
- printf("Dummyflasher shutdown... "); - assert_int_equal(0, programmer_shutdown()); - printf("done\n"); + teardown(&layout);
- printf("Releasing layout... "); - flashrom_layout_release(layout); - printf("done\n"); + free(param_dup); +} + +void read_chip_test_success(void **state) +{ + (void) state; /* unused */ + + struct flashchip chip = { + .vendor = "aklm", + /* + * Total size less than 16 to skip some steps + * in flashrom.c#prepare_flash_access. + */ + .total_size = 8, + .tested = TEST_OK_PREW, + .read = read_chip, + .write = write_chip, + .unlock = unlock_chip, + .block_erasers = + {{ + /* All blocks within total size of the chip. */ + .eraseblocks = { {2 * 1024, 4} }, + .block_erase = block_erase_chip, + }}, + }; + + struct flashrom_flashctx flash = { 0 }; + struct flashrom_layout *layout; + const char *param = ""; /* Default values for all params. */ + + setup_for_chip(&flash, &layout, &chip, param); + + const char *const filename = "read_chip.test"; + + printf("Read chip operation started.\n"); + assert_int_equal(0, do_read(&flash, filename)); + printf("Read chip operation done.\n"); + + teardown(&layout); +} + +void read_chip_with_dummyflasher_test_success(void **state) +{ + (void) state; /* unused */ + + struct flashchip chip = { + .vendor = "aklm&dummyflasher", + /* + * Setup the values for W25Q128.V because we ask dummyflasher + * to emulate this chip. All operations: read/write/unlock/erase + * are real, not mocks, and they are expected to be handled by + * dummyflasher. + */ + .total_size = 16 * 1024, + .tested = TEST_OK_PREW, + .read = spi_chip_read, + .write = spi_chip_write_256, + .unlock = spi_disable_blockprotect, + .block_erasers = + { + { + .eraseblocks = { {4 * 1024, 4096} }, + .block_erase = spi_block_erase_20, + }, { + .eraseblocks = { {32 * 1024, 512} }, + .block_erase = spi_block_erase_52, + }, { + .eraseblocks = { {64 * 1024, 256} }, + .block_erase = spi_block_erase_d8, + }, { + .eraseblocks = { {16 * 1024 * 1024, 1} }, + .block_erase = spi_block_erase_60, + }, { + .eraseblocks = { {16 * 1024 * 1024, 1} }, + .block_erase = spi_block_erase_c7, + } + }, + }; + + struct flashrom_flashctx flash = { 0 }; + struct flashrom_layout *layout; + /* + * Dummyflasher is capable to emulate a chip, so we ask it to do this. + * Nothing to mock, dummy is taking care of this already. + */ + char *param_dup = strdup("bus=spi,emulate=W25Q128FV"); + + setup_for_chip(&flash, &layout, &chip, param_dup); + + const char *const filename = "read_chip.test"; + + printf("Read chip operation started.\n"); + assert_int_equal(0, do_read(&flash, filename)); + printf("Read chip operation done.\n"); + + teardown(&layout);
free(param_dup); } diff --git a/tests/io_mock.h b/tests/io_mock.h index adb5f3b..a285e53 100644 --- a/tests/io_mock.h +++ b/tests/io_mock.h @@ -53,6 +53,9 @@ /* Linux I2C interface constants, avoiding linux/i2c-dev.h */ #define I2C_SLAVE 0x0703
+/* Always return success for tests. */ +#define S_ISREG(x) 0 + struct io_mock { void *state;
diff --git a/tests/meson.build b/tests/meson.build index 53885a8..8019bd3 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -39,8 +39,14 @@ '-Wl,--wrap=write', '-Wl,--wrap=fopen', '-Wl,--wrap=fopen64', + '-Wl,--wrap=fwrite', + '-Wl,--wrap=fflush', '-Wl,--wrap=stat', '-Wl,--wrap=stat64', + '-Wl,--wrap=fstat', + '-Wl,--wrap=fstat64', + '-Wl,--wrap=fileno', + '-Wl,--wrap=fsync', '-Wl,--wrap=fread', '-Wl,--wrap=fgets', '-Wl,--wrap=fclose', diff --git a/tests/tests.c b/tests/tests.c index 4965fe1..46d60c2 100644 --- a/tests/tests.c +++ b/tests/tests.c @@ -154,6 +154,18 @@ return 0; }
+int __wrap_fstat(int fd, void *buf) +{ + LOG_ME; + return 0; +} + +int __wrap_fstat64(int fd, void *buf) +{ + LOG_ME; + return 0; +} + char *__wrap_fgets(char *buf, int len, FILE *fp) { LOG_ME; @@ -170,6 +182,30 @@ return 0; }
+size_t __wrap_fwrite(const void *ptr, size_t size, size_t len, FILE *fp) +{ + LOG_ME; + return size * len; +} + +int __wrap_fflush(FILE *fp) +{ + LOG_ME; + return 0; +} + +int __wrap_fileno(FILE *fp) +{ + LOG_ME; + return MOCK_HANDLE; +} + +int __wrap_fsync(int fd) +{ + LOG_ME; + return 0; +} + int __wrap_setvbuf(FILE *fp, char *buf, int type, size_t size) { LOG_ME; @@ -359,6 +395,8 @@ const struct CMUnitTest chip_tests[] = { cmocka_unit_test(erase_chip_test_success), cmocka_unit_test(erase_chip_with_dummyflasher_test_success), + cmocka_unit_test(read_chip_test_success), + cmocka_unit_test(read_chip_with_dummyflasher_test_success), }; ret |= cmocka_run_group_tests_name("chip.c tests", chip_tests, NULL, NULL);
diff --git a/tests/tests.h b/tests/tests.h index df4a41c..70b041f 100644 --- a/tests/tests.h +++ b/tests/tests.h @@ -61,5 +61,7 @@ /* chip.c */ void erase_chip_test_success(void **state); void erase_chip_with_dummyflasher_test_success(void **state); +void read_chip_test_success(void **state); +void read_chip_with_dummyflasher_test_success(void **state);
#endif /* TESTS_H */