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:
Ivan Grokhotkov
2017-05-31 12:59:24 +08:00
parent d718cbd873
commit a25a4a0a7c
5 changed files with 70 additions and 19 deletions
+46 -10
View File
@@ -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