Import Mbed OS hard-float snapshot
This commit is contained in:
@@ -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
|
||||
@@ -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 doesn’t 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
|
||||
@@ -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
|
||||
1015
storage/kvstore/tests/TESTS/kvstore/static_tests/main.cpp
Normal file
1015
storage/kvstore/tests/TESTS/kvstore/static_tests/main.cpp
Normal file
File diff suppressed because it is too large
Load Diff
471
storage/kvstore/tests/TESTS/kvstore/tdbstore_whitebox/main.cpp
Normal file
471
storage/kvstore/tests/TESTS/kvstore/tdbstore_whitebox/main.cpp
Normal 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);
|
||||
}
|
||||
1
storage/kvstore/tests/UNITTESTS/.mbedignore
Normal file
1
storage/kvstore/tests/UNITTESTS/.mbedignore
Normal file
@@ -0,0 +1 @@
|
||||
*
|
||||
111
storage/kvstore/tests/UNITTESTS/FileSystemStore/moduletest.cpp
Normal file
111
storage/kvstore/tests/UNITTESTS/FileSystemStore/moduletest.cpp
Normal 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);
|
||||
}
|
||||
@@ -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
|
||||
)
|
||||
151
storage/kvstore/tests/UNITTESTS/TDBStore/moduletest.cpp
Normal file
151
storage/kvstore/tests/UNITTESTS/TDBStore/moduletest.cpp
Normal 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);
|
||||
}
|
||||
27
storage/kvstore/tests/UNITTESTS/TDBStore/unittest.cmake
Normal file
27
storage/kvstore/tests/UNITTESTS/TDBStore/unittest.cmake
Normal 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}")
|
||||
Reference in New Issue
Block a user