diff --git a/src/map.c b/src/map.c index 2c00a8d..fb16181 100644 --- a/src/map.c +++ b/src/map.c @@ -77,11 +77,10 @@ uwlkv_entry * uwlkv_create_entry(void) */ uwlkv_error uwlkv_update_entry(const uwlkv_key key, const uwlkv_offset offset) { - const uwlkv_key free = uwlkv_get_free_space(); - uwlkv_entry * entry; + uwlkv_entry *entry; if (UWLKV_E_NOT_EXIST == uwlkv_get_entry(key, &entry)) { - if (0 == free) + if (0 == uwlkv_map_free_entries()) { return UWLKV_E_NO_SPACE; } @@ -116,7 +115,7 @@ uwlkv_key uwlkv_get_used_entries(void) * * @returns Number of entries. */ -uwlkv_key uwlkv_get_free_space(void) +uwlkv_key uwlkv_map_free_entries(void) { return UWLKV_MAX_ENTRIES - used_entries; } diff --git a/src/map.h b/src/map.h index e0707d2..86b9317 100644 --- a/src/map.h +++ b/src/map.h @@ -7,6 +7,6 @@ uwlkv_entry * uwlkv_create_entry(void); uwlkv_error uwlkv_update_entry(const uwlkv_key key, const uwlkv_offset offset); void uwlkv_reset_map(void); uwlkv_key uwlkv_get_used_entries(void); -uwlkv_key uwlkv_get_free_space(void); +uwlkv_key uwlkv_map_free_entries(void); #endif diff --git a/src/uwlkv.c b/src/uwlkv.c index f78009c..0fdfa77 100644 --- a/src/uwlkv.c +++ b/src/uwlkv.c @@ -81,21 +81,17 @@ uwlkv_error uwlkv_set_value(uwlkv_key key, uwlkv_value value) } uwlkv_offset offset = uwlkv_get_next_block(); - uwlkv_entry * entry; - const uint8_t new_entry = UWLKV_E_SUCCESS == uwlkv_get_entry(key, &entry) ? 0 : 1; - - uwlkv_error update = uwlkv_update_entry(key, offset); - if (UWLKV_E_SUCCESS != update) + uwlkv_entry *entry; + if (UWLKV_E_NOT_EXIST == uwlkv_get_entry(key, &entry) + && (0 == uwlkv_map_free_entries())) { - return update; + return UWLKV_E_NO_SPACE; } uwlkv_error write = uwlkv_write_entry(offset, key, value); - if ( (UWLKV_E_SUCCESS != write) - && (new_entry) ) + if (UWLKV_E_SUCCESS == write) { - // On failed write, restore original entry offset - uwlkv_update_entry(key, entry->offset); + uwlkv_update_entry(key, offset); } return write; @@ -118,5 +114,5 @@ uwlkv_key uwlkv_get_entries_number(void) */ uwlkv_key uwlkv_get_free_entries(void) { - return uwlkv_get_free_space(); + return uwlkv_map_free_entries(); } diff --git a/tests/nvram_mock.cpp b/tests/nvram_mock.cpp index a0605e8..4997111 100644 --- a/tests/nvram_mock.cpp +++ b/tests/nvram_mock.cpp @@ -7,6 +7,7 @@ static uint8_t flash_memory[FLASH_REGION_SIZE]; static mock_nvram_erase main_erase_status, reserve_erase_status; +static bool write_enabled = true; void mock_nvram_init(void) { @@ -29,6 +30,10 @@ int mock_flash_read(uint8_t * data, uint32_t start, uint32_t length) int mock_flash_write(uint8_t * data, uint32_t start, uint32_t length) { + if (!write_enabled) { + return 2; + } + if ((start + length) > FLASH_REGION_SIZE) { return 1; @@ -50,6 +55,17 @@ int mock_flash_write(uint8_t * data, uint32_t start, uint32_t length) return 0; } +// Prohibits write operations by `mock_flash_write()`. It will always return an error. +void mock_nvram_disable_write(void) +{ + write_enabled = false; +} + +void mock_nvram_enable_write(void) +{ + write_enabled = true; +} + int mock_flash_erase_main(void) { if (ERASE_ENABLED == main_erase_status) diff --git a/tests/nvram_mock.h b/tests/nvram_mock.h index dc7f222..cbf9afb 100644 --- a/tests/nvram_mock.h +++ b/tests/nvram_mock.h @@ -19,6 +19,8 @@ void mock_nvram_init(void); int mock_flash_read(uint8_t * data, uint32_t start, uint32_t length); int mock_flash_write(uint8_t * data, uint32_t start, uint32_t length); +void mock_nvram_disable_write(void); +void mock_nvram_enable_write(void); int mock_flash_erase_main(void); int mock_flash_erase_reserve(void); diff --git a/tests/tests.cpp b/tests/tests.cpp index 675fe1a..8707650 100644 --- a/tests/tests.cpp +++ b/tests/tests.cpp @@ -99,6 +99,27 @@ TEST_CASE("Writing and reading values", "[read_write]") auto entries = uwlkv_get_entries_number(); CHECK(4 == entries); } + + SECTION("Failed write") + { + auto start = uwlkv_get_entries_number(); + mock_nvram_disable_write(); + uwlkv_value initial, actual; + + // Existing value + CHECK(uwlkv_get_value(0, &initial) == UWLKV_E_SUCCESS); + CHECK(UWLKV_E_NVRAM_ERROR == uwlkv_set_value(0, initial + 1)); + CHECK(uwlkv_get_value(0, &actual) == UWLKV_E_SUCCESS); + CHECK(initial == actual); + + // New value + CHECK(uwlkv_get_value(1, &initial) == UWLKV_E_NOT_EXIST); + CHECK(UWLKV_E_NVRAM_ERROR == uwlkv_set_value(1, initial + 1)); + CHECK(uwlkv_get_value(1, &actual) == UWLKV_E_NOT_EXIST); + + CHECK(uwlkv_get_entries_number() == start); + mock_nvram_enable_write(); + } SECTION("Using all keys") {