diff options
Diffstat (limited to 'test/flash_log.c')
-rw-r--r-- | test/flash_log.c | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/test/flash_log.c b/test/flash_log.c new file mode 100644 index 0000000000..20ae939f23 --- /dev/null +++ b/test/flash_log.c @@ -0,0 +1,218 @@ +/* Copyright 2019 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + * + * Test Cr-50 Non-Voltatile memory module + */ + +#include <stdlib.h> + +#include "common.h" +#include "flash_log.h" +#include "test_util.h" +#include "util.h" + +struct log_stats { + size_t total_size; + size_t entry_count; +}; + +static int verify_single_entry(uint8_t fill_byte, int expected_type) +{ + int entry_size; + union entry_u e; + size_t i; + uint8_t *log_base = (void *)CONFIG_FLASH_LOG_BASE; + + memset(log_base, fill_byte, CONFIG_FLASH_LOG_SPACE); + flash_log_init(); + + /* After initialization there should be a single log entry. */ + entry_size = flash_log_dequeue_event(0, e.entry, sizeof(e.entry)); + TEST_ASSERT(entry_size == sizeof(e.r)); + TEST_ASSERT(e.r.type == expected_type); + + entry_size = flash_log_dequeue_event(e.r.timestamp, e.entry, + sizeof(e.entry)); + TEST_ASSERT(entry_size == 0); + + /* Verify proper entry padding. */ + i = sizeof(e.r); + TEST_ASSERT(i % CONFIG_FLASH_WRITE_SIZE); + for (; i % CONFIG_FLASH_WRITE_SIZE; i++) + TEST_ASSERT(log_base[i] == FE_LOG_PAD); + + TEST_ASSERT(log_base[i] == 0xff); /* First byte above padding. */ + + return EC_SUCCESS; +} + +static int test_init_from_scratch(void) +{ + return verify_single_entry(0xff, FE_LOG_START); +} + +static int test_init_from_corrupted(void) +{ + /* Let's mess up the log space. */ + return verify_single_entry(0x55, FE_LOG_CORRUPTED); +} + +static int verify_log(struct log_stats *stats) +{ + union entry_u e; + size_t actual_size; + size_t actual_count; + int entry_size; + + e.r.timestamp = 0; + actual_size = 0; + actual_count = 0; + + while ((entry_size = flash_log_dequeue_event(e.r.timestamp, e.entry, + sizeof(e))) > 0) { + actual_count++; + actual_size += FLASH_LOG_ENTRY_SIZE(e.r.size); + } + + TEST_ASSERT(entry_size == 0); + + stats->total_size = actual_size; + stats->entry_count = actual_count; + + return EC_SUCCESS; +} + +static int fill_to_threshold(size_t threshold, struct log_stats *stats) +{ + int i; + uint8_t entry_type; + uint8_t payload_size; + uint8_t p[MAX_FLASH_LOG_PAYLOAD_SIZE]; + size_t total_size; + size_t entry_count; + + /* Start with an only entry in the log. */ + TEST_ASSERT(verify_single_entry(0xff, FE_LOG_START) == EC_SUCCESS); + + srand(0); /* Let's make sure it is consistent. */ + entry_count = 1; + total_size = FLASH_LOG_ENTRY_SIZE(0); + + /* Let's fill up the log to compaction limit. */ + do { + entry_type = rand() % 0xfe; + payload_size = rand() % MAX_FLASH_LOG_PAYLOAD_SIZE; + for (i = 0; i < payload_size; i++) + p[i] = (i + entry_type) & 0xff; + + flash_log_add_event(entry_type, payload_size, p); + total_size += FLASH_LOG_ENTRY_SIZE(payload_size); + entry_count++; + } while (total_size <= threshold); + + TEST_ASSERT(verify_log(stats) == EC_SUCCESS); + TEST_ASSERT(stats->total_size == total_size); + TEST_ASSERT(stats->entry_count == entry_count); + + /* This should get the log over the compaction threshold. */ + flash_log_add_event(entry_type, payload_size, p); + TEST_ASSERT(verify_log(stats) == EC_SUCCESS); + + return EC_SUCCESS; +} + +static int test_run_time_compaction(void) +{ + struct log_stats stats; + + TEST_ASSERT(fill_to_threshold(RUN_TIME_LOG_FULL_WATERMARK, &stats) == + EC_SUCCESS); + + /* + * Compacted space is guaranteed not to exceed the threshold plus the + * size of the largest possible entry. + */ + TEST_ASSERT(stats.total_size < + (COMPACTION_SPACE_PRESERVE + + FLASH_LOG_ENTRY_SIZE(MAX_FLASH_LOG_PAYLOAD_SIZE))); + + return EC_SUCCESS; +} + +static int test_init_time_compaction(void) +{ + struct log_stats stats; + + TEST_ASSERT(fill_to_threshold(STARTUP_LOG_FULL_WATERMARK, &stats) == + EC_SUCCESS); + + /* + * Init should roll the log back below the compaction preservation + * threshold. + */ + flash_log_init(); + TEST_ASSERT(verify_log(&stats) == EC_SUCCESS); + + /* + * Compacted space is guaranteed not to exceed the threshold plus the + * size of the largest possible entry. + */ + TEST_ASSERT(stats.total_size < + (COMPACTION_SPACE_PRESERVE + + FLASH_LOG_ENTRY_SIZE(MAX_FLASH_LOG_PAYLOAD_SIZE))); + + return EC_SUCCESS; +} + +static int test_lock_failure_reporting(void) +{ + union entry_u e; + + TEST_ASSERT(test_init_from_scratch() == EC_SUCCESS); + lock_failures_count = 0; + log_event_in_progress = 1; + + /* This should fail. */ + flash_log_add_event(FE_LOG_TEST, 0, NULL); + + /* Lock count should have been incremented. */ + TEST_ASSERT(lock_failures_count == 1); + + /* This should also fail. */ + TEST_ASSERT(flash_log_dequeue_event(0, e.entry, sizeof(e.entry)) == + -EC_ERROR_BUSY); + + log_event_in_progress = 0; + /* This should succeed. */ + flash_log_add_event(FE_LOG_TEST, 0, NULL); + + TEST_ASSERT(lock_failures_count == 0); + + /* There should be three entries in the log now. */ + flash_log_dequeue_event(0, e.entry, sizeof(e.entry)); + TEST_ASSERT(e.r.type == FE_LOG_START); + + flash_log_dequeue_event(e.r.timestamp, e.entry, sizeof(e.entry)); + TEST_ASSERT(e.r.type == FE_LOG_LOCKS); + TEST_ASSERT(FLASH_LOG_PAYLOAD_SIZE(e.r.size) == 1); + TEST_ASSERT(e.r.payload[0] == 1); + + flash_log_dequeue_event(e.r.timestamp, e.entry, sizeof(e.entry)); + TEST_ASSERT(e.r.type == FE_LOG_TEST); + + return EC_SUCCESS; +} + +void run_test(void) +{ + test_reset(); + + RUN_TEST(test_init_from_scratch); + RUN_TEST(test_init_from_corrupted); + RUN_TEST(test_run_time_compaction); + RUN_TEST(test_init_time_compaction); + RUN_TEST(test_lock_failure_reporting); + + test_print_result(); +} |