nvs: check value size before writing, document limitations
Writing values longer than half of the page size (with header taken into account) causes fragmentation issues. Previously it was suggested on the forum that using long values may cause issues, but this wasn’t checked in the library itself, and wasn’t documented. This change adds necessary checks and introduces the new error code. Documentation is also fixed to reflect the fact that the maximum length of the key is 15 characters, not 16.
This commit is contained in:
@@ -231,6 +231,34 @@ TEST_CASE("different key names are distinguished even if the pointer is the same
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("Page validates key size", "[nvs]")
|
||||
{
|
||||
SpiFlashEmulator emu(4);
|
||||
Page page;
|
||||
TEST_ESP_OK(page.load(0));
|
||||
// 16-character key fails
|
||||
TEST_ESP_ERR(page.writeItem(1, "0123456789123456", 1), ESP_ERR_NVS_KEY_TOO_LONG);
|
||||
// 15-character key is okay
|
||||
TEST_ESP_OK(page.writeItem(1, "012345678912345", 1));
|
||||
}
|
||||
|
||||
TEST_CASE("Page validates blob size", "[nvs]")
|
||||
{
|
||||
SpiFlashEmulator emu(4);
|
||||
Page page;
|
||||
TEST_ESP_OK(page.load(0));
|
||||
|
||||
char buf[2048] = { 0 };
|
||||
// There are two potential errors here:
|
||||
// - not enough space in the page (because one value has been written already)
|
||||
// - value is too long
|
||||
// Check that the second one is actually returned.
|
||||
TEST_ESP_ERR(page.writeItem(1, ItemType::BLOB, "2", buf, Page::ENTRY_COUNT * Page::ENTRY_SIZE), ESP_ERR_NVS_VALUE_TOO_LONG);
|
||||
// Should fail as well
|
||||
TEST_ESP_ERR(page.writeItem(1, ItemType::BLOB, "2", buf, Page::BLOB_MAX_SIZE + 1), ESP_ERR_NVS_VALUE_TOO_LONG);
|
||||
TEST_ESP_OK(page.writeItem(1, ItemType::BLOB, "2", buf, Page::BLOB_MAX_SIZE));
|
||||
}
|
||||
|
||||
TEST_CASE("can init PageManager in empty flash", "[nvs]")
|
||||
{
|
||||
SpiFlashEmulator emu(4);
|
||||
@@ -327,17 +355,19 @@ TEST_CASE("storage can find items on second page if first is not fully written a
|
||||
Storage storage;
|
||||
CHECK(storage.init(0, 3) == ESP_OK);
|
||||
int bar = 0;
|
||||
uint8_t bigdata[100 * 32] = {0};
|
||||
uint8_t bigdata[Page::BLOB_MAX_SIZE] = {0};
|
||||
// write one big chunk of data
|
||||
ESP_ERROR_CHECK(storage.writeItem(0, ItemType::BLOB, "first", bigdata, sizeof(bigdata)));
|
||||
ESP_ERROR_CHECK(storage.writeItem(0, ItemType::BLOB, "1", bigdata, sizeof(bigdata)));
|
||||
// write another big chunk of data
|
||||
ESP_ERROR_CHECK(storage.writeItem(0, ItemType::BLOB, "2", bigdata, sizeof(bigdata)));
|
||||
|
||||
// write second one; it will not fit into the first page
|
||||
ESP_ERROR_CHECK(storage.writeItem(0, ItemType::BLOB, "second", bigdata, sizeof(bigdata)));
|
||||
// write third one; it will not fit into the first page
|
||||
ESP_ERROR_CHECK(storage.writeItem(0, ItemType::BLOB, "3", bigdata, sizeof(bigdata)));
|
||||
|
||||
size_t size;
|
||||
ESP_ERROR_CHECK(storage.getItemDataSize(0, ItemType::BLOB, "first", size));
|
||||
ESP_ERROR_CHECK(storage.getItemDataSize(0, ItemType::BLOB, "1", size));
|
||||
CHECK(size == sizeof(bigdata));
|
||||
ESP_ERROR_CHECK(storage.getItemDataSize(0, ItemType::BLOB, "second", size));
|
||||
ESP_ERROR_CHECK(storage.getItemDataSize(0, ItemType::BLOB, "3", size));
|
||||
CHECK(size == sizeof(bigdata));
|
||||
}
|
||||
|
||||
@@ -1128,15 +1158,21 @@ TEST_CASE("read/write failure (TW8406)", "[nvs]")
|
||||
|
||||
TEST_CASE("nvs_flash_init checks for an empty page", "[nvs]")
|
||||
{
|
||||
const size_t blob_size = 2048; // big enough so that only one can fit into a page
|
||||
const size_t blob_size = Page::BLOB_MAX_SIZE;
|
||||
uint8_t blob[blob_size] = {0};
|
||||
SpiFlashEmulator emu(5);
|
||||
TEST_ESP_OK( nvs_flash_init_custom(0, 5) );
|
||||
nvs_handle handle;
|
||||
TEST_ESP_OK( nvs_open("test", NVS_READWRITE, &handle) );
|
||||
TEST_ESP_OK( nvs_set_blob(handle, "1", blob, blob_size) );
|
||||
TEST_ESP_OK( nvs_set_blob(handle, "2", blob, blob_size) );
|
||||
TEST_ESP_OK( nvs_set_blob(handle, "3", blob, blob_size) );
|
||||
// Fill first page
|
||||
TEST_ESP_OK( nvs_set_blob(handle, "1a", blob, blob_size) );
|
||||
TEST_ESP_OK( nvs_set_blob(handle, "1b", blob, blob_size) );
|
||||
// Fill second page
|
||||
TEST_ESP_OK( nvs_set_blob(handle, "2a", blob, blob_size) );
|
||||
TEST_ESP_OK( nvs_set_blob(handle, "2b", blob, blob_size) );
|
||||
// Fill third page
|
||||
TEST_ESP_OK( nvs_set_blob(handle, "3a", blob, blob_size) );
|
||||
TEST_ESP_OK( nvs_set_blob(handle, "3b", blob, blob_size) );
|
||||
TEST_ESP_OK( nvs_commit(handle) );
|
||||
nvs_close(handle);
|
||||
// first two pages are now full, third one is writable, last two are empty
|
||||
|
||||
Reference in New Issue
Block a user