Users needs functions to count the number of free and used entries.
1. `nvs_get_stats()` This function return structure of statistic about the uspace NVS.
(Struct: used_entries, free_entries, total_entries and namespace_count)
2. `nvs_get_used_entry_count()` The second function return amount of entries in the namespace (by handler)
3. Added unit tests.
Closes TW<12282>
*/
void nvs_close(nvs_handle handle);
+/**
+ * @note Info about storage space NVS.
+ */
+typedef struct {
+ size_t used_entries; /**< Amount of used entries. */
+ size_t free_entries; /**< Amount of free entries. */
+ size_t total_entries; /**< Amount all available entries. */
+ size_t namespace_count; /**< Amount name space. */
+} nvs_stats_t;
+
+/**
+ * @brief Fill structure nvs_stats_t. It provides info about used memory the partition.
+ *
+ * This function calculates to runtime the number of used entries, free entries, total entries,
+ * and amount namespace in partition.
+ *
+ * \code{c}
+ * // Example of nvs_get_stats() to get the number of used entries and free entries:
+ * nvs_stats_t nvs_stats;
+ * nvs_get_stats(NULL, &nvs_stats);
+ * printf("Count: UsedEntries = (%d), FreeEntries = (%d), AllEntries = (%d)\n",
+ nvs_stats.used_entries, nvs_stats.free_entries, nvs_stats.total_entries);
+ * \endcode
+ *
+ * @param[in] part_name Partition name NVS in the partition table.
+ * If pass a NULL than will use NVS_DEFAULT_PART_NAME ("nvs").
+ *
+ * @param[out] nvs_stats Returns filled structure nvs_states_t.
+ * It provides info about used memory the partition.
+ *
+ *
+ * @return
+ * - ESP_OK if the changes have been written successfully.
+ * Return param nvs_stats will be filled.
+ * - ESP_ERR_NVS_PART_NOT_FOUND if the partition with label "name" is not found.
+ * Return param nvs_stats will be filled 0.
+ * - ESP_ERR_NVS_NOT_INITIALIZED if the storage driver is not initialized.
+ * Return param nvs_stats will be filled 0.
+ * - ESP_ERR_INVALID_ARG if nvs_stats equal to NULL.
+ * - ESP_ERR_INVALID_STATE if there is page with the status of INVALID.
+ * Return param nvs_stats will be filled not with correct values because
+ * not all pages will be counted. Counting will be interrupted at the first INVALID page.
+ */
+esp_err_t nvs_get_stats(const char* part_name, nvs_stats_t* nvs_stats);
+
+/**
+ * @brief Calculate all entries in a namespace.
+ *
+ * Note that to find out the total number of records occupied by the namespace,
+ * add one to the returned value used_entries (if err is equal to ESP_OK).
+ * Because the name space entry takes one entry.
+ *
+ * \code{c}
+ * // Example of nvs_get_used_entry_count() to get amount of all key-value pairs in one namespace:
+ * nvs_handle handle;
+ * nvs_open("namespace1", NVS_READWRITE, &handle);
+ * ...
+ * size_t used_entries;
+ * size_t total_entries_namespace;
+ * if(nvs_get_used_entry_count(handle, &used_entries) == ESP_OK){
+ * // the total number of records occupied by the namespace
+ * total_entries_namespace = used_entries + 1;
+ * }
+ * \endcode
+ *
+ * @param[in] handle Handle obtained from nvs_open function.
+ *
+ * @param[out] used_entries Returns amount of used entries from a namespace.
+ *
+ *
+ * @return
+ * - ESP_OK if the changes have been written successfully.
+ * Return param used_entries will be filled valid value.
+ * - ESP_ERR_NVS_NOT_INITIALIZED if the storage driver is not initialized.
+ * Return param used_entries will be filled 0.
+ * - ESP_ERR_NVS_INVALID_HANDLE if handle has been closed or is NULL.
+ * Return param used_entries will be filled 0.
+ * - ESP_ERR_INVALID_ARG if nvs_stats equal to NULL.
+ * - Other error codes from the underlying storage driver.
+ * Return param used_entries will be filled 0.
+ */
+esp_err_t nvs_get_used_entry_count(nvs_handle handle, size_t* used_entries);
#ifdef __cplusplus
} // extern "C"
return nvs_get_str_or_blob(handle, nvs::ItemType::BLOB, key, out_value, length);
}
+extern "C" esp_err_t nvs_get_stats(const char* part_name, nvs_stats_t* nvs_stats)
+{
+ Lock lock;
+ nvs::Storage* pStorage;
+
+ if (nvs_stats == NULL) {
+ return ESP_ERR_INVALID_ARG;
+ }
+ nvs_stats->used_entries = 0;
+ nvs_stats->free_entries = 0;
+ nvs_stats->total_entries = 0;
+ nvs_stats->namespace_count = 0;
+
+ pStorage = lookup_storage_from_name((part_name == NULL) ? NVS_DEFAULT_PART_NAME : part_name);
+ if (pStorage == NULL) {
+ return ESP_ERR_NVS_PART_NOT_FOUND;
+ }
+
+ if(!pStorage->isValid()){
+ return ESP_ERR_NVS_NOT_INITIALIZED;
+ }
+
+ return pStorage->fillStats(*nvs_stats);
+}
+
+extern "C" esp_err_t nvs_get_used_entry_count(nvs_handle handle, size_t* used_entries)
+{
+ Lock lock;
+ if(used_entries == NULL){
+ return ESP_ERR_INVALID_ARG;
+ }
+ *used_entries = 0;
+
+ HandleEntry entry;
+ auto err = nvs_find_ns_handle(handle, entry);
+ if (err != ESP_OK) {
+ return err;
+ }
+
+ size_t used_entry_count;
+ err = entry.mStoragePtr->calcEntriesInNamespace(entry.mNsIndex, used_entry_count);
+ if(err == ESP_OK){
+ *used_entries = used_entry_count;
+ }
+ return err;
+}
}
}
+esp_err_t Page::calcEntries(nvs_stats_t &nvsStats)
+{
+ assert(mState != PageState::FREEING);
+
+ nvsStats.total_entries += ENTRY_COUNT;
+
+ switch (mState) {
+ case PageState::UNINITIALIZED:
+ case PageState::CORRUPT:
+ nvsStats.free_entries += ENTRY_COUNT;
+ break;
+
+ case PageState::FULL:
+ case PageState::ACTIVE:
+ nvsStats.used_entries += mUsedEntryCount;
+ nvsStats.free_entries += ENTRY_COUNT - mUsedEntryCount; // it's equivalent free + erase entries.
+ break;
+
+ case PageState::INVALID:
+ return ESP_ERR_INVALID_STATE;
+ break;
+
+ default:
+ assert(false && "Unhandled state");
+ break;
+ }
+ return ESP_OK;
+}
+
} // namespace nvs
void debugDump() const;
+ esp_err_t calcEntries(nvs_stats_t &nvsStats);
+
protected:
class Header
return ESP_OK;
}
+esp_err_t PageManager::fillStats(nvs_stats_t& nvsStats)
+{
+ nvsStats.used_entries = 0;
+ nvsStats.free_entries = 0;
+ nvsStats.total_entries = 0;
+ esp_err_t err = ESP_OK;
+
+ // list of used pages
+ for (auto p = mPageList.begin(); p != mPageList.end(); ++p) {
+ err = p->calcEntries(nvsStats);
+ if (err != ESP_OK) {
+ return err;
+ }
+ }
+
+ // free pages
+ nvsStats.total_entries += mFreePageList.size() * Page::ENTRY_COUNT;
+ nvsStats.free_entries += mFreePageList.size() * Page::ENTRY_COUNT;
+
+ return err;
+}
+
} // namespace nvs
esp_err_t requestNewPage();
+ esp_err_t fillStats(nvs_stats_t& nvsStats);
+
protected:
friend class Iterator;
}
#endif //ESP_PLATFORM
+esp_err_t Storage::fillStats(nvs_stats_t& nvsStats)
+{
+ nvsStats.namespace_count = mNamespaces.size();
+ return mPageManager.fillStats(nvsStats);
+}
+
+esp_err_t Storage::calcEntriesInNamespace(uint8_t nsIndex, size_t& usedEntries)
+{
+ usedEntries = 0;
+
+ if (mState != StorageState::ACTIVE) {
+ return ESP_ERR_NVS_NOT_INITIALIZED;
+ }
+
+ for (auto it = std::begin(mPageManager); it != std::end(mPageManager); ++it) {
+ size_t itemIndex = 0;
+ Item item;
+ while (true) {
+ auto err = it->findItem(nsIndex, ItemType::ANY, nullptr, itemIndex, item);
+ if (err == ESP_ERR_NVS_NOT_FOUND) {
+ break;
+ }
+ else if (err != ESP_OK) {
+ return err;
+ }
+ usedEntries += item.span;
+ itemIndex += item.span;
+ if(itemIndex >= it->ENTRY_COUNT) break;
+ }
+ }
+ return ESP_OK;
+}
+
}
void debugCheck();
+ esp_err_t fillStats(nvs_stats_t& nvsStats);
+
+ esp_err_t calcEntriesInNamespace(uint8_t nsIndex, size_t& usedEntries);
protected:
nvs_close(handle_2);
}
+
+TEST_CASE("calculate used and free space", "[nvs]")
+{
+ TEST_ESP_ERR(nvs_get_stats(NULL, NULL), ESP_ERR_INVALID_ARG);
+ nvs_stats_t stat1;
+ nvs_stats_t stat2;
+ TEST_ESP_ERR(nvs_get_stats(NULL, &stat1), ESP_ERR_NVS_PART_NOT_FOUND);
+ TEST_ASSERT_TRUE(stat1.free_entries == 0);
+ TEST_ASSERT_TRUE(stat1.namespace_count == 0);
+ TEST_ASSERT_TRUE(stat1.total_entries == 0);
+ TEST_ASSERT_TRUE(stat1.used_entries == 0);
+
+ nvs_handle handle = 0;
+ size_t h_count_entries;
+ TEST_ESP_ERR(nvs_get_used_entry_count(handle, &h_count_entries), ESP_ERR_NVS_INVALID_HANDLE);
+ TEST_ASSERT_TRUE(h_count_entries == 0);
+
+ esp_err_t err = nvs_flash_init();
+ if (err == ESP_ERR_NVS_NO_FREE_PAGES) {
+ ESP_LOGW(TAG, "nvs_flash_init failed (0x%x), erasing partition and retrying", err);
+ const esp_partition_t* nvs_partition = esp_partition_find_first(
+ ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, NULL);
+ assert(nvs_partition && "partition table must have an NVS partition");
+ ESP_ERROR_CHECK( esp_partition_erase_range(nvs_partition, 0, nvs_partition->size) );
+ err = nvs_flash_init();
+ }
+ ESP_ERROR_CHECK( err );
+
+ // erase if have any namespace
+ TEST_ESP_OK(nvs_get_stats(NULL, &stat1));
+ if(stat1.namespace_count != 0) {
+ TEST_ESP_OK(nvs_flash_erase());
+ TEST_ESP_OK(nvs_flash_deinit());
+ TEST_ESP_OK(nvs_flash_init());
+ }
+
+ // after erase. empty partition
+ TEST_ESP_OK(nvs_get_stats(NULL, &stat1));
+ TEST_ASSERT_TRUE(stat1.free_entries != 0);
+ TEST_ASSERT_TRUE(stat1.namespace_count == 0);
+ TEST_ASSERT_TRUE(stat1.total_entries != 0);
+ TEST_ASSERT_TRUE(stat1.used_entries == 0);
+
+ // create namespace test_k1
+ nvs_handle handle_1;
+ TEST_ESP_OK(nvs_open("test_k1", NVS_READWRITE, &handle_1));
+ TEST_ESP_OK(nvs_get_stats(NULL, &stat2));
+ TEST_ASSERT_TRUE(stat2.free_entries + 1 == stat1.free_entries);
+ TEST_ASSERT_TRUE(stat2.namespace_count == 1);
+ TEST_ASSERT_TRUE(stat2.total_entries == stat1.total_entries);
+ TEST_ASSERT_TRUE(stat2.used_entries == 1);
+
+ // create pair key-value com
+ TEST_ESP_OK(nvs_set_i32(handle_1, "com", 0x12345678));
+ TEST_ESP_OK(nvs_get_stats(NULL, &stat1));
+ TEST_ASSERT_TRUE(stat1.free_entries + 1 == stat2.free_entries);
+ TEST_ASSERT_TRUE(stat1.namespace_count == 1);
+ TEST_ASSERT_TRUE(stat1.total_entries == stat2.total_entries);
+ TEST_ASSERT_TRUE(stat1.used_entries == 2);
+
+ // change value in com
+ TEST_ESP_OK(nvs_set_i32(handle_1, "com", 0x01234567));
+ TEST_ESP_OK(nvs_get_stats(NULL, &stat2));
+ TEST_ASSERT_TRUE(stat2.free_entries == stat1.free_entries);
+ TEST_ASSERT_TRUE(stat2.namespace_count == 1);
+ TEST_ASSERT_TRUE(stat2.total_entries != 0);
+ TEST_ASSERT_TRUE(stat2.used_entries == 2);
+
+ // create pair key-value ru
+ TEST_ESP_OK(nvs_set_i32(handle_1, "ru", 0x00FF00FF));
+ TEST_ESP_OK(nvs_get_stats(NULL, &stat1));
+ TEST_ASSERT_TRUE(stat1.free_entries + 1 == stat2.free_entries);
+ TEST_ASSERT_TRUE(stat1.namespace_count == 1);
+ TEST_ASSERT_TRUE(stat1.total_entries != 0);
+ TEST_ASSERT_TRUE(stat1.used_entries == 3);
+
+ // amount valid pair in namespace 1
+ size_t h1_count_entries;
+ TEST_ESP_OK(nvs_get_used_entry_count(handle_1, &h1_count_entries));
+ TEST_ASSERT_TRUE(h1_count_entries == 2);
+
+ nvs_handle handle_2;
+ // create namespace test_k2
+ TEST_ESP_OK(nvs_open("test_k2", NVS_READWRITE, &handle_2));
+ TEST_ESP_OK(nvs_get_stats(NULL, &stat2));
+ TEST_ASSERT_TRUE(stat2.free_entries + 1 == stat1.free_entries);
+ TEST_ASSERT_TRUE(stat2.namespace_count == 2);
+ TEST_ASSERT_TRUE(stat2.total_entries == stat1.total_entries);
+ TEST_ASSERT_TRUE(stat2.used_entries == 4);
+
+ // create pair key-value
+ TEST_ESP_OK(nvs_set_i32(handle_2, "su1", 0x00000001));
+ TEST_ESP_OK(nvs_set_i32(handle_2, "su2", 0x00000002));
+ TEST_ESP_OK(nvs_set_i32(handle_2, "sus", 0x00000003));
+ TEST_ESP_OK(nvs_get_stats(NULL, &stat1));
+ TEST_ASSERT_TRUE(stat1.free_entries + 3 == stat2.free_entries);
+ TEST_ASSERT_TRUE(stat1.namespace_count == 2);
+ TEST_ASSERT_TRUE(stat1.total_entries == stat2.total_entries);
+ TEST_ASSERT_TRUE(stat1.used_entries == 7);
+
+ TEST_ASSERT_TRUE(stat1.total_entries == (stat1.used_entries + stat1.free_entries));
+
+ // amount valid pair in namespace 2
+ size_t h2_count_entries;
+ TEST_ESP_OK(nvs_get_used_entry_count(handle_2, &h2_count_entries));
+ TEST_ASSERT_TRUE(h2_count_entries == 3);
+
+ TEST_ASSERT_TRUE(stat1.used_entries == (h1_count_entries + h2_count_entries + stat1.namespace_count));
+
+ nvs_close(handle_1);
+ nvs_close(handle_2);
+
+ size_t temp = h2_count_entries;
+ TEST_ESP_ERR(nvs_get_used_entry_count(handle_1, &h2_count_entries), ESP_ERR_NVS_INVALID_HANDLE);
+ TEST_ASSERT_TRUE(h2_count_entries == 0);
+ h2_count_entries = temp;
+ TEST_ESP_ERR(nvs_get_used_entry_count(handle_1, NULL), ESP_ERR_INVALID_ARG);
+
+ nvs_handle handle_3;
+ // create namespace test_k3
+ TEST_ESP_OK(nvs_open("test_k3", NVS_READWRITE, &handle_3));
+ TEST_ESP_OK(nvs_get_stats(NULL, &stat2));
+ TEST_ASSERT_TRUE(stat2.free_entries + 1 == stat1.free_entries);
+ TEST_ASSERT_TRUE(stat2.namespace_count == 3);
+ TEST_ASSERT_TRUE(stat2.total_entries == stat1.total_entries);
+ TEST_ASSERT_TRUE(stat2.used_entries == 8);
+
+ // create pair blobs
+ uint32_t blob[12];
+ TEST_ESP_OK(nvs_set_blob(handle_3, "bl1", &blob, sizeof(blob)));
+ TEST_ESP_OK(nvs_get_stats(NULL, &stat1));
+ TEST_ASSERT_TRUE(stat1.free_entries + 3 == stat2.free_entries);
+ TEST_ASSERT_TRUE(stat1.namespace_count == 3);
+ TEST_ASSERT_TRUE(stat1.total_entries == stat2.total_entries);
+ TEST_ASSERT_TRUE(stat1.used_entries == 11);
+
+ // amount valid pair in namespace 2
+ size_t h3_count_entries;
+ TEST_ESP_OK(nvs_get_used_entry_count(handle_3, &h3_count_entries));
+ TEST_ASSERT_TRUE(h3_count_entries == 3);
+
+ TEST_ASSERT_TRUE(stat1.used_entries == (h1_count_entries + h2_count_entries + h3_count_entries + stat1.namespace_count));
+
+ nvs_close(handle_3);
+
+ TEST_ESP_OK(nvs_flash_erase());
+ TEST_ESP_OK(nvs_flash_deinit());
+}
CHECK(page.getErasedEntryCount() == 1);
for (size_t i = 0; i < Page::ENTRY_COUNT - 2; ++i) {
char name[16];
- snprintf(name, sizeof(name), "i%ld", i);
+ snprintf(name, sizeof(name), "i%ld", (long int)i);
CHECK(page.writeItem(1, name, i) == ESP_OK);
}
CHECK(page.getUsedEntryCount() == Page::ENTRY_COUNT - 1);
CHECK(page.getErasedEntryCount() == 1);
for (size_t i = 0; i < Page::ENTRY_COUNT - 2; ++i) {
char name[16];
- snprintf(name, sizeof(name), "i%ld", i);
+ snprintf(name, sizeof(name), "i%ld", (long int)i);
CHECK(page.eraseItem(1, itemTypeOf<size_t>(), name) == ESP_OK);
}
CHECK(page.getUsedEntryCount() == 1);
CHECK(page.load(0) == ESP_OK);
for (size_t i = 0; i < Page::ENTRY_COUNT; ++i) {
char name[16];
- snprintf(name, sizeof(name), "i%ld", i);
+ snprintf(name, sizeof(name), "i%ld", (long int)i);
CHECK(page.writeItem(1, name, i) == ESP_OK);
}
CHECK(page.writeItem(1, "foo", 64UL) == ESP_ERR_NVS_PAGE_FULL);
// add more items to make the page full
for (size_t i = 0; i < Page::ENTRY_COUNT; ++i) {
char item_name[Item::MAX_KEY_LENGTH + 1];
- snprintf(item_name, sizeof(item_name), "item_%ld", i);
+ snprintf(item_name, sizeof(item_name), "item_%ld", (long int)i);
TEST_ESP_OK(storage.writeItem(1, item_name, static_cast<uint32_t>(i)));
}
std::cout << s_perf.str() << std::endl;
std::cout << "====================" << std::endl;
}
+
+TEST_CASE("calculate used and free space", "[nvs]")
+{
+ SpiFlashEmulator emu(6);
+ TEST_ESP_ERR(nvs_get_stats(NULL, NULL), ESP_ERR_INVALID_ARG);
+ nvs_stats_t stat1;
+ nvs_stats_t stat2;
+ TEST_ESP_ERR(nvs_get_stats(NULL, &stat1), ESP_ERR_NVS_NOT_INITIALIZED);
+ CHECK(stat1.free_entries == 0);
+ CHECK(stat1.namespace_count == 0);
+ CHECK(stat1.total_entries == 0);
+ CHECK(stat1.used_entries == 0);
+
+ nvs_handle handle = 0;
+ size_t h_count_entries;
+ TEST_ESP_ERR(nvs_get_used_entry_count(handle, &h_count_entries), ESP_ERR_NVS_INVALID_HANDLE);
+ CHECK(h_count_entries == 0);
+
+ // init nvs
+ TEST_ESP_OK(nvs_flash_init_custom(NVS_DEFAULT_PART_NAME, 0, 6));
+
+ TEST_ESP_ERR(nvs_get_used_entry_count(handle, &h_count_entries), ESP_ERR_NVS_INVALID_HANDLE);
+ CHECK(h_count_entries == 0);
+
+ Page p;
+ // after erase. empty partition
+ TEST_ESP_OK(nvs_get_stats(NULL, &stat1));
+ CHECK(stat1.free_entries != 0);
+ CHECK(stat1.namespace_count == 0);
+ CHECK(stat1.total_entries == 6 * p.ENTRY_COUNT);
+ CHECK(stat1.used_entries == 0);
+
+ // create namespace test_k1
+ nvs_handle handle_1;
+ TEST_ESP_OK(nvs_open("test_k1", NVS_READWRITE, &handle_1));
+ TEST_ESP_OK(nvs_get_stats(NULL, &stat2));
+ CHECK(stat2.free_entries + 1 == stat1.free_entries);
+ CHECK(stat2.namespace_count == 1);
+ CHECK(stat2.total_entries == stat1.total_entries);
+ CHECK(stat2.used_entries == 1);
+
+ // create pair key-value com
+ TEST_ESP_OK(nvs_set_i32(handle_1, "com", 0x12345678));
+ TEST_ESP_OK(nvs_get_stats(NULL, &stat1));
+ CHECK(stat1.free_entries + 1 == stat2.free_entries);
+ CHECK(stat1.namespace_count == 1);
+ CHECK(stat1.total_entries == stat2.total_entries);
+ CHECK(stat1.used_entries == 2);
+
+ // change value in com
+ TEST_ESP_OK(nvs_set_i32(handle_1, "com", 0x01234567));
+ TEST_ESP_OK(nvs_get_stats(NULL, &stat2));
+ CHECK(stat2.free_entries == stat1.free_entries);
+ CHECK(stat2.namespace_count == 1);
+ CHECK(stat2.total_entries != 0);
+ CHECK(stat2.used_entries == 2);
+
+ // create pair key-value ru
+ TEST_ESP_OK(nvs_set_i32(handle_1, "ru", 0x00FF00FF));
+ TEST_ESP_OK(nvs_get_stats(NULL, &stat1));
+ CHECK(stat1.free_entries + 1 == stat2.free_entries);
+ CHECK(stat1.namespace_count == 1);
+ CHECK(stat1.total_entries != 0);
+ CHECK(stat1.used_entries == 3);
+
+ // amount valid pair in namespace 1
+ size_t h1_count_entries;
+ TEST_ESP_OK(nvs_get_used_entry_count(handle_1, &h1_count_entries));
+ CHECK(h1_count_entries == 2);
+
+ nvs_handle handle_2;
+ // create namespace test_k2
+ TEST_ESP_OK(nvs_open("test_k2", NVS_READWRITE, &handle_2));
+ TEST_ESP_OK(nvs_get_stats(NULL, &stat2));
+ CHECK(stat2.free_entries + 1 == stat1.free_entries);
+ CHECK(stat2.namespace_count == 2);
+ CHECK(stat2.total_entries == stat1.total_entries);
+ CHECK(stat2.used_entries == 4);
+
+ // create pair key-value
+ TEST_ESP_OK(nvs_set_i32(handle_2, "su1", 0x00000001));
+ TEST_ESP_OK(nvs_set_i32(handle_2, "su2", 0x00000002));
+ TEST_ESP_OK(nvs_set_i32(handle_2, "sus", 0x00000003));
+ TEST_ESP_OK(nvs_get_stats(NULL, &stat1));
+ CHECK(stat1.free_entries + 3 == stat2.free_entries);
+ CHECK(stat1.namespace_count == 2);
+ CHECK(stat1.total_entries == stat2.total_entries);
+ CHECK(stat1.used_entries == 7);
+
+ CHECK(stat1.total_entries == (stat1.used_entries + stat1.free_entries));
+
+ // amount valid pair in namespace 2
+ size_t h2_count_entries;
+ TEST_ESP_OK(nvs_get_used_entry_count(handle_2, &h2_count_entries));
+ CHECK(h2_count_entries == 3);
+
+ CHECK(stat1.used_entries == (h1_count_entries + h2_count_entries + stat1.namespace_count));
+
+ nvs_close(handle_1);
+ nvs_close(handle_2);
+
+ size_t temp = h2_count_entries;
+ TEST_ESP_ERR(nvs_get_used_entry_count(handle_1, &h2_count_entries), ESP_ERR_NVS_INVALID_HANDLE);
+ CHECK(h2_count_entries == 0);
+ h2_count_entries = temp;
+ TEST_ESP_ERR(nvs_get_used_entry_count(handle_1, NULL), ESP_ERR_INVALID_ARG);
+
+ nvs_handle handle_3;
+ // create namespace test_k3
+ TEST_ESP_OK(nvs_open("test_k3", NVS_READWRITE, &handle_3));
+ TEST_ESP_OK(nvs_get_stats(NULL, &stat2));
+ CHECK(stat2.free_entries + 1 == stat1.free_entries);
+ CHECK(stat2.namespace_count == 3);
+ CHECK(stat2.total_entries == stat1.total_entries);
+ CHECK(stat2.used_entries == 8);
+
+ // create pair blobs
+ uint32_t blob[12];
+ TEST_ESP_OK(nvs_set_blob(handle_3, "bl1", &blob, sizeof(blob)));
+ TEST_ESP_OK(nvs_get_stats(NULL, &stat1));
+ CHECK(stat1.free_entries + 3 == stat2.free_entries);
+ CHECK(stat1.namespace_count == 3);
+ CHECK(stat1.total_entries == stat2.total_entries);
+ CHECK(stat1.used_entries == 11);
+
+ // amount valid pair in namespace 2
+ size_t h3_count_entries;
+ TEST_ESP_OK(nvs_get_used_entry_count(handle_3, &h3_count_entries));
+ CHECK(h3_count_entries == 3);
+
+ CHECK(stat1.used_entries == (h1_count_entries + h2_count_entries + h3_count_entries + stat1.namespace_count));
+
+ nvs_close(handle_3);
+}