Skip to content

Commit f00bddb

Browse files
committed
feat(nvs_flash): Update nvs_flash from esp-idf
MR !14548.
1 parent d11de77 commit f00bddb

File tree

6 files changed

+115
-30
lines changed

6 files changed

+115
-30
lines changed

Diff for: components/nvs_flash/host_test/fixtures/test_fixtures.hpp

+16-9
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ class PartitionMock : public nvs::Partition {
5252

5353
esp_err_t read_raw(size_t src_offset, void* dst, size_t size) override
5454
{
55-
return esp_partition_read(&partition, src_offset, dst, size);
55+
return esp_partition_read_raw(&partition, src_offset, dst, size);
5656
}
5757

5858
esp_err_t read(size_t src_offset, void* dst, size_t size) override
@@ -62,7 +62,7 @@ class PartitionMock : public nvs::Partition {
6262

6363
esp_err_t write_raw(size_t dst_offset, const void* src, size_t size) override
6464
{
65-
return esp_partition_write(&partition, dst_offset, src, size);
65+
return esp_partition_write_raw(&partition, dst_offset, src, size);
6666
}
6767

6868
esp_err_t write(size_t dst_offset, const void* src, size_t size) override
@@ -122,6 +122,9 @@ struct PartitionMockFixture {
122122
const char *partition_name = NVS_DEFAULT_PART_NAME)
123123
: part_mock(start_sector * SPI_FLASH_SEC_SIZE, sector_size * SPI_FLASH_SEC_SIZE) {
124124
std::fill_n(raw_header, sizeof(raw_header)/sizeof(raw_header[0]), UINT8_MAX);
125+
126+
// This resets the mocks and prevents meeting accidental expectations from previous tests.
127+
Mockesp_partition_Init();
125128
}
126129

127130
~PartitionMockFixture() { }
@@ -151,7 +154,7 @@ struct NVSPageFixture : public PartitionMockFixture {
151154
nvs::Page page;
152155
};
153156

154-
struct NVSValidPageFixture : public PartitionMockFixture {
157+
struct NVSValidPageFlashFixture : public PartitionMockFixture {
155158
const static uint8_t NS_INDEX = 1;
156159

157160
// valid header
@@ -164,7 +167,7 @@ struct NVSValidPageFixture : public PartitionMockFixture {
164167

165168
uint8_t value_entry [32];
166169

167-
NVSValidPageFixture(uint32_t start_sector = 0,
170+
NVSValidPageFlashFixture(uint32_t start_sector = 0,
168171
uint32_t sector_size = 1,
169172
const char *partition_name = NVS_DEFAULT_PART_NAME)
170173
: PartitionMockFixture(start_sector, sector_size, partition_name),
@@ -173,8 +176,7 @@ struct NVSValidPageFixture : public PartitionMockFixture {
173176
ns_entry {0x00, 0x01, 0x01, 0xff, 0x68, 0xc5, 0x3f, 0x0b, 't', 'e', 's', 't', '_', 'n', 's', '\0',
174177
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', 1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
175178
value_entry {0x01, 0x01, 0x01, 0xff, 0x3d, 0xf3, 0x99, 0xe5, 't', 'e', 's', 't', '_', 'v', 'a', 'l',
176-
'u', 'e', '\0', '\0', '\0', '\0', '\0', '\0', 47, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
177-
page()
179+
'u', 'e', '\0', '\0', '\0', '\0', '\0', '\0', 47, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
178180
{
179181
std::fill_n(raw_entry_table, sizeof(raw_entry_table)/sizeof(raw_entry_table[0]), 0);
180182
raw_entry_table[0] = 0xfa;
@@ -202,7 +204,15 @@ struct NVSValidPageFixture : public PartitionMockFixture {
202204
// read normal entry second time during duplicated entry check
203205
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
204206
esp_partition_read_ReturnArrayThruPtr_dst(value_entry, 32);
207+
}
208+
};
205209

210+
struct NVSValidPageFixture : public NVSValidPageFlashFixture {
211+
NVSValidPageFixture(uint32_t start_sector = 0,
212+
uint32_t sector_size = 1,
213+
const char *partition_name = NVS_DEFAULT_PART_NAME)
214+
: NVSValidPageFlashFixture(start_sector, sector_size, partition_name), page()
215+
{
206216
if (page.load(&part_mock, start_sector) != ESP_OK) throw FixtureException("couldn't setup page");
207217
}
208218

@@ -392,9 +402,6 @@ struct NVSFullPageFixture : public PartitionMockFixture {
392402
'u', 'e', '\0', '\0', '\0', '\0', '\0', '\0', 47, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
393403
page()
394404
{
395-
std::fill_n(raw_entry_table, sizeof(raw_entry_table)/sizeof(raw_entry_table[0]), 0);
396-
raw_entry_table[0] = 0xfa;
397-
398405
// entry_table with all elements deleted except the namespace entry written and the last entry free
399406
std::fill_n(raw_entry_table, sizeof(raw_entry_table)/sizeof(raw_entry_table[0]), 0);
400407
raw_entry_table[0] = 0x0a;

Diff for: components/nvs_flash/host_test/nvs_page_test/main/nvs_page_test.cpp

+76-10
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
1-
/* Hello World Example
2-
3-
This example code is in the Public Domain (or CC0 licensed, at your option.)
4-
5-
Unless required by applicable law or agreed to in writing, this
6-
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
7-
CONDITIONS OF ANY KIND, either express or implied.
8-
*/
1+
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
914
#include <stdio.h>
1015
#include "unity.h"
1116
#include "test_fixtures.hpp"
@@ -25,6 +30,8 @@ void test_Page_load_reading_header_fails()
2530

2631
TEST_ASSERT_EQUAL(Page::PageState::INVALID, page.state());
2732
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, page.load(&mock, 0));
33+
34+
Mockesp_partition_Verify();
2835
}
2936

3037
void test_Page_load_reading_data_fails()
@@ -39,6 +46,8 @@ void test_Page_load_reading_data_fails()
3946

4047
TEST_ASSERT_EQUAL(Page::PageState::INVALID, page.state());
4148
TEST_ASSERT_EQUAL(ESP_FAIL, page.load(&mock, 0));
49+
50+
Mockesp_partition_Verify();
4251
}
4352

4453
void test_Page_load__uninitialized_page_has_0xfe()
@@ -57,6 +66,8 @@ void test_Page_load__uninitialized_page_has_0xfe()
5766
TEST_ASSERT_EQUAL(ESP_OK, page.load(&fix.part_mock, 0));
5867

5968
TEST_ASSERT_EQUAL(Page::PageState::CORRUPT, page.state());
69+
70+
Mockesp_partition_Verify();
6071
}
6172

6273
void test_Page_load__initialized_corrupt_header()
@@ -74,6 +85,60 @@ void test_Page_load__initialized_corrupt_header()
7485
TEST_ASSERT_EQUAL(ESP_OK, page.load(&fix.part_mock, 0));
7586

7687
TEST_ASSERT_EQUAL(Page::PageState::CORRUPT, page.state());
88+
89+
Mockesp_partition_Verify();
90+
}
91+
92+
void test_Page_load__corrupt_entry_table()
93+
{
94+
PartitionMockFixture fix;
95+
96+
// valid header
97+
uint8_t raw_header_valid [32] = {0xfe, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
98+
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc2, 0x16, 0xdd, 0xdc};
99+
100+
// entry table with one entry
101+
uint8_t raw_entry_table [32];
102+
103+
uint8_t ns_entry [32] = {0x00, 0x01, 0x01, 0xff, 0x68, 0xc5, 0x3f, 0x0b, 't', 'e', 's', 't', '_', 'n', 's', '\0',
104+
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', 1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
105+
106+
uint8_t raw_header[4] = {0xff, 0xff, 0xff, 0xff};
107+
std::fill_n(raw_entry_table, sizeof(raw_entry_table)/sizeof(raw_entry_table[0]), 0);
108+
raw_entry_table[0] = 0xfa;
109+
110+
// read page header
111+
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
112+
esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_header_valid, 32);
113+
114+
// read entry table
115+
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
116+
esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_entry_table, 32);
117+
118+
// read next free entry's header
119+
esp_partition_read_raw_ExpectAnyArgsAndReturn(ESP_OK);
120+
esp_partition_read_raw_ReturnArrayThruPtr_dst(raw_header, 4);
121+
122+
// read namespace entry
123+
esp_partition_read_ExpectAnyArgsAndReturn(ESP_OK);
124+
esp_partition_read_ReturnArrayThruPtr_dst(ns_entry, 32);
125+
126+
// we expect a raw word write from the partition in order to change the entry bits to erased (0)
127+
esp_partition_write_raw_ExpectAndReturn(&fix.part_mock.partition, 32, nullptr, 4, ESP_OK);
128+
esp_partition_write_raw_IgnoreArg_src();
129+
130+
// corrupt entry table as well as crc of corresponding item
131+
raw_entry_table[0] = 0xf6;
132+
133+
Page page;
134+
135+
// Page::load() should return ESP_OK, but state has to be corrupt
136+
TEST_ASSERT_EQUAL(ESP_OK, page.load(&fix.part_mock, 0));
137+
138+
TEST_ASSERT_EQUAL(Page::PageState::ACTIVE, page.state());
139+
TEST_ASSERT_EQUAL(1, page.getUsedEntryCount());
140+
141+
Mockesp_partition_Verify();
77142
}
78143

79144
void test_Page_load_success()
@@ -881,6 +946,7 @@ int main(int argc, char **argv)
881946
RUN_TEST(test_Page_load_reading_data_fails);
882947
RUN_TEST(test_Page_load__uninitialized_page_has_0xfe);
883948
RUN_TEST(test_Page_load__initialized_corrupt_header);
949+
RUN_TEST(test_Page_load__corrupt_entry_table);
884950
RUN_TEST(test_Page_load_success);
885951
RUN_TEST(test_Page_load_full_page);
886952
RUN_TEST(test_Page_load__seq_number_0);
@@ -929,6 +995,6 @@ int main(int argc, char **argv)
929995
RUN_TEST(test_Page_calcEntries__active_wo_blob);
930996
RUN_TEST(test_Page_calcEntries__active_with_blob);
931997
RUN_TEST(test_Page_calcEntries__invalid);
932-
UNITY_END();
933-
return 0;
998+
int failures = UNITY_END();
999+
return failures;
9341000
}

Diff for: components/nvs_flash/src/nvs_item_hash_list.cpp

+6-6
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ esp_err_t HashList::insert(const Item& item, size_t index)
6565
return ESP_OK;
6666
}
6767

68-
void HashList::erase(size_t index, bool itemShouldExist)
68+
bool HashList::erase(size_t index)
6969
{
7070
for (auto it = mBlockList.begin(); it != mBlockList.end();) {
7171
bool haveEntries = false;
@@ -81,7 +81,7 @@ void HashList::erase(size_t index, bool itemShouldExist)
8181
}
8282
if (haveEntries && foundIndex) {
8383
/* item was found, and HashListBlock still has some items */
84-
return;
84+
return true;
8585
}
8686
}
8787
/* no items left in HashListBlock, can remove */
@@ -95,12 +95,12 @@ void HashList::erase(size_t index, bool itemShouldExist)
9595
}
9696
if (foundIndex) {
9797
/* item was found and empty HashListBlock was removed */
98-
return;
98+
return true;
9999
}
100100
}
101-
if (itemShouldExist) {
102-
assert(false && "item should have been present in cache");
103-
}
101+
102+
// item hasn't been present in cache");
103+
return false;
104104
}
105105

106106
size_t HashList::find(size_t start, const Item& item)

Diff for: components/nvs_flash/src/nvs_item_hash_list.hpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class HashList
2929
~HashList();
3030

3131
esp_err_t insert(const Item& item, size_t index);
32-
void erase(const size_t index, bool itemShouldExist=true);
32+
bool erase(const size_t index);
3333
size_t find(size_t start, const Item& item);
3434
void clear();
3535

Diff for: components/nvs_flash/src/nvs_page.cpp

+13-2
Original file line numberDiff line numberDiff line change
@@ -393,8 +393,9 @@ esp_err_t Page::findItem(uint8_t nsIndex, ItemType datatype, const char* key, ui
393393

394394
esp_err_t Page::eraseEntryAndSpan(size_t index)
395395
{
396+
uint32_t seq_num;
397+
getSeqNumber(seq_num);
396398
auto state = mEntryTable.get(index);
397-
assert(state == EntryState::WRITTEN || state == EntryState::EMPTY);
398399

399400
size_t span = 1;
400401
if (state == EntryState::WRITTEN) {
@@ -404,7 +405,7 @@ esp_err_t Page::eraseEntryAndSpan(size_t index)
404405
return rc;
405406
}
406407
if (item.calculateCrc32() != item.crc32) {
407-
mHashList.erase(index, false);
408+
mHashList.erase(index);
408409
rc = alterEntryState(index, EntryState::ERASED);
409410
--mUsedEntryCount;
410411
++mErasedEntryCount;
@@ -601,6 +602,16 @@ esp_err_t Page::mLoadEntryTable()
601602
continue;
602603
}
603604

605+
if (mEntryTable.get(i) == static_cast<EntryState>(0x1)) {
606+
lastItemIndex = INVALID_ENTRY;
607+
auto err = eraseEntryAndSpan(i);
608+
if (err != ESP_OK) {
609+
mState = PageState::INVALID;
610+
return err;
611+
}
612+
continue;
613+
}
614+
604615
lastItemIndex = i;
605616

606617
auto err = readEntry(i, item);

Diff for: components/nvs_flash/test_nvs_host/test_nvs.cpp

+3-2
Original file line numberDiff line numberDiff line change
@@ -313,7 +313,8 @@ TEST_CASE("HashList is cleaned up as soon as items are erased", "[nvs]")
313313
INFO("Added " << count << " items, " << hashlist.getBlockCount() << " blocks");
314314
// Remove them in reverse order
315315
for (size_t i = count; i > 0; --i) {
316-
hashlist.erase(i - 1, true);
316+
// Make sure that the element existed before it's erased
317+
CHECK(hashlist.erase(i - 1) == true);
317318
}
318319
CHECK(hashlist.getBlockCount() == 0);
319320
// Add again
@@ -326,7 +327,7 @@ TEST_CASE("HashList is cleaned up as soon as items are erased", "[nvs]")
326327
INFO("Added " << count << " items, " << hashlist.getBlockCount() << " blocks");
327328
// Remove them in the same order
328329
for (size_t i = 0; i < count; ++i) {
329-
hashlist.erase(i, true);
330+
CHECK(hashlist.erase(i) == true);
330331
}
331332
CHECK(hashlist.getBlockCount() == 0);
332333
}

0 commit comments

Comments
 (0)