From 887a3f6c0e556bfb8308cf124edf087e53635ea8 Mon Sep 17 00:00:00 2001 From: Yuval Peress Date: Wed, 24 Aug 2022 23:50:52 -0600 Subject: test: Add basic tests exercising the panic output API Exercise some of the panic output API. Some of the basic printing API cannot yet be fully tested. But a fix upstream is coming to allow us to use the 'console' harness features to parse the output log and pass/fail the test based on output. BRANCH=none BUG=none TEST=twister -s zephyr/test/drivers/drivers.default Signed-off-by: Yuval Peress Change-Id: I8e56e8bcdaa0e095891c38a26e56ced8f3a8d4d0 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3855593 Reviewed-by: Simon Glass Code-Coverage: Zoss --- builtin/assert.h | 8 ++- common/panic_output.c | 2 +- include/common.h | 4 ++ include/panic.h | 21 ++++-- include/system.h | 4 +- zephyr/shim/src/system.c | 2 +- zephyr/shim/src/ztest_system.c | 10 ++- .../common/include/test/drivers/test_mocks.h | 2 + zephyr/test/drivers/common/src/test_mocks.c | 4 ++ zephyr/test/drivers/default/CMakeLists.txt | 1 + zephyr/test/drivers/default/src/panic_output.c | 75 ++++++++++++++++++++++ 11 files changed, 121 insertions(+), 12 deletions(-) create mode 100644 zephyr/test/drivers/default/src/panic_output.c diff --git a/builtin/assert.h b/builtin/assert.h index 010198fd1b..7008e24976 100644 --- a/builtin/assert.h +++ b/builtin/assert.h @@ -11,6 +11,8 @@ /* Include CONFIG definitions for EC sources. */ #ifndef THIRD_PARTY #include "common.h" +#else +#define test_mockable_noreturn noreturn #endif #ifdef __cplusplus @@ -21,7 +23,7 @@ extern "C" { #ifdef CONFIG_DEBUG_ASSERT_REBOOTS #ifdef CONFIG_DEBUG_ASSERT_BRIEF -noreturn void panic_assert_fail(const char *fname, int linenum); +test_mockable_noreturn void panic_assert_fail(const char *fname, int linenum); #define ASSERT(cond) \ do { \ if (!(cond)) \ @@ -30,8 +32,8 @@ noreturn void panic_assert_fail(const char *fname, int linenum); #else /* !CONFIG_DEBUG_ASSERT_BRIEF */ -noreturn void panic_assert_fail(const char *msg, const char *func, - const char *fname, int linenum); +test_mockable_noreturn void panic_assert_fail(const char *msg, const char *func, + const char *fname, int linenum); #define ASSERT(cond) \ do { \ if (!(cond)) \ diff --git a/common/panic_output.c b/common/panic_output.c index 4bbf9bc230..ffbe1525da 100644 --- a/common/panic_output.c +++ b/common/panic_output.c @@ -121,7 +121,7 @@ void panic_reboot(void) } /* Complete the processing of a panic, after the initial message is shown */ -static noreturn void complete_panic(int linenum) +test_mockable_static_noreturn void complete_panic(int linenum) { if (IS_ENABLED(CONFIG_SOFTWARE_PANIC)) software_panic(PANIC_SW_ASSERT, linenum); diff --git a/include/common.h b/include/common.h index dc20787e5b..49f5a4c15b 100644 --- a/include/common.h +++ b/include/common.h @@ -252,11 +252,15 @@ #define test_mockable __attribute__((weak)) #define test_mockable_static __attribute__((weak)) #define test_mockable_static_inline __attribute__((weak)) +#define test_mockable_noreturn __attribute__((weak)) +#define test_mockable_static_noreturn __attribute__((weak)) #define test_export_static #else #define test_mockable #define test_mockable_static static #define test_mockable_static_inline static inline +#define test_mockable_noreturn noreturn +#define test_mockable_static_noreturn static noreturn #define test_export_static static #endif diff --git a/include/panic.h b/include/panic.h index 1ccdbb41f6..6553b6feb0 100644 --- a/include/panic.h +++ b/include/panic.h @@ -15,6 +15,19 @@ #include "software_panic.h" +/* + * Define these helpers if needed. While normally they would be derived from + * common.h, we cannot include that header here because this file is also used + * in the ectool and the build breaks. + */ +#ifndef test_mockable_noreturn +#if defined(TEST_BUILD) || defined(CONFIG_ZTEST) +#define test_mockable_noreturn __attribute__((weak)) +#else +#define test_mockable_noreturn noreturn +#endif +#endif /* test_mockable_noreturn */ + #ifdef __cplusplus extern "C" { #endif @@ -197,10 +210,10 @@ void panic_data_ccprint(const struct panic_data *pdata); * @param linenum Line number where assertion happened */ #ifdef CONFIG_DEBUG_ASSERT_BRIEF -noreturn void panic_assert_fail(const char *fname, int linenum); +test_mockable_noreturn void panic_assert_fail(const char *fname, int linenum); #else -noreturn void panic_assert_fail(const char *msg, const char *func, - const char *fname, int linenum); +test_mockable_noreturn void panic_assert_fail(const char *msg, const char *func, + const char *fname, int linenum); #endif /** @@ -228,7 +241,7 @@ noreturn * Store a panic log and halt the system for a software-related reason, such as * stack overflow or assertion failure. */ -noreturn void software_panic(uint32_t reason, uint32_t info); +test_mockable_noreturn void software_panic(uint32_t reason, uint32_t info); /** * Log a panic in the panic log, but don't halt the system. Normally diff --git a/include/system.h b/include/system.h index 3dee2e9c30..ab9f6b6677 100644 --- a/include/system.h +++ b/include/system.h @@ -372,7 +372,9 @@ const char *system_get_build_info(void); * * @param flags Reset flags; see SYSTEM_RESET_* above. */ -#if !(defined(TEST_FUZZ) || defined(CONFIG_ZTEST)) +#if (defined(TEST_FUZZ) || defined(CONFIG_ZTEST)) +test_mockable +#else noreturn #endif void diff --git a/zephyr/shim/src/system.c b/zephyr/shim/src/system.c index 89356edf60..f4a105ddd7 100644 --- a/zephyr/shim/src/system.c +++ b/zephyr/shim/src/system.c @@ -197,7 +197,7 @@ const char *system_get_chip_revision(void) return cros_system_chip_revision(sys_dev); } -void system_reset(int flags) +test_mockable void system_reset(int flags) { int err; uint32_t save_flags; diff --git a/zephyr/shim/src/ztest_system.c b/zephyr/shim/src/ztest_system.c index d2dc41e18a..74491b2b04 100644 --- a/zephyr/shim/src/ztest_system.c +++ b/zephyr/shim/src/ztest_system.c @@ -3,11 +3,12 @@ * found in the LICENSE file. */ -#include "system.h" -#include "cros_version.h" #include "battery.h" #include "charge_manager.h" +#include "common.h" +#include "cros_version.h" #include "sysjump.h" +#include "system.h" #define CPRINTS(format, args...) cprints(CC_SYSTEM, format, ##args) @@ -26,6 +27,11 @@ __attribute__((weak)) void system_reset(int flags) __builtin_unreachable(); } +__attribute__((weak)) void software_panic(uint32_t reason, uint32_t info) +{ + __builtin_unreachable(); +} + static uint8_t bbram[SYSTEM_BBRAM_IDX_TRY_SLOT + 1]; test_mockable int system_get_bbram(enum system_bbram_idx idx, uint8_t *value) diff --git a/zephyr/test/drivers/common/include/test/drivers/test_mocks.h b/zephyr/test/drivers/common/include/test/drivers/test_mocks.h index 4db0102e1d..7fd794dcaa 100644 --- a/zephyr/test/drivers/common/include/test/drivers/test_mocks.h +++ b/zephyr/test/drivers/common/include/test/drivers/test_mocks.h @@ -105,3 +105,5 @@ DECLARE_FAKE_VALUE_FUNC(int, init_rom_copy, int, int, int); /* Mocks for common/system.c */ DECLARE_FAKE_VALUE_FUNC(int, system_jumped_late); +DECLARE_FAKE_VOID_FUNC(system_reset, int); +DECLARE_FAKE_VOID_FUNC(software_panic, uint32_t, uint32_t); diff --git a/zephyr/test/drivers/common/src/test_mocks.c b/zephyr/test/drivers/common/src/test_mocks.c index 3c8f31b9f2..fbc920d8f1 100644 --- a/zephyr/test/drivers/common/src/test_mocks.c +++ b/zephyr/test/drivers/common/src/test_mocks.c @@ -16,6 +16,8 @@ DEFINE_FAKE_VALUE_FUNC(int, init_rom_copy, int, int, int); /* Mocks for common/system.c */ DEFINE_FAKE_VALUE_FUNC(int, system_jumped_late); +DEFINE_FAKE_VOID_FUNC(system_reset, int); +DEFINE_FAKE_VOID_FUNC(software_panic, uint32_t, uint32_t); /** * @brief Reset all the fakes before each test. @@ -30,6 +32,8 @@ static void fff_reset_rule_before(const struct ztest_unit_test *test, RESET_FAKE(init_rom_unmap); RESET_FAKE(init_rom_copy); RESET_FAKE(system_jumped_late); + RESET_FAKE(system_reset); + RESET_FAKE(software_panic); } ZTEST_RULE(fff_reset_rule, fff_reset_rule_before, NULL); diff --git a/zephyr/test/drivers/default/CMakeLists.txt b/zephyr/test/drivers/default/CMakeLists.txt index 9053e00f77..53c5c9b376 100644 --- a/zephyr/test/drivers/default/CMakeLists.txt +++ b/zephyr/test/drivers/default/CMakeLists.txt @@ -57,6 +57,7 @@ target_sources(app PRIVATE src/locate_chip.c src/motion_sense/motion_sense.c src/panic.c + src/panic_output.c src/port80.c src/power_common.c src/ppc_sn5s330.c diff --git a/zephyr/test/drivers/default/src/panic_output.c b/zephyr/test/drivers/default/src/panic_output.c new file mode 100644 index 0000000000..4561a6afef --- /dev/null +++ b/zephyr/test/drivers/default/src/panic_output.c @@ -0,0 +1,75 @@ +/* Copyright 2022 The ChromiumOS Authors. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include + +#include "panic.h" +#include "test/drivers/test_mocks.h" +#include "test/drivers/test_state.h" + +ZTEST_SUITE(panic_output, drivers_predicate_post_main, NULL, NULL, NULL, NULL); + +ZTEST(panic_output, test_panic_printf) +{ + panic_printf("test output string from %s\n", __func__); +} + +ZTEST(panic_output, test_panic_puts) +{ + panic_puts("test output string\n"); +} + +ZTEST(panic_output, test_panic_sw_reason_is_valid) +{ + zassert_false(panic_sw_reason_is_valid(PANIC_SW_BASE - 1), NULL); + /* PANIC_SW_DIV_ZERO */ + zassert_true(panic_sw_reason_is_valid(PANIC_SW_BASE), NULL); + /* PANIC_SW_STACK_OVERFLOW */ + zassert_true(panic_sw_reason_is_valid(PANIC_SW_BASE + 1), NULL); + /* PANIC_SW_PD_CRASH */ + zassert_true(panic_sw_reason_is_valid(PANIC_SW_BASE + 2), NULL); + /* PANIC_SW_ASSERT */ + zassert_true(panic_sw_reason_is_valid(PANIC_SW_BASE + 3), NULL); + /* PANIC_SW_WATCHDOG */ + zassert_true(panic_sw_reason_is_valid(PANIC_SW_BASE + 4), NULL); + /* PANIC_SW_RNG */ + zassert_true(panic_sw_reason_is_valid(PANIC_SW_BASE + 5), NULL); + /* PANIC_SW_PMIC_FAULT */ + zassert_true(panic_sw_reason_is_valid(PANIC_SW_BASE + 6), NULL); + zassert_false(panic_sw_reason_is_valid(PANIC_SW_BASE + 7), NULL); +} + +ZTEST(panic_output, test_panic) +{ + panic(__func__); + zassert_equal(1, system_reset_fake.call_count, + "Expected system_reset() to be called once, but was " + "called %d times", + system_reset_fake.call_count); + zassert_equal(0, system_reset_fake.arg0_val, + "Expected system_reset() to be called with flags=0, but " + "got flags=%d", + system_reset_fake.arg0_val); +} + +ZTEST(panic_output, test_panic_assert_fail) +{ + int line_num = __LINE__; + + panic_assert_fail("Test panic message", __func__, __FILE_NAME__, + line_num); + zassert_equal(1, software_panic_fake.call_count, + "Expected sofware_panic() to be called once, but was " + "called %d times", + software_panic_fake.call_count); + zassert_equal(PANIC_SW_ASSERT, software_panic_fake.arg0_val, + "Expected software_panic() to be called with " + "reason=%d (PANIC_SW_ASSERT) but got %d", + PANIC_SW_ASSERT, software_panic_fake.arg0_val); + zassert_equal(line_num, software_panic_fake.arg1_val, + "Expected software_panic() to be called with " + "line=%d but got %d", + line_num, software_panic_fake.arg1_val); +} -- cgit v1.2.1