Anastasia Klimchuk has uploaded this change for review.

View Change

[WIP] Unit tests for erase function selection algo

This patch at the moment for testing only and not ready for an
actual code review.

Change-Id: I8f3fdefb76e71f6f8dc295d9dead5f38642aace7
Signed-off-by: Anastasia Klimchuk <aklm@chromium.org>
---
A tests/erase_func_algo.c
M tests/meson.build
M tests/tests.c
M tests/tests.h
4 files changed, 236 insertions(+), 0 deletions(-)

git pull ssh://review.coreboot.org:29418/flashrom refs/changes/35/67535/1
diff --git a/tests/erase_func_algo.c b/tests/erase_func_algo.c
new file mode 100644
index 0000000..4be1294
--- /dev/null
+++ b/tests/erase_func_algo.c
@@ -0,0 +1,214 @@
+/*
+ * This unit test suite is WIP and its purpose is to help with testing
+ * new algo for erase function selection.
+ *
+ * Not ready for proper code review.
+ */
+
+#include <include/test.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "tests.h"
+#include "chipdrivers.h"
+#include "flash.h"
+#include "io_mock.h"
+#include "libflashrom.h"
+#include "programmer.h"
+
+#define LOG_ERASE_FUNC printf("%s called with blockaddr=0x%x, blocklen=0x%x\n", __func__, blockaddr, blocklen)
+
+#define ERASE_VALUE 0xff
+#define MOCK_CHIP_SIZE 16
+#define CHIPS_NUM 3 /* How many small chip test cases. */
+
+struct test_region {
+ size_t start;
+ size_t end;
+ const char *name;
+};
+
+static struct chip_state {
+ unsigned int ind; /* Index of currently executed test case */
+ uint8_t buf[CHIPS_NUM][MOCK_CHIP_SIZE]; /* Contents of the mock chip. */
+ struct test_region regions[CHIPS_NUM][MOCK_CHIP_SIZE]; /* layout regions for each test case */
+ struct flashchip chips[CHIPS_NUM]; /* List of chips, same index as in buf */
+} g_chip_state;
+
+static int read_chip(struct flashctx *flash, uint8_t *buf, unsigned int start, unsigned int len)
+{
+ printf("Read chip called with start=0x%x, len=0x%x\n", start, len);
+
+ assert_in_range(start + len, 0, MOCK_CHIP_SIZE);
+
+ memcpy(buf, &g_chip_state.buf[g_chip_state.ind][start], len);
+ return 0;
+}
+
+static int write_chip(struct flashctx *flash, const uint8_t *buf, unsigned int start, unsigned int len)
+{
+ printf("Write chip called with start=0x%x, len=0x%x\n", start, len);
+
+ assert_in_range(start + len, 0, MOCK_CHIP_SIZE);
+
+ memcpy(&g_chip_state.buf[g_chip_state.ind][start], buf, len);
+ return 0;
+}
+
+static int block_erase_chip(unsigned int blockaddr, unsigned int blocklen)
+{
+ //printf("Block erase called with blockaddr=0x%x, blocklen=0x%x\n", blockaddr, blocklen);
+
+ assert_in_range(blockaddr + blocklen, 0, MOCK_CHIP_SIZE);
+
+ memset(&g_chip_state.buf[g_chip_state.ind][blockaddr], ERASE_VALUE, blocklen);
+ return 0;
+}
+
+/*
+ * Naming convention for mock erase functions:
+ * erase_<size of erase block>
+ */
+
+static int erase_1(struct flashctx *flash, unsigned int blockaddr, unsigned int blocklen)
+{
+ LOG_ERASE_FUNC;
+ return block_erase_chip(blockaddr, blocklen);
+}
+
+static int erase_2(struct flashctx *flash, unsigned int blockaddr, unsigned int blocklen)
+{
+ LOG_ERASE_FUNC;
+ return block_erase_chip(blockaddr, blocklen);
+}
+
+static int erase_4(struct flashctx *flash, unsigned int blockaddr, unsigned int blocklen)
+{
+ LOG_ERASE_FUNC;
+ return block_erase_chip(blockaddr, blocklen);
+}
+
+static int erase_8(struct flashctx *flash, unsigned int blockaddr, unsigned int blocklen)
+{
+ LOG_ERASE_FUNC;
+ return block_erase_chip(blockaddr, blocklen);
+}
+
+static int erase_16(struct flashctx *flash, unsigned int blockaddr, unsigned int blocklen)
+{
+ LOG_ERASE_FUNC;
+ return block_erase_chip(blockaddr, blocklen);
+}
+
+static const struct flashchip chip_small_size = {
+ .vendor = "aklm",
+ .total_size = MOCK_CHIP_SIZE,
+ .tested = TEST_OK_PREW,
+ .read = read_chip,
+ .write = write_chip,
+ .block_erasers =
+ {
+ {
+ .eraseblocks = { {1, MOCK_CHIP_SIZE} },
+ .block_erase = erase_1,
+ }, {
+ .eraseblocks = { {2, MOCK_CHIP_SIZE / 2} },
+ .block_erase = erase_2,
+ }, {
+ .eraseblocks = { {4, MOCK_CHIP_SIZE / 4} },
+ .block_erase = erase_4,
+ }, {
+ .eraseblocks = { {8, MOCK_CHIP_SIZE / 8} },
+ .block_erase = erase_8,
+ }, {
+ .eraseblocks = { {16, MOCK_CHIP_SIZE / 16} },
+ .block_erase = erase_16,
+ }
+ },
+};
+
+static void setup_chip(struct flashrom_flashctx *flashctx, struct flashrom_layout **layout,
+ const char *programmer_param, unsigned int ind)
+{
+ flashctx->chip = &g_chip_state.chips[ind];
+
+ printf("Creating layout for test case #%d... ", ind);
+ assert_int_equal(0, flashrom_layout_new(layout));
+ /* Regions from test case. */
+ int i = 0;
+ while (g_chip_state.regions[ind][i].name != NULL) {
+ assert_int_equal(0, flashrom_layout_add_region(*layout,
+ g_chip_state.regions[ind][i].start,
+ g_chip_state.regions[ind][i].end,
+ g_chip_state.regions[ind][i].name));
+ assert_int_equal(0, flashrom_layout_include_region(*layout, g_chip_state.regions[ind][i].name));
+ i++;
+ }
+
+ flashrom_layout_set(flashctx, *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. */
+ flashctx->mst = &registered_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");
+}
+
+/*
+ * Setup all test cases: the same chip definition is used.
+ * initial contents of buf is different
+ * layout region is different
+ */
+static struct chip_state g_chip_state = {
+ .chips = {chip_small_size, chip_small_size, chip_small_size},
+ .regions = {
+ {{0, MOCK_CHIP_SIZE - 1, "whole chip"}},
+ {{0, MOCK_CHIP_SIZE/2 - 1, "part1"}, {MOCK_CHIP_SIZE/2, MOCK_CHIP_SIZE - 1, "part2"}},
+ {{0, 10, "odd1"}, {11, 15, "odd2"}},
+ },
+ .buf = {
+ {0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf},
+ {0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff},
+ {0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0x0, 0xff, 0xff, 0xff, 0xff, 0xff},
+ },
+};
+
+void erase_function_algo_test_success(void **state)
+{
+ (void) state; /* unused */
+
+ struct flashrom_flashctx flashctx = { 0 };
+ const char *param = ""; /* Default values for all params. */
+
+ g_chip_state.ind = 0; /* Let's go! */
+
+ while (g_chip_state.ind < CHIPS_NUM) {
+ struct flashrom_layout *layout;
+ setup_chip(&flashctx, &layout, param, g_chip_state.ind);
+
+ printf("Erase test case #%d started.\n", g_chip_state.ind);
+ int ret = flashrom_flash_erase(&flashctx);
+ printf("Erase test case ##%d returned %d.\n", g_chip_state.ind, ret);
+
+ teardown(&layout);
+
+ g_chip_state.ind++;
+ };
+}
diff --git a/tests/meson.build b/tests/meson.build
index b629998..61b8a09 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -31,6 +31,7 @@
'layout.c',
'chip.c',
'chip_wp.c',
+ 'erase_func_algo.c',
]

mocks = [
diff --git a/tests/tests.c b/tests/tests.c
index 7a448d4..d30a5ae 100644
--- a/tests/tests.c
+++ b/tests/tests.c
@@ -459,5 +459,10 @@
};
ret |= cmocka_run_group_tests_name("chip_wp.c tests", chip_wp_tests, NULL, NULL);

+ const struct CMUnitTest erase_func_algo_tests[] = {
+ cmocka_unit_test(erase_function_algo_test_success),
+ };
+ ret |= cmocka_run_group_tests_name("erase_func_algo.c tests", erase_func_algo_tests, NULL, NULL);
+
return ret;
}
diff --git a/tests/tests.h b/tests/tests.h
index cdbf01c..ec868c6 100644
--- a/tests/tests.h
+++ b/tests/tests.h
@@ -86,4 +86,7 @@
void full_chip_erase_with_wp_dummyflasher_test_success(void **state);
void partial_chip_erase_with_wp_dummyflasher_test_success(void **state);

+/* erase_func_algo.c */
+void erase_function_algo_test_success(void **state);
+
#endif /* TESTS_H */

To view, visit change 67535. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: flashrom
Gerrit-Branch: master
Gerrit-Change-Id: I8f3fdefb76e71f6f8dc295d9dead5f38642aace7
Gerrit-Change-Number: 67535
Gerrit-PatchSet: 1
Gerrit-Owner: Anastasia Klimchuk <aklm@chromium.org>
Gerrit-MessageType: newchange