Anastasia Klimchuk has uploaded this change for review.

View Change

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 */

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

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