diff options
Diffstat (limited to 'test/nvmem_vars.c')
-rw-r--r-- | test/nvmem_vars.c | 538 |
1 files changed, 0 insertions, 538 deletions
diff --git a/test/nvmem_vars.c b/test/nvmem_vars.c deleted file mode 100644 index 99e059215e..0000000000 --- a/test/nvmem_vars.c +++ /dev/null @@ -1,538 +0,0 @@ -/* Copyright 2016 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 of the key=val variable implementation (set, get, delete, etc). - */ - -#include "common.h" -#include "compile_time_macros.h" -#include "nvmem.h" -#include "nvmem_vars.h" -#include "printf.h" -#include "shared_mem.h" -#include "test_util.h" - -/* Declare the user regions (see test_config.h) */ -uint32_t nvmem_user_sizes[] = { - CONFIG_FLASH_NVMEM_VARS_USER_SIZE, -}; -BUILD_ASSERT(ARRAY_SIZE(nvmem_user_sizes) == NVMEM_NUM_USERS); - -/****************************************************************************/ -/* Mock the flash storage */ - -static uint8_t ram_buffer[CONFIG_FLASH_NVMEM_VARS_USER_SIZE]; -static uint8_t flash_buffer[CONFIG_FLASH_NVMEM_VARS_USER_SIZE]; - -extern char *rbuf; - -/* Internal functions exported for test */ -void release_local_copy(void) -{ - rbuf = NULL; -} - -int get_local_copy(void) -{ - if (!rbuf) { - memcpy(ram_buffer, flash_buffer, sizeof(ram_buffer)); - rbuf = (char *)ram_buffer; - } - return EC_SUCCESS; -} - -int nvmem_read(uint32_t startOffset, uint32_t size, - void *data_, enum nvmem_users user) -{ - /* Our mocks make some assumptions */ - if (startOffset != 0 || - size > CONFIG_FLASH_NVMEM_VARS_USER_SIZE || - user != CONFIG_FLASH_NVMEM_VARS_USER_NUM) - return EC_ERROR_UNIMPLEMENTED; - - if (!data_) - return EC_ERROR_INVAL; - - memcpy(data_, flash_buffer, size); - - return EC_SUCCESS; -} - -int nvmem_write(uint32_t startOffset, uint32_t size, - void *data_, enum nvmem_users user) -{ - /* Our mocks make some assumptions */ - if (startOffset != 0 || - size > CONFIG_FLASH_NVMEM_VARS_USER_SIZE || - user != CONFIG_FLASH_NVMEM_VARS_USER_NUM) - return EC_ERROR_UNIMPLEMENTED; - - if (!data_) - return EC_ERROR_INVAL; - - memcpy(ram_buffer, data_, size); - - return EC_SUCCESS; -} - -int nvmem_commit(void) -{ - memcpy(flash_buffer, ram_buffer, CONFIG_FLASH_NVMEM_VARS_USER_SIZE); - return EC_SUCCESS; -} - -int nvmem_erase_user_data(enum nvmem_users user) -{ - memset(ram_buffer, 0xff, sizeof(ram_buffer)); - memset(flash_buffer, 0xff, sizeof(flash_buffer)); - return EC_SUCCESS; -} - -/****************************************************************************/ -/* Helper routines */ - -static void erase_flash(void) -{ - /* Invalidate the RAM cache */ - release_local_copy(); - - /* Zero flash */ - memset(flash_buffer, 0xff, sizeof(flash_buffer)); -} - -/* Erase flash, then copy data_ over it */ -static void load_flash(const uint8_t *data_, size_t data_len) -{ - erase_flash(); - memcpy(flash_buffer, data_, data_len); -} - -/* Return true if flash matches data_, and is followed by 0xff to the end */ -static int verify_flash(const uint8_t *data_, size_t data_len) -{ - size_t i; - - /* mismatch means false */ - if (memcmp(flash_buffer, data_, data_len)) - return 0; - - for (i = data_len; - i < CONFIG_FLASH_NVMEM_VARS_USER_SIZE - data_len; - i++) - if (flash_buffer[i] != 0xff) - return 0; - return 1; -} - -/* - * Treating both as strings, save the <key, value> pair. - */ -int str_setvar(const char *key, const char *val) -{ - /* Only for tests, so assume the length will fit */ - uint8_t key_len, val_len; - - key_len = strlen(key); - val_len = val ? strlen(val) : 0; - - return setvar(key, key_len, val, val_len); -} - -/* - * Treating both as strings, lookup the key and compare the result with the - * expected value. Return true if they match. - */ -static int str_matches(const char *key, const char *expected_val) -{ - const struct tuple *t = getvar(key, strlen(key)); - uint8_t expected_len; - - if (!expected_val && !t) - return 1; - - if (expected_val && !t) - return 0; - - if (!expected_val && t) - return 0; - - expected_len = strlen(expected_val); - return !memcmp(tuple_val(t), expected_val, expected_len); -} - -/****************************************************************************/ -/* Tests */ - -static int check_init(void) -{ - /* Valid entries */ - const uint8_t good[] = { 0x01, 0x01, 0x00, 'A', 'a', - 0x01, 0x01, 0x00, 'B', 'b', - 0x00 }; - - /* Empty variables are 0x00, followed by all 0xff */ - const uint8_t empty[] = { 0x00 }; - - /* - * This is parsed as though there's only one variable, but it's wrong - * because the rest of the storage isn't 0xff. - */ - const uint8_t bad_key[] = { 0x01, 0x01, 0x00, 'A', 'a', - 0x00, 0x01, 0x00, 'B', 'b', - 0x00 }; - - /* Zero-length variables are not allowed */ - const uint8_t bad_val[] = { 0x01, 0x01, 0x00, 'A', 'a', - 0x01, 0x00, 0x00, 'B', 'b', - 0x00 }; - - /* The next constants use magic numbers based on on the region size */ - BUILD_ASSERT(CONFIG_FLASH_NVMEM_VARS_USER_SIZE == 600); - - /* This is one byte too large */ - const uint8_t too_big[] = { [0] = 0xff, [1] = 0xff, /* 0 - 512 */ - [513] = 0x01, [514] = 0x53, /* 513 - 599 */ - [599] = 0x00 }; - - /* This should just barely fit */ - const uint8_t just_right[] = { [0] = 0xff, [1] = 0xff, /* 0-512 */ - [513] = 0x01, [514] = 0x52, /* 513-598 */ - [599] = 0x00 }; - - /* No end marker */ - const uint8_t not_right[] = { [0] = 0xff, [1] = 0xff, /* 0-512 */ - [513] = 0x01, [514] = 0x52, /* 513-598 */ - [599] = 0xff }; - - load_flash(good, sizeof(good)); - TEST_ASSERT(initvars() == EC_SUCCESS); - TEST_ASSERT(verify_flash(good, sizeof(good))); - - load_flash(empty, sizeof(empty)); - TEST_ASSERT(initvars() == EC_SUCCESS); - TEST_ASSERT(verify_flash(empty, sizeof(empty))); - - /* All 0xff quickly runs off the end of the storage */ - erase_flash(); - TEST_ASSERT(initvars() == EC_SUCCESS); - TEST_ASSERT(verify_flash(empty, sizeof(empty))); - - load_flash(bad_key, sizeof(bad_key)); - TEST_ASSERT(initvars() == EC_SUCCESS); - TEST_ASSERT(verify_flash(empty, sizeof(empty))); - - load_flash(bad_val, sizeof(bad_val)); - TEST_ASSERT(initvars() == EC_SUCCESS); - TEST_ASSERT(verify_flash(empty, sizeof(empty))); - - load_flash(too_big, sizeof(too_big)); - TEST_ASSERT(initvars() == EC_SUCCESS); - TEST_ASSERT(verify_flash(empty, sizeof(empty))); - - load_flash(just_right, sizeof(just_right)); - TEST_ASSERT(initvars() == EC_SUCCESS); - TEST_ASSERT(verify_flash(just_right, sizeof(just_right))); - - load_flash(not_right, sizeof(not_right)); - TEST_ASSERT(initvars() == EC_SUCCESS); - TEST_ASSERT(verify_flash(empty, sizeof(empty))); - - return EC_SUCCESS; -} - -static int simple_search(void) -{ - const uint8_t preload[] = { - 0x02, 0x02, 0x00, 'h', 'o', 'y', 'o', - 0x02, 0x4, 0x00, 'y', 'o', 'h', 'o', 'y', 'o', - 0x02, 0x06, 0x00, 'm', 'o', 'y', 'o', 'h', 'o', 'y', 'o', - 0x00 }; - - load_flash(preload, sizeof(preload)); - TEST_ASSERT(initvars() == EC_SUCCESS); - TEST_ASSERT(verify_flash(preload, sizeof(preload))); - - TEST_ASSERT(str_matches("no", 0)); - TEST_ASSERT(str_matches("ho", "yo")); - TEST_ASSERT(str_matches("yo", "hoyo")); - TEST_ASSERT(str_matches("mo", "yohoyo")); - - return EC_SUCCESS; -} - -static int simple_write(void) -{ - const uint8_t after_one[] = { - 0x02, 0x02, 0x00, 'h', 'o', 'y', 'o', - 0x00 }; - - const uint8_t after_two[] = { - 0x02, 0x02, 0x00, 'h', 'o', 'y', 'o', - 0x02, 0x4, 0x00, 'y', 'o', 'h', 'o', 'y', 'o', - 0x00 }; - - const uint8_t after_three[] = { - 0x02, 0x02, 0x00, 'h', 'o', 'y', 'o', - 0x02, 0x4, 0x00, 'y', 'o', 'h', 'o', 'y', 'o', - 0x02, 0x06, 0x00, 'm', 'o', 'y', 'o', 'h', 'o', 'y', 'o', - 0x00 }; - - erase_flash(); - TEST_ASSERT(initvars() == EC_SUCCESS); - - TEST_ASSERT(setvar("ho", 2, "yo", 2) == EC_SUCCESS); - TEST_ASSERT(writevars() == EC_SUCCESS); - TEST_ASSERT(verify_flash(after_one, sizeof(after_one))); - - TEST_ASSERT(setvar("yo", 2, "hoyo", 4) == EC_SUCCESS); - TEST_ASSERT(writevars() == EC_SUCCESS); - TEST_ASSERT(verify_flash(after_two, sizeof(after_two))); - - TEST_ASSERT(setvar("mo", 2, "yohoyo", 6) == EC_SUCCESS); - TEST_ASSERT(writevars() == EC_SUCCESS); - TEST_ASSERT(verify_flash(after_three, sizeof(after_three))); - - return EC_SUCCESS; -} - -static int simple_delete(void) -{ - const char start_with[] = { - 0x01, 0x05, 0x00, 'A', 'a', 'a', 'a', 'a', 'a', - 0x02, 0x03, 0x00, 'B', 'B', 'b', 'b', 'b', - 0x03, 0x06, 0x00, 'C', 'C', 'C', 'x', 'y', 'z', 'p', 'd', 'q', - 0x01, 0x03, 0x00, 'M', 'm', '0', 'm', - 0x04, 0x01, 0x00, 'N', 'N', 'N', 'N', 'n', - 0x00 }; - - const char after_one[] = { - 0x02, 0x03, 0x00, 'B', 'B', 'b', 'b', 'b', - 0x03, 0x06, 0x00, 'C', 'C', 'C', 'x', 'y', 'z', 'p', 'd', 'q', - 0x01, 0x03, 0x00, 'M', 'm', '0', 'm', - 0x04, 0x01, 0x00, 'N', 'N', 'N', 'N', 'n', - 0x00 }; - - const char after_two[] = { - 0x02, 0x03, 0x00, 'B', 'B', 'b', 'b', 'b', - 0x03, 0x06, 0x00, 'C', 'C', 'C', 'x', 'y', 'z', 'p', 'd', 'q', - 0x01, 0x03, 0x00, 'M', 'm', '0', 'm', - 0x00 }; - - const char after_three[] = { - 0x02, 0x03, 0x00, 'B', 'B', 'b', 'b', 'b', - 0x01, 0x03, 0x00, 'M', 'm', '0', 'm', - 0x00 }; - - const char empty[] = { 0x00 }; - - erase_flash(); - TEST_ASSERT(initvars() == EC_SUCCESS); - - TEST_ASSERT(setvar("A", 1, "aaaaa", 5) == EC_SUCCESS); - TEST_ASSERT(setvar("BB", 2, "bbb", 3) == EC_SUCCESS); - TEST_ASSERT(setvar("CCC", 3, "xyzpdq", 6) == EC_SUCCESS); - TEST_ASSERT(setvar("M", 1, "m0m", 3) == EC_SUCCESS); - TEST_ASSERT(setvar("NNNN", 4, "n", 1) == EC_SUCCESS); - TEST_ASSERT(writevars() == EC_SUCCESS); - TEST_ASSERT(verify_flash(start_with, sizeof(start_with))); - - /* Zap first variable by setting var_len to 0 */ - TEST_ASSERT(setvar("A", 1, "yohoyo", 0) == EC_SUCCESS); - TEST_ASSERT(writevars() == EC_SUCCESS); - TEST_ASSERT(verify_flash(after_one, sizeof(after_one))); - - /* Zap last variable by passing null pointer */ - TEST_ASSERT(setvar("NNNN", 4, 0, 3) == EC_SUCCESS); - TEST_ASSERT(writevars() == EC_SUCCESS); - TEST_ASSERT(verify_flash(after_two, sizeof(after_two))); - - /* Ensure that zapping nonexistant variable does nothing */ - TEST_ASSERT(setvar("XXX", 3, 0, 0) == EC_SUCCESS); - TEST_ASSERT(writevars() == EC_SUCCESS); - TEST_ASSERT(verify_flash(after_two, sizeof(after_two))); - - /* Zap variable in the middle */ - TEST_ASSERT(setvar("CCC", 3, 0, 0) == EC_SUCCESS); - TEST_ASSERT(writevars() == EC_SUCCESS); - TEST_ASSERT(verify_flash(after_three, sizeof(after_three))); - - /* Zap the rest */ - TEST_ASSERT(setvar("BB", 2, 0, 0) == EC_SUCCESS); - TEST_ASSERT(setvar("M", 1, 0, 0) == EC_SUCCESS); - TEST_ASSERT(writevars() == EC_SUCCESS); - TEST_ASSERT(verify_flash(empty, sizeof(empty))); - - /* Zapping a nonexistant variable still does nothing */ - TEST_ASSERT(setvar("XXX", 3, 0, 0) == EC_SUCCESS); - TEST_ASSERT(writevars() == EC_SUCCESS); - TEST_ASSERT(verify_flash(empty, sizeof(empty))); - - return EC_SUCCESS; -} - -static int complex_write(void) -{ - erase_flash(); - TEST_ASSERT(initvars() == EC_SUCCESS); - - /* Do a bunch of writes and erases */ - str_setvar("ho", "aa"); - str_setvar("zo", "nn"); - str_setvar("yo", "CCCCCCCC"); - str_setvar("zooo", "yyyyyyy"); - str_setvar("yo", "AA"); - str_setvar("ho", 0); - str_setvar("yi", "BBB"); - str_setvar("yi", "AA"); - str_setvar("hixx", 0); - str_setvar("yo", "BBB"); - str_setvar("zo", ""); - str_setvar("hi", "bbb"); - str_setvar("ho", "cccccc"); - str_setvar("yo", ""); - str_setvar("zo", "ggggg"); - - /* What do we expect to find? */ - TEST_ASSERT(str_matches("hi", "bbb")); - TEST_ASSERT(str_matches("hixx", 0)); - TEST_ASSERT(str_matches("ho", "cccccc")); - TEST_ASSERT(str_matches("yi", "AA")); - TEST_ASSERT(str_matches("yo", 0)); - TEST_ASSERT(str_matches("zo", "ggggg")); - TEST_ASSERT(str_matches("zooo", "yyyyyyy")); - - return EC_SUCCESS; -} - -static int weird_keys(void) -{ - uint8_t keyA[255]; - uint8_t keyB[255]; - const char *valA = "this is A"; - const char *valB = "THIS IS b"; - int i; - const struct tuple *t; - - erase_flash(); - TEST_ASSERT(initvars() == EC_SUCCESS); - - for (i = 0; i < 255; i++) { - keyA[i] = i; - keyB[i] = 255 - i; - } - - TEST_ASSERT(setvar(keyA, sizeof(keyA), - valA, strlen(valA)) == EC_SUCCESS); - - TEST_ASSERT(setvar(keyB, sizeof(keyB), - valB, strlen(valB)) == EC_SUCCESS); - - TEST_ASSERT(writevars() == EC_SUCCESS); - - t = getvar(keyA, sizeof(keyA)); - TEST_ASSERT(t); - TEST_ASSERT(t->val_len == strlen(valA)); - TEST_ASSERT(memcmp(tuple_val(t), valA, strlen(valA)) == 0); - - t = getvar(keyB, sizeof(keyB)); - TEST_ASSERT(t); - TEST_ASSERT(t->val_len == strlen(valB)); - TEST_ASSERT(memcmp(tuple_val(t), valB, strlen(valB)) == 0); - - return EC_SUCCESS; -} - -static int weird_values(void) -{ - const char *keyA = "this is A"; - const char *keyB = "THIS IS b"; - char valA[255]; - char valB[255]; - int i; - const struct tuple *t; - - erase_flash(); - TEST_ASSERT(initvars() == EC_SUCCESS); - - for (i = 0; i < 255; i++) { - valA[i] = i; - valB[i] = 255 - i; - } - - TEST_ASSERT(setvar(keyA, strlen(keyA), - valA, sizeof(valA)) == EC_SUCCESS); - TEST_ASSERT(str_setvar("c", "CcC") == EC_SUCCESS); - TEST_ASSERT(setvar(keyB, strlen(keyB), - valB, sizeof(valB)) == EC_SUCCESS); - TEST_ASSERT(str_setvar("d", "dDd") == EC_SUCCESS); - - TEST_ASSERT(writevars() == EC_SUCCESS); - - t = getvar(keyA, strlen(keyA)); - TEST_ASSERT(t); - TEST_ASSERT(memcmp(tuple_val(t), valA, sizeof(valA)) == 0); - - t = getvar(keyB, strlen(keyB)); - TEST_ASSERT(t); - TEST_ASSERT(memcmp(tuple_val(t), valB, sizeof(valB)) == 0); - - TEST_ASSERT(str_matches("c", "CcC")); - TEST_ASSERT(str_matches("d", "dDd")); - - return EC_SUCCESS; -} - -static int fill_it_up(void) -{ - int i, n; - char key[20]; - - erase_flash(); - TEST_ASSERT(initvars() == EC_SUCCESS); - - /* - * Some magic numbers here, because we want to use up 10 bytes at a - * time and end up with exactly 9 free bytes left. - */ - TEST_ASSERT(CONFIG_FLASH_NVMEM_VARS_USER_SIZE % 10 == 0); - n = CONFIG_FLASH_NVMEM_VARS_USER_SIZE / 10; - TEST_ASSERT(n < 1000); - - /* Fill up the storage */ - for (i = 0; i < n - 1; i++) { - /* 3-byte header, 5-char key, 2-char val, == 10 chars */ - snprintf(key, sizeof(key), "kk%03d", i); - TEST_ASSERT(setvar(key, 5, "aa", 2) == EC_SUCCESS); - } - - /* - * Should be nine bytes left in rbuf (because we need one more '\0' at - * the end). This won't fit. - */ - TEST_ASSERT(setvar("kk999", 5, "aa", 2) == EC_ERROR_OVERFLOW); - /* But this will. */ - TEST_ASSERT(setvar("kk999", 5, "a", 1) == EC_SUCCESS); - /* And this, because it replaces a previous entry */ - TEST_ASSERT(setvar("kk000", 5, "bc", 2) == EC_SUCCESS); - /* But this still won't fit */ - TEST_ASSERT(setvar("kk999", 5, "de", 2) == EC_ERROR_OVERFLOW); - - return EC_SUCCESS; -} - -void run_test(void) -{ - test_reset(); - - RUN_TEST(check_init); - RUN_TEST(simple_write); - RUN_TEST(simple_search); - RUN_TEST(simple_delete); - RUN_TEST(complex_write); - RUN_TEST(weird_keys); - RUN_TEST(weird_values); - RUN_TEST(fill_it_up); - - test_print_result(); -} |