mirror of
https://github.com/espressif/esp-idf.git
synced 2025-07-31 19:24:33 +02:00
NVS flash: host-based unit test of nvs::Page
* General tests like page loading from flash * Rough test of fixed-size data types * Rough test of blob read * Added coverage target in cmake, also accessible via `idf.py coverage` * Fixed unsigned comparison in comp. enum table * introducing temporary LINUX_TARGET define
This commit is contained in:
@@ -1,3 +1,5 @@
|
||||
idf_build_get_property(target IDF_TARGET)
|
||||
|
||||
set(srcs "src/nvs_api.cpp"
|
||||
"src/nvs_cxx_api.cpp"
|
||||
"src/nvs_item_hash_list.cpp"
|
||||
@@ -11,10 +13,39 @@ set(srcs "src/nvs_api.cpp"
|
||||
"src/nvs_partition_manager.cpp"
|
||||
"src/nvs_types.cpp")
|
||||
|
||||
if(CONFIG_NVS_ENCRYPTION)
|
||||
list(APPEND srcs "src/nvs_encrypted_partition.cpp")
|
||||
endif()
|
||||
set(public_req spi_flash)
|
||||
|
||||
set(include_dirs "include")
|
||||
|
||||
idf_component_register(SRCS "${srcs}"
|
||||
REQUIRES spi_flash mbedtls
|
||||
INCLUDE_DIRS include)
|
||||
REQUIRES "${public_req}"
|
||||
INCLUDE_DIRS "${include_dirs}")
|
||||
|
||||
# If we use the linux target, we need to redirect the crc functions to the linux
|
||||
if(${target} STREQUAL "linux")
|
||||
if(CONFIG_NVS_ENCRYPTION)
|
||||
# mbedtls isn't configured for building with linux or as mock target. It will draw in all kind of dependencies
|
||||
message(FATAL_ERROR "NVS currently doesn't support encryption if built for Linux.")
|
||||
endif()
|
||||
idf_component_get_property(spi_flash_dir spi_flash COMPONENT_DIR)
|
||||
target_include_directories(${COMPONENT_LIB} PUBLIC
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/mock/int"
|
||||
"${spi_flash_dir}/sim/stubs/freertos/include")
|
||||
target_sources(${COMPONENT_LIB} PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/mock/int/crc.cpp")
|
||||
target_compile_options(${COMPONENT_LIB} PUBLIC "-DLINUX_TARGET")
|
||||
else()
|
||||
# TODO: this is a workaround until IDF-2085 is fixed
|
||||
idf_component_get_property(mbedtls_lib mbedtls COMPONENT_LIB)
|
||||
target_link_libraries(${COMPONENT_LIB} PUBLIC ${mbedtls_lib})
|
||||
endif()
|
||||
|
||||
if(CONFIG_NVS_ENCRYPTION)
|
||||
target_sources(${COMPONENT_LIB} PRIVATE "src/nvs_encrypted_partition.cpp")
|
||||
idf_component_get_property(mbedtls_lib mbedtls COMPONENT_LIB)
|
||||
target_link_libraries(${COMPONENT_LIB} PUBLIC ${mbedtls_lib})
|
||||
endif()
|
||||
|
||||
if(${target} STREQUAL "linux")
|
||||
target_compile_options(${COMPONENT_LIB} PUBLIC --coverage)
|
||||
target_link_libraries(${COMPONENT_LIB} PUBLIC --coverage)
|
||||
endif()
|
||||
|
429
components/nvs_flash/host_test/fixtures/test_fixtures.hpp
Normal file
429
components/nvs_flash/host_test/fixtures/test_fixtures.hpp
Normal file
@@ -0,0 +1,429 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "nvs_partition.hpp"
|
||||
#include "nvs.h"
|
||||
#include "nvs_page.hpp"
|
||||
#include "nvs_storage.hpp"
|
||||
#include <exception>
|
||||
#include <string>
|
||||
|
||||
#ifdef CONFIG_NVS_ENCRYPTION
|
||||
#include "nvs_encrypted_partition.hpp"
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
#include "Mockesp_partition.h"
|
||||
}
|
||||
|
||||
struct FixtureException : std::exception {
|
||||
FixtureException(const std::string& msg) : msg(msg) { }
|
||||
|
||||
const char *what() {
|
||||
return msg.c_str();
|
||||
}
|
||||
|
||||
std::string msg;
|
||||
};
|
||||
|
||||
class PartitionMock : public nvs::Partition {
|
||||
public:
|
||||
PartitionMock(uint32_t address, uint32_t size)
|
||||
: partition(), address(address), size(size)
|
||||
{
|
||||
assert(size);
|
||||
}
|
||||
|
||||
const char *get_partition_name() override
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
esp_err_t read_raw(size_t src_offset, void* dst, size_t size) override
|
||||
{
|
||||
return esp_partition_read_raw(&partition, src_offset, dst, size);
|
||||
}
|
||||
|
||||
esp_err_t read(size_t src_offset, void* dst, size_t size) override
|
||||
{
|
||||
return esp_partition_read(&partition, src_offset, dst, size);
|
||||
}
|
||||
|
||||
esp_err_t write_raw(size_t dst_offset, const void* src, size_t size) override
|
||||
{
|
||||
return esp_partition_write_raw(&partition, dst_offset, src, size);
|
||||
}
|
||||
|
||||
esp_err_t write(size_t dst_offset, const void* src, size_t size) override
|
||||
{
|
||||
return esp_partition_write(&partition, dst_offset, src, size);
|
||||
}
|
||||
|
||||
esp_err_t erase_range(size_t dst_offset, size_t size) override
|
||||
{
|
||||
return esp_partition_erase_range(&partition, dst_offset, size);
|
||||
}
|
||||
|
||||
uint32_t get_address() override
|
||||
{
|
||||
return address;
|
||||
}
|
||||
|
||||
uint32_t get_size() override
|
||||
{
|
||||
return size;
|
||||
}
|
||||
|
||||
const esp_partition_t partition;
|
||||
|
||||
private:
|
||||
uint32_t address;
|
||||
|
||||
uint32_t size;
|
||||
};
|
||||
|
||||
#ifdef CONFIG_NVS_ENCRYPTION
|
||||
struct EncryptedPartitionFixture {
|
||||
EncryptedPartitionFixture(nvs_sec_cfg_t *cfg,
|
||||
uint32_t start_sector = 0,
|
||||
uint32_t sector_size = 1,
|
||||
const char *partition_name = NVS_DEFAULT_PART_NAME)
|
||||
: esp_partition(), emu(start_sector + sector_size),
|
||||
part(partition_name, &esp_partition) {
|
||||
esp_partition.address = start_sector * SPI_FLASH_SEC_SIZE;
|
||||
esp_partition.size = sector_size * SPI_FLASH_SEC_SIZE;
|
||||
assert(part.init(cfg) == ESP_OK);
|
||||
}
|
||||
|
||||
~EncryptedPartitionFixture() { }
|
||||
|
||||
esp_partition_t esp_partition;
|
||||
|
||||
SpiFlashEmulator emu;
|
||||
|
||||
nvs::NVSEncryptedPartition part;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct PartitionMockFixture {
|
||||
PartitionMockFixture(uint32_t start_sector = 0,
|
||||
uint32_t sector_size = 1,
|
||||
const char *partition_name = NVS_DEFAULT_PART_NAME)
|
||||
: part_mock(start_sector * SPI_FLASH_SEC_SIZE, sector_size * SPI_FLASH_SEC_SIZE) {
|
||||
std::fill_n(raw_header, sizeof(raw_header)/sizeof(raw_header[0]), UINT8_MAX);
|
||||
}
|
||||
|
||||
~PartitionMockFixture() { }
|
||||
|
||||
uint8_t raw_header[512];
|
||||
|
||||
PartitionMock part_mock;
|
||||
};
|
||||
|
||||
struct NVSPageFixture : public PartitionMockFixture {
|
||||
NVSPageFixture(uint32_t start_sector = 0,
|
||||
uint32_t sector_size = 1,
|
||||
const char *partition_name = NVS_DEFAULT_PART_NAME)
|
||||
: PartitionMockFixture(start_sector, sector_size, partition_name), page()
|
||||
{
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_header, 32);
|
||||
|
||||
for (int i = 0; i < 8; i++) {
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_header, 512);
|
||||
}
|
||||
|
||||
if (page.load(&part_mock, start_sector) != ESP_OK) throw FixtureException("couldn't setup page");
|
||||
}
|
||||
|
||||
nvs::Page page;
|
||||
};
|
||||
|
||||
struct NVSValidPageFixture : public PartitionMockFixture {
|
||||
const static uint8_t NS_INDEX = 1;
|
||||
|
||||
// valid header
|
||||
uint8_t raw_header_valid [32];
|
||||
|
||||
// entry table with one entry
|
||||
uint8_t raw_entry_table [32];
|
||||
|
||||
uint8_t ns_entry [32];
|
||||
|
||||
uint8_t value_entry [32];
|
||||
|
||||
NVSValidPageFixture(uint32_t start_sector = 0,
|
||||
uint32_t sector_size = 1,
|
||||
const char *partition_name = NVS_DEFAULT_PART_NAME)
|
||||
: PartitionMockFixture(start_sector, sector_size, partition_name),
|
||||
raw_header_valid {0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc2, 0x16, 0xdd, 0xdc},
|
||||
ns_entry {0x00, 0x01, 0x01, 0xff, 0x68, 0xc5, 0x3f, 0x0b, 't', 'e', 's', 't', '_', 'n', 's', '\0',
|
||||
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', 1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
|
||||
value_entry {0x01, 0x01, 0x01, 0xff, 0x3d, 0xf3, 0x99, 0xe5, 't', 'e', 's', 't', '_', 'v', 'a', 'l',
|
||||
'u', 'e', '\0', '\0', '\0', '\0', '\0', '\0', 47, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
|
||||
page()
|
||||
{
|
||||
std::fill_n(raw_entry_table, sizeof(raw_entry_table)/sizeof(raw_entry_table[0]), 0);
|
||||
raw_entry_table[0] = 0xfa;
|
||||
|
||||
// read page header
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_header_valid, 32);
|
||||
|
||||
// read entry table
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_entry_table, 32);
|
||||
|
||||
// read next free entry's header
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_header, 4);
|
||||
|
||||
// read namespace entry
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(ns_entry, 32);
|
||||
|
||||
// read normal entry
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(value_entry, 32);
|
||||
|
||||
// read normal entry second time during duplicated entry check
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(value_entry, 32);
|
||||
|
||||
if (page.load(&part_mock, start_sector) != ESP_OK) throw FixtureException("couldn't setup page");
|
||||
}
|
||||
|
||||
nvs::Page page;
|
||||
};
|
||||
|
||||
struct NVSValidStorageFixture : public PartitionMockFixture {
|
||||
const static uint8_t NS_INDEX = 1;
|
||||
|
||||
uint8_t ns_entry [32];
|
||||
|
||||
uint8_t empty_entry [32];
|
||||
|
||||
NVSValidStorageFixture(uint32_t start_sector = 0,
|
||||
uint32_t sector_size = 3,
|
||||
const char *partition_name = NVS_DEFAULT_PART_NAME)
|
||||
: PartitionMockFixture(start_sector, sector_size, partition_name),
|
||||
ns_entry {0x00, 0x01, 0x01, 0xff, 0x68, 0xc5, 0x3f, 0x0b, 't', 'e', 's', 't', '_', 'n', 's', '\0',
|
||||
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', 1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
|
||||
empty_entry(),
|
||||
storage(&part_mock)
|
||||
{
|
||||
std::fill_n(empty_entry, sizeof(empty_entry)/sizeof(empty_entry[0]), 0xFF);
|
||||
|
||||
// entry table with one entry
|
||||
uint8_t raw_entry_table [32];
|
||||
|
||||
uint8_t header_full_page [] = {
|
||||
0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc2, 0x16, 0xdd, 0xdc};
|
||||
|
||||
uint8_t header_second_page [] = {
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
|
||||
uint8_t header_third_page [] = {
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
|
||||
// entry_table with all elements deleted except the namespace entry written and the last entry free
|
||||
std::fill_n(raw_entry_table, sizeof(raw_entry_table)/sizeof(raw_entry_table[0]), 0);
|
||||
raw_entry_table[0] = 0x02;
|
||||
raw_entry_table[31] = 0xFC;
|
||||
|
||||
// read full page header
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(header_full_page, 32);
|
||||
|
||||
// read entry table
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_entry_table, 32);
|
||||
|
||||
// reading entry table checks empty entry
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(empty_entry, 32);
|
||||
|
||||
// read namespace entry
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(ns_entry, 32);
|
||||
|
||||
// read last two pages' headers, which trigger an automatic full read each because each page is empty
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(header_second_page, 32);
|
||||
for (int i = 0; i < 8; i++) {
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_header, 512);
|
||||
}
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(header_third_page, 32);
|
||||
for (int i = 0; i < 8; i++) {
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_header, 512);
|
||||
}
|
||||
|
||||
// read namespace entry in duplicated header item check of pagemanager::load
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(ns_entry, 32);
|
||||
|
||||
// storage finally actually reads namespace
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(ns_entry, 32);
|
||||
|
||||
// storage looks for blob index entries
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(ns_entry, 32);
|
||||
|
||||
// Storage::eraseOrphanDataBlobs() also wants to take it's turn...
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(ns_entry, 32);
|
||||
|
||||
if (storage.init(start_sector, sector_size) != ESP_OK) throw FixtureException("couldn't setup page");
|
||||
}
|
||||
|
||||
nvs::Storage storage;
|
||||
};
|
||||
|
||||
struct NVSValidBlobPageFixture : public PartitionMockFixture {
|
||||
const static uint8_t NS_INDEX = 1;
|
||||
const static size_t BLOB_DATA_SIZE = 32;
|
||||
|
||||
// valid header
|
||||
uint8_t raw_header_valid [32];
|
||||
|
||||
// entry table with one entry
|
||||
uint8_t raw_entry_table [32];
|
||||
|
||||
uint8_t ns_entry [32];
|
||||
|
||||
uint8_t blob_entry [32];
|
||||
uint8_t blob_data [BLOB_DATA_SIZE];
|
||||
uint8_t blob_index [32];
|
||||
|
||||
NVSValidBlobPageFixture(uint32_t start_sector = 0,
|
||||
uint32_t sector_size = 1,
|
||||
const char *partition_name = NVS_DEFAULT_PART_NAME)
|
||||
: PartitionMockFixture(start_sector, sector_size, partition_name),
|
||||
raw_header_valid {0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc2, 0x16, 0xdd, 0xdc},
|
||||
ns_entry {0x00, 0x01, 0x01, 0xff, 0x68, 0xc5, 0x3f, 0x0b, 't', 'e', 's', 't', '_', 'n', 's', '\0',
|
||||
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', 1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
|
||||
blob_entry {0x01, 0x42, 0x02, 0x00, 0xaa, 0xf3, 0x23, 0x87, 't', 'e', 's', 't', '_', 'b', 'l', 'o',
|
||||
'b', '\0', '\0', '\0', '\0', '\0', '\0', '\0', 0x20, 0x00, 0xff, 0xff, 0xc6, 0x96, 0x86, 0xd9},
|
||||
blob_data {0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef},
|
||||
blob_index {0x01, 0x48, 0x01, 0xff, 0x42, 0x6b, 0xdf, 0x66, 't', 'e', 's', 't', '_', 'b', 'l', 'o',
|
||||
'b', '\0', '\0', '\0', '\0', '\0', '\0', '\0', 0x20, 0x00, 0x00, 0x00, 0x01, 0x00, 0xff, 0xff},
|
||||
page()
|
||||
{
|
||||
std::fill_n(raw_entry_table, sizeof(raw_entry_table)/sizeof(raw_entry_table[0]), 0xFF);
|
||||
raw_entry_table[0] = 0xaa;
|
||||
|
||||
// read page header
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_header_valid, 32);
|
||||
|
||||
// read entry table
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_entry_table, 32);
|
||||
|
||||
// read next free entry's header
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_header, 4);
|
||||
|
||||
// read namespace entry
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(ns_entry, 32);
|
||||
|
||||
// read normal blob entry + index, not the data
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(blob_entry, 32);
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(blob_index, 32);
|
||||
|
||||
// read normal entry second time during duplicated entry check
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(blob_entry, 32);
|
||||
|
||||
if (page.load(&part_mock, start_sector) != ESP_OK) throw FixtureException("couldn't setup page");
|
||||
}
|
||||
|
||||
nvs::Page page;
|
||||
};
|
||||
|
||||
struct NVSFullPageFixture : public PartitionMockFixture {
|
||||
const static uint8_t NS_INDEX = 1;
|
||||
|
||||
// valid header
|
||||
uint8_t raw_header_valid [32];
|
||||
|
||||
// entry table with one entry
|
||||
uint8_t raw_entry_table [32];
|
||||
|
||||
uint8_t ns_entry [32];
|
||||
|
||||
uint8_t value_entry [32];
|
||||
|
||||
NVSFullPageFixture(uint32_t start_sector = 0,
|
||||
uint32_t sector_size = 1,
|
||||
const char *partition_name = NVS_DEFAULT_PART_NAME,
|
||||
bool load = true)
|
||||
: PartitionMockFixture(start_sector, sector_size, partition_name),
|
||||
raw_header_valid {0xfc, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xa3, 0x48, 0x9f, 0x38},
|
||||
ns_entry {0x00, 0x01, 0x01, 0xff, 0x68, 0xc5, 0x3f, 0x0b, 't', 'e', 's', 't', '_', 'n', 's', '\0',
|
||||
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', 1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
|
||||
value_entry {0x01, 0x01, 0x01, 0xff, 0x3d, 0xf3, 0x99, 0xe5, 't', 'e', 's', 't', '_', 'v', 'a', 'l',
|
||||
'u', 'e', '\0', '\0', '\0', '\0', '\0', '\0', 47, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
|
||||
page()
|
||||
{
|
||||
std::fill_n(raw_entry_table, sizeof(raw_entry_table)/sizeof(raw_entry_table[0]), 0);
|
||||
raw_entry_table[0] = 0xfa;
|
||||
|
||||
// entry_table with all elements deleted except the namespace entry written and the last entry free
|
||||
std::fill_n(raw_entry_table, sizeof(raw_entry_table)/sizeof(raw_entry_table[0]), 0);
|
||||
raw_entry_table[0] = 0x0a;
|
||||
raw_entry_table[31] = 0xFC;
|
||||
|
||||
// read page header
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_header_valid, 32);
|
||||
|
||||
// read entry table
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_entry_table, 32);
|
||||
|
||||
// no next free entry check, only one entry written
|
||||
|
||||
// read namespace entry
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(ns_entry, 32);
|
||||
|
||||
// read normal entry
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(value_entry, 32);
|
||||
|
||||
// no duplicated entry check
|
||||
|
||||
if (load) {
|
||||
if (page.load(&part_mock, start_sector) != ESP_OK) throw FixtureException("couldn't setup page");
|
||||
}
|
||||
}
|
||||
|
||||
nvs::Page page;
|
||||
};
|
27
components/nvs_flash/host_test/nvs_page_test/CMakeLists.txt
Normal file
27
components/nvs_flash/host_test/nvs_page_test/CMakeLists.txt
Normal file
@@ -0,0 +1,27 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
set(COMPONENTS main)
|
||||
idf_build_set_property(CONFIG_SPI_FLASH_MOCK 1)
|
||||
idf_build_set_property(COMPILE_DEFINITIONS "-DNO_DEBUG_STORAGE" APPEND)
|
||||
project(host_nvs_page_test)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/build/coverage.info"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/build"
|
||||
COMMAND lcov --capture --directory . --output-file coverage.info
|
||||
COMMENT "Create coverage report"
|
||||
)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT "${CMAKE_CURRENT_SOURCE_DIR}/build/coverage_report/"
|
||||
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/build/coverage.info"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/build"
|
||||
COMMAND genhtml coverage.info --output-directory coverage_report/
|
||||
COMMENT "Turn coverage report into html-based visualization"
|
||||
)
|
||||
|
||||
add_custom_target(coverage
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}/build"
|
||||
DEPENDS "coverage_report/"
|
||||
)
|
23
components/nvs_flash/host_test/nvs_page_test/README.rst
Normal file
23
components/nvs_flash/host_test/nvs_page_test/README.rst
Normal file
@@ -0,0 +1,23 @@
|
||||
NVS Page Test for Host
|
||||
======================
|
||||
|
||||
Build
|
||||
-----
|
||||
|
||||
First, make sure that the target is set to linux.
|
||||
Run ``idf.py --preview set-target linux`` to be sure.
|
||||
Then do a normal IDF build: ``idf.py build``.
|
||||
|
||||
Run
|
||||
---
|
||||
|
||||
IDF monitor doesn't work yet for Linux.
|
||||
You have to run the app manually: ``./build/host_nvs_page_test.elf``.
|
||||
|
||||
Coverage
|
||||
---
|
||||
|
||||
To generate the coverage, run: ``idf.py coverage``.
|
||||
Afterwards, you can view the coverage by opening ``build/coverage_report/index.html`` with your browser.
|
||||
Note that you need to run the application at least once before generating the coverage information.
|
||||
If you run it multiple times, the coverage information adds up.
|
@@ -0,0 +1,10 @@
|
||||
idf_component_register(SRCS "nvs_page_test.cpp"
|
||||
INCLUDE_DIRS
|
||||
"."
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../../fixtures"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../../../test_nvs_host"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/../../../src"
|
||||
REQUIRES cmock nvs_flash spi_flash)
|
||||
|
||||
target_compile_options(${COMPONENT_LIB} PUBLIC --coverage)
|
||||
target_link_libraries(${COMPONENT_LIB} --coverage)
|
@@ -0,0 +1,934 @@
|
||||
/* Hello World Example
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include "unity.h"
|
||||
#include "test_fixtures.hpp"
|
||||
|
||||
extern "C" {
|
||||
#include "Mockesp_partition.h"
|
||||
}
|
||||
|
||||
using namespace std;
|
||||
using namespace nvs;
|
||||
|
||||
void test_Page_load_reading_header_fails()
|
||||
{
|
||||
PartitionMock mock(0, 4096);
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_ERR_INVALID_ARG);
|
||||
Page page;
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::INVALID, page.state());
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, page.load(&mock, 0));
|
||||
}
|
||||
|
||||
void test_Page_load_reading_data_fails()
|
||||
{
|
||||
uint8_t header[64];
|
||||
std::fill_n(header, sizeof(header)/sizeof(header[0]), UINT8_MAX);
|
||||
PartitionMock mock(0, 4096);
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(header, 32);
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_FAIL);
|
||||
Page page;
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::INVALID, page.state());
|
||||
TEST_ASSERT_EQUAL(ESP_FAIL, page.load(&mock, 0));
|
||||
}
|
||||
|
||||
void test_Page_load__uninitialized_page_has_0xfe()
|
||||
{
|
||||
PartitionMockFixture fix;
|
||||
Page page;
|
||||
|
||||
fix.raw_header[511] = 0xfe;
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(fix.raw_header, 32);
|
||||
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(fix.raw_header, 512);
|
||||
|
||||
// Page::load() should return ESP_OK, but state has to be corrupt
|
||||
TEST_ASSERT_EQUAL(ESP_OK, page.load(&fix.part_mock, 0));
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::CORRUPT, page.state());
|
||||
}
|
||||
|
||||
void test_Page_load__initialized_corrupt_header()
|
||||
{
|
||||
PartitionMockFixture fix;
|
||||
Page page;
|
||||
|
||||
uint8_t raw_header_corrupt [] = {0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x16, 0xdd, 0xdc};
|
||||
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_header_corrupt, 32);
|
||||
|
||||
// Page::load() should return ESP_OK, but state has to be corrupt
|
||||
TEST_ASSERT_EQUAL(ESP_OK, page.load(&fix.part_mock, 0));
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::CORRUPT, page.state());
|
||||
}
|
||||
|
||||
void test_Page_load_success()
|
||||
{
|
||||
PartitionMockFixture fix;
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(fix.raw_header, 32);
|
||||
for (int i = 0; i < 8; i++) {
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(fix.raw_header, 512);
|
||||
}
|
||||
Page page;
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::INVALID, page.state());
|
||||
TEST_ASSERT_EQUAL(ESP_OK, page.load(&fix.part_mock, 0));
|
||||
TEST_ASSERT_EQUAL(Page::PageState::UNINITIALIZED, page.state());
|
||||
}
|
||||
|
||||
void test_Page_load_full_page()
|
||||
{
|
||||
NVSFullPageFixture fix(0, 1, NVS_DEFAULT_PART_NAME, false);
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::INVALID, fix.page.state());
|
||||
TEST_ASSERT_EQUAL(ESP_OK, fix.page.load(&fix.part_mock, 0));
|
||||
TEST_ASSERT_EQUAL(Page::PageState::FULL, fix.page.state());
|
||||
}
|
||||
void test_Page_load__seq_number_0()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
|
||||
uint32_t seq_num;
|
||||
fix.page.getSeqNumber(seq_num);
|
||||
TEST_ASSERT_EQUAL(0, seq_num);
|
||||
}
|
||||
|
||||
void test_Page_erase__write_fail()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
|
||||
esp_partition_erase_range_ExpectAndReturn(&fix.part_mock.partition, 0, 4096, ESP_FAIL);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_FAIL, fix.page.erase());
|
||||
TEST_ASSERT_EQUAL(Page::PageState::INVALID, fix.page.state());
|
||||
}
|
||||
|
||||
void test_Page_erase__success()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
|
||||
esp_partition_erase_range_ExpectAndReturn(&fix.part_mock.partition, 0, 4096, ESP_OK);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_OK, fix.page.erase());
|
||||
TEST_ASSERT_EQUAL(Page::PageState::UNINITIALIZED, fix.page.state());
|
||||
}
|
||||
|
||||
void test_Page_write__initialize_write_failure()
|
||||
{
|
||||
PartitionMockFixture fix;
|
||||
uint8_t write_data = 47;
|
||||
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(fix.raw_header, 32);
|
||||
for (int i = 0; i < 8; i++) {
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(fix.raw_header, 512);
|
||||
}
|
||||
esp_partition_write_raw_ExpectAnyArgsAndReturn(ESP_FAIL);
|
||||
|
||||
Page page;
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_OK, page.load(&fix.part_mock, 0));
|
||||
TEST_ASSERT_EQUAL(Page::PageState::UNINITIALIZED, page.state());
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_FAIL, page.writeItem(1, nvs::ItemType::U8, "test", &write_data, sizeof(write_data)));
|
||||
TEST_ASSERT_EQUAL(Page::PageState::INVALID, page.state());
|
||||
}
|
||||
|
||||
void test_Page_write__write_data_fails()
|
||||
{
|
||||
NVSPageFixture fix;
|
||||
uint8_t write_data = 47;
|
||||
esp_partition_write_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_write_ExpectAnyArgsAndReturn(ESP_FAIL);
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::UNINITIALIZED, fix.page.state());
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_FAIL, fix.page.writeItem(1, nvs::ItemType::U8, "test", &write_data, sizeof(write_data)));
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::INVALID, fix.page.state());
|
||||
}
|
||||
|
||||
void test_page_write__write_correct_entry_state()
|
||||
{
|
||||
NVSPageFixture fix;
|
||||
uint8_t write_data = 47;
|
||||
uint8_t raw_result [4];
|
||||
std::fill_n(raw_result, sizeof(raw_result)/sizeof(raw_result[0]), UINT8_MAX);
|
||||
// mark first entry as written
|
||||
raw_result[0] = 0xfe;
|
||||
|
||||
// initialize page
|
||||
esp_partition_write_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
|
||||
// write entry
|
||||
esp_partition_write_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
|
||||
// write entry state
|
||||
esp_partition_write_raw_ExpectWithArrayAndReturn(&fix.part_mock.partition, 1, 32, raw_result, 4, 4, ESP_OK);
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::UNINITIALIZED, fix.page.state());
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_OK, fix.page.writeItem(1, nvs::ItemType::U8, "test_key", &write_data, sizeof(write_data)));
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
}
|
||||
|
||||
void test_Page_write__write_correct_data()
|
||||
{
|
||||
NVSPageFixture fix;
|
||||
uint8_t write_data = 47;
|
||||
uint8_t raw_result [32] = {0x01, 0x01, 0x01, 0xff, 0x98, 0x6f, 0x21, 0xfd, 't', 'e', 's', 't', '_', 'k', 'e', 'y',
|
||||
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', 47, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
|
||||
|
||||
// initialize page
|
||||
esp_partition_write_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
|
||||
// write entry
|
||||
esp_partition_write_ExpectWithArrayAndReturn(&fix.part_mock.partition, 1, 64, raw_result, 32, 32, ESP_OK);
|
||||
|
||||
// write entry state
|
||||
esp_partition_write_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::UNINITIALIZED, fix.page.state());
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_OK, fix.page.writeItem(1, nvs::ItemType::U8, "test_key", &write_data, sizeof(write_data)));
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
}
|
||||
|
||||
void test_Page_readItem__read_entry_fails()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
|
||||
TEST_ASSERT_EQUAL(2, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(122, fix.page.getErasedEntryCount());
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
|
||||
uint8_t read_value = 0;
|
||||
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_FAIL);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_FAIL, fix.page.readItem(NVSValidPageFixture::NS_INDEX, "test_value", read_value));
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::INVALID, fix.page.state());
|
||||
|
||||
TEST_ASSERT_EQUAL(2, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(122, fix.page.getErasedEntryCount());
|
||||
}
|
||||
|
||||
void test_Page_readItem__read_corrupted_entry()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
TEST_ASSERT_EQUAL(2, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(122, fix.page.getErasedEntryCount());
|
||||
|
||||
uint8_t read_value = 0;
|
||||
|
||||
// corrupting entry
|
||||
fix.value_entry[0] = 0x0;
|
||||
|
||||
// first read the entry
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32);
|
||||
|
||||
// Page::eraseEntryAndSpan() reads entry again
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32);
|
||||
|
||||
// erasing entry by setting bit in entry table (0xfa -> 0xf2)
|
||||
uint8_t raw_result [4] = {0xf2, 0x00, 0x00, 0x00};
|
||||
esp_partition_write_raw_ExpectWithArrayAndReturn(&fix.part_mock.partition, 1, 32, raw_result, 4, 4, ESP_OK);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_NVS_NOT_FOUND, fix.page.readItem(NVSValidPageFixture::NS_INDEX, "test_value", read_value));
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
|
||||
TEST_ASSERT_EQUAL(1, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(123, fix.page.getErasedEntryCount());
|
||||
}
|
||||
|
||||
void test_Page_readItem__read_corrupted_second_read_fail()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
TEST_ASSERT_EQUAL(2, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(122, fix.page.getErasedEntryCount());
|
||||
|
||||
uint8_t read_value = 0;
|
||||
|
||||
// corrupting entry
|
||||
fix.value_entry[0] = 0x0;
|
||||
|
||||
// first read the entry
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32);
|
||||
|
||||
// Page::eraseEntryAndSpan() reads entry again
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_FAIL);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_FAIL, fix.page.readItem(NVSValidPageFixture::NS_INDEX, "test_value", read_value));
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::INVALID, fix.page.state());
|
||||
}
|
||||
|
||||
void test_Page_readItem__read_corrupted_erase_fail()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
TEST_ASSERT_EQUAL(2, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(122, fix.page.getErasedEntryCount());
|
||||
|
||||
uint8_t read_value = 0;
|
||||
|
||||
// corrupting entry
|
||||
fix.value_entry[0] = 0x0;
|
||||
|
||||
// first read the entry
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32);
|
||||
|
||||
// Page::eraseEntryAndSpan() reads entry again
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32);
|
||||
|
||||
// erasing entry by setting bit in entry table (0xfa -> 0xf2)
|
||||
uint8_t raw_result [4] = {0xf2, 0x00, 0x00, 0x00};
|
||||
esp_partition_write_raw_ExpectWithArrayAndReturn(&fix.part_mock.partition, 1, 32, raw_result, 4, 4, ESP_FAIL);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_FAIL, fix.page.readItem(NVSValidPageFixture::NS_INDEX, "test_value", read_value));
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::INVALID, fix.page.state());
|
||||
}
|
||||
|
||||
void test_Page_readItem__read_entry_suceeds()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
TEST_ASSERT_EQUAL(2, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(122, fix.page.getErasedEntryCount());
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
|
||||
uint8_t read_value = 0;
|
||||
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_OK, fix.page.readItem(NVSValidPageFixture::NS_INDEX, "test_value", read_value));
|
||||
|
||||
TEST_ASSERT_EQUAL(2, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(122, fix.page.getErasedEntryCount());
|
||||
|
||||
TEST_ASSERT_EQUAL(47, read_value);
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
}
|
||||
|
||||
void test_Page_readItem__blob_read_data_fails()
|
||||
{
|
||||
NVSValidBlobPageFixture fix;
|
||||
TEST_ASSERT_EQUAL(4, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(0, fix.page.getErasedEntryCount());
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
|
||||
uint8_t chunk_start = 0;
|
||||
uint8_t read_data [32];
|
||||
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.blob_entry, 32);
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_FAIL);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_FAIL, fix.page.readItem(NVSValidPageFixture::NS_INDEX,
|
||||
ItemType::BLOB_DATA,
|
||||
"test_blob",
|
||||
read_data,
|
||||
32,
|
||||
chunk_start));
|
||||
|
||||
TEST_ASSERT_EQUAL(4, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(0, fix.page.getErasedEntryCount());
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
}
|
||||
|
||||
void test_Page_readItem__corrupt_data_erase_failure()
|
||||
{
|
||||
NVSValidBlobPageFixture fix;
|
||||
TEST_ASSERT_EQUAL(4, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(0, fix.page.getErasedEntryCount());
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
|
||||
uint8_t chunk_start = 0;
|
||||
uint8_t read_data [32];
|
||||
|
||||
fix.blob_data[16] = 0xdf;
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.blob_entry, 32);
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.blob_data, fix.BLOB_DATA_SIZE);
|
||||
|
||||
// Page::eraseEntryAndSpan() reads entry again
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_FAIL);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.blob_data, fix.BLOB_DATA_SIZE);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_FAIL, fix.page.readItem(NVSValidPageFixture::NS_INDEX,
|
||||
ItemType::BLOB_DATA,
|
||||
"test_blob",
|
||||
read_data,
|
||||
32,
|
||||
chunk_start));
|
||||
|
||||
TEST_ASSERT_EQUAL(4, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(0, fix.page.getErasedEntryCount());
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
}
|
||||
|
||||
void test_Page_readItem__blob_corrupt_data()
|
||||
{
|
||||
NVSValidBlobPageFixture fix;
|
||||
TEST_ASSERT_EQUAL(4, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(0, fix.page.getErasedEntryCount());
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
|
||||
uint8_t chunk_start = 0;
|
||||
uint8_t read_data [32];
|
||||
|
||||
fix.blob_data[16] = 0xdf;
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.blob_entry, 32);
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.blob_data, fix.BLOB_DATA_SIZE);
|
||||
|
||||
// Page::eraseEntryAndSpan() reads entry again
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.blob_data, fix.BLOB_DATA_SIZE);
|
||||
|
||||
// erasing entry by setting bit in entry table (0xfa -> 0xf2)
|
||||
uint8_t raw_result [4] = {0xa2, 0xff, 0xff, 0xff};
|
||||
esp_partition_write_raw_ExpectWithArrayAndReturn(&fix.part_mock.partition, 1, 32, raw_result, 4, 4, ESP_OK);
|
||||
|
||||
esp_partition_erase_range_ExpectAndReturn(&fix.part_mock.partition, 96, 64, ESP_OK);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_NVS_NOT_FOUND, fix.page.readItem(NVSValidPageFixture::NS_INDEX,
|
||||
ItemType::BLOB_DATA,
|
||||
"test_blob",
|
||||
read_data,
|
||||
32,
|
||||
chunk_start));
|
||||
|
||||
TEST_ASSERT_EQUAL(3, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(1, fix.page.getErasedEntryCount());
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
}
|
||||
|
||||
void test_Page_readItem__blob_read_entry_suceeds()
|
||||
{
|
||||
NVSValidBlobPageFixture fix;
|
||||
TEST_ASSERT_EQUAL(4, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(0, fix.page.getErasedEntryCount());
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
|
||||
uint8_t chunk_start = 0;
|
||||
uint8_t read_data [32];
|
||||
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.blob_entry, 32);
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.blob_data, fix.BLOB_DATA_SIZE);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_OK, fix.page.readItem(NVSValidPageFixture::NS_INDEX,
|
||||
ItemType::BLOB_DATA,
|
||||
"test_blob",
|
||||
read_data,
|
||||
32,
|
||||
chunk_start));
|
||||
|
||||
TEST_ASSERT_EQUAL_MEMORY(fix.blob_data, read_data, fix.BLOB_DATA_SIZE);
|
||||
|
||||
// make sure nothing was erased, i.e. checksums matched
|
||||
TEST_ASSERT_EQUAL(4, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(0, fix.page.getErasedEntryCount());
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
}
|
||||
|
||||
void test_Page_cmp__uninitialized()
|
||||
{
|
||||
Page page;
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_NVS_INVALID_STATE, page.cmpItem(uint8_t(1) , "test", 47));
|
||||
}
|
||||
|
||||
void test_Page_cmp__item_not_found()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
|
||||
// no expectations here since comparison uses the item hash list
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_NVS_NOT_FOUND, fix.page.cmpItem(uint8_t(1), "different", 47));
|
||||
}
|
||||
|
||||
void test_Page_cmp__item_type_mismatch()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
|
||||
// read normal entry
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_NVS_TYPE_MISMATCH, fix.page.cmpItem(uint8_t(1), "test_value", int(47)));
|
||||
}
|
||||
|
||||
void test_Page_cmp__item_content_mismatch()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
|
||||
// read normal entry
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_NVS_CONTENT_DIFFERS, fix.page.cmpItem(uint8_t(1), "test_value", uint8_t(46)));
|
||||
}
|
||||
|
||||
void test_Page_cmp__item_content_match()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
|
||||
// read normal entry
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_OK, fix.page.cmpItem(NVSValidPageFixture::NS_INDEX, "test_value", uint8_t(47)));
|
||||
}
|
||||
|
||||
void test_Page_cmpItem__blob_data_mismatch()
|
||||
{
|
||||
NVSValidBlobPageFixture fix;
|
||||
|
||||
// read blob entry
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.blob_entry, 32);
|
||||
|
||||
// read blob data
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.blob_data, fix.BLOB_DATA_SIZE);
|
||||
|
||||
|
||||
uint8_t blob_data_different [] =
|
||||
{0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xee};
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_NVS_CONTENT_DIFFERS,
|
||||
fix.page.cmpItem(uint8_t(1),
|
||||
ItemType::BLOB_DATA,
|
||||
"test_blob",
|
||||
blob_data_different,
|
||||
32));
|
||||
}
|
||||
|
||||
void test_Page_cmpItem__blob_data_match()
|
||||
{
|
||||
NVSValidBlobPageFixture fix;
|
||||
|
||||
// read blob entry
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.blob_entry, 32);
|
||||
|
||||
// read blob data
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.blob_data, fix.BLOB_DATA_SIZE);
|
||||
|
||||
|
||||
uint8_t blob_data_same [] =
|
||||
{0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef,
|
||||
0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef, 0xde, 0xad, 0xbe, 0xef};
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_OK,
|
||||
fix.page.cmpItem(NVSValidPageFixture::NS_INDEX,
|
||||
ItemType::BLOB_DATA,
|
||||
"test_blob",
|
||||
blob_data_same,
|
||||
32));
|
||||
}
|
||||
|
||||
void test_Page_eraseItem__uninitialized()
|
||||
{
|
||||
Page page;
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_NVS_NOT_FOUND, page.eraseItem<uint8_t>(NVSValidPageFixture::NS_INDEX, "test_value"));
|
||||
}
|
||||
|
||||
void test_Page_eraseItem__key_not_found()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
TEST_ASSERT_EQUAL(2, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(122, fix.page.getErasedEntryCount());
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_NVS_NOT_FOUND, fix.page.eraseItem<uint8_t>(NVSValidPageFixture::NS_INDEX, "different"));
|
||||
|
||||
TEST_ASSERT_EQUAL(2, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(122, fix.page.getErasedEntryCount());
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
}
|
||||
|
||||
void test_Page_eraseItem__write_fail()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
TEST_ASSERT_EQUAL(2, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(122, fix.page.getErasedEntryCount());
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
|
||||
// first read the entry
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32);
|
||||
|
||||
// Page::eraseEntryAndSpan() reads entry again
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32);
|
||||
|
||||
// erasing entry by setting bit in entry table (0xfa -> 0xf2)
|
||||
uint8_t raw_result [4] = {0xf2, 0x00, 0x00, 0x00};
|
||||
esp_partition_write_raw_ExpectWithArrayAndReturn(&fix.part_mock.partition, 1, 32, raw_result, 4, 4, ESP_FAIL);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_FAIL, fix.page.eraseItem<uint8_t>(NVSValidPageFixture::NS_INDEX, "test_value"));
|
||||
|
||||
TEST_ASSERT_EQUAL(1, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(123, fix.page.getErasedEntryCount());
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::INVALID, fix.page.state());
|
||||
}
|
||||
|
||||
void test_Page_eraseItem__write_succeed()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
TEST_ASSERT_EQUAL(2, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(122, fix.page.getErasedEntryCount());
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
|
||||
// first read the entry
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32);
|
||||
|
||||
// Page::eraseEntryAndSpan() reads entry again
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32);
|
||||
|
||||
// erasing entry by setting bit in entry table (0xfa -> 0xf2)
|
||||
uint8_t raw_result [4] = {0xf2, 0x00, 0x00, 0x00};
|
||||
esp_partition_write_raw_ExpectWithArrayAndReturn(&fix.part_mock.partition, 1, 32, raw_result, 4, 4, ESP_OK);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_OK, fix.page.eraseItem<uint8_t>(NVSValidPageFixture::NS_INDEX, "test_value"));
|
||||
|
||||
TEST_ASSERT_EQUAL(1, fix.page.getUsedEntryCount());
|
||||
TEST_ASSERT_EQUAL(123, fix.page.getErasedEntryCount());
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, fix.page.state());
|
||||
}
|
||||
|
||||
void test_Page_findItem__uninitialized()
|
||||
{
|
||||
Page page;
|
||||
|
||||
size_t index = 0;
|
||||
Item item;
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_NVS_NOT_FOUND,
|
||||
page.findItem(NVSValidPageFixture::NS_INDEX, nvs::ItemType::U8, "test_value", index, item));
|
||||
}
|
||||
|
||||
void test_Page_find__wrong_ns()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
size_t index = 0;
|
||||
Item item;
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_NVS_NOT_FOUND,
|
||||
fix.page.findItem(NVSValidPageFixture::NS_INDEX + 1, nvs::ItemType::U8, "test_value", index, item));
|
||||
}
|
||||
|
||||
void test_Page_find__wrong_type()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
size_t index = 0;
|
||||
Item item;
|
||||
|
||||
// read normal entry
|
||||
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_ReturnArrayThruPtr_dst(fix.value_entry, 32);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_NVS_TYPE_MISMATCH,
|
||||
fix.page.findItem(NVSValidPageFixture::NS_INDEX, nvs::ItemType::I8, "test_value", index, item));
|
||||
}
|
||||
|
||||
void test_Page_find__key_empty()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
size_t index = 0;
|
||||
Item item;
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_NVS_NOT_FOUND,
|
||||
fix.page.findItem(NVSValidPageFixture::NS_INDEX, nvs::ItemType::U8, "", index, item));
|
||||
}
|
||||
|
||||
void test_Page_find__wrong_key()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
size_t index = 0;
|
||||
Item item;
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_NVS_NOT_FOUND,
|
||||
fix.page.findItem(NVSValidPageFixture::NS_INDEX, nvs::ItemType::U8, "different", index, item));
|
||||
}
|
||||
|
||||
void test_Page_find__too_large_index()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
size_t index = 2;
|
||||
Item item;
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_NVS_NOT_FOUND,
|
||||
fix.page.findItem(NVSValidPageFixture::NS_INDEX, nvs::ItemType::U8, "test_value", index, item));
|
||||
}
|
||||
|
||||
void test_Page_findItem__without_read()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_NVS_NOT_FOUND,
|
||||
fix.page.findItem(NVSValidPageFixture::NS_INDEX, nvs::ItemType::U8, "different"));
|
||||
}
|
||||
|
||||
void test_Page_markFull__wrong_state()
|
||||
{
|
||||
NVSPageFixture fix;
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_NVS_INVALID_STATE, fix.page.markFull());
|
||||
TEST_ASSERT_EQUAL(Page::PageState::UNINITIALIZED, fix.page.state());
|
||||
}
|
||||
|
||||
void test_Page_markFull__success()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
Page::PageState expected_state = Page::PageState::FULL;
|
||||
|
||||
esp_partition_write_raw_ExpectWithArrayAndReturn(&fix.part_mock.partition, sizeof(fix.part_mock.partition), 0, &expected_state, sizeof(expected_state), 4, ESP_OK);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_OK, fix.page.markFull());
|
||||
TEST_ASSERT_EQUAL(Page::PageState::FULL, fix.page.state());
|
||||
}
|
||||
|
||||
void test_Page_markFull__write_fail()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
Page::PageState expected_state = Page::PageState::FREEING;
|
||||
|
||||
esp_partition_write_raw_ExpectWithArrayAndReturn(&fix.part_mock.partition, sizeof(fix.part_mock.partition), 0, &expected_state, sizeof(expected_state), 4, ESP_FAIL);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_FAIL, fix.page.markFreeing());
|
||||
TEST_ASSERT_EQUAL(Page::PageState::INVALID, fix.page.state());
|
||||
}
|
||||
|
||||
void test_Page_markFreeing__wrong_state()
|
||||
{
|
||||
NVSPageFixture fix;
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_NVS_INVALID_STATE, fix.page.markFreeing());
|
||||
TEST_ASSERT_EQUAL(Page::PageState::UNINITIALIZED, fix.page.state());
|
||||
}
|
||||
|
||||
void test_Page_markFreeing__success()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
Page::PageState expected_state = Page::PageState::FREEING;
|
||||
|
||||
esp_partition_write_raw_ExpectWithArrayAndReturn(&fix.part_mock.partition, sizeof(fix.part_mock.partition), 0, &expected_state, sizeof(expected_state), 4, ESP_OK);
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_OK, fix.page.markFreeing());
|
||||
TEST_ASSERT_EQUAL(Page::PageState::FREEING, fix.page.state());
|
||||
}
|
||||
|
||||
void test_Page_getVarDataTailroom__uninitialized_page()
|
||||
{
|
||||
NVSPageFixture fix;
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::CHUNK_MAX_SIZE, fix.page.getVarDataTailroom());
|
||||
}
|
||||
|
||||
void test_Page_getVarDataTailroom__success()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
|
||||
// blob data item, written namespace item, written normal item: 3 items
|
||||
TEST_ASSERT_EQUAL((Page::ENTRY_COUNT - 3) * Page::ENTRY_SIZE, fix.page.getVarDataTailroom());
|
||||
}
|
||||
|
||||
void test_Page_calcEntries__uninit()
|
||||
{
|
||||
NVSPageFixture fix;
|
||||
TEST_ASSERT_EQUAL(Page::PageState::UNINITIALIZED, fix.page.state());
|
||||
|
||||
nvs_stats_t nvsStats = {0, 0, 0, 0};
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_OK, fix.page.calcEntries(nvsStats));
|
||||
TEST_ASSERT_EQUAL(0, nvsStats.used_entries);
|
||||
TEST_ASSERT_EQUAL(Page::ENTRY_COUNT, nvsStats.free_entries);
|
||||
TEST_ASSERT_EQUAL(Page::ENTRY_COUNT, nvsStats.total_entries);
|
||||
TEST_ASSERT_EQUAL(0, nvsStats.namespace_count);
|
||||
}
|
||||
|
||||
void test_Page_calcEntries__corrupt()
|
||||
{
|
||||
PartitionMockFixture fix;
|
||||
Page page;
|
||||
|
||||
uint8_t raw_header_corrupt [] = {0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x16, 0xdd, 0xdc};
|
||||
|
||||
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
|
||||
esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_header_corrupt, 32);
|
||||
|
||||
// Page::load() should return ESP_OK, but state has to be corrupt
|
||||
TEST_ASSERT_EQUAL(ESP_OK, page.load(&fix.part_mock, 0));
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::CORRUPT, page.state());
|
||||
|
||||
nvs_stats_t nvsStats = {0, 0, 0, 0};
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_OK, page.calcEntries(nvsStats));
|
||||
TEST_ASSERT_EQUAL(0, nvsStats.used_entries);
|
||||
TEST_ASSERT_EQUAL(Page::ENTRY_COUNT, nvsStats.free_entries);
|
||||
TEST_ASSERT_EQUAL(Page::ENTRY_COUNT, nvsStats.total_entries);
|
||||
TEST_ASSERT_EQUAL(0, nvsStats.namespace_count);
|
||||
}
|
||||
|
||||
void test_Page_calcEntries__active_wo_blob()
|
||||
{
|
||||
NVSValidPageFixture fix;
|
||||
|
||||
nvs_stats_t nvsStats = {0, 0, 0, 0};
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_OK, fix.page.calcEntries(nvsStats));
|
||||
TEST_ASSERT_EQUAL(2, nvsStats.used_entries);
|
||||
TEST_ASSERT_EQUAL(124, nvsStats.free_entries);
|
||||
TEST_ASSERT_EQUAL(Page::ENTRY_COUNT, nvsStats.total_entries);
|
||||
TEST_ASSERT_EQUAL(0, nvsStats.namespace_count);
|
||||
}
|
||||
|
||||
void test_Page_calcEntries__active_with_blob()
|
||||
{
|
||||
NVSValidBlobPageFixture fix;
|
||||
|
||||
nvs_stats_t nvsStats = {0, 0, 0, 0};
|
||||
|
||||
TEST_ASSERT_EQUAL(ESP_OK, fix.page.calcEntries(nvsStats));
|
||||
TEST_ASSERT_EQUAL(4, nvsStats.used_entries);
|
||||
TEST_ASSERT_EQUAL(122, nvsStats.free_entries);
|
||||
TEST_ASSERT_EQUAL(Page::ENTRY_COUNT, nvsStats.total_entries);
|
||||
TEST_ASSERT_EQUAL(0, nvsStats.namespace_count);
|
||||
}
|
||||
|
||||
void test_Page_calcEntries__invalid()
|
||||
{
|
||||
Page page;
|
||||
|
||||
nvs_stats_t nvsStats = {0, 0, 0, 0};
|
||||
|
||||
TEST_ASSERT_EQUAL(Page::PageState::INVALID, page.state());
|
||||
|
||||
// total entries always get updated
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, page.calcEntries(nvsStats));
|
||||
TEST_ASSERT_EQUAL(0, nvsStats.used_entries);
|
||||
TEST_ASSERT_EQUAL(0, nvsStats.free_entries);
|
||||
TEST_ASSERT_EQUAL(Page::ENTRY_COUNT, nvsStats.total_entries);
|
||||
TEST_ASSERT_EQUAL(0, nvsStats.namespace_count);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
UNITY_BEGIN();
|
||||
RUN_TEST(test_Page_load_reading_header_fails);
|
||||
RUN_TEST(test_Page_load_reading_data_fails);
|
||||
RUN_TEST(test_Page_load__uninitialized_page_has_0xfe);
|
||||
RUN_TEST(test_Page_load__initialized_corrupt_header);
|
||||
RUN_TEST(test_Page_load_success);
|
||||
RUN_TEST(test_Page_load_full_page);
|
||||
RUN_TEST(test_Page_load__seq_number_0);
|
||||
RUN_TEST(test_Page_erase__write_fail);
|
||||
RUN_TEST(test_Page_erase__success);
|
||||
RUN_TEST(test_Page_write__initialize_write_failure);
|
||||
RUN_TEST(test_Page_write__write_data_fails);
|
||||
RUN_TEST(test_page_write__write_correct_entry_state);
|
||||
RUN_TEST(test_Page_write__write_correct_data);
|
||||
RUN_TEST(test_Page_readItem__read_entry_fails);
|
||||
RUN_TEST(test_Page_readItem__read_corrupted_entry);
|
||||
RUN_TEST(test_Page_readItem__read_corrupted_second_read_fail);
|
||||
RUN_TEST(test_Page_readItem__read_corrupted_erase_fail);
|
||||
RUN_TEST(test_Page_readItem__read_entry_suceeds);
|
||||
RUN_TEST(test_Page_readItem__blob_read_data_fails);
|
||||
RUN_TEST(test_Page_readItem__blob_corrupt_data);
|
||||
RUN_TEST(test_Page_readItem__blob_read_entry_suceeds);
|
||||
RUN_TEST(test_Page_cmp__uninitialized);
|
||||
RUN_TEST(test_Page_cmp__item_not_found);
|
||||
RUN_TEST(test_Page_cmp__item_type_mismatch);
|
||||
RUN_TEST(test_Page_cmp__item_content_mismatch);
|
||||
RUN_TEST(test_Page_cmp__item_content_match);
|
||||
RUN_TEST(test_Page_cmpItem__blob_data_mismatch);
|
||||
RUN_TEST(test_Page_cmpItem__blob_data_match);
|
||||
RUN_TEST(test_Page_eraseItem__uninitialized);
|
||||
RUN_TEST(test_Page_eraseItem__key_not_found);
|
||||
RUN_TEST(test_Page_eraseItem__write_fail);
|
||||
RUN_TEST(test_Page_readItem__corrupt_data_erase_failure);
|
||||
RUN_TEST(test_Page_eraseItem__write_succeed);
|
||||
RUN_TEST(test_Page_findItem__uninitialized);
|
||||
RUN_TEST(test_Page_find__wrong_ns);
|
||||
RUN_TEST(test_Page_find__wrong_type);
|
||||
RUN_TEST(test_Page_find__key_empty);
|
||||
RUN_TEST(test_Page_find__wrong_key);
|
||||
RUN_TEST(test_Page_find__too_large_index);
|
||||
RUN_TEST(test_Page_findItem__without_read);
|
||||
RUN_TEST(test_Page_markFull__wrong_state);
|
||||
RUN_TEST(test_Page_markFreeing__wrong_state);
|
||||
RUN_TEST(test_Page_markFull__success);
|
||||
RUN_TEST(test_Page_markFreeing__success);
|
||||
RUN_TEST(test_Page_markFull__write_fail);
|
||||
RUN_TEST(test_Page_getVarDataTailroom__uninitialized_page);
|
||||
RUN_TEST(test_Page_getVarDataTailroom__success);
|
||||
RUN_TEST(test_Page_calcEntries__uninit);
|
||||
RUN_TEST(test_Page_calcEntries__corrupt);
|
||||
RUN_TEST(test_Page_calcEntries__active_wo_blob);
|
||||
RUN_TEST(test_Page_calcEntries__active_with_blob);
|
||||
RUN_TEST(test_Page_calcEntries__invalid);
|
||||
UNITY_END();
|
||||
return 0;
|
||||
}
|
@@ -0,0 +1,3 @@
|
||||
CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=n
|
||||
CONFIG_IDF_TARGET="linux"
|
||||
CONFIG_CXX_EXCEPTIONS=y
|
@@ -52,7 +52,7 @@ static const unsigned int crc32_le_table[256] = {
|
||||
|
||||
|
||||
|
||||
extern "C" unsigned int crc32_le(unsigned int crc, unsigned char const * buf,unsigned int len)
|
||||
extern "C" uint32_t esp_rom_crc32_le(unsigned int crc, unsigned char const * buf,unsigned int len)
|
||||
{
|
||||
unsigned int i;
|
||||
crc = ~crc;
|
@@ -20,7 +20,11 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
uint32_t crc32_le(uint32_t crc, const uint8_t* buf, size_t len);
|
||||
/**
|
||||
* Mock function to replace ESP ROM function used in IDF with a Linux implementation.
|
||||
* Note: the name MUST have the prefix esp_rom_* since tools/ci/check_rom_apis.sh checks and complains otherwise.
|
||||
*/
|
||||
uint32_t esp_rom_crc32_le(uint32_t crc, const uint8_t* buf, size_t len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
@@ -35,7 +35,7 @@ public:
|
||||
|
||||
Tenum get(size_t index) const
|
||||
{
|
||||
assert(index >= 0 && index < Nitems);
|
||||
assert(index < Nitems);
|
||||
size_t wordIndex = index / ITEMS_PER_WORD;
|
||||
size_t offset = (index % ITEMS_PER_WORD) * Nbits;
|
||||
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
|
||||
void set(size_t index, Tenum val)
|
||||
{
|
||||
assert(index >= 0 && index < Nitems);
|
||||
assert(index < Nitems);
|
||||
size_t wordIndex = index / ITEMS_PER_WORD;
|
||||
size_t offset = (index % ITEMS_PER_WORD) * Nbits;
|
||||
|
||||
|
@@ -22,17 +22,17 @@
|
||||
#include <functional>
|
||||
#include "nvs_handle_simple.hpp"
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
#ifdef LINUX_TARGET
|
||||
#include "crc.h"
|
||||
#define ESP_LOGD(...)
|
||||
#else // LINUX_TARGET
|
||||
#include <esp32/rom/crc.h>
|
||||
|
||||
// Uncomment this line to force output from this module
|
||||
// #define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
|
||||
#include "esp_log.h"
|
||||
static const char* TAG = "nvs";
|
||||
#else
|
||||
#include "crc.h"
|
||||
#define ESP_LOGD(...)
|
||||
#endif
|
||||
#endif // ! LINUX_TARGET
|
||||
|
||||
class NVSHandleEntry : public intrusive_list_node<NVSHandleEntry> {
|
||||
public:
|
||||
@@ -56,9 +56,9 @@ uint32_t NVSHandleEntry::s_nvs_next_handle;
|
||||
|
||||
extern "C" void nvs_dump(const char *partName);
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
#ifndef LINUX_TARGET
|
||||
SemaphoreHandle_t nvs::Lock::mSemaphore = nullptr;
|
||||
#endif
|
||||
#endif // ! LINUX_TARGET
|
||||
|
||||
using namespace std;
|
||||
using namespace nvs;
|
||||
@@ -125,7 +125,7 @@ extern "C" esp_err_t nvs_flash_init_partition_ptr(const esp_partition_t *partiti
|
||||
return init_res;
|
||||
}
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
#ifndef LINUX_TARGET
|
||||
extern "C" esp_err_t nvs_flash_init_partition(const char *part_name)
|
||||
{
|
||||
Lock::init();
|
||||
@@ -204,7 +204,7 @@ extern "C" esp_err_t nvs_flash_erase(void)
|
||||
{
|
||||
return nvs_flash_erase_partition(NVS_DEFAULT_PART_NAME);
|
||||
}
|
||||
#endif // ESP_PLATFORM
|
||||
#endif // ! LINUX_TARGET
|
||||
|
||||
extern "C" esp_err_t nvs_flash_deinit_partition(const char* partition_name)
|
||||
{
|
||||
@@ -528,7 +528,7 @@ extern "C" esp_err_t nvs_get_used_entry_count(nvs_handle_t c_handle, size_t* use
|
||||
return err;
|
||||
}
|
||||
|
||||
#if (defined CONFIG_NVS_ENCRYPTION) && (defined ESP_PLATFORM)
|
||||
#if (defined CONFIG_NVS_ENCRYPTION) && (!defined LINUX_TARGET)
|
||||
|
||||
extern "C" esp_err_t nvs_flash_generate_keys(const esp_partition_t* partition, nvs_sec_cfg_t* cfg)
|
||||
{
|
||||
|
@@ -12,10 +12,10 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "nvs_page.hpp"
|
||||
#if defined(ESP_PLATFORM)
|
||||
#include <esp32/rom/crc.h>
|
||||
#else
|
||||
#if defined(LINUX_TARGET)
|
||||
#include "crc.h"
|
||||
#else
|
||||
#include <esp_rom_crc.h>
|
||||
#endif
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
@@ -27,7 +27,7 @@ Page::Page() : mPartition(nullptr) { }
|
||||
|
||||
uint32_t Page::Header::calculateCrc32()
|
||||
{
|
||||
return crc32_le(0xffffffff,
|
||||
return esp_rom_crc32_le(0xffffffff,
|
||||
reinterpret_cast<uint8_t*>(this) + offsetof(Header, mSeqNumber),
|
||||
offsetof(Header, mCrc32) - offsetof(Header, mSeqNumber));
|
||||
}
|
||||
@@ -137,7 +137,7 @@ esp_err_t Page::writeEntryData(const uint8_t* data, size_t size)
|
||||
|
||||
const uint8_t* buf = data;
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
#if !defined LINUX_TARGET
|
||||
// TODO: check whether still necessary with esp_partition* API
|
||||
/* On the ESP32, data can come from DROM, which is not accessible by spi_flash_write
|
||||
* function. To work around this, we copy the data to heap if it came from DROM.
|
||||
@@ -153,15 +153,15 @@ esp_err_t Page::writeEntryData(const uint8_t* data, size_t size)
|
||||
}
|
||||
memcpy((void*)buf, data, size);
|
||||
}
|
||||
#endif //ESP_PLATFORM
|
||||
#endif // ! LINUX_TARGET
|
||||
|
||||
auto rc = mPartition->write(getEntryAddress(mNextFreeEntry), buf, size);
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
#if !defined LINUX_TARGET
|
||||
if (buf != data) {
|
||||
free((void*)buf);
|
||||
}
|
||||
#endif //ESP_PLATFORM
|
||||
#endif // ! LINUX_TARGET
|
||||
if (rc != ESP_OK) {
|
||||
mState = PageState::INVALID;
|
||||
return rc;
|
||||
@@ -968,7 +968,7 @@ size_t Page::getVarDataTailroom() const
|
||||
} else if (mState == PageState::FULL) {
|
||||
return 0;
|
||||
}
|
||||
/* Skip one entry for header*/
|
||||
/* Skip one entry for blob data item precessing the data */
|
||||
return ((mNextFreeEntry < (ENTRY_COUNT-1)) ? ((ENTRY_COUNT - mNextFreeEntry - 1) * ENTRY_SIZE): 0);
|
||||
}
|
||||
|
||||
|
@@ -224,6 +224,9 @@ protected:
|
||||
uint16_t mUsedEntryCount = 0;
|
||||
uint16_t mErasedEntryCount = 0;
|
||||
|
||||
/**
|
||||
* This hash list stores hashes of namespace index, key, and ChunkIndex for quick lookup when searching items.
|
||||
*/
|
||||
HashList mHashList;
|
||||
|
||||
Partition *mPartition;
|
||||
|
@@ -12,7 +12,7 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "string.h"
|
||||
#include <cstdlib>
|
||||
#include "nvs_partition.hpp"
|
||||
|
||||
namespace nvs {
|
||||
@@ -22,7 +22,7 @@ NVSPartition::NVSPartition(const esp_partition_t* partition)
|
||||
{
|
||||
// ensure the class is in a valid state
|
||||
if (partition == nullptr) {
|
||||
abort();
|
||||
std::abort();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -11,11 +11,23 @@
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#ifndef nvs_platform_h
|
||||
#define nvs_platform_h
|
||||
#pragma once
|
||||
|
||||
#ifdef LINUX_TARGET
|
||||
namespace nvs
|
||||
{
|
||||
class Lock
|
||||
{
|
||||
public:
|
||||
Lock() { }
|
||||
~Lock() { }
|
||||
static void init() {}
|
||||
static void uninit() {}
|
||||
};
|
||||
} // namespace nvs
|
||||
|
||||
#else // LINUX_TARGET
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
|
||||
@@ -63,19 +75,4 @@ public:
|
||||
};
|
||||
} // namespace nvs
|
||||
|
||||
#else // ESP_PLATFORM
|
||||
namespace nvs
|
||||
{
|
||||
class Lock
|
||||
{
|
||||
public:
|
||||
Lock() { }
|
||||
~Lock() { }
|
||||
static void init() {}
|
||||
static void uninit() {}
|
||||
};
|
||||
} // namespace nvs
|
||||
#endif // ESP_PLATFORM
|
||||
|
||||
|
||||
#endif /* nvs_platform_h */
|
||||
#endif // LINUX_TARGET
|
||||
|
@@ -14,9 +14,15 @@
|
||||
#include "nvs_storage.hpp"
|
||||
|
||||
#ifndef ESP_PLATFORM
|
||||
// We need NO_DEBUG_STORAGE here since the integration tests on the host add some debug code.
|
||||
// The unit tests, however, don't want debug code since they check the behavior via data in/output and disturb
|
||||
// the order of calling mocked functions.
|
||||
#ifndef NO_DEBUG_STORAGE
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#define DEBUG_STORAGE
|
||||
#endif
|
||||
#endif // !ESP_PLATFORM
|
||||
|
||||
namespace nvs
|
||||
{
|
||||
@@ -136,7 +142,7 @@ esp_err_t Storage::init(uint32_t baseSector, uint32_t sectorCount)
|
||||
// Purge the blob index list
|
||||
blobIdxList.clearAndFreeNodes();
|
||||
|
||||
#ifndef ESP_PLATFORM
|
||||
#ifdef DEBUG_STORAGE
|
||||
debugCheck();
|
||||
#endif
|
||||
return ESP_OK;
|
||||
@@ -165,7 +171,7 @@ esp_err_t Storage::writeMultiPageBlob(uint8_t nsIndex, const char* key, const vo
|
||||
uint8_t chunkCount = 0;
|
||||
TUsedPageList usedPages;
|
||||
size_t remainingSize = dataSize;
|
||||
size_t offset=0;
|
||||
size_t offset = 0;
|
||||
esp_err_t err = ESP_OK;
|
||||
|
||||
/* Check how much maximum data can be accommodated**/
|
||||
@@ -182,8 +188,8 @@ esp_err_t Storage::writeMultiPageBlob(uint8_t nsIndex, const char* key, const vo
|
||||
do {
|
||||
Page& page = getCurrentPage();
|
||||
size_t tailroom = page.getVarDataTailroom();
|
||||
size_t chunkSize =0;
|
||||
if (!chunkCount && tailroom < dataSize && tailroom < Page::CHUNK_MAX_SIZE/10) {
|
||||
size_t chunkSize = 0;
|
||||
if (chunkCount == 0U && ((tailroom < dataSize) || (tailroom == 0 && dataSize == 0)) && tailroom < Page::CHUNK_MAX_SIZE/10) {
|
||||
/** This is the first chunk and tailroom is too small ***/
|
||||
if (page.state() != Page::PageState::FULL) {
|
||||
err = page.markFull();
|
||||
@@ -206,7 +212,7 @@ esp_err_t Storage::writeMultiPageBlob(uint8_t nsIndex, const char* key, const vo
|
||||
}
|
||||
|
||||
/* Split the blob into two and store the chunk of available size onto the current page */
|
||||
assert(tailroom!=0);
|
||||
assert(tailroom != 0);
|
||||
chunkSize = (remainingSize > tailroom)? tailroom : remainingSize;
|
||||
remainingSize -= chunkSize;
|
||||
|
||||
@@ -383,7 +389,7 @@ esp_err_t Storage::writeItem(uint8_t nsIndex, ItemType datatype, const char* key
|
||||
return err;
|
||||
}
|
||||
}
|
||||
#ifndef ESP_PLATFORM
|
||||
#ifdef DEBUG_STORAGE
|
||||
debugCheck();
|
||||
#endif
|
||||
return ESP_OK;
|
||||
@@ -666,7 +672,7 @@ void Storage::debugDump()
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef ESP_PLATFORM
|
||||
#ifdef DEBUG_STORAGE
|
||||
void Storage::debugCheck()
|
||||
{
|
||||
std::map<std::string, Page*> keys;
|
||||
@@ -691,7 +697,7 @@ void Storage::debugCheck()
|
||||
assert(usedCount == p->getUsedEntryCount());
|
||||
}
|
||||
}
|
||||
#endif //ESP_PLATFORM
|
||||
#endif //DEBUG_STORAGE
|
||||
|
||||
esp_err_t Storage::fillStats(nvs_stats_t& nvsStats)
|
||||
{
|
||||
|
@@ -13,10 +13,10 @@
|
||||
// limitations under the License.
|
||||
#include "nvs_types.hpp"
|
||||
|
||||
#if defined(ESP_PLATFORM)
|
||||
#include <esp32/rom/crc.h>
|
||||
#else
|
||||
#if defined(LINUX_TARGET)
|
||||
#include "crc.h"
|
||||
#else
|
||||
#include <esp_rom_crc.h>
|
||||
#endif
|
||||
|
||||
namespace nvs
|
||||
@@ -25,10 +25,10 @@ uint32_t Item::calculateCrc32() const
|
||||
{
|
||||
uint32_t result = 0xffffffff;
|
||||
const uint8_t* p = reinterpret_cast<const uint8_t*>(this);
|
||||
result = crc32_le(result, p + offsetof(Item, nsIndex),
|
||||
result = esp_rom_crc32_le(result, p + offsetof(Item, nsIndex),
|
||||
offsetof(Item, crc32) - offsetof(Item, nsIndex));
|
||||
result = crc32_le(result, p + offsetof(Item, key), sizeof(key));
|
||||
result = crc32_le(result, p + offsetof(Item, data), sizeof(data));
|
||||
result = esp_rom_crc32_le(result, p + offsetof(Item, key), sizeof(key));
|
||||
result = esp_rom_crc32_le(result, p + offsetof(Item, data), sizeof(data));
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -36,17 +36,17 @@ uint32_t Item::calculateCrc32WithoutValue() const
|
||||
{
|
||||
uint32_t result = 0xffffffff;
|
||||
const uint8_t* p = reinterpret_cast<const uint8_t*>(this);
|
||||
result = crc32_le(result, p + offsetof(Item, nsIndex),
|
||||
result = esp_rom_crc32_le(result, p + offsetof(Item, nsIndex),
|
||||
offsetof(Item, datatype) - offsetof(Item, nsIndex));
|
||||
result = crc32_le(result, p + offsetof(Item, key), sizeof(key));
|
||||
result = crc32_le(result, p + offsetof(Item, chunkIndex), sizeof(chunkIndex));
|
||||
result = esp_rom_crc32_le(result, p + offsetof(Item, key), sizeof(key));
|
||||
result = esp_rom_crc32_le(result, p + offsetof(Item, chunkIndex), sizeof(chunkIndex));
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t Item::calculateCrc32(const uint8_t* data, size_t size)
|
||||
{
|
||||
uint32_t result = 0xffffffff;
|
||||
result = crc32_le(result, data, size);
|
||||
result = esp_rom_crc32_le(result, data, size);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@@ -3,6 +3,7 @@ all: $(TEST_PROGRAM)
|
||||
|
||||
SOURCE_FILES = \
|
||||
esp_error_check_stub.cpp \
|
||||
../mock/int/crc.cpp \
|
||||
$(addprefix ../src/, \
|
||||
nvs_types.cpp \
|
||||
nvs_api.cpp \
|
||||
@@ -28,7 +29,6 @@ SOURCE_FILES = \
|
||||
test_nvs_partition.cpp \
|
||||
test_nvs_cxx_api.cpp \
|
||||
test_nvs_initialization.cpp \
|
||||
crc.cpp \
|
||||
main.cpp
|
||||
|
||||
ifeq ($(shell $(CC) -v 2>&1 | grep -c "clang version"), 1)
|
||||
@@ -37,9 +37,9 @@ else
|
||||
COMPILER := gcc
|
||||
endif
|
||||
|
||||
CPPFLAGS += -I../include -I../src -I./ -I../../esp_common/include -I../../esp32/include -I ../../mbedtls/mbedtls/include -I ../../spi_flash/include -I ../../hal/include -I ../../xtensa/include -I ../../../tools/catch -fprofile-arcs -ftest-coverage -g2 -ggdb
|
||||
CFLAGS += -fprofile-arcs -ftest-coverage
|
||||
CXXFLAGS += -std=c++11 -Wall -Werror
|
||||
CPPFLAGS += -I../include -I../src -I../mock/int -I./ -I../../esp_common/include -I../../esp32/include -I ../../mbedtls/mbedtls/include -I ../../spi_flash/include -I ../../hal/include -I ../../xtensa/include -I ../../../tools/catch -fprofile-arcs -ftest-coverage -g2 -ggdb
|
||||
CFLAGS += -fprofile-arcs -ftest-coverage -DLINUX_TARGET
|
||||
CXXFLAGS += -std=c++11 -Wall -Werror -DLINUX_TARGET
|
||||
LDFLAGS += -lstdc++ -Wall -fprofile-arcs -ftest-coverage
|
||||
|
||||
ifeq ($(COMPILER),clang)
|
||||
|
@@ -1,7 +1,6 @@
|
||||
idf_build_get_property(spi_flash_mock CONFIG_SPI_FLASH_MOCK)
|
||||
idf_build_get_property(target IDF_TARGET)
|
||||
if(${spi_flash_mock})
|
||||
|
||||
message(STATUS "building SPI FLASH MOCKS")
|
||||
|
||||
set(IDF_PATH $ENV{IDF_PATH})
|
||||
@@ -41,13 +40,20 @@ if(${spi_flash_mock})
|
||||
INCLUDE_DIRS ${include_dirs}
|
||||
REQUIRES cmock)
|
||||
|
||||
add_custom_command(
|
||||
OUTPUT ruby_found SYMBOLIC
|
||||
COMMAND "ruby" "-v"
|
||||
COMMENT "Try to find ruby. If this fails, you need to install ruby"
|
||||
)
|
||||
|
||||
# This command builds the mocks.
|
||||
# First, environment variable UNITY_DIR is set. This is necessary to prevent unity from looking in its own submodule
|
||||
# which doesn't work in our CI yet...
|
||||
# The rest is a straight forward call to cmock.rb, consult cmock's documentation for more information.
|
||||
add_custom_command(
|
||||
OUTPUT ${MOCK_OUTPUT}
|
||||
COMMAND ${CMAKE_COMMAND} -E env "UNITY_DIR=${IDF_PATH}/components/unity/unity"
|
||||
OUTPUT ${MOCK_OUTPUT}
|
||||
DEPENDS ruby_found
|
||||
COMMAND ${CMAKE_COMMAND} -E env "UNITY_DIR=${IDF_PATH}/components/unity/unity"
|
||||
ruby
|
||||
${CMOCK_DIR}/lib/cmock.rb
|
||||
-o${CMAKE_CURRENT_SOURCE_DIR}/mock/mock_config.yaml
|
||||
|
@@ -63,4 +63,3 @@ const spi_flash_counters_t* spi_flash_get_counters(void);
|
||||
#endif
|
||||
|
||||
#endif //CONFIG_SPI_FLASH_ENABLE_COUNTERS
|
||||
|
||||
|
Reference in New Issue
Block a user