summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorEvan Benn <evanbenn@chromium.org>2022-11-14 16:02:47 +1100
committerAnastasia Klimchuk <aklm@chromium.org>2022-12-05 04:50:42 +0000
commit62ec7b7156e1b35da66f54f6d493b38a9e78f94c (patch)
tree6d4a90a16cb60170b8bef7c5708b444cf9c4edf6 /tests
parent8274c6321ae2ff29bc9eb0de9dc32d289d3c2cc5 (diff)
downloadflashrom-62ec7b7156e1b35da66f54f6d493b38a9e78f94c.tar.gz
flashrom-62ec7b7156e1b35da66f54f6d493b38a9e78f94c.tar.bz2
flashrom-62ec7b7156e1b35da66f54f6d493b38a9e78f94c.zip
tests: Add selfcheck to unit tests
Add unit tests for programmer_table, flashchips, and board_matches structs. The tests are derived from the selfcheck function, checking that the required fields have been filled in. BUG=b:140595239 BRANCH=None TEST=meson test Change-Id: I41cd014d9bf909296b6c28e3e00548e6883ff41a Signed-off-by: Evan Benn <evanbenn@chromium.org> Reviewed-on: https://review.coreboot.org/c/flashrom/+/69620 Reviewed-by: Edward O'Callaghan <quasisec@chromium.org> Reviewed-by: Anastasia Klimchuk <aklm@chromium.org> Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Diffstat (limited to 'tests')
-rw-r--r--tests/meson.build1
-rw-r--r--tests/selfcheck.c156
-rw-r--r--tests/tests.c9
-rw-r--r--tests/tests.h6
4 files changed, 172 insertions, 0 deletions
diff --git a/tests/meson.build b/tests/meson.build
index e846d91cf..b8a5ba843 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -22,6 +22,7 @@ test_srcs = files(
'layout.c',
'chip.c',
'chip_wp.c',
+ 'selfcheck.c',
)
if not programmer.get('dummy').get('active')
diff --git a/tests/selfcheck.c b/tests/selfcheck.c
new file mode 100644
index 000000000..aeccf1837
--- /dev/null
+++ b/tests/selfcheck.c
@@ -0,0 +1,156 @@
+/*
+ * This file is part of the flashrom project.
+ *
+ * Copyright 2022 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 "flash.h"
+#include "string.h"
+
+#include "include/test.h"
+#include "programmer.h"
+#include "tests.h"
+#include <cmocka.h>
+
+
+#define assert_table(assertion, message, index, name) \
+ do { \
+ if (!(assertion)) \
+ fail_msg(message " for index:%zu name:%s", (index), (name) ? (name) : "unknown"); \
+ } while (0)
+
+
+void selfcheck_programmer_table(void **state)
+{
+ (void)state; /* unused */
+
+ size_t i;
+ for (i = 0; i < programmer_table_size; i++) {
+ const struct programmer_entry *const p = programmer_table[i];
+ assert_table(p, "programmer entry is null", i, "unknown");
+ assert_table(p->name, "programmer name is null", i, p->name);
+ bool type_good = false;
+ switch (p->type) {
+ case PCI:
+ case USB:
+ case OTHER:
+ type_good = true;
+ }
+ assert_table(type_good, "programmer type is invalid", i, p->name);
+ /* internal has its device list stored separately. */
+ if (strcmp("internal", p->name) != 0)
+ assert_table(p->devs.note, "programmer devs.note is null", i, p->name);
+ assert_table(p->init, "programmer init is null", i, p->name);
+ }
+}
+
+void selfcheck_flashchips_table(void **state)
+{
+ (void)state; /* unused */
+
+ size_t i;
+ assert_true(flashchips_size > 1);
+ assert_true(flashchips[flashchips_size - 1].name == NULL);
+ for (i = 0; i < flashchips_size - 1; i++) {
+ const struct flashchip *chip = &flashchips[i];
+ assert_table(chip->vendor, "chip vendor is null", i, chip->name);
+ assert_table(chip->name, "chip name is null", i, chip->name);
+ assert_table(chip->bustype != BUS_NONE, "chip bustype is BUS_NONE", i, chip->name);
+ }
+}
+
+void selfcheck_eraseblocks(void **state)
+{
+ (void)state; /* unused */
+
+ size_t chip_index;
+ for (chip_index = 0; chip_index < flashchips_size - 1; chip_index++) {
+ size_t i, j, k;
+ const struct flashchip *chip = &flashchips[chip_index];
+ unsigned int prev_eraseblock_count = chip->total_size * 1024;
+
+ for (k = 0; k < NUM_ERASEFUNCTIONS; k++) {
+ unsigned int done = 0;
+ struct block_eraser eraser = chip->block_erasers[k];
+ unsigned int curr_eraseblock_count = 0;
+
+ for (i = 0; i < NUM_ERASEREGIONS; i++) {
+ /* Blocks with zero size are bugs in flashchips.c. */
+ if (eraser.eraseblocks[i].count && !eraser.eraseblocks[i].size) {
+ fail_msg("Flash chip %s erase function %zu region %zu has size 0",
+ chip->name, k, i);
+ }
+ /* Blocks with zero count are bugs in flashchips.c. */
+ if (!eraser.eraseblocks[i].count && eraser.eraseblocks[i].size) {
+ fail_msg("Flash chip %s erase function %zu region %zu has count 0",
+ chip->name, k, i);
+ }
+ done += eraser.eraseblocks[i].count * eraser.eraseblocks[i].size;
+ curr_eraseblock_count += eraser.eraseblocks[i].count;
+ }
+ /* Empty eraseblock definition with erase function. */
+ if (!done && eraser.block_erase) {
+ printf("Strange: Empty eraseblock definition with non-empty erase function chip %s function %zu. Not an error.\n",
+ chip->name, k);
+ }
+
+ if (!done)
+ continue;
+ if (done != chip->total_size * 1024) {
+ fail_msg(
+ "Flash chip %s erase function %zu region walking resulted in 0x%06x bytes total, expected 0x%06x bytes.",
+ chip->name, k, done, chip->total_size * 1024);
+ assert_true(false);
+ }
+
+ if (!eraser.block_erase)
+ continue;
+ /* Check if there are identical erase functions for different
+ * layouts. That would imply "magic" erase functions. The
+ * easiest way to check this is with function pointers.
+ */
+ for (j = k + 1; j < NUM_ERASEFUNCTIONS; j++) {
+ if (eraser.block_erase == chip->block_erasers[j].block_erase) {
+ fail_msg("Flash chip %s erase function %zu and %zu are identical.",
+ chip->name, k, j);
+ }
+ }
+ if (curr_eraseblock_count > prev_eraseblock_count) {
+ fail_msg("Flash chip %s erase function %zu is not in order", chip->name, k);
+ }
+ prev_eraseblock_count = curr_eraseblock_count;
+ }
+ }
+}
+
+#if CONFIG_INTERNAL == 1
+void selfcheck_board_matches_table(void **state)
+{
+ (void)state; /* unused */
+
+ size_t i;
+
+ assert_true(board_matches_size > 1);
+ assert_true(board_matches[board_matches_size - 1].vendor_name == NULL);
+ for (i = 0; i < board_matches_size - 1; i++) {
+ const struct board_match *b = &board_matches[i];
+ assert_table(b->vendor_name, "board vendor_name is null", i, b->board_name);
+ assert_table(b->board_name, "board boad_name is null", i, b->board_name);
+ if ((!b->first_vendor || !b->first_device || !b->second_vendor || !b->second_device)
+ || ((!b->lb_vendor) ^ (!b->lb_part)) || (!b->max_rom_decode_parallel && !b->enable))
+ fail_msg("Board enable for %s %s is misdefined.\n", b->vendor_name, b->board_name);
+ }
+}
+
+#else
+ SKIP_TEST(selfcheck_board_matches_table)
+#endif /* CONFIG_INTERNAL */
diff --git a/tests/tests.c b/tests/tests.c
index fe702046a..abbac643e 100644
--- a/tests/tests.c
+++ b/tests/tests.c
@@ -381,6 +381,15 @@ int main(int argc, char *argv[])
};
ret |= cmocka_run_group_tests_name("helpers.c tests", helpers_tests, NULL, NULL);
+ const struct CMUnitTest selfcheck[] = {
+ cmocka_unit_test(selfcheck_programmer_table),
+ cmocka_unit_test(selfcheck_flashchips_table),
+ cmocka_unit_test(selfcheck_eraseblocks),
+ cmocka_unit_test(selfcheck_board_matches_table),
+ };
+ ret |= cmocka_run_group_tests_name("selfcheck.c tests", selfcheck,
+ NULL, NULL);
+
const struct CMUnitTest flashrom_tests[] = {
cmocka_unit_test(flashbuses_to_text_test_success),
};
diff --git a/tests/tests.h b/tests/tests.h
index bcca9e89e..b36ac70da 100644
--- a/tests/tests.h
+++ b/tests/tests.h
@@ -89,4 +89,10 @@ void wp_init_from_status_dummyflasher_test_success(void **state);
void full_chip_erase_with_wp_dummyflasher_test_success(void **state);
void partial_chip_erase_with_wp_dummyflasher_test_success(void **state);
+/* selfcheck.c */
+void selfcheck_programmer_table(void **state);
+void selfcheck_flashchips_table(void **state);
+void selfcheck_eraseblocks(void **state);
+void selfcheck_board_matches_table(void **state);
+
#endif /* TESTS_H */