mirror of
https://github.com/Dasharo/zephyr.git
synced 2026-03-06 14:57:20 -08:00
tests: fs: nvs: added basic unittests for nvs
Added basic tests for the NVS file system. One of the tests covers power down during the flash write operation. Signed-off-by: Kamil Piszczek <Kamil.Piszczek@nordicsemi.no>
This commit is contained in:
committed by
Carles Cufí
parent
4054d2bacf
commit
e81090cff6
9
tests/subsys/fs/nvs/CMakeLists.txt
Normal file
9
tests/subsys/fs/nvs/CMakeLists.txt
Normal file
@@ -0,0 +1,9 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
cmake_minimum_required(VERSION 3.13.1)
|
||||
include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
|
||||
project(fs_nvs)
|
||||
|
||||
FILE(GLOB app_sources src/*.c)
|
||||
target_sources(app PRIVATE ${app_sources})
|
||||
target_include_directories(app PRIVATE $ENV{ZEPHYR_BASE}/subsys/fs/nvs)
|
||||
11
tests/subsys/fs/nvs/prj.conf
Normal file
11
tests/subsys/fs/nvs/prj.conf
Normal file
@@ -0,0 +1,11 @@
|
||||
CONFIG_ZTEST=y
|
||||
CONFIG_ZTEST_STACKSIZE=4096
|
||||
CONFIG_STDOUT_CONSOLE=y
|
||||
|
||||
CONFIG_FLASH=y
|
||||
CONFIG_FLASH_MAP=y
|
||||
CONFIG_FLASH_PAGE_LAYOUT=y
|
||||
|
||||
CONFIG_NVS=y
|
||||
CONFIG_LOG=y
|
||||
CONFIG_NVS_LOG_LEVEL_DBG=y
|
||||
189
tests/subsys/fs/nvs/src/main.c
Normal file
189
tests/subsys/fs/nvs/src/main.c
Normal file
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* Copyright (c) 2019 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ztest.h>
|
||||
|
||||
#include "flash.h"
|
||||
#include "flash_map.h"
|
||||
#include "stats.h"
|
||||
#include "nvs/nvs.h"
|
||||
|
||||
#define TEST_FLASH_AREA_STORAGE_OFFSET DT_FLASH_AREA_STORAGE_OFFSET
|
||||
#define TEST_DATA_ID 1
|
||||
#define TEST_SECTOR_COUNT 5U
|
||||
|
||||
static struct nvs_fs fs;
|
||||
struct stats_hdr *sim_stats;
|
||||
struct stats_hdr *sim_thresholds;
|
||||
|
||||
void setup(void)
|
||||
{
|
||||
sim_stats = stats_group_find("flash_sim_stats");
|
||||
sim_thresholds = stats_group_find("flash_sim_thresholds");
|
||||
}
|
||||
|
||||
void teardown(void)
|
||||
{
|
||||
if (sim_stats) {
|
||||
stats_reset(sim_stats);
|
||||
}
|
||||
if (sim_thresholds) {
|
||||
stats_reset(sim_thresholds);
|
||||
}
|
||||
}
|
||||
|
||||
void test_nvs_init(void)
|
||||
{
|
||||
int err;
|
||||
const struct flash_area *fa;
|
||||
struct flash_pages_info info;
|
||||
|
||||
err = flash_area_open(DT_FLASH_AREA_STORAGE_ID, &fa);
|
||||
zassert_true(err == 0, "flash_area_open() fail: %d", err);
|
||||
|
||||
fs.offset = TEST_FLASH_AREA_STORAGE_OFFSET;
|
||||
err = flash_get_page_info_by_offs(flash_area_get_device(fa), fs.offset,
|
||||
&info);
|
||||
zassert_true(err == 0, "Unable to get page info: %d", err);
|
||||
|
||||
fs.sector_size = info.size;
|
||||
fs.sector_count = TEST_SECTOR_COUNT;
|
||||
|
||||
err = nvs_init(&fs, DT_FLASH_DEV_NAME);
|
||||
zassert_true(err == 0, "nvs_init call failure: %d", err);
|
||||
}
|
||||
|
||||
void test_nvs_write(void)
|
||||
{
|
||||
int err;
|
||||
char rd_buf[512];
|
||||
char wr_buf[512];
|
||||
char pattern[] = {0xDE, 0xAD, 0xBE, 0xEF};
|
||||
size_t len;
|
||||
|
||||
err = nvs_read(&fs, TEST_DATA_ID, rd_buf, sizeof(rd_buf));
|
||||
zassert_true(err == -ENOENT, "nvs_read unexpected failure: %d", err);
|
||||
|
||||
BUILD_ASSERT((sizeof(wr_buf) % sizeof(pattern)) == 0);
|
||||
for (int i = 0; i < sizeof(wr_buf); i += sizeof(pattern)) {
|
||||
memcpy(wr_buf + i, pattern, sizeof(pattern));
|
||||
}
|
||||
|
||||
len = nvs_write(&fs, TEST_DATA_ID, wr_buf, sizeof(wr_buf));
|
||||
zassert_true(len == sizeof(wr_buf), "nvs_write failed: %d", len);
|
||||
|
||||
len = nvs_read(&fs, TEST_DATA_ID, rd_buf, sizeof(rd_buf));
|
||||
zassert_true(len == sizeof(rd_buf), "nvs_read unexpected failure: %d",
|
||||
len);
|
||||
zassert_mem_equal(wr_buf, rd_buf, sizeof(rd_buf),
|
||||
"RD buff should be equal to the WR buff");
|
||||
|
||||
nvs_delete(&fs, TEST_DATA_ID);
|
||||
}
|
||||
|
||||
static int flash_sim_write_calls_find(struct stats_hdr *hdr, void *arg,
|
||||
const char *name, uint16_t off)
|
||||
{
|
||||
if (!strcmp(name, "flash_write_calls")) {
|
||||
u32_t **flash_write_stat = (u32_t **) arg;
|
||||
*flash_write_stat = (u32_t *)((u8_t *)hdr + off);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int flash_sim_max_write_calls_find(struct stats_hdr *hdr, void *arg,
|
||||
const char *name, uint16_t off)
|
||||
{
|
||||
if (!strcmp(name, "max_write_calls")) {
|
||||
u32_t **max_write_calls = (u32_t **) arg;
|
||||
*max_write_calls = (u32_t *)((u8_t *)hdr + off);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void test_nvs_corrupted_write(void)
|
||||
{
|
||||
int err;
|
||||
size_t len;
|
||||
char rd_buf[512];
|
||||
char wr_buf_1[512];
|
||||
char wr_buf_2[512];
|
||||
char pattern_1[] = {0xDE, 0xAD, 0xBE, 0xEF};
|
||||
char pattern_2[] = {0x03, 0xAA, 0x85, 0x6F};
|
||||
u32_t *flash_write_stat;
|
||||
u32_t *flash_max_write_calls;
|
||||
|
||||
err = nvs_read(&fs, TEST_DATA_ID, rd_buf, sizeof(rd_buf));
|
||||
zassert_true(err == -ENOENT, "nvs_read unexpected failure: %d", err);
|
||||
|
||||
BUILD_ASSERT((sizeof(wr_buf_1) % sizeof(pattern_1)) == 0);
|
||||
for (int i = 0; i < sizeof(wr_buf_1); i += sizeof(pattern_1)) {
|
||||
memcpy(wr_buf_1 + i, pattern_1, sizeof(pattern_1));
|
||||
}
|
||||
|
||||
len = nvs_write(&fs, TEST_DATA_ID, wr_buf_1, sizeof(wr_buf_1));
|
||||
zassert_true(len == sizeof(wr_buf_1), "nvs_write failed: %d", len);
|
||||
|
||||
len = nvs_read(&fs, TEST_DATA_ID, rd_buf, sizeof(rd_buf));
|
||||
zassert_true(len == sizeof(rd_buf), "nvs_read unexpected failure: %d",
|
||||
len);
|
||||
zassert_mem_equal(wr_buf_1, rd_buf, sizeof(rd_buf),
|
||||
"RD buff should be equal to the first WR buff");
|
||||
|
||||
BUILD_ASSERT((sizeof(wr_buf_2) % sizeof(pattern_2)) == 0);
|
||||
for (int i = 0; i < sizeof(wr_buf_2); i += sizeof(pattern_2)) {
|
||||
memcpy(wr_buf_2 + i, pattern_2, sizeof(pattern_2));
|
||||
}
|
||||
|
||||
/* Set the maximum number of writes that the flash simulator can
|
||||
* execute.
|
||||
*/
|
||||
stats_walk(sim_thresholds, flash_sim_max_write_calls_find,
|
||||
&flash_max_write_calls);
|
||||
stats_walk(sim_stats, flash_sim_write_calls_find, &flash_write_stat);
|
||||
|
||||
*flash_max_write_calls = *flash_write_stat - 1;
|
||||
*flash_write_stat = 0;
|
||||
|
||||
/* Flash simulator will lose part of the data at the end of this write.
|
||||
* This should simulate power down during flash write. The written data
|
||||
* are corrupted at this point and should be discarded by the NVS.
|
||||
*/
|
||||
len = nvs_write(&fs, TEST_DATA_ID, wr_buf_2, sizeof(wr_buf_2));
|
||||
zassert_true(len == sizeof(wr_buf_2), "nvs_write failed: %d", len);
|
||||
|
||||
/* Reinitialize the NVS. */
|
||||
memset(&fs, 0, sizeof(fs));
|
||||
test_nvs_init();
|
||||
|
||||
len = nvs_read(&fs, TEST_DATA_ID, rd_buf, sizeof(rd_buf));
|
||||
zassert_true(len == sizeof(rd_buf), "nvs_read unexpected failure: %d",
|
||||
len);
|
||||
zassert_true(memcmp(wr_buf_2, rd_buf, sizeof(rd_buf)) != 0,
|
||||
"RD buff should not be equal to the second WR buff because of "
|
||||
"corrupted write operation");
|
||||
zassert_mem_equal(wr_buf_1, rd_buf, sizeof(rd_buf),
|
||||
"RD buff should be equal to the first WR buff because subsequent "
|
||||
"write operation has failed");
|
||||
}
|
||||
|
||||
void test_main(void)
|
||||
{
|
||||
ztest_test_suite(test_nvs,
|
||||
ztest_unit_test_setup_teardown(test_nvs_init, setup,
|
||||
teardown),
|
||||
ztest_unit_test_setup_teardown(test_nvs_write, setup,
|
||||
teardown),
|
||||
ztest_unit_test_setup_teardown(
|
||||
test_nvs_corrupted_write, setup, teardown)
|
||||
);
|
||||
|
||||
ztest_run_test_suite(test_nvs);
|
||||
}
|
||||
3
tests/subsys/fs/nvs/testcase.yaml
Normal file
3
tests/subsys/fs/nvs/testcase.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
tests:
|
||||
filesystem.nvs:
|
||||
platform_whitelist: qemu_x86
|
||||
Reference in New Issue
Block a user