mirror of https://github.com/ARMmbed/mbed-os.git
989 lines
31 KiB
C++
989 lines
31 KiB
C++
/* 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 "Thread.h"
|
||
#include "mbed_error.h"
|
||
#include "greentea-client/test_env.h"
|
||
#include "unity/unity.h"
|
||
#include "utest/utest.h"
|
||
#include "kvstore_global_api.h"
|
||
|
||
using namespace utest::v1;
|
||
using namespace mbed;
|
||
|
||
static const char data[] = "data";
|
||
static char key_buf[20] = {};
|
||
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;
|
||
static const char num_of_keys = 3;
|
||
|
||
static const int heap_alloc_threshold_size = 4096;
|
||
|
||
static const char *keys[] = {"key1", "key2", "key3"};
|
||
|
||
static int init_res = MBED_ERROR_NOT_READY;
|
||
|
||
kv_info_t info;
|
||
kv_iterator_t kvstore_it;
|
||
|
||
#define STR_EXPAND(tok) #tok
|
||
#define STR(tok) STR_EXPAND(tok)
|
||
|
||
/*----------------helpers------------------*/
|
||
|
||
static char *def_kv = NULL;
|
||
static char *key = NULL;
|
||
|
||
static void parse_default_kv()
|
||
{
|
||
const char *def_kv_temp = STR(MBED_CONF_STORAGE_DEFAULT_KV);
|
||
def_kv = new char[3 + strlen(def_kv_temp)];
|
||
sprintf(def_kv, "/%s/", def_kv_temp);
|
||
|
||
key = new char[4 + strlen(def_kv)];
|
||
sprintf(key, "%skey", def_kv);
|
||
}
|
||
|
||
/*----------------initialization------------------*/
|
||
|
||
//init the blockdevice
|
||
static void kvstore_init()
|
||
{
|
||
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;
|
||
|
||
parse_default_kv();
|
||
|
||
init_res = kv_reset(def_kv);
|
||
TEST_SKIP_UNLESS_MESSAGE(init_res != MBED_ERROR_UNSUPPORTED, "Unsupported configuration. Test skipped.");
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, init_res);
|
||
}
|
||
|
||
/*----------------set()------------------*/
|
||
|
||
//bad params : key is null
|
||
static void set_key_null()
|
||
{
|
||
TEST_SKIP_UNLESS(!init_res);
|
||
int res = kv_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(!init_res);
|
||
char key_max[KV_MAX_KEY_LENGTH + 1] = {};
|
||
memset(key_max, '*', KV_MAX_KEY_LENGTH);
|
||
int res = kv_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(!init_res);
|
||
int res = kv_set(key, NULL, data_size, 0);
|
||
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(!init_res);
|
||
int res = kv_set(key, data, 0, 0);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_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(!init_res);
|
||
int res = kv_set(key, data, data_size, 0);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_set(key, data, data_size, 0);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_set(key, data, data_size, 0);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_remove(key);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
}
|
||
|
||
static void test_thread_set(char *th_key)
|
||
{
|
||
TEST_SKIP_UNLESS(!init_res);
|
||
int res = kv_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(!init_res);
|
||
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 (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 = kv_get(keys[i], buffer, buffer_size, &actual_size);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
TEST_ASSERT_EQUAL_STRING_LEN(buffer, data, data_size);
|
||
|
||
res = kv_remove(keys[i]);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
}
|
||
}
|
||
|
||
//set key "write once" and try to set it again
|
||
static void set_write_once_flag_try_set_twice()
|
||
{
|
||
TEST_SKIP_UNLESS(!init_res);
|
||
char write_once_key[] = "write_once_key";
|
||
|
||
int res = kv_set(write_once_key, data, data_size, KV_WRITE_ONCE_FLAG);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_set(write_once_key, data, data_size, KV_WRITE_ONCE_FLAG);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_WRITE_PROTECTED, res);
|
||
}
|
||
|
||
//set key "write once" and try to remove it
|
||
static void set_write_once_flag_try_remove()
|
||
{
|
||
TEST_SKIP_UNLESS(!init_res);
|
||
int res = kv_set(key, data, data_size, KV_WRITE_ONCE_FLAG);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_remove(key);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_WRITE_PROTECTED, res);
|
||
|
||
res = kv_reset(def_kv);
|
||
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(!init_res);
|
||
char data_one = 'a';
|
||
int res = kv_set(key, &data_one, 1, 0);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_get(key, buffer, buffer_size, &actual_size);
|
||
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 = kv_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(!init_res);
|
||
char data_two[2] = "d";
|
||
int res = kv_set(key, data_two, 2, 0);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_get(key, buffer, buffer_size, &actual_size);
|
||
TEST_ASSERT_EQUAL_STRING_LEN(buffer, data_two, 1);
|
||
memset(buffer, 0, buffer_size);
|
||
|
||
res = kv_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(!init_res);
|
||
char data_five[5] = "data";
|
||
int res = kv_set(key, data_five, 5, 0);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_get(key, buffer, buffer_size, &actual_size);
|
||
TEST_ASSERT_EQUAL_STRING_LEN(buffer, data_five, 4);
|
||
memset(buffer, 0, buffer_size);
|
||
|
||
res = kv_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(!init_res);
|
||
char data_fif[15] = "data";
|
||
int res = kv_set(key, data_fif, 15, 0);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_get(key, buffer, buffer_size, &actual_size);
|
||
TEST_ASSERT_EQUAL_STRING_LEN(buffer, data_fif, 14);
|
||
memset(buffer, 0, buffer_size);
|
||
|
||
res = kv_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(!init_res);
|
||
char data_fif[17] = "data_is_everythi";
|
||
int res = kv_set(key, data_fif, 17, 0);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_get(key, buffer, buffer_size, &actual_size);
|
||
TEST_ASSERT_EQUAL_STRING_LEN(buffer, data_fif, 16);
|
||
memset(buffer, 0, buffer_size);
|
||
|
||
res = kv_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(!init_res);
|
||
char name[7] = "name_";
|
||
char c = 0;
|
||
int i = 0, res = 0;
|
||
|
||
name[6] = 0;
|
||
|
||
for (i = 0; i < 26; i++) {
|
||
c = i + 'a';
|
||
name[5] = c;
|
||
res = kv_set(name, name, sizeof(name), 0);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
}
|
||
|
||
for (i = 0; i < 26; i++) {
|
||
c = i + 'a';
|
||
name[5] = c;
|
||
res = kv_get(name, buffer, sizeof(buffer), &actual_size);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
TEST_ASSERT_EQUAL_STRING_LEN(name, buffer, sizeof(name));
|
||
memset(buffer, 0, sizeof(buffer));
|
||
|
||
res = kv_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(!init_res);
|
||
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 = kv_set(name, name, sizeof(name), 0);
|
||
if (unvalid[i] != '/') {
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_INVALID_ARGUMENT, res);
|
||
} else {
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_ITEM_NOT_FOUND, res);
|
||
}
|
||
}
|
||
}
|
||
|
||
/*----------------get()------------------*/
|
||
|
||
//bad params : key is null
|
||
static void get_key_null()
|
||
{
|
||
TEST_SKIP_UNLESS(!init_res);
|
||
int res = kv_get(NULL, buffer, buffer_size, &actual_size);
|
||
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(!init_res);
|
||
char key_max[KV_MAX_KEY_LENGTH + 1] = {};
|
||
memset(key_max, '*', KV_MAX_KEY_LENGTH);
|
||
int res = kv_get(key_max, buffer, buffer_size, &actual_size);
|
||
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(!init_res);
|
||
int res = kv_get(key, NULL, buffer_size, &actual_size);
|
||
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(!init_res);
|
||
int res = kv_set(key, NULL, 0, 0);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_get(key, buffer, 0, &actual_size);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_remove(key);
|
||
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(!init_res);
|
||
char big_data[25] = "data";
|
||
|
||
int res = kv_set(key, big_data, sizeof(big_data), 0);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_get(key, buffer, buffer_size, &actual_size);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
TEST_ASSERT_EQUAL_STRING_LEN(buffer, big_data, &actual_size);
|
||
memset(buffer, 0, buffer_size);
|
||
|
||
res = kv_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(!init_res);
|
||
int res = kv_set(key, data, data_size, 0);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
char big_buffer[25] = {};
|
||
res = kv_get(key, big_buffer, sizeof(big_buffer), &actual_size);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
TEST_ASSERT_EQUAL_STRING_LEN(big_buffer, data, &actual_size);
|
||
memset(buffer, 0, buffer_size);
|
||
|
||
res = kv_remove(key);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
}
|
||
|
||
//get a non existing key
|
||
static void get_non_existing_key()
|
||
{
|
||
TEST_SKIP_UNLESS(!init_res);
|
||
int res = kv_get(key, buffer, buffer_size, &actual_size);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_ITEM_NOT_FOUND, res);
|
||
}
|
||
|
||
//get a removed key
|
||
static void get_removed_key()
|
||
{
|
||
TEST_SKIP_UNLESS(!init_res);
|
||
int res = kv_set(key, data, data_size, 0);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_remove("key");
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_get(key, buffer, buffer_size, &actual_size);
|
||
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(!init_res);
|
||
int res = kv_set(key, data, data_size, 0);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
char new_data[] = "new_data";
|
||
res = kv_set(key, new_data, sizeof(new_data), 0);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_get(key, buffer, buffer_size, &actual_size);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
TEST_ASSERT_EQUAL_STRING_LEN(buffer, new_data, &actual_size);
|
||
memset(buffer, 0, buffer_size);
|
||
|
||
res = kv_remove(key);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
}
|
||
|
||
static void test_thread_get(const void *th_key)
|
||
{
|
||
TEST_SKIP_UNLESS(!init_res);
|
||
char buffer[5] = {0};
|
||
|
||
int res = kv_get((char *)th_key, buffer, sizeof(buffer), &actual_size);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
TEST_ASSERT_EQUAL_STRING((char *)th_key, buffer);
|
||
}
|
||
|
||
//get several keys multithreaded
|
||
static void get_several_keys_multithreaded()
|
||
{
|
||
TEST_SKIP_UNLESS(!init_res);
|
||
int i = 0, res = 0;
|
||
rtos::Thread kvstore_thread[num_of_threads];
|
||
osStatus threadStatus;
|
||
|
||
for (i = 0; i < num_of_threads; i++) {
|
||
res = kv_set(keys[i], keys[i], strlen(keys[i]) + 1, 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 (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 = kv_remove(keys[i]);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
}
|
||
}
|
||
|
||
/*----------------remove()------------------*/
|
||
|
||
//bad params : key is null
|
||
static void remove_key_null()
|
||
{
|
||
TEST_SKIP_UNLESS(!init_res);
|
||
int res = kv_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(!init_res);
|
||
char key_max[KV_MAX_KEY_LENGTH + 1] = {};
|
||
memset(key_max, '*', KV_MAX_KEY_LENGTH);
|
||
int res = kv_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(!init_res);
|
||
char new_key[] = "remove_key";
|
||
int res = kv_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(!init_res);
|
||
int res = kv_set(key, data, data_size, 0);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_remove(key);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_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(!init_res);
|
||
int res = kv_set(key, data, data_size, 0);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_remove(key);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
}
|
||
|
||
/*----------------get_info()------------------*/
|
||
|
||
//bad params : key is null
|
||
static void get_info_key_null()
|
||
{
|
||
TEST_SKIP_UNLESS(!init_res);
|
||
int res = kv_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(!init_res);
|
||
char key_max[KV_MAX_KEY_LENGTH + 1] = {};
|
||
memset(key_max, '*', KV_MAX_KEY_LENGTH);
|
||
int res = kv_get_info(key_max, &info);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_INVALID_ARGUMENT, res);
|
||
}
|
||
|
||
//bad params : &info is null
|
||
static void get_info_info_null()
|
||
{
|
||
TEST_SKIP_UNLESS(!init_res);
|
||
int res = kv_get_info(key, NULL);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_ITEM_NOT_FOUND, res);
|
||
}
|
||
|
||
//get_info of non existing key
|
||
static void get_info_non_existing_key()
|
||
{
|
||
TEST_SKIP_UNLESS(!init_res);
|
||
char new_key[] = "get_info_key";
|
||
int res = kv_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(!init_res);
|
||
int res = kv_set(key, data, data_size, 0);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_remove("key");
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_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(!init_res);
|
||
int res = kv_set(key, data, data_size, KV_WRITE_ONCE_FLAG);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_get_info(key, &info);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(info.flags, KV_WRITE_ONCE_FLAG);
|
||
|
||
res = kv_reset(def_kv);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
}
|
||
|
||
//get_info of overwritten key
|
||
static void get_info_overwritten_key()
|
||
{
|
||
TEST_SKIP_UNLESS(!init_res);
|
||
int res = kv_set(key, data, data_size, 0);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
char new_data[] = "new_data";
|
||
res = kv_set(key, new_data, sizeof(new_data), 0);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_get_info(key, &info);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(info.size, sizeof(new_data));
|
||
|
||
res = kv_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(!init_res);
|
||
int res = kv_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(!init_res);
|
||
int res = kv_iterator_open(&kvstore_it, NULL);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_iterator_next(kvstore_it, key_buf, 0);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_ITEM_NOT_FOUND, res);
|
||
|
||
res = kv_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(!init_res);
|
||
int res = kv_iterator_open(&kvstore_it, NULL);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_iterator_next(kvstore_it, key_buf, sizeof(key_buf));
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_ITEM_NOT_FOUND, res);
|
||
|
||
res = kv_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(!init_res);
|
||
int res = kv_set(key, data, data_size, 0);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_iterator_open(&kvstore_it, NULL);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_iterator_next(kvstore_it, key_buf, sizeof(key_buf));
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_iterator_close(kvstore_it);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_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(!init_res);
|
||
char new_key_1[] = "it_1";
|
||
int res = kv_set(new_key_1, data, data_size, 0);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
char new_key_2[] = "it_2";
|
||
res = kv_set(new_key_2, data, data_size, 0);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_remove(new_key_1);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_remove(new_key_2);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_iterator_open(&kvstore_it, NULL);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_iterator_next(kvstore_it, key_buf, sizeof(key_buf));
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_ITEM_NOT_FOUND, res);
|
||
|
||
res = kv_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(!init_res);
|
||
char new_key_1[] = "it_1";
|
||
int res = kv_set(new_key_1, data, data_size, 0);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
char new_key_2[] = "it_2";
|
||
res = kv_set(new_key_2, data, data_size, 0);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_iterator_open(&kvstore_it, "prefix");
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_iterator_next(kvstore_it, key_buf, sizeof(key_buf));
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_ITEM_NOT_FOUND, res);
|
||
|
||
res = kv_iterator_close(kvstore_it);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_remove(new_key_1);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_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(!init_res);
|
||
for (int i = 0; i < num_of_keys; i++) {
|
||
int res = kv_set(key, data, data_size, 0);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
}
|
||
|
||
int res = kv_iterator_open(&kvstore_it, NULL);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_iterator_next(kvstore_it, key_buf, sizeof(key_buf));
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_iterator_next(kvstore_it, key_buf, sizeof(key_buf));
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_ITEM_NOT_FOUND, res);
|
||
|
||
res = kv_iterator_close(kvstore_it);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_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(!init_res);
|
||
int i = 0;
|
||
bool *key_found = new bool[num_of_keys];
|
||
|
||
for (i = 0; i < num_of_keys; i++) {
|
||
int res = kv_set(keys[i], data, data_size, 0);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
key_found[i] = false;
|
||
}
|
||
|
||
int res = kv_iterator_open(&kvstore_it, NULL);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
char temp_key[KV_MAX_KEY_LENGTH];
|
||
|
||
for (i = 0; i < num_of_keys; i++) {
|
||
res = kv_iterator_next(kvstore_it, temp_key, sizeof(temp_key));
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_get(temp_key, buffer, buffer_size, &actual_size);
|
||
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 = kv_iterator_close(kvstore_it);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
for (i = 0; i < num_of_threads; i++) {
|
||
res = kv_remove(keys[i]);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
}
|
||
|
||
delete[] key_found;
|
||
}
|
||
|
||
//iterator_next for full path- check key names for validation
|
||
static void iterator_next_path_check()
|
||
{
|
||
TEST_SKIP_UNLESS(!init_res);
|
||
int res = kv_set(key, data, data_size, 0);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_iterator_open(&kvstore_it, def_kv);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
char temp_key[KV_MAX_KEY_LENGTH];
|
||
|
||
res = kv_iterator_next(kvstore_it, temp_key, sizeof(temp_key));
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
TEST_ASSERT_EQUAL_STRING(key, temp_key);
|
||
|
||
res = kv_iterator_close(kvstore_it);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_remove(key);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
}
|
||
|
||
//iteartor_next remove while iterating
|
||
static void iterator_next_remove_while_iterating()
|
||
{
|
||
TEST_SKIP_UNLESS(!init_res);
|
||
|
||
int i = 0, res = 0;
|
||
|
||
for (i = 0; i < num_of_keys; i++) {
|
||
int res = kv_set(keys[i], data, data_size, 0);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
}
|
||
|
||
char new_key_1[] = "new_key_1";
|
||
res = kv_set(new_key_1, data, data_size, 0);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
char new_key_2[] = "new_key_2";
|
||
res = kv_set(new_key_2, data, data_size, 0);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_iterator_open(&kvstore_it, "key");
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
char key[KV_MAX_KEY_LENGTH];
|
||
|
||
while (1) {
|
||
res = kv_iterator_next(kvstore_it, key, sizeof(key));
|
||
if (res != MBED_SUCCESS) {
|
||
break;
|
||
}
|
||
|
||
res = kv_remove(key);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
}
|
||
|
||
res = kv_iterator_open(&kvstore_it, NULL);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
while (1) {
|
||
res = kv_iterator_next(kvstore_it, key, sizeof(key));
|
||
if (res != MBED_SUCCESS) {
|
||
break;
|
||
}
|
||
|
||
TEST_ASSERT_EQUAL_STRING_LEN("new", key, 3);
|
||
|
||
res = kv_remove(key);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
}
|
||
|
||
res = kv_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(!init_res);
|
||
int res = kv_iterator_open(&kvstore_it, NULL);
|
||
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
|
||
|
||
res = kv_iterator_close(kvstore_it);
|
||
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;
|
||
}
|
||
|
||
Case cases[] = {
|
||
|
||
Case("kvstore_init", kvstore_init), //must be first
|
||
|
||
Case("set_key_null", set_key_null, greentea_failure_handler),
|
||
Case("set_key_length_exceeds_max", set_key_length_exceeds_max, greentea_failure_handler),
|
||
Case("set_buffer_null_size_not_zero", set_buffer_null_size_not_zero, greentea_failure_handler),
|
||
Case("set_buffer_size_is_zero", set_buffer_size_is_zero, greentea_failure_handler),
|
||
Case("set_same_key_several_time", set_same_key_several_time, greentea_failure_handler),
|
||
Case("set_several_keys_multithreaded", set_several_keys_multithreaded, greentea_failure_handler),
|
||
Case("set_write_once_flag_try_set_twice", set_write_once_flag_try_set_twice, greentea_failure_handler),
|
||
Case("set_write_once_flag_try_remove", set_write_once_flag_try_remove, greentea_failure_handler),
|
||
Case("set_key_value_one_byte_size", set_key_value_one_byte_size, greentea_failure_handler),
|
||
Case("set_key_value_two_byte_size", set_key_value_two_byte_size, greentea_failure_handler),
|
||
Case("set_key_value_five_byte_size", set_key_value_five_byte_size, greentea_failure_handler),
|
||
Case("set_key_value_fifteen_byte_size", set_key_value_fifteen_byte_size, greentea_failure_handler),
|
||
Case("set_key_value_seventeen_byte_size", set_key_value_seventeen_byte_size, greentea_failure_handler),
|
||
Case("set_several_key_value_sizes", set_several_key_value_sizes, greentea_failure_handler),
|
||
Case("set_several_unvalid_key_names", set_several_unvalid_key_names, greentea_failure_handler),
|
||
|
||
Case("get_key_null", get_key_null, greentea_failure_handler),
|
||
Case("get_key_length_exceeds_max", get_key_length_exceeds_max, greentea_failure_handler),
|
||
Case("get_buffer_null_size_not_zero", get_buffer_null_size_not_zero, greentea_failure_handler),
|
||
Case("get_buffer_size_is_zero", get_buffer_size_is_zero, greentea_failure_handler),
|
||
Case("get_buffer_size_smaller_than_data_real_size", get_buffer_size_smaller_than_data_real_size, greentea_failure_handler),
|
||
Case("get_buffer_size_bigger_than_data_real_size", get_buffer_size_bigger_than_data_real_size, greentea_failure_handler),
|
||
Case("get_non_existing_key", get_non_existing_key, greentea_failure_handler),
|
||
Case("get_removed_key", get_removed_key, greentea_failure_handler),
|
||
Case("get_key_that_was_set_twice", get_key_that_was_set_twice, greentea_failure_handler),
|
||
Case("get_several_keys_multithreaded", get_several_keys_multithreaded, greentea_failure_handler),
|
||
|
||
Case("remove_key_null", remove_key_null, greentea_failure_handler),
|
||
Case("remove_key_length_exceeds_max", remove_key_length_exceeds_max, greentea_failure_handler),
|
||
Case("remove_non_existing_key", remove_non_existing_key, greentea_failure_handler),
|
||
Case("remove_removed_key", remove_removed_key, greentea_failure_handler),
|
||
Case("remove_existed_key", remove_existed_key, greentea_failure_handler),
|
||
|
||
Case("get_info_key_null", get_info_key_null, greentea_failure_handler),
|
||
Case("get_info_key_length_exceeds_max", get_info_key_length_exceeds_max, greentea_failure_handler),
|
||
Case("get_info_info_null", get_info_info_null, greentea_failure_handler),
|
||
Case("get_info_non_existing_key", get_info_non_existing_key, greentea_failure_handler),
|
||
Case("get_info_removed_key", get_info_removed_key, greentea_failure_handler),
|
||
Case("get_info_existed_key", get_info_existed_key, greentea_failure_handler),
|
||
Case("get_info_overwritten_key", get_info_overwritten_key, greentea_failure_handler),
|
||
|
||
Case("iterator_open_it_null", iterator_open_it_null, greentea_failure_handler),
|
||
|
||
Case("iterator_next_key_size_zero", iterator_next_key_size_zero, greentea_failure_handler),
|
||
Case("iterator_next_empty_list", iterator_next_empty_list, greentea_failure_handler),
|
||
Case("iterator_next_one_key_list", iterator_next_one_key_list, greentea_failure_handler),
|
||
Case("iterator_next_empty_list_keys_removed", iterator_next_empty_list_keys_removed, greentea_failure_handler),
|
||
Case("iterator_next_empty_list_non_matching_prefix", iterator_next_empty_list_non_matching_prefix, greentea_failure_handler),
|
||
Case("iterator_next_several_overwritten_keys", iterator_next_several_overwritten_keys, greentea_failure_handler),
|
||
Case("iterator_next_full_list", iterator_next_full_list, greentea_failure_handler),
|
||
Case("iterator_next_path_check", iterator_next_path_check, greentea_failure_handler),
|
||
Case("iterator_next_remove_while_iterating", iterator_next_remove_while_iterating, greentea_failure_handler),
|
||
|
||
Case("iterator_close_right_after_iterator_open", iterator_close_right_after_iterator_open, greentea_failure_handler),
|
||
};
|
||
|
||
|
||
utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
|
||
{
|
||
GREENTEA_SETUP(3000, "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);
|
||
}
|