Import Mbed OS hard-float snapshot

This commit is contained in:
Beslan
2026-06-01 20:15:04 +03:00
commit d3738e2f89
16278 changed files with 10628036 additions and 0 deletions

View File

@@ -0,0 +1,527 @@
/* mbed Microcontroller Library
* Copyright (c) 2018 ARM Limited
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "rtos/Thread.h"
#include "mbed_trace.h"
#include "mbed_error.h"
#include "BlockDevice.h"
#include "FileSystem.h"
#include "FileSystemStore.h"
#include "greentea-client/test_env.h"
#include "unity.h"
#include "utest.h"
#include <stdlib.h>
#if !SECURESTORE_ENABLED
#error [NOT_SUPPORTED] SecureStore need to be enabled for this test
#else
#define FSST_TEST_NUM_OF_THREADS 5
static const int heap_alloc_threshold_size = 4096;
using namespace utest::v1;
using namespace mbed;
BlockDevice *bd = BlockDevice::get_default_instance();
typedef struct {
int thread_num;
FileSystemStore *fsst;
} thread_data_t;
static void test_set_thread_job(void *data)
{
char kv_value[12] = {"valuevalue"};
char kv_key[6] = {"key"};
char thread_str[3] = {0};
int err = 0;
thread_data_t *thread_data = (thread_data_t *)data;
int thread_num = thread_data->thread_num;
FileSystemStore *thread_fsst = (FileSystemStore *)(thread_data->fsst);
utest_printf("\n Thread %d Started\n", thread_num);
sprintf(thread_str, "%d", thread_num);
strcat(kv_value, thread_str);
strcat(kv_key, thread_str);
err = thread_fsst->set(kv_key, kv_value, strlen(kv_value) + 1, 0);
TEST_ASSERT_EQUAL(0, err);
}
void test_file_system_store_functionality_unit_test()
{
utest_printf("Test FileSystemStore Functionality APIs..\n");
TEST_SKIP_UNLESS(bd != NULL);
uint8_t *dummy = new (std::nothrow) uint8_t[heap_alloc_threshold_size];
TEST_SKIP_UNLESS_MESSAGE(dummy, "Not enough heap to run test");
delete[] dummy;
char kv_value1[64] = {"value1value1value1value1value1value1"};
char kv_key1[16] = {"key1"};
char kv_value2[64] = {"value2value2value2value2value2value2"};
char kv_key2[16] = {"key2"};
char kv_value3[64] = {"valui3valui3"};
char kv_key3[16] = {"kei3"};
char kv_value5[64] = {"setonce5555"};
char kv_key5[16] = {"key5"};
char kv_buf[64] = {0};
char kv_name[16] = {0};
int i_ind = 0;
int err = 0;
size_t actual_size = 0;
err = bd->init();
TEST_ASSERT_EQUAL(0, err);
FileSystem *fs = FileSystem::get_default_instance();
err = fs->mount(bd);
if (err) {
err = fs->reformat(bd);
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
}
FileSystemStore *fsst = new FileSystemStore(fs);
err = fsst->init();
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
err = fsst->reset();
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
/* Set key1 */
err = fsst->set(kv_key1, kv_value1, 64, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
/* Set key2 */
err = fsst->set(kv_key2, kv_value2, strlen(kv_value2), 0);
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
err = fsst->get(kv_key2, kv_buf, 64, &actual_size, 0);
TEST_ASSERT_EQUAL(0, strcmp(kv_buf, kv_value2));
TEST_ASSERT_EQUAL(strlen(kv_value2), (int)actual_size);
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
/* Set key3 */
err = fsst->set(kv_key3, kv_value3, 12, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
KVStore::info_t kv_info;
err = fsst->get_info(kv_key3, &kv_info);
TEST_ASSERT_EQUAL(((int)kv_info.flags), 0);
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
/* Set key5 WRITE_ONCE Twice */
err = fsst->set(kv_key5, kv_value5, 10, mbed::KVStore::WRITE_ONCE_FLAG);
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
err = fsst->set(kv_key5, kv_value3, 10, mbed::KVStore::WRITE_ONCE_FLAG);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_WRITE_PROTECTED, err);
err = fsst->get_info(kv_key5, &kv_info);
TEST_ASSERT_EQUAL(((int)kv_info.flags), mbed::KVStore::WRITE_ONCE_FLAG);
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
/* Verify value remains of first set */
memset(kv_buf, 0, 64);
err = fsst->get(kv_key5, kv_buf, 64, &actual_size, 0);
TEST_ASSERT_EQUAL(0, strncmp(kv_buf, kv_value5, 10));
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
/* Non existing File get fails */
err = fsst->get("key4", kv_buf, 64, &actual_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_ITEM_NOT_FOUND, err);
KVStore::iterator_t kv_it;
err = fsst->iterator_open(&kv_it, NULL);
TEST_ASSERT_EQUAL(0, err);
i_ind = 0;
while (fsst->iterator_next(kv_it, kv_name, 16) != MBED_ERROR_ITEM_NOT_FOUND) {
i_ind++;
}
TEST_ASSERT_EQUAL(i_ind, 4); /* 4 Files : key1, key2, kei3, key5 */
fsst->iterator_close(kv_it);
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
/* Remove Write Once key5 - should fail */
err = fsst->remove(kv_key5);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_WRITE_PROTECTED, err);
/* Verify key5 still remains and has the same value */
memset(kv_buf, 0, 64);
err = fsst->get(kv_key5, kv_buf, 64, &actual_size, 0);
TEST_ASSERT_EQUAL(0, strncmp(kv_buf, kv_value5, 10));
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
fsst->iterator_open(&kv_it, "key");
TEST_ASSERT_EQUAL(0, err);
i_ind = 0;
while (fsst->iterator_next(kv_it, kv_name, 16) != MBED_ERROR_ITEM_NOT_FOUND) {
i_ind++;
TEST_ASSERT_EQUAL(0, strncmp(kv_name, "key", strlen("key")));
}
TEST_ASSERT_EQUAL(i_ind, 3); /* 3 Files with prefix 'key' : key1, key2, key5 */
fsst->iterator_close(kv_it);
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
/* Verify double Remove kei3: first succeed, second fails */
err = fsst->remove(kv_key3);
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
err = fsst->remove(kv_key3);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_ITEM_NOT_FOUND, err);
/* Verify after removing kei3 that get value/info fail */
err = fsst->get(kv_key3, kv_buf, 64, &actual_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_ITEM_NOT_FOUND, err);
err = fsst->get_info(kv_key3, &kv_info);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_ITEM_NOT_FOUND, err);
/* Reset - Verify key2 exists before reset, and not found after reset */
err = fsst->get(kv_key2, kv_buf, 64, &actual_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
err = fsst->reset();
err = fsst->get(kv_key2, kv_buf, 64, &actual_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_ITEM_NOT_FOUND, err);
/* Verify that even Write-Once key5 is not found after reset */
err = fsst->get(kv_key5, kv_buf, 64, &actual_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_ITEM_NOT_FOUND, err);
/* Verify that key5 Write-Once can be set again after Reset*/
err = fsst->set(kv_key5, kv_value5, 10, 0x1);
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
err = fsst->deinit();
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
err = bd->deinit();
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
}
void test_file_system_store_edge_cases()
{
utest_printf("Test FileSystemStore Edge Cases..\n");
TEST_SKIP_UNLESS(bd != NULL);
uint8_t *dummy = new (std::nothrow) uint8_t[heap_alloc_threshold_size];
TEST_SKIP_UNLESS_MESSAGE(dummy, "Not enough heap to run test");
delete[] dummy;
KVStore::info_t kv_info;
KVStore::iterator_t kv_it;
char kv_value1[64] = {"value1value1value1value1value1value1"};
char kv_key1[16] = {"key1"};
char kv_value2[64] = {"value2value2value2value2value2value2"};
char kv_buf[64] = {0};
char kv_name[16] = {0};
int err = bd->init();
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
FileSystem *fs = FileSystem::get_default_instance();
err = fs->mount(bd);
if (err) {
err = fs->reformat(bd);
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
}
FileSystemStore *fsst = new FileSystemStore(fs);
err = fsst->init();
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
err = fsst->reset();
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
size_t actual_size = 0;
/*********************************/
/*********** Unit Test ***********/
/*********************************/
/* Fail Set - key NULL */
err = fsst->set(NULL, kv_value1, 64, 0);
TEST_ASSERT_NOT_EQUAL(0, err);
/* Fail Set - Key length exceeds max */
err = fsst->set(NULL, kv_value1, KVStore::MAX_KEY_SIZE + 10, 0);
TEST_ASSERT_NOT_EQUAL(0, err);
/* Fail Set - NULL Buffer and size larger than 0 */
err = fsst->set(kv_key1, NULL, 64, 0);
TEST_ASSERT_NOT_EQUAL(0, err);
/* OK Set - NULL Buffer and Size is 0 */
err = fsst->set(kv_key1, kv_value1, 0, 0);
TEST_ASSERT_EQUAL(0, err);
/* OK Set - Set Key1 twice and get returns second value */
err = fsst->set(kv_key1, kv_value1, 64, 0);
err = fsst->set(kv_key1, kv_value2, strlen(kv_value2), 0);
memset(kv_buf, 0, 64);
err = fsst->get(kv_key1, kv_buf, 64, &actual_size, 0);
TEST_ASSERT_EQUAL(0, strcmp(kv_buf, kv_value2));
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
/* Fail Get - NULL Key */
memset(kv_buf, 0, 64);
err = fsst->get(NULL, kv_buf, 64, &actual_size, 0);
TEST_ASSERT_NOT_EQUAL(0, err);
/* OK Get - NULL buffer , size=0 */
memset(kv_buf, 0, 64);
err = fsst->get(kv_key1, NULL, 0, &actual_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
/* Fail Get - NULL buffer , size>0 */
memset(kv_buf, 0, 64);
err = fsst->get(kv_key1, NULL, 64, &actual_size, 0);
TEST_ASSERT_NOT_EQUAL(0, err);
/* OK Get - buffer is smaller than value's actual size */
memset(kv_buf, 0, 64);
err = fsst->get(kv_key1, kv_buf, 8, &actual_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
/* Fail Get - offset larger than file size */
memset(kv_buf, 0, 64);
err = fsst->get(kv_key1, kv_buf, 8, &actual_size, 128);
TEST_ASSERT_NOT_EQUAL(0, err);
/* Fail Remove - NULL Key */
err = fsst->remove(NULL);
TEST_ASSERT_NOT_EQUAL(0, err);
/* Fail Remove - Key not found */
err = fsst->remove("key4");
TEST_ASSERT_NOT_EQUAL(0, err);
/* Fail Get_Info - NULL Key */
err = fsst->get_info(NULL, &kv_info);
TEST_ASSERT_NOT_EQUAL(0, err);
/* OK Get_Info - NULL info pointer - verifies whether a key exists */
err = fsst->get_info(kv_key1, NULL);
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
/* Fail Get_Info - Key not found */
err = fsst->get_info("key4", &kv_info);
TEST_ASSERT_NOT_EQUAL(0, err);
/* Fail Iteraor Open - NULL it */
err = fsst->iterator_open(NULL, NULL);
TEST_ASSERT_NOT_EQUAL(0, err);
/* Fail Iteraor Next - key size is 0 */
err = fsst->iterator_open(&kv_it, NULL);
err = fsst->iterator_next(kv_it, kv_name, 0);
TEST_ASSERT_NOT_EQUAL(0, err);
err = fsst->iterator_close(kv_it);
/* OK Iteraor Next - empty folder, returns not found */
err = fsst->reset();
err = fsst->iterator_open(&kv_it, NULL);
err = fsst->iterator_next(kv_it, kv_name, 16);
TEST_ASSERT_NOT_EQUAL(0, err);
err = fsst->iterator_close(kv_it);
/* OK Iteraor Next - 1 File in folder, first returns ok, second returns not found */
err = fsst->set(kv_key1, kv_value1, 64, 0);
err = fsst->iterator_open(&kv_it, NULL);
err = fsst->iterator_next(kv_it, kv_name, 16);
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
err = fsst->iterator_next(kv_it, kv_name, 16);
TEST_ASSERT_NOT_EQUAL(0, err);
err = fsst->iterator_close(kv_it);
/* OK Iteraor Close - close after open*/
err = fsst->iterator_open(&kv_it, NULL);
err = fsst->iterator_close(kv_it);
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
/* Fail Set_Start - NULL handle */
err = fsst->set_start(NULL, "key1", 64, 0);
TEST_ASSERT_NOT_EQUAL(0, err);
/* Fail Set_Start - NULL key */
KVStore::set_handle_t handle;
err = fsst->set_start(&handle, NULL, 64, 0);
TEST_ASSERT_NOT_EQUAL(0, err);
/* OK Set_Finalize - finalize after start, size 0 */
err = fsst->set_start(&handle, "key1", 0, 0);
err = fsst->set_finalize(handle);
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
/* Fail Set_Add_Data - NULL handle */
err = fsst->set_add_data(NULL, "setvalue1", 10);
TEST_ASSERT_NOT_EQUAL(0, err);
/* Fail Set_Add_Data - NULL value */
err = fsst->set_start(&handle, "key1", 0, 0);
err = fsst->set_add_data(handle, NULL, 10);
TEST_ASSERT_NOT_EQUAL(0, err);
err = fsst->set_finalize(handle);
/* OK Set_Add_Data - value size 0 */
err = fsst->set_start(&handle, "key1", 10, 0);
err = fsst->set_add_data(handle, "abcde12345", 10);
memset(kv_buf, 0, 64);
err = fsst->get(kv_key1, kv_buf, 10, &actual_size, 0);
err = fsst->set_add_data(handle, "abcde12345", 0);
err = fsst->set_finalize(handle);
/* OK Get after Finalize */
memset(kv_buf, 0, 64);
err = fsst->get(kv_key1, kv_buf, 12, &actual_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(0, strcmp(kv_buf, "abcde12345"));
/* FAIL SET_Add_Data - exceed final size */
err = fsst->set_start(&handle, "key1", 10, 0);
err = fsst->set_add_data(handle, "abcde12345", 5);
err = fsst->set_add_data(handle, "abcde12345", 10);
TEST_ASSERT_NOT_EQUAL(0, err);
err = fsst->set_add_data(handle, "abcde12345", 5);
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
err = fsst->set_finalize(handle);
/* FAIL SET_Add_Data - final size smaller than set at start */
err = fsst->set_start(&handle, "key1", 10, 0);
err = fsst->set_add_data(handle, "abcde12345", 5);
err = fsst->set_add_data(handle, "abcde12345", 3);
err = fsst->set_finalize(handle);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_INVALID_SIZE, err);
err = fsst->deinit();
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
err = bd->deinit();
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
}
#ifdef MBED_CONF_RTOS_PRESENT
void test_file_system_store_multi_threads()
{
utest_printf("\nTest Multi Threaded FileSystemStore Set Starts..\n");
TEST_SKIP_UNLESS(bd != NULL);
uint8_t *dummy = new (std::nothrow) uint8_t[heap_alloc_threshold_size];
TEST_SKIP_UNLESS_MESSAGE(dummy, "Not enough heap to run test");
delete[] dummy;
char kv_buf[64] = {0};
int err = bd->init();
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
FileSystem *fs = FileSystem::get_default_instance();
err = fs->mount(bd);
if (err) {
err = fs->reformat(bd);
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
}
FileSystemStore *fsst = new FileSystemStore(fs);
err = fsst->init();
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
err = fsst->reset();
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
thread_data_t thread_data[3];
/* Thread Access Test Starts */
rtos::Thread set_thread[FSST_TEST_NUM_OF_THREADS];
int i_ind = 0;
for (i_ind = 0; i_ind < FSST_TEST_NUM_OF_THREADS; i_ind++) {
thread_data[i_ind].fsst = fsst;
thread_data[i_ind].thread_num = i_ind + 1;
set_thread[i_ind].start(callback(test_set_thread_job, &(thread_data[i_ind])));
}
for (i_ind = 0; i_ind < FSST_TEST_NUM_OF_THREADS; i_ind++) {
set_thread[i_ind].join();
}
char kv_value[12] = {"valuevalue"};
char kv_key[6] = {"key"};
char thread_str[FSST_TEST_NUM_OF_THREADS] = {0};
size_t actual_size = 0;
for (i_ind = 1; i_ind < (FSST_TEST_NUM_OF_THREADS + 1); i_ind++) {
memset(kv_buf, 0, 64);
sprintf(thread_str, "%d", i_ind);
strcpy(&kv_value[10], thread_str);
strcpy(&kv_key[3], thread_str);
err = fsst->get(kv_key, kv_buf, 12, &actual_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
TEST_ASSERT_EQUAL(0, strcmp(kv_value, kv_buf));
}
err = fsst->reset();
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
err = fsst->deinit();
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
err = bd->deinit();
TEST_ASSERT_EQUAL_ERROR_CODE(0, err);
}
#endif
utest::v1::status_t greentea_failure_handler(const Case *const source, const failure_t reason)
{
greentea_case_failure_abort_handler(source, reason);
return STATUS_CONTINUE;
}
// Test setup
utest::v1::status_t test_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(60, "default_auto");
return verbose_test_setup_handler(number_of_cases);
}
Case cases[] = {
Case("Testing functionality APIs unit test", test_file_system_store_functionality_unit_test, greentea_failure_handler),
Case("Testing Edge Cases", test_file_system_store_edge_cases, greentea_failure_handler),
#ifdef MBED_CONF_RTOS_PRESENT
Case("Testing Multi Threads Set", test_file_system_store_multi_threads, greentea_failure_handler)
#endif
};
Specification specification(test_setup, cases);
int main()
{
mbed_trace_init();
utest_printf("MAIN STARTS\n");
return !Harness::run(specification);
}
#endif //!SECURESTORE_ENABLED

View File

@@ -0,0 +1,921 @@
/* Copyright (c) 2017 ARM Limited
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "securestore/SecureStore.h"
#include "kvstore/TDBStore.h"
#ifdef MBED_CONF_RTOS_PRESENT
#include "Thread.h"
#endif
#include "mbed_error.h"
#include "FlashSimBlockDevice.h"
#include "SlicingBlockDevice.h"
#include "greentea-client/test_env.h"
#include "unity/unity.h"
#include "utest/utest.h"
#include "FileSystemStore.h"
#include "DeviceKey.h"
using namespace utest::v1;
using namespace mbed;
#if !SECURESTORE_ENABLED
#error [NOT_SUPPORTED] SecureStore need to be enabled for this test
#else
static const char data[] = "data";
static const char key[] = "key";
static char buffer[20] = {};
static const size_t data_size = 5;
static size_t actual_size = 0;
static const size_t buffer_size = 20;
static const int num_of_threads = 3;
#ifdef MBED_CONF_RTOS_PRESENT
static const char *keys[] = {"key1", "key2", "key3"};
#endif
KVStore::info_t info;
KVStore::iterator_t kvstore_it;
KVStore *kvstore = NULL;
FileSystem *fs = NULL;
BlockDevice *bd = NULL;
FlashSimBlockDevice *flash_bd = NULL;
SlicingBlockDevice *ul_bd = NULL, *rbp_bd = NULL;
enum kv_setup {
TDBStoreSet = 0,
FSStoreSet,
SecStoreSet,
NumKVs
};
static const char *kv_prefix[] = {"TDB_", "FS_", "SEC_"};
static int kv_setup = TDBStoreSet;
static const int heap_alloc_threshold_size = 4096;
static inline uint32_t align_up(uint32_t val, uint32_t size)
{
return (((val - 1) / size) + 1) * size;
}
/*----------------initialization------------------*/
//init the blockdevice
static void kvstore_init()
{
// This directly corresponds to the pages allocated for each of the SecureStore block devices
// For the others it may not match exactly to the space that is used, but it is expected to
// be a close enough approximation to act as a guideline for how much of the block device we
// need to erase in order to ensure a stable initial condition.
const size_t PAGES_ESTIMATE = 40;
int res;
size_t program_size, erase_size, ul_bd_size, rbp_bd_size;
BlockDevice *sec_bd;
res = bd->init();
TEST_ASSERT_EQUAL_ERROR_CODE(0, res);
int erase_val = bd->get_erase_value();
// Clear out any stale data that might be left from a previous test.
// Multiply by 2 because SecureStore requires two underlying block devices of this size
size_t bytes_to_erase = align_up(2 * PAGES_ESTIMATE * bd->get_program_size(), bd->get_erase_size());
bd->erase(0, bytes_to_erase);
res = bd->deinit();
TEST_ASSERT_EQUAL_ERROR_CODE(0, res);
if (kv_setup == TDBStoreSet) {
if (erase_val == -1) {
flash_bd = new FlashSimBlockDevice(bd);
kvstore = new TDBStore(flash_bd);
} else {
kvstore = new TDBStore(bd);
}
}
if (kv_setup == FSStoreSet) {
fs = FileSystem::get_default_instance();
TEST_SKIP_UNLESS(fs != NULL);
res = fs->mount(bd);
if (res) {
res = fs->reformat(bd);
TEST_ASSERT_EQUAL_ERROR_CODE(0, res);
}
kvstore = new FileSystemStore(fs);
}
#if SECURESTORE_ENABLED
if (kv_setup == SecStoreSet) {
sec_bd = bd;
if (erase_val == -1) {
flash_bd = new FlashSimBlockDevice(bd);
sec_bd = flash_bd;
}
res = sec_bd->init();
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
program_size = sec_bd->get_program_size();
erase_size = sec_bd->get_erase_size();
// We must be able to hold at least 10 small keys (20 program sectors) and master record + internal data
// but minimum of 2 erase sectors, so that the garbage collection way work
ul_bd_size = align_up(program_size * PAGES_ESTIMATE, erase_size * 2);
rbp_bd_size = align_up(program_size * PAGES_ESTIMATE, erase_size * 2);
TEST_ASSERT((ul_bd_size + rbp_bd_size) < sec_bd->size());
res = sec_bd->deinit();
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
ul_bd = new SlicingBlockDevice(sec_bd, 0, ul_bd_size);
rbp_bd = new SlicingBlockDevice(sec_bd, ul_bd_size, ul_bd_size + rbp_bd_size);
TDBStore *ul_kv = new TDBStore(ul_bd);
TDBStore *rbp_kv = new TDBStore(rbp_bd);
kvstore = new SecureStore(ul_kv, rbp_kv);
}
#endif
TEST_SKIP_UNLESS(kvstore != NULL);
res = kvstore->init();
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
#if DEVICEKEY_ENABLED
DeviceKey::get_instance().generate_root_of_trust();
#endif
}
//deinit the blockdevice
static void kvstore_deinit()
{
int res = 0;
TEST_SKIP_UNLESS(kvstore != NULL);
int erase_val = bd->get_erase_value();
res = kvstore->deinit();
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
if (kv_setup == TDBStoreSet) {
if (erase_val == -1) {
delete flash_bd;
}
}
if (kv_setup == FSStoreSet) {
fs = FileSystem::get_default_instance();
TEST_SKIP_UNLESS(fs != NULL);
res = fs->unmount();
TEST_ASSERT_EQUAL_ERROR_CODE(0, res);
}
if (kv_setup == SecStoreSet) {
if (erase_val == -1) {
delete flash_bd;
}
delete ul_bd;
delete rbp_bd;
}
delete kvstore;
kvstore = NULL;
kv_setup++;
}
/*----------------set()------------------*/
//bad params : key is null
static void set_key_null()
{
TEST_SKIP_UNLESS(kvstore != NULL);
int res = kvstore->set(NULL, data, data_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_INVALID_ARGUMENT, res);
}
//bad params : key length over key max size
static void set_key_length_exceeds_max()
{
TEST_SKIP_UNLESS(kvstore != NULL);
char key_max[KVStore::MAX_KEY_SIZE + 1] = {0};
memset(key_max, '*', KVStore::MAX_KEY_SIZE);
int res = kvstore->set(key_max, data, data_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_INVALID_ARGUMENT, res);
}
//bad params : buffer is null, non zero size
static void set_buffer_null_size_not_zero()
{
TEST_SKIP_UNLESS(kvstore != NULL);
int res = kvstore->set(key, NULL, data_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_INVALID_ARGUMENT, res);
}
//bad params : undefined flag
static void set_key_undefined_flags()
{
TEST_SKIP_UNLESS(kvstore != NULL);
int res = kvstore->set(key, data, data_size, 16);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_INVALID_ARGUMENT, res);
}
//bad params : buffer full, size is 0
static void set_buffer_size_is_zero()
{
TEST_SKIP_UNLESS(kvstore != NULL);
int res = kvstore->set(key, data, 0, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->remove(key);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
//set same key several times
static void set_same_key_several_time()
{
TEST_SKIP_UNLESS(kvstore != NULL);
int res = kvstore->set(key, data, data_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->set(key, data, data_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->set(key, data, data_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->remove(key);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
#ifdef MBED_CONF_RTOS_PRESENT
static void test_thread_set(char *th_key)
{
int res = kvstore->set((char *)th_key, data, data_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
//get several keys multithreaded
static void set_several_keys_multithreaded()
{
TEST_SKIP_UNLESS(kvstore != NULL);
int i = 0, res = 0;
rtos::Thread kvstore_thread[num_of_threads];
osStatus threadStatus;
kvstore_thread[0].start(callback(test_thread_set, (char *)keys[0]));
kvstore_thread[1].start(callback(test_thread_set, (char *)keys[1]));
kvstore_thread[2].start(callback(test_thread_set, (char *)keys[2]));
for (i = 0; i < num_of_threads; i++) {
threadStatus = kvstore_thread[i].join();
if (threadStatus != 0) {
utest_printf("\nthread %d join failed!", i + 1);
}
}
for (i = 0; i < num_of_threads; i++) {
res = kvstore->get(keys[i], buffer, buffer_size, &actual_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
TEST_ASSERT_EQUAL_STRING_LEN(buffer, data, data_size);
}
for (i = 0; i < num_of_threads; i++) {
res = kvstore->remove(keys[i]);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
}
#endif
//set key "write once" and try to set it again
static void set_write_once_flag_try_set_twice()
{
char buf[10];
size_t len;
TEST_SKIP_UNLESS(kvstore != NULL);
int res = kvstore->set(key, "ONCE", 5, KVStore::WRITE_ONCE_FLAG);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->set(key, "TWICE", 6, KVStore::WRITE_ONCE_FLAG);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_WRITE_PROTECTED, res);
res = kvstore->get(key, buf, 10, &len);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
TEST_ASSERT_EQUAL(len, 5);
TEST_ASSERT_EQUAL_STRING_LEN(buf, "ONCE", 5);
res = kvstore->reset();
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
//set key "write once" and try to remove it
static void set_write_once_flag_try_remove()
{
char buf[20];
size_t len;
TEST_SKIP_UNLESS(kvstore != NULL);
int res = kvstore->set(key, "TO_BE_REMOVED", 14, KVStore::WRITE_ONCE_FLAG);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->get(key, buf, 20, &len);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
TEST_ASSERT_EQUAL(len, 14);
TEST_ASSERT_EQUAL_STRING_LEN(buf, "TO_BE_REMOVED", 14);
res = kvstore->remove(key);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_WRITE_PROTECTED, res);
res = kvstore->get(key, buf, 20, &len);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->reset();
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
//set key value one byte size
static void set_key_value_one_byte_size()
{
TEST_SKIP_UNLESS(kvstore != NULL);
char data_one = 'a';
int res = kvstore->set(key, &data_one, 1, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->get(key, buffer, buffer_size, &actual_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = strncmp(buffer, &data_one, 1);
TEST_ASSERT_EQUAL_ERROR_CODE(0, res);
memset(buffer, 0, buffer_size);
res = kvstore->remove(key);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
//set key value two byte size
static void set_key_value_two_byte_size()
{
TEST_SKIP_UNLESS(kvstore != NULL);
char data_two[2] = "d";
int res = kvstore->set(key, data_two, 2, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->get(key, buffer, buffer_size, &actual_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
TEST_ASSERT_EQUAL_STRING_LEN(buffer, data_two, 1);
memset(buffer, 0, buffer_size);
res = kvstore->remove(key);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
//set key value five byte size
static void set_key_value_five_byte_size()
{
TEST_SKIP_UNLESS(kvstore != NULL);
char data_five[5] = "data";
int res = kvstore->set(key, data_five, 5, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->get(key, buffer, buffer_size, &actual_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
TEST_ASSERT_EQUAL_STRING_LEN(buffer, data_five, 4);
memset(buffer, 0, buffer_size);
res = kvstore->remove(key);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
//set key value fifteen byte size
static void set_key_value_fifteen_byte_size()
{
TEST_SKIP_UNLESS(kvstore != NULL);
char data_fif[15] = "data_is_everyt";
int res = kvstore->set(key, data_fif, 15, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->get(key, buffer, buffer_size, &actual_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
TEST_ASSERT_EQUAL_STRING_LEN(buffer, data_fif, 14);
memset(buffer, 0, buffer_size);
res = kvstore->remove(key);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
//set key value seventeen byte size
static void set_key_value_seventeen_byte_size()
{
TEST_SKIP_UNLESS(kvstore != NULL);
char data_fif[17] = "data_is_everythi";
int res = kvstore->set(key, data_fif, 17, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->get(key, buffer, buffer_size, &actual_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
TEST_ASSERT_EQUAL_STRING_LEN(buffer, data_fif, 16);
memset(buffer, 0, buffer_size);
res = kvstore->remove(key);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
//set several different keys and retrieve them
static void set_several_key_value_sizes()
{
TEST_SKIP_UNLESS(kvstore != NULL);
char name[7] = "name_";
char c = 0;
int i = 0, res = 0;
name[6] = 0;
for (i = 0; i < 5; i++) {
c = i + 'a';
name[5] = c;
res = kvstore->set(name, name, sizeof(name), 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
for (i = 0; i < 5; i++) {
c = i + 'a';
name[5] = c;
res = kvstore->get(name, buffer, sizeof(buffer), &actual_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
TEST_ASSERT_EQUAL_STRING_LEN(name, buffer, sizeof(name));
memset(buffer, 0, sizeof(buffer));
res = kvstore->remove(name);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
}
//try to set several different unvalid key names
static void set_several_unvalid_key_names()
{
TEST_SKIP_UNLESS(kvstore != NULL);
char name[7] = "name_";
char unvalid[] = {'*', '?', ':', ';', '"', '|', ' ', '<', '>', '\\', '/'};
int i = 0, res = 0;
name[6] = 0;
for (i = 0; i < 11; i++) {
name[5] = unvalid[i];
res = kvstore->set(name, name, sizeof(name), 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_INVALID_ARGUMENT, res);
}
}
//set key initialize kvstore and retrieve it
static void set_key_init_deinit()
{
if (kv_setup == TDBStoreSet) {
TEST_SKIP_MESSAGE("Unstable testcase. Skipped. Issue # IOTSTOR-978");
}
TEST_SKIP_UNLESS(kvstore != NULL);
int res = kvstore->set(key, data, data_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->deinit();
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->init();
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->get(key, buffer, buffer_size, &actual_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
TEST_ASSERT_EQUAL_STRING(data, buffer);
memset(buffer, 0, buffer_size);
res = kvstore->remove(key);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
//set key with ROLLBACK flag and retrieve it, set it again with no ROLBACK
static void Sec_set_key_rollback_set_again_no_rollback()
{
char key_name[7] = "name";
TEST_SKIP_UNLESS(kvstore != NULL);
if (kv_setup != SecStoreSet) {
return;
}
int res = kvstore->set(key_name, data, data_size, KVStore::REQUIRE_REPLAY_PROTECTION_FLAG);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->get(key_name, buffer, sizeof(buffer), &actual_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
TEST_ASSERT_EQUAL_STRING_LEN(data, buffer, sizeof(data));
memset(buffer, 0, sizeof(buffer));
res = kvstore->set(key_name, data, data_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_INVALID_ARGUMENT, res);
res = kvstore->reset();
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
//set key with ENCRYPT flag and retrieve it
static void Sec_set_key_encrypt()
{
TEST_SKIP_UNLESS(kvstore != NULL);
if (kv_setup != SecStoreSet) {
return;
}
int res = kvstore->set(key, data, data_size, KVStore::REQUIRE_CONFIDENTIALITY_FLAG);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->get(key, buffer, sizeof(buffer), &actual_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
TEST_ASSERT_EQUAL_STRING_LEN(data, buffer, sizeof(data));
res = kvstore->get_info(key, &info);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
TEST_ASSERT_EQUAL_ERROR_CODE(KVStore::REQUIRE_CONFIDENTIALITY_FLAG, info.flags);
memset(buffer, 0, sizeof(buffer));
res = kvstore->remove(key);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
/*----------------get()------------------*/
//bad params : key is null
static void get_key_null()
{
TEST_SKIP_UNLESS(kvstore != NULL);
int res = kvstore->get(NULL, buffer, buffer_size, &actual_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_INVALID_ARGUMENT, res);
}
//bad params : key length over key max size
static void get_key_length_exceeds_max()
{
TEST_SKIP_UNLESS(kvstore != NULL);
char key_max[KVStore::MAX_KEY_SIZE + 1] = {0};
memset(key_max, '*', KVStore::MAX_KEY_SIZE);
int res = kvstore->get(key_max, buffer, buffer_size, &actual_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_INVALID_ARGUMENT, res);
}
//bad params : buffer is null, non zero size
static void get_buffer_null_size_not_zero()
{
TEST_SKIP_UNLESS(kvstore != NULL);
int res = kvstore->get(key, NULL, buffer_size, &actual_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_ITEM_NOT_FOUND, res);
}
//bad params : buffer full, size is 0
static void get_buffer_size_is_zero()
{
TEST_SKIP_UNLESS(kvstore != NULL);
int res = kvstore->set(key, NULL, 0, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->get(key, buffer, 0, &actual_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
//buffer_size smaller than data real size
static void get_buffer_size_smaller_than_data_real_size()
{
TEST_SKIP_UNLESS(kvstore != NULL);
char big_data[25] = "data";
int res = kvstore->set(key, big_data, sizeof(big_data), 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->get(key, buffer, buffer_size, &actual_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
TEST_ASSERT_EQUAL_STRING_LEN(buffer, big_data, &actual_size);
memset(buffer, 0, buffer_size);
res = kvstore->remove(key);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
//buffer_size bigger than data real size
static void get_buffer_size_bigger_than_data_real_size()
{
TEST_SKIP_UNLESS(kvstore != NULL);
int res = kvstore->set(key, data, data_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
char big_buffer[25] = {};
res = kvstore->get(key, big_buffer, sizeof(big_buffer), &actual_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
TEST_ASSERT_EQUAL_STRING_LEN(big_buffer, data, &actual_size);
memset(buffer, 0, buffer_size);
res = kvstore->remove(key);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
//offset bigger than data size
static void get_offset_bigger_than_data_size()
{
TEST_SKIP_UNLESS(kvstore != NULL);
int res = kvstore->set(key, data, data_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->get(key, buffer, buffer_size, &actual_size, data_size + 1);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_INVALID_SIZE, res);
res = kvstore->remove(key);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
//get a non existing key
static void get_non_existing_key()
{
TEST_SKIP_UNLESS(kvstore != NULL);
int res = kvstore->get(key, buffer, buffer_size, &actual_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_ITEM_NOT_FOUND, res);
}
//get a removed key
static void get_removed_key()
{
TEST_SKIP_UNLESS(kvstore != NULL);
int res = kvstore->set(key, data, data_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->remove(key);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->get(key, buffer, buffer_size, &actual_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_ITEM_NOT_FOUND, res);
}
//set the same key twice and get latest data
static void get_key_that_was_set_twice()
{
TEST_SKIP_UNLESS(kvstore != NULL);
int res = kvstore->set(key, data, data_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
char new_data[] = "new_data";
res = kvstore->set(key, new_data, sizeof(new_data), 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->get(key, buffer, buffer_size, &actual_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
TEST_ASSERT_EQUAL_STRING_LEN(buffer, new_data, &actual_size);
memset(buffer, 0, buffer_size);
res = kvstore->remove(key);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
#ifdef MBED_CONF_RTOS_PRESENT
static void test_thread_get(const void *th_key)
{
int res = kvstore->get((char *)th_key, buffer, buffer_size, &actual_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
//get several keys multithreaded
static void get_several_keys_multithreaded()
{
TEST_SKIP_UNLESS(kvstore != NULL);
rtos::Thread kvstore_thread[num_of_threads];
osStatus threadStatus;
for (int i = 0; i < num_of_threads; i++) {
int res = kvstore->set(keys[i], data, data_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
kvstore_thread[0].start(callback(test_thread_get, "key1"));
kvstore_thread[1].start(callback(test_thread_get, "key2"));
kvstore_thread[2].start(callback(test_thread_get, "key3"));
for (int i = 0; i < num_of_threads; i++) {
threadStatus = kvstore_thread[i].join();
if (threadStatus != 0) {
utest_printf("\nthread %d join failed!", i + 1);
}
}
for (int i = 0; i < num_of_threads; i++) {
int res = kvstore->remove(keys[i]);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
}
#endif
/*----------------remove()------------------*/
//bad params : key is null
static void remove_key_null()
{
TEST_SKIP_UNLESS(kvstore != NULL);
int res = kvstore->remove(NULL);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_INVALID_ARGUMENT, res);
}
//bad params : key length over key max size
static void remove_key_length_exceeds_max()
{
TEST_SKIP_UNLESS(kvstore != NULL);
char key_max[KVStore::MAX_KEY_SIZE + 1] = {0};
memset(key_max, '*', KVStore::MAX_KEY_SIZE);
int res = kvstore->remove(key_max);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_INVALID_ARGUMENT, res);
}
//key doesnt exist
static void remove_non_existing_key()
{
TEST_SKIP_UNLESS(kvstore != NULL);
char new_key[] = "remove_key";
int res = kvstore->remove(new_key);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_ITEM_NOT_FOUND, res);
}
//key already removed
static void remove_removed_key()
{
TEST_SKIP_UNLESS(kvstore != NULL);
int res = kvstore->set(key, data, data_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->remove(key);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->remove(key);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_ITEM_NOT_FOUND, res);
}
//key exist - valid flow
static void remove_existed_key()
{
TEST_SKIP_UNLESS(kvstore != NULL);
int res = kvstore->set(key, data, data_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->remove(key);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
/*----------------setup------------------*/
utest::v1::status_t greentea_failure_handler(const Case *const source, const failure_t reason)
{
greentea_case_failure_abort_handler(source, reason);
return STATUS_CONTINUE;
}
typedef struct {
const char *description;
const case_handler_t case_handler;
const case_failure_handler_t failure_handler;
} template_case_t;
template_case_t template_cases[] = {
{"kvstore_init", kvstore_init, greentea_failure_handler}, //must be first
{"set_key_null", set_key_null, greentea_failure_handler},
{"set_key_length_exceeds_max", set_key_length_exceeds_max, greentea_failure_handler},
{"set_buffer_null_size_not_zero", set_buffer_null_size_not_zero, greentea_failure_handler},
{"set_key_undefined_flags", set_key_undefined_flags, greentea_failure_handler},
{"set_buffer_size_is_zero", set_buffer_size_is_zero, greentea_failure_handler},
{"set_same_key_several_time", set_same_key_several_time, greentea_failure_handler},
#ifdef MBED_CONF_RTOS_PRESENT
{"set_several_keys_multithreaded", set_several_keys_multithreaded, greentea_failure_handler},
#endif
{"set_write_once_flag_try_set_twice", set_write_once_flag_try_set_twice, greentea_failure_handler},
{"set_write_once_flag_try_remove", set_write_once_flag_try_remove, greentea_failure_handler},
{"set_key_value_one_byte_size", set_key_value_one_byte_size, greentea_failure_handler},
{"set_key_value_two_byte_size", set_key_value_two_byte_size, greentea_failure_handler},
{"set_key_value_five_byte_size", set_key_value_five_byte_size, greentea_failure_handler},
{"set_key_value_fifteen_byte_size", set_key_value_fifteen_byte_size, greentea_failure_handler},
{"set_key_value_seventeen_byte_size", set_key_value_seventeen_byte_size, greentea_failure_handler},
{"set_several_key_value_sizes", set_several_key_value_sizes, greentea_failure_handler},
{"set_several_unvalid_key_names", set_several_unvalid_key_names, greentea_failure_handler},
{"set_key_init_deinit", set_key_init_deinit, greentea_failure_handler},
{"Sec_set_key_rollback_set_again_no_rollback", Sec_set_key_rollback_set_again_no_rollback, greentea_failure_handler},
{"Sec_set_key_encrypt", Sec_set_key_encrypt, greentea_failure_handler},
{"get_key_null", get_key_null, greentea_failure_handler},
{"get_key_length_exceeds_max", get_key_length_exceeds_max, greentea_failure_handler},
{"get_buffer_null_size_not_zero", get_buffer_null_size_not_zero, greentea_failure_handler},
{"get_buffer_size_is_zero", get_buffer_size_is_zero, greentea_failure_handler},
{"get_buffer_size_smaller_than_data_real_size", get_buffer_size_smaller_than_data_real_size, greentea_failure_handler},
{"get_buffer_size_bigger_than_data_real_size", get_buffer_size_bigger_than_data_real_size, greentea_failure_handler},
{"get_offset_bigger_than_data_size", get_offset_bigger_than_data_size, greentea_failure_handler},
{"get_non_existing_key", get_non_existing_key, greentea_failure_handler},
{"get_removed_key", get_removed_key, greentea_failure_handler},
{"get_key_that_was_set_twice", get_key_that_was_set_twice, greentea_failure_handler},
#ifdef MBED_CONF_RTOS_PRESENT
{"get_several_keys_multithreaded", get_several_keys_multithreaded, greentea_failure_handler},
#endif
{"remove_key_null", remove_key_null, greentea_failure_handler},
{"remove_key_length_exceeds_max", remove_key_length_exceeds_max, greentea_failure_handler},
{"remove_non_existing_key", remove_non_existing_key, greentea_failure_handler},
{"remove_removed_key", remove_removed_key, greentea_failure_handler},
{"remove_existed_key", remove_existed_key, greentea_failure_handler},
{"kvstore_deinit", kvstore_deinit, greentea_failure_handler},
};
utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
{
return greentea_test_setup_handler(number_of_cases);
}
int main()
{
GREENTEA_SETUP(300, "default_auto");
// Don't even start if conditions aren't appropriate for test run
uint8_t *dummy = new (std::nothrow) uint8_t[heap_alloc_threshold_size];
if (!dummy) {
printf("Not enough heap memory to run test. Test skipped.\n");
GREENTEA_TESTSUITE_RESULT(1);
return 0;
}
delete[] dummy;
bd = BlockDevice::get_default_instance();
if (!bd) {
printf("No default instance for this target. Test skipped.\n");
GREENTEA_TESTSUITE_RESULT(1);
return 0;
}
// We want to replicate our test cases to different KV types
size_t num_cases = sizeof(template_cases) / sizeof(template_case_t);
size_t total_num_cases = 0;
void *raw_mem = new (std::nothrow) uint8_t[NumKVs * num_cases * sizeof(Case)];
Case *cases = static_cast<Case *>(raw_mem);
for (int kv = 0; kv < NumKVs; kv++) {
for (size_t i = 0; i < num_cases; i++) {
char desc[128], *desc_ptr;
sprintf(desc, "%s%s", kv_prefix[kv], template_cases[i].description);
desc_ptr = new char[strlen(desc) + 1];
strcpy(desc_ptr, desc);
new (&cases[total_num_cases]) Case((const char *) desc_ptr, template_cases[i].case_handler,
template_cases[i].failure_handler);
total_num_cases++;
}
}
Specification specification(greentea_test_setup, cases, total_num_cases,
greentea_test_teardown_handler, default_handler);
return !Harness::run(specification);
}
#endif //!SECURESTORE_ENABLED

View File

@@ -0,0 +1,892 @@
/* Copyright (c) 2017 ARM Limited
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "securestore/SecureStore.h"
#include "kvstore/TDBStore.h"
#include "mbed_error.h"
#include "FlashSimBlockDevice.h"
#include "SlicingBlockDevice.h"
#include "greentea-client/test_env.h"
#include "unity/unity.h"
#include "utest/utest.h"
#include "FileSystemStore.h"
#include "DeviceKey.h"
using namespace utest::v1;
using namespace mbed;
#if !SECURESTORE_ENABLED
#error [NOT_SUPPORTED] SecureStore need to be enabled for this test
#else
static const char data[] = "data";
static const char key[] = "key";
static char buffer[20] = {};
static const size_t data_size = 5;
static size_t actual_size = 0;
static const size_t buffer_size = 20;
static const char num_of_keys = 3;
static const char *keys[] = {"key1", "key2", "key3"};
KVStore::info_t info;
KVStore::iterator_t kvstore_it;
KVStore *kvstore = NULL;
FileSystem *fs = NULL;
BlockDevice *bd = NULL;
FlashSimBlockDevice *flash_bd = NULL;
SlicingBlockDevice *ul_bd = NULL, *rbp_bd = NULL;
enum kv_setup {
TDBStoreSet = 0,
FSStoreSet,
SecStoreSet,
NumKVs
};
static const char *kv_prefix[] = {"TDB_", "FS_", "SEC_"};
static int kv_setup = TDBStoreSet;
static const int heap_alloc_threshold_size = 4096;
static inline uint32_t align_up(uint32_t val, uint32_t size)
{
return (((val - 1) / size) + 1) * size;
}
/*----------------initialization------------------*/
//init the blockdevice
static void kvstore_init()
{
// This directly corresponds to the pages allocated for each of the SecureStore block devices
// For the others it may not match exactly to the space that is used, but it is expected to
// be a close enough approximation to act as a guideline for how much of the block device we
// need to erase in order to ensure a stable initial condition.
const size_t PAGES_ESTIMATE = 40;
int res;
size_t program_size, erase_size, ul_bd_size, rbp_bd_size;
BlockDevice *sec_bd;
res = bd->init();
TEST_ASSERT_EQUAL_ERROR_CODE(0, res);
int erase_val = bd->get_erase_value();
// Clear out any stale data that might be left from a previous test
// Multiply by 2 because SecureStore requires two underlying block devices of this size
size_t bytes_to_erase = align_up(2 * PAGES_ESTIMATE * bd->get_program_size(), bd->get_erase_size());
bd->erase(0, bytes_to_erase);
res = bd->deinit();
TEST_ASSERT_EQUAL_ERROR_CODE(0, res);
if (kv_setup == TDBStoreSet) {
if (erase_val == -1) {
flash_bd = new FlashSimBlockDevice(bd);
kvstore = new TDBStore(flash_bd);
} else {
kvstore = new TDBStore(bd);
}
}
if (kv_setup == FSStoreSet) {
fs = FileSystem::get_default_instance();
TEST_SKIP_UNLESS(fs != NULL);
res = fs->mount(bd);
if (res) {
res = fs->reformat(bd);
TEST_ASSERT_EQUAL_ERROR_CODE(0, res);
}
kvstore = new FileSystemStore(fs);
}
#if SECURESTORE_ENABLED
if (kv_setup == SecStoreSet) {
sec_bd = bd;
if (erase_val == -1) {
flash_bd = new FlashSimBlockDevice(bd);
sec_bd = flash_bd;
}
res = sec_bd->init();
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
program_size = sec_bd->get_program_size();
erase_size = sec_bd->get_erase_size();
// We must be able to hold at least 10 small keys (20 program sectors) and master record + internal data
// but minimum of 2 erase sectors, so that the garbage collection way work
ul_bd_size = align_up(program_size * PAGES_ESTIMATE, erase_size * 2);
rbp_bd_size = align_up(program_size * PAGES_ESTIMATE, erase_size * 2);
res = sec_bd->deinit();
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
ul_bd = new SlicingBlockDevice(sec_bd, 0, ul_bd_size);
rbp_bd = new SlicingBlockDevice(sec_bd, ul_bd_size, ul_bd_size + rbp_bd_size);
TDBStore *ul_kv = new TDBStore(ul_bd);
TDBStore *rbp_kv = new TDBStore(rbp_bd);
kvstore = new SecureStore(ul_kv, rbp_kv);
}
#endif
TEST_SKIP_UNLESS(kvstore != NULL);
res = kvstore->init();
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
#if DEVICEKEY_ENABLED
DeviceKey::get_instance().generate_root_of_trust();
#endif
}
//deinit the blockdevice
static void kvstore_deinit()
{
int res = 0;
TEST_SKIP_UNLESS(kvstore != NULL);
int erase_val = bd->get_erase_value();
res = kvstore->deinit();
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
if (kv_setup == TDBStoreSet) {
if (erase_val == -1) {
delete flash_bd;
}
}
if (kv_setup == FSStoreSet) {
fs = FileSystem::get_default_instance();
TEST_SKIP_UNLESS(fs != NULL);
res = fs->unmount();
TEST_ASSERT_EQUAL_ERROR_CODE(0, res);
}
if (kv_setup == SecStoreSet) {
if (erase_val == -1) {
delete flash_bd;
}
delete ul_bd;
delete rbp_bd;
}
delete kvstore;
kvstore = NULL;
kv_setup++;
}
/*----------------get_info()------------------*/
//bad params : key is null
static void get_info_key_null()
{
TEST_SKIP_UNLESS(kvstore != NULL);
int res = kvstore->get_info(NULL, &info);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_INVALID_ARGUMENT, res);
}
//bad params : key length over key max size
static void get_info_key_length_exceeds_max()
{
TEST_SKIP_UNLESS(kvstore != NULL);
char key_max[KVStore::MAX_KEY_SIZE + 1] = {0};
memset(key_max, '*', KVStore::MAX_KEY_SIZE);
int res = kvstore->get_info(key_max, &info);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_INVALID_ARGUMENT, res);
}
//get_info of non existing key
static void get_info_non_existing_key()
{
TEST_SKIP_UNLESS(kvstore != NULL);
char new_key[] = "get_info_key";
int res = kvstore->get_info(new_key, &info);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_ITEM_NOT_FOUND, res);
}
//get_info of removed key
static void get_info_removed_key()
{
TEST_SKIP_UNLESS(kvstore != NULL);
int res = kvstore->set(key, data, data_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->remove(key);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->get_info(key, &info);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_ITEM_NOT_FOUND, res);
}
//get_info of existing key - valid flow
static void get_info_existed_key()
{
TEST_SKIP_UNLESS(kvstore != NULL);
int res = kvstore->set(key, data, data_size, KVStore::WRITE_ONCE_FLAG);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->get_info(key, &info);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
TEST_ASSERT_EQUAL_ERROR_CODE(info.flags, KVStore::WRITE_ONCE_FLAG);
res = kvstore->get_info(key, NULL);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->get_info(key);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->reset();
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
//get_info of overwritten key
static void get_info_overwritten_key()
{
TEST_SKIP_UNLESS(kvstore != NULL);
int res = kvstore->set(key, data, data_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
char new_data[] = "new_data";
res = kvstore->set(key, new_data, sizeof(new_data), 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->get_info(key, &info);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
TEST_ASSERT_EQUAL_ERROR_CODE(info.size, sizeof(new_data));
res = kvstore->remove(key);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
/*----------------iterator_open()------------------*/
//bad params : it is null
static void iterator_open_it_null()
{
TEST_SKIP_UNLESS(kvstore != NULL);
int res = kvstore->iterator_open(NULL, NULL);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_INVALID_ARGUMENT, res);
}
/*----------------iterator_next()------------------*/
//key valid, key_size 0
static void iterator_next_key_size_zero()
{
TEST_SKIP_UNLESS(kvstore != NULL);
int res = kvstore->iterator_open(&kvstore_it, NULL);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
char key[KVStore::MAX_KEY_SIZE];
res = kvstore->iterator_next(kvstore_it, key, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_ITEM_NOT_FOUND, res);
res = kvstore->iterator_close(kvstore_it);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
//iteartor_next with empty list
static void iterator_next_empty_list()
{
TEST_SKIP_UNLESS(kvstore != NULL);
int res = kvstore->iterator_open(&kvstore_it, NULL);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
char key[KVStore::MAX_KEY_SIZE];
res = kvstore->iterator_next(kvstore_it, key, sizeof(key));
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_ITEM_NOT_FOUND, res);
res = kvstore->iterator_close(kvstore_it);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
//iterator_next for one key list
static void iterator_next_one_key_list()
{
TEST_SKIP_UNLESS(kvstore != NULL);
int res = kvstore->set(key, data, data_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->iterator_open(&kvstore_it, NULL);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
char key_buf[KVStore::MAX_KEY_SIZE];
res = kvstore->iterator_next(kvstore_it, key_buf, sizeof(key_buf));
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->iterator_close(kvstore_it);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->remove(key);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
//iteartor_next with empty list (all keys removed)
static void iterator_next_empty_list_keys_removed()
{
TEST_SKIP_UNLESS(kvstore != NULL);
char new_key_1[] = "it_1";
int res = kvstore->set(new_key_1, data, data_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
char new_key_2[] = "it_2";
res = kvstore->set(new_key_2, data, data_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->remove(new_key_1);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->remove(new_key_2);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->iterator_open(&kvstore_it, NULL);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
char key_buf[KVStore::MAX_KEY_SIZE];
res = kvstore->iterator_next(kvstore_it, key_buf, sizeof(key_buf));
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_ITEM_NOT_FOUND, res);
res = kvstore->iterator_close(kvstore_it);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
//iteartor_next with non matching prefix (empty list)
static void iterator_next_empty_list_non_matching_prefix()
{
TEST_SKIP_UNLESS(kvstore != NULL);
char new_key_1[] = "it_1";
int res = kvstore->set(new_key_1, data, data_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
char new_key_2[] = "it_2";
res = kvstore->set(new_key_2, data, data_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->iterator_open(&kvstore_it, "Key*");
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
char key_buf[KVStore::MAX_KEY_SIZE];
res = kvstore->iterator_next(kvstore_it, key_buf, sizeof(key_buf));
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_ITEM_NOT_FOUND, res);
res = kvstore->iterator_close(kvstore_it);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->remove(new_key_1);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->remove(new_key_2);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
//iteartor_next with several overwritten keys
static void iterator_next_several_overwritten_keys()
{
TEST_SKIP_UNLESS(kvstore != NULL);
for (int i = 0; i < num_of_keys; i++) {
int res = kvstore->set(key, data, data_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
int res = kvstore->iterator_open(&kvstore_it, NULL);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
char key[KVStore::MAX_KEY_SIZE];
res = kvstore->iterator_next(kvstore_it, key, sizeof(key));
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->iterator_next(kvstore_it, key, sizeof(key));
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_ITEM_NOT_FOUND, res);
res = kvstore->iterator_close(kvstore_it);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->remove(key);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
//iterator_next for full list - check key names for validation
static void iterator_next_full_list()
{
TEST_SKIP_UNLESS(kvstore != NULL);
int i = 0;
bool *key_found = new bool[num_of_keys];
for (i = 0; i < num_of_keys; i++) {
int res = kvstore->set(keys[i], data, data_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
key_found[i] = false;
}
int res = kvstore->iterator_open(&kvstore_it, NULL);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
char temp_key[KVStore::MAX_KEY_SIZE];
for (i = 0; i < num_of_keys; i++) {
res = kvstore->iterator_next(kvstore_it, temp_key, sizeof(temp_key));
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->get(temp_key, buffer, buffer_size, &actual_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
int j;
for (j = 0; j < num_of_keys; j++) {
if (!key_found[j] && (!strcmp(keys[j], temp_key))) {
key_found[j] = true;
break;
}
}
TEST_ASSERT_NOT_EQUAL(j, num_of_keys);
}
res = kvstore->iterator_close(kvstore_it);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
for (i = 0; i < num_of_keys; i++) {
int res = kvstore->remove(keys[i]);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
}
//iteartor_next remove while iterating
static void iterator_next_remove_while_iterating()
{
TEST_SKIP_UNLESS(kvstore != NULL);
int i = 0, res = 0;
for (i = 0; i < num_of_keys; i++) {
int res = kvstore->set(keys[i], data, data_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
char new_key_1[] = "new_key_1";
res = kvstore->set(new_key_1, data, data_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
char new_key_2[] = "new_key_2";
res = kvstore->set(new_key_2, data, data_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->iterator_open(&kvstore_it, "key");
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
char key[KVStore::MAX_KEY_SIZE];
while (1) {
res = kvstore->iterator_next(kvstore_it, key, sizeof(key));
if (res != MBED_SUCCESS) {
break;
}
res = kvstore->remove(key);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
res = kvstore->iterator_open(&kvstore_it, NULL);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
while (1) {
res = kvstore->iterator_next(kvstore_it, key, sizeof(key));
if (res != MBED_SUCCESS) {
break;
}
TEST_ASSERT_EQUAL_STRING_LEN("new", key, 3);
res = kvstore->remove(key);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
res = kvstore->iterator_close(kvstore_it);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
/*----------------iterator_close()------------------*/
//iterator_close right after iterator_open
static void iterator_close_right_after_iterator_open()
{
TEST_SKIP_UNLESS(kvstore != NULL);
int res = kvstore->iterator_open(&kvstore_it, NULL);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->iterator_close(kvstore_it);
}
/*----------------set_start()------------------*/
//bad params : key is null
static void set_start_key_is_null()
{
TEST_SKIP_UNLESS(kvstore != NULL);
KVStore::set_handle_t handle;
int res = kvstore->set_start(&handle, NULL, data_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_INVALID_ARGUMENT, res);
}
//bad params : key_size over max_size
static void set_start_key_size_exceeds_max_size()
{
TEST_SKIP_UNLESS(kvstore != NULL);
KVStore::set_handle_t handle;
char key_max[KVStore::MAX_KEY_SIZE + 1] = {0};
memset(key_max, '*', KVStore::MAX_KEY_SIZE);
int res = kvstore->set_start(&handle, key_max, data_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_INVALID_ARGUMENT, res);
}
//final_data_size is 0
static void set_start_final_data_size_is_zero()
{
TEST_SKIP_UNLESS(kvstore != NULL);
KVStore::set_handle_t handle;
int res = kvstore->set_start(&handle, key, 0, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->set_finalize(handle);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
//final_data_size is smaller than actual data
static void set_start_final_data_size_is_smaller_than_real_data()
{
TEST_SKIP_UNLESS(kvstore != NULL);
KVStore::set_handle_t handle;
size_t new_data_size = 20;
int res = kvstore->set_start(&handle, key, new_data_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->set_add_data(handle, data, data_size);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->set_finalize(handle);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_INVALID_SIZE, res);
}
//final_data_size is smaller than actual data
static void set_start_final_data_size_is_bigger_than_real_data()
{
TEST_SKIP_UNLESS(kvstore != NULL);
KVStore::set_handle_t handle;
char new_data[] = "new_data_buffer";
int res = kvstore->set_start(&handle, key, data_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->set_add_data(handle, new_data, sizeof(new_data));
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_INVALID_SIZE, res);
}
/*----------------set_add_data()------------------*/
//bad params : value_data is null
static void set_add_data_value_data_is_null()
{
TEST_SKIP_UNLESS(kvstore != NULL);
KVStore::set_handle_t handle;
int res = kvstore->set_start(&handle, key, data_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->set_add_data(handle, NULL, sizeof(data_size));
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_INVALID_ARGUMENT, res);
res = kvstore->reset();
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
//bad params : value_data is valid, data_size is 0
static void set_add_data_data_size_is_zero()
{
TEST_SKIP_UNLESS(kvstore != NULL);
KVStore::set_handle_t handle;
int res = kvstore->set_start(&handle, key, 0, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->set_add_data(handle, NULL, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->set_finalize(handle);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->remove(key);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
//data_size is bigger than actual data
static void set_add_data_data_size_bigger_than_real_data()
{
TEST_SKIP_UNLESS(kvstore != NULL);
KVStore::set_handle_t handle;
size_t new_data_size = 20;
int res = kvstore->set_start(&handle, key, new_data_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->set_add_data(handle, data, new_data_size - 1);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->set_add_data(handle, data, data_size);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_INVALID_SIZE, res);
res = kvstore->reset();
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
//set different data_sizes chunks of data in the same transaction
static void set_add_data_set_different_data_size_in_same_transaction()
{
TEST_SKIP_UNLESS(kvstore != NULL);
KVStore::set_handle_t handle;
char new_data[] = "new_data_tests";
size_t new_data_size = 15;
int res = kvstore->set_start(&handle, key, new_data_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->set_add_data(handle, new_data, new_data_size - 5);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->set_add_data(handle, new_data, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->set_add_data(handle, new_data + (new_data_size - 5), 5);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->set_finalize(handle);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->get(key, buffer, buffer_size, &actual_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
TEST_ASSERT_EQUAL_STRING(new_data, buffer);
res = kvstore->remove(key);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
//set key value five Kbyte size
static void set_add_data_set_key_value_five_Kbytes()
{
TEST_SKIP_UNLESS(kvstore != NULL);
KVStore::set_handle_t handle;
size_t new_data_size = 5000;
char temp_buf[50] = {};
char read_temp_buf[50] = {};
unsigned int i = 0;
int res = kvstore->set_start(&handle, key, new_data_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
for (i = 0; i < (new_data_size / sizeof(temp_buf)); i++) {
memset(temp_buf, '*', sizeof(temp_buf));
res = kvstore->set_add_data(handle, temp_buf, sizeof(temp_buf));
}
res = kvstore->set_finalize(handle);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->get(key, read_temp_buf, sizeof(read_temp_buf), &actual_size, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
TEST_ASSERT_EQUAL_STRING_LEN(temp_buf, read_temp_buf, sizeof(temp_buf));
res = kvstore->remove(key);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
//set_add_data without set_start
static void set_add_data_without_set_start()
{
TEST_SKIP_UNLESS(kvstore != NULL);
KVStore::set_handle_t handle = reinterpret_cast<KVStore::set_handle_t>(0);
int res = kvstore->set_add_data(handle, data, data_size);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_INVALID_ARGUMENT, res);
}
/*----------------set_finalize()------------------*/
//set_finalize without set_start
static void set_finalize_without_set_start()
{
TEST_SKIP_UNLESS(kvstore != NULL);
KVStore::set_handle_t handle = reinterpret_cast<KVStore::set_handle_t>(0);
int res = kvstore->set_finalize(handle);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_INVALID_ARGUMENT, res);
}
static void set_finalize_right_after_set_start()
{
TEST_SKIP_UNLESS(kvstore != NULL);
KVStore::set_handle_t handle;
int res = kvstore->set_start(&handle, key, 0, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
res = kvstore->set_finalize(handle);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
}
/*----------------setup------------------*/
utest::v1::status_t greentea_failure_handler(const Case *const source, const failure_t reason)
{
greentea_case_failure_abort_handler(source, reason);
return STATUS_CONTINUE;
}
typedef struct {
const char *description;
const case_handler_t case_handler;
const case_failure_handler_t failure_handler;
} template_case_t;
template_case_t template_cases[] = {
{"kvstore_init", kvstore_init, greentea_failure_handler}, //must be first
{"get_info_key_null", get_info_key_null, greentea_failure_handler},
{"get_info_key_length_exceeds_max", get_info_key_length_exceeds_max, greentea_failure_handler},
{"get_info_non_existing_key", get_info_non_existing_key, greentea_failure_handler},
{"get_info_removed_key", get_info_removed_key, greentea_failure_handler},
{"get_info_existed_key", get_info_existed_key, greentea_failure_handler},
{"get_info_overwritten_key", get_info_overwritten_key, greentea_failure_handler},
{"iterator_open_it_null", iterator_open_it_null, greentea_failure_handler},
{"iterator_next_key_size_zero", iterator_next_key_size_zero, greentea_failure_handler},
{"iterator_next_empty_list", iterator_next_empty_list, greentea_failure_handler},
{"iterator_next_one_key_list", iterator_next_one_key_list, greentea_failure_handler},
{"iterator_next_empty_list_keys_removed", iterator_next_empty_list_keys_removed, greentea_failure_handler},
{"iterator_next_empty_list_non_matching_prefix", iterator_next_empty_list_non_matching_prefix, greentea_failure_handler},
{"iterator_next_several_overwritten_keys", iterator_next_several_overwritten_keys, greentea_failure_handler},
{"iterator_next_full_list", iterator_next_full_list, greentea_failure_handler},
{"iterator_next_remove_while_iterating", iterator_next_remove_while_iterating, greentea_failure_handler},
{"iterator_close_right_after_iterator_open", iterator_close_right_after_iterator_open, greentea_failure_handler},
{"set_start_key_is_null", set_start_key_is_null, greentea_failure_handler},
{"set_start_key_size_exceeds_max_size", set_start_key_size_exceeds_max_size, greentea_failure_handler},
{"set_start_final_data_size_is_zero", set_start_final_data_size_is_zero, greentea_failure_handler},
{"set_start_final_data_size_is_smaller_than_real_data", set_start_final_data_size_is_smaller_than_real_data, greentea_failure_handler},
{"set_start_final_data_size_is_bigger_than_real_data", set_start_final_data_size_is_bigger_than_real_data, greentea_failure_handler},
{"set_add_data_value_data_is_null", set_add_data_value_data_is_null, greentea_failure_handler},
{"set_add_data_data_size_is_zero", set_add_data_data_size_is_zero, greentea_failure_handler},
{"set_add_data_data_size_bigger_than_real_data", set_add_data_data_size_bigger_than_real_data, greentea_failure_handler},
{"set_add_data_set_different_data_size_in_same_transaction", set_add_data_set_different_data_size_in_same_transaction, greentea_failure_handler},
{"set_add_data_set_key_value_five_Kbytes", set_add_data_set_key_value_five_Kbytes, greentea_failure_handler},
{"set_add_data_without_set_start", set_add_data_without_set_start, greentea_failure_handler},
{"set_finalize_without_set_start", set_finalize_without_set_start, greentea_failure_handler},
{"set_finalize_right_after_set_start", set_finalize_right_after_set_start, greentea_failure_handler},
{"kvstore_deinit", kvstore_deinit, greentea_failure_handler},
};
utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
{
return greentea_test_setup_handler(number_of_cases);
}
int main()
{
GREENTEA_SETUP(300, "default_auto");
// Don't even start if conditions aren't appropriate for test run
uint8_t *dummy = new (std::nothrow) uint8_t[heap_alloc_threshold_size];
if (!dummy) {
printf("Not enough heap memory to run test. Test skipped.\n");
GREENTEA_TESTSUITE_RESULT(1);
return 0;
}
delete[] dummy;
bd = BlockDevice::get_default_instance();
if (!bd) {
printf("No default instance for this target. Test skipped.\n");
GREENTEA_TESTSUITE_RESULT(1);
return 0;
}
// We want to replicate our test cases to different KV types
size_t num_cases = sizeof(template_cases) / sizeof(template_case_t);
size_t total_num_cases = 0;
void *raw_mem = new (std::nothrow) uint8_t[NumKVs * num_cases * sizeof(Case)];
Case *cases = static_cast<Case *>(raw_mem);
for (int kv = 0; kv < NumKVs; kv++) {
for (size_t i = 0; i < num_cases; i++) {
char desc[128], *desc_ptr;
sprintf(desc, "%s%s", kv_prefix[kv], template_cases[i].description);
desc_ptr = new char[strlen(desc) + 1];
strcpy(desc_ptr, desc);
new (&cases[total_num_cases]) Case((const char *) desc_ptr, template_cases[i].case_handler,
template_cases[i].failure_handler);
total_num_cases++;
}
}
Specification specification(greentea_test_setup, cases, total_num_cases,
greentea_test_teardown_handler, default_handler);
return !Harness::run(specification);
}
#endif //!SECURESTORE_ENABLED

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,471 @@
/*
* Copyright (c) 2018 ARM Limited. All rights reserved.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the License); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "TDBStore.h"
#ifdef MBED_CONF_RTOS_PRESENT
#include "Thread.h"
#endif
#include "mbed_error.h"
#include "Timer.h"
#include "HeapBlockDevice.h"
#include "FlashSimBlockDevice.h"
#include "SlicingBlockDevice.h"
#include "greentea-client/test_env.h"
#include "unity/unity.h"
#include "utest/utest.h"
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <algorithm>
using namespace mbed;
using namespace utest::v1;
#undef TEST_SPIF
#undef TEST_SD
#undef TEST_FLASHIAP
#ifdef TEST_SPIF
#include "SPIFBlockDevice.h"
SPIFBlockDevice bd(MBED_CONF_SPIF_DRIVER_SPI_MOSI, MBED_CONF_SPIF_DRIVER_SPI_MISO,
MBED_CONF_SPIF_DRIVER_SPI_CLK, MBED_CONF_SPIF_DRIVER_SPI_CS);
SlicingBlockDevice flash_bd(&bd, 0, 16 * 4096);
#elif defined(TEST_SD)
#include "SDBlockDevice.h"
SDBlockDevice bd(MBED_CONF_SD_SPI_MOSI, MBED_CONF_SD_SPI_MISO,
MBED_CONF_SD_SPI_CLK, MBED_CONF_SD_SPI_CS);
SlicingBlockDevice slice_bd(&bd, 0, 512 * 512);
FlashSimBlockDevice flash_bd(&slice_bd);
#elif defined(TEST_FLASHIAP)
#include "FlashIAPBlockDevice.h"
FlashIAPBlockDevice flash_bd(0xF0000, 0x10000);
#else
#define USE_HEAP_BD 1
HeapBlockDevice bd(8 * 4096, 1, 1, 4096);
FlashSimBlockDevice flash_bd(&bd);
#endif
static const int heap_alloc_threshold_size = 4096;
typedef struct {
size_t size;
size_t read_size;
size_t prog_size;
size_t erase_size;
} bd_params_t;
static const char *const key1 = "key1";
static const char *const key1_val1 = "val1";
static const char *const key2 = "name_of_key2";
static const char *const key2_val1 = "val3";
static const char *const key2_val2 = "val2 of key 2";
static const char *const key2_val3 = "Val1 value of key 2 ";
static const char *const key3 = "This_is_the_name_of_key3";
static const char *const key3_val1 = "Data value of key 3 is the following";
static const char *const key4 = "This_is_the_name_of_key4";
static const char *const key4_val1 = "Is this the value of key 4?";
static const char *const key4_val2 = "What the hell is the value of key 4, god damn it!";
static const char *const key5 = "This_is_the_real_name_of_Key5";
static const char *const key5_val1 = "Key 5 value that should definitely be written";
static const char *const key5_val2 = "Key 5 value that should definitely not be written";
static const char *const res_val1 = "This should be saved as the reserved data";
static const char *const res_val2 = "This should surely not be saved as the reserved data";
static void white_box_test()
{
bd_params_t bd_params[] = {
{8192, 1, 16, 4096}, // Standard
{4096 * 4, 1, 1, 4096}, // K82F like
{8192, 64, 128, 2048}, // Awkward read and program sizes, both larger than header size
{2048, 1, 4, 128}, // Small sector and total sizes
{0, 0, 0, 0}, // Place holder for real non volatile device (if defined)
};
int num_bds = sizeof(bd_params) / sizeof(bd_params_t);
uint8_t get_buf[128];
size_t actual_data_size;
int result;
mbed::Timer timer;
int elapsed;
KVStore::info_t info;
#ifndef USE_HEAP_BD
flash_bd.init();
bd_params[num_bds - 1].size = flash_bd.size();
bd_params[num_bds - 1].read_size = flash_bd.get_read_size();
bd_params[num_bds - 1].prog_size = flash_bd.get_program_size();
bd_params[num_bds - 1].erase_size = flash_bd.get_erase_size();
flash_bd.deinit();
#endif
timer.start();
for (int bd_num = 0; bd_num < num_bds; bd_num++) {
uint8_t *dummy = new (std::nothrow) uint8_t[heap_alloc_threshold_size];
TEST_SKIP_UNLESS_MESSAGE(dummy, "Not enough heap to run test");
bd_params_t *bdp = &bd_params[bd_num];
if (!bdp->size) {
break;
}
printf("\n\nBD #%d: size %d, read %d, prog %d, erase %d\n",
bd_num, bdp->size, bdp->read_size, bdp->prog_size, bdp->erase_size);
HeapBlockDevice heap_bd(bdp->size, bdp->read_size, bdp->prog_size, bdp->erase_size);
FlashSimBlockDevice flash_sim_bd(&heap_bd);
BlockDevice *test_bd;
if (bd_num == num_bds - 1) {
test_bd = &flash_bd;
} else {
test_bd = &flash_sim_bd;
// We need to skip the test if we don't have enough memory for the heap block device.
// However, this device allocates the erase units on the fly, so "erase" it via the flash
// simulator. A failure here means we haven't got enough memory.
flash_sim_bd.init();
result = flash_sim_bd.erase(0, flash_sim_bd.size());
TEST_SKIP_UNLESS_MESSAGE(!result, "Not enough heap to run test");
flash_sim_bd.deinit();
}
delete[] dummy;
TDBStore *tdbs = new TDBStore(test_bd);
timer.reset();
result = tdbs->init();
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
elapsed = timer.read_ms();
printf("Elapsed time for init %d ms\n", elapsed);
timer.reset();
result = tdbs->reset();
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
elapsed = timer.read_ms();
printf("Elapsed time for reset is %d ms\n", elapsed);
result = tdbs->reserved_data_get(get_buf, strlen(res_val1));
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_ITEM_NOT_FOUND, result);
result = tdbs->reserved_data_set(res_val1, strlen(res_val1));
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
result = tdbs->reserved_data_set(res_val2, strlen(res_val2));
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_WRITE_FAILED, result);
result = tdbs->set(key1, key1_val1, strlen(key1_val1), 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
result = tdbs->set(key2, key2_val1, strlen(key2_val1), 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
result = tdbs->set(key2, key2_val2, strlen(key2_val2), 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
timer.reset();
result = tdbs->set(key2, key2_val3, strlen(key2_val3), 0);
elapsed = timer.read_ms();
printf("Elapsed time for set is %d ms\n", elapsed);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
result = tdbs->set(key3, key3_val1, strlen(key3_val1), 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
result = tdbs->get(key3, get_buf, sizeof(get_buf), &actual_data_size);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
TEST_ASSERT_EQUAL(strlen(key3_val1), actual_data_size);
TEST_ASSERT_EQUAL_STRING_LEN(key3_val1, get_buf, strlen(key3_val1));
KVStore::set_handle_t handle;
result = tdbs->set_start(&handle, key4, 15, 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
result = tdbs->set_add_data(handle, key4_val2, 10);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
result = tdbs->set_add_data(handle, key4_val2 + 10, 5);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
result = tdbs->set_finalize(handle);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
result = tdbs->get(key4, get_buf, sizeof(get_buf), &actual_data_size);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
TEST_ASSERT_EQUAL(15, actual_data_size);
TEST_ASSERT_EQUAL_STRING_LEN(key4_val2, get_buf, actual_data_size);
result = tdbs->get(key4, get_buf, 7, &actual_data_size, 4);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
TEST_ASSERT_EQUAL(7, actual_data_size);
TEST_ASSERT_EQUAL_STRING_LEN(key4_val2 + 4, get_buf, actual_data_size);
for (int j = 0; j < 2; j++) {
result = tdbs->set(key4, key4_val1, strlen(key4_val1), 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
result = tdbs->set(key4, key4_val2, strlen(key4_val2), 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
}
result = tdbs->remove(key3);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
result = tdbs->remove(key3);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_ITEM_NOT_FOUND, result);
result = tdbs->get_info(key5, &info);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_ITEM_NOT_FOUND, result);
result = tdbs->set(key5, key5_val1, strlen(key5_val1), KVStore::WRITE_ONCE_FLAG);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
result = tdbs->set(key5, key5_val2, strlen(key5_val2), 0);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_WRITE_PROTECTED, result);
result = tdbs->remove(key5);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_WRITE_PROTECTED, result);
result = tdbs->get_info(key5, &info);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
TEST_ASSERT_EQUAL(strlen(key5_val1), info.size);
TEST_ASSERT_EQUAL(KVStore::WRITE_ONCE_FLAG, info.flags);
result = tdbs->get(key5, get_buf, sizeof(get_buf), &actual_data_size);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
TEST_ASSERT_EQUAL(strlen(key5_val1), actual_data_size);
TEST_ASSERT_EQUAL_STRING_LEN(key5_val1, get_buf, strlen(key5_val1));
for (int i = 0; i < 2; i++) {
printf("%s deinit/init\n", i ? "After" : "Before");
result = tdbs->get(key1, get_buf, sizeof(get_buf), &actual_data_size);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
TEST_ASSERT_EQUAL(strlen(key1_val1), actual_data_size);
TEST_ASSERT_EQUAL_STRING_LEN(key1_val1, get_buf, strlen(key1_val1));
timer.reset();
result = tdbs->get(key2, get_buf, sizeof(get_buf), &actual_data_size);
elapsed = timer.read_ms();
printf("Elapsed time for get is %d ms\n", elapsed);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
TEST_ASSERT_EQUAL(strlen(key2_val3), actual_data_size);
TEST_ASSERT_EQUAL_STRING_LEN(key2_val3, get_buf, strlen(key2_val3));
result = tdbs->get(key3, get_buf, sizeof(get_buf), &actual_data_size);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_ITEM_NOT_FOUND, result);
result = tdbs->get(key4, get_buf, sizeof(get_buf), &actual_data_size);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
TEST_ASSERT_EQUAL(strlen(key4_val2), actual_data_size);
TEST_ASSERT_EQUAL_STRING_LEN(key4_val2, get_buf, strlen(key4_val2));
result = tdbs->get(key5, get_buf, sizeof(get_buf), &actual_data_size);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
TEST_ASSERT_EQUAL(strlen(key5_val1), actual_data_size);
TEST_ASSERT_EQUAL_STRING_LEN(key5_val1, get_buf, strlen(key5_val1));
KVStore::iterator_t it;
char *char_get_buf = reinterpret_cast <char *>(get_buf);
result = tdbs->iterator_open(&it, "This");
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
result = tdbs->iterator_next(it, char_get_buf, sizeof(get_buf));
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
bool got_key4 = !strcmp(key4, char_get_buf);
bool got_key5 = !strcmp(key5, char_get_buf);
TEST_ASSERT_EQUAL(true, got_key4 || got_key5);
result = tdbs->iterator_next(it, char_get_buf, sizeof(get_buf));
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
if (got_key4) {
TEST_ASSERT_EQUAL_STRING(key5, char_get_buf);
} else {
TEST_ASSERT_EQUAL_STRING(key4, char_get_buf);
}
result = tdbs->iterator_next(it, (char *)get_buf, sizeof(get_buf));
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_ITEM_NOT_FOUND, result);
result = tdbs->iterator_close(it);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
result = tdbs->reserved_data_get(get_buf, strlen(res_val1));
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
TEST_ASSERT_EQUAL_STRING_LEN(res_val1, get_buf, strlen(res_val1));
result = tdbs->deinit();
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
timer.reset();
result = tdbs->init();
elapsed = timer.read_ms();
printf("Elapsed time for init is %d ms\n", elapsed);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
}
result = tdbs->deinit();
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
delete tdbs;
}
}
static void multi_set_test()
{
char *key;
uint8_t *get_buf, *set_buf;
size_t key_size = 32;
size_t data_size = 512;
size_t num_keys = 16;
size_t set_iters = 3;
size_t actual_data_size;
int result;
mbed::Timer timer;
int elapsed;
size_t i;
uint8_t key_ind;
timer.start();
uint8_t *dummy = new (std::nothrow) uint8_t[heap_alloc_threshold_size];
TEST_SKIP_UNLESS_MESSAGE(dummy, "Not enough heap to run test");
#ifdef USE_HEAP_BD
// We need to skip the test if we don't have enough memory for the heap block device.
// However, this device allocates the erase units on the fly, so "erase" it via the flash
// simulator. A failure here means we haven't got enough memory.
flash_bd.init();
result = flash_bd.erase(0, flash_bd.size());
TEST_SKIP_UNLESS_MESSAGE(!result, "Not enough heap to run test");
flash_bd.deinit();
#endif
delete[] dummy;
TDBStore *tdbs = new TDBStore(&flash_bd);
timer.reset();
result = tdbs->init();
elapsed = timer.read_ms();
printf("Elapsed time for initial init is %d ms\n", elapsed);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
key = new char[key_size + 1];
get_buf = new uint8_t[data_size];
set_buf = new uint8_t[data_size];
srand(1);
for (i = 0; i < key_size; i++) {
// Alphabet characters only
key[i] = 'a' + rand() % ('z' - 'a' + 1);
}
key[key_size] = '\0';
for (i = 0; i < data_size; i++) {
set_buf[i] = rand() % 256;
}
int max_set_time = 0, total_set_time = 0;
int max_get_time = 0, total_get_time = 0;
timer.reset();
result = tdbs->reset();
elapsed = timer.read_ms();
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
for (i = 0; i < set_iters; i++) {
for (key_ind = 0; key_ind < num_keys; key_ind++) {
key[0] = 'A' + key_ind;
set_buf[0] = key_ind * (i + 1);
timer.reset();
result = tdbs->set(key, set_buf, data_size, 0);
elapsed = timer.read_ms();
TEST_ASSERT_EQUAL_ERROR_CODE(0, result);
if (elapsed > max_set_time) {
max_set_time = elapsed;
}
total_set_time += elapsed;
}
}
for (key_ind = 0; key_ind < num_keys; key_ind++) {
key[0] = 'A' + key_ind;
set_buf[0] = key_ind * set_iters;
timer.reset();
result = tdbs->get(key, get_buf, data_size, &actual_data_size);
elapsed = timer.read_ms();
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
TEST_ASSERT_EQUAL(data_size, actual_data_size);
TEST_ASSERT_EQUAL_STRING_LEN(set_buf, get_buf, data_size);
if (elapsed > max_get_time) {
max_get_time = elapsed;
}
total_get_time += elapsed;
}
printf("set time: Total (%d * %d times) - %d ms, Average - %d ms, Max - %d ms\n",
set_iters, num_keys, total_set_time,
total_set_time / (set_iters * num_keys), max_set_time);
printf("get time: Total (%d times) - %d ms, Average - %d ms, Max - %d ms\n",
num_keys, total_get_time,
total_get_time / num_keys, max_get_time);
result = tdbs->deinit();
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
timer.reset();
result = tdbs->init();
elapsed = timer.read_ms();
printf("Elapsed time for init is %d ms\n", elapsed);
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
result = tdbs->deinit();
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, result);
delete[] key;
delete[] get_buf;
delete[] set_buf;
delete tdbs;
}
utest::v1::status_t greentea_failure_handler(const Case *const source, const failure_t reason)
{
greentea_case_failure_abort_handler(source, reason);
return STATUS_CONTINUE;
}
Case cases[] = {
Case("TDBStore: White box test", white_box_test, greentea_failure_handler),
Case("TDBStore: Multiple set test", multi_set_test, greentea_failure_handler),
};
utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(120, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
int main()
{
return !Harness::run(specification);
}

View File

@@ -0,0 +1 @@
*

View File

@@ -0,0 +1,111 @@
/* Copyright (c) 2020 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "gtest/gtest.h"
#include "blockdevice/HeapBlockDevice.h"
#include "kvstore/FileSystemStore.h"
#include "littlefs/LittleFileSystem.h"
#include "mbed_error.h"
#include <stdlib.h>
#define HEAPBLOCK_SIZE (4096)
using namespace mbed;
class FileSystemStoreModuleTest : public testing::Test {
protected:
HeapBlockDevice heap{HEAPBLOCK_SIZE};
LittleFileSystem *fs;
FileSystemStore *store;
virtual void SetUp()
{
fs = new LittleFileSystem("kvstore", &heap);
if(fs->mount(&heap) != MBED_SUCCESS) {
EXPECT_EQ(fs->reformat(&heap), MBED_SUCCESS);
}
store = new FileSystemStore(fs);
EXPECT_EQ(store->init(), MBED_SUCCESS);
}
virtual void TearDown()
{
EXPECT_EQ(store->deinit(), MBED_SUCCESS);
delete store;
EXPECT_EQ(fs->unmount(), MBED_SUCCESS);
delete fs;
}
};
TEST_F(FileSystemStoreModuleTest, init)
{
EXPECT_EQ(store->deinit(), MBED_SUCCESS);
EXPECT_EQ(store->init(), MBED_SUCCESS);
EXPECT_EQ(store->init(), MBED_SUCCESS);
}
TEST_F(FileSystemStoreModuleTest, set_get)
{
char buf[100];
size_t size;
EXPECT_EQ(store->set("key", "data", 5, 0), MBED_SUCCESS);
EXPECT_EQ(store->get("key", buf, 100, &size), MBED_SUCCESS);
EXPECT_EQ(size, 5);
EXPECT_STREQ("data", buf);
}
TEST_F(FileSystemStoreModuleTest, erased_set_get)
{
EXPECT_EQ(store->deinit(), MBED_SUCCESS);
EXPECT_EQ(heap.init(), MBED_SUCCESS);
EXPECT_EQ(heap.erase(0, heap.size()), MBED_SUCCESS);
EXPECT_EQ(heap.deinit(), MBED_SUCCESS);
EXPECT_EQ(store->init(), MBED_SUCCESS);
char buf[100];
size_t size;
EXPECT_EQ(store->set("key", "data", 5, 0), MBED_SUCCESS);
EXPECT_EQ(store->get("key", buf, 100, &size), MBED_SUCCESS);
EXPECT_EQ(size, 5);
EXPECT_STREQ("data", buf);
}
TEST_F(FileSystemStoreModuleTest, set_deinit_init_get)
{
char buf[100];
size_t size;
for (int i = 0; i < 100; ++i) {
EXPECT_EQ(store->set("key", "data", 5, 0), MBED_SUCCESS);
EXPECT_EQ(store->deinit(), MBED_SUCCESS);
EXPECT_EQ(store->init(), MBED_SUCCESS);
EXPECT_EQ(store->get("key", buf, 100, &size), MBED_SUCCESS);
EXPECT_EQ(size, 5);
EXPECT_STREQ("data", buf);
EXPECT_EQ(store->remove("key"), MBED_SUCCESS);
}
}
TEST_F(FileSystemStoreModuleTest, set_multiple_iterate)
{
char buf[100];
KVStore::iterator_t iterator;
EXPECT_EQ(store->set("primary_key", "data", 5, 0), MBED_SUCCESS);
EXPECT_EQ(store->set("primary_second_key", "value", 6, 0), MBED_SUCCESS);
EXPECT_EQ(store->iterator_open(&iterator, "primary"), MBED_SUCCESS);
EXPECT_EQ(store->iterator_next(iterator, buf, 100), MBED_SUCCESS);
EXPECT_EQ(store->iterator_next(iterator, buf, 100), MBED_SUCCESS);
EXPECT_EQ(store->iterator_next(iterator, buf, 100), MBED_ERROR_ITEM_NOT_FOUND);
EXPECT_EQ(store->iterator_close(iterator), MBED_SUCCESS);
}

View File

@@ -0,0 +1,40 @@
####################
# UNIT TESTS
####################
set(unittest-includes ${unittest-includes}
.
..
../features/frameworks/mbed-trace/mbed-trace
)
set(unittest-sources
../storage/blockdevice/source/HeapBlockDevice.cpp
../storage/kvstore/source/FileSystemStore.cpp
../storage/filesystem/littlefs/source/LittleFileSystem.cpp
../storage/filesystem/source/Dir.cpp
../storage/filesystem/source/File.cpp
../storage/filesystem/source/FileSystem.cpp
../features/frameworks/mbed-trace/source/mbed_trace.c
../storage/filesystem/littlefs/littlefs/lfs_util.c
../storage/filesystem/littlefs/littlefs/lfs.c
../platform/source/FileBase.cpp
../platform/source/FileSystemHandle.cpp
../platform/source/FileHandle.cpp
)
set(unittest-test-sources
${CMAKE_CURRENT_LIST_DIR}/moduletest.cpp
stubs/mbed_atomic_stub.c
stubs/mbed_assert_stub.cpp
stubs/mbed_error.c
stubs/kv_config_stub.cpp
stubs/mbed_retarget_stub.cpp
)
set(unittest-test-flags
-DMBED_LFS_READ_SIZE=64
-DMBED_LFS_PROG_SIZE=64
-DMBED_LFS_BLOCK_SIZE=512
-DMBED_LFS_LOOKAHEAD=512
)

View File

@@ -0,0 +1,151 @@
/* Copyright (c) 2020 ARM Limited
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "gtest/gtest.h"
#include "blockdevice/HeapBlockDevice.h"
#include "blockdevice/FlashSimBlockDevice.h"
#include "kvstore/TDBStore.h"
#include <stdlib.h>
#define BLOCK_SIZE (512)
#define DEVICE_SIZE (BLOCK_SIZE*200)
using namespace mbed;
class TDBStoreModuleTest : public testing::Test {
protected:
HeapBlockDevice heap{DEVICE_SIZE};
FlashSimBlockDevice flash{&heap};
TDBStore tdb{&flash};
virtual void SetUp()
{
EXPECT_EQ(tdb.init(), MBED_SUCCESS);
EXPECT_EQ(tdb.reset(), MBED_SUCCESS);
}
virtual void TearDown()
{
EXPECT_EQ(tdb.deinit(), MBED_SUCCESS);
}
};
TEST_F(TDBStoreModuleTest, init)
{
EXPECT_EQ(tdb.deinit(), MBED_SUCCESS);
EXPECT_EQ(tdb.init(), MBED_SUCCESS);
EXPECT_EQ(tdb.init(), MBED_SUCCESS);
}
TEST_F(TDBStoreModuleTest, set_get)
{
char buf[100];
size_t size;
EXPECT_EQ(tdb.set("key", "data", 5, 0), MBED_SUCCESS);
EXPECT_EQ(tdb.get("key", buf, 100, &size), MBED_SUCCESS);
EXPECT_EQ(size, 5);
EXPECT_STREQ("data", buf);
}
TEST_F(TDBStoreModuleTest, erased_set_get)
{
EXPECT_EQ(tdb.deinit(), MBED_SUCCESS);
EXPECT_EQ(flash.init(), MBED_SUCCESS);
EXPECT_EQ(flash.erase(0, flash.size()), MBED_SUCCESS);
EXPECT_EQ(flash.deinit(), MBED_SUCCESS);
EXPECT_EQ(tdb.init(), MBED_SUCCESS);
char buf[100];
size_t size;
EXPECT_EQ(tdb.set("key", "data", 5, 0), MBED_SUCCESS);
EXPECT_EQ(tdb.get("key", buf, 100, &size), MBED_SUCCESS);
EXPECT_EQ(size, 5);
EXPECT_STREQ("data", buf);
}
TEST_F(TDBStoreModuleTest, set_deinit_init_get)
{
char buf[100];
size_t size;
for (int i = 0; i < 100; ++i) {
EXPECT_EQ(tdb.set("key", "data", 5, 0), MBED_SUCCESS);
EXPECT_EQ(tdb.deinit(), MBED_SUCCESS);
EXPECT_EQ(tdb.init(), MBED_SUCCESS);
EXPECT_EQ(tdb.get("key", buf, 100, &size), MBED_SUCCESS);
EXPECT_EQ(size, 5);
EXPECT_STREQ("data", buf);
EXPECT_EQ(tdb.remove("key"), MBED_SUCCESS);
}
}
TEST_F(TDBStoreModuleTest, corrupted_set_deinit_init_get)
{
char buf[100];
char *block = new char[BLOCK_SIZE];
size_t size;
EXPECT_EQ(heap.init(), MBED_SUCCESS); // Extra init, so the heap will not be deinitialized
srand(0); // Prefer to have always the same pattern
for (int i = 0; i < 100; ++i) {
EXPECT_EQ(tdb.deinit(), MBED_SUCCESS);
// Corrupt the first part of the storage
for (int j = 0; j < heap.size()/BLOCK_SIZE/2; j++) {
for (int k = 0; k < BLOCK_SIZE; k++) {
block[k] = rand();
}
EXPECT_EQ(heap.program(block, BLOCK_SIZE * j, BLOCK_SIZE), MBED_SUCCESS);
}
EXPECT_EQ(tdb.init(), MBED_SUCCESS);
for (int j = 0; j < 100; ++j) {
// Use random data, so the data has to be updated
EXPECT_EQ(tdb.set("key", block+j, 50, 0), MBED_SUCCESS);
EXPECT_EQ(tdb.deinit(), MBED_SUCCESS);
EXPECT_EQ(tdb.init(), MBED_SUCCESS);
EXPECT_EQ(tdb.get("key", buf, 100, &size), MBED_SUCCESS);
EXPECT_EQ(size, 50);
EXPECT_EQ(0, memcmp(buf, block+j, size));
}
EXPECT_EQ(tdb.remove("key"), MBED_SUCCESS);
}
EXPECT_EQ(heap.deinit(), MBED_SUCCESS);
delete[] block;
}
TEST_F(TDBStoreModuleTest, set_multiple_iterate)
{
char buf[100];
KVStore::iterator_t iterator;
EXPECT_EQ(tdb.set("primary_key", "data", 5, 0), MBED_SUCCESS);
EXPECT_EQ(tdb.set("primary_second_key", "value", 6, 0), MBED_SUCCESS);
EXPECT_EQ(tdb.iterator_open(&iterator, "primary"), MBED_SUCCESS);
EXPECT_EQ(tdb.iterator_next(iterator, buf, 100), MBED_SUCCESS);
EXPECT_EQ(tdb.iterator_next(iterator, buf, 100), MBED_SUCCESS);
EXPECT_EQ(tdb.iterator_next(iterator, buf, 100), MBED_ERROR_ITEM_NOT_FOUND);
EXPECT_EQ(tdb.iterator_close(iterator), MBED_SUCCESS);
}
TEST_F(TDBStoreModuleTest, reserved_data_set_get)
{
char reserved_key[] = "value";
char buf[64];
size_t size;
EXPECT_EQ(tdb.reserved_data_set(reserved_key, 6), MBED_SUCCESS);
EXPECT_EQ(tdb.reserved_data_get(buf, 64, &size), MBED_SUCCESS);
EXPECT_STREQ("value", buf);
EXPECT_EQ(size, 6);
EXPECT_EQ(tdb.reserved_data_set(reserved_key, 6), MBED_ERROR_WRITE_FAILED);
}

View File

@@ -0,0 +1,27 @@
####################
# UNIT TESTS
####################
set(unittest-includes ${unittest-includes}
.
..
../features/frameworks/mbed-trace/mbed-trace
)
set(unittest-sources
../storage/blockdevice/source/FlashSimBlockDevice.cpp
../storage/blockdevice/source/HeapBlockDevice.cpp
../storage/blockdevice/source/BufferedBlockDevice.cpp
../storage/kvstore/source/TDBStore.cpp
../features/frameworks/mbed-trace/source/mbed_trace.c
stubs/mbed_atomic_stub.c
stubs/mbed_assert_stub.cpp
stubs/mbed_error.c
)
set(unittest-test-sources
${CMAKE_CURRENT_LIST_DIR}/moduletest.cpp
)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")