Merge pull request #244 from simonqhughes/master

Integrating configuration-store into mbed-os
Sam Grove 2016-06-09 10:08:46 +01:00
commit 28a39bdefd
64 changed files with 17364 additions and 0 deletions

View File

@ -0,0 +1,378 @@
/** @file add_del.cpp
*
* mbed Microcontroller Library
* Copyright (c) 2006-2016 ARM Limited
*
* 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.
*
* Test cases to add and delete KVs in the CFSTORE.
*/
#if defined __MBED__ && ! defined TOOLCHAIN_GCC_ARM
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#ifdef TARGET_LIKE_FRDM_K64F_GCC
#include <mbed-drivers/mbed.h>
#endif
#include "cfstore_config.h"
#include <Driver_Common.h>
#include "cfstore_debug.h"
#include "cfstore_test.h"
#include <configuration-store/configuration_store.h>
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#ifdef YOTTA_CFG_CFSTORE_UVISOR
#include "uvisor-lib/uvisor-lib.h"
#include "cfstore_uvisor.h"
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
using namespace utest::v1;
static control_t cfstore_add_del_test_00(const size_t call_count)
{
(void) call_count;
printf("Not implemented for ARM toolchain\n");
return CaseNext;
}
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(100, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
/* 1 2 3 4 5 6 7 */
/* 1234567890123456789012345678901234567890123456789012345678901234567890 */
Case("ADD_DEL_test_00", cfstore_add_del_test_00),
};
/* Declare your test specification with a custom setup handler */
Specification specification(greentea_setup, cases);
int main()
{
return !Harness::run(specification);
}
#else
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#ifdef TARGET_LIKE_FRDM_K64F_GCC
#include <mbed-drivers/mbed.h>
#endif
#include "cfstore_config.h"
//#include <flash-abstraction/Driver_Common.h>
#include <Driver_Common.h>
#include "cfstore_debug.h"
#include "cfstore_test.h"
#include <configuration-store/configuration_store.h>
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#include "cfstore_utest.h"
#ifdef YOTTA_CFG_CFSTORE_UVISOR
#include "uvisor-lib/uvisor-lib.h"
#include "cfstore_uvisor.h"
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
using namespace utest::v1;
static char cfstore_add_del_utest_msg_g[CFSTORE_UTEST_MSG_BUF_SIZE];
#ifdef YOTTA_CFG_CFSTORE_UVISOR
/* Create the main box ACL list for the application.
* The main ACL gets inherited by all the other boxes
*/
CFSTORE_UVISOR_MAIN_ACL(cfstore_acl_uvisor_box_add_del_g);
/* Enable uVisor. */
UVISOR_SET_MODE_ACL(UVISOR_ENABLED, cfstore_acl_uvisor_box_add_del_g);
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
static cfstore_kv_data_t cfstore_add_del_test_07_data[] = {
CFSTORE_INIT_1_TABLE_MID_NODE,
{ NULL, NULL},
};
/* report whether built/configured for flash sync or async mode */
static control_t cfstore_add_del_test_00(const size_t call_count)
{
(void) call_count;
ARM_CFSTORE_CAPABILITIES caps = cfstore_driver.GetCapabilities();
CFSTORE_LOG("INITIALIZING: caps.asynchronous_ops=%lu\n", caps.asynchronous_ops);
return CaseNext;
}
/**
* @brief test to open() a pre-existing key and try to write it, which should fail
*
* @return status code
* ARM_DRIVER_OK, the test passed successfully
* ret < ARM_DRIVER_OK, the test failed with the return code
* supplying more details
*/
static control_t cfstore_add_del_test_01_end(const size_t call_count)
{
bool bfound = false;
int32_t ret = ARM_DRIVER_ERROR;
ARM_CFSTORE_SIZE len = 0;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
ARM_CFSTORE_KEYDESC kdesc;
ARM_CFSTORE_HANDLE_INIT(hkey);
ARM_CFSTORE_FMODE flags;
CFSTORE_FENTRYLOG("%s:entered\n", __func__);
(void) call_count;
CFSTORE_LOG("cfstore_add_del_test_07: Start%s", "\n");
memset(&kdesc, 0, sizeof(kdesc));
memset(&flags, 0, sizeof(flags));
kdesc.drl = ARM_RETENTION_WHILE_DEVICE_ACTIVE;
len = strlen(cfstore_add_del_test_07_data[0].value);
ret = cfstore_test_create(cfstore_add_del_test_07_data[0].key_name, (char*) cfstore_add_del_test_07_data[0].value, &len, &kdesc);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_add_del_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create KV in store (ret=%" PRId32 ").\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_add_del_utest_msg_g);
/* now delete KV*/
ret = drv->Open(cfstore_add_del_test_07_data[0].key_name, flags, hkey);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_add_del_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to Open() (ret=%" PRId32 ").\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_add_del_utest_msg_g);
if(hkey != NULL){
ret = drv->Delete(hkey);
drv->Close(hkey);
hkey = NULL;
}
/* check that the KV has been deleted */
printf("LOG: WARNING: About to look for non-existent key (key_name=%s) (which will generate internal trace reporting errors if debug trace enabled).\n", cfstore_add_del_test_07_data[0].key_name);
ret = cfstore_test_kv_is_found(cfstore_add_del_test_07_data[0].key_name, &bfound);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_add_del_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error failed to delete a key (ret=%" PRId32 ").\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret == ARM_CFSTORE_DRIVER_ERROR_KEY_NOT_FOUND, cfstore_add_del_utest_msg_g);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_add_del_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Test failed: found KV that was previously deleted (key_name=%s)\n", __func__, cfstore_add_del_test_07_data[0].key_name);
TEST_ASSERT_MESSAGE(bfound == false, cfstore_add_del_utest_msg_g);
ret = drv->Uninitialize();
CFSTORE_TEST_UTEST_MESSAGE(cfstore_add_del_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Uninitialize() call failed.\n", __func__);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_add_del_utest_msg_g);
return CaseNext;
}
static cfstore_kv_data_t cfstore_add_del_test_08_data[] = {
CFSTORE_INIT_1_TABLE_HEAD,
CFSTORE_INIT_1_TABLE_MID_NODE,
CFSTORE_INIT_1_TABLE_TAIL,
{ NULL, NULL},
};
/**
* @brief test to add small number of KVs e.g. 3, and then delete them.
* basic delete test:
* - add key(s)
* - delete key(s)
* - make sure can't find key in cfstore
*
* @return status code
* ARM_DRIVER_OK, the test passed successfully
* ret < ARM_DRIVER_OK, the test failed with the return code
* supplying more details
*/
static control_t cfstore_add_del_test_02_end(const size_t call_count)
{
bool bResult = true; // We'll do "&=" cumulative checking.
int32_t ret = ARM_DRIVER_ERROR;
ARM_CFSTORE_SIZE len = 0;
ARM_CFSTORE_KEYDESC kdesc;
cfstore_kv_data_t* node = NULL;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
CFSTORE_FENTRYLOG("%s:entered\n", __func__);
(void) call_count;
CFSTORE_LOG("%s: Start\n", __func__);
memset(&kdesc, 0, sizeof(kdesc));
/* create */
kdesc.drl = ARM_RETENTION_WHILE_DEVICE_ACTIVE;
node = cfstore_add_del_test_08_data;
while(node->key_name != NULL)
{
len = strlen(node->value);
ret = cfstore_test_create(node->key_name, (char*) node->value, &len, &kdesc);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_add_del_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create kv (key_name=%s.\n", __func__, node->key_name);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_add_del_utest_msg_g);
CFSTORE_LOG("Created KV successfully (key_name=\"%s\", value=\"%s\")\n", node->key_name, node->value);
node++;
}
/* test delete all */
ret = cfstore_test_delete_all();
CFSTORE_TEST_UTEST_MESSAGE(cfstore_add_del_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to delete all KVs.\n", __func__);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_add_del_utest_msg_g);
/* check there are no KVs present as expected */
node = cfstore_add_del_test_08_data;
while(node->key_name != NULL)
{
ret = cfstore_test_kv_is_found(node->key_name, &bResult);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_add_del_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: found key when should not be present.\n", __func__);
TEST_ASSERT_MESSAGE(ret == ARM_CFSTORE_DRIVER_ERROR_KEY_NOT_FOUND && bResult == false, cfstore_add_del_utest_msg_g);
CFSTORE_LOG("Found KV successfully (key_name=\"%s\")\n", node->key_name);
node++;
}
ret = drv->Uninitialize();
CFSTORE_TEST_UTEST_MESSAGE(cfstore_add_del_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Uninitialize() call failed.\n", __func__);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_add_del_utest_msg_g);
return CaseNext;
}
/**
* @brief add ~50 KVs, and then delete entries at the start, middle and end of sram area
*
* @return status code
* ARM_DRIVER_OK, the test passed successfully
* ret < ARM_DRIVER_OK, the test failed with the return code
* supplying more details
*/
static control_t cfstore_add_del_test_03_end(const size_t call_count)
{
bool bfound = false;
int32_t ret = ARM_DRIVER_ERROR;
ARM_CFSTORE_FMODE flags;
cfstore_kv_data_t *node;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
CFSTORE_FENTRYLOG("%s:entered\n", __func__);
(void) call_count;
memset(&flags, 0, sizeof(flags));
ret = cfstore_test_init_1();
CFSTORE_TEST_UTEST_MESSAGE(cfstore_add_del_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to initialise cfstore area with entries\n", __func__);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_add_del_utest_msg_g);
/* delete some keys */
node = cfstore_add_del_test_08_data;
while(node->key_name != NULL)
{
CFSTORE_DBGLOG("%s:about to delete key (key_name=%s).\n", __func__, node->key_name);
cfstore_test_delete(node->key_name);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_add_del_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error failed to delete a key (ret=%" PRId32 ").\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_add_del_utest_msg_g);
CFSTORE_LOG("Deleted KV successfully (key_name=\"%s\")\n", node->key_name);
node++;
}
/* check the keys have been deleted */
node = cfstore_add_del_test_08_data;
while(node->key_name != NULL)
{
ret = cfstore_test_kv_is_found(node->key_name, &bfound);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_add_del_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to delete a key (ret=%" PRId32 ").\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret == ARM_CFSTORE_DRIVER_ERROR_KEY_NOT_FOUND, cfstore_add_del_utest_msg_g);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_add_del_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Test failed: found KV that was previously deleted (key_name=%s)\n", __func__, node->key_name);
TEST_ASSERT_MESSAGE(bfound == false, cfstore_add_del_utest_msg_g);
node++;
}
/* clean up by deleting all remaining KVs. this is not part of the test */
ret = cfstore_test_delete_all();
CFSTORE_TEST_UTEST_MESSAGE(cfstore_add_del_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error failed to delete a all KVs (ret=%" PRId32 ").\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_add_del_utest_msg_g);
ret = drv->Uninitialize();
CFSTORE_TEST_UTEST_MESSAGE(cfstore_add_del_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to initialize CFSTORE (ret=%" PRId32 ")\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_add_del_utest_msg_g);
return CaseNext;
}
/**
* @brief test as per test_09 but using delete_all() on all init_1 data.
*
* @return status code
* ARM_DRIVER_OK, the test passed successfully
* ret < ARM_DRIVER_OK, the test failed with the return code
* supplying more details
*/
static control_t cfstore_add_del_test_04(const size_t call_count)
{
(void) call_count;
/*todo: implement test */
CFSTORE_TEST_UTEST_MESSAGE(cfstore_add_del_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Warn: Not implemented\n", __func__);
CFSTORE_LOG("%s: WARN: requires implementation\n", __func__);
TEST_ASSERT_MESSAGE(true, cfstore_add_del_utest_msg_g);
return CaseNext;
}
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(100, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
/* 1 2 3 4 5 6 7 */
/* 1234567890123456789012345678901234567890123456789012345678901234567890 */
Case("ADD_DEL_test_00", cfstore_add_del_test_00),
Case("ADD_DEL_test_01_start", cfstore_utest_default_start),
Case("ADD_DEL_test_01_end", cfstore_add_del_test_01_end),
Case("ADD_DEL_test_02_start", cfstore_utest_default_start),
Case("ADD_DEL_test_02_end", cfstore_add_del_test_02_end),
Case("ADD_DEL_test_03_start", cfstore_utest_default_start),
Case("ADD_DEL_test_03_end", cfstore_add_del_test_03_end),
Case("ADD_DEL_test_04", cfstore_add_del_test_04),
};
/* Declare your test specification with a custom setup handler */
Specification specification(greentea_setup, cases);
#if defined CFSTORE_CONFIG_MBED_OS_VERSION && CFSTORE_CONFIG_MBED_OS_VERSION == 3
/* mbedosV3*/
void app_start(int argc __unused, char** argv __unused)
{
/* Run the test specification */
Harness::run(specification);
}
#endif /* CFSTORE_CONFIG_MBED_OS_VERSION == 3 */
#if defined CFSTORE_CONFIG_MBED_OS_VERSION && CFSTORE_CONFIG_MBED_OS_VERSION == 4
/* mbedosV3++*/
int main()
{
return !Harness::run(specification);
}
#endif /* CFSTORE_CONFIG_MBED_OS_VERSION == 4 */
#endif // __MBED__ && ! defined TOOLCHAIN_GCC_ARM

View File

@ -0,0 +1,321 @@
/*
* @file close.cpp
*
* mbed Microcontroller Library
* Copyright (c) 2006-2016 ARM Limited
*
* 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.
*
* Test cases to close KVs in the CFSTORE using the drv->Cpen() interface.
*/
#if defined __MBED__ && ! defined TOOLCHAIN_GCC_ARM
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#ifdef TARGET_LIKE_FRDM_K64F_GCC
#include <mbed-drivers/mbed.h>
#endif
#include "cfstore_config.h"
#include <Driver_Common.h>
#include "cfstore_debug.h"
#include "cfstore_test.h"
#include <configuration-store/configuration_store.h>
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#ifdef YOTTA_CFG_CFSTORE_UVISOR
#include "uvisor-lib/uvisor-lib.h"
#include "cfstore_uvisor.h"
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
using namespace utest::v1;
static control_t cfstore_close_test_00(const size_t call_count)
{
(void) call_count;
printf("Not implemented for ARM toolchain\n");
return CaseNext;
}
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(100, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
/* 1 2 3 4 5 6 7 */
/* 1234567890123456789012345678901234567890123456789012345678901234567890 */
Case("CLOSE_test_00", cfstore_close_test_00),
};
/* Declare your test specification with a custom setup handler */
Specification specification(greentea_setup, cases);
int main()
{
return !Harness::run(specification);
}
#else
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#ifdef TARGET_LIKE_FRDM_K64F_GCC
#include <mbed-drivers/mbed.h>
#endif
#include "cfstore_config.h"
//#include <flash-abstraction/Driver_Common.h>
#include <Driver_Common.h>
#include <configuration-store/configuration_store.h>
#include "cfstore_test.h"
#include "cfstore_debug.h"
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#include "cfstore_utest.h"
#ifdef YOTTA_CFG_CFSTORE_UVISOR
#include "uvisor-lib/uvisor-lib.h"
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
using namespace utest::v1;
static char cfstore_close_utest_msg_g[CFSTORE_UTEST_MSG_BUF_SIZE];
/* Configure secure box. */
#ifdef YOTTA_CFG_CFSTORE_UVISOR
UVISOR_BOX_NAMESPACE("com.arm.mbed.cfstore.test.close.box1");
UVISOR_BOX_CONFIG(cfstore_close_box1, UVISOR_BOX_STACK_SIZE);
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
/* KV data for test_01 */
static cfstore_kv_data_t cfstore_close_test_01_kv_data[] = {
{ "yotta.hello-world.animal{wobbly-dog}{foot}frontLeft", "first_data_"},
{ "yotta.hello-world.animal{wobbly-dog}{foot}frontLeft", "second_data"},
{ NULL, NULL},
};
/* report whether built/configured for flash sync or async mode */
static control_t cfstore_close_test_00(const size_t call_count)
{
(void) call_count;
ARM_CFSTORE_CAPABILITIES caps = cfstore_driver.GetCapabilities();
CFSTORE_LOG("INITIALIZING: caps.asynchronous_ops=%lu\n", caps.asynchronous_ops);
return CaseNext;
}
/** @brief basic test
*
* @note
*
* The test does the following:
* 01. create a key with handle hkey1
* 02. write data of hkey
* 03. opens KV with 2nd handle, hkey2
* 04. read data with hkey2 and make sure its the same as that written with hkey1
* 05. write new data with hkey2
* 06. delete hkey2
* 07. close hkey2
* 08. read hkey1 and make sure the data is the newly written data i.e. the key hasnt
* been deleted yet
* 09. try to open KV and make sure unable to do so, as KV is deleting
* 10. close hkey1
* 11. try to open KV and make sure unable to do so because its now been deleted
* 12. create new KV with same key_name to make sure can re-create the key again.
*
*
* @return status code
* ARM_DRIVER_OK, the test passed successfully
* ret < ARM_DRIVER_OK, the test failed with the return code
* supplying more details
*/
static control_t cfstore_close_test_01_end(const size_t call_count)
{
char read_buf[CFSTORE_KEY_NAME_MAX_LENGTH];
int32_t ret = ARM_DRIVER_ERROR;
ARM_CFSTORE_SIZE len = 0;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
ARM_CFSTORE_KEYDESC kdesc;
ARM_CFSTORE_HANDLE_INIT(hkey1);
ARM_CFSTORE_HANDLE_INIT(hkey2);
cfstore_kv_data_t *node;
ARM_CFSTORE_FMODE flags;
CFSTORE_DBGLOG("%s:entered\n", __func__);
(void) call_count;
node = &cfstore_close_test_01_kv_data[0];
memset(&kdesc, 0, sizeof(kdesc));
memset(&flags, 0, sizeof(flags));
memset(read_buf, 0, CFSTORE_KEY_NAME_MAX_LENGTH);
/* step 01 */
kdesc.drl = ARM_RETENTION_WHILE_DEVICE_ACTIVE;
CFSTORE_DBGLOG("%s:About to create new node (key_name=\"%s\", value=\"%s\")\n", __func__, node->key_name, node->value);
ret = drv->Create(node->key_name, strlen(node->value), &kdesc, hkey1);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_close_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create node (key_name=\"%s\", value=\"%s\")(ret=%" PRId32 ")\n", __func__, node->key_name, node->value, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_close_utest_msg_g);
CFSTORE_DBGLOG("%s:length of KV=%d (key_name=\"%s\", value=\"%s\")\n", __func__, (int) len, node->key_name, node->value);
/* step 02 */
len = strlen(node->value);
ret = drv->Write(hkey1, (char*) node->value, &len);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_close_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to write key (key_name=\"%s\", value=\"%s\")(ret=%" PRId32 ")\n", __func__, node->key_name, node->value, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_close_utest_msg_g);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_close_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to write full value data (key_name=\"%s\", value=\"%s\"), len=%d, (ret=%d)\n", __func__, node->key_name, node->value, (int) len, (int) ret);
TEST_ASSERT_MESSAGE(len == strlen(node->value), cfstore_close_utest_msg_g);
printf("Created KV successfully (key_name=\"%s\", value=\"%s\")\n", node->key_name, node->value);
/* step 03: Now open second handle while keeping first handle open */
flags.read = true;
flags.write = true;
ret = drv->Open(node->key_name, flags, hkey2);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_close_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to open node (key_name=\"%s\", value=\"%s\")(ret=%" PRId32 ")\n", __func__, node->key_name, node->value, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_close_utest_msg_g);
len = strlen(node->value) + 1;
printf("Opened KV successfully (key_name=\"%s\", value=\"%s\")\n", node->key_name, node->value);
/* step 04 */
ret = drv->Read(hkey2, read_buf, &len);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_close_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to read key (key_name=\"%s\", value=\"%s\")\n", __func__, node->key_name, node->value);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_close_utest_msg_g);
/* check read data is as expected */
CFSTORE_TEST_UTEST_MESSAGE(cfstore_close_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: read value data (%s) != KV value data (key_name=\"%s\", value=\"%s\")\n", __func__, read_buf, node->key_name, node->value);
TEST_ASSERT_MESSAGE(strncmp(read_buf, node->value, strlen(node->value)) == 0, cfstore_close_utest_msg_g);
/* step 05 write new data using hkey2 */
node = &cfstore_close_test_01_kv_data[1];
len = strlen(node->value);
ret = drv->Write(hkey2, (char*) node->value, &len);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_close_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to write key with 2nd handle (key_name=\"%s\", value=\"%s\")(ret=%" PRId32 ")\n", __func__, node->key_name, node->value, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_close_utest_msg_g);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_close_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to write full value data (key_name=\"%s\", value=\"%s\"), len=%d, (ret=%" PRId32 ")\n", __func__, node->key_name, node->value, (int) len, ret);
TEST_ASSERT_MESSAGE(len == strlen(node->value), cfstore_close_utest_msg_g);
printf("Wrote KV successfully with new data (key_name=\"%s\", value=\"%s\")\n", node->key_name, node->value);
/* step 06 delete hkey2 */
ret = drv->Delete(hkey2);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_close_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to Delete KV with 2nd handle (key_name=\"%s\", value=\"%s\")(ret=%" PRId32 ")\n", __func__, node->key_name, node->value, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_close_utest_msg_g);
/* step 07 close hkey2 */
ret = drv->Close(hkey2);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_close_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to Close KV with 2nd handle (key_name=\"%s\", value=\"%s\")(ret=%" PRId32 ")\n", __func__, node->key_name, node->value, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_close_utest_msg_g);
/* step 08 read hkey1 for updated data */
len = strlen(node->value) + 1;
memset(read_buf, 0, len);
ret = drv->Read(hkey1, read_buf, &len);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_close_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to read key with hkey1 (key_name=\"%s\", value=\"%s\")\n", __func__, node->key_name, node->value);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_close_utest_msg_g);
/* check read data is as expected */
CFSTORE_TEST_UTEST_MESSAGE(cfstore_close_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: read value data (%s) != KV value data (key_name=\"%s\", value=\"%s\")\n", __func__, read_buf, node->key_name, node->value);
TEST_ASSERT_MESSAGE(strncmp(read_buf, node->value, strlen(node->value)) == 0, cfstore_close_utest_msg_g);
/* step 09 */
ret = drv->Open(node->key_name, flags, hkey2);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_close_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Should not be able to open pre-existing key in deleting state (key_name=\"%s\", value=\"%s\")(ret=%" PRId32 ")\n", __func__, node->key_name, node->value, ret);
TEST_ASSERT_MESSAGE(ret == ARM_CFSTORE_DRIVER_ERROR_PREEXISTING_KEY_DELETING || ret == ARM_CFSTORE_DRIVER_ERROR_KEY_NOT_FOUND, cfstore_close_utest_msg_g);
/* step 10 close hkey1 */
ret = drv->Close(hkey1);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_close_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to Close KV with 1st handle (key_name=\"%s\", value=\"%s\")(ret=%" PRId32 ")\n", __func__, node->key_name, node->value, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_close_utest_msg_g);
/* step 11 try to open KV and make sure unable to do so because its now been deleted */
ret = drv->Open(node->key_name, flags, hkey1);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_close_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Should not be able to open key as it should not be present in the CFSTORE (key_name=\"%s\", value=\"%s\")(ret=%" PRId32 ")\n", __func__, node->key_name, node->value, ret);
TEST_ASSERT_MESSAGE(ret == ARM_CFSTORE_DRIVER_ERROR_KEY_NOT_FOUND, cfstore_close_utest_msg_g);
/* step 12. create new KV with same key_name to make sure can re-create the key again. */
node = &cfstore_close_test_01_kv_data[0];
len = strlen(node->value);
kdesc.drl = ARM_RETENTION_WHILE_DEVICE_ACTIVE;
CFSTORE_DBGLOG("%s:About to create new node (key_name=\"%s\", value=\"%s\")\n", __func__, node->key_name, node->value);
ret = drv->Create(node->key_name, strlen(node->value), &kdesc, hkey1);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_close_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create node (key_name=\"%s\", value=\"%s\")(ret=%" PRId32 ")\n", __func__, node->key_name, node->value, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_close_utest_msg_g);
CFSTORE_DBGLOG("%s:length of KV=%d (key_name=\"%s\", value=\"%s\")\n", __func__, (int) len, node->key_name, node->value);
len = strlen(node->value);
ret = drv->Write(hkey1, (char*) node->value, &len);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_close_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to write key (key_name=\"%s\", value=\"%s\")(ret=%" PRId32 ")\n", __func__, node->key_name, node->value, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_close_utest_msg_g);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_close_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to write full value data (key_name=\"%s\", value=\"%s\"), len=%d, (ret=%" PRId32 ")\n", __func__, node->key_name, node->value, (int) len, ret);
TEST_ASSERT_MESSAGE(len == strlen(node->value), cfstore_close_utest_msg_g);
printf("Created KV successfully (key_name=\"%s\", value=\"%s\")\n", node->key_name, node->value);
ret = drv->Uninitialize();
CFSTORE_TEST_UTEST_MESSAGE(cfstore_close_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Uninitialize() call failed.\n", __func__);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_close_utest_msg_g);
return CaseNext;
}
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(100, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
/* 1 2 3 4 5 6 7 */
/* 1234567890123456789012345678901234567890123456789012345678901234567890 */
Case("CLOSE_test_00", cfstore_close_test_00),
Case("CLOSE_test_01_start", cfstore_utest_default_start),
Case("CLOSE_test_01_end", cfstore_close_test_01_end)
};
/* Declare your test specification with a custom setup handler */
Specification specification(greentea_setup, cases);
#if defined CFSTORE_CONFIG_MBED_OS_VERSION && CFSTORE_CONFIG_MBED_OS_VERSION == 3
/* mbedosV3*/
void app_start(int argc __unused, char** argv __unused)
{
/* Run the test specification */
Harness::run(specification);
}
#endif /* CFSTORE_CONFIG_MBED_OS_VERSION == 3 */
#if defined CFSTORE_CONFIG_MBED_OS_VERSION && CFSTORE_CONFIG_MBED_OS_VERSION == 4
/* mbedosV3++*/
int main()
{
return !Harness::run(specification);
}
#endif /* CFSTORE_CONFIG_MBED_OS_VERSION == 4 */
#endif // __MBED__ && ! defined TOOLCHAIN_GCC_ARM

View File

@ -0,0 +1,760 @@
/** @file create.cpp
*
* mbed Microcontroller Library
* Copyright (c) 2006-2016 ARM Limited
*
* 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.
*
* Test cases to create KVs in the CFSTORE using the drv->Create() API call.
*/
#if defined __MBED__ && ! defined TOOLCHAIN_GCC_ARM
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#ifdef TARGET_LIKE_FRDM_K64F_GCC
#include <mbed-drivers/mbed.h>
#endif
#include "cfstore_config.h"
#include <Driver_Common.h>
#include "cfstore_debug.h"
#include "cfstore_test.h"
#include <configuration-store/configuration_store.h>
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#ifdef YOTTA_CFG_CFSTORE_UVISOR
#include "uvisor-lib/uvisor-lib.h"
#include "cfstore_uvisor.h"
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
using namespace utest::v1;
static control_t cfstore_create_test_00(const size_t call_count)
{
(void) call_count;
printf("Not implemented for ARM toolchain\n");
return CaseNext;
}
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(100, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
/* 1 2 3 4 5 6 7 */
/* 1234567890123456789012345678901234567890123456789012345678901234567890 */
Case("CREATE_test_00", cfstore_create_test_00),
};
/* Declare your test specification with a custom setup handler */
Specification specification(greentea_setup, cases);
int main()
{
return !Harness::run(specification);
}
#else
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#ifdef TARGET_LIKE_FRDM_K64F_GCC
#include <mbed-drivers/mbed.h>
#endif
#include "cfstore_config.h"
#include "cfstore_debug.h"
#include "cfstore_test.h"
//#include <flash-abstraction/Driver_Common.h>
#include <Driver_Common.h>
#include <configuration-store/configuration_store.h>
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#include "cfstore_utest.h"
#ifdef YOTTA_CFG_CFSTORE_UVISOR
#include "uvisor-lib/uvisor-lib.h"
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
using namespace utest::v1;
#ifdef CFSTORE_DEBUG
#define CFSTORE_CREATE_GREENTEA_TIMEOUT_S 360
#else
#define CFSTORE_CREATE_GREENTEA_TIMEOUT_S 60
#endif
static char cfstore_create_utest_msg_g[CFSTORE_UTEST_MSG_BUF_SIZE];
/* Configure secure box. */
#ifdef YOTTA_CFG_CFSTORE_UVISOR
UVISOR_BOX_NAMESPACE("com.arm.mbed.cfstore.test.create.box1");
UVISOR_BOX_CONFIG(cfstore_create_box1, UVISOR_BOX_STACK_SIZE);
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
#define CFSTORE_CREATE_TEST_01_TABLE_HEAD_ENTRY_01 { "Lefkada.Vathi.Meganisi.Atokos.Vathi.Ithaki.PeriPigathi.AgiosAndreas.Sami.Kefalonia.AgiaEffimia.AgiaSofia.Fiskardo.Frikes.Kioni.Meganissi.Lefkada", "Penelope"}
#define CFSTORE_CREATE_TEST_01_TABLE_HEAD_ENTRY_02 { "Iolcus.Lemnos.Salmydessus.Cyzicus.Cios.Berbryces.Symplegadese.IsleAres.Colchis.Anenea.Sirens.Scylia.Charybdis.Phaeacia.Triton.Iolcus", "Medea"}
#define CFSTORE_CREATE_TEST_01_TABLE_HEAD_ENTRY_03 { "338.Chaeronea.336.Macedonia.334.Granicus.333.Issus.332.Tyre.331.Gaugamela.330.Persepolis.Philotas.Parmenion.329.Bactria.Oxus.Samarkand.328.Cleitus.327.Roxane.326.Hydaspes.Bucephalus.324.Hephaestion.323.AlexanderDies", "TheGreat"}
#define CFSTORE_CREATE_TEST_01_TABLE_MID_ENTRY_01 { "0123456789abcdef0123456", "abcdefghijklmnopqrstuvwxyz"}
#define CFSTORE_CREATE_TEST_01_TABLE_MID_ENTRY_02 { "0123456789abcdef0123456", "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"}
#define CFSTORE_CREATE_TEST_01_TABLE_MID_ENTRY_03 { "0123456789abcdef0123456", "nopqrstuvwxyz"}
#define CFSTORE_CREATE_TEST_01_TABLE_TAIL_ENTRY_01 { "Time.Will.Explain.It.All", "Aegeus"}
#define CFSTORE_CREATE_TEST_01_TABLE_TAIL_ENTRY_02 { "Cleverness.Is.Not.Wisdom", "Bacchae"}
#define CFSTORE_CREATE_TEST_01_TABLE_TAIL_ENTRY_03 { "Talk.Sense.To.A.Fool.And.He.Calls.You.Foolish", "Bacchae"}
#define CFSTORE_CREATE_TEST_01_TABLE_TAIL_ENTRY_04 { "There.is.in.the.worst.of.fortune.the.best.of.chances.for.a.happy.change", "Iphigenia.in.Tauris"}
static cfstore_kv_data_t cfstore_create_test_01_data[] = {
CFSTORE_CREATE_TEST_01_TABLE_MID_ENTRY_01,
CFSTORE_CREATE_TEST_01_TABLE_MID_ENTRY_02,
CFSTORE_CREATE_TEST_01_TABLE_MID_ENTRY_03,
{ NULL, NULL},
};
/* table 1: to initialise cfstore with CFSTORE_CREATE_TEST_01_TABLE_MID_ENTRY_01 */
static cfstore_kv_data_t cfstore_create_test_01_data_step_01[] = {
CFSTORE_CREATE_TEST_01_TABLE_HEAD_ENTRY_01,
CFSTORE_CREATE_TEST_01_TABLE_HEAD_ENTRY_02,
CFSTORE_CREATE_TEST_01_TABLE_HEAD_ENTRY_03,
CFSTORE_CREATE_TEST_01_TABLE_MID_ENTRY_01,
CFSTORE_CREATE_TEST_01_TABLE_TAIL_ENTRY_01,
CFSTORE_CREATE_TEST_01_TABLE_TAIL_ENTRY_02,
CFSTORE_CREATE_TEST_01_TABLE_TAIL_ENTRY_03,
CFSTORE_CREATE_TEST_01_TABLE_TAIL_ENTRY_04,
{ NULL, NULL},
};
/* table 2: to CFSTORE_CREATE_TEST_01_TABLE_MID_ENTRY_01 grown to CFSTORE_CREATE_TEST_01_TABLE_MID_ENTRY_02 */
static cfstore_kv_data_t cfstore_create_test_01_data_step_02[] = {
CFSTORE_CREATE_TEST_01_TABLE_HEAD_ENTRY_01,
CFSTORE_CREATE_TEST_01_TABLE_HEAD_ENTRY_02,
CFSTORE_CREATE_TEST_01_TABLE_HEAD_ENTRY_03,
CFSTORE_CREATE_TEST_01_TABLE_MID_ENTRY_02,
CFSTORE_CREATE_TEST_01_TABLE_TAIL_ENTRY_01,
CFSTORE_CREATE_TEST_01_TABLE_TAIL_ENTRY_02,
CFSTORE_CREATE_TEST_01_TABLE_TAIL_ENTRY_03,
CFSTORE_CREATE_TEST_01_TABLE_TAIL_ENTRY_04,
{ NULL, NULL},
};
/* table 3: to CFSTORE_CREATE_TEST_01_TABLE_MID_ENTRY_02 shrunk to CFSTORE_CREATE_TEST_01_TABLE_MID_ENTRY_03 */
static cfstore_kv_data_t cfstore_create_test_01_data_step_03[] = {
CFSTORE_CREATE_TEST_01_TABLE_HEAD_ENTRY_01,
CFSTORE_CREATE_TEST_01_TABLE_HEAD_ENTRY_02,
CFSTORE_CREATE_TEST_01_TABLE_HEAD_ENTRY_03,
CFSTORE_CREATE_TEST_01_TABLE_MID_ENTRY_03,
CFSTORE_CREATE_TEST_01_TABLE_TAIL_ENTRY_01,
CFSTORE_CREATE_TEST_01_TABLE_TAIL_ENTRY_02,
CFSTORE_CREATE_TEST_01_TABLE_TAIL_ENTRY_03,
CFSTORE_CREATE_TEST_01_TABLE_TAIL_ENTRY_04,
{ NULL, NULL},
};
/* table 3: CFSTORE_CREATE_TEST_01_TABLE_MID_ENTRY_03 deleted */
static cfstore_kv_data_t cfstore_create_test_01_data_step_04[] = {
CFSTORE_CREATE_TEST_01_TABLE_HEAD_ENTRY_01,
CFSTORE_CREATE_TEST_01_TABLE_HEAD_ENTRY_02,
CFSTORE_CREATE_TEST_01_TABLE_HEAD_ENTRY_03,
CFSTORE_CREATE_TEST_01_TABLE_TAIL_ENTRY_01,
CFSTORE_CREATE_TEST_01_TABLE_TAIL_ENTRY_02,
CFSTORE_CREATE_TEST_01_TABLE_TAIL_ENTRY_03,
CFSTORE_CREATE_TEST_01_TABLE_TAIL_ENTRY_04,
{ NULL, NULL},
};
/* support functions */
/* @brief support function for generating value blob data */
static int32_t cfstore_create_kv_value_gen(char* value, const size_t len)
{
size_t i = 0;
size_t cpy_size = 0;
CFSTORE_FENTRYLOG("%s:entered\n", __func__);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_create_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: value pointer is null.\n", __func__);
TEST_ASSERT_MESSAGE(value != NULL, cfstore_create_utest_msg_g);
while(i < len)
{
cpy_size = len - i > CFSTORE_TEST_BYTE_DATA_TABLE_SIZE ? CFSTORE_TEST_BYTE_DATA_TABLE_SIZE : len - i;
memcpy(value + i, cfstore_test_byte_data_table, cpy_size);
i += cpy_size;
}
return ARM_DRIVER_OK;
}
static char* CFSTORE_CREATE_KV_CREATE_NO_TAG = NULL;
/* @brief
* support function to create a KV
* - a kv name is generated with the length name_len
* - a kv value blob is generated with the length value_len
*
* @param name_len the length of the kv_name
* @param name_tag tag to append to name, intended to enable large number of unique strings
* @param value_buf buffer to use for storing the generated value data
* @param value_len the length of the value to generate
*/
static int32_t cfstore_create_kv_create(size_t name_len, char* name_tag, char* value_buf, size_t value_len)
{
int32_t ret = ARM_DRIVER_OK;
size_t name_len_ex = name_len;
char kv_name[CFSTORE_KEY_NAME_MAX_LENGTH+1]; /* extra char for terminating null */
ARM_CFSTORE_KEYDESC kdesc;
CFSTORE_FENTRYLOG("%s:entered\n", __func__);
memset(kv_name, 0, CFSTORE_KEY_NAME_MAX_LENGTH+1);
memset(&kdesc, 0, sizeof(kdesc));
kdesc.drl = ARM_RETENTION_WHILE_DEVICE_ACTIVE;
name_len_ex = name_len;
if(name_tag){
name_len_ex += strlen(name_tag);
}
CFSTORE_TEST_UTEST_MESSAGE(cfstore_create_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: max supported KV name length for testing exceeded.\n", __func__);
TEST_ASSERT_MESSAGE(name_len_ex < CFSTORE_KEY_NAME_MAX_LENGTH+1, cfstore_create_utest_msg_g);
ret = cfstore_test_kv_name_gen(kv_name, name_len);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_create_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: unable to generate kv_name.\n", __func__);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK , cfstore_create_utest_msg_g);
/* append name tag */
if(name_tag){
strncat(kv_name, name_tag, CFSTORE_KEY_NAME_MAX_LENGTH);
}
CFSTORE_TEST_UTEST_MESSAGE(cfstore_create_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: kv_name is not the correct length (name_len_ex=%d, expected=%d).\n", __func__, (int) strlen(kv_name), (int) name_len_ex);
TEST_ASSERT_MESSAGE(strlen(kv_name) == name_len_ex, cfstore_create_utest_msg_g);
ret = cfstore_create_kv_value_gen(value_buf, value_len);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_create_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: unable to generate kv_name.\n", __func__);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK , cfstore_create_utest_msg_g);
ret = cfstore_test_create(kv_name, value_buf, &value_len, &kdesc);
if(ret == ARM_CFSTORE_DRIVER_ERROR_OUT_OF_MEMORY){
CFSTORE_ERRLOG("%s: Error: out of memory\n", __func__);
return ret;
}
CFSTORE_TEST_UTEST_MESSAGE(cfstore_create_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create KV in store for kv_name_good(ret=%" PRId32 ").\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_create_utest_msg_g);
return ret;
}
/* @brief cfstore_create_test_01() support function change the size of a value blob in the cfstore */
static int32_t cfstore_create_test_KV_change(const cfstore_kv_data_t* old_node, const cfstore_kv_data_t* new_node )
{
int32_t ret = ARM_DRIVER_ERROR;
size_t len = 0;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
ARM_CFSTORE_HANDLE_INIT(hkey);
ARM_CFSTORE_FMODE flags;
ARM_CFSTORE_KEYDESC kdesc;
CFSTORE_DBGLOG("%s:entered\n", __func__);
memset(&flags, 0, sizeof(flags));
memset(&kdesc, 0, sizeof(kdesc));
/* check node key_names are identical */
if(strncmp(old_node->key_name, new_node->key_name, strlen(old_node->key_name)) != 0){
CFSTORE_ERRLOG("%s:old and new entries so not have the same key_name (old_key_name=%s, new_key_name=%s).\n", __func__, old_node->key_name, new_node->key_name);
return ret;
}
len = strlen(new_node->value);
/* supply NULL key descriptor to open a pre-existing key for increasing the blob size */
ret = drv->Create(new_node->key_name, len, NULL, hkey);
if(ret < ARM_DRIVER_OK){
CFSTORE_ERRLOG("%s:Error: failed to change size of KV (key_name=%s)(ret=%d).\n", __func__, new_node->key_name, (int) ret);
goto out1;
}
len = strlen(new_node->value);
ret = drv->Write(hkey, new_node->value, &len);
if(ret < ARM_DRIVER_OK){
CFSTORE_ERRLOG("%s:Error: failed to write KV (key_name=%s)(ret=%d).\n", __func__, new_node->key_name, (int) ret);
goto out2;
}
if(len != strlen(new_node->value)){
CFSTORE_DBGLOG("%s:Failed wrote (%d) rather than the correct number of bytes (%d).\n", __func__, (int) len, (int) strlen(cfstore_create_test_01_data[1].value));
goto out2;
}
out2:
drv->Close(hkey);
out1:
return ret;
}
/* report whether built/configured for flash sync or async mode */
static control_t cfstore_create_test_00(const size_t call_count)
{
(void) call_count;
CFSTORE_LOG("INITIALIZING: caps.asynchronous_ops=%lu\n", cfstore_driver.GetCapabilities().asynchronous_ops);
return CaseNext;
}
/**
* @brief test to change the value blob size of pre-existing key
*
* @notes
*
* The test does the following:
* - creates a cfstore with ~10 entries.
* - for a mid-cfstore entry, grow the value blob size
* - check all the cfstore entries can be read correctly and their
* data agrees with the data supplied upon creation.
* - grow the mid-entry value blob size to be ~double the initial size.
* - check all the cfstore entries can be read correctly and their
* data agrees with the data supplied upon creation.
*
* @return status code
* ARM_DRIVER_OK, the test passed successfully
* ret < ARM_DRIVER_OK, the test failed with the return code
* supplying more details
*/
static control_t cfstore_create_test_01_end(const size_t call_count)
{
int32_t ret = ARM_DRIVER_ERROR;
ARM_CFSTORE_FMODE flags;
cfstore_kv_data_t* node = NULL;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
CFSTORE_FENTRYLOG("%s:entered\n", __func__);
(void) call_count;
memset(&flags, 0, sizeof(flags));
ret = cfstore_test_create_table(cfstore_create_test_01_data_step_01);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_create_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Failed to add cfstore_create_test_01_data_head (ret=%" PRId32 ").\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_create_utest_msg_g);
/* find cfstore_create_test_01_data[0] and grow the KV MID_ENTRY_01 to MID_ENTRY_02 */
ret = cfstore_create_test_KV_change(&cfstore_create_test_01_data[0], &cfstore_create_test_01_data[1]);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_create_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Failed to increase size of KV (ret=%" PRId32 ").\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_create_utest_msg_g);
/* Now check that the KVs are all present and correct */
node = cfstore_create_test_01_data_step_02;
while(node->key_name != NULL)
{
ret = cfstore_test_check_node_correct(node);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_create_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:node (key_name=\"%s\", value=\"%s\") not correct in cfstore\n", __func__, node->key_name, node->value);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_create_utest_msg_g);
node++;
}
CFSTORE_LOG("KV successfully increased in size and other KVs remained unchanged.%s", "\n");
/* Shrink the KV from KV MID_ENTRY_02 to MID_ENTRY_03 */
ret = cfstore_create_test_KV_change(&cfstore_create_test_01_data[1], &cfstore_create_test_01_data[2]);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_create_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Failed to decrease size of KV (ret=%" PRId32 ").\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_create_utest_msg_g);
/* Now check that the KVs are all present and correct */
node = cfstore_create_test_01_data_step_03;
while(node->key_name != NULL)
{
ret = cfstore_test_check_node_correct(node);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_create_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:node (key_name=\"%s\", value=\"%s\") not correct in cfstore\n", __func__, node->key_name, node->value);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_create_utest_msg_g);
node++;
}
CFSTORE_LOG("KV successfully decreased in size and other KVs remained unchanged.%s", "\n");
/* Delete the KV */
ret = cfstore_test_delete(cfstore_create_test_01_data[2].key_name);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_create_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:failed to delete node(key_name=\"%s\")\n", __func__, node->key_name);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_create_utest_msg_g);
/* Now check that the KVs are all present and correct */
node = cfstore_create_test_01_data_step_04;
while(node->key_name != NULL)
{
ret = cfstore_test_check_node_correct(node);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_create_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:node (key_name=\"%s\", value=\"%s\") not correct in cfstore\n", __func__, node->key_name, node->value);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_create_utest_msg_g);
node++;
}
ret = drv->Uninitialize();
CFSTORE_TEST_UTEST_MESSAGE(cfstore_create_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Uninitialize() call failed.\n", __func__);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_create_utest_msg_g);
return CaseNext;
}
/**
* @brief create the 10 kvs.
* @note
* The amount of data store in the cfstore is as follows:
* - 10 kvs
* - kv name lengths are ~220 => ~ 2200 bytes
* - value blob length is 1x256, 2x256, 3x256, ... 10x256)) = 256(1+2+3+4+..10) = 256*10*11/2 = 14080
* - kv overhead = 8bytes/kv = 8 * 10 = 80bytes
* - total = (220*10)+256*10*11/2 10*8 = 143800 bytes
*
*
* @return status code
* ARM_DRIVER_OK, the test passed successfully
* ret < ARM_DRIVER_OK, the test failed with the return code
* supplying more details
*/
static int32_t cfstore_create_test_02_core(const size_t call_count)
{
int32_t ret = ARM_DRIVER_ERROR;
uint32_t i = 0;
uint32_t bytes_stored = 0;
const uint32_t max_num_kvs_create = 10;
const size_t kv_name_min_len = CFSTORE_KEY_NAME_MAX_LENGTH - max_num_kvs_create;
const size_t kv_value_min_len = CFSTORE_TEST_BYTE_DATA_TABLE_SIZE;
const size_t max_value_buf_size = kv_value_min_len * (max_num_kvs_create +1);
char value_buf[max_value_buf_size];
CFSTORE_FENTRYLOG("%s:entered\n", __func__);
(void) call_count;
memset(value_buf, 0, max_value_buf_size);
for(i = 0; i < max_num_kvs_create; i++)
{
memset(value_buf, 0, max_value_buf_size);
ret = cfstore_create_kv_create(kv_name_min_len +i, CFSTORE_CREATE_KV_CREATE_NO_TAG, value_buf, kv_value_min_len * (i+1));
bytes_stored += kv_name_min_len + i; /* kv_name */
bytes_stored += kv_value_min_len * (i+1); /* kv value blob */
bytes_stored += 8; /* kv overhead */
if(ret == ARM_CFSTORE_DRIVER_ERROR_OUT_OF_MEMORY){
CFSTORE_ERRLOG("Out of memory on %" PRId32 "-th KV, trying to allocate memory totalling %" PRIu32 ".\n", i, bytes_stored);
break;
}
CFSTORE_DBGLOG("Successfully stored %" PRId32 "-th KV bytes, totalling %" PRIu32 ".\n", i, bytes_stored);
}
ret = cfstore_test_delete_all();
CFSTORE_TEST_UTEST_MESSAGE(cfstore_create_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to delete_all() attributes to clean up after test (ret=%" PRId32 ").\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_create_utest_msg_g);
return ret;
}
static control_t cfstore_create_test_02_end(const size_t call_count)
{
int32_t ret;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
CFSTORE_FENTRYLOG("%s:entered\n", __func__);
(void) call_count;
ret = cfstore_create_test_02_core(call_count);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_create_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: something went wrong (ret=%" PRId32 ").\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_create_utest_msg_g);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_create_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Uninitialize() call failed.\n", __func__);
TEST_ASSERT_MESSAGE(drv->Uninitialize() >= ARM_DRIVER_OK, cfstore_create_utest_msg_g);
return CaseNext;
}
static control_t cfstore_create_test_03_end(const size_t call_count)
{
int32_t i = 0;
int32_t ret;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
CFSTORE_FENTRYLOG("%s:entered\n", __func__);
for(i = 0; i < 100; i++)
{
ret = cfstore_create_test_02_core(call_count);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_create_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: something went wrong (ret=%" PRId32 ").\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_create_utest_msg_g);
CFSTORE_LOG("Successfully completed create/destroy loop %" PRId32 ".\n", i);
}
CFSTORE_TEST_UTEST_MESSAGE(cfstore_create_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Uninitialize() call failed.\n", __func__);
TEST_ASSERT_MESSAGE(drv->Uninitialize() >= ARM_DRIVER_OK, cfstore_create_utest_msg_g);
return CaseNext;
}
/**
* @brief create the 100 kvs to make the device run out of memory
* @note
* The amount of data store in the cfstore is as follows:
* - total = (220*100)+256*100*101/2 100*8 = 1315600 = 1.315x10^6
*
* @return status code
* ARM_DRIVER_OK, the test passed successfully
* ret < ARM_DRIVER_OK, the test failed with the return code
* supplying more details
*/
static control_t cfstore_create_test_04_end(const size_t call_count)
{
int32_t ret = ARM_DRIVER_ERROR;
uint32_t i = 0;
uint32_t bytes_stored = 0;
const uint32_t max_num_kvs_create = 100;
const size_t kv_name_min_len = CFSTORE_KEY_NAME_MAX_LENGTH - max_num_kvs_create;
const size_t kv_value_min_len = CFSTORE_TEST_BYTE_DATA_TABLE_SIZE;
const size_t max_value_buf_size = kv_value_min_len/8 * (max_num_kvs_create +1);
char* value_buf = NULL;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
CFSTORE_FENTRYLOG("%s:entered\n", __func__);
(void) call_count;
value_buf = (char*) malloc(max_value_buf_size);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_create_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: out of memory.\n", __func__);
TEST_ASSERT_MESSAGE(value_buf != NULL, cfstore_create_utest_msg_g);
for(i = 0; i < max_num_kvs_create; i++)
{
memset(value_buf, 0, max_value_buf_size);
ret = cfstore_create_kv_create(kv_name_min_len +i, CFSTORE_CREATE_KV_CREATE_NO_TAG, value_buf, kv_value_min_len/8 * (i+1));
bytes_stored += kv_name_min_len + i; /* kv_name */
bytes_stored += kv_value_min_len/8 * (i+1); /* kv value blob */
bytes_stored += 8; /* kv overhead */
if(ret == ARM_CFSTORE_DRIVER_ERROR_OUT_OF_MEMORY){
CFSTORE_LOG("Out of memory on %" PRId32 "-th KV, trying to allocate memory totalling %" PRIu32 ".\n", i, bytes_stored);
break;
}
CFSTORE_LOG("Successfully stored %" PRId32 "-th KV bytes, totalling %" PRIu32 ".\n", i, bytes_stored);
}
ret = cfstore_test_delete_all();
CFSTORE_TEST_UTEST_MESSAGE(cfstore_create_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to delete_all() attributes to clean up after test (ret=%" PRId32 ").\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_create_utest_msg_g);
free(value_buf);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_create_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Uninitialize() call failed.\n", __func__);
TEST_ASSERT_MESSAGE(drv->Uninitialize() >= ARM_DRIVER_OK, cfstore_create_utest_msg_g);
return CaseNext;
}
/**
* @brief create the 500 kvs.
* @note
* The amount of data store in the cfstore is as follows:
* - total = (220*500)+(256/64)*500*501/2 500*8 = 8236000 = 8.236M
*
* @return status code
* ARM_DRIVER_OK, the test passed successfully
* ret < ARM_DRIVER_OK, the test failed with the return code
* supplying more details
*/
static control_t cfstore_create_test_05_end(const size_t call_count)
{
int32_t ret = ARM_DRIVER_ERROR;
uint32_t i = 0;
uint32_t bytes_stored = 0;
const uint32_t max_num_kvs_create = 200;
const size_t kv_name_tag_len = 3;
const size_t kv_name_min_len = 10;
const size_t kv_value_min_len = CFSTORE_TEST_BYTE_DATA_TABLE_SIZE;
const size_t max_value_buf_size = kv_value_min_len/64 * (max_num_kvs_create+1);
char kv_name_tag_buf[kv_name_tag_len+1];
char* value_buf = NULL;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
CFSTORE_FENTRYLOG("%s:entered\n", __func__);
(void) call_count;
value_buf = (char*) malloc(max_value_buf_size);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_create_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: out of memory.\n", __func__);
TEST_ASSERT_MESSAGE(value_buf != NULL, cfstore_create_utest_msg_g);
for(i = 0; i < max_num_kvs_create; i++)
{
memset(value_buf, 0, max_value_buf_size);
snprintf(kv_name_tag_buf, kv_name_tag_len+1, "%0d", (int) i);
ret = cfstore_create_kv_create(kv_name_min_len, kv_name_tag_buf, value_buf, kv_value_min_len/64 * (i+1));
bytes_stored += kv_name_min_len + i + strlen(kv_name_tag_buf); /* kv_name */
bytes_stored += kv_value_min_len/64 * (i+1); /* kv value blob */
bytes_stored += 8; /* kv overhead */
if(ret == ARM_CFSTORE_DRIVER_ERROR_OUT_OF_MEMORY){
CFSTORE_LOG("Out of memory on %" PRId32 "-th KV, trying to allocate memory totalling %" PRIu32 ".\n", i, bytes_stored);
break;
}
CFSTORE_LOG("Successfully stored %" PRId32 "-th KV bytes, totalling %" PRIu32 ".\n", i, bytes_stored);
}
ret = cfstore_test_delete_all();
CFSTORE_TEST_UTEST_MESSAGE(cfstore_create_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to delete_all() attributes to clean up after test.\n", __func__);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_create_utest_msg_g);
free(value_buf);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_create_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Uninitialize() call failed.\n", __func__);
TEST_ASSERT_MESSAGE(drv->Uninitialize() >= ARM_DRIVER_OK, cfstore_create_utest_msg_g);
return CaseNext;
}
typedef struct cfstore_create_key_name_validate_t {
const char* key_name;
uint32_t f_allowed : 1;
} cfstore_create_key_name_validate_t;
cfstore_create_key_name_validate_t cfstore_create_test_06_data[] = {
/* ruler for measuring text strings */
/* 1 1 1 1 1 1 1 1 1 1 2 2 2 */
/* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 */
/* 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 */
{ "", false},
{ "abc.{1}.efg", true },
{ "abc.{1.efg", false },
{ "abc.1}.efg", false },
{ "abc.{{1}}.efg", false },
{ "abc.{}.efg", true },
{ "abc.}1{.efg", false },
{ ".piety.demands.us.to.honour.truth.above.our.friends", false },
{ "basement.medicine.pavement.government.trenchcoat.off.cough.off.kid.did.when.again.alleyway.friend.cap.pen.dollarbills.ten.foot.soot.put.but.anyway.say.May.DA.kid.did.toes.bows.those.hose.nose.clothes.man.blows.{100000000}", false },
{ NULL, false},
};
/**
* @brief function to test whether a key name can be created or not
*
* @param key_name
* name of the key to create in the store
* @param should_create
* if true, then create KV should succeed, otherwise should fail.
*
* @return status code
* ARM_DRIVER_OK, the test passed successfully
* ret < ARM_DRIVER_OK, the test failed with the return code
* supplying more details
*/
bool cfstore_create_key_name_validate(const char *key_name, bool should_create)
{
bool bret = false;
char* test_data = (char*) "test_data";
int32_t ret = ARM_DRIVER_ERROR;
ARM_CFSTORE_SIZE len = 0;
ARM_CFSTORE_KEYDESC kdesc;
CFSTORE_FENTRYLOG("%s:entered\r\n", __func__);
memset(&kdesc, 0, sizeof(kdesc));
/* create */
kdesc.drl = ARM_RETENTION_WHILE_DEVICE_ACTIVE;
len = strlen(test_data);
ret = cfstore_test_create((const char*) key_name, test_data, &len, &kdesc);
/* dont not use any functions that require finding the created item as they may not work,
* depending on the construction of the test key_name & match strings */
if(should_create == true)
{
if(ret < ARM_DRIVER_OK){
CFSTORE_ERRLOG("%s:Error: failed to create kv (key_name=%s.\r\n", __func__, key_name);
return bret;
}
CFSTORE_DBGLOG("%s:Success: Create() behaved as expected.\r\n", __func__);
/* delete using the actual name */
ret = cfstore_test_delete((const char*) key_name);
if(ret < ARM_DRIVER_OK){
CFSTORE_ERRLOG("%s:Error: failed to delete kv (key_name=%s)(ret=%d).\r\n", __func__, key_name, (int)ret);
}
bret = true;
}
else
{
if(ret >= ARM_DRIVER_OK){
CFSTORE_ERRLOG("%s:Error: created kv (key_name=%s) when Create() should have failed.\r\n", __func__, key_name);
return bret;
}
/* the operation failed which was the expected result hence return true*/
bret = true;
}
return bret;
}
/**
* @brief check that key names with non-matching braces etc do no get created.
*
* @return status code
* ARM_DRIVER_OK, the test passed successfully
* ret < ARM_DRIVER_OK, the test failed with the return code
* supplying more details
*/
static control_t cfstore_create_test_06_end(const size_t call_count)
{
bool ret = false;
int32_t ret32 = ARM_DRIVER_ERROR;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
cfstore_create_key_name_validate_t* node = cfstore_create_test_06_data;
(void) call_count;
while(node->key_name != NULL)
{
ret = cfstore_create_key_name_validate(node->key_name, node->f_allowed);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_create_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: test failed (ret=%d, key_name=%s, f_allowed=%d)\n", __func__, (int) ret, node->key_name, node->f_allowed);
TEST_ASSERT_MESSAGE(ret == true, cfstore_create_utest_msg_g);
node++;
}
ret32 = drv->Uninitialize();
CFSTORE_TEST_UTEST_MESSAGE(cfstore_create_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Uninitialize() call failed.\n", __func__);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_create_utest_msg_g);
return CaseNext;
}
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(CFSTORE_CREATE_GREENTEA_TIMEOUT_S, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
/* 1 2 3 4 5 6 7 */
/* 1234567890123456789012345678901234567890123456789012345678901234567890 */
Case("CREATE_test_00", cfstore_create_test_00),
Case("CREATE_test_01_start", cfstore_utest_default_start),
Case("CREATE_test_01_end", cfstore_create_test_01_end),
Case("CREATE_test_02_start", cfstore_utest_default_start),
Case("CREATE_test_02_end", cfstore_create_test_02_end),
Case("CREATE_test_03_start", cfstore_utest_default_start),
Case("CREATE_test_03_end", cfstore_create_test_03_end),
Case("CREATE_test_04_start", cfstore_utest_default_start),
Case("CREATE_test_04_end", cfstore_create_test_04_end),
Case("CREATE_test_05_start", cfstore_utest_default_start),
Case("CREATE_test_05_end", cfstore_create_test_05_end),
Case("CREATE_test_06_start", cfstore_utest_default_start),
Case("CREATE_test_06_end", cfstore_create_test_06_end),
};
/* Declare your test specification with a custom setup handler */
Specification specification(greentea_setup, cases);
#if defined CFSTORE_CONFIG_MBED_OS_VERSION && CFSTORE_CONFIG_MBED_OS_VERSION == 3
/* mbedosV3*/
void app_start(int argc __unused, char** argv __unused)
{
/* Run the test specification */
Harness::run(specification);
}
#endif /* CFSTORE_CONFIG_MBED_OS_VERSION == 3 */
#if defined CFSTORE_CONFIG_MBED_OS_VERSION && CFSTORE_CONFIG_MBED_OS_VERSION == 4
/* mbedosV3++*/
int main()
{
return !Harness::run(specification);
}
#endif /* CFSTORE_CONFIG_MBED_OS_VERSION == 4 */
#endif // __MBED__ && ! defined TOOLCHAIN_GCC_ARM

View File

@ -0,0 +1,868 @@
/** @file example1.cpp
*
* mbed Microcontroller Library
* Copyright (c) 2006-2016 ARM Limited
*
* 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.
*
* Test cases to add and delete KVs in the CFSTORE.
*/
/* EXAMPLE1 Notes
* ==============
*
* The example test does the following CFSTORE operations:
* - initialises
* - creates a key-value pair (KV).
* - writes the data for the KV
* - closes KV.
* - flushes the KV to flash
* - opens KV for reading.
* - reads KV and checks the value blob was the same as previously written.
* - closes KV.
* - finds a KV (there is only 1 to find).
* - for the KV returned, get the key name.
* - for the KV returned, get the value length.
* - for the KV returned, delete the KV.
* - find another KV (which fails as there are no more keys to find).
* - flushes the updated state to flash to store the removal of the deleted KV.
* - uninitialises
* - stops
*
* This test is coded so as to work in the following modes:
* - flash sync mode i.e. with caps.asynchronous_ops == false
* - flash async mode i.e. with caps.asynchronous_ops == true
* The dual async/sync mode support with the same code is more complicated
* than if the implementation just supported sync mode for example. However,
* it has the benefit of being more versatile.
*
* The test leaves the flash in the same state as at the beginning of the test so
* it can be run a second time on the device without flashing, and the test should
* still work.
*
*/
#if defined __MBED__ && ! defined TOOLCHAIN_GCC_ARM
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#ifdef TARGET_LIKE_FRDM_K64F_GCC
#include <mbed-drivers/mbed.h>
#endif
#include "cfstore_config.h"
#include <Driver_Common.h>
#include "cfstore_debug.h"
#include "cfstore_test.h"
#include <configuration-store/configuration_store.h>
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#ifdef YOTTA_CFG_CFSTORE_UVISOR
#include "uvisor-lib/uvisor-lib.h"
#include "cfstore_uvisor.h"
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
using namespace utest::v1;
static control_t cfstore_example1_test_00(const size_t call_count)
{
(void) call_count;
printf("Not implemented for ARM toolchain\n");
return CaseNext;
}
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(100, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
/* 1 2 3 4 5 6 7 */
/* 1234567890123456789012345678901234567890123456789012345678901234567890 */
Case("EXAMPLE1_test_00", cfstore_example1_test_00),
};
/* Declare your test specification with a custom setup handler */
Specification specification(greentea_setup, cases);
int main()
{
return !Harness::run(specification);
}
#else
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef TARGET_LIKE_FRDM_K64F_GCC
#include <mbed-drivers/mbed.h>
#endif
#ifndef YOTTA_CONFIGURATION_STORE_EXAMPLE1_VERSION_STRING
/* when built as Configuration-Store example, include greentea support otherwise omit */
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#else // YOTTA_CONFIGURATION_STORE_EXAMPLE1_VERSION_STRING
// map utest types for building as stand alone example
#define control_t void
#define CaseNext
#endif // YOTTA_CONFIGURATION_STORE_EXAMPLE1_VERSION_STRING
#include <stdio.h>
#include <string.h>
#include "cfstore_config.h"
#include <configuration-store/configuration_store.h>
#ifdef YOTTA_CFG_CONFIG_UVISOR
#include "uvisor-lib/uvisor-lib.h"
#endif /* YOTTA_CFG_CONFIG_UVISOR */
#ifndef YOTTA_CONFIGURATION_STORE_EXAMPLE1_VERSION_STRING
using namespace utest::v1;
#endif
#define CFSTORE_EX1_TEST_ASSERT(Expr) if (!(Expr)) { printf("%s:%u: assertion failure\r\n", __FUNCTION__, __LINE__); while (1) ;}
#define CFSTORE_EX1_TEST_ASSERT_EQUAL(expected, actual) if ((expected) != (actual)) {printf("%s:%u: assertion failure\r\n", __FUNCTION__, __LINE__); while (1) ;}
#define CFSTORE_EX1_TEST_ASSERT_NOT_EQUAL(expected, actual) if ((expected) == (actual)) {printf("%s:%u: assertion failure\r\n", __FUNCTION__, __LINE__); while (1) ;}
#define CFSTORE_EX1_TEST_ASSERT_MSG(Expr, _fmt, ...) \
do \
{ \
if (!(Expr)) \
{ \
printf(_fmt, __VA_ARGS__); \
while (1) ; \
} \
}while(0);
#define CFSTORE_EX1_LOG(_fmt, ...) \
do \
{ \
printf(_fmt, __VA_ARGS__); \
}while(0);
const char* cfstore_ex_opcode_str[] =
{
"UNDEFINED",
"CFSTORE_OPCODE_CLOSE",
"CFSTORE_OPCODE_CREATE",
"CFSTORE_OPCODE_DELETE",
"CFSTORE_OPCODE_FIND",
"CFSTORE_OPCODE_FLUSH",
"CFSTORE_OPCODE_GET_KEY_NAME",
"CFSTORE_OPCODE_GET_STATUS",
"CFSTORE_OPCODE_GET_VALUE_LEN",
"CFSTORE_OPCODE_INITIALIZE",
"CFSTORE_OPCODE_OPEN",
"CFSTORE_OPCODE_POWER_CONTROL",
"CFSTORE_OPCODE_READ",
"CFSTORE_OPCODE_RSEEK",
"CFSTORE_OPCODE_UNINITIALIZE",
"CFSTORE_OPCODE_WRITE",
"CFSTORE_OPCODE_MAX"
};
bool cfstore_example1_done = false;
const char* cfstore_ex_kv_name = "basement.medicine.pavement.government.trenchcoat.off.cough.off.kid.did.when.again.alleyway.friend.cap.pen.dollarbills.ten.foot.soot.put.but.anyway.say.May.DA.kid.did.toes.bows.those.hose.nose.clothes.man.blows.well.well";
const char* cfstore_ex_kv_value = "TheRollingStone";
#define CFSTORE_EX1_RSEEK_OFFSET 10 /* offset to S of Stone */
typedef enum cfstore_ex_state_t {
CFSTORE_EX_STATE_INITIALIZING = 1,
CFSTORE_EX_STATE_INIT_DONE,
CFSTORE_EX_STATE_CREATING,
CFSTORE_EX_STATE_CREATE_DONE,
CFSTORE_EX_STATE_WRITING,
CFSTORE_EX_STATE_WRITE_DONE,
CFSTORE_EX_STATE_CLOSING1,
CFSTORE_EX_STATE_CLOSE_DONE1,
CFSTORE_EX_STATE_FLUSHING1,
CFSTORE_EX_STATE_FLUSH_DONE1,
CFSTORE_EX_STATE_OPENING,
CFSTORE_EX_STATE_OPEN_DONE,
CFSTORE_EX_STATE_READING1,
CFSTORE_EX_STATE_READ_DONE1,
CFSTORE_EX_STATE_RSEEKING,
CFSTORE_EX_STATE_RSEEK_DONE,
CFSTORE_EX_STATE_READING2,
CFSTORE_EX_STATE_READ_DONE2,
CFSTORE_EX_STATE_CLOSING2,
CFSTORE_EX_STATE_CLOSE_DONE2,
CFSTORE_EX_STATE_FINDING1,
CFSTORE_EX_STATE_FIND_DONE1,
CFSTORE_EX_STATE_GETTING_KEY_NAME,
CFSTORE_EX_STATE_GET_KEY_NAME_DONE,
CFSTORE_EX_STATE_GETTING_VALUE_LEN,
CFSTORE_EX_STATE_GET_VALUE_LEN_DONE,
CFSTORE_EX_STATE_DELETING,
CFSTORE_EX_STATE_DELETE_DONE,
CFSTORE_EX_STATE_FINDING2,
CFSTORE_EX_STATE_FIND_DONE2,
CFSTORE_EX_STATE_FLUSHING2,
CFSTORE_EX_STATE_FLUSH_DONE2,
CFSTORE_EX_STATE_UNINITIALIZING,
CFSTORE_EX_STATE_UNINIT_DONE
} cfstore_ex_state_t;
typedef struct cfstore_example1_ctx_t
{
ARM_CFSTORE_CAPABILITIES caps;;
uint8_t hkey[CFSTORE_HANDLE_BUFSIZE];
uint8_t hkey_next_buf[CFSTORE_HANDLE_BUFSIZE];
uint8_t hkey_prev_buf[CFSTORE_HANDLE_BUFSIZE];
ARM_CFSTORE_HANDLE hkey_next;
ARM_CFSTORE_HANDLE hkey_prev;
cfstore_ex_state_t state;
ARM_CFSTORE_SIZE len;
ARM_CFSTORE_KEYDESC kdesc;
ARM_CFSTORE_FMODE flags;
char value[CFSTORE_KEY_NAME_MAX_LENGTH+1];
/* callback attributes*/
int32_t callback_status;
ARM_CFSTORE_HANDLE callback_handle;
} cfstore_example1_ctx_t;
static cfstore_example1_ctx_t cfstore_example1_ctx_g;
extern ARM_CFSTORE_DRIVER cfstore_driver;
ARM_CFSTORE_DRIVER *cfstore_drv = &cfstore_driver;
/* forward declarations */
static void cfstore_ex_fms_update(cfstore_example1_ctx_t* ctx);
static void cfstore_ex_callback(int32_t status, ARM_CFSTORE_OPCODE cmd_code, void *client_context, ARM_CFSTORE_HANDLE handle)
{
(void) handle;
cfstore_example1_ctx_t* ctx = (cfstore_example1_ctx_t*) client_context;
/* CFSTORE_EX1_LOG("%s:entered: status=%d, cmd_code=%d (%s) handle=%p\r\n", __func__, (int) status, (int) cmd_code, cfstore_ex_opcode_str[cmd_code], handle); */
switch(cmd_code)
{
case CFSTORE_OPCODE_INITIALIZE:
ctx->state = CFSTORE_EX_STATE_INIT_DONE;
break;
case CFSTORE_OPCODE_CREATE:
ctx->state = CFSTORE_EX_STATE_CREATE_DONE;
break;
case CFSTORE_OPCODE_WRITE:
ctx->state = CFSTORE_EX_STATE_WRITE_DONE;
break;
case CFSTORE_OPCODE_CLOSE:
switch(ctx->state)
{
case(CFSTORE_EX_STATE_CLOSING1):
ctx->state = CFSTORE_EX_STATE_CLOSE_DONE1;
break;
case(CFSTORE_EX_STATE_CLOSING2):
ctx->state = CFSTORE_EX_STATE_CLOSE_DONE2;
break;
default:
CFSTORE_EX1_TEST_ASSERT_MSG(false, "%s:Error: unknown Close() error (line=%u)\r\n", __func__, __LINE__);
break;
}
break;
case CFSTORE_OPCODE_FLUSH:
switch(ctx->state)
{
case(CFSTORE_EX_STATE_FLUSHING1):
ctx->state = CFSTORE_EX_STATE_FLUSH_DONE1;
break;
case(CFSTORE_EX_STATE_FLUSHING2):
ctx->state = CFSTORE_EX_STATE_FLUSH_DONE2;
break;
default:
CFSTORE_EX1_TEST_ASSERT_MSG(false, "%s:Error: unknown Find() error (line=%u)\r\n", __func__, __LINE__);
break;
}
break;
case CFSTORE_OPCODE_OPEN:
ctx->state = CFSTORE_EX_STATE_OPEN_DONE;
break;
case CFSTORE_OPCODE_FIND:
switch(ctx->state)
{
case(CFSTORE_EX_STATE_FINDING1):
ctx->state = CFSTORE_EX_STATE_FIND_DONE1;
break;
case(CFSTORE_EX_STATE_FINDING2):
ctx->state = CFSTORE_EX_STATE_FIND_DONE2;
break;
default:
CFSTORE_EX1_TEST_ASSERT_MSG(false, "%s:Error: unknown Find() error (line=%u)\r\n", __func__, __LINE__);
break;
}
break;
case CFSTORE_OPCODE_GET_KEY_NAME:
ctx->state = CFSTORE_EX_STATE_GET_KEY_NAME_DONE;
break;
case CFSTORE_OPCODE_GET_VALUE_LEN:
ctx->state = CFSTORE_EX_STATE_GET_VALUE_LEN_DONE;
break;
case CFSTORE_OPCODE_READ:
switch(ctx->state)
{
case(CFSTORE_EX_STATE_READING1):
ctx->state = CFSTORE_EX_STATE_READ_DONE1;
break;
case(CFSTORE_EX_STATE_READING2):
ctx->state = CFSTORE_EX_STATE_READ_DONE2;
break;
default:
CFSTORE_EX1_TEST_ASSERT_MSG(false, "%s:Error: unknown Read() error (line=%u)\r\n", __func__, __LINE__);
break;
}
break;
case CFSTORE_OPCODE_RSEEK:
ctx->state = CFSTORE_EX_STATE_RSEEK_DONE;
break;
case CFSTORE_OPCODE_DELETE:
ctx->state = CFSTORE_EX_STATE_DELETE_DONE;
break;
case CFSTORE_OPCODE_UNINITIALIZE:
ctx->state = CFSTORE_EX_STATE_UNINIT_DONE;
break;
case CFSTORE_OPCODE_GET_STATUS:
case CFSTORE_OPCODE_POWER_CONTROL:
default:
CFSTORE_EX1_TEST_ASSERT_MSG(false, "%s:Error: received asynchronous notification for opcode=%d (%s)\r\b", __func__, cmd_code, cmd_code < CFSTORE_OPCODE_MAX ? cfstore_ex_opcode_str[cmd_code] : "unknown");
break;
}
ctx->callback_status = status;
ctx->callback_handle = handle;
cfstore_ex_fms_update(ctx);
return;
}
static void cfstore_ex_fms_update(cfstore_example1_ctx_t* ctx)
{
int32_t ret;
switch (ctx->state)
{
case CFSTORE_EX_STATE_INITIALIZING:
CFSTORE_EX1_LOG("INITIALIZING%s", "\r\n");
// note that cfstore_ex_callback() for cmd_code==CFSTORE_OPCODE_INITIALIZE can be invoked before Initialize() has returned
ret = cfstore_drv->Initialize(cfstore_ex_callback, ctx);
CFSTORE_EX1_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: Initialize() should return ret >= 0 for async/synch modes(ret=%ld)\r\n", __func__, ret);
if(ret >= ARM_DRIVER_OK && ctx->caps.asynchronous_ops == false) {
ctx->state = CFSTORE_EX_STATE_INIT_DONE;
break;
} else if(ret >= ARM_DRIVER_OK && ctx->caps.asynchronous_ops == true) {
// await pending notification of completion.
break;
}
CFSTORE_EX1_TEST_ASSERT_MSG(false, "%s:Error: unknown error (line=%u)\r\n", __func__, __LINE__);
break;
case CFSTORE_EX_STATE_INIT_DONE:
CFSTORE_EX1_LOG("INIT_DONE%s", "\r\n");
CFSTORE_EX1_TEST_ASSERT_MSG(ctx->callback_status >= ARM_DRIVER_OK, "%s:Error: Initialize() completion failed (status=%ld)\r\n", __func__, ctx->callback_status);
CFSTORE_EX1_TEST_ASSERT_MSG(ctx->callback_handle == NULL, "%s:Error: the cfstore_ex_callback(cmd_code==CFSTORE_OPCODE_INITIALIZE) received non-NULL handle (%p)\r\n", __func__, ctx->callback_handle);
ctx->state = CFSTORE_EX_STATE_CREATING;
// intentional fall-through
case CFSTORE_EX_STATE_CREATING:
CFSTORE_EX1_LOG("CREATING%s", "\r\n");
memset(&ctx->kdesc, 0, sizeof(ARM_CFSTORE_KEYDESC));
ctx->kdesc.drl = ARM_RETENTION_NVM;
ctx->len = strlen(cfstore_ex_kv_value);
// note that cfstore_ex_callback() for cmd_code==CFSTORE_OPCODE_CREATE can be invoked before Create() has returned
ret = cfstore_drv->Create(cfstore_ex_kv_name, ctx->len, &ctx->kdesc, ctx->hkey);
CFSTORE_EX1_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: Create() failed (ret=%ld)\r\n", __func__, ret);
if(ret >= ARM_DRIVER_OK && ctx->caps.asynchronous_ops == false) {
ctx->state = CFSTORE_EX_STATE_CREATE_DONE;
break;
} else if(ret >= ARM_DRIVER_OK && ctx->caps.asynchronous_ops == true) {
// await pending notification of completion.
break;
}
CFSTORE_EX1_TEST_ASSERT_MSG(false, "%s:Error: unknown error (line=%u)\r\n", __func__, __LINE__);
break;
case CFSTORE_EX_STATE_CREATE_DONE:
CFSTORE_EX1_LOG("CREATE_DONE%s", "\r\n");
CFSTORE_EX1_TEST_ASSERT_MSG(ctx->callback_status >= ARM_DRIVER_OK, "%s:Error: Create() completion failed (status=%ld)\r\n", __func__, ctx->callback_status);
CFSTORE_EX1_TEST_ASSERT_MSG(ctx->callback_handle == ctx->hkey, "%s:Error: the cfstore_ex_callback(cmd_code==CFSTORE_OPCODE_CREATE) received handle (%p) is not the hkey supplied to Create()(%p)\r\n", __func__, ctx->callback_handle, ctx->hkey);
ctx->state = CFSTORE_EX_STATE_WRITING;
// intentional fall-through
case CFSTORE_EX_STATE_WRITING:
CFSTORE_EX1_LOG("WRITING%s", "\r\n");
ctx->len = strlen(cfstore_ex_kv_value);
// note that cfstore_ex_callback() for cmd_code==CFSTORE_OPCODE_WRITE can be invoked before Write() has returned
ret = cfstore_drv->Write(ctx->hkey, cfstore_ex_kv_value, &ctx->len);
CFSTORE_EX1_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: Write() failed (ret=%ld)\r\n", __func__, ret);
if(ret >= ARM_DRIVER_OK && ctx->caps.asynchronous_ops == false) {
ctx->state = CFSTORE_EX_STATE_WRITE_DONE;
break;
} else if(ret >= ARM_DRIVER_OK && ctx->caps.asynchronous_ops == true) {
// await pending notification of completion.
break;
}
CFSTORE_EX1_TEST_ASSERT_MSG(false, "%s:Error: unknown error (line=%u)\r\n", __func__, __LINE__);
break;
case CFSTORE_EX_STATE_WRITE_DONE:
CFSTORE_EX1_LOG("WRITE_DONE%s", "\r\n");
CFSTORE_EX1_TEST_ASSERT_MSG(ctx->callback_status >= ARM_DRIVER_OK, "%s:Error: Write() completion failed (status=%ld)\r\n", __func__, ctx->callback_status);
CFSTORE_EX1_TEST_ASSERT_MSG(ctx->callback_status == (int32_t) strlen(cfstore_ex_kv_value), "%s:Error: Write() number of octets written (i.e. completion status (%ld)) != strlen(ctx->value)(%ld)\r\n", __func__, ctx->callback_status, (int32_t) strlen(cfstore_ex_kv_value));
CFSTORE_EX1_TEST_ASSERT_MSG(ctx->callback_status == (int32_t) ctx->len, "%s:Error: Write() number of octets written (i.e. completion status (%ld)) != updated value of len parameter (%ld)\r\n", __func__, ctx->callback_status, (int32_t) ctx->len);
CFSTORE_EX1_TEST_ASSERT_MSG(ctx->callback_handle == ctx->hkey, "%s:Error: the cfstore_ex_callback(cmd_code==CFSTORE_OPCODE_WRITE) received handle (%p) is not the hkey supplied to Write()(%p)\r\n", __func__, ctx->callback_handle, ctx->hkey);
ctx->state = CFSTORE_EX_STATE_CLOSING1;
// intentional fall-through
case CFSTORE_EX_STATE_CLOSING1:
CFSTORE_EX1_LOG("CLOSING1%s", "\r\n");
// note that cfstore_ex_callback() for cmd_code==CFSTORE_OPCODE_CLOSE can be invoked before Close() has returned
ret = cfstore_drv->Close(ctx->hkey);
CFSTORE_EX1_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: Close() failed (ret=%ld)\r\n", __func__, ret);
if(ret >= ARM_DRIVER_OK && ctx->caps.asynchronous_ops == false) {
ctx->state = CFSTORE_EX_STATE_CLOSE_DONE1;
break;
} else if(ret >= ARM_DRIVER_OK && ctx->caps.asynchronous_ops == true) {
// await pending notification of completion.
break;
}
CFSTORE_EX1_TEST_ASSERT_MSG(false, "%s:Error: unknown error (line=%u)\r\n", __func__, __LINE__);
break;
case CFSTORE_EX_STATE_CLOSE_DONE1:
CFSTORE_EX1_LOG("CLOSE_DONE1%s", "\r\n");
CFSTORE_EX1_TEST_ASSERT_MSG(ctx->callback_status >= ARM_DRIVER_OK, "%s:Error: Close() completion failed (status=%ld)\r\n", __func__, ctx->callback_status);
CFSTORE_EX1_TEST_ASSERT_MSG(ctx->callback_handle == NULL, "%s:Error: the cfstore_ex_callback(cmd_code==CFSTORE_OPCODE_CLOSE) received non-NULL handle (%p)\r\n", __func__, ctx->callback_handle);
ctx->state = CFSTORE_EX_STATE_FLUSHING1;
// intentional fall-through
case CFSTORE_EX_STATE_FLUSHING1:
CFSTORE_EX1_LOG("FLUSHING1%s", "\r\n");
// note that cfstore_ex_callback() for cmd_code==CFSTORE_OPCODE_FLUSH can be invoked before Flush() has returned
ret = cfstore_drv->Flush();
CFSTORE_EX1_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: Flush() failed (ret=%ld)\r\n", __func__, ret);
if(ret >= ARM_DRIVER_OK && ctx->caps.asynchronous_ops == false) {
ctx->state = CFSTORE_EX_STATE_FLUSH_DONE1;
break;
} else if(ret >= ARM_DRIVER_OK && ctx->caps.asynchronous_ops == true) {
// await pending notification of completion.
break;
}
CFSTORE_EX1_TEST_ASSERT_MSG(false, "%s:Error: unknown error (line=%u)\r\n", __func__, __LINE__);
break;
case CFSTORE_EX_STATE_FLUSH_DONE1:
CFSTORE_EX1_LOG("FLUSH_DONE1%s", "\r\n");
CFSTORE_EX1_TEST_ASSERT_MSG(ctx->callback_status >= ARM_DRIVER_OK, "%s:Error: Flush() completion failed (status=%ld)\r\n", __func__, ctx->callback_status);
CFSTORE_EX1_TEST_ASSERT_MSG(ctx->callback_handle == NULL, "%s:Error: the cfstore_ex_callback(cmd_code==CFSTORE_OPCODE_FLUSH) received non-NULL handle (%p)\r\n", __func__, ctx->callback_handle);
ctx->state = CFSTORE_EX_STATE_OPENING;
// intentional fall-through
case CFSTORE_EX_STATE_OPENING:
CFSTORE_EX1_LOG("OPENING%s", "\r\n");
memset(&ctx->flags, 0, sizeof(ctx->flags));
memset(&ctx->hkey, 0, CFSTORE_HANDLE_BUFSIZE);
// note that cfstore_ex_callback() for cmd_code==CFSTORE_OPCODE_OPEN can be invoked before Open() has returned
ret = cfstore_drv->Open(cfstore_ex_kv_name, ctx->flags, ctx->hkey);
CFSTORE_EX1_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: Open() failed (ret=%ld)\r\n", __func__, ret);
if(ret >= ARM_DRIVER_OK && ctx->caps.asynchronous_ops == false) {
ctx->state = CFSTORE_EX_STATE_OPEN_DONE;
break;
} else if(ret >= ARM_DRIVER_OK && ctx->caps.asynchronous_ops == true) {
// await pending notification of completion.
break;
}
CFSTORE_EX1_TEST_ASSERT_MSG(false, "%s:Error: unknown error (line=%u)\r\n", __func__, __LINE__);
break;
case CFSTORE_EX_STATE_OPEN_DONE:
CFSTORE_EX1_LOG("OPEN_DONE%s", "\r\n");
CFSTORE_EX1_TEST_ASSERT_MSG(ctx->callback_status >= ARM_DRIVER_OK, "%s:Error: Open() completion failed (status=%ld)\r\n", __func__, ctx->callback_status);
CFSTORE_EX1_TEST_ASSERT_MSG(ctx->callback_handle == ctx->hkey, "%s:Error: the cfstore_ex_callback(cmd_code==CFSTORE_OPCODE_OPEN) received handle (%p) is not the hkey supplied to Open()(%p)\r\n", __func__, ctx->callback_handle, ctx->hkey);
ctx->state = CFSTORE_EX_STATE_READING1;
// intentional fall-through
case CFSTORE_EX_STATE_READING1:
CFSTORE_EX1_LOG("READING1%s", "\r\n");
ctx->len = CFSTORE_KEY_NAME_MAX_LENGTH;
memset(ctx->value, 0, CFSTORE_KEY_NAME_MAX_LENGTH+1);
// note that cfstore_ex_callback() for cmd_code==CFSTORE_OPCODE_READ can be invoked before Read() has returned
ret = cfstore_drv->Read(ctx->hkey, ctx->value, &ctx->len);
CFSTORE_EX1_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: Read() failed (ret=%ld)\r\n", __func__, ret);
if(ret >= ARM_DRIVER_OK && ctx->caps.asynchronous_ops == false) {
ctx->state = CFSTORE_EX_STATE_READ_DONE1;
break;
} else if(ret >= ARM_DRIVER_OK && ctx->caps.asynchronous_ops == true) {
// await pending notification of completion.
break;
}
CFSTORE_EX1_TEST_ASSERT_MSG(false, "%s:Error: unknown error (line=%u)\r\n", __func__, __LINE__);
break;
case CFSTORE_EX_STATE_READ_DONE1:
CFSTORE_EX1_LOG("READ_DONE1%s", "\r\n");
CFSTORE_EX1_TEST_ASSERT_MSG(ctx->callback_status >= ARM_DRIVER_OK, "%s:Error: Read() completion failed (status=%ld)\r\n", __func__, ctx->callback_status);
CFSTORE_EX1_TEST_ASSERT_MSG(ctx->callback_status == (int32_t) strlen(cfstore_ex_kv_value), "%s:Error: Read() number of octets read (i.e. completion status (%ld)) != strlen(ctx->value)(%ld)\r\n", __func__, ctx->callback_status, (int32_t) strlen(cfstore_ex_kv_value));
CFSTORE_EX1_TEST_ASSERT_MSG(ctx->callback_status == (int32_t) ctx->len, "%s:Error: Read() number of octets read (i.e. completion status (%ld)) != updated value of len parameter (%ld)\r\n", __func__, ctx->callback_status, (int32_t) ctx->len);
CFSTORE_EX1_TEST_ASSERT_MSG(ctx->callback_handle == ctx->hkey, "%s:Error: the cfstore_ex_callback(cmd_code==CFSTORE_OPCODE_READ) received handle (%p) is not the hkey supplied to Read()(%p)\r\n", __func__, ctx->callback_handle, ctx->hkey);
CFSTORE_EX1_TEST_ASSERT_MSG(strncmp(ctx->value, cfstore_ex_kv_value, strlen(cfstore_ex_kv_value)) == 0, "%s:Error: the read value (%s) is not as expected (%s)\r\n", __func__, ctx->value, cfstore_ex_kv_value);
ctx->state = CFSTORE_EX_STATE_RSEEKING;
// intentional fall-through
case CFSTORE_EX_STATE_RSEEKING:
CFSTORE_EX1_LOG("RSEEKING%s", "\r\n");
// note that cfstore_ex_callback() for cmd_code==CFSTORE_OPCODE_READ can be invoked before Read() has returned
ret = cfstore_drv->Rseek(ctx->hkey, CFSTORE_EX1_RSEEK_OFFSET);
CFSTORE_EX1_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: Rseek() failed (ret=%ld)\r\n", __func__, ret);
if(ret >= ARM_DRIVER_OK && ctx->caps.asynchronous_ops == false) {
ctx->state = CFSTORE_EX_STATE_RSEEK_DONE;
break;
} else if(ret >= ARM_DRIVER_OK && ctx->caps.asynchronous_ops == true) {
// await pending notification of completion.
break;
}
CFSTORE_EX1_TEST_ASSERT_MSG(false, "%s:Error: unknown error (line=%u)\r\n", __func__, __LINE__);
break;
case CFSTORE_EX_STATE_RSEEK_DONE:
CFSTORE_EX1_LOG("RSEEK_DONE%s", "\r\n");
CFSTORE_EX1_TEST_ASSERT_MSG(ctx->callback_status >= ARM_DRIVER_OK, "%s:Error: Read() completion failed (status=%ld)\r\n", __func__, ctx->callback_status);
CFSTORE_EX1_TEST_ASSERT_MSG(ctx->callback_handle == ctx->hkey, "%s:Error: the cfstore_ex_callback(cmd_code==CFSTORE_OPCODE_RSEEK) received handle (%p) is not the hkey supplied to Read()(%p)\r\n", __func__, ctx->callback_handle, ctx->hkey);
ctx->state = CFSTORE_EX_STATE_READING2;
// intentional fall-through
case CFSTORE_EX_STATE_READING2:
CFSTORE_EX1_LOG("READING2%s", "\r\n");
ctx->len = CFSTORE_KEY_NAME_MAX_LENGTH;
memset(ctx->value, 0, CFSTORE_KEY_NAME_MAX_LENGTH+1);
// note that cfstore_ex_callback() for cmd_code==CFSTORE_OPCODE_READ can be invoked before Read() has returned
ret = cfstore_drv->Read(ctx->hkey, ctx->value, &ctx->len);
CFSTORE_EX1_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: Read() failed (ret=%ld)\r\n", __func__, ret);
if(ret >= ARM_DRIVER_OK && ctx->caps.asynchronous_ops == false) {
ctx->state = CFSTORE_EX_STATE_READ_DONE2;
break;
} else if(ret >= ARM_DRIVER_OK && ctx->caps.asynchronous_ops == true) {
// await pending notification of completion.
break;
}
CFSTORE_EX1_TEST_ASSERT_MSG(false, "%s:Error: unknown error (line=%u)\r\n", __func__, __LINE__);
break;
case CFSTORE_EX_STATE_READ_DONE2:
CFSTORE_EX1_LOG("READ_DONE2%s", "\r\n");
CFSTORE_EX1_LOG("%s: value=%s\r\n", __func__, ctx->value);
CFSTORE_EX1_TEST_ASSERT_MSG(ctx->callback_status >= ARM_DRIVER_OK, "%s:Error: Read() completion failed (status=%ld)\r\n", __func__, ctx->callback_status);
CFSTORE_EX1_TEST_ASSERT_MSG(ctx->callback_status == (int32_t) strlen(&cfstore_ex_kv_value[CFSTORE_EX1_RSEEK_OFFSET]), "%s:Error: Read() number of octets read (i.e. completion status (%ld)) != strlen(ctx->value)(%ld)\r\n", __func__, ctx->callback_status, (int32_t) strlen(&cfstore_ex_kv_value[CFSTORE_EX1_RSEEK_OFFSET]));
CFSTORE_EX1_TEST_ASSERT_MSG(ctx->callback_status == (int32_t) ctx->len, "%s:Error: Read() number of octets read (i.e. completion status (%ld)) != updated value of len parameter (%ld)\r\n", __func__, ctx->callback_status, (int32_t) ctx->len);
CFSTORE_EX1_TEST_ASSERT_MSG(ctx->callback_handle == ctx->hkey, "%s:Error: the cfstore_ex_callback(cmd_code==CFSTORE_OPCODE_READ) received handle (%p) is not the hkey supplied to Read()(%p)\r\n", __func__, ctx->callback_handle, ctx->hkey);
CFSTORE_EX1_TEST_ASSERT_MSG(strncmp(ctx->value, &cfstore_ex_kv_value[CFSTORE_EX1_RSEEK_OFFSET], strlen(&cfstore_ex_kv_value[CFSTORE_EX1_RSEEK_OFFSET])) == 0, "%s:Error: the read value (%s) is not as expected (%s)\r\n", __func__, ctx->value, &cfstore_ex_kv_value[CFSTORE_EX1_RSEEK_OFFSET]);
ctx->state = CFSTORE_EX_STATE_CLOSING2;
// intentional fall-through
case CFSTORE_EX_STATE_CLOSING2:
CFSTORE_EX1_LOG("CLOSING2%s", "\r\n");
// note that cfstore_ex_callback() for cmd_code==CFSTORE_OPCODE_CLOSE can be invoked before Close() has returned
ret = cfstore_drv->Close(ctx->hkey);
CFSTORE_EX1_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: Close() failed (ret=%ld)\r\n", __func__, ret);
if(ret >= ARM_DRIVER_OK && ctx->caps.asynchronous_ops == false) {
ctx->state = CFSTORE_EX_STATE_CLOSE_DONE2;
break;
} else if(ret >= ARM_DRIVER_OK && ctx->caps.asynchronous_ops == true) {
// await pending notification of completion.
break;
}
CFSTORE_EX1_TEST_ASSERT_MSG(false, "%s:Error: unknown error (line=%u)\r\n", __func__, __LINE__);
break;
case CFSTORE_EX_STATE_CLOSE_DONE2:
CFSTORE_EX1_LOG("CLOSE_DONE2%s", "\r\n");
CFSTORE_EX1_TEST_ASSERT_MSG(ctx->callback_status >= ARM_DRIVER_OK, "%s:Error: Close() completion failed (status=%ld)\r\n", __func__, ctx->callback_status);
CFSTORE_EX1_TEST_ASSERT_MSG(ctx->callback_handle == NULL, "%s:Error: the cfstore_ex_callback(cmd_code==CFSTORE_OPCODE_CLOSE) received non-NULL handle (%p)\r\n", __func__, ctx->callback_handle);
ctx->state = CFSTORE_EX_STATE_FINDING1;
// intentional fall-through
case CFSTORE_EX_STATE_FINDING1:
CFSTORE_EX1_LOG("FINDING1%s", "\r\n");
// note that cfstore_ex_callback() for cmd_code==CFSTORE_OPCODE_FIND can be invoked before Find() has returned
ret = cfstore_drv->Find("*", ctx->hkey_next, ctx->hkey_prev);
CFSTORE_EX1_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: Find() failed (ret=%ld)\r\n", __func__, ret);
if(ret >= ARM_DRIVER_OK && ctx->caps.asynchronous_ops == false) {
ctx->state = CFSTORE_EX_STATE_FIND_DONE1;
break;
} else if(ret >= ARM_DRIVER_OK && ctx->caps.asynchronous_ops == true) {
// await pending notification of completion.
break;
}
CFSTORE_EX1_TEST_ASSERT_MSG(false, "%s:Error: unknown error (line=%u)\r\n", __func__, __LINE__);
break;
case CFSTORE_EX_STATE_FIND_DONE1:
CFSTORE_EX1_LOG("FIND_DONE1%s", "\r\n");
CFSTORE_EX1_TEST_ASSERT_MSG(ctx->callback_status == ARM_DRIVER_OK, "%s:Error: Find() completion failed (status=%ld)\r\n", __func__, ctx->callback_status);
CFSTORE_EX1_TEST_ASSERT_MSG(ctx->callback_handle == ctx->hkey_prev, "%s:Error: the cfstore_ex_callback(cmd_code==CFSTORE_OPCODE_FIND) received handle (%p) is not the hkey supplied to Find()(%p)\r\n", __func__, ctx->callback_handle, ctx->hkey_prev);
ctx->state = CFSTORE_EX_STATE_GETTING_KEY_NAME;
// intentional fall-through
case CFSTORE_EX_STATE_GETTING_KEY_NAME:
CFSTORE_EX1_LOG("GETTING_KEY_NAME%s", "\r\n");
ctx->len = CFSTORE_KEY_NAME_MAX_LENGTH;
memset(ctx->value, 0, CFSTORE_KEY_NAME_MAX_LENGTH+1);
// note that cfstore_ex_callback() for cmd_code==CFSTORE_OPCODE_GET_KEY_NAME can be invoked before GetKeyName() has returned
ret = cfstore_drv->GetKeyName(ctx->hkey_prev, ctx->value, (uint8_t*) &ctx->len);
CFSTORE_EX1_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: GetKeyName() failed (ret=%ld)\r\n", __func__, ret);
if(ret >= ARM_DRIVER_OK && ctx->caps.asynchronous_ops == false) {
ctx->state = CFSTORE_EX_STATE_GET_KEY_NAME_DONE;
break;
} else if(ret >= ARM_DRIVER_OK && ctx->caps.asynchronous_ops == true) {
// await pending notification of completion.
break;
}
CFSTORE_EX1_TEST_ASSERT_MSG(false, "%s:Error: unknown error (line=%u)\r\n", __func__, __LINE__);
break;
case CFSTORE_EX_STATE_GET_KEY_NAME_DONE:
CFSTORE_EX1_LOG("GET_KEY_NAME_DONE%s", "\r\n");
CFSTORE_EX1_TEST_ASSERT_MSG(ctx->callback_status >= ARM_DRIVER_OK, "%s:Error: GetKeyName() completion failed (status=%ld)\r\n", __func__, ctx->callback_status);
CFSTORE_EX1_TEST_ASSERT_MSG( ((int32_t) ctx->len == ((int32_t) strlen(cfstore_ex_kv_name)+1)), "%s:Error: GetKeyName() updated value of len parameter (%ld) != strlen(cfstore_ex_kv_name) (%ld) (\r\n", __func__, (int32_t) ctx->len, (int32_t) strlen(cfstore_ex_kv_name));
CFSTORE_EX1_TEST_ASSERT_MSG(ctx->callback_handle == ctx->hkey_prev, "%s:Error: the cfstore_ex_callback(cmd_code==CFSTORE_OPCODE_GET_KEY_NAME) received handle (%p) is not the hkey supplied to GetKeyName()(%p)\r\n", __func__, ctx->callback_handle, ctx->hkey_prev);
CFSTORE_EX1_TEST_ASSERT_MSG(strncmp(ctx->value, cfstore_ex_kv_name, strlen(cfstore_ex_kv_name)) == 0, "%s:Error: the key name (%s) is not as expected (%s)\r\n", __func__, ctx->value, cfstore_ex_kv_name);
ctx->state = CFSTORE_EX_STATE_GETTING_VALUE_LEN;
// intentional fall-through
case CFSTORE_EX_STATE_GETTING_VALUE_LEN:
CFSTORE_EX1_LOG("GETTING_VALUE_LEN%s", "\r\n");
ctx->len = CFSTORE_KEY_NAME_MAX_LENGTH;
// note that cfstore_ex_callback() for cmd_code==CFSTORE_OPCODE_GET_VALUE_LEN can be invoked before GetValueLen() has returned
ret = cfstore_drv->GetValueLen(ctx->hkey_prev, &ctx->len);
CFSTORE_EX1_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: GetValueLen() failed (ret=%ld)\r\n", __func__, ret);
if(ret >= ARM_DRIVER_OK && ctx->caps.asynchronous_ops == false) {
ctx->state = CFSTORE_EX_STATE_GET_VALUE_LEN_DONE;
break;
} else if(ret >= ARM_DRIVER_OK && ctx->caps.asynchronous_ops == true) {
// await pending notification of completion.
break;
}
CFSTORE_EX1_TEST_ASSERT_MSG(false, "%s:Error: unknown error (line=%u)\r\n", __func__, __LINE__);
break;
case CFSTORE_EX_STATE_GET_VALUE_LEN_DONE:
CFSTORE_EX1_LOG("GET_VALUE_LEN_DONE%s", "\r\n");
CFSTORE_EX1_TEST_ASSERT_MSG(ctx->callback_status >= ARM_DRIVER_OK, "%s:Error: GetValueLen() completion failed (status=%ld)\r\n", __func__, ctx->callback_status);
CFSTORE_EX1_TEST_ASSERT_MSG((int32_t) ctx->len == (int32_t) strlen(cfstore_ex_kv_value), "%s:Error: GetValueLen() updated value of len parameter (%ld) != strlen(cfstore_ex_kv_value)(%ld) \r\n", __func__, (int32_t) ctx->len, (int32_t) strlen(cfstore_ex_kv_value));
CFSTORE_EX1_TEST_ASSERT_MSG(ctx->callback_handle == ctx->hkey_prev, "%s:Error: the cfstore_ex_callback(cmd_code==CFSTORE_OPCODE_GET_VALUE_LEN) received handle (%p) is not the hkey supplied to GetValueLen()(%p)\r\n", __func__, ctx->callback_handle, ctx->hkey_prev);
ctx->state = CFSTORE_EX_STATE_DELETING;
// intentional fall-through
case CFSTORE_EX_STATE_DELETING:
CFSTORE_EX1_LOG("DELETING%s", "\r\n");
// note that cfstore_ex_callback() for cmd_code==CFSTORE_OPCODE_DELETE can be invoked before Delete() has returned
ret = cfstore_drv->Delete(ctx->callback_handle);
CFSTORE_EX1_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: Close() failed (ret=%ld)\r\n", __func__, ret);
if(ret >= ARM_DRIVER_OK && ctx->caps.asynchronous_ops == false) {
ctx->state = CFSTORE_EX_STATE_DELETE_DONE;
break;
} else if(ret >= ARM_DRIVER_OK && ctx->caps.asynchronous_ops == true) {
// await pending notification of completion.
break;
}
CFSTORE_EX1_TEST_ASSERT_MSG(false, "%s:Error: unknown error (line=%u)\r\n", __func__, __LINE__);
break;
case CFSTORE_EX_STATE_DELETE_DONE:
CFSTORE_EX1_LOG("DELETE_DONE%s", "\r\n");
CFSTORE_EX1_TEST_ASSERT_MSG(ctx->callback_status >= ARM_DRIVER_OK, "%s:Error: Delete() completion failed (status=%ld)\r\n", __func__, ctx->callback_status);
CFSTORE_EX1_TEST_ASSERT_MSG(ctx->callback_handle == NULL, "%s:Error: the cfstore_ex_callback(cmd_code==CFSTORE_OPCODE_DELETE) received non-NULL handle (%p)\r\n", __func__, ctx->callback_handle);
CFSTORE_HANDLE_SWAP(ctx->hkey_prev, ctx->hkey_next);
ctx->state = CFSTORE_EX_STATE_FINDING2;
// intentional fall-through
case CFSTORE_EX_STATE_FINDING2:
CFSTORE_EX1_LOG("FINDING2%s", "\r\n");
// note that cfstore_ex_callback() for cmd_code==CFSTORE_OPCODE_FIND can be invoked before Find() has returned
ret = cfstore_drv->Find("*", ctx->hkey_next, ctx->hkey_prev);
CFSTORE_EX1_TEST_ASSERT_MSG(ret == ARM_CFSTORE_DRIVER_ERROR_KEY_NOT_FOUND, "%s:Error: Find() failed to return expected value of ARM_CFSTORE_DRIVER_ERROR_KEY_NOT_FOUND (ret=%ld)\r\n", __func__, ret);
if(ret == ARM_CFSTORE_DRIVER_ERROR_KEY_NOT_FOUND && ctx->caps.asynchronous_ops == false) {
ctx->state = CFSTORE_EX_STATE_FIND_DONE2;
break;
} else if(ret == ARM_CFSTORE_DRIVER_ERROR_KEY_NOT_FOUND && ctx->caps.asynchronous_ops == true) {
// await pending notification of completion.
break;
}
CFSTORE_EX1_TEST_ASSERT_MSG(false, "%s:Error: unknown error (line=%u)\r\n", __func__, __LINE__);
break;
case CFSTORE_EX_STATE_FIND_DONE2:
CFSTORE_EX1_LOG("FIND_DONE2%s", "\r\n");
CFSTORE_EX1_TEST_ASSERT_MSG(ctx->callback_status == ARM_CFSTORE_DRIVER_ERROR_KEY_NOT_FOUND, "%s:Error: Find() completion should have been ARM_CFSTORE_DRIVER_ERROR_KEY_NOT_FOUND (status=%ld)\r\n", __func__, ctx->callback_status);
ctx->state = CFSTORE_EX_STATE_FLUSHING2;
// intentional fall-through
case CFSTORE_EX_STATE_FLUSHING2:
CFSTORE_EX1_LOG("FLUSHING2%s", "\r\n");
// note that cfstore_ex_callback() for cmd_code==CFSTORE_OPCODE_FLUSH can be invoked before Flush() has returned
ret = cfstore_drv->Flush();
CFSTORE_EX1_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error:2: Flush() failed (ret=%ld)\r\n", __func__, ret);
if(ret >= ARM_DRIVER_OK && ctx->caps.asynchronous_ops == false) {
ctx->state = CFSTORE_EX_STATE_FLUSH_DONE2;
break;
} else if(ret >= ARM_DRIVER_OK && ctx->caps.asynchronous_ops == true) {
// await pending notification of completion.
break;
}
CFSTORE_EX1_TEST_ASSERT_MSG(false, "%s:Error: unknown error (line=%u)\r\n", __func__, __LINE__);
break;
case CFSTORE_EX_STATE_FLUSH_DONE2:
CFSTORE_EX1_LOG("FLUSH_DONE2%s", "\r\n");
CFSTORE_EX1_TEST_ASSERT_MSG(ctx->callback_status >= ARM_DRIVER_OK, "%s:Error: Flush() completion failed (status=%ld)\r\n", __func__, ctx->callback_status);
CFSTORE_EX1_TEST_ASSERT_MSG(ctx->callback_handle == NULL, "%s:Error: the cfstore_ex_callback(cmd_code==CFSTORE_OPCODE_FLUSH) received non-NULL handle (%p)\r\n", __func__, ctx->callback_handle);
ctx->state = CFSTORE_EX_STATE_UNINITIALIZING;
// intentional fall-through
case CFSTORE_EX_STATE_UNINITIALIZING:
CFSTORE_EX1_LOG("UNINITIALIZING%s", "\r\n");
ret = cfstore_drv->Uninitialize();
CFSTORE_EX1_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: Uninitialize() should return ret >= 0 for async/synch modes(ret=%ld)\r\n", __func__, ret);
if(ret >= ARM_DRIVER_OK && ctx->caps.asynchronous_ops == false) {
ctx->state = CFSTORE_EX_STATE_UNINIT_DONE;
break;
} else if(ret >= ARM_DRIVER_OK && ctx->caps.asynchronous_ops == true) {
// await pending notification of completion.
break;
}
CFSTORE_EX1_TEST_ASSERT_MSG(false, "%s:Error: unknown error (line=%u)\r\n", __func__, __LINE__);
break;
case CFSTORE_EX_STATE_UNINIT_DONE:
CFSTORE_EX1_LOG("UNINIT_DONE%s", "\r\n");
CFSTORE_EX1_TEST_ASSERT_MSG(ctx->callback_handle == NULL, "%s:Error: the cfstore_ex_callback(cmd_code==CFSTORE_OPCODE_UNINITIALIZE) received non-NULL handle (%p)\r\n", __func__, ctx->callback_handle);
cfstore_example1_done = true;
CFSTORE_EX1_LOG("***************%s", "\r\n");
CFSTORE_EX1_LOG("*** SUCCESS ***%s", "\r\n");
CFSTORE_EX1_LOG("***************%s", "\r\n");
break;
}
}
static control_t cfstore_example1_app_start(const size_t call_count)
{
cfstore_example1_ctx_t* ctx = &cfstore_example1_ctx_g;
(void) call_count;
/* initialise the context */
memset(ctx, 0, sizeof(cfstore_example1_ctx_t));
cfstore_example1_done = false;
ctx->hkey_next = ctx->hkey_next_buf;
ctx->hkey_prev = ctx->hkey_prev_buf;
ctx->callback_status = ARM_DRIVER_ERROR;
ctx->state = CFSTORE_EX_STATE_INITIALIZING;
ctx->caps = cfstore_drv->GetCapabilities();
CFSTORE_EX1_LOG("%s:INITIALIZING: caps.asynchronous_ops=%lu\n", __func__, ctx->caps.asynchronous_ops);
cfstore_ex_fms_update(ctx);
/* main application worker loop */
while (!cfstore_example1_done)
{
// do some work
CFSTORE_EX1_LOG("%s: going to sleep!\r\n", __func__);
#if defined CFSTORE_CONFIG_MBED_OS_VERSION && CFSTORE_CONFIG_MBED_OS_VERSION == 3
__WFE();
#endif /* CFSTORE_CONFIG_MBED_OS_VERSION == 3 */
#if defined CFSTORE_CONFIG_MBED_OS_VERSION && CFSTORE_CONFIG_MBED_OS_VERSION == 4
/* mbedosV3++
* todo: port __WFE()
*/
#endif /* CFSTORE_CONFIG_MBED_OS_VERSION == 4 */
CFSTORE_EX1_LOG("%s: woke up!\r\n", __func__);
}
return CaseNext;
}
#ifndef YOTTA_CONFIGURATION_STORE_EXAMPLE1_VERSION_STRING
/* when built as Configuration-Store example, include greentea support otherwise omit */
/* report whether built/configured for flash sync or async mode */
static control_t cfstore_example1_test_00(const size_t call_count)
{
(void) call_count;
CFSTORE_EX1_LOG("INITIALIZING: caps.asynchronous_ops=%lu\n", cfstore_driver.GetCapabilities().asynchronous_ops);
return CaseNext;
}
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(100, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
/* 1 2 3 4 5 6 7 */
/* 1234567890123456789012345678901234567890123456789012345678901234567890 */
Case("EXAMPLE1_test_00", cfstore_example1_test_00),
Case("EXAMPLE1_test_01_start", cfstore_example1_app_start),
};
/* Declare your test specification with a custom setup handler */
Specification specification(greentea_setup, cases);
#if defined CFSTORE_CONFIG_MBED_OS_VERSION && CFSTORE_CONFIG_MBED_OS_VERSION == 3
/* mbedosV3*/
void app_start(int argc __unused, char** argv __unused)
{
/* Run the test specification */
Harness::run(specification);
}
#endif /* CFSTORE_CONFIG_MBED_OS_VERSION == 3 */
#if defined CFSTORE_CONFIG_MBED_OS_VERSION && CFSTORE_CONFIG_MBED_OS_VERSION == 4
/* mbedosV3++*/
int main()
{
return !Harness::run(specification);
}
#endif /* CFSTORE_CONFIG_MBED_OS_VERSION == 4 */
#else // YOTTA_CONFIGURATION_STORE_EXAMPLE1_VERSION_STRING
// stand alone Configuration-Store-Example
void app_start(int argc __unused, char** argv __unused)
{
cfstore_example1_app_start(0);
}
#endif // YOTTA_CONFIGURATION_STORE_EXAMPLE1_VERSION_STRING
#endif // __MBED__ && ! defined TOOLCHAIN_GCC_ARM

View File

@ -0,0 +1,328 @@
/** @file example2.cpp
*
* mbed Microcontroller Library
* Copyright (c) 2006-2016 ARM Limited
*
* 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.
*
*/
/* Overview of test:
* - initialises cfstore
* - creates a key called "com.arm.mbed.spv.assets.asset2.payload" with value blob length = 15 = strlen("Grumpy old man")+1.
* - writes the data for the key to be "Grumpy old man"
* - closes kv.
* - opens kv for reading/writing
* - reads the value blob and checks its == "Grumpy old man"
* - writes the first 11 chars of the value blob to be "Grumpy man" plus a NULL;
* - reads the value blob back and checks its as expected
*
* This test is coded so as to work in the following modes:
* - flash sync mode i.e. with caps.asynchronous_ops == false
* - flash async mode i.e. with caps.asynchronous_ops == true
*/
#if defined __MBED__ && ! defined TOOLCHAIN_GCC_ARM
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#ifdef TARGET_LIKE_FRDM_K64F_GCC
#include <mbed-drivers/mbed.h>
#endif
#include "cfstore_config.h"
#include <Driver_Common.h>
#include "cfstore_debug.h"
#include "cfstore_test.h"
#include <configuration-store/configuration_store.h>
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#ifdef YOTTA_CFG_CFSTORE_UVISOR
#include "uvisor-lib/uvisor-lib.h"
#include "cfstore_uvisor.h"
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
using namespace utest::v1;
static control_t cfstore_example2_test_00(const size_t call_count)
{
(void) call_count;
printf("Not implemented for ARM toolchain\n");
return CaseNext;
}
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(100, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
/* 1 2 3 4 5 6 7 */
/* 1234567890123456789012345678901234567890123456789012345678901234567890 */
Case("EXAMPLE2_test_00", cfstore_example2_test_00),
};
/* Declare your test specification with a custom setup handler */
Specification specification(greentea_setup, cases);
int main()
{
return !Harness::run(specification);
}
#else
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <inttypes.h>
#ifdef TARGET_LIKE_FRDM_K64F_GCC
#include <mbed-drivers/mbed.h>
#endif
#include "cfstore_config.h"
#include "cfstore_test.h"
#include "cfstore_debug.h"
//#include <flash-abstraction/Driver_Common.h>
#include <Driver_Common.h>
#include <configuration-store/configuration_store.h>
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#ifdef YOTTA_CFG_CONFIG_UVISOR
#include "uvisor-lib/uvisor-lib.h"
#endif /* YOTTA_CFG_CONFIG_UVISOR */
using namespace utest::v1;
static char cfstore_example2_utest_msg_g[CFSTORE_UTEST_MSG_BUF_SIZE];
/* defines */
#define PvMemSet memset
#define PvStrLen strlen
/* report whether built/configured for flash sync or async mode */
static control_t cfstore_example2_test_00(const size_t call_count)
{
(void) call_count;
CFSTORE_LOG("INITIALIZING: caps.asynchronous_ops=%lu\n", cfstore_driver.GetCapabilities().asynchronous_ops);
return CaseNext;
}
ARM_CFSTORE_DRIVER *drv = &cfstore_driver;
static int32_t CreateKeyValueStore(
const char *keyName,
const char *data,
ARM_CFSTORE_SIZE *dataLength,
ARM_CFSTORE_KEYDESC *keyDesc)
{
int32_t cfsStatus = ARM_DRIVER_ERROR;
ARM_CFSTORE_SIZE valueLength = 0;
ARM_CFSTORE_HANDLE_INIT(hkey);
valueLength = *dataLength;
cfsStatus = drv->Create(keyName, valueLength, keyDesc, hkey);
TEST_ASSERT_EQUAL(ARM_DRIVER_OK, cfsStatus);
valueLength = *dataLength;
cfsStatus = drv->Write(hkey, data, &valueLength);
/*
* (1) Note the following:
* - if cfsStatus > 0 then Write() has completed synchronously and returned the number of bytes written (irrespective of the caps.asynchronous_ops attribute).
* - if cfsStatus == ARM_DRIVER_OK then:
* - if caps.asynchronous_ops == true then the operation will be completed with registered client callback passed to Initialize().
* - if caps.asynchronous_ops == false then the operation has completed synchronously and no bytes were written.
* - if cfsStatus < ARM_DRIVER_OK then an error has occurred
*/
CFSTORE_TEST_UTEST_MESSAGE(cfstore_example2_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to write key (rc=%" PRId32 ")\n", __func__, cfsStatus);
TEST_ASSERT_MESSAGE(cfsStatus >= ARM_DRIVER_OK, cfstore_example2_utest_msg_g);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_example2_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%sError: valueLength(%" PRId32 ") does not match the expected dataLength(%" PRId32 ")\n", __func__, (int32_t) valueLength, (int32_t) *dataLength);
TEST_ASSERT_MESSAGE(*dataLength == valueLength, cfstore_example2_utest_msg_g);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_example2_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%sError: Write() return value cfsStatus(%" PRId32 ") does not match the expected dataLength(%" PRId32 ")\n", __func__, cfsStatus, (int32_t) *dataLength);
TEST_ASSERT_MESSAGE((int32_t) *dataLength == cfsStatus, cfstore_example2_utest_msg_g);
drv->Close(hkey);
/* CreateKeyValueStore() returns what was returned from Write(). See (1) above for description. */
return cfsStatus;
}
static control_t cfstore_example2_test_01(const size_t call_count)
{
int32_t cfsStatus;
ARM_CFSTORE_HANDLE_INIT(hkey);
ARM_CFSTORE_HANDLE_INIT(updatedKeyH);
ARM_CFSTORE_FMODE flags;
ARM_CFSTORE_KEYDESC kdesc;
ARM_CFSTORE_SIZE valueLen;
char* ptr = NULL;
const char key[] = "com.arm.mbed.spv.assets.asset2.payload";
const char value[] = "Grumpy old man";
(void) call_count;
// It must not exceed the value_len field specified when the Key-Value pair was created
const char newDataToWrite[] = "Grumpy man";
char readBuf[CFSTORE_KEY_NAME_MAX_LENGTH + 1];
ARM_CFSTORE_SIZE len = 0;
// Write a key-value pair
PvMemSet(&kdesc, 0, sizeof(kdesc));
PvMemSet(&flags, 0, sizeof(flags));
PvMemSet(readBuf, 0, CFSTORE_KEY_NAME_MAX_LENGTH + 1);
kdesc.drl = ARM_RETENTION_WHILE_DEVICE_ACTIVE;
/* The length supplied to Write() is the number of octets to store in the blob.
* Specifying the following value for valueLen will store the terminating null to
* a string, for example.
*/
valueLen = PvStrLen(value) + 1;
cfsStatus = drv->Initialize(NULL, NULL);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_example2_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Initialize() failed (cfsStatus=%" PRId32 ")\n", __func__, cfsStatus);
TEST_ASSERT_MESSAGE(cfsStatus >= ARM_DRIVER_OK, cfstore_example2_utest_msg_g);
cfsStatus = CreateKeyValueStore(key, value, &valueLen, &kdesc);
/* CreateKeyValueStore() returns the number of characters written, which can vary between 0 and the supplied arg valueLen
* - in the case that this example is compiled for flash mode sync, CreateKeyValueStore(), on success should always return valueLen
* - in the case that this example is compiled for flash mode async, CreateKeyValueStore() on success may return a value 0 to valueLen
* with async notification of the completed transaction.
*/
CFSTORE_TEST_UTEST_MESSAGE(cfstore_example2_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%sError: valueLen(%" PRId32 ") does not match the expected returned value from CreateKeyValueStore(%" PRId32 ")\n", __func__, (int32_t) valueLen, cfsStatus);
TEST_ASSERT_MESSAGE(cfsStatus == (int32_t) valueLen, cfstore_example2_utest_msg_g);
// Read key-value pair with 'Write' permission
flags.read = true;
flags.write = true;
cfsStatus = drv->Open(key, flags, hkey);
TEST_ASSERT_EQUAL(ARM_DRIVER_OK, cfsStatus);
len = sizeof(readBuf);
cfsStatus = drv->Read(hkey, readBuf, &len);
/* Read() returns the number of characters read, which can vary between 0 and the size of the value blob, and the size of the supplied buffer */
CFSTORE_TEST_UTEST_MESSAGE(cfstore_example2_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Read() returned value (%" PRId32 ") does not match the created length of the value blob(%" PRId32 ")\n", __func__, cfsStatus, (int32_t) PvStrLen(value) + 1);
TEST_ASSERT_MESSAGE(cfsStatus == (int32_t) (PvStrLen(value) + 1), cfstore_example2_utest_msg_g);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_example2_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Read() returned len value (%" PRId32 ") does not match the created length of the value blob(%" PRId32 ")\n", __func__, (int32_t) len, (int32_t) PvStrLen(value) + 1);
TEST_ASSERT_MESSAGE(len == PvStrLen(value) + 1, cfstore_example2_utest_msg_g);
/* Note:
* - original data = "Grumpy old man", which is 14+1 chars inc NULL
* - New data = "Grumpy man" which is 10+1 chars inc NULL
* - when the key "com.arm.mbed.spv.assets.asset2.payload"; was created, it was created with a value blob size of 14+1=15 chars.
* - The new data is shorter that the old data so it will be accommodated in the value blob
* - The size of the value blob will stay the same.
*/
// Update the value and value length
/* note len set to sizeof(newDataToWrite) which includes the terminating null of the string */
len = sizeof(newDataToWrite);
cfsStatus = drv->Write(hkey, newDataToWrite, &len);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_example2_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Write() returned cfsStatus value (%" PRId32 ") does not match the length of new data written(%" PRId32 ")\n", __func__, cfsStatus, (int32_t) sizeof(newDataToWrite));
TEST_ASSERT_MESSAGE(cfsStatus == (int32_t) sizeof(newDataToWrite), cfstore_example2_utest_msg_g);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_example2_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Write() returned len (%" PRId32 ") does not match the length of new data written(%" PRId32 ")\n", __func__, (int32_t) len, (int32_t) sizeof(newDataToWrite));
TEST_ASSERT_MESSAGE((int32_t) len == (int32_t) sizeof(newDataToWrite), cfstore_example2_utest_msg_g);
drv->Close(hkey);
// Check that the value was updated
flags.write = false;
cfsStatus = drv->Open(key, flags, updatedKeyH);
TEST_ASSERT_EQUAL(ARM_DRIVER_OK, cfsStatus);
len = CFSTORE_KEY_NAME_MAX_LENGTH;
PvMemSet(readBuf, 0, len);
cfsStatus = drv->Read(updatedKeyH, readBuf, &len);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_example2_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Read() returned value (%" PRId32 ") does not match the created length of the value blob(%" PRId32 ")\n", __func__, cfsStatus, (int32_t) PvStrLen(value) + 1);
TEST_ASSERT_MESSAGE(cfsStatus == (int32_t) (PvStrLen(value) + 1), cfstore_example2_utest_msg_g);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_example2_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Read() returned len value (%" PRId32 ") does not match the created length of the value blob(%" PRId32 ")\n", __func__, (int32_t) len, (int32_t) PvStrLen(value) + 1);
TEST_ASSERT_MESSAGE(len == (PvStrLen(value) + 1), cfstore_example2_utest_msg_g);
/* convert any terminating nulls to '=' */
while( (ptr = (char*) memchr(readBuf, 0, (PvStrLen(value) + 1))) != NULL)
{
*ptr = '=';
}
/* check the data is as expected */
CFSTORE_TEST_UTEST_MESSAGE(cfstore_example2_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Read() returned unexpected string (%s) where nulls have been converted to '=' chars\n", __func__, readBuf);
TEST_ASSERT_MESSAGE(strncmp(readBuf, "Grumpy man=man=", (PvStrLen(value) + 1)) == 0, cfstore_example2_utest_msg_g);
CFSTORE_LOG("Success: New value of KV (%s) value blob (with nulls converted to '=') = (%s)\n", key, readBuf);
drv->Close(updatedKeyH);
cfsStatus = drv->Uninitialize();
CFSTORE_TEST_UTEST_MESSAGE(cfstore_example2_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Uninitialize() failed (cfsStatus=%" PRId32 ")\n", __func__, cfsStatus);
TEST_ASSERT_MESSAGE(cfsStatus >= ARM_DRIVER_OK, cfstore_example2_utest_msg_g);
return CaseNext;
}
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(400, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
/* 1 2 3 4 5 6 7 */
/* 1234567890123456789012345678901234567890123456789012345678901234567890 */
Case("EXAMPLE2_test_00", cfstore_example2_test_00),
Case("EXAMPLE2_test_01", cfstore_example2_test_01),
};
/* Declare your test specification with a custom setup handler */
Specification specification(greentea_setup, cases);
#if defined CFSTORE_CONFIG_MBED_OS_VERSION && CFSTORE_CONFIG_MBED_OS_VERSION == 3
/* mbedosV3*/
void app_start(int argc __unused, char** argv __unused)
{
/* Run the test specification */
Harness::run(specification);
}
#endif /* CFSTORE_CONFIG_MBED_OS_VERSION == 3 */
#if defined CFSTORE_CONFIG_MBED_OS_VERSION && CFSTORE_CONFIG_MBED_OS_VERSION == 4
/* mbedosV3++*/
int main()
{
return !Harness::run(specification);
}
#endif /* CFSTORE_CONFIG_MBED_OS_VERSION == 4 */
#endif // __MBED__ && ! defined TOOLCHAIN_GCC_ARM

View File

@ -0,0 +1,393 @@
/** @file example3.cpp
*
* mbed Microcontroller Library
* Copyright (c) 2006-2016 ARM Limited
*
* 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.
*
* Test cases to add and delete KVs in the CFSTORE.
*/
/* Notes
* =====
*
* The flash-journal synchronous mode example test does the following CFSTORE operations:
* - initialises
* - creates a key-value pair (KV).
* - writes the data for the KV
* - closes KV.
* - flushes the KV to flash
* - opens KV for reading.
* - reads KV and checks the value blob was the same as previously written.
* - closes KV.
* - finds a KV (there is only 1 to find).
* - for the KV returned, get the key name.
* - for the KV returned, get the value length.
* - for the KV returned, delete the KV.
* - find another KV (which fails as there are no more keys to find).
* - flushes the updated state to flash to store the removal of the deleted KV.
* - uninitialises
* - stops
*
* This test is coded so as to work only in flash journal sync mode
* i.e. with caps.asynchronous_ops == false
*
* The test leaves the flash in the same state as at the beginning of the test so
* it can be run a second time on the device without flashing, and the test should
* still work.
*/
#if defined __MBED__ && ! defined TOOLCHAIN_GCC_ARM
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#ifdef TARGET_LIKE_FRDM_K64F_GCC
#include <mbed-drivers/mbed.h>
#endif
#include "cfstore_config.h"
#include <Driver_Common.h>
#include "cfstore_debug.h"
#include "cfstore_test.h"
#include <configuration-store/configuration_store.h>
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#ifdef YOTTA_CFG_CFSTORE_UVISOR
#include "uvisor-lib/uvisor-lib.h"
#include "cfstore_uvisor.h"
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
using namespace utest::v1;
static control_t cfstore_example3_test_00(const size_t call_count)
{
(void) call_count;
printf("Not implemented for ARM toolchain\n");
return CaseNext;
}
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(100, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
/* 1 2 3 4 5 6 7 */
/* 1234567890123456789012345678901234567890123456789012345678901234567890 */
Case("EXAMPLE3_test_00", cfstore_example3_test_00),
};
/* Declare your test specification with a custom setup handler */
Specification specification(greentea_setup, cases);
int main()
{
return !Harness::run(specification);
}
#else
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef TARGET_LIKE_FRDM_K64F_GCC
#include <mbed-drivers/mbed.h>
#endif
#ifndef YOTTA_CONFIGURATION_STORE_EXAMPLE3_VERSION_STRING
/* when built as Configuration-Store example, include greentea support otherwise omit */
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#else // YOTTA_CONFIGURATION_STORE_EXAMPLE3_VERSION_STRING
// map utest types for building as stand alone example
#define control_t void
#define CaseNext
#endif // YOTTA_CONFIGURATION_STORE_EXAMPLE3_VERSION_STRING
#include <stdio.h>
#include <string.h>
#include "cfstore_config.h"
#include <configuration-store/configuration_store.h>
#ifdef YOTTA_CFG_CONFIG_UVISOR
#include "uvisor-lib/uvisor-lib.h"
#endif /* YOTTA_CFG_CONFIG_UVISOR */
#ifndef YOTTA_CONFIGURATION_STORE_EXAMPLE3_VERSION_STRING
using namespace utest::v1;
#endif
#define CFSTORE_EX1_TEST_ASSERT(Expr) if (!(Expr)) { printf("%s:%u: assertion failure\r\n", __FUNCTION__, __LINE__); while (1) ;}
#define CFSTORE_EX1_TEST_ASSERT_EQUAL(expected, actual) if ((expected) != (actual)) {printf("%s:%u: assertion failure\r\n", __FUNCTION__, __LINE__); while (1) ;}
#define CFSTORE_EX1_TEST_ASSERT_NOT_EQUAL(expected, actual) if ((expected) == (actual)) {printf("%s:%u: assertion failure\r\n", __FUNCTION__, __LINE__); while (1) ;}
#define CFSTORE_EX1_TEST_ASSERT_MSG(Expr, _fmt, ...) \
do \
{ \
if (!(Expr)) \
{ \
printf(_fmt, __VA_ARGS__); \
while (1) ; \
} \
}while(0);
#define CFSTORE_EX1_LOG(_fmt, ...) \
do \
{ \
printf(_fmt, __VA_ARGS__); \
}while(0);
const char* cfstore_ex3_opcode_str[] =
{
"UNDEFINED",
"CFSTORE_OPCODE_CLOSE",
"CFSTORE_OPCODE_CREATE",
"CFSTORE_OPCODE_DELETE",
"CFSTORE_OPCODE_FIND",
"CFSTORE_OPCODE_FLUSH",
"CFSTORE_OPCODE_GET_KEY_NAME",
"CFSTORE_OPCODE_GET_STATUS",
"CFSTORE_OPCODE_GET_VALUE_LEN",
"CFSTORE_OPCODE_INITIALIZE",
"CFSTORE_OPCODE_OPEN",
"CFSTORE_OPCODE_POWER_CONTROL",
"CFSTORE_OPCODE_READ",
"CFSTORE_OPCODE_RSEEK",
"CFSTORE_OPCODE_UNINITIALIZE",
"CFSTORE_OPCODE_WRITE",
"CFSTORE_OPCODE_MAX"
};
const char* cfstore_ex3_kv_name = "basement.medicine.pavement.government.trenchcoat.off.cough.off.kid.did.when.again.alleyway.friend.cap.pen.dollarbills.ten.foot.soot.put.but.anyway.say.May.DA.kid.did.toes.bows.those.hose.nose.clothes.man.blows.well.well";
const char* cfstore_ex3_kv_value = "TheRollingStone";
#define CFSTORE_EX1_RSEEK_OFFSET 10 /* offset to S of Stone */
typedef struct cfstore_example3_ctx_t
{
ARM_CFSTORE_CAPABILITIES caps;;
uint8_t hkey[CFSTORE_HANDLE_BUFSIZE];
uint8_t hkey_next_buf[CFSTORE_HANDLE_BUFSIZE];
uint8_t hkey_prev_buf[CFSTORE_HANDLE_BUFSIZE];
ARM_CFSTORE_HANDLE hkey_next;
ARM_CFSTORE_HANDLE hkey_prev;
ARM_CFSTORE_SIZE len;
ARM_CFSTORE_KEYDESC kdesc;
ARM_CFSTORE_FMODE flags;
char value[CFSTORE_KEY_NAME_MAX_LENGTH+1];
} cfstore_example3_ctx_t;
static cfstore_example3_ctx_t cfstore_example3_ctx_g;
extern ARM_CFSTORE_DRIVER cfstore_driver;
ARM_CFSTORE_DRIVER *cfstore_drv = &cfstore_driver;
static void cfstore_ex3_test_01(cfstore_example3_ctx_t* ctx)
{
int32_t ret;
CFSTORE_EX1_LOG("INITIALIZING%s", "\r\n");
ret = cfstore_drv->Initialize(NULL, NULL);
CFSTORE_EX1_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: Initialize() should return ret >= 0 for async/synch modes(ret=%ld)\r\n", __func__, ret);
CFSTORE_EX1_LOG("CREATING%s", "\r\n");
memset(&ctx->kdesc, 0, sizeof(ARM_CFSTORE_KEYDESC));
ctx->kdesc.drl = ARM_RETENTION_NVM;
ctx->len = strlen(cfstore_ex3_kv_value);
ret = cfstore_drv->Create(cfstore_ex3_kv_name, ctx->len, &ctx->kdesc, ctx->hkey);
CFSTORE_EX1_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: Create() failed (ret=%ld)\r\n", __func__, ret);
CFSTORE_EX1_LOG("WRITING%s", "\r\n");
ctx->len = strlen(cfstore_ex3_kv_value);
ret = cfstore_drv->Write(ctx->hkey, cfstore_ex3_kv_value, &ctx->len);
CFSTORE_EX1_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: Write() failed (ret=%ld)\r\n", __func__, ret);
CFSTORE_EX1_TEST_ASSERT_MSG(ret == (int32_t) strlen(cfstore_ex3_kv_value), "%s:Error: Write() number of octets written (i.e. completion status (%ld)) != strlen(ctx->value)(%ld)\r\n", __func__, ret, (int32_t) strlen(cfstore_ex3_kv_value));
CFSTORE_EX1_TEST_ASSERT_MSG(ret == (int32_t) ctx->len, "%s:Error: Write() number of octets written (i.e. completion status (%ld)) != updated value of len parameter (%ld)\r\n", __func__, ret, (int32_t) ctx->len);
CFSTORE_EX1_LOG("CLOSING1%s", "\r\n");
ret = cfstore_drv->Close(ctx->hkey);
CFSTORE_EX1_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: Close() failed (ret=%ld)\r\n", __func__, ret);
CFSTORE_EX1_LOG("FLUSHING1%s", "\r\n");
ret = cfstore_drv->Flush();
CFSTORE_EX1_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: Flush() failed (ret=%ld)\r\n", __func__, ret);
CFSTORE_EX1_LOG("OPENING%s", "\r\n");
memset(&ctx->flags, 0, sizeof(ctx->flags));
memset(&ctx->hkey, 0, CFSTORE_HANDLE_BUFSIZE);
ret = cfstore_drv->Open(cfstore_ex3_kv_name, ctx->flags, ctx->hkey);
CFSTORE_EX1_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: Open() failed (ret=%ld)\r\n", __func__, ret);
CFSTORE_EX1_LOG("READING1%s", "\r\n");
ctx->len = CFSTORE_KEY_NAME_MAX_LENGTH;
memset(ctx->value, 0, CFSTORE_KEY_NAME_MAX_LENGTH+1);
ret = cfstore_drv->Read(ctx->hkey, ctx->value, &ctx->len);
CFSTORE_EX1_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: Read() failed (ret=%ld)\r\n", __func__, ret);
CFSTORE_EX1_TEST_ASSERT_MSG(ret == (int32_t) strlen(cfstore_ex3_kv_value), "%s:Error: Read() number of octets read (i.e. completion status (%ld)) != strlen(ctx->value)(%ld)\r\n", __func__, ret, (int32_t) strlen(cfstore_ex3_kv_value));
CFSTORE_EX1_TEST_ASSERT_MSG(ret == (int32_t) ctx->len, "%s:Error: Read() number of octets read (i.e. completion status (%ld)) != updated value of len parameter (%ld)\r\n", __func__, ret, (int32_t) ctx->len);
CFSTORE_EX1_TEST_ASSERT_MSG(strncmp(ctx->value, cfstore_ex3_kv_value, strlen(cfstore_ex3_kv_value)) == 0, "%s:Error: the read value (%s) is not as expected (%s)\r\n", __func__, ctx->value, cfstore_ex3_kv_value);
CFSTORE_EX1_LOG("RSEEKING%s", "\r\n");
ret = cfstore_drv->Rseek(ctx->hkey, CFSTORE_EX1_RSEEK_OFFSET);
CFSTORE_EX1_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: Rseek() failed (ret=%ld)\r\n", __func__, ret);
CFSTORE_EX1_LOG("READING2%s", "\r\n");
ctx->len = CFSTORE_KEY_NAME_MAX_LENGTH;
memset(ctx->value, 0, CFSTORE_KEY_NAME_MAX_LENGTH+1);
ret = cfstore_drv->Read(ctx->hkey, ctx->value, &ctx->len);
CFSTORE_EX1_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: Read() failed (ret=%ld)\r\n", __func__, ret);
CFSTORE_EX1_TEST_ASSERT_MSG(ret == (int32_t) strlen(&cfstore_ex3_kv_value[CFSTORE_EX1_RSEEK_OFFSET]), "%s:Error: Read() number of octets read (i.e. completion status (%ld)) != strlen(ctx->value)(%ld)\r\n", __func__, ret, (int32_t) strlen(&cfstore_ex3_kv_value[CFSTORE_EX1_RSEEK_OFFSET]));
CFSTORE_EX1_TEST_ASSERT_MSG(ret == (int32_t) ctx->len, "%s:Error: Read() number of octets read (i.e. completion status (%ld)) != updated value of len parameter (%ld)\r\n", __func__, ret, (int32_t) ctx->len);
CFSTORE_EX1_TEST_ASSERT_MSG(strncmp(ctx->value, &cfstore_ex3_kv_value[CFSTORE_EX1_RSEEK_OFFSET], strlen(&cfstore_ex3_kv_value[CFSTORE_EX1_RSEEK_OFFSET])) == 0, "%s:Error: the read value (%s) is not as expected (%s)\r\n", __func__, ctx->value, &cfstore_ex3_kv_value[CFSTORE_EX1_RSEEK_OFFSET]);
CFSTORE_EX1_LOG("CLOSING2%s", "\r\n");
ret = cfstore_drv->Close(ctx->hkey);
CFSTORE_EX1_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: Close() failed (ret=%ld)\r\n", __func__, ret);
CFSTORE_EX1_LOG("FINDING1%s", "\r\n");
ret = cfstore_drv->Find("*", ctx->hkey_next, ctx->hkey_prev);
CFSTORE_EX1_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: Find() failed (ret=%ld)\r\n", __func__, ret);
CFSTORE_EX1_LOG("GETTING_KEY_NAME%s", "\r\n");
ctx->len = CFSTORE_KEY_NAME_MAX_LENGTH;
memset(ctx->value, 0, CFSTORE_KEY_NAME_MAX_LENGTH+1);
ret = cfstore_drv->GetKeyName(ctx->hkey_prev, ctx->value, (uint8_t*) &ctx->len);
CFSTORE_EX1_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: GetKeyName() failed (ret=%ld)\r\n", __func__, ret);
CFSTORE_EX1_TEST_ASSERT_MSG( ((int32_t) ctx->len == ((int32_t) strlen(cfstore_ex3_kv_name)+1)), "%s:Error: GetKeyName() updated value of len parameter (%ld) != strlen(cfstore_ex3_kv_name) (%ld) (\r\n", __func__, (int32_t) ctx->len, (int32_t) strlen(cfstore_ex3_kv_name));
CFSTORE_EX1_TEST_ASSERT_MSG(strncmp(ctx->value, cfstore_ex3_kv_name, strlen(cfstore_ex3_kv_name)) == 0, "%s:Error: the key name (%s) is not as expected (%s)\r\n", __func__, ctx->value, cfstore_ex3_kv_name);
CFSTORE_EX1_LOG("GETTING_VALUE_LEN%s", "\r\n");
ctx->len = CFSTORE_KEY_NAME_MAX_LENGTH;
ret = cfstore_drv->GetValueLen(ctx->hkey_prev, &ctx->len);
CFSTORE_EX1_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: GetValueLen() failed (ret=%ld)\r\n", __func__, ret);
CFSTORE_EX1_TEST_ASSERT_MSG((int32_t) ctx->len == (int32_t) strlen(cfstore_ex3_kv_value), "%s:Error: GetValueLen() updated value of len parameter (%ld) != strlen(cfstore_ex3_kv_value)(%ld) \r\n", __func__, (int32_t) ctx->len, (int32_t) strlen(cfstore_ex3_kv_value));
CFSTORE_EX1_LOG("DELETING%s", "\r\n");
ret = cfstore_drv->Delete(ctx->hkey_prev);
CFSTORE_EX1_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: Close() failed (ret=%ld)\r\n", __func__, ret);
CFSTORE_HANDLE_SWAP(ctx->hkey_prev, ctx->hkey_next);
CFSTORE_EX1_LOG("FINDING2%s", "\r\n");
ret = cfstore_drv->Find("*", ctx->hkey_next, ctx->hkey_prev);
CFSTORE_EX1_TEST_ASSERT_MSG(ret == ARM_CFSTORE_DRIVER_ERROR_KEY_NOT_FOUND, "%s:Error: Find() failed to return expected value of ARM_CFSTORE_DRIVER_ERROR_KEY_NOT_FOUND (ret=%ld)\r\n", __func__, ret);
CFSTORE_EX1_LOG("FLUSHING2%s", "\r\n");
ret = cfstore_drv->Flush();
CFSTORE_EX1_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error:2: Flush() failed (ret=%ld)\r\n", __func__, ret);
CFSTORE_EX1_LOG("UNINITIALIZING%s", "\r\n");
ret = cfstore_drv->Uninitialize();
CFSTORE_EX1_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: Uninitialize() should return ret >= 0 for synch mode(ret=%ld)\r\n", __func__, ret);
CFSTORE_EX1_LOG("***************%s", "\r\n");
CFSTORE_EX1_LOG("*** SUCCESS ***%s", "\r\n");
CFSTORE_EX1_LOG("***************%s", "\r\n");
return;
}
static control_t cfstore_example3_app_start(const size_t call_count)
{
cfstore_example3_ctx_t* ctx = &cfstore_example3_ctx_g;
(void) call_count;
/* initialise the context */
memset(ctx, 0, sizeof(cfstore_example3_ctx_t));
ctx->hkey_next = ctx->hkey_next_buf;
ctx->hkey_prev = ctx->hkey_prev_buf;
ctx->caps = cfstore_drv->GetCapabilities();
CFSTORE_EX1_LOG("%s:INITIALIZING: caps.asynchronous_ops=%lu\n", __func__, ctx->caps.asynchronous_ops);
if(ctx->caps.asynchronous_ops == true){
/* This is a sync mode only test. If this test is not built for sync mode, then skip testing return true
* This means the test will conveniently pass when run in CI as part of async mode testing */
CFSTORE_EX1_LOG("*** Skipping test as binary built for flash journal async mode, and this test is sync-only%s", "\n");
return CaseNext;
}
cfstore_ex3_test_01(ctx);
return CaseNext;
}
#ifndef YOTTA_CONFIGURATION_STORE_EXAMPLE3_VERSION_STRING
/* when built as Configuration-Store example, include greentea support otherwise omit */
/* report whether built/configured for flash sync or async mode */
static control_t cfstore_example3_test_00(const size_t call_count)
{
(void) call_count;
CFSTORE_EX1_LOG("INITIALIZING: caps.asynchronous_ops=%lu\n", cfstore_driver.GetCapabilities().asynchronous_ops);
return CaseNext;
}
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(100, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
/* 1 2 3 4 5 6 7 */
/* 1234567890123456789012345678901234567890123456789012345678901234567890 */
Case("EXAMPLE3_test_00", cfstore_example3_test_00),
Case("EXAMPLE3_test_01_start", cfstore_example3_app_start),
};
/* Declare your test specification with a custom setup handler */
Specification specification(greentea_setup, cases);
#if defined CFSTORE_CONFIG_MBED_OS_VERSION && CFSTORE_CONFIG_MBED_OS_VERSION == 3
/* mbedosV3*/
void app_start(int argc __unused, char** argv __unused)
{
/* Run the test specification */
Harness::run(specification);
}
#endif /* CFSTORE_CONFIG_MBED_OS_VERSION == 3 */
#if defined CFSTORE_CONFIG_MBED_OS_VERSION && CFSTORE_CONFIG_MBED_OS_VERSION == 4
/* mbedosV3++*/
int main()
{
return !Harness::run(specification);
}
#endif /* CFSTORE_CONFIG_MBED_OS_VERSION == 4 */
#else // YOTTA_CONFIGURATION_STORE_EXAMPLE3_VERSION_STRING
// stand alone Configuration-Store-Example
void app_start(int argc __unused, char** argv __unused)
{
cfstore_example3_app_start(0);
}
#endif // YOTTA_CONFIGURATION_STORE_EXAMPLE3_VERSION_STRING
#endif // __MBED__ && ! defined TOOLCHAIN_GCC_ARM

View File

@ -0,0 +1,278 @@
/** @file example3.cpp
*
* mbed Microcontroller Library
* Copyright (c) 2006-2016 ARM Limited
*
* 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.
*
* Test cases to add and delete KVs in the CFSTORE.
*/
#if defined __MBED__ && ! defined TOOLCHAIN_GCC_ARM
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#ifdef TARGET_LIKE_FRDM_K64F_GCC
#include <mbed-drivers/mbed.h>
#endif
#include "cfstore_config.h"
#include <Driver_Common.h>
#include "cfstore_debug.h"
#include "cfstore_test.h"
#include <configuration-store/configuration_store.h>
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#ifdef YOTTA_CFG_CFSTORE_UVISOR
#include "uvisor-lib/uvisor-lib.h"
#include "cfstore_uvisor.h"
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
using namespace utest::v1;
static control_t cfstore_example4_test_00(const size_t call_count)
{
(void) call_count;
printf("Not implemented for ARM toolchain\n");
return CaseNext;
}
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(100, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
/* 1 2 3 4 5 6 7 */
/* 1234567890123456789012345678901234567890123456789012345678901234567890 */
Case("EXAMPLE4_test_00", cfstore_example4_test_00),
};
/* Declare your test specification with a custom setup handler */
Specification specification(greentea_setup, cases);
int main()
{
return !Harness::run(specification);
}
#else
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <inttypes.h>
#ifdef TARGET_LIKE_FRDM_K64F_GCC
#include <mbed-drivers/mbed.h>
#endif
#include "cfstore_config.h"
#include "cfstore_test.h"
#include "cfstore_debug.h"
//#include <flash-abstraction/Driver_Common.h>
#include <Driver_Common.h>
#include <configuration-store/configuration_store.h>
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#ifdef YOTTA_CFG_CONFIG_UVISOR
#include "uvisor-lib/uvisor-lib.h"
#endif /* YOTTA_CFG_CONFIG_UVISOR */
using namespace utest::v1;
static char cfstore_example4_utest_msg_g[CFSTORE_UTEST_MSG_BUF_SIZE];
/* Notes
* Test case created from Issue 10 code supplied by Motti Gondabi. The code:
* - creates a KV
* - writes the KV
* - closes the KV
* - flushes the KV
* - opens the KV.
* - deletes the KV.
* - flushes empty configuration store.
*
* The test case makes sure that the implementation can flush an empty configuration store
* without causing errors. This has only been possible since flash-journal-strategy-sequential
* v0.4.0.
*/
/* defines */
#define PvMemSet memset
#define PvStrLen strlen
#define PvKeyValue_t cfstore_kv_data_t
ARM_CFSTORE_DRIVER *gCfStoreDriver = &cfstore_driver;
static const PvKeyValue_t testDataKeyValue[] = {
{ "com.arm.mbed.spv.assets.dtls", "This Is my DTLS Secret" },
{ "com.arm.mbed.spv.assets.asset1.payload", "The Rolling Stone" },
{ "com.arm.mbed.spv.assets.asset2.payload", "Grumpy old man" },
{ "com.arm.mbed.spv.assets.asset3.payload", "Delete this asset payload" },
};
static control_t cfstore_example4_test_00(const size_t call_count)
{
ARM_CFSTORE_CAPABILITIES caps;;
(void) call_count;
/* initialise the context */
caps = gCfStoreDriver->GetCapabilities();
CFSTORE_LOG("%s:INITIALIZING: caps.asynchronous_ops=%lu\n", __func__, caps.asynchronous_ops);
if(caps.asynchronous_ops == true){
/* This is a sync mode only test. If this test is not built for sync mode, then skip testing return true
* This means the test will conveniently pass when run in CI as part of async mode testing */
CFSTORE_LOG("*** Skipping test as binary built for flash journal async mode, and this test is sync-only%s", "\n");
return CaseNext;
}
return CaseNext;
}
static int32_t CreateKeyValueStore(
const char *keyName,
const char *data,
ARM_CFSTORE_SIZE *dataLength,
ARM_CFSTORE_KEYDESC *keyDesc)
{
int32_t cfsStatus = ARM_DRIVER_ERROR;
ARM_CFSTORE_SIZE valueLength = 0;
ARM_CFSTORE_HANDLE_INIT(hkey);
valueLength = *dataLength;
cfsStatus = gCfStoreDriver->Create(keyName, valueLength, keyDesc, hkey);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_example4_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Create() failed (cfsStatus=%" PRId32 ")\n", __func__, cfsStatus);
TEST_ASSERT_MESSAGE(cfsStatus >= ARM_DRIVER_OK, cfstore_example4_utest_msg_g);
valueLength = *dataLength;
cfsStatus = gCfStoreDriver->Write(hkey, data, &valueLength);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_example4_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Write() failed (cfsStatus=%" PRId32 ")\n", __func__, cfsStatus);
TEST_ASSERT_MESSAGE(cfsStatus >= ARM_DRIVER_OK, cfstore_example4_utest_msg_g);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_example4_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: valueLength != *dataLength\n", __func__);
TEST_ASSERT_MESSAGE(valueLength == *dataLength, cfstore_example4_utest_msg_g);
cfsStatus = gCfStoreDriver->Close(hkey);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_example4_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Close() failed (cfsStatus=%" PRId32 ")\n", __func__, cfsStatus);
TEST_ASSERT_MESSAGE(cfsStatus >= ARM_DRIVER_OK, cfstore_example4_utest_msg_g);
cfsStatus = gCfStoreDriver->Flush();
CFSTORE_TEST_UTEST_MESSAGE(cfstore_example4_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Flush() failed (cfsStatus=%" PRId32 ")\n", __func__, cfsStatus);
TEST_ASSERT_MESSAGE(cfsStatus >= ARM_DRIVER_OK, cfstore_example4_utest_msg_g);
return ARM_DRIVER_OK;
}
// main test.
static control_t cfstore_example4_test_01(const size_t call_count)
{
int32_t cfsStatus = ARM_DRIVER_ERROR;
ARM_CFSTORE_KEYDESC kdesc;
ARM_CFSTORE_SIZE valueLen;
ARM_CFSTORE_FMODE flags;
ARM_CFSTORE_HANDLE_INIT(hkey);
(void) call_count;
PvMemSet(&kdesc, 0, sizeof(kdesc));
kdesc.drl = ARM_RETENTION_NVM;
valueLen = PvStrLen(testDataKeyValue[0].value);
cfsStatus = gCfStoreDriver->Initialize(NULL, NULL);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_example4_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Initialize() failed (cfsStatus=%" PRId32 ")\n", __func__, cfsStatus);
TEST_ASSERT_MESSAGE(cfsStatus >= ARM_DRIVER_OK, cfstore_example4_utest_msg_g);
cfsStatus = CreateKeyValueStore(testDataKeyValue[0].key_name, testDataKeyValue[0].value, &valueLen, &kdesc);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_example4_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: CreateKeyValueStore() failed (cfsStatus=%" PRId32 ")\n", __func__, cfsStatus);
TEST_ASSERT_MESSAGE(cfsStatus >= ARM_DRIVER_OK, cfstore_example4_utest_msg_g);
PvMemSet(&flags, 0, sizeof(flags));
cfsStatus = gCfStoreDriver->Open(testDataKeyValue[0].key_name, flags, hkey);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_example4_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Open() failed (cfsStatus=%" PRId32 ")\n", __func__, cfsStatus);
TEST_ASSERT_MESSAGE(cfsStatus >= ARM_DRIVER_OK, cfstore_example4_utest_msg_g);
cfsStatus = gCfStoreDriver->Delete(hkey);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_example4_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Delete() failed (cfsStatus=%" PRId32 ")\n", __func__, cfsStatus);
TEST_ASSERT_MESSAGE(cfsStatus >= ARM_DRIVER_OK, cfstore_example4_utest_msg_g);
cfsStatus = gCfStoreDriver->Close(hkey);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_example4_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Close() failed (cfsStatus=%" PRId32 ")\n", __func__, cfsStatus);
TEST_ASSERT_MESSAGE(cfsStatus >= ARM_DRIVER_OK, cfstore_example4_utest_msg_g);
cfsStatus = gCfStoreDriver->Flush();
CFSTORE_TEST_UTEST_MESSAGE(cfstore_example4_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Flush() failed (cfsStatus=%" PRId32 ")\n", __func__, cfsStatus);
TEST_ASSERT_MESSAGE(cfsStatus >= ARM_DRIVER_OK, cfstore_example4_utest_msg_g);
cfsStatus = gCfStoreDriver->Uninitialize();
CFSTORE_TEST_UTEST_MESSAGE(cfstore_example4_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Uninitialize() failed (cfsStatus=%" PRId32 ")\n", __func__, cfsStatus);
TEST_ASSERT_MESSAGE(cfsStatus >= ARM_DRIVER_OK, cfstore_example4_utest_msg_g);
return CaseNext;
}
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(400, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
/* 1 2 3 4 5 6 7 */
/* 1234567890123456789012345678901234567890123456789012345678901234567890 */
Case("EXAMPLE4_test_00", cfstore_example4_test_00),
#if defined YOTTA_CFG_CONFIG_HARDWARE_MTD_ASYNC_OPS && YOTTA_CFG_CONFIG_HARDWARE_MTD_ASYNC_OPS == 0
Case("EXAMPLE4_test_01", cfstore_example4_test_01),
#endif // YOTTA_CFG_CONFIG_HARDWARE_MTD_ASYNC_OPS
};
/* Declare your test specification with a custom setup handler */
Specification specification(greentea_setup, cases);
#if defined CFSTORE_CONFIG_MBED_OS_VERSION && CFSTORE_CONFIG_MBED_OS_VERSION == 3
/* mbedosV3*/
void app_start(int argc __unused, char** argv __unused)
{
/* Run the test specification */
Harness::run(specification);
}
#endif /* CFSTORE_CONFIG_MBED_OS_VERSION == 3 */
#if defined CFSTORE_CONFIG_MBED_OS_VERSION && CFSTORE_CONFIG_MBED_OS_VERSION == 4
/* mbedosV3++*/
int main()
{
return !Harness::run(specification);
}
#endif /* CFSTORE_CONFIG_MBED_OS_VERSION == 4 */
#endif // __MBED__ && ! defined TOOLCHAIN_GCC_ARM

View File

@ -0,0 +1,365 @@
/** @file EXAMPLE5.cpp
*
* mbed Microcontroller Library
* Copyright (c) 2006-2016 ARM Limited
*
* 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.
*
* Test cases to add and delete KVs in the CFSTORE.
*/
/* Notes
* =====
*
* The flash-journal synchronous mode example test does the following CFSTORE operations:
* - initialises
* - creates a key-value pair (KV).
* - writes the data for the KV
* - closes KV.
* - flushes the KV to flash
* - flushes the KV to flash again
* - uninitialises
* - initialises
* - opens KV for reading.
* - deletes KV
* - closes KV.
* - flushes the updated state to flash to store the removal of the deleted KV.
* - uninitialises
* - stops
*
* This test is coded so as to work only in flash journal sync mode
* i.e. with caps.asynchronous_ops == false
*
* The test leaves the flash in the same state as at the beginning of the test so
* it can be run a second time on the device without flashing, and the test should
* still work.
*/
#if defined __MBED__ && ! defined TOOLCHAIN_GCC_ARM
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#ifdef TARGET_LIKE_FRDM_K64F_GCC
#include <mbed-drivers/mbed.h>
#endif
#include "cfstore_config.h"
#include <Driver_Common.h>
#include "cfstore_debug.h"
#include "cfstore_test.h"
#include <configuration-store/configuration_store.h>
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#ifdef YOTTA_CFG_CFSTORE_UVISOR
#include "uvisor-lib/uvisor-lib.h"
#include "cfstore_uvisor.h"
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
using namespace utest::v1;
static control_t cfstore_example5_test_00(const size_t call_count)
{
(void) call_count;
printf("Not implemented for ARM toolchain\n");
return CaseNext;
}
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(100, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
/* 1 2 3 4 5 6 7 */
/* 1234567890123456789012345678901234567890123456789012345678901234567890 */
Case("EXAMPLE5_test_00", cfstore_example5_test_00),
};
/* Declare your test specification with a custom setup handler */
Specification specification(greentea_setup, cases);
int main()
{
return !Harness::run(specification);
}
#else
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
#ifdef TARGET_LIKE_FRDM_K64F_GCC
#include <mbed-drivers/mbed.h>
#endif
//#include <flash-abstraction/Driver_Common.h>
#include <Driver_Common.h>
#ifndef YOTTA_CONFIGURATION_STORE_EXAMPLE5_VERSION_STRING
/* when built as Configuration-Store example, include greentea support otherwise omit */
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#else // YOTTA_CONFIGURATION_STORE_EXAMPLE5_VERSION_STRING
// map utest types for building as stand alone example
#define control_t void
#define CaseNext
#endif // YOTTA_CONFIGURATION_STORE_EXAMPLE5_VERSION_STRING
#include "cfstore_config.h"
#include <configuration-store/configuration_store.h>
#ifndef YOTTA_CONFIGURATION_STORE_EXAMPLE5_VERSION_STRING
using namespace utest::v1;
#endif
#define CFSTORE_EX5_TEST_ASSERT(Expr) if (!(Expr)) { printf("%s:%u: assertion failure\r\n", __FUNCTION__, __LINE__); while (1) ;}
#define CFSTORE_EX5_TEST_ASSERT_EQUAL(expected, actual) if ((expected) != (actual)) {printf("%s:%u: assertion failure\r\n", __FUNCTION__, __LINE__); while (1) ;}
#define CFSTORE_EX5_TEST_ASSERT_NOT_EQUAL(expected, actual) if ((expected) == (actual)) {printf("%s:%u: assertion failure\r\n", __FUNCTION__, __LINE__); while (1) ;}
#define CFSTORE_EX5_TEST_ASSERT_MSG(Expr, _fmt, ...) \
do \
{ \
if (!(Expr)) \
{ \
printf(_fmt, __VA_ARGS__); \
while (1) ; \
} \
}while(0);
#define CFSTORE_EX5_LOG(_fmt, ...) \
do \
{ \
printf(_fmt, __VA_ARGS__); \
}while(0);
const char* cfstore_ex5_opcode_str[] =
{
"UNDEFINED",
"CFSTORE_OPCODE_CLOSE",
"CFSTORE_OPCODE_CREATE",
"CFSTORE_OPCODE_DELETE",
"CFSTORE_OPCODE_FIND",
"CFSTORE_OPCODE_FLUSH",
"CFSTORE_OPCODE_GET_KEY_NAME",
"CFSTORE_OPCODE_GET_STATUS",
"CFSTORE_OPCODE_GET_VALUE_LEN",
"CFSTORE_OPCODE_INITIALIZE",
"CFSTORE_OPCODE_OPEN",
"CFSTORE_OPCODE_POWER_CONTROL",
"CFSTORE_OPCODE_READ",
"CFSTORE_OPCODE_RSEEK",
"CFSTORE_OPCODE_UNINITIALIZE",
"CFSTORE_OPCODE_WRITE",
"CFSTORE_OPCODE_MAX"
};
const char* cfstore_ex5_kv_name = "basement.medicine.pavement.government.trenchcoat.off.cough.off.kid.did.when.again.alleyway.friend.cap.pen.dollarbills.ten.foot.soot.put.but.anyway.say.May.DA.kid.did.toes.bows.those.hose.nose.clothes.man.blows.well.well";
const char* cfstore_ex5_kv_value = "TheRollingStone";
#define CFSTORE_EX5_RSEEK_OFFSET 10 /* offset to S of Stone */
typedef struct cfstore_EXAMPLE5_ctx_t
{
ARM_CFSTORE_CAPABILITIES caps;;
uint8_t hkey[CFSTORE_HANDLE_BUFSIZE];
uint8_t hkey_next_buf[CFSTORE_HANDLE_BUFSIZE];
uint8_t hkey_prev_buf[CFSTORE_HANDLE_BUFSIZE];
ARM_CFSTORE_HANDLE hkey_next;
ARM_CFSTORE_HANDLE hkey_prev;
ARM_CFSTORE_SIZE len;
ARM_CFSTORE_KEYDESC kdesc;
ARM_CFSTORE_FMODE flags;
char value[CFSTORE_KEY_NAME_MAX_LENGTH+1];
} cfstore_EXAMPLE5_ctx_t;
static cfstore_EXAMPLE5_ctx_t cfstore_EXAMPLE5_ctx_g;
extern ARM_CFSTORE_DRIVER cfstore_driver;
ARM_CFSTORE_DRIVER *cfstore_drv = &cfstore_driver;
static void cfstore_ex5_test_01(cfstore_EXAMPLE5_ctx_t* ctx)
{
int32_t ret;
CFSTORE_EX5_LOG("INITIALIZING1%s", "\r\n");
ret = cfstore_drv->Initialize(NULL, NULL);
CFSTORE_EX5_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: Initialize() should return ret >= 0 for async/synch modes(ret=%ld)\r\n", __func__, ret);
CFSTORE_EX5_LOG("CREATING%s", "\r\n");
memset(&ctx->kdesc, 0, sizeof(ARM_CFSTORE_KEYDESC));
ctx->kdesc.drl = ARM_RETENTION_NVM;
ctx->len = strlen(cfstore_ex5_kv_value);
ret = cfstore_drv->Create(cfstore_ex5_kv_name, ctx->len, &ctx->kdesc, ctx->hkey);
CFSTORE_EX5_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: Create() failed (ret=%ld)\r\n", __func__, ret);
CFSTORE_EX5_LOG("WRITING%s", "\r\n");
ctx->len = strlen(cfstore_ex5_kv_value);
ret = cfstore_drv->Write(ctx->hkey, cfstore_ex5_kv_value, &ctx->len);
CFSTORE_EX5_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: Write() failed (ret=%ld)\r\n", __func__, ret);
CFSTORE_EX5_TEST_ASSERT_MSG(ret == (int32_t) strlen(cfstore_ex5_kv_value), "%s:Error: Write() number of octets written (i.e. completion status (%ld)) != strlen(ctx->value)(%ld)\r\n", __func__, ret, (int32_t) strlen(cfstore_ex5_kv_value));
CFSTORE_EX5_TEST_ASSERT_MSG(ret == (int32_t) ctx->len, "%s:Error: Write() number of octets written (i.e. completion status (%ld)) != updated value of len parameter (%ld)\r\n", __func__, ret, (int32_t) ctx->len);
CFSTORE_EX5_LOG("CLOSING1%s", "\r\n");
ret = cfstore_drv->Close(ctx->hkey);
CFSTORE_EX5_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: Close() failed (ret=%ld)\r\n", __func__, ret);
CFSTORE_EX5_LOG("FLUSHING1%s", "\r\n");
ret = cfstore_drv->Flush();
CFSTORE_EX5_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: Flush() failed (ret=%ld)\r\n", __func__, ret);
/* commenting out the 2nd flush() means the test works.*/
//CFSTORE_EX5_LOG("FLUSHING2%s", "\r\n");
//ret = cfstore_drv->Flush();
//CFSTORE_EX5_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: Flush() failed (ret=%ld)\r\n", __func__, ret);
/* todo: re-instate when Flush() really persists to flash on mbedOSv3+++.
* currently in the supported sram version Uninitialize() clears the sram
CFSTORE_EX5_LOG("UNINITIALIZING1%s", "\r\n");
ret = cfstore_drv->Uninitialize();
CFSTORE_EX5_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: Uninitialize() should return ret >= 0 for synch mode(ret=%ld)\r\n", __func__, ret);
CFSTORE_EX5_LOG("INITIALIZING2%s", "\r\n");
ret = cfstore_drv->Initialize(NULL, NULL);
CFSTORE_EX5_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: Initialize() should return ret >= 0 for async/synch modes(ret=%ld)\r\n", __func__, ret);
*/
CFSTORE_EX5_LOG("OPENING%s", "\r\n");
memset(&ctx->flags, 0, sizeof(ctx->flags));
memset(&ctx->hkey, 0, CFSTORE_HANDLE_BUFSIZE);
ret = cfstore_drv->Open(cfstore_ex5_kv_name, ctx->flags, ctx->hkey);
CFSTORE_EX5_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: Open() failed (ret=%ld)\r\n", __func__, ret);
CFSTORE_EX5_LOG("DELETE1%s", "\r\n");
ctx->len = CFSTORE_KEY_NAME_MAX_LENGTH;
memset(ctx->value, 0, CFSTORE_KEY_NAME_MAX_LENGTH + 1);
ret = cfstore_drv->Delete(ctx->hkey);
CFSTORE_EX5_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: Delete() failed (ret=%ld)\r\n", __func__, ret);
CFSTORE_EX5_LOG("CLOSING2%s", "\r\n");
ret = cfstore_drv->Close(ctx->hkey);
CFSTORE_EX5_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: Close() failed (ret=%ld)\r\n", __func__, ret);
CFSTORE_EX5_LOG("FLUSHING3%s", "\r\n");
ret = cfstore_drv->Flush();
CFSTORE_EX5_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: Flush() failed (ret=%ld)\r\n", __func__, ret);
CFSTORE_EX5_LOG("OPEN2 %s", "\r\n");
memset(&ctx->flags, 0, sizeof(ctx->flags));
memset(&ctx->hkey, 0, CFSTORE_HANDLE_BUFSIZE);
ret = cfstore_drv->Open(cfstore_ex5_kv_name, ctx->flags, ctx->hkey);
CFSTORE_EX5_TEST_ASSERT_MSG(ret == ARM_CFSTORE_DRIVER_ERROR_KEY_NOT_FOUND, "%s:Error: Find() failed to return expected value of ARM_CFSTORE_DRIVER_ERROR_KEY_NOT_FOUND (ret=%ld)\r\n", __func__, ret);
CFSTORE_EX5_LOG("FLUSHING2%s", "\r\n");
ret = cfstore_drv->Flush();
CFSTORE_EX5_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error:2: Flush() failed (ret=%ld)\r\n", __func__, ret);
CFSTORE_EX5_LOG("UNINITIALIZING3%s", "\r\n");
ret = cfstore_drv->Uninitialize();
CFSTORE_EX5_TEST_ASSERT_MSG(ret >= ARM_DRIVER_OK, "%s:Error: Uninitialize() should return ret >= 0 for synch mode(ret=%ld)\r\n", __func__, ret);
CFSTORE_EX5_LOG("***************%s", "\r\n");
CFSTORE_EX5_LOG("*** SUCCESS ***%s", "\r\n");
CFSTORE_EX5_LOG("***************%s", "\r\n");
return;
}
static control_t cfstore_EXAMPLE5_app_start(const size_t call_count)
{
cfstore_EXAMPLE5_ctx_t* ctx = &cfstore_EXAMPLE5_ctx_g;
(void) call_count;
/* initialise the context */
memset(ctx, 0, sizeof(cfstore_EXAMPLE5_ctx_t));
ctx->hkey_next = ctx->hkey_next_buf;
ctx->hkey_prev = ctx->hkey_prev_buf;
ctx->caps = cfstore_drv->GetCapabilities();
CFSTORE_EX5_LOG("%s:INITIALIZING: caps.asynchronous_ops=%lu\n", __func__, ctx->caps.asynchronous_ops);
if(ctx->caps.asynchronous_ops == true){
/* This is a sync mode only test. If this test is not built for sync mode, then skip testing return true
* This means the test will conveniently pass when run in CI as part of async mode testing */
CFSTORE_EX5_LOG("*** Skipping test as binary built for flash journal async mode, and this test is sync-only%s", "\n");
return CaseNext;
}
cfstore_ex5_test_01(ctx);
return CaseNext;
}
#ifndef YOTTA_CONFIGURATION_STORE_EXAMPLE5_VERSION_STRING
/* when built as Configuration-Store example, include greentea support otherwise omit */
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(100, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
/* 1 2 3 4 5 6 7 */
/* 1234567890123456789012345678901234567890123456789012345678901234567890 */
Case("EXAMPLE5_test_01_start", cfstore_EXAMPLE5_app_start),
};
/* Declare your test specification with a custom setup handler */
Specification specification(greentea_setup, cases);
#if defined CFSTORE_CONFIG_MBED_OS_VERSION && CFSTORE_CONFIG_MBED_OS_VERSION == 3
/* mbedosV3*/
void app_start(int argc __unused, char** argv __unused)
{
/* Run the test specification */
Harness::run(specification);
}
#endif /* CFSTORE_CONFIG_MBED_OS_VERSION == 3 */
#if defined CFSTORE_CONFIG_MBED_OS_VERSION && CFSTORE_CONFIG_MBED_OS_VERSION == 4
/* mbedosV3++*/
int main()
{
return !Harness::run(specification);
}
#endif /* CFSTORE_CONFIG_MBED_OS_VERSION == 4 */
#else // YOTTA_CONFIGURATION_STORE_EXAMPLE5_VERSION_STRING
// stand alone Configuration-Store-Example
void app_start(int argc __unused, char** argv __unused)
{
cfstore_EXAMPLE5_app_start(0);
}
#endif // YOTTA_CONFIGURATION_STORE_EXAMPLE5_VERSION_STRING
#endif // __MBED__ && ! defined TOOLCHAIN_GCC_ARM

443
TESTS/cfstore/find/find.cpp Normal file
View File

@ -0,0 +1,443 @@
/** @file find.cpp
*
* mbed Microcontroller Library
* Copyright (c) 2006-2016 ARM Limited
*
* 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.
*
* Test cases to find KVs in the CFSTORE using the drv->Find() interface.
*/
#if defined __MBED__ && ! defined TOOLCHAIN_GCC_ARM
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#ifdef TARGET_LIKE_FRDM_K64F_GCC
#include <mbed-drivers/mbed.h>
#endif
#include "cfstore_config.h"
#include <Driver_Common.h>
#include "cfstore_debug.h"
#include "cfstore_test.h"
#include <configuration-store/configuration_store.h>
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#ifdef YOTTA_CFG_CFSTORE_UVISOR
#include "uvisor-lib/uvisor-lib.h"
#include "cfstore_uvisor.h"
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
using namespace utest::v1;
static control_t cfstore_find_test_00(const size_t call_count)
{
(void) call_count;
printf("Not implemented for ARM toolchain\n");
return CaseNext;
}
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(100, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
/* 1 2 3 4 5 6 7 */
/* 1234567890123456789012345678901234567890123456789012345678901234567890 */
Case("FIND_test_00", cfstore_find_test_00),
};
/* Declare your test specification with a custom setup handler */
Specification specification(greentea_setup, cases);
int main()
{
return !Harness::run(specification);
}
#else
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <inttypes.h>
#ifdef TARGET_LIKE_FRDM_K64F_GCC
#include <mbed-drivers/mbed.h>
#endif
#include "cfstore_config.h"
#include "cfstore_test.h"
#include "cfstore_debug.h"
//#include <flash-abstraction/Driver_Common.h>
#include <Driver_Common.h>
#include <configuration-store/configuration_store.h>
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#include "cfstore_utest.h"
#ifdef YOTTA_CFG_CFSTORE_UVISOR
#include "uvisor-lib/uvisor-lib.h"
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
using namespace utest::v1;
static char cfstore_find_utest_msg_g[CFSTORE_UTEST_MSG_BUF_SIZE];
/* Configure secure box. */
#ifdef YOTTA_CFG_CFSTORE_UVISOR
UVISOR_BOX_NAMESPACE("com.arm.mbed.cfstore.test.find.box1");
UVISOR_BOX_CONFIG(cfstore_find_box1, UVISOR_BOX_STACK_SIZE);
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
/* report whether built/configured for flash sync or async mode */
static control_t cfstore_find_test_00(const size_t call_count)
{
(void) call_count;
CFSTORE_LOG("INITIALIZING: caps.asynchronous_ops=%lu\n", cfstore_driver.GetCapabilities().asynchronous_ops);
return CaseNext;
}
/**
* @brief test to call cfstore_find() with a key_name string that exceeds
* the maximum length
* @return status code
* ARM_DRIVER_OK, the test passed successfully
* ret < ARM_DRIVER_OK, the test failed with the return code
* supplying more details
*/
static control_t cfstore_find_test_01(const size_t call_count)
{
(void) call_count;
/*todo: implement test */
CFSTORE_TEST_UTEST_MESSAGE(cfstore_find_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Warn: Not implemented\n", __func__);
CFSTORE_LOG("%s: WARN: requires implementation\n", __func__);
TEST_ASSERT_MESSAGE(true, cfstore_find_utest_msg_g);
return CaseNext;
}
/**
* @brief test to call cfstore_find() with key_name that in includes
* illegal characters
* - the character can be at the beginning of the key_name
* - the character can be at the end of the key_name
* - the character can be somewhere within the key_name string
*
* @return status code
* ARM_DRIVER_OK, the test passed successfully
* ret < ARM_DRIVER_OK, the test failed with the return code
* supplying more details
*/
static control_t cfstore_find_test_02(const size_t call_count)
{
/*todo: implement test
*
* specify the allowable characters in a set.
* e.g. "0123456789ABCDEFGHIJKLMNOPQRSTUVQXYZabcdefghijklmnopqrstuvwxyz.[]*"
* and use this set as the sell of allowable character codes.
* All other 0-255 values for character codes should not be found in the key_name string
* but the function should be tested for what happens in that case.
*
* Some code may be common here with other functions requiring a key_name e.g. cfstore_find(
*/
(void) call_count;
/*todo: implement test */
CFSTORE_TEST_UTEST_MESSAGE(cfstore_find_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Warn: Not implemented\n", __func__);
CFSTORE_LOG("%s: WARN: requires implementation\n", __func__);
TEST_ASSERT_MESSAGE(true, cfstore_find_utest_msg_g);
return CaseNext;
}
static control_t cfstore_find_test_03_end(const size_t call_count)
{
char* read_buf = NULL;
const uint8_t key_name_max_len = CFSTORE_KEY_NAME_MAX_LENGTH+1;
char key_name_buf[key_name_max_len];
int32_t ret = ARM_DRIVER_ERROR;
ARM_CFSTORE_SIZE len = 0;
ARM_CFSTORE_SIZE max_len = 0;
cfstore_kv_data_t* node;
cfstore_kv_data_t* client_node = cfstore_test_init_1_data;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
ARM_CFSTORE_KEYDESC kdesc;
ARM_CFSTORE_HANDLE_INIT(prev);
ARM_CFSTORE_HANDLE_INIT(next);
CFSTORE_DBGLOG("%s:entered\r\n", __func__);
(void) call_count;
memset(&kdesc, 0, sizeof(kdesc));
memset(key_name_buf, 0, CFSTORE_KEY_NAME_MAX_LENGTH+1);
/*scan for max length of value blob*/
node = client_node;
while(node->key_name != NULL)
{
len = strlen(node->value);
if(len > max_len){
max_len = len;
}
node++;
}
max_len++; /* space for a terminating null, if required */
read_buf = (char*) malloc(max_len);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_find_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Failed to allocated read buffer \r\n", __func__);
TEST_ASSERT_MESSAGE(read_buf != NULL, cfstore_find_utest_msg_g);
ret = cfstore_test_init_1();
CFSTORE_TEST_UTEST_MESSAGE(cfstore_find_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to initialise cfstore area with entries\r\n", __func__);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_find_utest_msg_g);
/* now find and read back the key values */
ret = ARM_DRIVER_ERROR;
node = client_node;
while(node->key_name != NULL)
{
CFSTORE_DBGLOG("%s:About to find node (key_name=\"%s\", value=\"%s\")\r\n", __func__, node->key_name, node->value);
ret = drv->Find(node->key_name, prev, next);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_find_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Failed to find node (key_name=\"%s\", value=\"%s\")\r\n", __func__, node->key_name, node->value);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_find_utest_msg_g);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_find_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Find failed to return valid key handle\r\n", __func__);
TEST_ASSERT_MESSAGE(next != NULL, cfstore_find_utest_msg_g);
ret = drv->GetValueLen(next, &len);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_find_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to write key (key_name=\"%s\", value=\"%s\")\r\n", __func__, node->key_name, node->value);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_find_utest_msg_g);
if(len > 0) {
ret = drv->Read(next, read_buf, &len);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_find_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to read value (key_name=\"%s\", value=\"%s\")\r\n", __func__, node->key_name, node->value);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_find_utest_msg_g);
/* check read data is as expected */
CFSTORE_TEST_UTEST_MESSAGE(cfstore_find_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Read value data (%s) != KV value data (key_name=\"%s\", value=\"%s\")\r\n", __func__, read_buf, node->key_name, node->value);
TEST_ASSERT_MESSAGE(strncmp(read_buf, node->value, strlen(node->value)) == 0, cfstore_find_utest_msg_g);
}
read_buf[len] = '\0';
printf("Successfully found KV and read value data (key_name=\"%s\", value=\"%s\")\r\n", node->key_name, read_buf);
memset(read_buf, 0, len);
drv->Close(next);
node++;
}
ret = drv->Uninitialize();
CFSTORE_TEST_UTEST_MESSAGE(cfstore_find_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Uninitialize() call failed.\n", __func__);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_find_utest_msg_g);
return CaseNext;
}
static cfstore_kv_data_t cfstore_find_test_04_kv_data[] = {
{ "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", "abcdefghjklmnopqrstuvwxyzabcdefghjklmnopqrstuvwxyzabcdefghjklmnopqrstuvwxyzabcdefghjklmnopqrstuvwxyzabcdefghjklmnopqrstuvwxyzabcdefghjklmnopqrstuvwxyzabcdefghjklmnopqrstuvwxyzabcdefghjklmnopqrstuvwxyzabcdefghjklmnopqrstuvwxyz"},
{ NULL, NULL},
};
/**
* @brief TODO: write test that uses cfstore_find_test_04_kv_data to grow {key, value}
* from 1 char to 221 chars long.
*
* @return status code
* ARM_DRIVER_OK, the test passed successfully
* ret < ARM_DRIVER_OK, the test failed with the return code
* supplying more details
*/
static control_t cfstore_find_test_04(const size_t call_count)
{
/*todo: implement test
*
* */
(void) cfstore_find_test_04_kv_data;
(void) call_count;
/*todo: implement test */
CFSTORE_TEST_UTEST_MESSAGE(cfstore_find_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Warn: Not implemented\n", __func__);
CFSTORE_LOG("%s: WARN: requires implementation\n", __func__);
TEST_ASSERT_MESSAGE(true, cfstore_find_utest_msg_g);
return CaseNext;
}
/**
* @brief function to test whether a key name is valid, can be added to the
* cfstore and found by a wildcard string
*
* @param key_name
* name of the key to create in the store
* @param match
* string to use to try and find key_name in the cfstore
* @param should_find
* if true, then 'match' should find 'key_name' in the store
* if false, then 'match' should not find 'key_name' in the store
*
* @return status code
* ARM_DRIVER_OK, the test passed successfully
* ret < ARM_DRIVER_OK, the test failed with the return code
* supplying more details
*/
bool cfstore_find_key_name_validate(const char *key_name, const char *match, bool should_find)
{
bool bret = true;
bool btest_status = false;
char* test_data = (char*) "test_data";
int32_t ret = ARM_DRIVER_ERROR;
ARM_CFSTORE_SIZE len = 0;
ARM_CFSTORE_KEYDESC kdesc;
CFSTORE_FENTRYLOG("%s:entered\r\n", __func__);
memset(&kdesc, 0, sizeof(kdesc));
/* create */
kdesc.drl = ARM_RETENTION_WHILE_DEVICE_ACTIVE;
len = strlen(test_data);
ret = cfstore_test_create((const char*) key_name, test_data, &len, &kdesc);
if(ret < ARM_DRIVER_OK){
CFSTORE_ERRLOG("%s:Error: failed to create kv (key_name=%s.\r\n", "cfstore_find_test_05_ex", key_name);
return ret;
}
ret = cfstore_test_kv_is_found(match, &bret);
if(ret < ARM_DRIVER_OK && ret != ARM_CFSTORE_DRIVER_ERROR_KEY_NOT_FOUND){
CFSTORE_ERRLOG("%s:Error: cfstore_test_kv_is_found() failed.\r\n", "cfstore_find_test_05_ex");
return ret;
}
/* dont not use any functions that require finding the created item as they may not work,
* depending on the construction of the test key_name & match strings */
if(should_find == bret)
{
CFSTORE_DBGLOG("%s:Success: Find() behaved as expected.\r\n", "cfstore_find_test_05_ex");
btest_status = true;
}
else
{
CFSTORE_ERRLOG("cfstore_find_test_05_ex: Failed match on %s vs. %s\n", key_name, match);
}
/*delete using the actual name */
ret = cfstore_test_delete((const char*) key_name);
if(ret < ARM_DRIVER_OK){
CFSTORE_ERRLOG("%s:Error: failed to delete kv (key_name=%s)(ret=%d).\r\n", "cfstore_find_test_05_ex", key_name, (int)ret);
}
return btest_status;
}
typedef struct cfstore_find_key_name_validate_t {
const char* key_name;
const char* match;
uint32_t f_allowed : 1;
} cfstore_find_key_name_validate_t;
cfstore_find_key_name_validate_t cfstore_find_test_05_data[] = {
{ "yotta.hello-world.animal{wobbly-dog}{foot}backLeft", "yotta.hello-world.animal{*}{foot}backLeft", true},
{ "yotta.hello-world.animal{wobbly-dog}{foot}backLeft", "yotta.hello-world.animal{wobbly-dog}{*}backLeft", true},
{ "yotta.hello-world.animal{wobbly-dog}{foot}backLeft", "yotta.hello-world.animal{wobbly-dog}{*}*", true},
{ "yotta.hello-world.animal{1}{foot}backLeft", "yotta.hello-world.animal{?}{foot}backLeft", false},
{ "xyz", "xyz", true},
{ "xyzijkXYZ", "XYZ", false},
{ "xyzijkXYZ", "*XYZ", true},
{ "xyzijkXYZ", "xyz*XYZ", true},
{ "xyzijkXYZ", "*yz*XYZ", true},
{ "xyzijkXYZ", "*ijk*", true},
{ NULL, NULL, false},
};
/**
* @brief test whether a key name in the above table are valid, can be added to the
* cfstore and found by a wildcard string
*
* @return status code
* ARM_DRIVER_OK, the test passed successfully
* ret < ARM_DRIVER_OK, the test failed with the return code
* supplying more details
*/
static control_t cfstore_find_test_05_end(const size_t call_count)
{
bool ret = false;
int32_t ret32 = ARM_DRIVER_ERROR;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
cfstore_find_key_name_validate_t* node = cfstore_find_test_05_data;
(void) call_count;
while(node->key_name != NULL)
{
ret = cfstore_find_key_name_validate(node->key_name, node->match, node->f_allowed);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_find_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: test failed (ret=%d)\n", __func__, (int) ret);
TEST_ASSERT_MESSAGE(ret == true, cfstore_find_utest_msg_g);
node++;
}
ret32 = drv->Uninitialize();
CFSTORE_TEST_UTEST_MESSAGE(cfstore_find_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Uninitialize() call failed.\n", __func__);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_find_utest_msg_g);
return CaseNext;
}
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(400, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
/* 1 2 3 4 5 6 7 */
/* 1234567890123456789012345678901234567890123456789012345678901234567890 */
Case("FIND_test_00", cfstore_find_test_00),
Case("FIND_test_01", cfstore_find_test_01),
Case("FIND_test_02", cfstore_find_test_02),
Case("FIND_test_03_start", cfstore_utest_default_start),
Case("FIND_test_03_end", cfstore_find_test_03_end),
Case("FIND_test_04", cfstore_find_test_04),
Case("FIND_test_05_start", cfstore_utest_default_start),
Case("FIND_test_05_end", cfstore_find_test_05_end),
};
/* Declare your test specification with a custom setup handler */
Specification specification(greentea_setup, cases);
#if defined CFSTORE_CONFIG_MBED_OS_VERSION && CFSTORE_CONFIG_MBED_OS_VERSION == 3
/* mbedosV3*/
void app_start(int argc __unused, char** argv __unused)
{
/* Run the test specification */
Harness::run(specification);
}
#endif /* CFSTORE_CONFIG_MBED_OS_VERSION == 3 */
#if defined CFSTORE_CONFIG_MBED_OS_VERSION && CFSTORE_CONFIG_MBED_OS_VERSION == 4
/* mbedosV3++*/
int main()
{
return !Harness::run(specification);
}
#endif /* CFSTORE_CONFIG_MBED_OS_VERSION == 4 */
#endif // __MBED__ && ! defined TOOLCHAIN_GCC_ARM

View File

@ -0,0 +1,310 @@
/** @file find.cpp
*
* mbed Microcontroller Library
* Copyright (c) 2006-2016 ARM Limited
*
* 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.
*
* Test cases to find KVs in the CFSTORE using the drv->Find() interface.
*/
#if defined __MBED__ && ! defined TOOLCHAIN_GCC_ARM
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#ifdef TARGET_LIKE_FRDM_K64F_GCC
#include <mbed-drivers/mbed.h>
#endif
#include "cfstore_config.h"
#include <Driver_Common.h>
#include "cfstore_debug.h"
#include "cfstore_test.h"
#include <configuration-store/configuration_store.h>
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#ifdef YOTTA_CFG_CFSTORE_UVISOR
#include "uvisor-lib/uvisor-lib.h"
#include "cfstore_uvisor.h"
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
using namespace utest::v1;
static control_t cfstore_find2_test_00(const size_t call_count)
{
(void) call_count;
printf("Not implemented for ARM toolchain\n");
return CaseNext;
}
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(100, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
/* 1 2 3 4 5 6 7 */
/* 1234567890123456789012345678901234567890123456789012345678901234567890 */
Case("FIND2_test_00", cfstore_find2_test_00),
};
/* Declare your test specification with a custom setup handler */
Specification specification(greentea_setup, cases);
int main()
{
return !Harness::run(specification);
}
#else
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <inttypes.h>
#ifdef TARGET_LIKE_FRDM_K64F_GCC
#include <mbed-drivers/mbed.h>
#endif
#include "cfstore_config.h"
#include "cfstore_test.h"
#include "cfstore_debug.h"
//#include <flash-abstraction/Driver_Common.h>
#include <Driver_Common.h>
#include <configuration-store/configuration_store.h>
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#ifdef YOTTA_CFG_CFSTORE_UVISOR
#include "uvisor-lib/uvisor-lib.h"
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
using namespace utest::v1;
static char cfstore_find2_utest_msg_g[CFSTORE_UTEST_MSG_BUF_SIZE];
/* Configure secure box. */
#ifdef YOTTA_CFG_CFSTORE_UVISOR
UVISOR_BOX_NAMESPACE("com.arm.mbed.cfstore.test.find2.box1");
UVISOR_BOX_CONFIG(cfstore_find2_box1, UVISOR_BOX_STACK_SIZE);
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
extern ARM_CFSTORE_DRIVER cfstore_driver;
#ifdef TARGET_LIKE_FRDM_K64F_GCC
#define CFSTORE_FIND_MBED_HOSTTEST_TIMEOUT 60
#endif
void cfstore_find2_callback(int32_t status, ARM_CFSTORE_OPCODE cmd_code, void *client_context, ARM_CFSTORE_HANDLE handle)
{
(void) status;
(void) cmd_code;
(void) client_context;
(void) handle;
return;
}
/* report whether built/configured for flash sync or async mode */
static control_t cfstore_find2_test_00(const size_t call_count)
{
(void) call_count;
CFSTORE_LOG("INITIALIZING: caps.asynchronous_ops=%lu\n", cfstore_driver.GetCapabilities().asynchronous_ops);
return CaseNext;
}
static control_t cfstore_find2_test_01(const size_t call_count)
{
char keyBuffer[128] = "com.arm.mbed.manifest-manager.root.AQAAAAAAAAA-.manifest";
int32_t rc;
ARM_CFSTORE_HANDLE_INIT(hkey);
ARM_CFSTORE_HANDLE_INIT(prev);
// Initialize the config store
(void) call_count;
cfstore_driver.Initialize(cfstore_find2_callback, NULL);
cfstore_driver.PowerControl(ARM_POWER_FULL);
// Find the target key
rc = cfstore_driver.Find(keyBuffer, prev, hkey);
// If the target key was not found
if (rc == ARM_CFSTORE_DRIVER_ERROR_KEY_NOT_FOUND) {
ARM_CFSTORE_KEYDESC kdesc = {
.acl = {
.perm_owner_read = 1,
.perm_owner_write = 1,
.perm_owner_execute = 0,
.perm_other_read = 1,
.perm_other_write = 0,
.perm_other_execute = 0,
/* added initialisers */
.reserved = 0
}, .drl = ARM_RETENTION_WHILE_DEVICE_ACTIVE,
.security = {
.acls = 1,
.rollback_protection = 0,
.tamper_proof = 0,
.internal_flash = 0,
/* added initialisers */
.reserved1 = 0,
.software_attacks = 0,
.board_level_attacks = 0,
.chip_level_attacks = 0,
.side_channel_attacks = 0,
.reserved2 = 0
},
.flags = {
.continuous = 0,
.lazy_flush = 1,
.flush_on_close = 1,
.read = 0,
.write = 1,
.execute = 0,
.storage_detect = 1,
/* added initialisers */
.reserved = 0
}
};
// Create the target key
rc = cfstore_driver.Create(keyBuffer, 191, &kdesc, hkey);
}
return CaseNext;
}
/* fixed version of brendans code */
#define CFSTORE_FIND2_TEST_02_VALUE_SIZE 191
static control_t cfstore_find2_test_02(const size_t call_count)
{
char keyBuffer[128] = "com.arm.mbed.manifest-manager.root.AQAAAAAAAAA-.manifest";
int32_t rc;
ARM_CFSTORE_HANDLE_INIT(hkey);
ARM_CFSTORE_HANDLE_INIT(prev);
ARM_CFSTORE_SIZE length;
char value[CFSTORE_FIND2_TEST_02_VALUE_SIZE];
// Initialize the config store
(void) call_count;
cfstore_driver.Initialize(NULL, NULL); /* non-null client_callback not supported for MBED_V_0_1_x */
cfstore_driver.PowerControl(ARM_POWER_FULL);
memset(value, 0, 191);
// Find the target key
rc = cfstore_driver.Find(keyBuffer, prev, hkey);
// If the target key was not found
if (rc == ARM_CFSTORE_DRIVER_ERROR_KEY_NOT_FOUND) {
ARM_CFSTORE_KEYDESC kdesc = {
.acl = {
.perm_owner_read = 1,
.perm_owner_write = 1,
.perm_owner_execute = 0,
.perm_other_read = 1,
.perm_other_write = 0,
.perm_other_execute = 0,
.reserved = 0
}, .drl = ARM_RETENTION_WHILE_DEVICE_ACTIVE, /* DATA_RETENTION_NVM not supported for MBED_V_0_1_x */
.security = {
.acls = 0, /* protection against internal software attacks using ACLs not supported for MBED_V_0_1_x */
.rollback_protection = 0,
.tamper_proof = 0,
.internal_flash = 0,
.reserved1 = 0,
.software_attacks = 0,
.board_level_attacks = 0,
.chip_level_attacks = 0,
.side_channel_attacks = 0,
.reserved2 = 0
},
.flags = {
.continuous = 0,
.lazy_flush = 0, /* lazy flush not supported for MBED_V_0_1_x */
.flush_on_close = 0, /* flush on close not supported for MBED_V_0_1_x */
.read = 0,
.write = 1,
.execute = 0,
.storage_detect = 0, /* storage detect supported for MBED_V_0_1_x */
/* added initialisers */
.reserved = 0
}
};
// Create the target key
rc = cfstore_driver.Create(keyBuffer, 191, &kdesc, hkey);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_find2_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%sError: failed to create key\n", __func__);
TEST_ASSERT_MESSAGE(rc >= ARM_DRIVER_OK, cfstore_find2_utest_msg_g);
strncpy(value, "MyValueData", CFSTORE_FIND2_TEST_02_VALUE_SIZE);
length = strlen(value);
rc = cfstore_driver.Write(hkey, value, &length);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_find2_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%sError: failed to write key\n", __func__);
TEST_ASSERT_MESSAGE(rc >= ARM_DRIVER_OK, cfstore_find2_utest_msg_g);
printf("Success!\n");
}
return CaseNext;
}
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(400, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
/* 1 2 3 4 5 6 7 */
/* 1234567890123456789012345678901234567890123456789012345678901234567890 */
Case("FIND2_test_00", cfstore_find2_test_00),
Case("FIND2_test_01", cfstore_find2_test_01),
Case("FIND2_test_02", cfstore_find2_test_02),
};
/* Declare your test specification with a custom setup handler */
Specification specification(greentea_setup, cases);
#if defined CFSTORE_CONFIG_MBED_OS_VERSION && CFSTORE_CONFIG_MBED_OS_VERSION == 3
/* mbedosV3*/
void app_start(int argc __unused, char** argv __unused)
{
/* Run the test specification */
Harness::run(specification);
}
#endif /* CFSTORE_CONFIG_MBED_OS_VERSION == 3 */
#if defined CFSTORE_CONFIG_MBED_OS_VERSION && CFSTORE_CONFIG_MBED_OS_VERSION == 4
/* mbedosV3++*/
int main()
{
return !Harness::run(specification);
}
#endif /* CFSTORE_CONFIG_MBED_OS_VERSION == 4 */
#endif // __MBED__ && ! defined TOOLCHAIN_GCC_ARM

View File

@ -0,0 +1,752 @@
/* @file flush.cpp
*
* mbed Microcontroller Library
* Copyright (c) 2006-2016 ARM Limited
*
* 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.
*
* Test cases to flush KVs in the CFSTORE using the drv->Flush() interface.
*/
#if defined __MBED__ && ! defined TOOLCHAIN_GCC_ARM
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#ifdef TARGET_LIKE_FRDM_K64F_GCC
#include <mbed-drivers/mbed.h>
#endif
#include "cfstore_config.h"
#include <Driver_Common.h>
#include "cfstore_debug.h"
#include "cfstore_test.h"
#include <configuration-store/configuration_store.h>
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#ifdef YOTTA_CFG_CFSTORE_UVISOR
#include "uvisor-lib/uvisor-lib.h"
#include "cfstore_uvisor.h"
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
using namespace utest::v1;
static control_t cfstore_flash_test_00(const size_t call_count)
{
(void) call_count;
printf("Not implemented for ARM toolchain\n");
return CaseNext;
}
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(100, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
/* 1 2 3 4 5 6 7 */
/* 1234567890123456789012345678901234567890123456789012345678901234567890 */
Case("FLASH_test_00", cfstore_flash_test_00),
};
/* Declare your test specification with a custom setup handler */
Specification specification(greentea_setup, cases);
int main()
{
return !Harness::run(specification);
}
#else
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#if defined CFSTORE_CONFIG_BACKEND_FLASH_ENABLED && CFSTORE_CONFIG_BACKEND_FLASH_ENABLED == 1
#include <flash-journal-strategy-sequential/flash_journal_strategy_sequential.h>
#include <flash-journal/flash_journal.h>
#endif /* CFSTORE_CONFIG_BACKEND_FLASH_ENABLED */
#include "cfstore_config.h"
#include "cfstore_test.h"
#include "cfstore_debug.h"
//#include <flash-abstraction/Driver_Common.h>
#include <Driver_Common.h>
#include <configuration-store/configuration_store.h>
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#ifdef YOTTA_CFG_CFSTORE_UVISOR
#include "uvisor-lib/uvisor-lib.h"
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
using namespace utest::v1;
/* Configure secure box. */
#ifdef YOTTA_CFG_CFSTORE_UVISOR
UVISOR_BOX_NAMESPACE("com.arm.mbed.cfstore.test.flash.box1");
UVISOR_BOX_CONFIG(cfstore_flash_box1, UVISOR_BOX_STACK_SIZE);
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
/* shared code common to both sync and async test cases */
/*
* Defines
*
*/
#define CFSTORE_FREE free
#define CFSTORE_MALLOC malloc
#define CFSTORE_REALLOC realloc
#define CFSTORE_FLASH_STACK_BUF_SIZE 64
#define CFSTORE_FLASH_K64F_CURRENT_PROGRAM_UNIT_SIZE 8
#define CFSTORE_TEST_DATA_KEYNAME "com.arm.mbed.configurationstore.test.flush.cfstoreflushtest02"
#define CFSTORE_TEST_DATA_KEYNAME_SHORT "com.arm"
#define CFSTORE_TEST_DATA_VALUE_INIT "\1"
#define CFSTORE_TEST_DATA_KEYNAME_SIZE (sizeof(CFSTORE_TEST_DATA_KEYNAME) - 1)
#define CFSTORE_TEST_DATA_VALUE_SIZE (sizeof(CFSTORE_TEST_DATA_VALUE_INIT) - 1)
#define CFSTORE_FLASH_UTEST_MSG_BUF_SIZE 256
#define CFSTORE_FLASH_MTD_ASYNC_OPS_ON 1
#define CFSTORE_FLASH_MTD_ASYNC_OPS_OFF 0
#define CFSTORE_FLASH_CASE_TIMEOUT_MS 5000
/*
* Globals
*/
#if defined CFSTORE_CONFIG_BACKEND_FLASH_ENABLED && CFSTORE_CONFIG_BACKEND_FLASH_ENABLED == 1
char cfstore_flash_utest_msg_g[CFSTORE_FLASH_UTEST_MSG_BUF_SIZE];
uint16_t cfstore_flash_mtd_async_ops_g = 0;
extern ARM_DRIVER_STORAGE ARM_Driver_Storage_(0);
/* KV data for test_01 */
static cfstore_kv_data_t cfstore_flush_test_01_kv_data[] = {
{ CFSTORE_TEST_DATA_KEYNAME, CFSTORE_TEST_DATA_VALUE_INIT},
{ NULL, NULL},
};
/* @brief key value header structure defining key_name length, value length
* @note
* 8 bytes long */
typedef struct cfstore_area_header_t
{
uint32_t vlength;
uint8_t klength;
uint8_t perm_owner_read : 1;
uint8_t perm_owner_write : 1;
uint8_t perm_owner_execute : 1;
uint8_t perm_other_read : 1;
uint8_t perm_other_write : 1;
uint8_t perm_other_execute : 1;
uint8_t reserved : 2;
uint8_t refcount;
struct flags_t {
uint8_t deleting : 1;
uint8_t reserved : 7;
} flags ;
} cfstore_area_header_t;
/* @brief data structure for managing test data */
typedef struct cfstore_flash_data_blob_t {
cfstore_area_header_t hdr;
uint8_t data[CFSTORE_TEST_DATA_KEYNAME_SIZE + CFSTORE_TEST_DATA_VALUE_SIZE]; /* 61 bytes for key_name, 1 byte for value */
} cfstore_flash_data_blob_t;
/*
* Defines
*
* CFSTORE_FLASH_AREA_SIZE_MIN
* valid sizes of areas should always be greater than the size of the header, and therefore
* greater than this value, which is defined as smaller than the header size
*/
#define CFSTORE_FLASH_AREA_SIZE_MIN (sizeof(cfstore_area_header_t) - 1)
/*
* Shared implementation between sync and async tests
*/
/* print key name string from area where key_name is not null terminated*/
static void cfstore_dump_key_name(uint8_t* keyname, uint8_t len, const char* tag)
{
char blob_data[CFSTORE_KEY_NAME_MAX_LENGTH];
(void) tag;
assert(keyname != NULL);
assert(tag != NULL);
assert(len > 0);
memcpy(blob_data, keyname, len);
blob_data[len] = '\0';
CFSTORE_DBGLOG("%s:keyname=%s\r\n", tag, blob_data);
}
/* @brief test fsm states and events */
typedef enum cfstore_flash_fsm_state_t {
cfstore_flash_fsm_state_initializing = 0,
cfstore_flash_fsm_state_reading,
cfstore_flash_fsm_state_writing,
cfstore_flash_fsm_state_committing,
cfstore_flash_fsm_state_max
} cfstore_flash_fsm_state_t;
/* @brief test fsm events */
typedef enum cfstore_flash_fsm_event_t {
cfstore_flash_fsm_event_init_done = 0,
cfstore_flash_fsm_event_read_done,
cfstore_flash_fsm_event_write_done,
cfstore_flash_fsm_event_commit_done,
cfstore_flash_fsm_event_max,
} cfstore_flash_fsm_event_t;
typedef void (*cfstore_flash_fsm_handler)(void* ctx);
typedef struct cfstore_fsm_t
{
cfstore_flash_fsm_state_t state;
cfstore_flash_fsm_event_t event;
} cfstore_fsm_t;
typedef struct cfstore_flash_ctx_t
{
uint8_t* area_0_head;
uint8_t* area_0_tail;
FlashJournal_t jrnl;
uint64_t expected_blob_size;
cfstore_fsm_t fsm;
int32_t status;
FlashJournal_OpCode_t cmd_code;
uint64_t expected_read_size;
} cfstore_flash_ctx_t;
/*
* Globals
*/
static cfstore_flash_ctx_t cfstore_flash_ctx_g;
static const char* cfstore_flash_opcode_str[] =
{
"FLASH_JOURNAL_OPCODE_INITIALIZE",
"FLASH_JOURNAL_OPCODE_GET_INFO",
"FLASH_JOURNAL_OPCODE_READ_BLOB",
"FLASH_JOURNAL_OPCODE_LOG_BLOB",
"FLASH_JOURNAL_OPCODE_COMMIT",
"FLASH_JOURNAL_OPCODE_RESET",
};
#ifdef CFSTORE_DEBUG
static const char* cfstore_flash_state_str[] =
{
"initializing",
"reading",
"writing",
"committing",
"unknown"
};
static const char* cfstore_flash_event_str[] =
{
"init_done",
"read_done",
"write_done",
"commit_done",
"unknown"
};
#endif /* CFSTORE_DEBUG */
/*
* Forward decl
*/
static void cfstore_fsm_state_handle_event(cfstore_fsm_t* fsm, cfstore_flash_fsm_event_t event, void* context);
static void cfstore_fsm_state_set(cfstore_fsm_t* fsm, cfstore_flash_fsm_state_t new_state, void* ctx);
/*
* context related methods
*/
/* @brief get a pointer to the global context data structure */
static cfstore_flash_ctx_t* cfstore_flash_ctx_get(void)
{
return &cfstore_flash_ctx_g;
}
/* @brief flash journal asynchronous callback handler */
void cfstore_flash_test_01_callback(int32_t status, FlashJournal_OpCode_t cmd_code)
{
cfstore_flash_ctx_t* ctx = cfstore_flash_ctx_get();
CFSTORE_FENTRYLOG("%s:entered: status=%d, cmd_code=%d (%s)\r\n", __func__, (int) status, (int) cmd_code, cfstore_flash_opcode_str[cmd_code]);
switch(cmd_code)
{
case FLASH_JOURNAL_OPCODE_INITIALIZE:
ctx->fsm.event = cfstore_flash_fsm_event_init_done;
break;
case FLASH_JOURNAL_OPCODE_READ_BLOB:
ctx->fsm.event = cfstore_flash_fsm_event_read_done;
break;
case FLASH_JOURNAL_OPCODE_LOG_BLOB:
ctx->fsm.event = cfstore_flash_fsm_event_write_done;
break;
case FLASH_JOURNAL_OPCODE_COMMIT:
ctx->fsm.event = cfstore_flash_fsm_event_commit_done;
break;
case FLASH_JOURNAL_OPCODE_GET_INFO:
case FLASH_JOURNAL_OPCODE_RESET:
default:
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: received asynchronous notification for opcode=%d (%s) when api call should have been synchronous", __func__, cmd_code, cmd_code <= FLASH_JOURNAL_OPCODE_RESET ? cfstore_flash_opcode_str[cmd_code] : "unknown");
TEST_ASSERT_MESSAGE(false, cfstore_flash_utest_msg_g)
return;
}
ctx->status = status;
ctx->cmd_code = cmd_code;
cfstore_fsm_state_handle_event(&ctx->fsm, ctx->fsm.event, (void*) ctx);
return;
}
/* @brief fsm handler called on entry to initializing state */
static void cfstore_flash_fsm_init_on_entry(void* context)
{
/* round up cfstore_flash_data_blob_t to nearest k64f program unit size */
const ARM_DRIVER_STORAGE *drv = &ARM_Driver_Storage_(0);
FlashJournal_Info_t info;
FlashJournal_Status_t status = JOURNAL_STATUS_ERROR;
cfstore_flash_ctx_t* ctx = (cfstore_flash_ctx_t*) context;
/* check that the mtd is in synchronous mode */
CFSTORE_FENTRYLOG("%s:entered: \r\n", __func__);
memset(&info, 0, sizeof(info));
/* FlashJournal_initialize() is potentially asynchronous */
status = (FlashJournal_Status_t) FlashJournal_initialize(&ctx->jrnl, drv, &FLASH_JOURNAL_STRATEGY_SEQUENTIAL, cfstore_flash_test_01_callback);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: failed to initialize flash journaling layer (status=%d)\r\n", __func__, status);
TEST_ASSERT_MESSAGE(status >= JOURNAL_STATUS_OK, cfstore_flash_utest_msg_g);
/* if status > 0, expect async callback, otherwise initialisation has been completed */
if(status > 0) {
cfstore_flash_test_01_callback(status, FLASH_JOURNAL_OPCODE_INITIALIZE);
}
return;
}
/* brief callback handler when in state initializing */
static void cfstore_flash_fsm_initializing(void* context)
{
cfstore_flash_ctx_t* ctx = (cfstore_flash_ctx_t*) context;
CFSTORE_FENTRYLOG("%s:entered\r\n", __func__);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: entered handler(%s) but not in initializing state (fsm->state=%d)\r\n", __func__, __func__, (int) ctx->fsm.state);
TEST_ASSERT_MESSAGE(ctx->fsm.state == cfstore_flash_fsm_state_initializing, cfstore_flash_utest_msg_g);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: cmd_code code (%d) is not as expected (%d)\r\n", __func__, ctx->cmd_code, FLASH_JOURNAL_OPCODE_INITIALIZE);
TEST_ASSERT_MESSAGE(ctx->cmd_code == FLASH_JOURNAL_OPCODE_INITIALIZE, cfstore_flash_utest_msg_g);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: status=%" PRId32 "\r\n", __func__, ctx->status);
TEST_ASSERT_MESSAGE(ctx->status >= JOURNAL_STATUS_OK, cfstore_flash_utest_msg_g);
/* only change state if status > 0*/
if(ctx->status > 0){
cfstore_fsm_state_set(&ctx->fsm, cfstore_flash_fsm_state_reading, ctx);
}
}
/* static void cfstore_flash_fsm_init_on_exit(void* context){ (void) context;} */
/* brief callback handler called when entering the reading state
* note
* flash journal has initialised successfully. now
*/
static void cfstore_flash_fsm_read_on_entry(void* context)
{
uint8_t* ptr = NULL;
int32_t ret = 0;
FlashJournal_Info_t info;
FlashJournal_Status_t status = JOURNAL_STATUS_ERROR;
cfstore_flash_ctx_t* ctx = (cfstore_flash_ctx_t*) context;
CFSTORE_FENTRYLOG("%s:entered\r\n", __func__);
CFSTORE_ASSERT(ctx != NULL);
/* drv->GetInfo() is synchronous */
status = FlashJournal_getInfo(&ctx->jrnl, &info);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: failed get journal info (status=%d)\r\n", __func__, (int) status);
TEST_ASSERT_MESSAGE(status == JOURNAL_STATUS_OK, cfstore_flash_utest_msg_g);
CFSTORE_DBGLOG("%s:FlashJournal_getInfo() done. info.sizeofJournaledBlob=%lu\r\n", __func__, (long unsigned int) info.sizeofJournaledBlob);
if(info.sizeofJournaledBlob > 0)
{
/* setup the expected blob size for writing
* This is a multiple of program unit so the write doesnt fail due to unaligned log */
ctx->expected_blob_size = sizeof(cfstore_flash_data_blob_t);
if(ctx->expected_blob_size % CFSTORE_FLASH_K64F_CURRENT_PROGRAM_UNIT_SIZE > 0){
ctx->expected_blob_size += (CFSTORE_FLASH_K64F_CURRENT_PROGRAM_UNIT_SIZE - (sizeof(cfstore_flash_data_blob_t) % CFSTORE_FLASH_K64F_CURRENT_PROGRAM_UNIT_SIZE));
}
/* test that a blob size is the expected size for flash data that has been written before */
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: info.sizeofJournaledBlob does not match expect size. expected_blob_size (%lu) != info.sizeofJournaledBlob (%lu)\r\n", __func__, (unsigned long int) ctx->expected_blob_size, (unsigned long int) info.sizeofJournaledBlob);
TEST_ASSERT_EQUAL_INT64_MESSAGE(ctx->expected_blob_size, info.sizeofJournaledBlob, cfstore_flash_utest_msg_g);
/* grow the area by the size of the stored blob */
ptr = (uint8_t*) CFSTORE_REALLOC((void*) ctx->area_0_head, ctx->expected_blob_size);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:realloc failed flash blob (size=%d)\r\n", __func__, (int)info.sizeofJournaledBlob);
TEST_ASSERT_MESSAGE(ptr != NULL, cfstore_flash_utest_msg_g);
memset(ptr, 0, ctx->expected_blob_size);
if(ptr != ctx->area_0_head){
CFSTORE_DBGLOG("%s:cfstore_ctx_g.area_0_head pointer changed (cfstore_ctx_g.area_0_head=%p, ptr=%p)\r\n", __func__, ctx->area_0_head, ptr);
ctx->area_0_head = ptr;
ctx->area_0_tail = ctx->area_0_head + info.sizeofJournaledBlob;
}
ret = FlashJournal_read(&ctx->jrnl, (void*) ctx->area_0_head, info.sizeofJournaledBlob);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: unable to read flash journal (ret=%" PRId32 ". info.sizeofJournaledBlob=%d)\r\n", __func__, ret, (int) info.sizeofJournaledBlob);
TEST_ASSERT_MESSAGE(ret >= JOURNAL_STATUS_OK, cfstore_flash_utest_msg_g);
if(ret > 0){
/* read has completed synchronously*/
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: unable to read all data from flash journal (expected size=%lu, read=%" PRId32 ")\r\n", __func__, (unsigned long int)info.sizeofJournaledBlob, ret);
TEST_ASSERT_EQUAL_INT32_MESSAGE( (int32_t) info.sizeofJournaledBlob, ret, cfstore_flash_utest_msg_g);
cfstore_flash_test_01_callback(ret, FLASH_JOURNAL_OPCODE_READ_BLOB);
}
} else {
/* there is no blob, move to next state. need a +ve status value to indicate async completion
* to the fsm reading state handler. use CFSTORE_FLASH_AREA_SIZE_MIN for this value */
ctx->expected_blob_size = CFSTORE_FLASH_AREA_SIZE_MIN;
status = (FlashJournal_Status_t) CFSTORE_FLASH_AREA_SIZE_MIN;
cfstore_flash_test_01_callback(status, FLASH_JOURNAL_OPCODE_READ_BLOB);
}
return;
}
/* @brief fsm handler when in reading state */
void cfstore_flash_fsm_reading(void* context)
{
int32_t ret = 0;
cfstore_flash_ctx_t* ctx = (cfstore_flash_ctx_t*) context;
cfstore_flash_data_blob_t *blob = NULL;
CFSTORE_FENTRYLOG("%s:entered\r\n", __func__);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: entered handler(%s) but not in reading state (fsm->state=%d)\r\n", __func__, __func__, (int) ctx->fsm.state);
TEST_ASSERT_MESSAGE(ctx->fsm.state == cfstore_flash_fsm_state_reading, cfstore_flash_utest_msg_g);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: cmd_code code (%d) is not as expected (%d)\r\n", __func__, ctx->cmd_code, FLASH_JOURNAL_OPCODE_READ_BLOB);
TEST_ASSERT_MESSAGE(ctx->cmd_code == FLASH_JOURNAL_OPCODE_READ_BLOB, cfstore_flash_utest_msg_g);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: status=%" PRId32 "\r\n", __func__, ctx->status);
TEST_ASSERT_MESSAGE(ctx->status >= JOURNAL_STATUS_OK, cfstore_flash_utest_msg_g);
if(ctx->status > 0)
{
if(ctx->status > (int32_t) CFSTORE_FLASH_AREA_SIZE_MIN)
{
/* check the correct amount of data was read, which is the status code */
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: unable to read all data from flash journal (expected size=%lu, read=%" PRId32 ")\r\n", __func__, (unsigned long int) ctx->expected_blob_size, ctx->status);
/* ctx->status contains the status of the read that was completed */
TEST_ASSERT_EQUAL_INT64_MESSAGE(ctx->expected_blob_size, (int32_t) ctx->status, cfstore_flash_utest_msg_g);
if(ctx->area_0_head != NULL)
{
/* check the key_name read from flash is correct */
blob = (cfstore_flash_data_blob_t*) ctx->area_0_head;
cfstore_dump_key_name(blob->data, CFSTORE_TEST_DATA_KEYNAME_SIZE, __func__);
ret = memcmp(blob->data, cfstore_flush_test_01_kv_data[0].key_name, strlen(cfstore_flush_test_01_kv_data[0].key_name));
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: incorrect key_name read from flash (expected 0 from memcpy(keyname, flash_data), actual was non-zero)", __func__);
TEST_ASSERT_EQUAL_INT_MESSAGE(0, ret, cfstore_flash_utest_msg_g);
}
}
cfstore_fsm_state_set(&ctx->fsm, cfstore_flash_fsm_state_writing, ctx);
}
}
/* void cfstore_flash_fsm_read_on_exit(void* context){ (void) context;} */
/* @brief on entry to writing state, update value */
void cfstore_flash_fsm_write_on_entry(void* context)
{
uint8_t value = 0;
int32_t ret = 0;
cfstore_flash_ctx_t* ctx = (cfstore_flash_ctx_t*) context;
cfstore_flash_data_blob_t *blob = NULL;
CFSTORE_FENTRYLOG("%s:entered:\r\n", __func__);
/* allocate memory for data if not already done so */
if(ctx->area_0_head == NULL)
{
/* This is a multiple of program unit so the write doesnt fail due to unaligned log */
ctx->expected_blob_size = sizeof(cfstore_flash_data_blob_t);
if(ctx->expected_blob_size % CFSTORE_FLASH_K64F_CURRENT_PROGRAM_UNIT_SIZE > 0){
ctx->expected_blob_size += (CFSTORE_FLASH_K64F_CURRENT_PROGRAM_UNIT_SIZE - (sizeof(cfstore_flash_data_blob_t) % CFSTORE_FLASH_K64F_CURRENT_PROGRAM_UNIT_SIZE));
}
ctx->area_0_head = (uint8_t*) CFSTORE_REALLOC((void*) ctx->area_0_head, ctx->expected_blob_size);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: unable to allocate memory for context\r\n", __func__);
TEST_ASSERT_MESSAGE(ctx->area_0_head != NULL, cfstore_flash_utest_msg_g);
ctx->area_0_tail = ctx->area_0_head + ctx->expected_blob_size;
memset(ctx->area_0_head, 0, ctx->expected_blob_size);
/* setup data to write to flash */
blob = (cfstore_flash_data_blob_t*) ctx->area_0_head;
blob->hdr.klength = strlen(cfstore_flush_test_01_kv_data->key_name);
blob->hdr.vlength= 1;
blob->hdr.perm_owner_read = true;
blob->hdr.perm_owner_write = true;
blob->hdr.refcount = 1;
memcpy((void*) blob->data, (const void*) cfstore_flush_test_01_kv_data->key_name, strlen(cfstore_flush_test_01_kv_data->key_name));
memcpy((void*) &blob->data[CFSTORE_TEST_DATA_KEYNAME_SIZE], (const void*) cfstore_flush_test_01_kv_data->value, strlen(cfstore_flush_test_01_kv_data->value));
}
if(ctx->area_0_head != NULL)
{
/* data has been read */
/* check the key_name read from flash is correct */
blob = (cfstore_flash_data_blob_t*) ctx->area_0_head;
value = (uint8_t) blob->data[CFSTORE_TEST_DATA_KEYNAME_SIZE];
printf("INFO: value read from flash = %u\r\n", value);
/* update the value */
value++;
memcpy((void*) &blob->data[CFSTORE_TEST_DATA_KEYNAME_SIZE], (const void*) &value, sizeof(uint8_t));
}
ret = FlashJournal_log(&ctx->jrnl, (const void*) ctx->area_0_head, ctx->expected_blob_size);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: ret = JOURNAL_STATUS_SMALL_LOG_REQUEST, bailing out.", __func__);
TEST_ASSERT_MESSAGE(ret != (int32_t) JOURNAL_STATUS_SMALL_LOG_REQUEST, cfstore_flash_utest_msg_g);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: failed to perform log operation to flash journal (ret=%" PRId32 ")\r\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret >= 0, cfstore_flash_utest_msg_g);
if(ret > 0){
/* write has completed synchronously*/
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: unable to write all data from flash journal (expected size=%lu, read=%d)\r\n", __func__, (unsigned long int) ctx->expected_blob_size, (int) ret);
TEST_ASSERT_EQUAL_INT32_MESSAGE(ret, (int32_t) ctx->expected_blob_size, cfstore_flash_utest_msg_g);
cfstore_flash_test_01_callback(ret, FLASH_JOURNAL_OPCODE_LOG_BLOB);
}
/* wait for async completion handler*/
}
/* @brief fsm handler when in reading state */
void cfstore_flash_fsm_writing(void* context)
{
cfstore_flash_ctx_t* ctx = (cfstore_flash_ctx_t*) context;
CFSTORE_FENTRYLOG("%s:entered:\r\n", __func__);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: entered handler(%s) but not in writing state (fsm->state=%d)\r\n", __func__, __func__, (int) ctx->fsm.state);
TEST_ASSERT_MESSAGE(ctx->fsm.state == cfstore_flash_fsm_state_writing, cfstore_flash_utest_msg_g);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: cmd_code code (%d) is not as expected (%d)\r\n", __func__, ctx->cmd_code, FLASH_JOURNAL_OPCODE_LOG_BLOB);
TEST_ASSERT_MESSAGE(ctx->cmd_code == FLASH_JOURNAL_OPCODE_LOG_BLOB, cfstore_flash_utest_msg_g);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: status=%" PRId32 "\r\n", __func__, ctx->status);
TEST_ASSERT_MESSAGE(ctx->status >= JOURNAL_STATUS_OK, cfstore_flash_utest_msg_g);
if(ctx->status > 0){
/* check the correct amount of data was written */
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: unable to write all data from flash journal (expected size=%lu, read=%" PRId32 ")\r\n", __func__, (unsigned long int) ctx->expected_blob_size, ctx->status);
TEST_ASSERT_EQUAL_INT64_MESSAGE(ctx->expected_blob_size, ctx->status, cfstore_flash_utest_msg_g);
cfstore_fsm_state_set(&ctx->fsm, cfstore_flash_fsm_state_committing, ctx);
}
return;
}
/* void cfstore_flash_fsm_write_on_exit(void* ctx){(void) ctx;} */
/* @brief fsm handler when entering committing state */
void cfstore_flash_fsm_commit_on_entry(void* context)
{
int32_t ret = 0;
cfstore_flash_ctx_t* ctx = (cfstore_flash_ctx_t*) context;
CFSTORE_FENTRYLOG("%s:entered:\r\n", __func__);
ret = FlashJournal_commit(&ctx->jrnl);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: failed to perform commit operation to flash journal (ret=%d)\r\n", __func__, (int) ret);
TEST_ASSERT_MESSAGE(ret >= (int32_t) JOURNAL_STATUS_OK, cfstore_flash_utest_msg_g);
/* for flash-journal-strategy-sequential version >0.4.0, commit() return no longer reports size of commit block */
if(ret > 0){
Harness::validate_callback();
}
/* wait for async completion handler*/
return;
}
/* @brief fsm handler when in committing state */
void cfstore_flash_fsm_committing(void* context)
{
cfstore_flash_ctx_t* ctx = (cfstore_flash_ctx_t*) context;
CFSTORE_FENTRYLOG("%s:entered\r\n", __func__);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: entered handler(%s) but not in committing state (fsm->state=%d)\r\n", __func__, __func__, (int) ctx->fsm.state);
TEST_ASSERT_MESSAGE(ctx->fsm.state == cfstore_flash_fsm_state_committing, cfstore_flash_utest_msg_g);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: cmd_code code (%d) is not as expected (%d)\r\n", __func__, ctx->cmd_code, FLASH_JOURNAL_OPCODE_COMMIT);
TEST_ASSERT_MESSAGE(ctx->cmd_code == FLASH_JOURNAL_OPCODE_COMMIT, cfstore_flash_utest_msg_g);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: status=%" PRId32 "\r\n", __func__, ctx->status);
TEST_ASSERT_MESSAGE(ctx->status >= JOURNAL_STATUS_OK, cfstore_flash_utest_msg_g);
/* check the correct amount of data was written */
/* for flash-journal-strategy-sequential version >0.4.0, commit() return no longer reports size of commit block */
Harness::validate_callback();
}
/* @brief fsm handler when exiting committing state */
void cfstore_flash_fsm_commit_on_exit(void* context)
{
cfstore_flash_ctx_t* ctx = (cfstore_flash_ctx_t*) context;
CFSTORE_FENTRYLOG("%s:entered\r\n", __func__);
/* test done. clean up*/
if(ctx->area_0_head){
CFSTORE_FREE(ctx->area_0_head);
ctx->area_0_head = NULL;
}
Harness::validate_callback();
}
#define cfstore_flash_fsm_null NULL
/* handler functions while in state */
static cfstore_flash_fsm_handler cfstore_flash_fsm[cfstore_flash_fsm_state_max][cfstore_flash_fsm_event_max] =
{
/* state\event: init_done read_done write_done commit_done */
/* initialising */ {cfstore_flash_fsm_initializing, cfstore_flash_fsm_null, cfstore_flash_fsm_null, cfstore_flash_fsm_null },
/* reading */ {cfstore_flash_fsm_null, cfstore_flash_fsm_reading, cfstore_flash_fsm_null, cfstore_flash_fsm_null },
/* writing */ {cfstore_flash_fsm_null, cfstore_flash_fsm_null, cfstore_flash_fsm_writing, cfstore_flash_fsm_null },
/* committing */ {cfstore_flash_fsm_null, cfstore_flash_fsm_null, cfstore_flash_fsm_null, cfstore_flash_fsm_committing },
};
/* handler functions for entering the state*/
cfstore_flash_fsm_handler cfstore_flash_fsm_on_entry[cfstore_flash_fsm_state_max] =
{
cfstore_flash_fsm_init_on_entry,
cfstore_flash_fsm_read_on_entry,
cfstore_flash_fsm_write_on_entry,
cfstore_flash_fsm_commit_on_entry,
};
/* handler functions for exiting state, currently none used */
cfstore_flash_fsm_handler cfstore_flash_fsm_on_exit[cfstore_flash_fsm_state_max] =
{
NULL, NULL, NULL, NULL,
};
/* @brief inject event into fsm */
static void cfstore_fsm_state_handle_event(cfstore_fsm_t* fsm, cfstore_flash_fsm_event_t event, void* context)
{
cfstore_flash_ctx_t* ctx = (cfstore_flash_ctx_t*) context;
CFSTORE_FENTRYLOG("%s:entered: fsm=%p, event=%d (%s), ctx=%p\r\n", __func__, fsm, (int) event, cfstore_flash_event_str[event], ctx);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: invalid event (%d)\r\n", __func__, (int) event);
TEST_ASSERT_MESSAGE(event < cfstore_flash_fsm_event_max, cfstore_flash_utest_msg_g);
fsm->event = event;
if(cfstore_flash_fsm[fsm->state][fsm->event] != NULL){
cfstore_flash_fsm[fsm->state][fsm->event](ctx);
}
/* do not clear context data set by caller as it may be used later
* fsm->event = cfstore_flash_fsm_event_max;
* ctx->status = 0;
* ctx->cmd_code = (FlashJournal_OpCode_t)((int) FLASH_JOURNAL_OPCODE_RESET+1);
*/
return;
}
/* @brief function to move to new fsm state, calling state exit function for old state and entry function for new state */
static void cfstore_fsm_state_set(cfstore_fsm_t* fsm, cfstore_flash_fsm_state_t new_state, void* ctx)
{
CFSTORE_FENTRYLOG("%s:entered: fsm=%p, new_state=%d, ctx=%p\r\n", __func__, fsm, (int) new_state, ctx);
CFSTORE_DBGLOG("%s:FSM:REQ RX:%s:%s\r\n", __func__, cfstore_flash_state_str[fsm->state], cfstore_flash_state_str[new_state]);
TEST_ASSERT_MESSAGE(fsm != NULL, "fsm is not a valid pointer");
TEST_ASSERT_MESSAGE(new_state < cfstore_flash_fsm_state_max, "new_state is not a valid state");
TEST_ASSERT_MESSAGE(ctx != NULL, "ctx is not a valid pointer");
TEST_ASSERT_MESSAGE(fsm->state < cfstore_flash_fsm_state_max, "fsm->state is not a valid state");
if(cfstore_flash_fsm_on_exit[fsm->state] != NULL){
cfstore_flash_fsm_on_exit[fsm->state](ctx);
}
fsm->state = new_state;
if(cfstore_flash_fsm_on_entry[new_state] != NULL){
cfstore_flash_fsm_on_entry[new_state](ctx);
}
CFSTORE_DBGLOG("%s:FSM:REQ DONE:\r\n", __func__);
return;
}
/* @brief initialize global context data structure */
static void cfstore_flash_ctx_init(cfstore_flash_ctx_t* ctx)
{
TEST_ASSERT_MESSAGE(ctx != NULL, "ctx is NULL");
CFSTORE_FENTRYLOG("%s:entered\r\n", __func__);
memset(&cfstore_flash_ctx_g, 0, sizeof(cfstore_flash_ctx_g));
}
/* @brief asynchronous test 01 */
static control_t cfstore_flash_journal_async_test_01(void)
{
cfstore_flash_ctx_t* ctx = cfstore_flash_ctx_get();
CFSTORE_FENTRYLOG("%s:entered: \r\n", __func__);
cfstore_flash_mtd_async_ops_g = CFSTORE_FLASH_MTD_ASYNC_OPS_ON;
cfstore_flash_ctx_init(ctx);
cfstore_fsm_state_set(&ctx->fsm, cfstore_flash_fsm_state_initializing, ctx);
/* allow time for work to be done */
return CaseTimeout(CFSTORE_FLASH_CASE_TIMEOUT_MS);
}
#endif /* CFSTORE_CONFIG_BACKEND_FLASH_ENABLED */
/* report whether built/configured for flash sync or async mode */
static control_t cfstore_flash_test_00(const size_t call_count)
{
(void) call_count;
CFSTORE_LOG("INITIALIZING: caps.asynchronous_ops=%lu\n", cfstore_driver.GetCapabilities().asynchronous_ops);
#ifdef YOTTA_CFG_CFSTORE_BACKEND_SRAM
CFSTORE_LOG("INITIALIZING: BACKEND=SRAM. Skipping flash test%s", "\n");
#endif
return CaseNext;
}
/* Specify all your test cases here */
Case cases[] = {
Case("flash_journal_async_test_00", cfstore_flash_test_00),
#if defined CFSTORE_CONFIG_BACKEND_FLASH_ENABLED && CFSTORE_CONFIG_BACKEND_FLASH_ENABLED == 1
Case("flash_journal_async_test_01", cfstore_flash_journal_async_test_01),
#endif
};
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(100, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
/* Declare your test specification with a custom setup handler */
Specification specification(greentea_setup, cases);
#if defined CFSTORE_CONFIG_MBED_OS_VERSION && CFSTORE_CONFIG_MBED_OS_VERSION == 3
/* mbedosV3*/
void app_start(int argc __unused, char** argv __unused)
{
/* Run the test specification */
Harness::run(specification);
}
#endif /* CFSTORE_CONFIG_MBED_OS_VERSION == 3 */
#if defined CFSTORE_CONFIG_MBED_OS_VERSION && CFSTORE_CONFIG_MBED_OS_VERSION == 4
/* mbedosV3++*/
int main()
{
return !Harness::run(specification);
}
#endif /* CFSTORE_CONFIG_MBED_OS_VERSION == 4 */
#endif // __MBED__ && ! defined TOOLCHAIN_GCC_ARM

View File

@ -0,0 +1,638 @@
/* @file flush.cpp
*
* mbed Microcontroller Library
* Copyright (c) 2006-2016 ARM Limited
*
* 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.
*
* Test cases to flush KVs in the CFSTORE using the drv->Flush() interface.
*/
#if defined __MBED__ && ! defined TOOLCHAIN_GCC_ARM
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#ifdef TARGET_LIKE_FRDM_K64F_GCC
#include <mbed-drivers/mbed.h>
#endif
#include "cfstore_config.h"
#include <Driver_Common.h>
#include "cfstore_debug.h"
#include "cfstore_test.h"
#include <configuration-store/configuration_store.h>
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#ifdef YOTTA_CFG_CFSTORE_UVISOR
#include "uvisor-lib/uvisor-lib.h"
#include "cfstore_uvisor.h"
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
using namespace utest::v1;
static control_t cfstore_flush_test_00(const size_t call_count)
{
(void) call_count;
printf("Not implemented for ARM toolchain\n");
return CaseNext;
}
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(100, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
/* 1 2 3 4 5 6 7 */
/* 1234567890123456789012345678901234567890123456789012345678901234567890 */
Case("FLUSH_test_00", cfstore_flush_test_00),
};
/* Declare your test specification with a custom setup handler */
Specification specification(greentea_setup, cases);
int main()
{
return !Harness::run(specification);
}
#else
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#ifdef TARGET_LIKE_FRDM_K64F_GCC
#include <mbed-drivers/mbed.h>
#endif
#include "cfstore_config.h"
#include "cfstore_test.h"
#include "cfstore_debug.h"
//#include <flash-abstraction/Driver_Common.h>
#include <Driver_Common.h>
#include <configuration-store/configuration_store.h>
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#ifdef YOTTA_CFG_CFSTORE_UVISOR
#include "uvisor-lib/uvisor-lib.h"
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
using namespace utest::v1;
/*
* Defines
*/
#define CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE 256
#define cfstore_flush_fsm_null NULL
#define CFSTORE_FLUSH_CASE_TIMEOUT_MS 10000
#define CFSTORE_FLUSH_FSM_LOOPS 20
#ifdef CFSTORE_DEBUG
#define CFSTORE_FLUSH_GREENTEA_TIMEOUT_S 360
#else
#define CFSTORE_FLUSH_GREENTEA_TIMEOUT_S 60
#endif
/*
* Globals
*
* cfstore_flush_utest_msg_g
* buffer for storing TEST_ASSERT_xxx_MESSAGE messages
*/
char cfstore_flush_utest_msg_g[CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE];
/* Configure secure box. */
#ifdef YOTTA_CFG_CFSTORE_UVISOR
UVISOR_BOX_NAMESPACE("com.arm.mbed.cfstore.test.flush.box1");
UVISOR_BOX_CONFIG(cfstore_flush_box1, UVISOR_BOX_STACK_SIZE);
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
#ifdef TARGET_LIKE_X86_LINUX_NATIVE
/** @brief basic Flush() test
*
* @return status code
* ARM_DRIVER_OK, the test passed successfully
* ret != ARM_DRIVER_OK, the test failed with the return code
* supplying more details
*/
static int32_t cfstore_flush_test_01_x86_sync(void)
{
int32_t ret = ARM_DRIVER_ERROR;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
CFSTORE_LOG("cfstore_flush_test_01: Start%s", "\r\n");
ret = drv->Initialize(NULL, NULL);
if(ret != ARM_DRIVER_OK){
CFSTORE_ERRLOG("%s:Initialize() call failed (ret=%" PRId32 ").\r\n", __func__, ret);
goto out0;
}
ret = drv->Flush();
if(ret != ARM_DRIVER_OK){
CFSTORE_ERRLOG("%s:Flush() call failed (ret=%" PRId32 ").\r\n", __func__, ret);
}
ret = drv->Uninitialize();
if(ret != ARM_DRIVER_OK){
CFSTORE_ERRLOG("%s:Initialize() call failed to Uninitialise(ret=%" PRId32 ").\r\n", __func__, ret);
goto out0;
}
out0:
if(ret == ARM_DRIVER_OK){
CFSTORE_LOG("cfstore_flush_test_01: End: Success%s", "\r\n");
} else {
CFSTORE_LOG("cfstore_flush_test_01: End: Failed%s", "\r\n");
}
return ret;
}
#endif /* TARGET_LIKE_X86_LINUX_NATIVE */
/* KV data for test_03 */
static cfstore_kv_data_t cfstore_flush_test_02_kv_data[] = {
{ "com.arm.mbed.configurationstore.test.flush.cfstoreflushtest02", "1"},
/* 1 2 3 4 5 6 7 */
/* 1234567890123456789012345678901234567890123456789012345678901234567890 */
{ NULL, NULL},
};
/* async test version */
/* @brief test fsm states and events */
typedef enum cfstore_flush_fsm_state_t {
cfstore_flush_fsm_state_stopped = 0,
cfstore_flush_fsm_state_initializing,
cfstore_flush_fsm_state_flushing,
cfstore_flush_fsm_state_uninitializing,
cfstore_flush_fsm_state_max
} cfstore_flush_fsm_state_t;
/* @brief test fsm events */
typedef enum cfstore_flush_fsm_event_t {
cfstore_flush_fsm_event_init_done = 0,
cfstore_flush_fsm_event_flush_done,
cfstore_flush_fsm_event_uninit_done,
cfstore_flush_fsm_event_max,
} cfstore_flush_fsm_event_t;
typedef void (*cfstore_flush_fsm_handler)(void* ctx);
typedef struct cfstore_fsm_t
{
cfstore_flush_fsm_state_t state;
cfstore_flush_fsm_event_t event;
} cfstore_fsm_t;
typedef struct cfstore_flush_ctx_t
{
int32_t loops_done;
cfstore_fsm_t fsm;
int32_t status;
ARM_CFSTORE_OPCODE cmd_code;
} cfstore_flush_ctx_t;
/*
* Globals
*/
static cfstore_flush_ctx_t cfstore_flush_ctx_g;
#ifdef CFSTORE_DEBUG
static const char* cfstore_flush_state_str[] =
{
"stopped",
"initializing",
"flushing",
"uninitializing",
"unknown"
};
static const char* cfstore_flush_event_str[] =
{
"init_done",
"flush_done",
"uninit_done",
"unknown"
};
#endif
/*
* Forward decl
*/
static void cfstore_flush_fsm_state_handle_event(cfstore_fsm_t* fsm, cfstore_flush_fsm_event_t event, void* context);
static void cfstore_flush_fsm_state_set(cfstore_fsm_t* fsm, cfstore_flush_fsm_state_t new_state, void* ctx);
/*
* context related methods
*/
/* @brief get a pointer to the global context data structure */
static cfstore_flush_ctx_t* cfstore_flush_ctx_get(void)
{
return &cfstore_flush_ctx_g;
}
/* @brief initialize global context data structure */
static void cfstore_flush_ctx_init(cfstore_flush_ctx_t* ctx)
{
TEST_ASSERT_MESSAGE(ctx != NULL, "ctx is NULL");
CFSTORE_FENTRYLOG("%s:entered\r\n", __func__);
memset(&cfstore_flush_ctx_g, 0, sizeof(cfstore_flush_ctx_g));
}
/* @brief cfstore asynchronous callback handler */
void cfstore_flush_test_01_callback(int32_t status, ARM_CFSTORE_OPCODE cmd_code, void *client_context, ARM_CFSTORE_HANDLE handle)
{
cfstore_flush_ctx_t* ctx = (cfstore_flush_ctx_t*) client_context;
CFSTORE_FENTRYLOG("%s:entered: status=%d, cmd_code=%d (%s) ctx=%p, handle=%p\r\n", __func__, (int) status, (int) cmd_code, cfstore_test_opcode_str[cmd_code], ctx, handle);
(void) handle;
switch(cmd_code)
{
case CFSTORE_OPCODE_INITIALIZE:
ctx->fsm.event = cfstore_flush_fsm_event_init_done;
break;
case CFSTORE_OPCODE_FLUSH:
ctx->fsm.event = cfstore_flush_fsm_event_flush_done;
break;
case CFSTORE_OPCODE_UNINITIALIZE:
ctx->fsm.event = cfstore_flush_fsm_event_uninit_done;
break;
case CFSTORE_OPCODE_CLOSE:
case CFSTORE_OPCODE_CREATE:
case CFSTORE_OPCODE_DELETE:
case CFSTORE_OPCODE_FIND:
case CFSTORE_OPCODE_GET_KEY_NAME:
case CFSTORE_OPCODE_GET_STATUS:
case CFSTORE_OPCODE_GET_VALUE_LEN:
case CFSTORE_OPCODE_OPEN:
case CFSTORE_OPCODE_POWER_CONTROL:
case CFSTORE_OPCODE_READ:
case CFSTORE_OPCODE_RSEEK:
case CFSTORE_OPCODE_WRITE:
default:
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:WARN: received asynchronous notification for opcode=%d (%s) when api call should have been synchronous", __func__, cmd_code, cmd_code < CFSTORE_OPCODE_MAX ? cfstore_test_opcode_str[cmd_code] : "unknown");
CFSTORE_DBGLOG("%s:WARN: received asynchronous notification for opcode=%d (%s) when api call should have been synchronous", __func__, cmd_code, cmd_code < CFSTORE_OPCODE_MAX ? cfstore_test_opcode_str[cmd_code] : "unknown");
/* TEST_ASSERT_MESSAGE(false, cfstore_flush_utest_msg_g) */
return;
}
ctx->status = status;
ctx->cmd_code = cmd_code;
cfstore_flush_fsm_state_handle_event(&ctx->fsm, ctx->fsm.event, client_context);
return;
}
/* @brief fsm handler called on entry to stopping state */
static void cfstore_flush_fsm_stop_on_entry(void* context)
{
(void) context;
CFSTORE_FENTRYLOG("%s:entered:\r\n", __func__);
Harness::validate_callback();
return;
}
/* @brief fsm handler called on entry to initializing state */
static void cfstore_flush_fsm_init_on_entry(void* context)
{
int32_t ret = ARM_DRIVER_ERROR;
cfstore_flush_ctx_t* ctx = (cfstore_flush_ctx_t*) context;
const ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
/* check that the mtd is in synchronous mode */
CFSTORE_FENTRYLOG("%s:entered: callback=%p, ctx=%p\r\n", __func__, cfstore_flush_test_01_callback, ctx);
ret = drv->Initialize(cfstore_flush_test_01_callback, ctx);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: failed to initialize CFSTORE (ret=%" PRId32 ")\r\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_flush_utest_msg_g);
CFSTORE_DBGLOG("%s:debug: ret=%" PRId32 "\r\n", __func__, ret);
return;
}
/* brief callback handler when in state initializing */
static void cfstore_flush_fsm_initializing(void* context)
{
cfstore_flush_ctx_t* ctx = (cfstore_flush_ctx_t*) context;
CFSTORE_FENTRYLOG("%s:entered\r\n", __func__);
CFSTORE_FENTRYLOG("%s:entered: status = %d\r\n", __func__, (int) ctx->status);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: entered handler(%s) but not in initializing state (fsm->state=%d)\r\n", __func__, __func__, (int) ctx->fsm.state);
TEST_ASSERT_MESSAGE(ctx->fsm.state == cfstore_flush_fsm_state_initializing, cfstore_flush_utest_msg_g);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: cmd_code code (%d) is not as expected (%d)\r\n", __func__, ctx->cmd_code, CFSTORE_OPCODE_INITIALIZE);
TEST_ASSERT_MESSAGE(ctx->cmd_code == CFSTORE_OPCODE_INITIALIZE, cfstore_flush_utest_msg_g);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: status=%" PRId32 "\r\n", __func__, ctx->status);
TEST_ASSERT_MESSAGE(ctx->status >= ARM_DRIVER_OK, cfstore_flush_utest_msg_g);
/* only change state if status >= 0*/
if(ctx->status >= 0){
cfstore_flush_fsm_state_set(&ctx->fsm, cfstore_flush_fsm_state_flushing, ctx);
}
return;
}
/* static void cfstore_flush_fsm_init_on_exit(void* context){ (void) context;} */
/* @brief fsm handler called on entry to flushing state */
static void cfstore_flush_fsm_flush_on_entry(void* context)
{
bool bfound = false;
int32_t ivalue = 0;
int32_t ret = ARM_DRIVER_ERROR;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
const char* key_name_query = "*";
char value[CFSTORE_KEY_NAME_MAX_LENGTH+1];
ARM_CFSTORE_SIZE len = CFSTORE_KEY_NAME_MAX_LENGTH+1;
ARM_CFSTORE_HANDLE_INIT(next);
ARM_CFSTORE_HANDLE_INIT(prev);
ARM_CFSTORE_KEYDESC kdesc;
cfstore_flush_ctx_t* ctx = (cfstore_flush_ctx_t*) context;
/* check that the mtd is in synchronous mode */
CFSTORE_FENTRYLOG("%s:entered: \r\n", __func__);
memset(&kdesc, 0, sizeof(kdesc));
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: entered handler(%s) but not in flushing state (fsm->state=%d)\r\n", __func__, __func__, (int) ctx->fsm.state);
TEST_ASSERT_MESSAGE(ctx->fsm.state == cfstore_flush_fsm_state_flushing, cfstore_flush_utest_msg_g);
/* try to read key; should not be found */
ret = cfstore_test_kv_is_found(cfstore_flush_test_02_kv_data->key_name, &bfound);
if(ret != ARM_DRIVER_OK && ret != ARM_CFSTORE_DRIVER_ERROR_KEY_NOT_FOUND){
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: cfstore_test_kv_is_found() call failed (ret=%" PRId32 ").\r\n", __func__, ret);
TEST_ASSERT_MESSAGE(false, cfstore_flush_utest_msg_g);
}
if(!bfound)
{
/* first time start up. nothing is stored in cfstore flash. check this is the case */
while(drv->Find(key_name_query, prev, next) == ARM_DRIVER_OK)
{
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: have found an entry in cfstore when none should be present", __func__);
TEST_ASSERT_MESSAGE(false, cfstore_flush_utest_msg_g);
}
/* no entries found, which is correct.
* store a value */
len = strlen(cfstore_flush_test_02_kv_data->value);
ret = cfstore_test_create(cfstore_flush_test_02_kv_data->key_name, cfstore_flush_test_02_kv_data->value, &len, &kdesc);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error:1: failed to write kv data (ret=%" PRId32 ").\r\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_flush_utest_msg_g);
/* flush to flash */
ret = drv->Flush();
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: failed to flush data to cfstore flash (ret=%" PRId32 ").\r\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_flush_utest_msg_g);
CFSTORE_LOG("FLUSH: Success pending for new KV creation (name=%s, value=%s)\n", cfstore_flush_test_02_kv_data->key_name, cfstore_flush_test_02_kv_data->value)
} else {
/*read the value, increment by 1 and write value back */
len = CFSTORE_KEY_NAME_MAX_LENGTH+1;
ret = cfstore_test_read(cfstore_flush_test_02_kv_data->key_name, value, &len);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: failed to read kv data (ret=%" PRId32 ").\r\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_flush_utest_msg_g);
ivalue = atoi(value);
CFSTORE_LOG("FLUSH: Read KV from flash (name=%s, value=%" PRId32 ")\n", cfstore_flush_test_02_kv_data->key_name, ivalue);
/* increment value */
++ivalue;
snprintf(value, CFSTORE_KEY_NAME_MAX_LENGTH+1, "%" PRId32 "", ivalue);
len = strlen(value);
ret = cfstore_test_write(cfstore_flush_test_02_kv_data->key_name, value, &len);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: failed to write kv data (ret=%" PRId32 ").\r\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_flush_utest_msg_g);
/* flush to flash */
ret = drv->Flush();
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: failed to flush data to cfstore flash (ret=%" PRId32 ").\r\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_flush_utest_msg_g);
CFSTORE_LOG("FLUSH: Success pending for new KV value to flash (name=%s, value=%" PRId32 ")\n", cfstore_flush_test_02_kv_data->key_name, ivalue);
}
return;
}
/* brief callback handler when in state flushing */
static void cfstore_flush_fsm_flushing(void* context)
{
cfstore_flush_ctx_t* ctx = (cfstore_flush_ctx_t*) context;
CFSTORE_FENTRYLOG("%s:entered\r\n", __func__);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: entered handler(%s) but not in flushing state (fsm->state=%d)\r\n", __func__, __func__, (int) ctx->fsm.state);
TEST_ASSERT_MESSAGE(ctx->fsm.state == cfstore_flush_fsm_state_flushing, cfstore_flush_utest_msg_g);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: cmd_code code (%d) is not as expected (%d)\r\n", __func__, ctx->cmd_code, CFSTORE_OPCODE_FLUSH);
TEST_ASSERT_MESSAGE(ctx->cmd_code == CFSTORE_OPCODE_FLUSH, cfstore_flush_utest_msg_g);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: status=%" PRId32 "\r\n", __func__, ctx->status);
TEST_ASSERT_MESSAGE(ctx->status >= ARM_DRIVER_OK, cfstore_flush_utest_msg_g);
/* only change state if status >= 0*/
if(ctx->status >= 0){
CFSTORE_LOG("FLUSH: Successfully flushed data to flash.%s", "\n");
cfstore_flush_fsm_state_set(&ctx->fsm, cfstore_flush_fsm_state_uninitializing, ctx);
}
return;
}
/* static void cfstore_flush_fsm_flush_on_exit(void* context){ (void) context;} */
/* @brief fsm handler called on entry to uninitializing state */
static void cfstore_flush_fsm_uninit_on_entry(void* context)
{
int32_t ret = ARM_DRIVER_ERROR;
cfstore_flush_ctx_t* ctx = (cfstore_flush_ctx_t*) context;
const ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
/* check that the mtd is in synchronous mode */
CFSTORE_FENTRYLOG("%s:entered: \r\n", __func__);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: entered handler(%s) but not in uninitializing state (fsm->state=%d)\r\n", __func__, __func__, (int) ctx->fsm.state);
TEST_ASSERT_MESSAGE(ctx->fsm.state == cfstore_flush_fsm_state_uninitializing, cfstore_flush_utest_msg_g);
ret = drv->Uninitialize();
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: failed to uninitialize CFSTORE (ret=%" PRId32 ")\r\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_flush_utest_msg_g);
return;
}
/* brief callback handler when in state uninitializing */
static void cfstore_flush_fsm_uninitializing(void* context)
{
cfstore_flush_ctx_t* ctx = (cfstore_flush_ctx_t*) context;
CFSTORE_FENTRYLOG("%s:entered\r\n", __func__);
CFSTORE_DBGLOG("%s:ctx->status=%" PRId32 ", ctx->loops_done=%" PRId32 "\r\n", __func__, ctx->status, ctx->loops_done);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: entered handler(%s) but not in uninitializing state (fsm->state=%d)\r\n", __func__, __func__, (int) ctx->fsm.state);
TEST_ASSERT_MESSAGE(ctx->fsm.state == cfstore_flush_fsm_state_uninitializing, cfstore_flush_utest_msg_g);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: cmd_code code (%d) is not as expected (%d)\r\n", __func__, ctx->cmd_code, CFSTORE_OPCODE_UNINITIALIZE);
TEST_ASSERT_MESSAGE(ctx->cmd_code == CFSTORE_OPCODE_UNINITIALIZE, cfstore_flush_utest_msg_g);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: status=%" PRId32 "\r\n", __func__, ctx->status);
TEST_ASSERT_MESSAGE(ctx->status >= ARM_DRIVER_OK, cfstore_flush_utest_msg_g);
/* only change state if status >= 0*/
if(ctx->status >= ARM_DRIVER_OK){
++ctx->loops_done;
if(ctx->loops_done < CFSTORE_FLUSH_FSM_LOOPS){
cfstore_flush_fsm_state_set(&ctx->fsm, cfstore_flush_fsm_state_initializing, ctx);
} else {
/* move to init state */
cfstore_flush_fsm_state_set(&ctx->fsm, cfstore_flush_fsm_state_stopped, ctx);
}
}
return;
}
/* static void cfstore_flush_fsm_uninit_on_exit(void* context) {(void)context;} */
/* handler functions while in state */
static cfstore_flush_fsm_handler cfstore_flush_fsm[cfstore_flush_fsm_state_max][cfstore_flush_fsm_event_max] =
{
/* state\event: init_done flush_done unint_done */
/* stopped */ {cfstore_flush_fsm_null, cfstore_flush_fsm_null, cfstore_flush_fsm_null },
/* initialising */ {cfstore_flush_fsm_initializing, cfstore_flush_fsm_null, cfstore_flush_fsm_null },
/* flushing */ {cfstore_flush_fsm_null, cfstore_flush_fsm_flushing, cfstore_flush_fsm_null },
/* uninitializing */ {cfstore_flush_fsm_null, cfstore_flush_fsm_null, cfstore_flush_fsm_uninitializing }
};
/* handler functions for entering the state*/
static cfstore_flush_fsm_handler cfstore_flush_fsm_on_entry[cfstore_flush_fsm_state_max] =
{
cfstore_flush_fsm_stop_on_entry,
cfstore_flush_fsm_init_on_entry,
cfstore_flush_fsm_flush_on_entry,
cfstore_flush_fsm_uninit_on_entry
};
/* handler functions for exiting state, currently none used */
static cfstore_flush_fsm_handler cfstore_flush_fsm_on_exit[cfstore_flush_fsm_state_max] =
{
cfstore_flush_fsm_null,
cfstore_flush_fsm_null,
cfstore_flush_fsm_null,
cfstore_flush_fsm_null
};
/* @brief inject event into fsm */
static void cfstore_flush_fsm_state_handle_event(cfstore_fsm_t* fsm, cfstore_flush_fsm_event_t event, void* context)
{
cfstore_flush_ctx_t* ctx = (cfstore_flush_ctx_t*) context;
CFSTORE_FENTRYLOG("%s:entered: fsm=%p, state=(%s), event=%d (%s), ctx=%p\r\n", __func__, fsm, cfstore_flush_state_str[fsm->state], (int) event, cfstore_flush_event_str[event], ctx);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: invalid event (%d)\r\n", __func__, (int) event);
TEST_ASSERT_MESSAGE(event < cfstore_flush_fsm_event_max, cfstore_flush_utest_msg_g);
fsm->event = event;
if(cfstore_flush_fsm[fsm->state][fsm->event] != NULL){
cfstore_flush_fsm[fsm->state][fsm->event](ctx);
}
/* do not clear context data set by caller as it may be used later
* fsm->event = cfstore_flush_fsm_event_max;
* ctx->status = 0;
* ctx->cmd_code = (FlashJournal_OpCode_t)((int) FLASH_JOURNAL_OPCODE_RESET+1);
*/
return;
}
/* @brief function to move to new fsm state, calling state exit function for old state and entry function for new state */
static void cfstore_flush_fsm_state_set(cfstore_fsm_t* fsm, cfstore_flush_fsm_state_t new_state, void* ctx)
{
#ifdef CFSTORE_DEBUG
cfstore_flush_fsm_state_t old_state = fsm->state;
#endif
CFSTORE_FENTRYLOG("%s:entered: fsm=%p, ctx=%p\r\n", __func__, fsm, ctx);
#ifdef CFSTORE_DEBUG
CFSTORE_DBGLOG("%s:FSM:REQ RX:%s:%s\r\n", __func__, cfstore_flush_state_str[fsm->state], cfstore_flush_state_str[new_state]);
#endif
TEST_ASSERT_MESSAGE(fsm != NULL, "fsm is not a valid pointer");
TEST_ASSERT_MESSAGE(new_state < cfstore_flush_fsm_state_max, "new_state is not a valid state");
TEST_ASSERT_MESSAGE(ctx != NULL, "ctx is not a valid pointer");
TEST_ASSERT_MESSAGE(fsm->state < cfstore_flush_fsm_state_max, "fsm->state is not a valid state");
if(cfstore_flush_fsm_on_exit[fsm->state] != NULL){
cfstore_flush_fsm_on_exit[fsm->state](ctx);
}
fsm->state = new_state;
if(cfstore_flush_fsm_on_entry[new_state] != NULL){
cfstore_flush_fsm_on_entry[new_state](ctx);
}
#ifdef CFSTORE_DEBUG
CFSTORE_DBGLOG("%s:FSM:REQ DONE fsm=%p, fsm->state (old_state)=%s, new_state=%s, ctx=%p\r\n", __func__, fsm, cfstore_flush_state_str[old_state], cfstore_flush_state_str[new_state], ctx);
#endif
return;
}
/* @brief asynchronous test 01 */
static control_t cfstore_flush_test_02_k64f(void)
{
cfstore_flush_ctx_t* ctx = cfstore_flush_ctx_get();
CFSTORE_FENTRYLOG("%s:entered: \r\n", __func__);
cfstore_flush_ctx_init(ctx);
cfstore_flush_fsm_state_set(&ctx->fsm, cfstore_flush_fsm_state_initializing, ctx);
return CaseTimeout(CFSTORE_FLUSH_GREENTEA_TIMEOUT_S*1000);
}
/* report whether built/configured for flash sync or async mode */
static control_t cfstore_flush_test_00(const size_t call_count)
{
(void) call_count;
CFSTORE_LOG("INITIALIZING: caps.asynchronous_ops=%lu\n", cfstore_driver.GetCapabilities().asynchronous_ops);
return CaseNext;
}
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(CFSTORE_FLUSH_GREENTEA_TIMEOUT_S, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
Case("FLUSH_test_00", cfstore_flush_test_00),
Case("FLUSH_test_01", cfstore_flush_test_02_k64f),
};
/* Declare your test specification with a custom setup handler */
Specification specification(greentea_setup, cases);
#if defined CFSTORE_CONFIG_MBED_OS_VERSION && CFSTORE_CONFIG_MBED_OS_VERSION == 3
/* mbedosV3*/
void app_start(int argc __unused, char** argv __unused)
{
/* Run the test specification */
Harness::run(specification);
}
#endif /* CFSTORE_CONFIG_MBED_OS_VERSION == 3 */
#if defined CFSTORE_CONFIG_MBED_OS_VERSION && CFSTORE_CONFIG_MBED_OS_VERSION == 4
/* mbedosV3++*/
int main()
{
return !Harness::run(specification);
}
#endif /* CFSTORE_CONFIG_MBED_OS_VERSION == 4 */
#endif // __MBED__ && ! defined TOOLCHAIN_GCC_ARM

View File

@ -0,0 +1,333 @@
/* @file flush.cpp
*
* mbed Microcontroller Library
* Copyright (c) 2006-2016 ARM Limited
*
* 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.
*
* Test cases to flush KVs in the CFSTORE using the drv->Flush() interface.
*/
#if defined __MBED__ && ! defined TOOLCHAIN_GCC_ARM
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#ifdef TARGET_LIKE_FRDM_K64F_GCC
#include <mbed-drivers/mbed.h>
#endif
#include "cfstore_config.h"
#include <Driver_Common.h>
#include "cfstore_debug.h"
#include "cfstore_test.h"
#include <configuration-store/configuration_store.h>
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#ifdef YOTTA_CFG_CFSTORE_UVISOR
#include "uvisor-lib/uvisor-lib.h"
#include "cfstore_uvisor.h"
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
using namespace utest::v1;
static control_t cfstore_flush2_test_00(const size_t call_count)
{
(void) call_count;
printf("Not implemented for ARM toolchain\n");
return CaseNext;
}
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(100, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
/* 1 2 3 4 5 6 7 */
/* 1234567890123456789012345678901234567890123456789012345678901234567890 */
Case("FLUSH2_test_00", cfstore_flush2_test_00),
};
/* Declare your test specification with a custom setup handler */
Specification specification(greentea_setup, cases);
int main()
{
return !Harness::run(specification);
}
#else
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#ifdef TARGET_LIKE_FRDM_K64F_GCC
#include <mbed-drivers/mbed.h>
#endif
#include "utest/utest.h"
#include "unity/unity.h"
#include "cfstore_config.h"
#include <configuration-store/configuration_store.h>
#include "greentea-client/test_env.h"
#include "cfstore_test.h"
#include "cfstore_debug.h"
#include "cfstore_utest.h"
#ifdef YOTTA_CFG_CFSTORE_UVISOR
#include "uvisor-lib/uvisor-lib.h"
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
using namespace utest::v1;
/*
* Defines
*/
#define CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE 256
#define cfstore_flush_fsm_null NULL
#define CFSTORE_FLUSH_CASE_TIMEOUT_MS 10000
/* Configure secure box. */
#ifdef YOTTA_CFG_CFSTORE_UVISOR
UVISOR_BOX_NAMESPACE("com.arm.mbed.cfstore.test.flush2.box1");
UVISOR_BOX_CONFIG(cfstore_flush2_box1, UVISOR_BOX_STACK_SIZE);
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
/*
* Globals
*
* cfstore_flush_utest_msg_g
* buffer for storing TEST_ASSERT_xxx_MESSAGE messages
*/
static char cfstore_flush_utest_msg_g[CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE];
/* KV data for test_03 */
static cfstore_kv_data_t cfstore_flush_test_02_kv_data[] = {
{ "com.arm.mbed.configurationstore.test.flush.cfstoreflushtest02", "1"},
/* 1 2 3 4 5 6 7 */
/* 1234567890123456789012345678901234567890123456789012345678901234567890 */
{ NULL, NULL},
};
/* async test version */
typedef struct cfstore_flush_ctx_t
{
int32_t status;
ARM_CFSTORE_OPCODE cmd_code;
} cfstore_flush_ctx_t;
/*
* Globals
*/
static cfstore_flush_ctx_t cfstore_flush_ctx_g;
/*
* context related methods
*/
/* @brief get a pointer to the global context data structure */
static cfstore_flush_ctx_t* cfstore_flush_ctx_get(void)
{
return &cfstore_flush_ctx_g;
}
/* @brief initialize global context data structure */
static void cfstore_flush_ctx_init(cfstore_flush_ctx_t* ctx)
{
TEST_ASSERT_MESSAGE(ctx != NULL, "ctx is NULL");
CFSTORE_FENTRYLOG("%s:entered\r\n", __func__);
memset(&cfstore_flush_ctx_g, 0, sizeof(cfstore_flush_ctx_g));
}
/* report whether built/configured for flash sync or async mode */
static control_t cfstore_flush2_test_00(const size_t call_count)
{
(void) call_count;
CFSTORE_LOG("INITIALIZING: caps.asynchronous_ops=%lu\n", cfstore_driver.GetCapabilities().asynchronous_ops);
return CaseNext;
}
control_t cfstore_flush2_test_01_start(const size_t call_count)
{
int32_t ret = ARM_DRIVER_ERROR;
cfstore_flush_ctx_t* ctx = cfstore_flush_ctx_get();
const ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
/* check that the mtd is in synchronous mode */
CFSTORE_FENTRYLOG("%s:entered:\r\n", __func__);
(void) call_count;
cfstore_flush_ctx_init(ctx);
ret = drv->Initialize(cfstore_utest_default_callback, ctx);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: failed to initialize CFSTORE (ret=%" PRId32 ")\r\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_flush_utest_msg_g);
return CaseTimeout(100000);
}
static control_t cfstore_flush2_test_01_mid(const size_t call_count)
{
bool bfound = false;
int32_t ivalue = 0;
int32_t ret = ARM_DRIVER_ERROR;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
const char* key_name_query = "*";
char value[CFSTORE_KEY_NAME_MAX_LENGTH+1];
ARM_CFSTORE_SIZE len = CFSTORE_KEY_NAME_MAX_LENGTH+1;
ARM_CFSTORE_HANDLE_INIT(next);
ARM_CFSTORE_HANDLE_INIT(prev);
ARM_CFSTORE_KEYDESC kdesc;
/* check that the mtd is in synchronous mode */
CFSTORE_FENTRYLOG("%s:entered: \r\n", __func__);
(void) call_count;
memset(&kdesc, 0, sizeof(kdesc));
/* try to read key; should not be found */
ret = cfstore_test_kv_is_found(cfstore_flush_test_02_kv_data->key_name, &bfound);
if(ret != ARM_DRIVER_OK && ret != ARM_CFSTORE_DRIVER_ERROR_KEY_NOT_FOUND){
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: cfstore_test_kv_is_found() call failed (ret=%" PRId32 ").\r\n", __func__, ret);
TEST_ASSERT_MESSAGE(false, cfstore_flush_utest_msg_g);
}
if(!bfound)
{
/* first time start up. nothing is stored in cfstore flash. check this is the case */
while(drv->Find(key_name_query, prev, next) == ARM_DRIVER_OK)
{
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: have found an entry in cfstore when none should be present", __func__);
TEST_ASSERT_MESSAGE(false, cfstore_flush_utest_msg_g);
}
/* no entries found, which is correct.
* store a value */
len = strlen(cfstore_flush_test_02_kv_data->value);
ret = cfstore_test_create(cfstore_flush_test_02_kv_data->key_name, cfstore_flush_test_02_kv_data->value, &len, &kdesc);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error:1: failed to write kv data (ret=%" PRId32 ").\r\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_flush_utest_msg_g);
/* flush to flash */
ret = drv->Flush();
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: failed to flush data to cfstore flash (ret=%" PRId32 ").\r\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_flush_utest_msg_g);
} else {
/*read the value, increment by 1 and write value back */
len = CFSTORE_KEY_NAME_MAX_LENGTH+1;
ret = cfstore_test_read(cfstore_flush_test_02_kv_data->key_name, value, &len);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: failed to read kv data (ret=%" PRId32 ").\r\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_flush_utest_msg_g);
/* increment value */
ivalue = atoi(value);
++ivalue;
snprintf(value, CFSTORE_KEY_NAME_MAX_LENGTH+1, "%d", (int) ivalue);
len = strlen(value);
ret = cfstore_test_write(cfstore_flush_test_02_kv_data->key_name, value, &len);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: failed to write kv data (ret=%" PRId32 ").\r\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_flush_utest_msg_g);
/* flush to flash */
ret = drv->Flush();
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_FLUSH_UTEST_MSG_BUF_SIZE, "%s:Error: failed to flush data to cfstore flash (ret=%" PRId32 ").\r\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_flush_utest_msg_g);
}
return CaseTimeout(100000);
}
control_t cfstore_flush2_test_01_end(const size_t call_count)
{
const ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
CFSTORE_FENTRYLOG("%s:entered:\r\n", __func__);
(void) call_count;
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Uninitialize() call failed.\n", __func__);
TEST_ASSERT_MESSAGE(drv->Uninitialize() >= ARM_DRIVER_OK, cfstore_flush_utest_msg_g);
return CaseNext;
}
/**
* @brief test to open(create) a very large value, write the data, close, then flush.
* for a N keys simultaneously.
*
* @return status code
* ARM_DRIVER_OK, the test passed successfully
* ret < ARM_DRIVER_OK, the test failed with the return code
* supplying more details
*/
static control_t cfstore_flush2_test_02(const size_t call_count)
{
(void) call_count;
//todo: implement test
CFSTORE_TEST_UTEST_MESSAGE(cfstore_flush_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Warn: Not implemented\n", __func__);
CFSTORE_LOG("%s: WARN: requires implementation\n", __func__);
TEST_ASSERT_MESSAGE(true, cfstore_flush_utest_msg_g);
return CaseNext;
}
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
// Call the default reporting function-
GREENTEA_SETUP(100, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
Case("CFSTORE_FLUSH2_test_00", cfstore_flush2_test_00),
Case("CFSTORE_FLUSH2_test_01_start", cfstore_flush2_test_01_start),
Case("CFSTORE_FLUSH2_test_01_mid", cfstore_flush2_test_01_mid),
Case("CFSTORE_FLUSH2_test_01_end", cfstore_flush2_test_01_end),
Case("CFSTORE_FLUSH2_test_02_start", cfstore_utest_default_start),
Case("CFSTORE_FLUSH2_test_02_end", cfstore_flush2_test_02),
};
// Declare your test specification with a custom setup handler
Specification specification(greentea_setup, cases);
#if defined CFSTORE_CONFIG_MBED_OS_VERSION && CFSTORE_CONFIG_MBED_OS_VERSION == 3
/* mbedosV3*/
void app_start(int argc __unused, char** argv __unused)
{
/* Run the test specification */
Harness::run(specification);
}
#endif /* CFSTORE_CONFIG_MBED_OS_VERSION == 3 */
#if defined CFSTORE_CONFIG_MBED_OS_VERSION && CFSTORE_CONFIG_MBED_OS_VERSION == 4
/* mbedosV3++*/
int main()
{
return !Harness::run(specification);
}
#endif /* CFSTORE_CONFIG_MBED_OS_VERSION == 4 */
#endif // __MBED__ && ! defined TOOLCHAIN_GCC_ARM

223
TESTS/cfstore/init/init.cpp Normal file
View File

@ -0,0 +1,223 @@
/** @file init.cpp
*
* mbed Microcontroller Library
* Copyright (c) 2006-2016 ARM Limited
*
* 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.
*
* Test cases to test initialization/uninitialization code.
*/
#if defined __MBED__ && ! defined TOOLCHAIN_GCC_ARM
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#ifdef TARGET_LIKE_FRDM_K64F_GCC
#include <mbed-drivers/mbed.h>
#endif
#include "cfstore_config.h"
#include <Driver_Common.h>
#include "cfstore_debug.h"
#include "cfstore_test.h"
#include <configuration-store/configuration_store.h>
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#ifdef YOTTA_CFG_CFSTORE_UVISOR
#include "uvisor-lib/uvisor-lib.h"
#include "cfstore_uvisor.h"
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
using namespace utest::v1;
static control_t cfstore_init_test_00(const size_t call_count)
{
(void) call_count;
printf("Not implemented for ARM toolchain\n");
return CaseNext;
}
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(100, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
/* 1 2 3 4 5 6 7 */
/* 1234567890123456789012345678901234567890123456789012345678901234567890 */
Case("INIT_test_00", cfstore_init_test_00),
};
/* Declare your test specification with a custom setup handler */
Specification specification(greentea_setup, cases);
int main()
{
return !Harness::run(specification);
}
#else
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#ifdef TARGET_LIKE_FRDM_K64F_GCC
#include <mbed-drivers/mbed.h>
#endif
//#include <flash-abstraction/Driver_Common.h>
#include <Driver_Common.h>
#include "cfstore_config.h"
#include "cfstore_test.h"
#include "cfstore_debug.h"
#include <configuration-store/configuration_store.h>
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#ifdef YOTTA_CFG_CONFIG_UVISOR
#include "uvisor-lib/uvisor-lib.h"
#endif /* YOTTA_CFG_CONFIG_UVISOR */
using namespace utest::v1;
static char cfstore_init_utest_msg_g[CFSTORE_UTEST_MSG_BUF_SIZE];
typedef struct cfstore_init_ctx_t
{
ARM_CFSTORE_CAPABILITIES caps;
} cfstore_init_ctx_t;
static cfstore_init_ctx_t cfstore_init_ctx_g;
extern ARM_CFSTORE_DRIVER cfstore_driver;
ARM_CFSTORE_DRIVER *cfstore_drv = &cfstore_driver;
/* report whether built/configured for flash sync or async mode */
static control_t cfstore_init_test_00(const size_t call_count)
{
(void) call_count;
CFSTORE_LOG("INITIALIZING: caps.asynchronous_ops=%lu\n", cfstore_driver.GetCapabilities().asynchronous_ops);
return CaseNext;
}
static void cfstore_init_test_01(cfstore_init_ctx_t* ctx)
{
int32_t ret;
(void) ctx;
CFSTORE_LOG("INITIALIZING%s", "\r\n");
ret = cfstore_drv->Initialize(NULL, NULL);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_init_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Initialize() should return ret >= 0 for async/synch modes(ret=%ld)\r\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_init_utest_msg_g);
CFSTORE_LOG("FLUSHING1%s", "\r\n");
ret = cfstore_drv->Flush();
CFSTORE_TEST_UTEST_MESSAGE(cfstore_init_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Flush() failed (ret=%ld)\r\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_init_utest_msg_g);
CFSTORE_LOG("UNINITIALIZING%s", "\r\n");
ret = cfstore_drv->Uninitialize();
CFSTORE_TEST_UTEST_MESSAGE(cfstore_init_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Uninitialize() should return ret >= 0 for synch mode(ret=%ld)\r\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_init_utest_msg_g);
CFSTORE_LOG("***************%s", "\r\n");
CFSTORE_LOG("*** SUCCESS ***%s", "\r\n");
CFSTORE_LOG("***************%s", "\r\n");
return;
}
static control_t cfstore_init_app_start(const size_t call_count)
{
cfstore_init_ctx_t* ctx = &cfstore_init_ctx_g;
(void) call_count;
/* initialise the context */
memset(ctx, 0, sizeof(cfstore_init_ctx_t));
ctx->caps = cfstore_drv->GetCapabilities();
CFSTORE_LOG("%s:INITIALIZING: caps.asynchronous_ops=%lu\n", __func__, ctx->caps.asynchronous_ops);
if(ctx->caps.asynchronous_ops == true){
/* This is a sync mode only test. If this test is not built for sync mode, then skip testing return true
* This means the test will conveniently pass when run in CI as part of async mode testing */
CFSTORE_LOG("*** Skipping test as binary built for flash journal async mode, and this test is sync-only%s", "\n");
return CaseNext;
}
cfstore_init_test_01(ctx);
return CaseNext;
}
#ifndef YOTTA_CONFIGURATION_STORE_INIT_VERSION_STRING
/* when built as Configuration-Store example, include greentea support otherwise omit */
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(100, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
/* 1 2 3 4 5 6 7 */
/* 1234567890123456789012345678901234567890123456789012345678901234567890 */
Case("INIT_test_00", cfstore_init_test_00),
Case("INIT_test_01_start", cfstore_init_app_start),
};
/* Declare your test specification with a custom setup handler */
Specification specification(greentea_setup, cases);
#if defined CFSTORE_CONFIG_MBED_OS_VERSION && CFSTORE_CONFIG_MBED_OS_VERSION == 3
/* mbedosV3*/
void app_start(int argc __unused, char** argv __unused)
{
/* Run the test specification */
Harness::run(specification);
}
#endif /* CFSTORE_CONFIG_MBED_OS_VERSION == 3 */
#if defined CFSTORE_CONFIG_MBED_OS_VERSION && CFSTORE_CONFIG_MBED_OS_VERSION == 4
/* mbedosV3++*/
int main()
{
return !Harness::run(specification);
}
#endif /* CFSTORE_CONFIG_MBED_OS_VERSION == 4 */
#else // YOTTA_CONFIGURATION_STORE_INIT_VERSION_STRING
// stand alone Configuration-Store-Example
void app_start(int argc __unused, char** argv __unused)
{
cfstore_init_app_start(0);
}
#endif // YOTTA_CONFIGURATION_STORE_INIT_VERSION_STRING
#endif // __MBED__ && ! defined TOOLCHAIN_GCC_ARM

460
TESTS/cfstore/misc/misc.cpp Normal file
View File

@ -0,0 +1,460 @@
/*
* @file misc.cpp
*
* mbed Microcontroller Library
* Copyright (c) 2006-2016 ARM Limited
*
* 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.
*
* Test cases for miscellaneious API drv->Xxx() functions.
*/
#if defined __MBED__ && ! defined TOOLCHAIN_GCC_ARM
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#ifdef TARGET_LIKE_FRDM_K64F_GCC
#include <mbed-drivers/mbed.h>
#endif
#include "cfstore_config.h"
#include <Driver_Common.h>
#include "cfstore_debug.h"
#include "cfstore_test.h"
#include <configuration-store/configuration_store.h>
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#ifdef YOTTA_CFG_CFSTORE_UVISOR
#include "uvisor-lib/uvisor-lib.h"
#include "cfstore_uvisor.h"
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
using namespace utest::v1;
static control_t cfstore_misc_test_00(const size_t call_count)
{
(void) call_count;
printf("Not implemented for ARM toolchain\n");
return CaseNext;
}
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(100, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
/* 1 2 3 4 5 6 7 */
/* 1234567890123456789012345678901234567890123456789012345678901234567890 */
Case("MISC_test_00", cfstore_misc_test_00),
};
/* Declare your test specification with a custom setup handler */
Specification specification(greentea_setup, cases);
int main()
{
return !Harness::run(specification);
}
#else
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#ifdef TARGET_LIKE_FRDM_K64F_GCC
#include <mbed-drivers/mbed.h>
#endif
#include "cfstore_config.h"
#include "cfstore_test.h"
#include "cfstore_debug.h"
#include <Driver_Common.h>
#include "cfstore_config.h"
#include <configuration-store/configuration_store.h>
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#include "cfstore_utest.h"
#ifdef YOTTA_CFG_CFSTORE_UVISOR
#include "uvisor-lib/uvisor-lib.h"
#include "cfstore_uvisor.h"
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
using namespace utest::v1;
static char cfstore_misc_utest_msg_g[CFSTORE_UTEST_MSG_BUF_SIZE];
#ifdef YOTTA_CFG_CFSTORE_UVISOR
/* Create the main box ACL list for the application.
* The main ACL gets inherited by all the other boxes
*/
CFSTORE_UVISOR_MAIN_ACL(cfstore_acl_uvisor_box_misc_g);
/* Enable uVisor. */
UVISOR_SET_MODE_ACL(UVISOR_ENABLED, cfstore_acl_uvisor_box_misc_g);
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
/* report whether built/configured for flash sync or async mode */
static control_t cfstore_misc_test_00(const size_t call_count)
{
(void) call_count;
CFSTORE_LOG("INITIALIZING: caps.asynchronous_ops=%lu\n", cfstore_driver.GetCapabilities().asynchronous_ops);
return CaseNext;
}
/** @brief basic PowerControl() test
*
* @return status code
* ARM_DRIVER_OK, the test passed successfully
* ret < ARM_DRIVER_OK, the test failed with the return code
* supplying more details
*/
static control_t cfstore_misc_test_00_start(const size_t call_count)
{
int32_t ret = ARM_DRIVER_ERROR;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
ARM_POWER_STATE state = ARM_POWER_OFF;
CFSTORE_FENTRYLOG("%s:entered\n", __func__);
(void) call_count;
/* try setting the power control state before initialised, which should fail */
ret = drv->PowerControl(state);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_misc_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Eror: PowerControl() call should have failed as CFSTORE not initialised, but the call succeeded\r\n", __func__);
TEST_ASSERT_MESSAGE(ret < ARM_DRIVER_OK, cfstore_misc_utest_msg_g);
ret = drv->Initialize(cfstore_utest_default_callback, NULL);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_misc_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to initialize CFSTORE (ret=%" PRId32 ")\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_misc_utest_msg_g);
return CaseTimeout(CFSTORE_UTEST_DEFAULT_TIMEOUT_MS);
}
static control_t cfstore_misc_test_00_end(const size_t call_count)
{
int32_t ret = ARM_DRIVER_ERROR;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
ARM_POWER_STATE state = ARM_POWER_OFF;
CFSTORE_FENTRYLOG("%s:entered\n", __func__);
(void) call_count;
while(state <= ARM_POWER_FULL)
{
ret = drv->PowerControl(state);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_misc_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: PowerControl() call failed\r\n", __func__);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_misc_utest_msg_g);
state = (ARM_POWER_STATE)((uint32_t) state + 1);
}
/*try invalid value which should fail*/
ret = drv->PowerControl((ARM_POWER_STATE ) 0xffffffff);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_misc_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:ERror: PowerControl() did not fail with bad value 0xffffffff (not as expected)\r\n", __func__);
TEST_ASSERT_MESSAGE(ret < ARM_DRIVER_OK, cfstore_misc_utest_msg_g);
ret = drv->Uninitialize();
CFSTORE_TEST_UTEST_MESSAGE(cfstore_misc_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Uninitialize() call failed.\n", __func__);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_misc_utest_msg_g);
return CaseNext;
}
/** @brief basic GetVersion() test
*
* @return status code
* ARM_DRIVER_OK, the test passed successfully
* ret < ARM_DRIVER_OK, the test failed with the return code
* supplying more details
*/
static control_t cfstore_misc_test_01(const size_t call_count)
{
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
ARM_DRIVER_VERSION version;
CFSTORE_FENTRYLOG("%s:entered\n", __func__);
(void) call_count;
memset(&version, 0, sizeof(version));
version = drv->GetVersion();
CFSTORE_TEST_UTEST_MESSAGE(cfstore_misc_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:GetVersion() failed to return correct API version.\r\n", __func__);
TEST_ASSERT_MESSAGE(version.api == ARM_CFSTORE_API_VERSION, cfstore_misc_utest_msg_g);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_misc_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:GetVersion() to return correct driver version.\r\n", __func__);
TEST_ASSERT_MESSAGE(version.drv == ARM_CFSTORE_DRV_VERSION, cfstore_misc_utest_msg_g);
return CaseNext;
}
/** @brief basic GetCapabilities() test
*
* @return status code
* ARM_DRIVER_OK, the test passed successfully
* ret < ARM_DRIVER_OK, the test failed with the return code
* supplying more details
*/
static control_t cfstore_misc_test_02(const size_t call_count)
{
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
ARM_CFSTORE_CAPABILITIES caps;
CFSTORE_FENTRYLOG("%s:entered\n", __func__);
(void) call_count;
memset(&caps, 0, sizeof(caps));
caps = drv->GetCapabilities();
//CFSTORE_TEST_UTEST_MESSAGE(cfstore_misc_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Capabilities() failed to return asynchronous_ops == false.\r\n", __func__);
//TEST_ASSERT_MESSAGE(caps.asynchronous_ops == false, cfstore_misc_utest_msg_g);
#ifdef YOTTA_CFG_CONFIG_HARDWARE_MTD_ASYNC_OPS
/* sync mode */
printf("%s:sync mode: caps.asynchronous_ops =%" PRIu32 "\n", __func__, caps.asynchronous_ops);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_misc_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: GetCapabilities() reported caps.asynchronous_ops != false but system built for sync operation.\r\n", __func__);
TEST_ASSERT_MESSAGE(caps.asynchronous_ops == false, cfstore_misc_utest_msg_g);
#else
/* async mode */
printf("%s:async mode: caps.asynchronous_ops =%" PRIu32 "\n", __func__, caps.asynchronous_ops);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_misc_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: GetCapabilities() reported caps.asynchronous_ops != true but system built for async operation.\r\n", __func__);
TEST_ASSERT_MESSAGE(caps.asynchronous_ops == true, cfstore_misc_utest_msg_g);
#endif
CFSTORE_TEST_UTEST_MESSAGE(cfstore_misc_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Capabilities() failed to return uvisor_support_enabled == false.\r\n", __func__);
TEST_ASSERT_MESSAGE(caps.uvisor_support_enabled == false, cfstore_misc_utest_msg_g);
return CaseNext;
}
/* KV data for test_03 */
static cfstore_kv_data_t cfstore_misc_test_03_kv_data[] = {
/* 1 2 3 4 5 6 7 */
/* 1234567890123456789012345678901234567890123456789012345678901234567890 */
{ "The.principles.of.least.action.in.quantum.mechanics", "DoctoralThesis"},
{ "Space.Time.Approach.to.Quantum.Electrodynamic", " PhysicalReview766)"},
{ "An.Operator.Calculus.Having.Applications.in.Quantum.Electrodynamics", "PhysicalReview84)"},
{ NULL, NULL},
};
/** @brief basic GetKeyName() test
*
* @return status code
* ARM_DRIVER_OK, the test passed successfully
* ret < ARM_DRIVER_OK, the test failed with the return code
* supplying more details
*/
static control_t cfstore_misc_test_03_end(const size_t call_count)
{
uint8_t key_name_len = 0;
char key_name_buf[CFSTORE_KEY_NAME_MAX_LENGTH+1];
int32_t ret = ARM_DRIVER_ERROR;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
cfstore_kv_data_t* node = NULL;
ARM_CFSTORE_HANDLE_INIT(hkey);
ARM_CFSTORE_FMODE flags;
CFSTORE_FENTRYLOG("%s:entered\r\n", __func__);
(void) call_count;
memset(key_name_buf, 0, CFSTORE_KEY_NAME_MAX_LENGTH+1);
/* dont set any flags to get default settings */
memset(&flags, 0, sizeof(flags));
ret = cfstore_test_create_table(cfstore_misc_test_03_kv_data);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_misc_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: unable to create keys from table.\r\n", __func__);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_misc_utest_msg_g);
node = cfstore_misc_test_03_kv_data;
while(node->key_name != NULL)
{
CFSTORE_DBGLOG("%s:About to open KV (key_name=\"%s\", value=\"%s\")\r\n", __func__, node->key_name, node->value);
ret = drv->Open(node->key_name, flags, hkey);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_misc_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Failed to open node (key_name=\"%s\", value=\"%s\")(ret=%" PRId32 ")\r\n", __func__, node->key_name, node->value, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_misc_utest_msg_g);
key_name_len = CFSTORE_KEY_NAME_MAX_LENGTH+1;
memset(key_name_buf, 0, key_name_len);
drv->GetKeyName(hkey, key_name_buf, &key_name_len);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_misc_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to GetKeyName() (key_name (expected)=\"%s\", key_name (returned)=\"%s\", value=\"%s\"), len return=%d, len expected=%d\r\n", __func__, node->key_name, key_name_buf, node->value, (int) key_name_len, (int) strlen(node->key_name));
TEST_ASSERT_MESSAGE(key_name_len == strlen(node->key_name)+1, cfstore_misc_utest_msg_g);
CFSTORE_LOG("GetKeyName() successfully reported key_name (key_name=\"%s\")\r\n", key_name_buf);
ret = drv->Close(hkey);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_misc_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Failed to close key (key_name=\"%s\", value=\"%s\")\r\n", __func__, node->key_name, node->value);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_misc_utest_msg_g);
node++;
}
cfstore_test_delete_all();
ret = drv->Uninitialize();
CFSTORE_TEST_UTEST_MESSAGE(cfstore_misc_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Uninitialize() call failed.\n", __func__);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_misc_utest_msg_g);
return CaseNext;
}
/** @brief basic GetValueLen() test
*
* @return status code
* ARM_DRIVER_OK, the test passed successfully
* ret < ARM_DRIVER_OK, the test failed with the return code
* supplying more details
*/
static control_t cfstore_misc_test_04_end(const size_t call_count)
{
int32_t ret = ARM_DRIVER_ERROR;
ARM_CFSTORE_SIZE len = 0;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
cfstore_kv_data_t* node = NULL;
ARM_CFSTORE_HANDLE_INIT(hkey);
ARM_CFSTORE_FMODE flags;
CFSTORE_FENTRYLOG("%s:entered\n", __func__);
(void) call_count;
/* dont set any flags to get default settings */
memset(&flags, 0, sizeof(flags));
ret = cfstore_test_create_table(cfstore_misc_test_03_kv_data);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_misc_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: unable to create keys from table.\r\n", __func__);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_misc_utest_msg_g);
node = cfstore_misc_test_03_kv_data;
while(node->key_name != NULL)
{
CFSTORE_DBGLOG("%s:About to open KV (key_name=\"%s\", value=\"%s\")\r\n", __func__, node->key_name, node->value);
ret = drv->Open(node->key_name, flags, hkey);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_misc_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Failed to open node (key_name=\"%s\", value=\"%s\")(ret=%d)\r\n", __func__, node->key_name, node->value, (int) ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_misc_utest_msg_g);
drv->GetValueLen(hkey, &len);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_misc_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Errro: GetValueLen() retrieve incorrect length of value blob(expected=%d, returned=%d)\r\n", __func__, (int) strlen(node->value), (int) len);
TEST_ASSERT_MESSAGE(len == strlen(node->value), cfstore_misc_utest_msg_g);
CFSTORE_LOG("GetValueLen() successfully reported correct value blob length%s", "\r\n");
ret = drv->Close(hkey);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_misc_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Failed to close key (key_name=\"%s\", value=\"%s\")\r\n", __func__, node->key_name, node->value);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_misc_utest_msg_g);
node++;
}
cfstore_test_delete_all();
ret = drv->Uninitialize();
CFSTORE_TEST_UTEST_MESSAGE(cfstore_misc_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Uninitialize() call failed.\n", __func__);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_misc_utest_msg_g);
return CaseNext;
}
/** @brief basic GetStatus() test
*
* @return status code
* ARM_DRIVER_OK, the test passed successfully
* ret < ARM_DRIVER_OK, the test failed with the return code
* supplying more details
*/
static control_t cfstore_misc_test_05_start(const size_t call_count)
{
int32_t ret = ARM_DRIVER_ERROR;
ARM_CFSTORE_STATUS status;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
CFSTORE_FENTRYLOG("%s:entered\n", __func__);
(void) call_count;
status = drv->GetStatus();
CFSTORE_TEST_UTEST_MESSAGE(cfstore_misc_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: GetStatus() before initialisation should have reported error, but reported no error.\r\n", __func__);
TEST_ASSERT_MESSAGE(status.error == true, cfstore_misc_utest_msg_g);
ret = drv->Initialize(cfstore_utest_default_callback, NULL);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_misc_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to initialize CFSTORE (ret=%" PRId32 ")\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_misc_utest_msg_g);
return CaseTimeout(CFSTORE_UTEST_DEFAULT_TIMEOUT_MS);
}
static control_t cfstore_misc_test_05_end(const size_t call_count)
{
int32_t ret = ARM_DRIVER_ERROR;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
ARM_CFSTORE_STATUS status;
CFSTORE_FENTRYLOG("%s:entered\n", __func__);
(void) call_count;
status = drv->GetStatus();
CFSTORE_TEST_UTEST_MESSAGE(cfstore_misc_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: GetStatus() but reported error.\r\n", __func__);
TEST_ASSERT_MESSAGE(status.error == false, cfstore_misc_utest_msg_g);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_misc_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: GetStatus() reported operation in progress.\r\n", __func__);
TEST_ASSERT_MESSAGE(status.in_progress == false, cfstore_misc_utest_msg_g);
ret = drv->Uninitialize();
CFSTORE_TEST_UTEST_MESSAGE(cfstore_misc_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Uninitialize() call failed.\n", __func__);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_misc_utest_msg_g);
return CaseNext;
}
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(200, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
/* 1 2 3 4 5 6 7 */
/* 1234567890123456789012345678901234567890123456789012345678901234567890 */
Case("MISC_test_00", cfstore_misc_test_00),
Case("MISC_test_00_start", cfstore_misc_test_00_start),
Case("MISC_test_00_end", cfstore_misc_test_00_end),
Case("MISC_test_01", cfstore_misc_test_01),
Case("MISC_test_02", cfstore_misc_test_02),
Case("MISC_test_03_start", cfstore_utest_default_start),
Case("MISC_test_03_end", cfstore_misc_test_03_end),
Case("MISC_test_04_start", cfstore_utest_default_start),
Case("MISC_test_04_end", cfstore_misc_test_04_end),
Case("MISC_test_05_start", cfstore_misc_test_05_start),
Case("MISC_test_05_end", cfstore_misc_test_05_end),
};
/* Declare your test specification with a custom setup handler */
Specification specification(greentea_setup, cases);
#if defined CFSTORE_CONFIG_MBED_OS_VERSION && CFSTORE_CONFIG_MBED_OS_VERSION == 3
/* mbedosV3*/
void app_start(int argc __unused, char** argv __unused)
{
/* Run the test specification */
Harness::run(specification);
}
#endif /* CFSTORE_CONFIG_MBED_OS_VERSION == 3 */
#if defined CFSTORE_CONFIG_MBED_OS_VERSION && CFSTORE_CONFIG_MBED_OS_VERSION == 4
/* mbedosV3++*/
int main()
{
return !Harness::run(specification);
}
#endif /* CFSTORE_CONFIG_MBED_OS_VERSION == 4 */
#endif // __MBED__ && ! defined TOOLCHAIN_GCC_ARM

702
TESTS/cfstore/open/open.cpp Normal file
View File

@ -0,0 +1,702 @@
/*
* @file open.cpp
*
* mbed Microcontroller Library
* Copyright (c) 2006-2016 ARM Limited
*
* 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.
*
* Test cases to open KVs in the CFSTORE using the drv->Open() interface.
*/
#if defined __MBED__ && ! defined TOOLCHAIN_GCC_ARM
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#ifdef TARGET_LIKE_FRDM_K64F_GCC
#include <mbed-drivers/mbed.h>
#endif
#include "cfstore_config.h"
#include <Driver_Common.h>
#include "cfstore_debug.h"
#include "cfstore_test.h"
#include <configuration-store/configuration_store.h>
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#ifdef YOTTA_CFG_CFSTORE_UVISOR
#include "uvisor-lib/uvisor-lib.h"
#include "cfstore_uvisor.h"
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
using namespace utest::v1;
static control_t cfstore_open_test_00(const size_t call_count)
{
(void) call_count;
printf("Not implemented for ARM toolchain\n");
return CaseNext;
}
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(100, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
/* 1 2 3 4 5 6 7 */
/* 1234567890123456789012345678901234567890123456789012345678901234567890 */
Case("OPEN_test_00", cfstore_open_test_00),
};
/* Declare your test specification with a custom setup handler */
Specification specification(greentea_setup, cases);
int main()
{
return !Harness::run(specification);
}
#else
#include <stdio.h>
#include <string.h>
#include <stdlib.h> /*rand()*/
#include <inttypes.h>
#ifdef TARGET_LIKE_FRDM_K64F_GCC
#include <mbed-drivers/mbed.h>
#endif
#include "cfstore_config.h"
#include "cfstore_test.h"
#include "cfstore_debug.h"
//#include <flash-abstraction/Driver_Common.h>
#include <Driver_Common.h>
#include <configuration-store/configuration_store.h>
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#include "cfstore_utest.h"
#ifdef YOTTA_CFG_CFSTORE_UVISOR
#include "uvisor-lib/uvisor-lib.h"
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
using namespace utest::v1;
static char cfstore_open_utest_msg_g[CFSTORE_UTEST_MSG_BUF_SIZE];
/* Configure secure box. */
#ifdef YOTTA_CFG_CFSTORE_UVISOR
UVISOR_BOX_NAMESPACE("com.arm.mbed.cfstore.test.open.box1");
UVISOR_BOX_CONFIG(cfstore_open_box1, UVISOR_BOX_STACK_SIZE);
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
#ifdef CFSTORE_DEBUG
#define CFSTORE_OPEN_GREENTEA_TIMEOUT_S 3000
#else
#define CFSTORE_OPEN_GREENTEA_TIMEOUT_S 1000
#endif
/* support functions */
/*
* open tests that focus on testing cfstore_open()
* cfstore_handle_t cfstore_open(const char* key_name, char* data, ARM_CFSTORE_SIZE* len, cfstore_key_desc_t* kdesc)
*/
/* KV data for test_01 */
static cfstore_kv_data_t cfstore_open_test_01_kv_data[] = {
{ "yotta.hello-world.animal{wobbly-dog}{foot}frontLeft", "missing"},
{ NULL, NULL},
};
/* report whether built/configured for flash sync or async mode */
static control_t cfstore_open_test_00(const size_t call_count)
{
(void) call_count;
CFSTORE_LOG("INITIALIZING: caps.asynchronous_ops=%lu\n", cfstore_driver.GetCapabilities().asynchronous_ops);
return CaseNext;
}
/** @brief
* Basic open test which does the following:
* - creates KV with default rw perms and writes some data to the value blob.
* - closes the newly created KV.
* - opens the KV with the default permissions (r-only)
* - reads the KV data and checks its the same as the previously created data.
* - closes the opened key
*
* @return status code
* ARM_DRIVER_OK, the test passed successfully
* ret < ARM_DRIVER_OK, the test failed with the return code
* supplying more details
*/
static control_t cfstore_open_test_01_end(const size_t call_count)
{
char* read_buf;
int32_t ret = ARM_DRIVER_ERROR;
ARM_CFSTORE_SIZE len = 0;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
ARM_CFSTORE_KEYDESC kdesc;
ARM_CFSTORE_HANDLE_INIT(hkey);
cfstore_kv_data_t *node;
ARM_CFSTORE_FMODE flags;
CFSTORE_DBGLOG("%s:entered\n", __func__);
(void) call_count;
node = cfstore_open_test_01_kv_data;
memset(&kdesc, 0, sizeof(kdesc));
memset(&flags, 0, sizeof(flags));
kdesc.drl = ARM_RETENTION_WHILE_DEVICE_ACTIVE;
CFSTORE_DBGLOG("%s:About to create new node (key_name=\"%s\", value=\"%s\")\n", __func__, node->key_name, node->value);
ret = drv->Create(node->key_name, strlen(node->value), &kdesc, hkey);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_open_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create node (key_name=\"%s\", value=\"%s\")(ret=%" PRId32 ")\n", __func__, node->key_name, node->value, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_open_utest_msg_g);
CFSTORE_DBGLOG("%s:length of KV=%d (key_name=\"%s\", value=\"%s\")\n", __func__, (int) len, node->key_name, node->value);
len = strlen(node->value);
ret = drv->Write(hkey, (char*) node->value, &len);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_open_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to write key (key_name=\"%s\", value=\"%s\")(ret=%" PRId32 ")\n", __func__, node->key_name, node->value, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_open_utest_msg_g);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_open_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to write full value data (key_name=\"%s\", value=\"%s\"), len=%d, (ret=%" PRId32 ")\n", __func__, node->key_name, node->value, (int) len, ret);
TEST_ASSERT_MESSAGE(len == strlen(node->value), cfstore_open_utest_msg_g);
printf("Created KV successfully (key_name=\"%s\", value=\"%s\")\n", node->key_name, node->value);
ret = drv->Close(hkey);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_open_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to close handle (ret=%" PRId32 ")\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_open_utest_msg_g);
/* now open the newly created key */
ret = drv->Open(node->key_name, flags, hkey);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_open_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to open node (key_name=\"%s\", value=\"%s\")(ret=%" PRId32 ")\n", __func__, node->key_name, node->value, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_open_utest_msg_g);
len = strlen(node->value) + 1;
read_buf = (char*) malloc(len);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_open_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to allocated read buffer \n", __func__);
TEST_ASSERT_MESSAGE(read_buf != NULL, cfstore_open_utest_msg_g);
printf("Opened KV successfully (key_name=\"%s\", value=\"%s\")\n", node->key_name, node->value);
memset(read_buf, 0, len);
ret = drv->Read(hkey, read_buf, &len);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_open_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to write key (key_name=\"%s\", value=\"%s\")\n", __func__, node->key_name, node->value);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_open_utest_msg_g);
/* check read data is as expected */
CFSTORE_TEST_UTEST_MESSAGE(cfstore_open_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: read value data (%s) != KV value data (key_name=\"%s\", value=\"%s\")\n", __func__, read_buf, node->key_name, node->value);
TEST_ASSERT_MESSAGE(strncmp(read_buf, node->value, strlen(node->value)) == 0, cfstore_open_utest_msg_g);
if(read_buf){
free(read_buf);
}
CFSTORE_TEST_UTEST_MESSAGE(cfstore_open_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Close() call failed.\n", __func__);
TEST_ASSERT_MESSAGE(drv->Close(hkey) >= ARM_DRIVER_OK, cfstore_open_utest_msg_g);
ret = drv->Uninitialize();
CFSTORE_TEST_UTEST_MESSAGE(cfstore_open_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Uninitialize() call failed.\n", __func__);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_open_utest_msg_g);
return CaseNext;
}
static cfstore_kv_data_t cfstore_open_test_02_data[] = {
CFSTORE_INIT_1_TABLE_MID_NODE,
{ NULL, NULL},
};
/**
* @brief test to open() a pre-existing key and try to write it, which should fail
* as by default pre-existing keys are opened read-only
*
* Basic open test which does the following:
* - creates KV with default rw perms and writes some data to the value blob.
* - closes the newly created KV.
* - opens the KV with the default permissions (read-only)
* - tries to write the KV data which should fail because KV was not opened with write flag set.
* - closes the opened key
*
* @return status code
* ARM_DRIVER_OK, the test passed successfully
* ret < ARM_DRIVER_OK, the test failed with the return code
* supplying more details
*/
static control_t cfstore_open_test_02_end(const size_t call_count)
{
int32_t ret = ARM_DRIVER_ERROR;
ARM_CFSTORE_SIZE len = 0;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
ARM_CFSTORE_KEYDESC kdesc;
ARM_CFSTORE_HANDLE_INIT(hkey);
ARM_CFSTORE_FMODE flags;
CFSTORE_FENTRYLOG("%s:entered\n", __func__);
(void) call_count;
memset(&kdesc, 0, sizeof(kdesc));
/* dont set any flags to get default settings */
memset(&flags, 0, sizeof(flags));
kdesc.drl = ARM_RETENTION_WHILE_DEVICE_ACTIVE;
len = strlen(cfstore_open_test_02_data[0].value);
ret = cfstore_test_create(cfstore_open_test_02_data[0].key_name, (char*) cfstore_open_test_02_data[0].value, &len, &kdesc);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_open_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create KV in store (ret=%" PRId32 ").\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_open_utest_msg_g);
/* by default, owner of key opens with read-only permissions*/
ret = drv->Open(cfstore_open_test_02_data[0].key_name, flags, hkey);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_open_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to open node (key_name=\"%s\")(ret=%" PRId32 ")\n", __func__, cfstore_open_test_02_data[0].key_name, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_open_utest_msg_g);
len = strlen(cfstore_open_test_02_data[0].value);
ret = drv->Write(hkey, cfstore_open_test_02_data[0].value, &len);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_open_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: call to Write() succeeded when should have failed (key_name=\"%s\")(ret=%" PRId32 ").\n", __func__, cfstore_open_test_02_data[0].key_name, ret);
TEST_ASSERT_MESSAGE(ret == ARM_CFSTORE_DRIVER_ERROR_KEY_READ_ONLY, cfstore_open_utest_msg_g);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_open_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Close() call failed.\n", __func__);
TEST_ASSERT_MESSAGE(drv->Close(hkey) >= ARM_DRIVER_OK, cfstore_open_utest_msg_g);
ret = drv->Uninitialize();
CFSTORE_TEST_UTEST_MESSAGE(cfstore_open_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Uninitialize() call failed.\n", __func__);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_open_utest_msg_g);
return CaseNext;
}
/**
* @brief test to open() a pre-existing key and try to write it, which should succeed
* because the key was opened read-write permissions explicitly
*
* Basic open test which does the following:
* - creates KV with default rw perms and writes some data to the value blob.
* - closes the newly created KV.
* - opens the KV with the rw permissions (non default)
* - tries to write the KV data which should succeeds because KV was opened with write flag set.
* - closes the opened key
*
* @return status code
* ARM_DRIVER_OK, the test passed successfully
* ret < ARM_DRIVER_OK, the test failed with the return code
* supplying more details
*/
static control_t cfstore_open_test_03_end(const size_t call_count)
{
int32_t ret = ARM_DRIVER_ERROR;
ARM_CFSTORE_SIZE len = 0;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
ARM_CFSTORE_KEYDESC kdesc;
ARM_CFSTORE_HANDLE_INIT(hkey);
ARM_CFSTORE_FMODE flags;
CFSTORE_FENTRYLOG("%s:entered\n", __func__);
(void) call_count;
memset(&kdesc, 0, sizeof(kdesc));
/* dont set any flags to get default settings */
memset(&flags, 0, sizeof(flags));
kdesc.drl = ARM_RETENTION_WHILE_DEVICE_ACTIVE;
len = strlen(cfstore_open_test_02_data[0].value);
ret = cfstore_test_create(cfstore_open_test_02_data[0].key_name, (char*) cfstore_open_test_02_data[0].value, &len, &kdesc);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_open_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create KV in store (ret=%" PRId32 ").\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_open_utest_msg_g);
/* opens with read-write permissions*/
flags.read = true;
flags.write = true;
ret = drv->Open(cfstore_open_test_02_data[0].key_name, flags, hkey);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_open_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to open node (key_name=\"%s\")(ret=%" PRId32 ")\n", __func__, cfstore_open_test_02_data[0].key_name, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_open_utest_msg_g);
len = strlen(cfstore_open_test_02_data[0].value);
ret = drv->Write(hkey, cfstore_open_test_02_data[0].value, &len);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_open_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: call to Write() failed when should have succeeded (key_name=\"%s\")(ret=%" PRId32 ").\n", __func__, cfstore_open_test_02_data[0].key_name, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_open_utest_msg_g);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_open_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Close() call failed.\n", __func__);
TEST_ASSERT_MESSAGE(drv->Close(hkey) >= ARM_DRIVER_OK, cfstore_open_utest_msg_g);
ret = drv->Uninitialize();
CFSTORE_TEST_UTEST_MESSAGE(cfstore_open_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Uninitialize() call failed.\n", __func__);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_open_utest_msg_g);
return CaseNext;
}
/** @brief test to call cfstore_open() with a key_name string that exceeds
* the maximum length
*
* @return status code
* CFSTORE_ERR_SUCCESS, the test passed successfully
* CFSTORE_ERR_FAILED, the test failed
*
*/
static control_t cfstore_open_test_04_end(const size_t call_count)
{
char kv_name_good[CFSTORE_KEY_NAME_MAX_LENGTH+1]; /* extra char for terminating null */
char kv_name_bad[CFSTORE_KEY_NAME_MAX_LENGTH+2];
int32_t ret = ARM_DRIVER_ERROR;
ARM_CFSTORE_SIZE len = 0;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
ARM_CFSTORE_KEYDESC kdesc;
ARM_CFSTORE_FMODE flags;
CFSTORE_FENTRYLOG("%s:entered\n", __func__);
(void) call_count;
memset(kv_name_good, 0, CFSTORE_KEY_NAME_MAX_LENGTH+1);
memset(kv_name_bad, 0, CFSTORE_KEY_NAME_MAX_LENGTH+2);
memset(&kdesc, 0, sizeof(kdesc));
/* dont set any flags to get default settings */
memset(&flags, 0, sizeof(flags));
len = CFSTORE_KEY_NAME_MAX_LENGTH;
ret = cfstore_test_kv_name_gen(kv_name_good, len);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_open_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: unable to generate kv_name_good.\n", __func__);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK , cfstore_open_utest_msg_g);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_open_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: kv_name_good is not the correct length (len=%d, expected=%d).\n", __func__, (int) strlen(kv_name_good), (int) len);
TEST_ASSERT_MESSAGE(strlen(kv_name_good) == CFSTORE_KEY_NAME_MAX_LENGTH, cfstore_open_utest_msg_g);
ret = cfstore_test_create(kv_name_good, kv_name_good, &len, &kdesc);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_open_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create KV in store for kv_name_good(ret=%" PRId32 ").\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_open_utest_msg_g);
len = CFSTORE_KEY_NAME_MAX_LENGTH+1;
ret = cfstore_test_kv_name_gen(kv_name_bad, len);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_open_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: unable to generate kv_name_bad.\n", __func__);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK , cfstore_open_utest_msg_g);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_open_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: kv_name_bad is not the correct length (len=%d, expected=%d).\n", __func__, (int) strlen(kv_name_bad), (int) len);
TEST_ASSERT_MESSAGE(strlen(kv_name_bad) == CFSTORE_KEY_NAME_MAX_LENGTH+1, cfstore_open_utest_msg_g);
memset(&kdesc, 0, sizeof(kdesc));
ret = cfstore_test_create(kv_name_bad, kv_name_bad, &len, &kdesc);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_open_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: created KV in store for kv_name_bad when should have failed(ret=%" PRId32 ").\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret < ARM_DRIVER_OK, cfstore_open_utest_msg_g);
ret = drv->Uninitialize();
CFSTORE_TEST_UTEST_MESSAGE(cfstore_open_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Uninitialize() call failed.\n", __func__);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_open_utest_msg_g);
return CaseNext;
}
typedef struct cfstore_open_kv_name_ascii_node {
uint32_t code;
uint32_t f_allowed : 1;
} cfstore_open_kv_name_ascii_node;
static const uint32_t cfstore_open_kv_name_ascii_table_code_sentinel_g = 256;
/*@brief table recording ascii character codes permitted in kv names */
static cfstore_open_kv_name_ascii_node cfstore_open_kv_name_ascii_table[] =
{
{0, false}, /* codes 0-44 not allowed */
{45, true}, /* codes 45-46 == [-.] allowed */
{47, false}, /* code 47 not allowed */
{48, true}, /* codes 48-57 not allowed */
{58, false}, /* codes 46-64 not allowed */
{64, true}, /* codes 64-91 allowed [@A-Z] */
{91, false}, /* code 91-96 not allowed */
{95, true}, /* code 95 allowed '_' */
{96, false}, /* codes 96 not allowed */
{97, true}, /* codes 65-90 allowed [A-Z] and {*/
{123, false}, /* codes 123 '}' not allowed on its own*/
{124, false}, /* codes 124 not allowed */
{125, false}, /* code 125 '}' not allowed on its own*/
{126, false}, /* codes 126-255 not allowed */
{cfstore_open_kv_name_ascii_table_code_sentinel_g, false}, /* sentinel */
};
enum cfstore_open_kv_name_pos {
cfstore_open_kv_name_pos_start = 0x0,
cfstore_open_kv_name_pos_mid,
cfstore_open_kv_name_pos_end,
cfstore_open_kv_name_pos_max
};
/** @brief test to call cfstore_open() with key_name that in includes
* illegal characters
* - the character(s) can be at the beginning of the key_name
* - the character(s) can be at the end of the key_name
* - the character(s) can be somewhere within the key_name string
* - a max-length string of random characters (legal and illegal)
* - a max-length string of random illegal characters only
*
* @return status code
* ARM_DRIVER_OK, the test passed successfully
* ret < ARM_DRIVER_OK, the test failed with the return code
* supplying more details
*/
static control_t cfstore_open_test_05_end(const size_t call_count)
{
bool f_allowed = false;
const char* pos_str = NULL;
char kv_name[CFSTORE_KEY_NAME_MAX_LENGTH+1]; /* extra char for terminating null */
uint32_t j = 0;
int32_t ret = ARM_DRIVER_OK;
size_t name_len = CFSTORE_KEY_NAME_MAX_LENGTH;
ARM_CFSTORE_KEYDESC kdesc;
cfstore_open_kv_name_ascii_node* node = NULL;
uint32_t pos;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
CFSTORE_FENTRYLOG("%s:entered\n", __func__);
(void) call_count;
/* create bad keyname strings with invalid character code at start of keyname */
node = cfstore_open_kv_name_ascii_table;
while(node->code != cfstore_open_kv_name_ascii_table_code_sentinel_g)
{
/* loop over range */
for(j = node->code; j < (node+1)->code; j++)
{
/* set the start, mid, last character of the name to the test char code */
for(pos = (uint32_t) cfstore_open_kv_name_pos_start; pos < (uint32_t) cfstore_open_kv_name_pos_max; pos++)
{
name_len = CFSTORE_KEY_NAME_MAX_LENGTH;
memset(kv_name, 0, CFSTORE_KEY_NAME_MAX_LENGTH+1);
memset(&kdesc, 0, sizeof(kdesc));
kdesc.drl = ARM_RETENTION_WHILE_DEVICE_ACTIVE;
ret = cfstore_test_kv_name_gen(kv_name, name_len);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_open_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: unable to generate kv_name.\n", __func__);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK , cfstore_open_utest_msg_g);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_open_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: kv_name incorrect length (len=%d, expected= %d).\n", __func__, (int) strlen(kv_name), (int) name_len);
TEST_ASSERT_MESSAGE(strlen(kv_name) == name_len, cfstore_open_utest_msg_g);
/* overwrite a char at the pos start, mid, end of the kv_name with an ascii char code (both illegal and legal)*/
switch(pos)
{
case cfstore_open_kv_name_pos_start:
kv_name[0] = (char) j;
pos_str = "start";
break;
case cfstore_open_kv_name_pos_mid:
/* create bad keyname strings with invalid character code in the middle of keyname */
kv_name[name_len/2] = (char) j;
pos_str = "middle";
break;
case cfstore_open_kv_name_pos_end:
/* create bad keyname strings with invalid character code at end of keyname */
kv_name[name_len-1] = (char) j;
pos_str = "end";
break;
default:
CFSTORE_TEST_UTEST_MESSAGE(cfstore_open_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: unexpected value of pos (pos=%d).\n", __func__, (int) pos);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_open_utest_msg_g);
break;
}
ret = cfstore_test_create(kv_name, kv_name, &name_len, &kdesc);
/* special cases */
switch(j)
{
case 0 :
case 46 :
switch(pos)
{
/* for code = 0 (null terminator). permitted at mid and end of string */
/* for code = 46 ('.'). permitted at mid and end of string but not at start */
case cfstore_open_kv_name_pos_start:
f_allowed = false;
break;
case cfstore_open_kv_name_pos_mid:
case cfstore_open_kv_name_pos_end:
default:
f_allowed = true;
break;
}
break;
default:
f_allowed = node->f_allowed;
break;
}
if(f_allowed == true)
{
CFSTORE_TEST_UTEST_MESSAGE(cfstore_open_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create KV in store when kv_name contains valid characters (code=%" PRId32 ", ret=%" PRId32 ").\n", __func__, j, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_open_utest_msg_g);
CFSTORE_LOG("Successfully created a KV with valid keyname containing ascii character code %" PRIu32 " (%c) at the %s of the keyname.\n", j, (int) j, pos_str);
ret = cfstore_test_delete(kv_name);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_open_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to delete KV previously created (code=%" PRId32 ", ret=%" PRId32 ").\n", __func__, j, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_open_utest_msg_g);
}
else
{ /*node->f_allowed == false => not allowed to create kv name with ascii code */
CFSTORE_TEST_UTEST_MESSAGE(cfstore_open_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: created KV in store when kv_name contains an invalid character (code=%" PRId32 ", ret=%" PRId32 ").\n", __func__, j, ret);
TEST_ASSERT_MESSAGE(ret < ARM_DRIVER_OK, cfstore_open_utest_msg_g);
CFSTORE_LOG("Successfully failed to create a KV with an invalid keyname containing ascii character code %" PRId32 " at the %s of the keyname.\n", j, pos_str);
}
}
}
node++;
}
CFSTORE_TEST_UTEST_MESSAGE(cfstore_open_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Uninitialize() call failed.\n", __func__);
TEST_ASSERT_MESSAGE(drv->Uninitialize() >= ARM_DRIVER_OK, cfstore_open_utest_msg_g);
return CaseNext;
}
static const char cfstore_open_ascii_illegal_buf_g[] = "!\"<EFBFBD>$%&'()*+,./:;<=>?@[\\]^_`{|}~"; /* 31 chars */
/** @brief test to call cfstore_open() with key_name that in includes
* illegal characters
* - a max-length string of random illegal characters only
*
* @return status code
* ARM_DRIVER_OK, the test passed successfully
* ret < ARM_DRIVER_OK, the test failed with the return code
* supplying more details
*/
static control_t cfstore_open_test_06_end(const size_t call_count)
{
char kv_name[CFSTORE_KEY_NAME_MAX_LENGTH+1]; /* extra char for terminating null */
size_t i = 0;
uint32_t pos = 0;
int32_t ret = ARM_DRIVER_OK;
size_t name_len = CFSTORE_KEY_NAME_MAX_LENGTH;
ARM_CFSTORE_KEYDESC kdesc;
size_t buf_data_max = 0;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
CFSTORE_FENTRYLOG("%s:entered\n", __func__);
(void) call_count;
/* create bad keyname strings with invalid character code at start of keyname */
buf_data_max = strlen(cfstore_open_ascii_illegal_buf_g);
name_len = CFSTORE_KEY_NAME_MAX_LENGTH;
memset(kv_name, 0, CFSTORE_KEY_NAME_MAX_LENGTH+1);
kdesc.drl = ARM_RETENTION_WHILE_DEVICE_ACTIVE;
/* generate a kv name of illegal chars*/
for(i = 0; i < name_len; i++)
{
pos = rand() % (buf_data_max+1);
kv_name[i] = cfstore_open_ascii_illegal_buf_g[pos];
}
ret = cfstore_test_create(kv_name, kv_name, &name_len, &kdesc);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_open_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: created KV in store when kv_name contains invalid characters (ret=%" PRId32 ").\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret < ARM_DRIVER_OK, cfstore_open_utest_msg_g);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_open_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Uninitialize() call failed.\n", __func__);
TEST_ASSERT_MESSAGE(drv->Uninitialize() >= ARM_DRIVER_OK, cfstore_open_utest_msg_g);
return CaseNext;
}
/** @brief test to call cfstore_open() with key_name that in includes
* illegal characters
* - a max-length string of random characters (legal and illegal)
*
* @return status code
* ARM_DRIVER_OK, the test passed successfully
* ret < ARM_DRIVER_OK, the test failed with the return code
* supplying more details
*/
static control_t cfstore_open_test_07_end(const size_t call_count)
{
char kv_name[CFSTORE_KEY_NAME_MAX_LENGTH+1]; /* extra char for terminating null */
size_t i = 0;
int32_t ret = ARM_DRIVER_OK;
size_t name_len = CFSTORE_KEY_NAME_MAX_LENGTH;
ARM_CFSTORE_KEYDESC kdesc;
size_t buf_data_max = 0;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
CFSTORE_FENTRYLOG("%s:entered\n", __func__);
(void) call_count;
/* create bad keyname strings with invalid character code at start of keyname */
buf_data_max = strlen(cfstore_open_ascii_illegal_buf_g);
name_len = CFSTORE_KEY_NAME_MAX_LENGTH;
memset(kv_name, 0, CFSTORE_KEY_NAME_MAX_LENGTH+1);
kdesc.drl = ARM_RETENTION_WHILE_DEVICE_ACTIVE;
ret = cfstore_test_kv_name_gen(kv_name, name_len);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_open_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: unable to generate kv_name.\n", __func__);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK , cfstore_open_utest_msg_g);
/* pepper the illegal chars across the string*/
for(i++; i < buf_data_max; i++){
kv_name[rand() % (name_len+1)] = cfstore_open_ascii_illegal_buf_g[i];
}
ret = cfstore_test_create(kv_name, kv_name, &name_len, &kdesc);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_open_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: created KV in store when kv_name contains invalid characters (ret=%" PRId32 ").\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret < ARM_DRIVER_OK, cfstore_open_utest_msg_g);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_open_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Uninitialize() call failed.\n", __func__);
TEST_ASSERT_MESSAGE(drv->Uninitialize() >= ARM_DRIVER_OK, cfstore_open_utest_msg_g);
return CaseNext;
}
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(CFSTORE_OPEN_GREENTEA_TIMEOUT_S, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
/* 1 2 3 4 5 6 7 */
/* 1234567890123456789012345678901234567890123456789012345678901234567890 */
Case("OPEN_test_00", cfstore_open_test_00),
Case("OPEN_test_01_start", cfstore_utest_default_start),
Case("OPEN_test_01_end", cfstore_open_test_01_end),
Case("OPEN_test_02_start", cfstore_utest_default_start),
Case("OPEN_test_02_end", cfstore_open_test_02_end),
Case("OPEN_test_03_start", cfstore_utest_default_start),
Case("OPEN_test_03_end", cfstore_open_test_03_end),
Case("OPEN_test_04_start", cfstore_utest_default_start),
Case("OPEN_test_04_end", cfstore_open_test_04_end),
Case("OPEN_test_05_start", cfstore_utest_default_start),
Case("OPEN_test_05_end", cfstore_open_test_05_end),
Case("OPEN_test_06_start", cfstore_utest_default_start),
Case("OPEN_test_06_end", cfstore_open_test_06_end),
Case("OPEN_test_07_start", cfstore_utest_default_start),
Case("OPEN_test_07_end", cfstore_open_test_07_end),
};
/* Declare your test specification with a custom setup handler */
Specification specification(greentea_setup, cases);
#if defined CFSTORE_CONFIG_MBED_OS_VERSION && CFSTORE_CONFIG_MBED_OS_VERSION == 3
/* mbedosV3*/
void app_start(int argc __unused, char** argv __unused)
{
/* Run the test specification */
Harness::run(specification);
}
#endif /* CFSTORE_CONFIG_MBED_OS_VERSION == 3 */
#if defined CFSTORE_CONFIG_MBED_OS_VERSION && CFSTORE_CONFIG_MBED_OS_VERSION == 4
/* mbedosV3++*/
int main()
{
return !Harness::run(specification);
}
#endif /* CFSTORE_CONFIG_MBED_OS_VERSION == 4 */
#endif // __MBED__ && ! defined TOOLCHAIN_GCC_ARM

265
TESTS/cfstore/read/read.cpp Normal file
View File

@ -0,0 +1,265 @@
/** @file read.cpp
*
* mbed Microcontroller Library
* Copyright (c) 2006-2016 ARM Limited
*
* 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.
*
* Test cases to read KVs in the CFSTORE using the drv->Read() API call.
*/
#if defined __MBED__ && ! defined TOOLCHAIN_GCC_ARM
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#ifdef TARGET_LIKE_FRDM_K64F_GCC
#include <mbed-drivers/mbed.h>
#endif
#include "cfstore_config.h"
#include <Driver_Common.h>
#include "cfstore_debug.h"
#include "cfstore_test.h"
#include <configuration-store/configuration_store.h>
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#ifdef YOTTA_CFG_CFSTORE_UVISOR
#include "uvisor-lib/uvisor-lib.h"
#include "cfstore_uvisor.h"
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
using namespace utest::v1;
static control_t cfstore_read_test_00(const size_t call_count)
{
(void) call_count;
printf("Not implemented for ARM toolchain\n");
return CaseNext;
}
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(100, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
/* 1 2 3 4 5 6 7 */
/* 1234567890123456789012345678901234567890123456789012345678901234567890 */
Case("READ_test_00", cfstore_read_test_00),
};
/* Declare your test specification with a custom setup handler */
Specification specification(greentea_setup, cases);
int main()
{
return !Harness::run(specification);
}
#else
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#ifdef TARGET_LIKE_FRDM_K64F_GCC
#include <mbed-drivers/mbed.h>
#endif
#include "cfstore_config.h"
#include "cfstore_test.h"
#include "cfstore_debug.h"
//#include <flash-abstraction/Driver_Common.h>
#include <Driver_Common.h>
#include <configuration-store/configuration_store.h>
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#include "cfstore_utest.h"
#ifdef YOTTA_CFG_CFSTORE_UVISOR
#include "uvisor-lib/uvisor-lib.h"
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
using namespace utest::v1;
static char cfstore_read_utest_msg_g[CFSTORE_UTEST_MSG_BUF_SIZE];
/* Configure secure box. */
#ifdef YOTTA_CFG_CFSTORE_UVISOR
UVISOR_BOX_NAMESPACE("com.arm.mbed.cfstore.test.read.box1");
UVISOR_BOX_CONFIG(cfstore_read_box1, UVISOR_BOX_STACK_SIZE);
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
/* KV data for test_01 */
static cfstore_kv_data_t cfstore_read_test_01_kv_data[] = {
CFSTORE_INIT_1_TABLE_MID_NODE,
{ NULL, NULL},
};
/* report whether built/configured for flash sync or async mode */
static control_t cfstore_read_test_00(const size_t call_count)
{
(void) call_count;
CFSTORE_LOG("INITIALIZING: caps.asynchronous_ops=%lu\n", cfstore_driver.GetCapabilities().asynchronous_ops);
return CaseNext;
}
/* @brief check char at offset is as expected */
static int32_t cfstore_read_seek_test(ARM_CFSTORE_HANDLE hkey, uint32_t offset, const char expected)
{
ARM_CFSTORE_SIZE len = 1;
char read_buf[1];
int32_t ret = ARM_DRIVER_ERROR;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
ret = drv->Rseek(hkey, offset);
if(ret < ARM_DRIVER_OK){
CFSTORE_ERRLOG("%s:failed to Rseek() to desired offset (offset=%d) (ret=%" PRId32 ").\n", __func__, (int) offset, ret);
goto out0;
}
ret = drv->Read(hkey, read_buf, &len);
if(ret < ARM_DRIVER_OK){
CFSTORE_ERRLOG("%s:failed to Read() (offset=%d)(ret=%" PRId32 ").\n", __func__, (int) offset, ret);
goto out0;
}
if(read_buf[0] != expected){
ret = ARM_DRIVER_ERROR;
goto out0;
}
out0:
return ret;
}
/** @brief
*
*
* @return status code
* ARM_DRIVER_OK, the test passed successfully
* ret < ARM_DRIVER_OK, the test failed with the return code
* supplying more details
*/
static control_t cfstore_read_test_01_end(const size_t call_count)
{
int32_t ret = ARM_DRIVER_ERROR;
ARM_CFSTORE_SIZE len = 0;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
ARM_CFSTORE_KEYDESC kdesc;
ARM_CFSTORE_HANDLE_INIT(hkey);
cfstore_test_rw_data_entry_t *node;
ARM_CFSTORE_FMODE flags;
CFSTORE_DBGLOG("%s:entered\n", __func__);
(void) call_count;
memset(&kdesc, 0, sizeof(kdesc));
memset(&flags, 0, sizeof(flags));
/* create a key for reading */
kdesc.drl = ARM_RETENTION_WHILE_DEVICE_ACTIVE;
len = strlen(cfstore_read_test_01_kv_data[0].value);
ret = cfstore_test_create(cfstore_read_test_01_kv_data[0].key_name, (char*) cfstore_read_test_01_kv_data[0].value, &len, &kdesc);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_read_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create KV in store (ret=%" PRId32 ").\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_read_utest_msg_g);
/* now open the newly created key */
ret = drv->Open(cfstore_read_test_01_kv_data[0].key_name, flags, hkey);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_read_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to open node (key_name=\"%s\", value=\"%s\")(ret=%" PRId32 ")\n", __func__, cfstore_read_test_01_kv_data[0].key_name, cfstore_read_test_01_kv_data[0].value, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_read_utest_msg_g);
/* seek back and forth in key and check the characters are as expected */
node = cfstore_test_rw_data_table;
while(node->offset != CFSTORE_TEST_RW_TABLE_SENTINEL)
{
ret = cfstore_read_seek_test(hkey, node->offset, node->rw_char);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_read_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Rseek() to offset (%d) didn't read expected char (\'%c\') (ret=%" PRId32 ")\n", __func__, (int) node->offset, node->rw_char, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_read_utest_msg_g);
node++;
}
CFSTORE_TEST_UTEST_MESSAGE(cfstore_read_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Close() call failed.\n", __func__);
TEST_ASSERT_MESSAGE(drv->Close(hkey) >= ARM_DRIVER_OK, cfstore_read_utest_msg_g);
ret = drv->Uninitialize();
CFSTORE_TEST_UTEST_MESSAGE(cfstore_read_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Uninitialize() call failed.\n", __func__);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_read_utest_msg_g);
return CaseNext;
}
/** @brief
*
* @return status code
* ARM_DRIVER_OK, the test passed successfully
* ret < ARM_DRIVER_OK, the test failed with the return code
* supplying more details
*/
static control_t cfstore_read_test_02_end(const size_t call_count)
{
(void) call_count;
/*todo: implement test */
CFSTORE_TEST_UTEST_MESSAGE(cfstore_read_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Warn: Not implemented\n", __func__);
CFSTORE_LOG("%s: WARN: requires implementation\n", __func__);
TEST_ASSERT_MESSAGE(true, cfstore_read_utest_msg_g);
return CaseNext;
}
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(200, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
/* 1 2 3 4 5 6 7 */
/* 1234567890123456789012345678901234567890123456789012345678901234567890 */
Case("READ_test_00", cfstore_read_test_00),
Case("READ_test_01_start", cfstore_utest_default_start),
Case("READ_test_01_end", cfstore_read_test_01_end),
Case("READ_test_02_start", cfstore_utest_default_start),
Case("READ_test_02_end", cfstore_read_test_02_end),
};
/* Declare your test specification with a custom setup handler */
Specification specification(greentea_setup, cases);
#if defined CFSTORE_CONFIG_MBED_OS_VERSION && CFSTORE_CONFIG_MBED_OS_VERSION == 3
/* mbedosV3*/
void app_start(int argc __unused, char** argv __unused)
{
/* Run the test specification */
Harness::run(specification);
}
#endif /* CFSTORE_CONFIG_MBED_OS_VERSION == 3 */
#if defined CFSTORE_CONFIG_MBED_OS_VERSION && CFSTORE_CONFIG_MBED_OS_VERSION == 4
/* mbedosV3++*/
int main()
{
return !Harness::run(specification);
}
#endif /* CFSTORE_CONFIG_MBED_OS_VERSION == 4 */
#endif // __MBED__ && ! defined TOOLCHAIN_GCC_ARM

View File

@ -0,0 +1,272 @@
/** @file write.cpp
*
* mbed Microcontroller Library
* Copyright (c) 2006-2016 ARM Limited
*
* 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.
*
* Test cases to write KVs in the CFSTORE using the drv->Write() API call.
*/
#if defined __MBED__ && ! defined TOOLCHAIN_GCC_ARM
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#ifdef TARGET_LIKE_FRDM_K64F_GCC
#include <mbed-drivers/mbed.h>
#endif
#include "cfstore_config.h"
#include <Driver_Common.h>
#include "cfstore_debug.h"
#include "cfstore_test.h"
#include <configuration-store/configuration_store.h>
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#ifdef YOTTA_CFG_CFSTORE_UVISOR
#include "uvisor-lib/uvisor-lib.h"
#include "cfstore_uvisor.h"
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
using namespace utest::v1;
static control_t cfstore_write_test_00(const size_t call_count)
{
(void) call_count;
printf("Not implemented for ARM toolchain\n");
return CaseNext;
}
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(100, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
/* 1 2 3 4 5 6 7 */
/* 1234567890123456789012345678901234567890123456789012345678901234567890 */
Case("WRITE_test_00", cfstore_write_test_00),
};
/* Declare your test specification with a custom setup handler */
Specification specification(greentea_setup, cases);
int main()
{
return !Harness::run(specification);
}
#else
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#ifdef TARGET_LIKE_FRDM_K64F_GCC
#include <mbed-drivers/mbed.h>
#endif
#include "cfstore_config.h"
#include "cfstore_test.h"
#include "cfstore_debug.h"
//#include <flash-abstraction/Driver_Common.h>
#include <Driver_Common.h>
#include <configuration-store/configuration_store.h>
#include "utest/utest.h"
#include "unity/unity.h"
#include "greentea-client/test_env.h"
#include "cfstore_utest.h"
#ifdef YOTTA_CFG_CFSTORE_UVISOR
#include "uvisor-lib/uvisor-lib.h"
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
using namespace utest::v1;
static char cfstore_write_utest_msg_g[CFSTORE_UTEST_MSG_BUF_SIZE];
/* Configure secure box. */
#ifdef YOTTA_CFG_CFSTORE_UVISOR
UVISOR_BOX_NAMESPACE("com.arm.mbed.cfstore.test.write.box1");
UVISOR_BOX_CONFIG(cfstore_write_box1, UVISOR_BOX_STACK_SIZE);
#endif /* YOTTA_CFG_CFSTORE_UVISOR */
/*
* write tests
* cfstore_handle_t cfstore_write()
*/
/* KV data for test_01 */
static cfstore_kv_data_t cfstore_write_test_01_kv_data[] = {
CFSTORE_INIT_1_TABLE_MID_NODE,
{ NULL, NULL},
};
/* report whether built/configured for flash sync or async mode */
static control_t cfstore_write_test_00(const size_t call_count)
{
(void) call_count;
CFSTORE_LOG("INITIALIZING: caps.asynchronous_ops=%lu\n", cfstore_driver.GetCapabilities().asynchronous_ops);
return CaseNext;
}
/** @brief test to write many times to an open KV to test data is appended
* sequentially to the end of the value blob
*
*
* @return status code
* ARM_DRIVER_OK, the test passed successfully
* ret < ARM_DRIVER_OK, the test failed with the return code
* supplying more details
*/
static control_t cfstore_write_test_01_end(const size_t call_count)
{
char read_buf[CFSTORE_KEY_NAME_MAX_LENGTH+1];
uint32_t i = 0;
int32_t ret = ARM_DRIVER_ERROR;
ARM_CFSTORE_SIZE len = 0;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
ARM_CFSTORE_KEYDESC kdesc;
ARM_CFSTORE_HANDLE_INIT(hkey);
ARM_CFSTORE_FMODE flags;
CFSTORE_DBGLOG("%s:entered\n", __func__);
(void) call_count;
memset(read_buf, 0, CFSTORE_KEY_NAME_MAX_LENGTH+1);
memset(&kdesc, 0, sizeof(kdesc));
memset(&flags, 0, sizeof(flags));
/* create an empty KV of the required length */
kdesc.drl = ARM_RETENTION_WHILE_DEVICE_ACTIVE;
len = strlen(cfstore_write_test_01_kv_data[0].value);
ret = cfstore_test_create(cfstore_write_test_01_kv_data[0].key_name, "one", &len, &kdesc);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_write_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create new KV (key_name=%s, ret=%" PRId32 ").\n", __func__, cfstore_write_test_01_kv_data[0].key_name, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_write_utest_msg_g);
/* now open the newly created key and write repeated to created the string */
flags.write = true;
ret = drv->Open(cfstore_write_test_01_kv_data[0].key_name, flags, hkey);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_write_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to open node (key_name=\"%s\", value=\"%s\")(ret=%" PRId32 ")\n", __func__, cfstore_write_test_01_kv_data[0].key_name, cfstore_write_test_01_kv_data[0].value, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_write_utest_msg_g);
for(i = 0; i < strlen(cfstore_write_test_01_kv_data[0].value); i++)
{
len = 1;
ret = drv->Write(hkey, &cfstore_write_test_01_kv_data[0].value[i], &len);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_write_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Write failed for char (\'%c\') (ret=%" PRId32 ")\n", __func__, cfstore_write_test_01_kv_data[0].value[i], ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_write_utest_msg_g);
}
/* check that the value created in the key is as expected*/
len = CFSTORE_KEY_NAME_MAX_LENGTH+1;
ret = drv->Read(hkey, read_buf, &len);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_write_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Read failed (ret=%" PRId32 ")\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_write_utest_msg_g);
/* check node key_names are identical */
CFSTORE_TEST_UTEST_MESSAGE(cfstore_write_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: KV value (%s) is not as expected (%s).\n", __func__, read_buf, cfstore_write_test_01_kv_data[0].value);
TEST_ASSERT_MESSAGE(strncmp(read_buf, cfstore_write_test_01_kv_data[0].value, strlen(cfstore_write_test_01_kv_data[0].value)) == 0, cfstore_write_utest_msg_g);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_write_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Close() call failed.\n", __func__);
TEST_ASSERT_MESSAGE(drv->Close(hkey) >= ARM_DRIVER_OK, cfstore_write_utest_msg_g);
cfstore_test_delete_all();
ret = drv->Uninitialize();
CFSTORE_TEST_UTEST_MESSAGE(cfstore_write_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Uninitialize() call failed.\n", __func__);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_write_utest_msg_g);
return CaseNext;
}
/** @brief test to write with a NULL buffer, which should fail gracefully
*
*
* @return status code
* ARM_DRIVER_OK, the test passed successfully
* ret < ARM_DRIVER_OK, the test failed with the return code
* supplying more details
*/
static control_t cfstore_write_test_02_end(const size_t call_count)
{
int32_t ret = ARM_DRIVER_ERROR;
ARM_CFSTORE_SIZE len = 0;
ARM_CFSTORE_KEYDESC kdesc;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
CFSTORE_DBGLOG("%s:entered\n", __func__);
(void) call_count;
memset(&kdesc, 0, sizeof(kdesc));
/* create an empty KV of the required length */
kdesc.drl = ARM_RETENTION_WHILE_DEVICE_ACTIVE;
len = strlen(cfstore_write_test_01_kv_data[0].value);
ret = cfstore_test_create(cfstore_write_test_01_kv_data[0].key_name, NULL, &len, &kdesc);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_write_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error KV creation should have failed due to null write buffer but something else happended (ret=%" PRId32 ").\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret == ARM_CFSTORE_DRIVER_ERROR_INVALID_WRITE_BUFFER, cfstore_write_utest_msg_g);
ret = drv->Uninitialize();
CFSTORE_TEST_UTEST_MESSAGE(cfstore_write_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: Uninitialize() call failed.\n", __func__);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_write_utest_msg_g);
return CaseNext;
}
utest::v1::status_t greentea_setup(const size_t number_of_cases)
{
GREENTEA_SETUP(200, "default_auto");
return greentea_test_setup_handler(number_of_cases);
}
Case cases[] = {
/* 1 2 3 4 5 6 7 */
/* 1234567890123456789012345678901234567890123456789012345678901234567890 */
Case("WRITE_test_00", cfstore_write_test_00),
Case("WRITE_test_01_start", cfstore_utest_default_start),
Case("WRITE_test_01_end", cfstore_write_test_01_end),
Case("WRITE_test_02_start", cfstore_utest_default_start),
Case("WRITE_test_02_end", cfstore_write_test_02_end),
};
/* Declare your test specification with a custom setup handler */
Specification specification(greentea_setup, cases);
#if defined CFSTORE_CONFIG_MBED_OS_VERSION && CFSTORE_CONFIG_MBED_OS_VERSION == 3
/* mbedosV3*/
void app_start(int argc __unused, char** argv __unused)
{
/* Run the test specification */
Harness::run(specification);
}
#endif /* CFSTORE_CONFIG_MBED_OS_VERSION == 3 */
#if defined CFSTORE_CONFIG_MBED_OS_VERSION && CFSTORE_CONFIG_MBED_OS_VERSION == 4
/* mbedosV3++*/
int main()
{
return !Harness::run(specification);
}
#endif /* CFSTORE_CONFIG_MBED_OS_VERSION == 4 */
#endif // __MBED__ && ! defined TOOLCHAIN_GCC_ARM

8
storage/cfstore/LICENSE Normal file
View File

@ -0,0 +1,8 @@
Unless specifically indicated otherwise in a file, files are licensed
2 under the Apache 2.0 license, as can be found in: apache-2.0.txt
Source code in cfstore_fnmatch.c is licensed under the agreements in the
following files:
- berkeley.txt
- chernov.txt
- tatmanjants.txt

View File

@ -0,0 +1,65 @@
###########################################################################
#
# Copyright (c) 2013-2015, 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.
#
###########################################################################
#
# inline debugging/flashing scripts
#
define __SCRIPT_GDB
target remote $(DEBUG_HOST)
monitor endian little
monitor reset
monitor halt
monitor semihosting enable
monitor speed 1000
monitor loadbin $(TARGET_BIN) 0
monitor flash device = $(CPU)
load $(TARGET)
file $(TARGET)
$(GDB_DEBUG_UVISOR)
b vmpu_init_post
b app_start
endef
export __SCRIPT_GDB
define __SCRIPT_FLASH
r
loadbin $(TARGET_BIN) 0
r
g
q
endef
export __SCRIPT_FLASH
define __SCRIPT_ERASE
h
Sleep 100
unlock kinetis
Sleep 100
erase
q
endef
export __SCRIPT_ERASE
define __SCRIPT_RESET
h
r
g
q
endef
export __SCRIPT_RESET

112
storage/cfstore/README.md Normal file
View File

@ -0,0 +1,112 @@
# Secure Key-Value Storage #
## Executive Summary
The Configuration Store (CFSTORE) is a secure,
associative key-value (KV) store C-Language Hardware Abstraction Layer.
CFSTORE provides the secure and persistent storage for:
- Storing encryption keys data.
- Storing configuration data.
- Storing firmware, firmware updates and incremental firmware blocks for assembling into a firmware update.
These services are presented to clients with:
- A conceptually simple, file-like interface for storing and managing data using (key, value) pairs in
persistent storage media.
- A simple, hardware-independent API to promote portability across multiple platforms and a low attack surface.
- A very small code/memory footprint so CFSTORE is capable of running on highly-constrained memory systems (~10kB free memory)
where typically available SRAM << NV storage.
- A simple (low complexity) storage capability at the expense of features. For example, CFSTORE only supports the storage of
binary blobs rather than a rich set of data types.
Current support includes:
- NV-backed support. Integration with Flash Abstraction (Flash Journal Strategy Sequential) for persistent storage on the Freescale FRDM K64F target.
- SRAM backed support.
- More than 60 test cases with >80% test coverage.
- Comprehensive documentation.
# Configuration-Store Software Architecture
```C
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Configuration Store Client |
| e.g. FOTA |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| Configuration Store | | uvisor |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| Flash Abstraction Layer | | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | |
| Flash Driver Layer | | |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
SW
-----------------------------------------------------------------------
HW
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| NV Storage Media e.g. Flash |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
Configuration Store Software Architecture
```
The above figure shows the following entities (from top to bottom):
- A Configuration Store client e.g. FOTA.
- Configuration Store, the associative KV pair store.
- Flash Abstraction Layer, portable across the driver layer.
- Flash Driver layer e.g. CMSIS-Driver.
- NV Storage Media. These are the physical storage media.
# Providing Feedback
If you would like to make a contribution to CFSTORE, please provide feedback/designs/comments/code in one of the following ways:
- By logging an issue in the CFSTORE repo.
- By submitting a Pull Request to the CFSTORE repo.
- By sending an email to:
-- simon.hughes@arm.com
-- milosch.meriac@arm.com
# Further Reading
* The [CFSTORE Getting Started Guide.][CFSTORE_GETSTART]
* The [CFSTORE Client Example 3 for flash-journal synchronous mode only (simpler code).][CFSTORE_EX3]
* The [CFSTORE Client Example 1 for both flash-journal modes (asynchronous and synchronous)(more complicated but versatile code).][CFSTORE_EX1]
* The CFSTORE Product Requirements were not written.
* The [CFSTORE Engineering Requirements.][CFSTORE_ENGREQ]
* The [CFSTORE High Level Design Document.][CFSTORE_HLD]
* The [CFSTORE Low Level Design Document.][CFSTORE_LLD]
* The [CFSTORE Project Test Plan describing the test methodologies and test cases.][CFSTORE_TESTPLAN]
* The [CFSTORE Release Notes.][CFSTORE_RELEASES]
* The [CFSTORE Jenkins Build and Test Results.][CFSTORE_JENKINS_BT]
* The [CFSTORE Jenkins Code Coverage Results.][CFSTORE_JENKINS_COV]
* The [CFSTORE Project Plan describing milestones and roadmap.][CFSTORE_PROJPLAN]
* The [CFSTORE Project Plan Excel Spreadsheet with estimates and milestones][CFSTORE_PROJXLS]
* The [Flash Abstraction Layer.][FAL]
[CFSTORE_ENGREQ]: https://github.com/ARMmbed/configuration-store/blob/master/doc/design/configuration_store_requirements.md
[CFSTORE_EX1]: https://github.com/ARMmbed/configuration-store-example1
[CFSTORE_EX3]: https://github.com/ARMmbed/configuration-store-example3
[CFSTORE_GETSTART]: https://github.com/ARMmbed/configuration-store/blob/master/doc/design/configuration_store_getting_started.md
[CFSTORE_HLD]: https://github.com/ARMmbed/configuration-store/blob/master/doc/design/configuration_store_hld.md
[CFSTORE_JENKINS_BT]: http://e108747.cambridge.arm.com:8080/job/configuration-store-nightly-build-and-test/
[CFSTORE_JENKINS_COV]: http://e108747.cambridge.arm.com:8080/job/configuration-store-test-coverage/
[CFSTORE_LLD]: https://github.com/ARMmbed/configuration-store/blob/master/doc/design/configuration_store_lld.md
[CFSTORE_TESTPLAN]: https://github.com/ARMmbed/configuration-store/blob/master/doc/design/configuration_store_test_plan.md
[CFSTORE_PRODREQ]: https://github.com/ARMmbed/configuration-store/blob/master/doc/design/configuration_store_product_requirements.md
[CFSTORE_PROJPLAN]:https://github.com/ARMmbed/configuration-store/blob/master/doc/design/configuration_store_project.md
[CFSTORE_PROJXLS]:https://github.com/ARMmbed/configuration-store/blob/master/doc/project/ARM_MBED_TN_0020_cfstore_project_plan.xlsx
[CFSTORE_RELEASES]:https://github.com/ARMmbed/configuration-store/blob/master/doc/project/configuration_store_releases.md
[CFSTORE_TERM]: https://github.com/ARMmbed/configuration-store/blob/master/doc/design/configuration_store_terminology.md
[FAL]: https://github.com/ARMmbed/flash-abstraction

3
storage/cfstore/VERSION Normal file
View File

@ -0,0 +1,3 @@
{
"version": "0.3.3",
}

View File

@ -0,0 +1,13 @@
Copyright (c) 2016 ARM Limited
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.

View File

@ -0,0 +1,31 @@
/*
* Copyright (c) 1989, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Guido van Rossum.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/

View File

@ -0,0 +1,25 @@
/*
* Copyright (C) 1996 by Andrey A. Chernov, Moscow, Russia.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/

View File

@ -0,0 +1,949 @@
/** @file configure-store.h
*
* mbed Microcontroller Library
* Copyright (c) 2006-2016 ARM Limited
*
* 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.
*
* This is the interface file to configuration store service.
*/
#ifndef __CONFIGURATION_STORE_H
#define __CONFIGURATION_STORE_H
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <string.h> /* requierd for memset() in ARM_CFSTORE_HANDLE_INIT() */
#define DEVICE_STORAGE 1 /* enable storage */
#include <Driver_Storage.h>
#include <Driver_Common.h>
#define ARM_CFSTORE_API_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(1,0) /* API version */
#define ARM_CFSTORE_DRV_VERSION ARM_DRIVER_VERSION_MAJOR_MINOR(0,1) /* DRV version */
/* CFSTORE Specific error codes*/
#define ARM_CFSTORE_DRIVER_ERROR_UNINITIALISED -1000 /* Start of driver specific errors */
#define ARM_CFSTORE_DRIVER_ERROR_PREEXISTING_KEY -1001
#define ARM_CFSTORE_DRIVER_ERROR_KEY_NOT_FOUND -1002
#define ARM_CFSTORE_DRIVER_ERROR_INVALID_HANDLE -1003
#define ARM_CFSTORE_DRIVER_ERROR_OUT_OF_MEMORY -1004
#define ARM_CFSTORE_DRIVER_ERROR_PREEXISTING_KEY_DELETING -1005
#define ARM_CFSTORE_DRIVER_ERROR_INVALID_HANDLE_BUF -1006
#define ARM_CFSTORE_DRIVER_ERROR_INTERNAL -1007
#define ARM_CFSTORE_DRIVER_ERROR_INVALID_KEY_NAME -1008
#define ARM_CFSTORE_DRIVER_ERROR_VALUE_SIZE_TOO_LARGE -1009
#define ARM_CFSTORE_DRIVER_ERROR_KEY_READ_ONLY -1010
#define ARM_CFSTORE_DRIVER_ERROR_INVALID_SEEK -1011
#define ARM_CFSTORE_DRIVER_ERROR_KEY_UNREADABLE -1012
#define ARM_CFSTORE_DRIVER_ERROR_INVALID_WRITE_BUFFER -1013
#define ARM_CFSTORE_DRIVER_ERROR_INVALID_KEY_LEN -1014
#define ARM_CFSTORE_DRIVER_ERROR_NOT_SUPPORTED -1015
#define ARM_CFSTORE_DRIVER_ERROR_INVALID_READ_BUFFER -1016
#define ARM_CFSTORE_DRIVER_ERROR_INVALID_KEY_DESCRIPTOR -1017
#define ARM_CFSTORE_DRIVER_ERROR_PERM_NO_READ_ACCESS -1018
#define ARM_CFSTORE_DRIVER_ERROR_PERM_NO_WRITE_ACCESS -1019
#define ARM_CFSTORE_DRIVER_ERROR_PERM_NO_EXECUTE_ACCESS -1020
#define ARM_CFSTORE_DRIVER_ERROR_NO_PERMISSIONS -1021
#define ARM_CFSTORE_DRIVER_ERROR_HANDLE_COUNT_MAX -1022
#define ARM_CFSTORE_DRIVER_ERROR_JOURNAL_STATUS_ERROR -1023
#define ARM_CFSTORE_DRIVER_ERROR_JOURNAL_STATUS_BUSY -1024
#define ARM_CFSTORE_DRIVER_ERROR_JOURNAL_STATUS_TIMEOUT -1025
#define ARM_CFSTORE_DRIVER_ERROR_JOURNAL_STATUS_UNSUPPORTED -1026
#define ARM_CFSTORE_DRIVER_ERROR_JOURNAL_STATUS_PARAMETER -1027
#define ARM_CFSTORE_DRIVER_ERROR_JOURNAL_STATUS_BOUNDED_CAPACITY -1028
#define ARM_CFSTORE_DRIVER_ERROR_JOURNAL_STATUS_STORAGE_API_ERROR -1029
#define ARM_CFSTORE_DRIVER_ERROR_JOURNAL_STATUS_STORAGE_IO_ERROR -1030
#define ARM_CFSTORE_DRIVER_ERROR_JOURNAL_STATUS_NOT_INITIALIZED -1031
#define ARM_CFSTORE_DRIVER_ERROR_JOURNAL_STATUS_ATTEMPTING_COMMIT_WITHOUT_WRITE -1032
#define ARM_CFSTORE_DRIVER_ERROR_JOURNAL_STATUS_EMPTY -1033
#define ARM_CFSTORE_DRIVER_ERROR_JOURNAL_STATUS_SMALL_LOG_REQUEST -1034
#define ARM_CFSTORE_DRIVER_ERROR_OPERATION_PENDING -1035
#define ARM_CFSTORE_DRIVER_ERROR_UVISOR_BOX_ID -1036
#define ARM_CFSTORE_DRIVER_ERROR_UVISOR_NAMESPACE -1037
/*
* Type Definitions
*
* ARM_CFSTORE_HANDLE
* opaque cfstore handle for manipulating cfstore data objects e.g. KV pairs.
*/
typedef void *ARM_CFSTORE_HANDLE;
typedef size_t ARM_CFSTORE_SIZE;
typedef size_t ARM_CFSTORE_OFFSET;
typedef struct _ARM_CFSTORE_STATUS {
uint32_t in_progress : 1;
uint32_t error : 1;
} ARM_CFSTORE_STATUS;
/* Defines
*
* CFSTORE_KEY_NAME_MAX_LENGTH
* The maximum length of the null terminated character string used as a
* key name string.
*
* CFSTORE_VALUE_SIZE_MAX
* Max size of the KV value blob (currently 64MB)
*
* CFSTORE_HANDLE_BUFSIZE
* size of the buffer owned and supplied by client to CFSTORE to hold internal
* data structures, referenced by the key handle. Note this can change on
* different platforms depending on the sizeof types.
*
*/
#define CFSTORE_KEY_NAME_MAX_LENGTH 220
#define CFSTORE_VALUE_SIZE_MAX (1<<26)
#ifdef TARGET_LIKE_FRDM_K64F_GCC
#define CFSTORE_HANDLE_BUFSIZE 24
#endif
#ifdef TARGET_LIKE_X86_LINUX_NATIVE
#define CFSTORE_HANDLE_BUFSIZE 40
#endif
/* @brief Helper macro to declare handle and client owned buffer supplied
* to CFSTORE for storing opaque handle state */
#define ARM_CFSTORE_HANDLE_INIT(__name) \
uint8_t (__name##_buf_cFsToRe)[CFSTORE_HANDLE_BUFSIZE]; \
ARM_CFSTORE_HANDLE (__name) = (ARM_CFSTORE_HANDLE) (__name##_buf_cFsToRe); \
memset((__name##_buf_cFsToRe), 0, CFSTORE_HANDLE_BUFSIZE)
/* @brief Helper macro to swap 2 handles, which is useful for the Find()
* idiom (see CFSTORE_NOTE1 later).
*/
#if defined __MBED__ && defined TOOLCHAIN_GCC_ARM
#define CFSTORE_HANDLE_SWAP(__a_HaNdLe, __b_HaNdLe) \
do{ ARM_CFSTORE_HANDLE __temp_HaNdLe = (__a_HaNdLe); \
__asm volatile("" ::: "memory"); \
(__a_HaNdLe) = (__b_HaNdLe); \
__asm volatile("" ::: "memory"); \
(__b_HaNdLe) = (__temp_HaNdLe); \
__asm volatile("" ::: "memory"); \
}while(0)
#endif
#if defined __MBED__ && defined TOOLCHAIN_ARM
/* todo: implment this macro */
#define CFSTORE_HANDLE_SWAP(__a_HaNdLe, __b_HaNdLe) \
do{ ARM_CFSTORE_HANDLE __temp_HaNdLe = (__a_HaNdLe); \
__dmb(0xf); \
(__a_HaNdLe) = (__b_HaNdLe); \
__dmb(0xf); \
(__b_HaNdLe) = (__temp_HaNdLe); \
__dmb(0xf); \
}while(0)
#endif
/* @brief The access control permissions for the key-value.
* @note A client requires the perm_xxx_write set to be able to
* delete the KV.
* @param perm_owner_read
* if set => this KV is owner readable
* @param perm_owner_write
* if set => this KV is owner writable
* @param perm_owner_execute (currently not supported)
* if set => this KV is owner executable
* @param perm_other_read
* if set => this KV is world readable
* @param perm_other_write
* if set => this KV is world writable
* @param perm_other_execute (currently not supported)
* if set => this KV is world executable
* @param reserved
* reserved for future use.
*/
typedef struct ARM_CFSTORE_ACCESS_CONTROL_LIST
{
uint32_t perm_owner_read : 1;
uint32_t perm_owner_write : 1;
uint32_t perm_owner_execute : 1;
uint32_t perm_other_read : 1;
uint32_t perm_other_write : 1;
uint32_t perm_other_execute : 1;
uint32_t reserved : 26;
} ARM_CFSTORE_ACCESS_CONTROL_LIST;
/* @brief file mode bitfield structure for specifying how flags for the
* following operations:
* - ARM_CFSTORE_DRIVER::(*Create)(), when creating a KV.
* - ARM_CFSTORE_DRIVER::(*Open)(), when opening a pre-existing KV.
*
* continuous
* if set, the key value should be stored in a continuous sequence of hardware
* addresses
*
* lazy_flush
* if set then configuration store will defer flushing the KV
* changes until an optimal time. e.g. to save energy rather than performing
* the operation immediately.
*
* flush_on_close
* if set then the key-value should be flushed to the backing store when
* the key is closed.
*
* read
* if set then the KV can be read
*
* write
* if set then the KV can be written
*
* storage_detect
* if set then the call to ARM_CFSTORE_DRIVER::(*Create)() returns whether
* a key could be created with the required storage characteristics. The
* key is not created.
*/
typedef struct ARM_CFSTORE_FMODE
{
uint32_t continuous : 1;
uint32_t lazy_flush : 1;
uint32_t flush_on_close : 1;
uint32_t read : 1;
uint32_t write : 1;
uint32_t execute : 1;
uint32_t storage_detect : 1;
uint32_t reserved : 25;
} ARM_CFSTORE_FMODE;
/**
* @brief descriptor used to create keys
*
* @param acl
* Access Control List specifying the access permissions of the KV.
* @param drl
* data retention level for the KV required by the client. CFSTORE will
* store the KV in the specified type store/media.
* @param security
* flash security properties for the KV required by the client. CFSTORE
* will store the KV in a storage media supporting the specified
* security attributes.
* @param flags
* A bitfield containing the access mode setting for the key.
*
*/
typedef struct ARM_CFSTORE_KEYDESC
{
/*key descriptor attributes */
ARM_CFSTORE_ACCESS_CONTROL_LIST acl;
uint8_t drl;
ARM_STORAGE_SECURITY_FEATURES security;
ARM_CFSTORE_FMODE flags;
} ARM_CFSTORE_KEYDESC;
/* ARM_CFSTORE_OPCODE, ARM_CFSTORE_CALLBACK and the Asynchronous Completion
* of Driver Dispatch methods [REFERENCE_1]
*
* Configuration Store driver dispatch methods can operate in 2 modes:
* - Synchronous i.e. when:
* ARM_CFSTORE_CAPABILITIES::asynchronous_ops == 0
* then the ARM_CFSTORE_DRIVER::Dispatch_Method_Xxx() will return:
* - >= 0 => CFSTORE Dispatch_Method_Xxx() completed successfully
* - otherwise CFSTORE Dispatch_Method_Xxx() did not complete successfully
* (return code supplies further details).
* In synchronous mode there it is optional as to whether the client registers
* a client callback with the Initialize() method. If one is registered, it
* will be called to indicate the synchronous completion status.
*
* - Asynchronous i.e. when:
* ARM_CFSTORE_CAPABILITIES::asynchronous_ops == 1
* then the ARM_CFSTORE_DRIVER::Dispatch_Method_Xxx() will return:
* - return_value = ARM_DRIVER_OK (i.e. ==0) implies CFSTORE
* Dispatch_Method_Xxx() transaction pending. Dispatch_Method_Xxx
* completion status will be indicated via
* an asynchronous call to ARM_CFSTORE_CALLBACK registered with the
* ARM_CFSTORE_DRIVER::(*Initialize)(), where the status supplied to
* the callback will be the final status of the call.
* - return_value > ARM_DRIVER_OK (i.e. > 0) implies CFSTORE Dispatch_Method_Xxx() completely
* synchronously and successfully. The return_value has specific
* meaning for the Dispatch_Method_Xxx() e.g. for the Read() method
* return_value is the number of bytes read.
* - otherwise return_value < 0 => CFSTORE Dispatch_Method_Xxx()
* completed unsuccessfully (return code supplies further details).
*
* The client registered asynchronous callback method ARM_CFSTORE_CALLBACK is
* registered by the client using:
* ARM_CFSTORE_DRIVER::(*Initialize)(ARM_CFSTORE_CALLBACK callback,
* void* client_context)
* See the (*Initialize) documentation for more details.
*
* The registered callback has the following prototype:
*
* typedef void (*ARM_CFSTORE_CALLBACK)(
* int32_t status,
* ARM_CFSTORE_OPCODE cmd_code,
* void *client_context,
* ARM_CFSTORE_HANDLE handle);
*
* Before an asynchronous notification is received, a client can check on the
* status of the call by calling ARM_CFSTORE_DRIVER::(*GetStatus)().
*
*/
typedef enum ARM_CFSTORE_OPCODE {
CFSTORE_OPCODE_CLOSE = 1,
CFSTORE_OPCODE_CREATE,
CFSTORE_OPCODE_DELETE,
CFSTORE_OPCODE_FIND,
CFSTORE_OPCODE_FLUSH,
CFSTORE_OPCODE_GET_KEY_NAME,
CFSTORE_OPCODE_GET_STATUS,
CFSTORE_OPCODE_GET_VALUE_LEN,
CFSTORE_OPCODE_INITIALIZE,
CFSTORE_OPCODE_OPEN,
CFSTORE_OPCODE_POWER_CONTROL,
CFSTORE_OPCODE_READ,
CFSTORE_OPCODE_RSEEK,
CFSTORE_OPCODE_UNINITIALIZE,
CFSTORE_OPCODE_WRITE,
CFSTORE_OPCODE_MAX
} ARM_CFSTORE_OPCODE;
/* [REFERENCE_2]
*
* @brief client registered callback type for receiving asynchronous event
* notifications.
*
* @param status
* In the case that cmd_code is one of ARM_CFSTORE_OPCODE then this
* is the asynchronous completion status of the associated
* ARM_CFSTORE_DRIVER::Dispatch_Method_Xxx()
* @param cmd_code
* ARM_CFSTORE_OPCODE for the
* ARM_CFSTORE_DRIVER::Dispatch_Method_Xxx() for which this
* invocation of the callback is an asynchronous completion event.
* @param client_context
* The client ARM_CFSTORE_CALLBACK context registered with the
* ARM_CFSTORE_DRIVER::(*Initialize)() method.
* @param handle
* For certain ARM_CFSTORE_DRIVER::Dispatch_Method_Xxx() e.g.
* ARM_CFSTORE_DRIVER::(*Create)()
* ARM_CFSTORE_DRIVER::(*Open)()
* ARM_CFSTORE_DRIVER::(*Find)()
* then an open key handle is supplied upon asynchronous completion.
* See the documentation of the ARM_CFSTORE_OpCode_e and the
* ARM_CFSTORE_DRIVER::Dispatch_Method_Xxx() for further details.
*
*/
typedef void (*ARM_CFSTORE_CALLBACK)(int32_t status, ARM_CFSTORE_OPCODE cmd_code, void *client_context, ARM_CFSTORE_HANDLE handle);
/* @brief Find the capabilities of the configuration store.
*
* @param asynchronous_ops
* If set => the configuration store dispatch interface is operating in
* non-blocking (asynchronous) mode.
* If clr => the configuration store dispatch interface is operating in
* blocking (synchronous) mode.
* @param uvisor_support_enabled
* The configuration store is using uvisor security contexts.
*/
typedef struct ARM_CFSTORE_CAPABILITIES
{
uint32_t asynchronous_ops : 1;
uint32_t uvisor_support_enabled : 1;
} ARM_CFSTORE_CAPABILITIES;
/**
* This is the set of operations constituting the Configuration Store driver.
*
* The functions dispatch methods can operate synchronously or asynchronously
* depending on the underlying implementation. The client of this interface
* should not assume one or other mode of operation but use the
* (*GetCapabilities) method to determine the operational mode and then
* behave accordingly.
*/
typedef struct _ARM_DRIVER_CFSTORE
{
/**
* @brief Get driver version.
*
* The synchronous function GetVersion() returns version information of the
* driver implementation in ARM_DRIVER_VERSION.
* - ARM_DRIVER_VERSION::api
* the version of the CMSIS-Driver specification used to implement
* this driver.
* - ARM_DRIVER_VERSION::drv
* the source code version of the actual configuration store driver
* implementation.
*
* @return \ref ARM_DRIVER_VERSION, the configuration store driver
* version information
*/
ARM_DRIVER_VERSION (*GetVersion)(void);
/**
* @brief Close the hkey context previously recovered from CFSTORE.
*
* @param hkey
* IN: a previously returned handle from (*Create((), (*Open)()
* or (*Find)() to close.
*
* @return return_value
*
* See REFERENCE_1 and REFERENCE_2.
* ARM_CFSTORE_DRIVER::(*Close)() asynchronous completion command code
* (*ARM_CFSTORE_CALLBACK) function argument values on return:
* @param status
* ARM_DRIVER_OK => success, KV deleted, else failure.
* @param cmd_code == CFSTORE_OPCODE_CLOSE
* @param client context
* as registered with ARM_CFSTORE_DRIVER::(*Initialize)()
* @param hkey == NULL
*/
int32_t (*Close)(ARM_CFSTORE_HANDLE hkey);
/**
* @brief Create a key-value int he configuration strore.
*
* Once created, the following attributes of a KV cannot be changed:
* - the key_name
* - the permissions or attributes specifies by the key descriptor kdesc.
* To change these properties, the key must be deleted and then created
* again with the new properties.
*
* @param key_name
* IN: zero terminated string specifying the key name.
* @param value_len
* the client specifies the length of the value data item in the
* KV being created.
* @param kdesc
* IN: key descriptor, specifying how the details of the key
* create operations. Note the following cases:
* 1) if key_name is not present in the CFSTORE and kdesc is NULL
* (i.e. a new KV pair is being created),
* then CFSTORE will chose the most appropriate defaults
* e.g. CFSTORE will store the KV in nv store if the value size
* is large, with no security guarantees just safety.
* 2) if key_name is present in the CFSTORE and kdesc is NULL
* (i.e. there is a pre-existing KV pair),
* then CFSTORE will grow/shrink the value data buffer to
* value_len octets. This idiom can be used to increase/decrease
* the size of the KV value storage.
* 3) If the kdesc->flags.storage_detect == 1 then the function
* does not create the key but reports whether the key
* with the specified size and storage media attributes
* could/could not be created by configuration storage.
* @param hkey
* IN: pointer to client owned buffer of CFSTORE_HANDLE_BUFSIZE
* bytes
* OUT: on success, hkey is a valid handle to a KV.
*
* @return return_value
*
* See REFERENCE_1 and REFERENCE_2.
* ARM_CFSTORE_DRIVER::(*Create)() asynchronous completion command code
* (*ARM_CFSTORE_CALLBACK) function argument values on return:
* @param status
* ARM_DRIVER_OK => success, KV deleted, else failure.
* @param cmd_code == CFSTORE_OPCODE_CREATE
* @param client context
* as registered with ARM_CFSTORE_DRIVER::(*Initialize)()
* @param hkey now contains returned handle to newly created key.
*/
int32_t (*Create)(const char* key_name, ARM_CFSTORE_SIZE value_len, const ARM_CFSTORE_KEYDESC* kdesc, ARM_CFSTORE_HANDLE hkey);
/**
* @brief delete key-value from configuration store
*
* This method is used in the following ways:
* - (*Open)() to get a handle to the key, (*Delete)() to delete the key,
* (*Close)() to close the handle to the key.
* - (*Find)() to get a handle to the key, (*Delete)() to delete the key,
* (*Close)() to close the handle to the key.
*
* @param hkey
* IN: the handle of the key to delete.
*
* @return return_value
*
* See REFERENCE_1 and REFERENCE_2.
* ARM_CFSTORE_DRIVER::(*Delete)() asynchronous completion command code
* (*ARM_CFSTORE_CALLBACK) function argument values on return:
* @param status
* ARM_DRIVER_OK => success, KV deleted, else failure.
* @param cmd_code == CFSTORE_OPCODE_DELETE
* @param client context
* as registered with ARM_CFSTORE_DRIVER::(*Initialize)()
* @param hkey, unused.
*
*/
int32_t (*Delete)(ARM_CFSTORE_HANDLE hkey);
/**
* @brief find stored keys that match a query string
*
* find a list of pre-existing keys according to a query pattern.
* The search pattern can have the following formats
* - 'com.arm.mbed.wifi.accesspoint.essid'. Find whether an object
* exists that has a key matching
* 'com.arm.mbed.wifi.accesspoint.essid'
* - 'com.arm.mbed.wifi.accesspoint*.essid'. Find all keys that
* start with the substring 'com.arm.mbed.wifi.accesspoint' and
* end with the substring '.essid'
* - 'yotta.your-yotta-registry-module-name.*'. Find all key_name
* strings that begin with the substring
* 'yotta.your-yotta-registry-module-name.'
* - 'yotta.hello-world.animal[dog][foot][*]'. Find all key_name
* strings beginning yotta.hello-world.animal[dog][foot]
* - 'yotta.hello-world.animal[dog][foot]*'
* - 'yotta.hello-world.animal[dog*3]'
*
* It is possible to iterate over the list of matching keys by
* using the idiom below (in the synchronous case)(CFSTORE_NOTE1)
*
* int32_t ret = ARM_DRIVER_ERROR;
* const char* key_name_query = "*";
* char key_name[CFSTORE_KEY_NAME_MAX_LENGTH+1];
* uint8_t len = CFSTORE_KEY_NAME_MAX_LENGTH+1;
* ARM_CFSTORE_HANDLE_INIT(next);
* ARM_CFSTORE_HANDLE_INIT(prev);
*
* while(drv->Find(key_name_query, prev, next) == ARM_DRIVER_OK)
* {
* len = CFSTORE_KEY_NAME_MAX_LENGTH+1;
* drv->GetKeyName(next, key_name, &len);
* printf("Found matching key-value with key_name=%s\n", key_name);
* CFSTORE_HANDLE_SWAP(prev, next);
* }
*
* The iteration over the find results can be terminated before
* the end of the list is reached by closing the last open
* file handle and not making any further calls to
* find() e.g.
*
* int32_t ret = ARM_DRIVER_ERROR;
* const char* key_name_query = "*";
* char key_name[CFSTORE_KEY_NAME_MAX_LENGTH+1];
* uint8_t len = CFSTORE_KEY_NAME_MAX_LENGTH+1;
* ARM_CFSTORE_HANDLE_INIT(next);
* ARM_CFSTORE_HANDLE_INIT(prev);
*
* while(drv->Find(key_name_query, prev, next) == ARM_DRIVER_OK)
* {
* len = CFSTORE_KEY_NAME_MAX_LENGTH+1;
* drv->GetKeyName(next, key_name, &len);
* if(strncmp(key_name, "my.key_name", CFSTORE_KEY_NAME_MAX_LENGTH))
* {
* printf("Found matching key-value with key_name=%s\n", key_name;
* // terminating walk of find results
* drv->Close(next);
* break;
* }
* CFSTORE_HANDLE_SWAP(prev, next);
* }
*
* @param key_name_query
* IN: a search string to find. This can include the wildcard '*'
* character
* @param previous
* IN: On the first call to (*Find) then previous is a pointer
* (the handle) to a buffer initialised to 0.
* On the subsequent calls to (*Find), a previously returned
* key handle can be supplied as the previous argument. The next
* available search result will be returned. If no further search
* results are available then (*Find) will return
* ARM_CFSTORE_DRIVER_ERROR_KEY_NOT_FOUND. Once the
* file handle has been supplied to the function as the prev
* argument, CFSTORE close the open file handle. Otherwise, the
* client must call (*Close)() on the open file handle.
* @param next
* IN: pointer to client owned buffer of CFSTORE_HANDLE_BUFSIZE
* bytes to hold the
* OUT: Success: In the case that a match has been found then hkey
* is a valid handle to an open KV. The key must be explicitly closed
* by the client. Note this is a read-only key.
* Async operation: The storage at hkey must be available until after
* the completion notification has been received by the client.
* @return return_value
* On success (finding a KV matching the query) ARM_DRIVER_OK is
* returned. If a KV is not found matching the description then
* ARM_CFSTORE_DRIVER_ERROR_KEY_NOT_FOUND is returned.
* See REFERENCE_1 and REFERENCE_2.
* ARM_CFSTORE_DRIVER::(*Find)() asynchronous completion command code
* (*ARM_CFSTORE_CALLBACK) function argument values on return:
* @param status
* ARM_DRIVER_OK => success, hkey contains open key
* else failure.
* @param cmd_code == CFSTORE_OPCODE_FIND
* @param client context
* as registered with ARM_CFSTORE_DRIVER::(*Initialize)()
* @param hkey
* ARM_DRIVER_OK => contains returned handle to newly found key.
* else, indeterminate data.
*/
int32_t (*Find)(const char* key_name_query, const ARM_CFSTORE_HANDLE previous, ARM_CFSTORE_HANDLE next);
/**
* @brief flush (write) the configuration changes to the nv backing
* store.
*
* @note all open key handles must be closed before flushing the CFSTORE to nv
* backing store.
*
* @return return_value
* See REFERENCE_1 and REFERENCE_2.
* ARM_CFSTORE_DRIVER::(*Flush)() asynchronous completion command code
* (*ARM_CFSTORE_CALLBACK) function argument values on return:
* @param status
* ARM_DRIVER_OK => success, hkey contains open key
* else failure.
* @param cmd_code == CFSTORE_OPCODE_FLUSH
* @param client context, registered ARM_CFSTORE_DRIVER::(*Initialize)()
* @param hkey, unused
*/
int32_t (*Flush)(void);
/**
* @brief Get configuration store capabilities.
*
* This synchronous function returns a ARM_CFSTORE_CAPABILITIES
* information structure describing configuration store implementation
* attributes.
*
* @return \ref ARM_CFSTORE_CAPABILITIES
*/
ARM_CFSTORE_CAPABILITIES (*GetCapabilities)(void);
/**
* @brief get the name of an open key handle
*
* @param hkey
* open handle of key to get the key_name
* @param key_name. The key name string is guaranteed to be terminated
* with '\0'.
* @param key_len, the length of the buffer available at data to receive
* the key_name string
* @return return_value
* See REFERENCE_1 and REFERENCE_2.
* ARM_CFSTORE_DRIVER::(*GetKeyName)() asynchronous completion command code
* (*ARM_CFSTORE_CALLBACK) function argument values on return:
* @param status
* ARM_DRIVER_OK => success, key_name contains key_name string, len
* contains length of string.
* else failure.
* @param cmd_code == CFSTORE_OPCODE_GET_KEY_NAME
* @param client context, registered ARM_CFSTORE_DRIVER::(*Initialize)()
* @param hkey supplied to the GetKeyName() call at hkey.
* @param key_name
* on success, the buffer holds the name of the key
* @param key_len
* on success, the supplied integer is set to strlen(key_name)+1, where
* the additional character corresponds to the terminating null.
*
*/
int32_t (*GetKeyName)(ARM_CFSTORE_HANDLE hkey, char* key_name, uint8_t *key_len);
/**
* @brief Get the status of the configuration store.
*
* @return return_value
* See REFERENCE_1 and REFERENCE_2
* ARM_DRIVER_OK if the command has been accepted and
* enqueued by the underlying controller, else an appropriate
* error code. Getting a return value of ARM_DRIVER_OK
* implies that basic argument validation was successful, and the
* caller can expect a command completion callback to be invoked
* at a later time.
*
* ARM_CFSTORE_DRIVER::(*GetStatus)() asynchronous completion command code
* (*ARM_CFSTORE_CALLBACK) function argument values on return:
* @param status
* status of next command pending completion
* @param cmd_code
* next command pending completion.
* @param client context registered ARM_CFSTORE_DRIVER::(*Initialize)()
* @param hkey
* unused.
*/
ARM_CFSTORE_STATUS (*GetStatus)(void);
/**
* @brief get the value length from an open key handle
*
* @param hkey
* open handle of key for which to get value length
* @param value_len, the location in which to store the value length.
* @return return_value
* See REFERENCE_1 and REFERENCE_2.
* ARM_CFSTORE_DRIVER::(*GetValueLen)() asynchronous completion command code
* (*ARM_CFSTORE_CALLBACK) function argument values on return:
* @param status
* ARM_DRIVER_OK => success, value_len contains length value.
* else failure.
* @param cmd_code == CFSTORE_OPCODE_GET_VALUE_LEN
* @param client context, registered ARM_CFSTORE_DRIVER::(*Initialize)()
* @param hkey supplied to the GetValueLen() call at hkey.
*
*/
int32_t (*GetValueLen)(ARM_CFSTORE_HANDLE hkey, ARM_CFSTORE_SIZE *value_len);
/**
* @brief Initialize the Configuration Store
*
* This function:
* - initialised the configuration store service
* - allows the client to subscribe to event notifications, in particular
* the asynchronous completion events for the driver dispatch interface
* (see ARM_CFSTORE_OPCODE).
*
* The configuration store should be initialised as follows:
* drv->initialise(client_callback, client_callback_context);
* drv->PowerControl(ARM_POWER_FULL)
* where:
* - client_callback is a client implemented callback function.
* - client_callback_context is a client registered context that
* will be supplied as an argument to the client_callback
* when called.
* - PowerControl indicates that any underlying system services
* that are in the low power state should be powered up.
*
* The configuration store should be de-initialised as follows:
* drv->PowerControl(ARM_POWER_OFF)
* drv->Deinitialise();
*
* @param client_callback
* this is a client implemented callback function for
* receiving asynchronous event notifications (see
* ARM_CFSTORE_CALLBACK). NULL indicates client does
* not subscribed to event notifications.
*
* @param client_callback_context
* this is the client registered context that
* will be supplied as an argument to the client_callback
* when called. This argument can be NULL.
*
* @return return_value
* See REFERENCE_1 and REFERENCE_2
* ARM_CFSTORE_DRIVER::(*Initialize)() asynchronous completion command code
* (*ARM_CFSTORE_CALLBACK) function argument values on return:
* @param status
* ARM_DRIVER_OK => success, configuration store initialised,
* else failure
* @param CFSTORE_OPCODE_INITIALIZE
* @param client context registered ARM_CFSTORE_DRIVER::(*Initialize)()
* @param hkey, unused.
*
*/
int32_t (*Initialize)(ARM_CFSTORE_CALLBACK callback, void* client_context);
/**
* @brief Function to set the target configuration store power state.
*
* @param state
* \ref ARM_POWER_STATE. The target power-state for the
* configuration store. The parameter state can have the
* following values:
* - ARM_POWER_FULL => set the mode to full power state
* - ARM_POWER_LOW => set the mode to low power state
* - ARM_POWER_OFF => set the mode to off power state
*
* @return return_value
* See REFERENCE_1 and REFERENCE_2.
* CFSTORE_OPCODE_POWER_CONTROL
* ARM_CFSTORE_DRIVER::(*PowerControl)() asynchronous completion command code
* (*ARM_CFSTORE_CALLBACK) function argument values on return:
* @param status
* ARM_DRIVER_OK => success, power control set, else failure.
* @param cmd_code == CFSTORE_OPCODE_POWER_CONTROL
* @param client context, registered ARM_CFSTORE_DRIVER::(*Initialize)()
* @param hkey, unused.
*/
int32_t (*PowerControl)(ARM_POWER_STATE state);
/**
* @brief read the value data associated with a specified key.
*
* @param hkey
* IN: the handle returned from a previous call to (*Open)() to
* get a handle to the key
* @param data
* IN: a pointer to a data buffer supplied by the caller for CFSTORE to
* fill with value data
* OUT: on ARM_DRIVER_OK the data is (or will be when asynchronously
* completed) available in the buffer. The data will be read from
* the current form the current location (see (*Rseek)().
* @param len
* IN: the client specifies the length of the buffer available at data
* OUT: the CFSTORE specifies how many octets have been stored in the
* supplied buffer. Note fewer octets may be stored than the input len
* depending on the CFSTORE internal representation of the value.
*
* @return return_value
* See REFERENCE_1 and REFERENCE_2.
* return_value == ARM_DRIVER_OK (==0) => asynchronous
* transaction pending.
* return_value > 0 => synchronous completion of read with the
* number of bytes read == return_value
* return_value < 0, error condition.
*
* ARM_CFSTORE_DRIVER::(*Read)() asynchronous completion command code
* (*ARM_CFSTORE_CALLBACK) function argument values on return:
* @param status
* >= 0 => success with number of bytes read as indicated by
* the value of status
* < 0 => error, data in the data buffer is undefined, len is
* undefined.
* @param cmd_code == CFSTORE_OPCODE_READ
* @param client context, registered ARM_CFSTORE_DRIVER::(*Initialize)()
* @param hkey, unused.
*/
int32_t (*Read)(ARM_CFSTORE_HANDLE hkey, void* data, ARM_CFSTORE_SIZE* len);
/**
* @brief Open a key-value object for future operations.
*
* @param key_name
* IN: zero terminated string specifying the key name.
* @param flags
* can open a RW key in read only mode.
* @param hkey
* IN: pointer to client owned buffer of CFSTORE_HANDLE_BUFSIZE
* bytes
* OUT: on success, hkey is a valid handle to an open KV.
*
* @return return_value
* See REFERENCE_1 and REFERENCE_2.
* ARM_CFSTORE_DRIVER::(*Open)() asynchronous completion command code
* (*ARM_CFSTORE_CALLBACK) function argument values on return:
* @param status
* ARM_DRIVER_OK => success, KV opened, else failure.
* @param cmd_code == CFSTORE_OPCODE_OPEN
* @param client context, registered ARM_CFSTORE_DRIVER::(*Initialize)()
* @param hkey now contains returned handle to newly opened key.
*/
int32_t (*Open)(const char* key_name, ARM_CFSTORE_FMODE flags, ARM_CFSTORE_HANDLE hkey);
/**
* @brief move the position of the read pointer within a value
*
* @param hkey
* IN: the key referencing the value data for which the read
* location should be updated. Note that this function can
* only be called on pre-existing keys opened with read-only
* flag. Performing a seek operation on a writable key will fail.
* @param offset
* IN: the new offset position from the start of the value data
*
* @return return_value
* See REFERENCE_1 and REFERENCE_2.
* ARM_CFSTORE_DRIVER::(*Rseek)() asynchronous completion command code
* (*ARM_CFSTORE_CALLBACK) function argument values on return:
* @param status
* >=0 => success, read location set, else failure.
* upon success, the function returns the current read
* location measured from the beginning of the data value.
* <0 => error
* @param cmd_code == CFSTORE_OPCODE_RSEEK
* @param client context, registered ARM_CFSTORE_DRIVER::(*Initialize)()
* @param hkey, unused.
*/
int32_t (*Rseek)(ARM_CFSTORE_HANDLE hkey, ARM_CFSTORE_OFFSET offset);
/**
* @brief Function to de-initialise the Configuration Store
*
* @return return_value
* See REFERENCE_1 and REFERENCE_2
* CFSTORE_OPCODE_UNINITIALIZE
* ARM_CFSTORE_DRIVER::(*Uninitialize)() asynchronous completion command code
* (*ARM_CFSTORE_CALLBACK) function argument values on return:
* @param status
* ARM_DRIVER_OK => success, read location set, else failure.
* @param cmd_code == CFSTORE_OPCODE_UNINITIALIZE
* @param client context, registered ARM_CFSTORE_DRIVER::(*Initialize)()
* @param hkey, unused.
*/
int32_t (*Uninitialize)(void);
/**
* @brief write the value data associated with a specified key
*
* @note Note that Write() only supports sequential-access.
*
* @param hkey
* IN: the key for which value data will be written
* @param data
* IN: a pointer to a data buffer supplied by the caller for CFSTORE to
* write as the binary blob value data.
* Async operation: the buffer must be available until after
* completion notification is received by the client.
* @param len
* IN: the client specifies the length of the data buffer available.
* len must not exceed the value_len field specified when the
* KV pair was created.
* OUT: the CFSTORE specifies how many octets have been stored.
* Note that fewer octets may be stored than the input len
* depending on the CFSTORE internal representation of the value.
* Async operation: the len storage location must be available
* until after completion notification is received by the client.
*
* @return return_value
* See REFERENCE_1 and REFERENCE_2.
* return_value == ARM_DRIVER_OK (==0) => asynchronous
* transaction pending.
* return_value > 0 => synchronous completion of write with the
* number of bytes written == return_value
* return_value < 0, error condition.
*
* ARM_CFSTORE_DRIVER::(*Write)() asynchronous completion
* (*ARM_CFSTORE_CALLBACK) function argument values on return:
* @param status
* >= 0 => success with the number bytes written equal to the value
* of the return status
* ARM_CFSTORE_CALLBACK status argument < 0 => error
* @param cmd_code == CFSTORE_OPCODE_WRITE
* @param client context, registered ARM_CFSTORE_DRIVER::(*Initialize)()
* @param hkey, unused.
*/
int32_t (*Write)(ARM_CFSTORE_HANDLE hkey, const char* data, ARM_CFSTORE_SIZE* len);
} const ARM_CFSTORE_DRIVER;
extern ARM_CFSTORE_DRIVER cfstore_driver;
#ifdef __cplusplus
}
#endif
#endif /* __CONFIGURATION_STORE_H */

View File

@ -0,0 +1,219 @@
# Configuration Store Getting Started
Author: Simon Hughes
# Overview
## Executive Summary
This document describes how to get started with the configuration store module.
## Terminology
The terminology used throughout this document is defined on the [CFSTORE Terminology](https://github.com/ARMmbed/configuration-store/blob/master/doc/design/configuration_store_terminology.md) page.
# CFSTORE : Getting started
This is the link to the configuration store github repo, with links to further documentation from the top level readme.md is [here.](https://github.com/ARMmbed/configuration-store/README.md)
The documentation explains how the API works. There are also a number of test cases in the repo which can be used as examples of how to use the API.
This is the project plan is [here.](https://github.com/ARMmbed/configuration-store/blob/master/doc/design/configuration_store_project.md)
* Milestone 1 (SRAM version) has been released and tagged MBED_V_0_1_0.
* Milestone 2 (CFSTORE Flash Journal Integration) has been released and tagged MBED_V_0_2_0.
# CFSTORE : Building the Module
First take a clone of the configuration store github repository from the tag of the last release. For example:
```
simhug01@E107851:/d/sdh_dev$ git clone git@github.com:ARMmbed/configuration-store.git
```
Then cd into the configuration-store sub-dir and get a list of the tags
```
simhug01@E107851:/d/sdh_dev$ cd configuration-store
simhug01@E107851:/d/sdh_dev/configuration-store $ git tag -l
MBED_V_0_1_0
MBED_V_0_2_0
```
The current release is MBED_V_0_2_0 (CFSTORE-flash journal integrated version). Checkout this version for evaluation:
```
simhug01@E107851:/d/sdh_dev/configuration-store $ git checkout tags/MBED_V_0_2_0
```
configuration-store depends on modules published in the private yotta registry and therefore you need access to this registry. To login to the yotta private use the following command:
```
simhug01@E107851:/d/sdh_dev/configuration-store $ yotta login --registry https://yotta-private.herokuapp.com --apikey=873_b8isfdns3684_327t2evut3r
```
Set the yotta target:
```
simhug01@E107851:/d/sdh_dev/configuration-store $ yt target frdm-k64f-gcc
```
Now install the yotta dependencies (which will require access to the yotta private registry to succeed):
```
simhug01@E107851:/d/sdh_dev/configuration-store $ yt install
```
You should see something like the following for the output to yotta list, which shows the CFSTORE module dependency graph:
```
simhug01@E107851:/d/datastore/public/jobs/yr2016/2247/sdh_dev_8/configuration-store$ yt list
configuration-store 0.2.0
|_ mbed-drivers 1.5.0
| |_ mbed-hal 1.3.0 yotta_modules\mbed-hal
| | \_ mbed-hal-freescale 1.1.0 yotta_modules\mbed-hal-freescale
| | \_ mbed-hal-ksdk-mcu 1.3.0 yotta_modules\mbed-hal-ksdk-mcu
| | |_ uvisor-lib 2.1.2 yotta_modules\uvisor-lib
| | \_ mbed-hal-k64f 1.3.0 yotta_modules\mbed-hal-k64f
| | \_ mbed-hal-frdm-k64f 1.1.1 yotta_modules\mbed-hal-frdm-k64f
| |_ cmsis-core 1.2.0 yotta_modules\cmsis-core
| | \_ cmsis-core-freescale 1.1.0 yotta_modules\cmsis-core-freescale
| | \_ cmsis-core-k64f 1.1.0 yotta_modules\cmsis-core-k64f
| |_ ualloc 1.3.0 yotta_modules\ualloc
| | \_ dlmalloc 1.1.0 yotta_modules\dlmalloc
| |_ minar 1.3.0 yotta_modules\minar
| | \_ minar-platform 1.1.0 yotta_modules\minar-platform
| | \_ minar-platform-mbed 1.3.0 yotta_modules\minar-platform-mbed
| |_ core-util 1.8.0 yotta_modules\core-util
| \_ compiler-polyfill 1.3.0 yotta_modules\compiler-polyfill
|_ flash-journal-strategy-sequential 0.3.0
| \_ flash-journal 0.3.0 yotta_modules\flash-journal
| \_ flash-abstraction 0.3.0 yotta_modules\flash-abstraction
| \_ mtd-k64f 0.3.0 yotta_modules\mtd-k64f
|_ unity 2.2.0 (test dependency)
| \_ utest 1.12.2 yotta_modules\utest
\_ greentea-client 0.1.8 (test dependency)
```
Now build configuration-store:
```
simhug01@E107851:/d/sdh_dev/configuration-store $ yt build
```
The above command builds CFSTORE with support for asynchronous mode flash-journal. If you would like synchronous mode support then use
the following build command:
```
simhug01@E107851:/d/sdh_dev/configuration-store $ yotta --config='{"config":{"hardware":{"mtd":{"async":{"ops":0}}}}}' build
```
Having built successfully, you can now test with the following mbed-greentea command:
```
simhug01@E107851:/d/sdh_dev/configuration-store $ mbedgt -V
```
The test results should be similar to the test results form the [Jenkins CFSTORE Build and Test Job](http://e108747.cambridge.arm.com:8080/job/configuration-store-nightly-build-and-test/) the summary of which is provided below for reference:
```
mbedgt: test suite report:
+---------------+---------------+----------------------------------+--------+--------------------+-------------+
| target | platform_name | test suite | result | elapsed_time (sec) | copy_method |
+---------------+---------------+----------------------------------+--------+--------------------+-------------+
| frdm-k64f-gcc | K64F | configuration-store-test-acl | OK | 10.26 | shell |
| frdm-k64f-gcc | K64F | configuration-store-test-add_del | OK | 20.78 | shell |
| frdm-k64f-gcc | K64F | configuration-store-test-close | OK | 13.02 | shell |
| frdm-k64f-gcc | K64F | configuration-store-test-create | OK | 12.8 | shell |
| frdm-k64f-gcc | K64F | configuration-store-test-find | OK | 24.31 | shell |
| frdm-k64f-gcc | K64F | configuration-store-test-flash | OK | 11.27 | shell |
| frdm-k64f-gcc | K64F | configuration-store-test-flush | OK | 12.51 | shell |
| frdm-k64f-gcc | K64F | configuration-store-test-flush2 | OK | 12.53 | shell |
| frdm-k64f-gcc | K64F | configuration-store-test-misc | OK | 14.64 | shell |
| frdm-k64f-gcc | K64F | configuration-store-test-open | OK | 14.5 | shell |
| frdm-k64f-gcc | K64F | configuration-store-test-read | OK | 12.78 | shell |
| frdm-k64f-gcc | K64F | configuration-store-test-write | OK | 12.88 | shell |
+---------------+---------------+----------------------------------+--------+--------------------+-------------+
mbedgt: test suite results: 12 OK
mbedgt: test case report:
+---------------+---------------+----------------------------------+------------------------------+--------+--------+--------+--------------------+
| target | platform_name | test suite | test case | passed | failed | result | elapsed_time (sec) |
+---------------+---------------+----------------------------------+------------------------------+--------+--------+--------+--------------------+
| frdm-k64f-gcc | K64F | configuration-store-test-acl | CFSTORE_ACL_test_01 | 1 | 0 | OK | 0.1 |
| frdm-k64f-gcc | K64F | configuration-store-test-add_del | ADD_DEL_test_01 | 1 | 0 | OK | 0.1 |
| frdm-k64f-gcc | K64F | configuration-store-test-add_del | ADD_DEL_test_02 | 1 | 0 | OK | 0.1 |
| frdm-k64f-gcc | K64F | configuration-store-test-add_del | ADD_DEL_test_03 | 1 | 0 | OK | 0.1 |
| frdm-k64f-gcc | K64F | configuration-store-test-add_del | ADD_DEL_test_04 | 1 | 0 | OK | 0.1 |
| frdm-k64f-gcc | K64F | configuration-store-test-add_del | ADD_DEL_test_05 | 1 | 0 | OK | 0.11 |
| frdm-k64f-gcc | K64F | configuration-store-test-add_del | ADD_DEL_test_06 | 1 | 0 | OK | 0.1 |
| frdm-k64f-gcc | K64F | configuration-store-test-add_del | ADD_DEL_test_07_end | 1 | 0 | OK | 0.25 |
| frdm-k64f-gcc | K64F | configuration-store-test-add_del | ADD_DEL_test_07_start | 1 | 0 | OK | 0.05 |
| frdm-k64f-gcc | K64F | configuration-store-test-add_del | ADD_DEL_test_08_end | 1 | 0 | OK | 0.54 |
| frdm-k64f-gcc | K64F | configuration-store-test-add_del | ADD_DEL_test_08_start | 1 | 0 | OK | 0.05 |
| frdm-k64f-gcc | K64F | configuration-store-test-add_del | ADD_DEL_test_09_end | 1 | 0 | OK | 4.94 |
| frdm-k64f-gcc | K64F | configuration-store-test-add_del | ADD_DEL_test_09_start | 1 | 0 | OK | 0.05 |
| frdm-k64f-gcc | K64F | configuration-store-test-add_del | ADD_DEL_test_10 | 1 | 0 | OK | 0.11 |
| frdm-k64f-gcc | K64F | configuration-store-test-close | CLOSE_test_01_end | 1 | 0 | OK | 0.51 |
| frdm-k64f-gcc | K64F | configuration-store-test-close | CLOSE_test_01_start | 1 | 0 | OK | 0.04 |
| frdm-k64f-gcc | K64F | configuration-store-test-create | CREATE_test_01_end | 1 | 0 | OK | 0.19 |
| frdm-k64f-gcc | K64F | configuration-store-test-create | CREATE_test_01_start | 1 | 0 | OK | 0.05 |
| frdm-k64f-gcc | K64F | configuration-store-test-find | FIND_test_01 | 1 | 0 | OK | 0.1 |
| frdm-k64f-gcc | K64F | configuration-store-test-find | FIND_test_02 | 1 | 0 | OK | 0.1 |
| frdm-k64f-gcc | K64F | configuration-store-test-find | FIND_test_03_end | 1 | 0 | OK | 10.53 |
| frdm-k64f-gcc | K64F | configuration-store-test-find | FIND_test_03_start | 1 | 0 | OK | 0.05 |
| frdm-k64f-gcc | K64F | configuration-store-test-find | FIND_test_04 | 1 | 0 | OK | 0.09 |
| frdm-k64f-gcc | K64F | configuration-store-test-find | FIND_test_05_end | 1 | 0 | OK | 0.05 |
| frdm-k64f-gcc | K64F | configuration-store-test-find | FIND_test_05_start | 1 | 0 | OK | 0.05 |
| frdm-k64f-gcc | K64F | configuration-store-test-flash | flash_journal_async_test_01 | 1 | 0 | OK | 0.22 |
| frdm-k64f-gcc | K64F | configuration-store-test-flush | initialize | 1 | 0 | OK | 0.03 |
| frdm-k64f-gcc | K64F | configuration-store-test-flush2 | CFSTORE_FLUSH2_flush | 1 | 0 | OK | 0.17 |
| frdm-k64f-gcc | K64F | configuration-store-test-flush2 | CFSTORE_FLUSH2_init_on_entry | 1 | 0 | OK | 0.06 |
| frdm-k64f-gcc | K64F | configuration-store-test-misc | MISC_test_00_end | 1 | 0 | OK | 0.04 |
| frdm-k64f-gcc | K64F | configuration-store-test-misc | MISC_test_00_start | 1 | 0 | OK | 0.05 |
| frdm-k64f-gcc | K64F | configuration-store-test-misc | MISC_test_01 | 1 | 0 | OK | 0.04 |
| frdm-k64f-gcc | K64F | configuration-store-test-misc | MISC_test_02 | 1 | 0 | OK | 0.04 |
| frdm-k64f-gcc | K64F | configuration-store-test-misc | MISC_test_03_end | 1 | 0 | OK | 0.4 |
| frdm-k64f-gcc | K64F | configuration-store-test-misc | MISC_test_03_start | 1 | 0 | OK | 0.05 |
| frdm-k64f-gcc | K64F | configuration-store-test-misc | MISC_test_04_end | 1 | 0 | OK | 0.24 |
| frdm-k64f-gcc | K64F | configuration-store-test-misc | MISC_test_04_start | 1 | 0 | OK | 0.05 |
| frdm-k64f-gcc | K64F | configuration-store-test-misc | MISC_test_05_end | 1 | 0 | OK | 0.05 |
| frdm-k64f-gcc | K64F | configuration-store-test-misc | MISC_test_05_start | 1 | 0 | OK | 0.05 |
| frdm-k64f-gcc | K64F | configuration-store-test-open | OPEN_test_01_end | 1 | 0 | OK | 0.26 |
| frdm-k64f-gcc | K64F | configuration-store-test-open | OPEN_test_01_start | 1 | 0 | OK | 0.04 |
| frdm-k64f-gcc | K64F | configuration-store-test-open | OPEN_test_02_end | 1 | 0 | OK | 0.05 |
| frdm-k64f-gcc | K64F | configuration-store-test-open | OPEN_test_02_start | 1 | 0 | OK | 0.05 |
| frdm-k64f-gcc | K64F | configuration-store-test-open | OPEN_test_100 | 1 | 0 | OK | 0.1 |
| frdm-k64f-gcc | K64F | configuration-store-test-open | OPEN_test_101 | 1 | 0 | OK | 0.1 |
| frdm-k64f-gcc | K64F | configuration-store-test-open | OPEN_test_102 | 1 | 0 | OK | 0.09 |
| frdm-k64f-gcc | K64F | configuration-store-test-open | OPEN_test_103 | 1 | 0 | OK | 0.1 |
| frdm-k64f-gcc | K64F | configuration-store-test-open | OPEN_test_104 | 1 | 0 | OK | 0.1 |
| frdm-k64f-gcc | K64F | configuration-store-test-open | OPEN_test_105 | 1 | 0 | OK | 0.1 |
| frdm-k64f-gcc | K64F | configuration-store-test-read | READ_test_01_end | 1 | 0 | OK | 0.05 |
| frdm-k64f-gcc | K64F | configuration-store-test-read | READ_test_01_start | 1 | 0 | OK | 0.04 |
| frdm-k64f-gcc | K64F | configuration-store-test-read | READ_test_02 | 1 | 0 | OK | 0.1 |
| frdm-k64f-gcc | K64F | configuration-store-test-write | WRITE_test_01_end | 1 | 0 | OK | 0.04 |
| frdm-k64f-gcc | K64F | configuration-store-test-write | WRITE_test_01_start | 1 | 0 | OK | 0.04 |
| frdm-k64f-gcc | K64F | configuration-store-test-write | WRITE_test_02_end | 1 | 0 | OK | 0.04 |
| frdm-k64f-gcc | K64F | configuration-store-test-write | WRITE_test_02_start | 1 | 0 | OK | 0.05 |
+---------------+---------------+----------------------------------+------------------------------+--------+--------+--------+--------------------+
mbedgt: test case results: 56 OK
mbedgt: completed in 177.39 sec
simhug01@E107851:/d/datastore/public/jobs/yr2016/2247/sdh_dev_8/configuration-store$```
# FAQ
## Q: What version has been published in the yotta registry?
A: Version 0.1.0 is the latest version published in the yotta registry.
## Q: Does Configuration-Store work with mbed OS 16.3?
A: Yes
## Q: Does Configuration-Store work with mbed OS 15.11?
A: Yes

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,17 @@
# Configuration Store Low Level Design
Author: Simon Hughes
# Revision History
20160127: first version.
# API
## CFSTORE Client API interface
The CFSTORE client API interface is represented diagramatically in the following UML digarm
![CFSTORE_UML_HLD_01](https://github.com/ARMmbed/configuration-store/blob/master/doc/design/pics/configuration_store_hld_api_summary.jpg)
The above UML diagram shows the low level design of the CFSTORE API.

View File

@ -0,0 +1,107 @@
# IoT\Product Requirements\IOTPREQ-334: Design of the mbed OS Configuration Store
The Configuration Store forms a building block of mbed OS. It forms a central repository where configuration for many modules can be placed. This hides the complexity of implementing a similar system from each module owner and it encourages rich configuration interfaces for the developer.
## Background
Configuration is a common operation in embedded systems. It happens at compile time, and run time. Sometimes runtime configuration is persistent across resets, sometimes it is not. Frequently, configuration data is sensitive, such as WiFi passwords, API tokens, encryption keys, and the like. Some configuration is only accessed once in a while. Other configuration must be changed and accessed very frequently and with very little overhead.
## Sample Use Cases
Several sample use cases were used to derive the requirements of the Configuration Store
### Network Configuration
Network configuration varies by network type. As a result, presenting a common interface for network configuration is difficult. Using a pointer to a configuration blob simplifies the Network API and concentrates complexity and knowledge about the network implementation in the network driver and the configuration mechanism in the application.
Networks need hierarchical configuration. A flat model starts to fail when multiple interfaces with similar parameters are used. Most networks need non-volatile, runtime configuration, but Wi-Fi demonstrates this need the best: configuring a Wi-Fi network on a device requires, at minimum, selecting a SSID and entering a password. These must persist past power cycles. Network configuration needs to support overrides. When configuring a network device, it should be possible to recover old configuration until new configuration is committed to non-volatile storage. A network device should ship with sensible default configuration (e.g. DHCP), but this should be overridden when necessary.
Network configuration requires many kinds of value: integer (Channel number), string (SSID), binary blob (hashed password). There is an argument for floating point (transmit power), but this can be done via integer and fixed-point.
### Credential Storage
Storing credentials requires secure access to the storage. As a result, it must be possible to apply permissions to parts or the whole of the tree. Exactly how these permissions work is TBD.
### System initialization
It is conceptually possible to reduce the number of code versions by using more configuration. For example, clock configuration can be done using the config mechanism. If this is the case, then the permanent config store must be accessible early in the boot process, when clocks are configured.
It is necessary to provide a list of modules that explicitly require an init function to be called. To make this possible, those functions could be listed, in order in the configuration store. This has some advantages over conventional approaches, such as linker sections, in that it provides a much more readable way to inspect the modules that are being initialized.
### Resource Management
In the future, a resource manager may be an integral part of mbed OS. In this instance, the resource manager needs in-depth information about how peripherals are connected to clocks and power domains. The Configuration Store should contain this information.
### Peripheral Configuration
If the system interface API (mbed-drivers) were aware of the Configuration Store, then it would be straight-forward to encode defaults via config. This would allow the interface API to extract application-dependent, but still sensible defaults from the config store when they are omitted. This could be combined with Resource Management to automatically correct for clock scaling of buses or the core.
## Design Goals
A number of design goals must be met for the configuration store to be used widely. These design goals are brought out of
The configuration store must:
* hierarchical
* configuration data must be groupable
* groups of configuration data should be handled as a unit
* support multiple degrees of persistence
* permanent
* non-volatile
* volatile
* allow config overrides between persistence levels (volatile being the highest priority and permanent the lowest)
* support multiple sources of configuration
* yotta config
* application configuration
* runtime configuration
* remote configuration (e.g. CBOR blobs returned by a server)
* support multiple kinds of values
* integer
* floating point
* string
* arbitrary binary blob
* be compatible with [yotta config](http://yottadocs.mbed.com/reference/config.html) output
* Any format to which JSON is convertible fulfills this requirement
* globally accessible by any module
* able to enforce permissions on entire branches of the config data
* accessible early
* Low memory footprint for parsing
* Low CPU overhead for data accesses
## CBOR
The simplest approach to guaranteeing interoperability with yotta config is to ensure that the format of the Config Store is convertible to JSON. There are several options for this, but the most promising is CBOR. CBOR may not be appropriate for an in-memory representation, but it is likely appropriate for both permanent and non-volatile representations.
Selection of CBOR as an intermediate representation also satisfies the hierarchy requirement and multiple value requirement. CBOR may require a significant CPU/memory tradeoff to be made during parse operations, but there are several mitigation strategies that can be employed.
## Applying permissions
It may be very difficult to apply permissions to a CBOR tree directly. A review of permission management with the uVisor team is necessary.
## Configuration Overrides
To ensure that the correct configuration is always used, permanent configuration must be overriden by non-volatile configuration. Likewise, non-volatile configuration must be overridden by volatile configuration.
The exact method of overrides is TBD.
An initial assessment of this suggests that it would be feasible to accomplish overrides by using only two layers instead of three. On boot, the non-volatile storage is parsed into the volatile storage area. When a node is deleted and its parent is a non-volatile storage element, the key of the deleted node should be re-parsed from non-volatile storage into the location of the deleted node.
## Early Accessibility
Configuration Store initialization must occur after C library init, but before static object initialization, so that static objects can access the Configuration Store. It is possible that a limited version of the Configuration Store could be used prior to C library init, but it would need to be written very carefully.
## Configuration Sources
In some cases, it might be desirable to treat configuration delivered by a server as non-volatile. Changes can be applied locally or requested remotely, but the server is always queried on startup to obtain the configuration data. In general, yotta config will aggregate all configuration data and supply it to the build system in a single JSON file.
Where credentials are provisioned at time of programming, it might be desirable to supply an alternative method of installing a source of configuration. The method for using this alternative source is TBD.
# Low Level Design
The Configuration Store is built in three tiers:
* Permanent Storage
* Non-volatile Storage
* Volatile Storage
## Permanent Storage
Permanent configuration is generated as a CBOR translation of the JSON file created by yotta config. It is linked into the final executable. Parsing permanent storage requires a CPU/memory tradeoff to be made. Indices into the CBOR object can be retained either in RAM or ROM to reduce parsing time at the expense of additional memory. Parsing could be done on-demand or in advance.
## Non-volatile Storage
Non-volatile storage has no specific format requirements, however reusing CBOR parsing from permanent storage may be a good solution. When a change is committed to non-volatile storage, the non-volatile portions of the Configuration store must be re-encoded for storage to flash.
## Volatile Storage
There are two possibilities for implementing volatile storage: either a document object model, or a flat key-value store with recognition of prefixes. The document object model will present a familiar interface for web programmers, and occupy less memory than a flat key-value store. Therefore, a document object model is the preferred solution.
### Objects containing constant data
For most operations, the Configuration Store must copy both keys and values into its own storage. In some cases, it may be advantageous to only retain a reference to external data, such as in cases where external data has been stored in a nonvolatile medium. While this is not an immediate requirement, care should be taken not to prevent this future optimization.
# References
- IoT\Product Requirements\IOTPREQ-334 ![CFSTORE_PROD_REQ_REF_01](http://jira.arm.com/browse/IOTPREQ-334)

View File

@ -0,0 +1,99 @@
# Configuration Store Project Documentation
# Feature 1 (FT1): SRAM-backed CFSTORE (Complete)
This feature includes the following:
- CFSTORE API implementation backed by SRAM (non-persistent).
- Synchronous mode implementation.
- Supported on the K64F target.
- mbed greentea tests demonstrating how to use the API.
- High Level Design Document present.
- Alpha grade code quality (testing giving ~50% code coverage).
- area_0 SRAM initialisation using target.json generated CFSTORE_SRAM_START_ADDR & CFSTORE_SRAM_SIZE #defines rather than malloc().
## Features Not Included in this Feature (Complete)
This feature does not including the following:
- Integration with the Flash Abstraction Layer.
- Integration with uVisor.
# Feature 2: CFSTORE Flash Ping-Pong Alpha (Complete)
- CFSTORE API implementation backed by SRAM and Non-Volatile (NV) storage.
- Flash-jounral asynchronous mode support.
- Flash-jounral synchronous mode support.
- Flash-jounral supported on the K64F target.
- High Level Design Document present.
# Feature 3.0: CFSTORE+SRAM with mbedOS Q2 Release (Complete)
- CFSTORE SRAM version ported to mbedOS Q2 Release.
# Feature 3.1: CFSTORE + Flash-Journal + mbedOS Q2 Release.
- CFSTORE with Flash-Journal integration ported to mbedOS Q2 Release.
# Feature 4: CFSTORE + uvisor + mbedOS Q2 Release
- CFSTORE with Flash-Journal integration ported to mbedOS Q2 Release.
- uvisor integration working
# Guidance for Submitting Issues
Here are the guidelines for submitting issues to the configuration-store repository:
- If you have an issue with configuration-store then please file an issue at github.com/armmbed/configuration-store.git
- The issue should be filed with a stand-alone testcase or sample application that only depends on configuration-store and shows the fault on the target platform.
- The issue should include the following information under separate SUMMARY and DETAILS headings:
```
SUMMARY
=======
APPLCIATION/Library NAME: <e.g. configuration_store, example3, myappname>
OS VERSION: <e.g. MBEDOSv3>
TARGET: <e.g. k64f>
TOOLCHAIN: <e.g. GCC_ARM, ARM>
DESCRIPTION: <e.g. a 1-line summary description of the problem >
MODULE DEPENDENCIES: <e.g. the version of the modules used to build the application, output from yotta ls, etc>
DETAILS
=======
<step by step guide about how to build and test the provided resources so as to reproduce the problem.
CODE
====
<details of supplied code sample showing problem>
```
# References
## Useful Documents
- [KeyValueStorage.md](https://github.com/ARMmbed/device-security/blob/master/KeyValueStorage.md)
- [uVisor README.md](https://github.com/ARMmbed/uvisor/blob/master/README.md)
- [FlashAbstraction](https://github.com/ARMmbed/device-security/blob/master/FlashAbstraction.md)
## Useful GitHub Repositories
- [device-security](https://github.com/ARMmbed/device-security)
## Useful References
- [mbed Coding Standard](https://developer.mbed.org/teams/SDK-Development/wiki/mbed-sdk-coding-style)
- [Security Ref](http://resources.sei.cmu.edu/asset_files/BookChapter/2005_009_001_52692.pdf)
- [Security Ref](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1255.pdf)
## Useful Jira Tickets
- [Configuration Store for mbed OS IOT Product Requirements IOTPREQ-334](http://jira.arm.com/browse/IOTPREQ-334)

View File

@ -0,0 +1,410 @@
# ENGINEERING REQUIREMENTS
## Definition of Terms
https://github.com/ARMmbed/configuration-store/blob/master/doc/design/configuration_store_terminology.md
The [CFSTORE Terminology][CFSTORE_TERM] defines terms used in this document.
## Secure Key Value Storage\Rationale (REQ-1.xx-SKVS-R) Requirements
##### REQ-1.01-SKVS-R:
The CFSTORE must provide a non-volatile, hardware-independent secure storage
service that can be used by CFSTORE API clients for storing data owned
by a client security context (uvisor box).
##### REQ-1.02-SKVS-R:
Clients of the CFSTORE API must be security contexts (boxes) so that security
policies can be enforced.
##### REQ-1.03-SKVS-R:
The CFSTORE design values simplicity over complexity to promote security by
minimizing the attack surface to secure data.
##### REQ-1.04-SKVS-R:
The CFSTORE must be implemented as a uvisor secure box.
##### REQ-1.05-SKVS-R:
The CFSTORE must support the use of Access Control Lists for policing access to
secure data.
##### REQ-1.06-SKVS-R:
The CFSTORE must support the storage of a {key, value} tuples where
- the key is a zero terminated string of arbitrary length.
- the value is a binary blob of data of arbitrary length
The {key, value} tuple is a CFSTORE object.
###### Discussion
A null key (i.e. "" which includes a terminating null) is not a valid because the null string is not a valid security_prefix_name.
##### REQ-1.07-SKVS-R: CFSTORE Stores Binary Blobs
The CFSTORE must provide support so that other (client) components can implement
more complex storage types other than a binary blob e.g. by
wrapping the underlying CFSTORE {key, value} tuple with additional
type information.
##### REQ-1.08-SKVS-R: CFSTORE Key Structure as Name Strings
This requirement has been removed as it is a subset of REQ-1.06-SKVS-R [REQ-1.06-SKVS-R].
##### REQ-1.09-SKVS-R: Key Creation and Ownership Part 1
CFSTORE keys must be owned by the security context. A security context (box)
is identified by a unique security_name_prefix and this identifier
must be used when the key is created. CFSTORE must support the use of the
security_name_prefix as the leading substring of the CFSTORE key string, in which
case the key_name_prefix is the security_name_prefix and identifies the
owner of the key.
##### REQ-1.10-SKVS-R: Security Context
In order to create objects in the CFSTORE, a security context (box) must have
a security_name_prefix.
##### REQ-1.11-SKVS-R: CFSTORE object
This requirement has been removed as it is a duplicate of REQ-1.10-SKVS-R
## Secure Key Value Storage High Level Design (REQ-1.2.xx-SKVS-HLD) Requirements
##### REQ-1.2.01-SKVS-HLD:
The CFSTORE must be able to detect the available types of storage media
in the system and report associated storage media attributes.
##### REQ-1.2.02-SKVS-HLD:
The CFSTORE may report the following storage media data retention level attribute,
when available:
- only during device activity
- during sleep
- during deep-sleep
- battery-backed, device can be powered off
- internal non-volatile memory
- external non-volatile memory
##### REQ-1.2.03-SKVS-HLD:
For a particular storage medium, the CFSTORE may report the following device
data security protection features, when available:
- no security, just safety
- write-once-read-only-memory (WORM)
- against internal software attacks using ACLs
- roll-back protection
- immovable (for internal memory mapping, to stop relocated block to move).
This attribute must only be set provided:
- the device memory is mapped into the CPU address space
- access is only granted to specific CFSTORE API system clients e.g. FOTA,
DMA.
- hardening against device software (malware running on the device)
- hardening against board level attacks (debug probes, copy protection
fuses)
- hardening against chip level attacks (tamper-protection)
- hardening against side channel attacks
- tamper-proof memory (will be deleted on tamper-attempts using board level
or chip level sensors)
##### REQ-1.2.04-SKVS-HLD:
The CFSTORE may be used to implement KV storage protection services
(e.g. flash image roll-back protection, confidentiality) for off-chip
(external) storage media (e.g. SPI/I2C/NAND Flash).
##### REQ-1.2.05-SKVS-HLD:
The device data security protection immovable attribute may only be set
## Secure Key Value Storage\High Level API Description\Key Value Storage (REQ-3.1.xx-SKVS-HLAPID-KVS) Requirements.
##### REQ-3.1.01-SKVS-HLAPID-KVS: CFSTORE Global Key Namespace
The CFSTORE must implement a system global hierarchical tree name-space for
keys. The namespace is shared by all software components operating within
the system. Examples of key names include the following:
- 'com.arm.mbed.wifi.accesspoint[5].essid'
- 'com.arm.mbed.wifi.accesspoint[home].essid'
- 'yotta.your-yotta-registry-module-name.your-value'
- 'yotta.hello-world.animal{dog}{foot}[3]'
The key name string forms a path where 'Path Directory Entries' are
separated by the '.' character.
##### REQ-3.1.02-SKVS-HLAPID-KVS: CFSTORE Key Name String Format Max Length
For CFSTORE keys The maximum length of a CFSTORE key is 220 characters excluding
the terminating null.
##### REQ-3.1.03-SKVS-HLAPID-KVS: CFSTORE Key Name String Allowed Characters
CFSTORE key name strings must only contain the following characters:
- [a-zA-Z0-9.]
- '-'
##### REQ-3.1.04-SKVS-HLAPID-KVS: Key Name Path Directory Entry List {}
Path Directory Entries may have list indicators designated by {}. For
example,
- 'com.arm.mbed.wifi.accesspoint{5}.essid'
- 'com.arm.mbed.wifi.accesspoint{home}.essid'
- 'yotta.hello-world.animal{dog}{foot}{3}'
In the above the list item specifiers are respectively:
- '5'
- 'home'
- 'dog', 'foot, '3'
As list item specifiers are part of the key name string, the list item
substring must be composed of allowable characters.
##### REQ-3.1.05-SKVS-HLAPID-KVS: CFSTORE Global Key Yotta Namespace
The key name prefix 'yotta' is reserved for use by the yotta module. Other
prefixes may be reserved.
##### REQ-3.1.06-SKVS-HLAPID-KVS: CFSTORE Key Names Mapable to Common OS Filesystem Name
The CFSTORE key names must be mappable to common OS Filesystem file names. This requirment
permits a CFSTORE backend to map individual KVs to files with the filename being the
key name, for example. Supported OS Filesytems must include DOS, NTFS, EXT3, EXT4 and
JFFS.
## Secure Key Value Storage\High Level API Description\Access Control Security (REQ-3.2.xx-SKVS-HLAPID-ACS) Requirements.
##### REQ-3.2.01-SKVS-HLAPID-KACS:
The CFSTORE must enforce security policies as defined by Access Control Lists.
##### REQ-3.2.02-SKVS-HLAPID-KACS: CFSTORE Key Creation Part 2
The CFSTORE objects must be created with an ACL. The ACL is attached to the object
so that access permissions to the KV data can be enforced.
##### REQ-3.2.03-SKVS-HLAPID-KACS:
The CFSTORE Access Control Lists must support the groups for 'owner' and 'other',
with optional permissions read, write and executable. The owner group
permissions describe the access permissions of the owner of the object. The
other group permissions describe the access permissions for entities other
than the owner. The writable and executable permissions are mutually
exclusive.
##### REQ-3.2.04-SKVS-HLAPID-KACS:
A CFSTORE API client must be able to query the CFSTORE for a list of KV pairs provided
the KV pair ACL permissions allow the client access. The query result must
contain all client owner KVs. The query results may include non-client
owned KVs provided the other group permissions grant access.
## Secure Key Value Storage\API Logic\Finding Keys (REQ-5.1.xx-SKVS-APIL-FK) Requirements.
##### REQ-5.1.01-SKVS-APIL-FK: Key Searching/Finding Scoped by ACL
The CFSTORE must provide an interface to query for active keys in the global
storage. The query must:
- return results based on the ACL provided by the client
- support wild card searches using the '*' character. The '*' character
can occur at most once any point in the search string. For example:
- com.arm.mbed.wifi.accesspoint*.essid
- yotta.your-yotta-registry-module-name.*
- yotta.hello-world.animal{dog}{foot}{*}
- yotta.hello-world.animal{dog}{foot}*
- yotta.hello-world.animal{dog*3}
##### REQ-5.1.02-SKVS-APIL-FK: CFSTORE Global Key Namespace Reserves Character '*'
The character '*' is reserved in the CFSTORE global key namespace. The current
functions of this character as follows:
- a wild card character in searches.
- a wild card character used in the delete operation.
##### REQ-5.1.03-SKVS-APIL-FK: Key Searching/Finding Resume
In order to support the return of a large list of key query results (perhaps
exceeding the ability of the caller to consume in a single operation), the
query interface must support the ability to restart/resume the query to
retrieve a subsequent set of records to those already received.
##### REQ-5.1.04-SKVS-APIL-FK: Key Searching/Finding Internals (key versions)
The CFSTORE must be robust against incomplete, corrupted or aborted write
operations to NV store caused for example, by loss of power during the
write.
## Secure Key Value Storage\API Logic\Get Storage Information (REQ-5.2.xx-SKVS-APIL-GSI) Requirements.
##### REQ-5.2.01-SKVS-APIL-GSI: storage_detect
The CFSTORE must provide an API so that clients can discover the CFSTORE storage
capabilities. Storage capabilities may include:
- write-block sizes for O_BLOCK_WRITE mode (sequence of writes into the
same value)
- supported Data Retention Levels
- supported Device Data Security Protection Features
##### REQ-5.2.02-SKVS-APIL-GSI: Minimal Storage Support
The CFSTORE must provide minimal storage media services including the following:
- SRAM/SDRAM memory with no security guarantees.
## Secure Key Value Storage\API Logic\Creating & Opening Keys for Writing (REQ-5.3.xx-SKVS-APIL-COKFW) Requirements.
##### REQ-5.3.01-SKVS-APIL-COKFW: storage_key_create with O_CREATE
CFSTORE keys must be explicitly created using 'storage_key_create' with the following
parameters:
- security ACLs (owner & others)
- the intended retention levels (bit mask to allow caching if needed)
- indicating the expected Device Data Security Protection Features
- the key pointer (zero-terminated)
- the value size
- alignment bits of the value hardware address (only for O_CONTINUOUS).
The structure start is aligned accordingly to ensure that the value
blob is aligned on a multiple of the 2^alignment_bits
- mode flags (O_CREATE, O_CONTINUOUS, O_LAZY_FLUSH, O_BLOCK_WRITE,
O_ALLOCATE_AT_OFFEST).
- O_CREATE. The call will create the KV pair. If a
pre-existing KV with the same name is present in CFSTORE then the
storage_key_create will fail with FILE_EXISTS.
- O_CONTINUOUS. The KV value will be stored in a continuous range
of hardware addresses.
- O_LAZY_FLUSH
- O_BLOCK_WRITE
- O_ALLOCATE_AT_OFFEST
###### Discussion
The following should not be included in the API (e.g. because the principle of encapsulation is broken, or specific to a particular clients requirements):
- optionally the offset address (restricted feature, ideally only granted
to the FOTA security context)
##### REQ-5.3.02-SKVS-APIL-COKFW: storage_key_create without O_CREATE
Pre-existing CFSTORE objects can be updated by calling the storage_key_create
API with the O_CREATE not set.
In case a pre-existing key is updated (O_CREATE not set) and the previous
ACL allows writing to the caller:
- all key-value fragments of the previous key are set as inactive
- the new key is allocated (in fragments if permitted)
- all permissions and settings are copied from the previous key
- the version number is incremented compared to the previous key (see
REQ-5.3.05-SKVS-APIL-COKFW).
##### REQ-5.3.03-SKVS-APIL-COKFW: O_CONTINUOUS for executable objects
CFSTORE will manage an executable KV as though the mode O_CONTINUOUS flag
is set.
##### REQ-5.3.04-SKVS-APIL-COKFW: O_CONTINUOUS for non-executable objects
A CFSTORE client may specify the mode O_CONTINUOUS flag for non-executable
objects.
##### REQ-5.3.05-SKVS-APIL-COKFW: Versioning of KVs
KVs in NV storage should have version numbers. When writing an updated
KV (with changed value data for example), a new copy of the KV data with
updated version number should be written to NV store. The earlier version is
left as a fallback copy of data that may be deleted at some point in time,
when the NV storage is required, or more than a certain number of
versions is exceeded.
## Secure Key Value Storage\Updating and Settings and Permissions (REQ-6.1.xx-SKVS-USP) Requirements.
##### REQ-6.1.01-SKVS-USP:
CFSTORE does not permit the updating of KV pair permissions or settings. This is to promote security.
## Secure Key Value Storage\Updating and Settings and Permissions\Deleting Keys (REQ-6.2.xx-SKVS-USP-DK) Requirements.
##### REQ-6.2.01-SKVS-USP-DK:
Only the owner of the CFSTORE KV pair can delete the object. The wildcard
'*' character can be specified to delete an owned subtree of the CFSTORE
global key namespace.
##### REQ-6.2.02-SKVS-USP-DK:
This requirement has been removed.
## Secure Key Value Storage\Updating and Settings and Permissions\Opening Keys for Reading (REQ-6.2.xx-SKVS-USP-OKFR) Requirements.
##### REQ-6.3.xx-SKVS-USP-OKFR storage_key_open_read
CFSTORE objects must be explicitly opened with storage_key_open_read(key_name)
before operations on the KV pair can be performed. The KV must
pre-exist in the store before it can be opened.
## Secure Key Value Storage\Updating and Settings and Permissions\Seeking in Key Values (REQ-6.3.xx-SKVS-USP-SIKV) Requirements.
##### REQ-6.4.01-SKVS-USP-SIKV storage_value_rseek
The function storage_value_rseek can be used on a opaque reference to a KV
to change the read position inside a value i.e. the storage_value_read
method supports random-access.
##### REQ-6.4.02-SKVS-USP-SIKV storage_value_write has no write location
storage_value_write does not support the concept of a write location that can be modified i.e. random access write support is not supported.
##### REQ-6.4.03-SKVS-USP-SIKV storage_value_write sequential-access
storage_value_write supports sequential-access. Random-access to the value data is not supported.
## Secure Key Value Storage\Updating and Settings and Permissions\Writing Keys (REQ-6.4.xx-SKVS-USP-WK) Requirements.
##### REQ-6.5.01-SKVS-USP-WK
CFSTORE KV values can be written in one or more operation. For example, if a value blob has size n bytes, then 2 n/2 byte write operations have the following effect:
- the first write sets bytes 0-n/2-1 in the value blob.
- the second write sets bytes n/2 to n-1 in the value blob.
This may require a write position to be maintained, for example. The ability to seek the write location must not be supported.
##### REQ-6.5.02-SKVS-USP-WK
This requirement has been removed.
##### REQ-6.5.03-SKVS-USP-WK
The KV stored in NV store should have an associated CRC so that:
- the integrity of the data can be protected
- the corruption of the data can be detected e.g. if power is lost during the flush to NV store.
The CRC should be stored at the end of the KV so it is written last. The CRC write transaction is termed "finalising" the KV.
##### REQ-6.5.04-SKVS-USP-WK
KVs that have not been flushed to NV storage should be flushed at reboot time.
##### REQ-6.5.05-SKVS-USP-WK
KVs may be fragmented into several smaller pieces for NV storage. In the case that a KV is fragmented, each fragment should have a an associated CRC as per REQ-6.5.03-SKVS-USP-WK.
##### REQ-6.5.06-SKVS-USP-WK
A KV value or KV fragment can only be finalised by its owner.
##### REQ-6.5.07-SKVS-USP-WK
Closing of a written KV in the finalization of all open value-fragment for that KV.
##### REQ-6.5.08-SKVS-USP-WK
Flushing of the KVs causes finalisation of the store.
##### REQ-6.5.09-SKVS-USP-WK
Non-finalised object must not be readable.
## Secure Key Value Storage\Updating and Settings and Permissions\Executable Keys and Firmware Updates (REQ-6.6.xx-SKVS-USP-EKFU)
Requirements.
##### REQ-6.6.01-SKVS-USP-EKFU
To facilitate modular firmware updates in future, executable keys are supported by the API
##### REQ-6.6.02-SKVS-USP-EKFU
For immovable & O_CONTINUOUS keys, the absolute hardware address and the relative address of a value key can be queried using the API
This API feature is restricted to boxes that require that function (FOTA, DMA). By keeping most key-value pairs movable the flash can be de-fragmented.
## Secure Key Value Storage\Miscellaneous (REQ-7.1.xx-SKVS-M)Requirements.
##### REQ-7.1.01-SKVS-M
The CFSTORE will implement a C Language interface.
##### REQ-7.1.02-SKVS-M
The CFSTORE does not support hot-pluggable storage devices e.g. SD flash.
##### REQ-7.1.03-SKVS-M KV Value Data May Not Fit into Available (SRAM) Memory.
CFSTORE must be capable of writing a KV to NV backing store where the value
data length >> size of available SRAM. This requirement therefore implies
that CFSTORE must support the case that the whole of the KV value data cannot all be
resident in SRAM memory at one time.
# Outstanding Issues With This Document
##### REQ-5.3.01-SKVS-APIL-COKFW: storage_key_create with O_CREATE
- How does the offset-address work?
- What is the definition of O_LAZY_FLUSH
- What is the definition of O_BLOCK_WRITE
- What is the definition of O_ALLOCATE_AT_OFFEST
##### REQ-5.3.02-SKVS-APIL-COKFW: storage_key_create without O_CREATE
- To which "previous ACL" does this requirement refer?
- Is an implementation internally creating a new copy of the key?
##### REQ-6.5.01-SKVS-USP-WK
- Are there any additional requirements arising from these statements?
# Contributors
This document was made possible through the contributions of the following people:
- Rohit Grover
- Simon Hughes
- Milosch Meriac
[CFSTORE_TERM]: https://github.com/ARMmbed/configuration-store/blob/master/doc/design/configuration_store_terminology.md

View File

@ -0,0 +1,34 @@
# Configuration-Store Terminology
## Defintion of Terms
###### ACL
Access Control List
###### CFSTORE
Configuration Store
###### FOTA
Firmware Over The Air
###### HLD
High Level Design
###### KV
Key Value Pair, also represented as {key, value}
###### Key Name Prefix
This is indentical tot he Security Name Prefix.
###### LLD
Low Level Design
###### NV
Non Volatile
###### OS
Operating System
###### Security Name Prefix
If a client security context (uvisor box) needs to create CFSTORE KV entries, it must have a (mandatory) key name prefix. This is called the security_prefix_name.

View File

@ -0,0 +1,64 @@
# Test Plan
This document describes the test plan and test cases for the configuration-store project.
# x86 Testing
The x86-linux-native target is supported and the tests can be run on a linux PC, for example.
# FRDM-K64F-GCC Testing
The frdm-k64f-gcc target is supported and the tests can be run on the k64f target.
# Overview of Test Cases
## Access Control List() API Tests
Currently, the ACL tests are not implemented as the uvisor integration is still outstanding.
## Close() API Tests
These test cases are to be documented.
## Add and Delete() API Tests
These test cases are to be documented.
## Create() API Tests
These test cases are to be documented.
## Find() API Tests
These test cases are to be documented.
## Flush() API Tests
These test cases are to be documented.
## Misc API Tests
These test cases are to be documented.
## Open() API Tests
These test cases are to be documented.
## Read() API Tests
These test cases are to be documented.
## Write() API Tests
These test cases are to be documented.

Binary file not shown.

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 79 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 89 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 KiB

View File

@ -0,0 +1,363 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<diagram program="umlet" version="13.2">
<zoom_level>8</zoom_level>
<element>
<id>UMLInterface</id>
<coordinates>
<x>0</x>
<y>872</y>
<w>784</w>
<h>312</h>
</coordinates>
<panel_attributes>ARM_DRIVER_CFSTORE
Config-Store (CS) Interface
--
ARM_DRIVER_VERSION (*GetVersion)(void);
int32_t (*Close)(ARM_CFSTORE_HANDLE hkey);
int32_t (*Create)(const char* key_name, ARM_CFSTORE_SIZE value_len, const ARM_CFSTORE_KEYDESC* kdesc, ARM_CFSTORE_HANDLE hkey);
int32_t (*Delete)(ARM_CFSTORE_HANDLE hkey);
int32_t (*Find)(const char* key_name_query, const ARM_CFSTORE_HANDLE previous, ARM_CFSTORE_HANDLE next);
int32_t (*Flush)(void);
int32_t (*GetKeyName)(ARM_CFSTORE_HANDLE hkey, char* key_name, uint8_t *key_len);
ARM_CFSTORE_CAPABILITIES (*GetCapabilities)(void);
ARM_CFSTORE_STATUS (*GetStatus)(void);
int32_t (*GetValueLen)(ARM_CFSTORE_HANDLE hkey, ARM_CFSTORE_SIZE *value_len);
int32_t (*Initialize)(ARM_CFSTORE_CALLBACK callback, void* client_context);
int32_t (*PowerControl)(ARM_POWER_STATE state);
int32_t (*Read)(ARM_CFSTORE_HANDLE hkey, void* data, ARM_CFSTORE_SIZE* len);
int32_t (*Open)(const char* key_name, ARM_CFSTORE_FMODE flags, ARM_CFSTORE_HANDLE hkey);
int32_t (*Rseek)(ARM_CFSTORE_HANDLE hkey, ARM_CFSTORE_OFFSET offset);
int32_t (*Uninitialise)(void);
int32_t (*Write)(ARM_CFSTORE_HANDLE hkey, const char* data, ARM_CFSTORE_SIZE* len);
</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>UMLClass</id>
<coordinates>
<x>488</x>
<y>1168</y>
<w>192</w>
<h>112</h>
</coordinates>
<panel_attributes>ARM_CFSTORE_ACCESS_CONTROL_LIST
--
uint32_t perm_owner_read : 1;
uint32_t perm_owner_write : 1;
uint32_t perm_owner_execute : 1;
uint32_t perm_other_read : 1;
uint32_t perm_other_write : 1;
uint32_t perm_other_execute : 1;
</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>UMLClass</id>
<coordinates>
<x>688</x>
<y>1168</y>
<w>264</w>
<h>144</h>
</coordinates>
<panel_attributes>ARM_STOR_DATA_RETENTION_LEVEL
--
/* supported volatility values of different sotrage mediums */
DATA_RETENTION_WHILE_DEVICE_ACTIVE,
DATA_RETENTION_ACROSS_SLEEP,
DATA_RETENTION_ACROSS_DEEP_SLEEP,
DATA_RETENTION_BATTERY_BACKED,
DATA_RETENTION_NVM,
</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>UMLClass</id>
<coordinates>
<x>1320</x>
<y>1168</y>
<w>184</w>
<h>136</h>
</coordinates>
<panel_attributes>ARM_CFSTORE_FMODE
--
uint32_t continuous : 1;
uint32_t lazy_flush : 1;
uint32_t flush_on_close : 1;
uint32_t read : 1;
uint32_t write : 1;
uint32_t execute : 1;
uint32_t storage_detect : 1;
</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>536</x>
<y>1072</y>
<w>544</w>
<h>112</h>
</coordinates>
<panel_attributes>lt=&lt;-</panel_attributes>
<additional_attributes>10.0;120.0;660.0;10.0</additional_attributes>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>1056</x>
<y>1072</y>
<w>368</w>
<h>112</h>
</coordinates>
<panel_attributes>lt=&lt;-</panel_attributes>
<additional_attributes>440.0;120.0;10.0;10.0</additional_attributes>
</element>
<element>
<id>UMLClass</id>
<coordinates>
<x>968</x>
<y>1168</y>
<w>344</w>
<h>256</h>
</coordinates>
<panel_attributes>ARM_STOR_SECURITY_FEATURES
--
uint8_t acls : 1; ///&lt; protection against internal software attacks using ACLs.
uint8_t rollback_protection : 1; ///&lt; roll-back protection.
uint8_t tamper_proof : 1; ///&lt; tamper-proof memory (will be deleted on tamper-attempts using board level or chip level sensors).
uint8_t internal_flash : 1; ///&lt; Internal flash.
uint8_t reserved : 4;
/**
* Encode support for hardening against various classes of attacks.
*/
struct ARM_STOR_HARDENING
{
uint8_t device_software : 1; ///&lt; device software (malware running on the device).
uint8_t board_level_attacks : 1; ///&lt; board level attacks (debug probes, copy protection fuses.)
uint8_t chip_level_attacks : 1; ///&lt; chip level attacks (tamper-protection).
uint8_t side_channel_attacks : 1; ///&lt; side channel attacks.
uint8_t reserved : 4;
} hardening_against; ///&lt; hardening.
</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>816</x>
<y>1072</y>
<w>264</w>
<h>112</h>
</coordinates>
<panel_attributes>lt=&lt;-</panel_attributes>
<additional_attributes>10.0;120.0;310.0;10.0</additional_attributes>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>1056</x>
<y>1072</y>
<w>24</w>
<h>112</h>
</coordinates>
<panel_attributes>lt=&lt;-</panel_attributes>
<additional_attributes>10.0;120.0;10.0;10.0</additional_attributes>
</element>
<element>
<id>UMLActor</id>
<coordinates>
<x>1304</x>
<y>0</y>
<w>104</w>
<h>96</h>
</coordinates>
<panel_attributes>Box 1
Security Context</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>UMLActor</id>
<coordinates>
<x>1408</x>
<y>0</y>
<w>104</w>
<h>96</h>
</coordinates>
<panel_attributes>Box i
Security Context</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>UMLActor</id>
<coordinates>
<x>1504</x>
<y>0</y>
<w>104</w>
<h>96</h>
</coordinates>
<panel_attributes>Box n
Security Context</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>UMLUseCase</id>
<coordinates>
<x>1376</x>
<y>160</y>
<w>184</w>
<h>96</h>
</coordinates>
<panel_attributes>Config Store
{key,value} storage operations
</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>1360</x>
<y>48</y>
<w>128</w>
<h>128</h>
</coordinates>
<panel_attributes>&lt;&lt;uses&gt;&gt;</panel_attributes>
<additional_attributes>10.0;10.0;140.0;140.0</additional_attributes>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>1464</x>
<y>48</y>
<w>56</w>
<h>128</h>
</coordinates>
<panel_attributes>&lt;&lt;uses&gt;&gt;</panel_attributes>
<additional_attributes>10.0;10.0;10.0;140.0</additional_attributes>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>1464</x>
<y>48</y>
<w>120</w>
<h>128</h>
</coordinates>
<panel_attributes>&lt;&lt;uses&gt;&gt;</panel_attributes>
<additional_attributes>130.0;10.0;10.0;140.0</additional_attributes>
</element>
<element>
<id>UMLNote</id>
<coordinates>
<x>224</x>
<y>656</y>
<w>304</w>
<h>64</h>
</coordinates>
<panel_attributes>Note..
mbed_config_store_hld
v0.04
20160225
</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>UMLClass</id>
<coordinates>
<x>824</x>
<y>968</y>
<w>264</w>
<h>112</h>
</coordinates>
<panel_attributes>ARM_CFSTORE_KEYDESC
--
/*key descriptor attributes */
ARM_CFSTORE_ACCESS_CONTROL_LIST acl;
ARM_STOR_DATA_RETENTION_LEVEL drl;
ARM_STOR_SECURITY_FEATURES security;
ARM_CFSTORE_FMODE flags;
</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>UMLClass</id>
<coordinates>
<x>904</x>
<y>720</y>
<w>240</w>
<h>232</h>
</coordinates>
<panel_attributes>ARM_CFSTORE_OPCODE;
--
CFSTORE_OPCODE_CLOSE
CFSTORE_OPCODE_CREATE
CFSTORE_OPCODE_DELETE
CFSTORE_OPCODE_FIND
CFSTORE_OPCODE_FLUSH
CFSTORE_OPCODE_GET_KEY_NAME
CFSTORE_OPCODE_GET_STATUS
CFSTORE_OPCODE_GET_VALUE_LEN
CFSTORE_OPCODE_INITIALIZE
CFSTORE_OPCODE_OPEN
CFSTORE_OPCODE_POWER_CONTROL
CFSTORE_OPCODE_READ
CFSTORE_OPCODE_RSEEK
CFSTORE_OPCODE_UNINITIALIZE
CFSTORE_OPCODE_WRITE
CFSTORE_OPCODE_MAX
</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>UMLClass</id>
<coordinates>
<x>576</x>
<y>608</y>
<w>808</w>
<h>64</h>
</coordinates>
<panel_attributes>ARM_CFSTORE_CALLBACK
--
typedef void (*ARM_CFSTORE_CALLBACK)(int32_t status, ARM_CFSTORE_OPCODE cmd_code, void *client_context, ARM_CFSTORE_HANDLE handle);
</panel_attributes>
<additional_attributes/>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>392</x>
<y>880</y>
<w>576</w>
<h>104</h>
</coordinates>
<panel_attributes>lt=&lt;-</panel_attributes>
<additional_attributes>700.0;110.0;10.0;10.0</additional_attributes>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>392</x>
<y>664</y>
<w>536</w>
<h>240</h>
</coordinates>
<panel_attributes>lt=&lt;-</panel_attributes>
<additional_attributes>650.0;10.0;10.0;280.0</additional_attributes>
</element>
<element>
<id>Relation</id>
<coordinates>
<x>392</x>
<y>816</y>
<w>528</w>
<h>88</h>
</coordinates>
<panel_attributes>lt=&lt;-</panel_attributes>
<additional_attributes>640.0;10.0;10.0;90.0</additional_attributes>
</element>
</diagram>

View File

@ -0,0 +1,68 @@
# Configuration Store Releases
Author: Simon Hughes
# Overview
This page documents the supported requirements in each release. The Configuration Store Requirements are documented here:
[CFSTORE_REQUIREMENTS](https://github.com/ARMmbed/meVo/blob/master/config_store/doc/design/configuration_store_requirements.md)
# Releases
## Release 0.3.2
The requirements status (supported versus not supported) in this release are as follows:
- REQ-1.01-SKVS-R: Not supported. Currently only SRAM back CFSTORE is supported.
- REQ-1.02-SKVS-R: Not supported. uvisor integration is still outstanding.
- REQ-1.03-SKVS-R: Supported.
- REQ-1.04-SKVS-R: Supported.
- REQ-1.05-SKVS-R: Supported.
- REQ-1.06-SKVS-R: Supported.
- REQ-1.07-SKVS-R: CS Stores Binary Blobs: Supported.
- REQ-1.08-SKVS-R: CS Key Structure as Name Strings: Supported.
- REQ-1.09-SKVS-R: Key Creation and Ownership Part 1: Not supported. uvisor integration is still outstanding.
- REQ-1.10-SKVS-R: Security Context: Not supported. uvisor integration is still outstanding.
- REQ-1.2.01-SKVS-HLD: Not supported. Currently only SRAM back CFSTORE is supported.
- REQ-1.2.02-SKVS-HLD: "only during device activity" supported but other options not supported.
- REQ-1.2.03-SKVS-HLD: Not supported.
- REQ-1.2.04-SKVS-HLD: Not supported.
- REQ-1.2.05-SKVS-HLD: Supported.
- REQ-3.1.01-SKVS-HLAPID-KVS: CS Global Key Namespace: Supported.
- REQ-3.1.02-SKVS-HLAPID-KVS: CS Key Name String Format Max Length: Supported.
- REQ-3.1.03-SKVS-HLAPID-KVS: CS Key Name String Allowed Characters: Supported.
- REQ-3.1.04-SKVS-HLAPID-KVS: Key Name Path Directory Entry List []: Supported.
- REQ-3.1.05-SKVS-HLAPID-KVS: CS Global Key Yotta Namespace: Supported.
- REQ-3.2.01-SKVS-HLAPID-KACS: Not supported as requires uvisor integration.
- REQ-3.2.02-SKVS-HLAPID-KACS: CS Key Creation Part 2: Supported.
- REQ-3.2.03-SKVS-HLAPID-KACS: Partially supported as requires uvisor integration.
- REQ-3.2.04-SKVS-HLAPID-KACS: Supported.
- REQ-5.1.01-SKVS-APIL-FK: Key Searching/Finding Scoped by ACL: Supported.
- REQ-5.1.02-SKVS-APIL-FK: CS Global Key Namespace Reserves Character '*': Supported.
- REQ-5.1.03-SKVS-APIL-FK: Key Searching/Finding Resume: Supported.
- REQ-5.1.04-SKVS-APIL-FK: Key Searching/Finding Internals (key versions): Not supported.
- REQ-5.2.01-SKVS-APIL-GSI: storage_detect: Not supported.
- REQ-5.2.02-SKVS-APIL-GSI: Minimal Storage Support: Supported.
- REQ-5.3.01-SKVS-APIL-COKFW: storage_key_create with O_CREATE: Partially suppported.
- REQ-5.3.02-SKVS-APIL-COKFW: storage_key_create without O_CREATE: Not supported.
- REQ-5.3.03-SKVS-APIL-COKFW: O_CONTINUOUS for executable objects: Not supported.
- REQ-5.3.04-SKVS-APIL-COKFW: O_CONTINUOUS for non-executable objects: Not supported.
- REQ-6.1.01-SKVS-USP: Supported.
- REQ-6.2.01-SKVS-USP-DK: Supported.
- REQ-6.2.02-SKVS-USP-DK: Supported.
- REQ-6.3.01-SKVS-USP-OKFR storage_key_open_read: Supported.
- REQ-6.4.01-SKVS-USP-SIKV storage_value_rseek: Supported.
- REQ-6.4.02-SKVS-USP-SIKV storage_value_write has no write location: Supported.
- REQ-6.4.03-SKVS-USP-SIKV storage_value_write sequential-access: Supported.
- REQ-6.5.01-SKVS-USP-WK: Partially supported.
- REQ-6.5.01-SKVS-USP-WK: Not supported.
- REQ-6.6.01-SKVS-USP-EKFU: Not supported.
- REQ-6.6.02-SKVS-USP-EKFU: Not supported.
- REQ-7.1.01-SKVS-M: Supported.
- REQ-7.1.02-SKVS-M: Supported.
- REQ-7.1.03-SKVS-M KV Value Data May Not Fit into Available (SRAM) Memory. Not supported.

View File

@ -0,0 +1,60 @@
/** @file cfstore_debug.h
*
* component debug header file.
*/
#ifndef __CFSTORE_CONFIG_H
#define __CFSTORE_CONFIG_H
/*
* CFSTORE_CONFIG_BACKEND_FLASH_ENABLED
* = 1 >1 build with the flash
* CFSTORE_CONFIG_BACKEND_SRAM_ENABLED
* CFSTORE_CONFIG_BACKEND_UVISOR_ENABLED
* CFSTORE_CONFIG_MBED_OS_VERSION
* 3 => mbedosV3
* 4 => morpheus
*/
/* default values */
#define CFSTORE_CONFIG_BACKEND_FLASH_ENABLED 1
#define CFSTORE_CONFIG_BACKEND_SRAM_ENABLED 0
#define CFSTORE_CONFIG_BACKEND_UVISOR_ENABLED 0
#define CFSTORE_CONFIG_MBED_OS_VERSION 3
/* default build config overridden by package manager configuarion
*
* __MBED__
* Morpheus build system (mbed-classic) defines the __MBED__ symbol
*
* YOTTA_CFG_CFSTORE_BACKEND_SRAM
* build only for sram backend (no flash integration)
* YOTTA_CFG_CFSTORE_UVISOR_ENABLE
* build with uvisor enable
*
* */
#ifdef __MBED__
#undef CFSTORE_CONFIG_MBED_OS_VERSION
#define CFSTORE_CONFIG_MBED_OS_VERSION 4
/* currently build only sram version (port flash-journal later) */
#define YOTTA_CFG_CFSTORE_BACKEND_SRAM
/* define the symbol that yotta would define for the k64f target */
#define TARGET_LIKE_FRDM_K64F_GCC
/* at present time building for sram so set yotta symbol for sync mode i.e. async_ops = 0*/
#define YOTTA_CFG_CONFIG_HARDWARE_MTD_ASYNC_OPS 0
#endif /* __MBED__ */
#if defined YOTTA_CFG_CFSTORE_BACKEND_SRAM
#undef CFSTORE_CONFIG_BACKEND_FLASH_ENABLED
#define CFSTORE_CONFIG_BACKEND_FLASH_ENABLED 0
#undef CFSTORE_CONFIG_BACKEND_SRAM_ENABLED
#define CFSTORE_CONFIG_BACKEND_SRAM_ENABLED 1
#endif /* YOTTA_CFG_CFSTORE_BACKEND_SRAM */
#endif /*__CFSTORE_CONFIG_H*/

View File

@ -0,0 +1,118 @@
/** @file cfstore_debug.h
*
* component debug header file.
*/
#ifndef __CFSTORE_DEBUG
#define __CFSTORE_DEBUG
#include <stdint.h>
#include <assert.h>
/* Debug Support */
#define CFSTORE_LOG_NONE 0
#define CFSTORE_LOG_ERR 1
#define CFSTORE_LOG_WARN 2
#define CFSTORE_LOG_NOTICE 3
#define CFSTORE_LOG_INFO 4
#define CFSTORE_LOG_DEBUG 5
#define CFSTORE_LOG_FENTRY 6
#define CFSTORE_LOG(_fmt, ...) \
do \
{ \
printf(_fmt, __VA_ARGS__); \
}while(0);
#define noCFSTORE_DEBUG
#ifdef CFSTORE_DEBUG
extern uint32_t cfstore_optDebug_g;
extern uint32_t cfstore_optLogLevel_g;
extern uint32_t cfstore_optLogTracepoint_g;
/* uncomment for asserts to work */
/* #undef NDEBUG */
// todo: port to mbedOSV3++ #include <core-util/assert.h>
#define CFSTORE_INLINE
// todo: port to mbedOSV3++ #define CFSTORE_ASSERT CORE_UTIL_ASSERT
#define CFSTORE_ASSERT(...)
#define CFSTORE_DBGLOG(_fmt, ...) \
do \
{ \
if(cfstore_optDebug_g && (cfstore_optLogLevel_g >= CFSTORE_LOG_DEBUG)) \
{ \
printf(_fmt, __VA_ARGS__); \
} \
}while(0);
#define CFSTORE_ERRLOG(_fmt, ...) \
do \
{ \
if(cfstore_optDebug_g && (cfstore_optLogLevel_g >= CFSTORE_LOG_ERR)) \
{ \
printf(_fmt, __VA_ARGS__); \
} \
}while(0);
#define CFSTORE_FENTRYLOG(_fmt, ...) \
do \
{ \
if(cfstore_optDebug_g && (cfstore_optLogLevel_g >= CFSTORE_LOG_FENTRY)) \
{ \
printf(_fmt, __VA_ARGS__); \
} \
}while(0);
/* tracepoints */
#define CFSTORE_TP_NONE 0x0
#define CFSTORE_TP_CLOSE (1<<0)
#define CFSTORE_TP_CREATE (1<<1)
#define CFSTORE_TP_DELETE (1<<2)
#define CFSTORE_TP_FILE (1<<3)
#define CFSTORE_TP_FIND (1<<4)
#define CFSTORE_TP_FLUSH (1<<5)
#define CFSTORE_TP_FSM (1<<6)
#define CFSTORE_TP_INIT (1<<7)
#define CFSTORE_TP_MEM (1<<8)
#define CFSTORE_TP_OPEN (1<<9)
#define CFSTORE_TP_READ (1<<10)
#define CFSTORE_TP_WRITE (1<<11)
#define CFSTORE_TP_VERBOSE1 (1<<12)
#define CFSTORE_TP_VERBOSE2 (1<<13)
#define CFSTORE_TP_VERBOSE3 (1<<14)
#define CFSTORE_TP_FENTRY (1<<31)
#define CFSTORE_TP(_tp, _fmt, ...) \
do \
{ \
if(cfstore_optDebug_g && (cfstore_optLogLevel_g >= CFSTORE_LOG_DEBUG)) \
{ \
if((cfstore_optLogTracepoint_g & (_tp)) == (uint32_t)(_tp)) \
{ \
printf(_fmt, __VA_ARGS__); \
} \
} \
}while(0);
#else
#define CFSTORE_ASSERT(_x) do { } while(0)
#define CFSTORE_INLINE inline
#define CFSTORE_DBGLOG(_fmt, ...) do { } while(0)
#define CFSTORE_ERRLOG(_fmt, ...) do { printf(_fmt, __VA_ARGS__); } while(0)
#define CFSTORE_FENTRYLOG(_fmt, ...) do { } while(0)
#define CFSTORE_TP(_tp, _fmt, ...) do { } while(0)
#endif /* CFSTORE_DEBUG */
#endif /*__CFSTORE_DEBUG*/

View File

@ -0,0 +1,322 @@
/*
* Copyright (c) 1989, 1993, 1994
* The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Guido van Rossum.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#ifndef _NO_FNMATCH
#if defined(LIBC_SCCS) && !defined(lint)
static char sccsid[] = "@(#)fnmatch.c 8.2 (Berkeley) 4/16/94";
#endif /* LIBC_SCCS and not lint */
/* In order to support ARM toolchain, this have been removed from the original
* fnmatch.c from newlib.
* #include <sys/cdefs.h>
*/
/*
* Function fnmatch() as specified in POSIX 1003.2-1992, section B.6.
* Compares a filename or pathname to a pattern.
*/
#include <ctype.h>
#include <cfstore_fnmatch.h>
#include <string.h>
#include <stdio.h>
#include <limits.h>
#define EOS '\0'
#define RANGE_MATCH 1
#define RANGE_NOMATCH 0
#define RANGE_ERROR (-1)
/* In order to support ARM toolchain and simplify the number of newlib posix files used,
* this have been copied from collate.c, and the license for this code has been included at the
* here:
*
* Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua>
* at Electronni Visti IA, Kiev, Ukraine.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/
int __collate_load_error = 1;
/* In order to support ARM toolchain and simplify the number of newlib posix files used,
* the following has been copied from collcmp.c, and the license for this code is
* included here:
*
* Copyright (C) 1996 by Andrey A. Chernov, Moscow, Russia.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
/*
* Compare two characters converting collate information
* into ASCII-compatible range, it allows to handle
* "[a-z]"-type ranges with national characters.
*/
int __collate_range_cmp (c1, c2)
int c1, c2;
{
static char s1[2], s2[2];
int ret;
c1 &= UCHAR_MAX;
c2 &= UCHAR_MAX;
if (c1 == c2)
return (0);
s1[0] = c1;
s2[0] = c2;
if ((ret = strcoll(s1, s2)) != 0)
return (ret);
return (c1 - c2);
}
static int rangematch(const char *, char, int, char **);
int
fnmatch(pattern, string, flags)
const char *pattern, *string;
int flags;
{
const char *stringstart;
char *newp;
char c, test;
for (stringstart = string;;)
switch (c = *pattern++) {
case EOS:
if ((flags & FNM_LEADING_DIR) && *string == '/')
return (0);
return (*string == EOS ? 0 : FNM_NOMATCH);
case '?':
if (*string == EOS)
return (FNM_NOMATCH);
if (*string == '/' && (flags & FNM_PATHNAME))
return (FNM_NOMATCH);
if (*string == '.' && (flags & FNM_PERIOD) &&
(string == stringstart ||
((flags & FNM_PATHNAME) && *(string - 1) == '/')))
return (FNM_NOMATCH);
++string;
break;
case '*':
c = *pattern;
/* Collapse multiple stars. */
while (c == '*')
c = *++pattern;
if (*string == '.' && (flags & FNM_PERIOD) &&
(string == stringstart ||
((flags & FNM_PATHNAME) && *(string - 1) == '/')))
return (FNM_NOMATCH);
/* Optimize for pattern with * at end or before /. */
if (c == EOS)
if (flags & FNM_PATHNAME)
return ((flags & FNM_LEADING_DIR) ||
strchr(string, '/') == NULL ?
0 : FNM_NOMATCH);
else
return (0);
else if (c == '/' && flags & FNM_PATHNAME) {
if ((string = strchr(string, '/')) == NULL)
return (FNM_NOMATCH);
break;
}
/* General case, use recursion. */
while ((test = *string) != EOS) {
if (!fnmatch(pattern, string, flags & ~FNM_PERIOD))
return (0);
if (test == '/' && flags & FNM_PATHNAME)
break;
++string;
}
return (FNM_NOMATCH);
case '[':
if (*string == EOS)
return (FNM_NOMATCH);
if (*string == '/' && (flags & FNM_PATHNAME))
return (FNM_NOMATCH);
if (*string == '.' && (flags & FNM_PERIOD) &&
(string == stringstart ||
((flags & FNM_PATHNAME) && *(string - 1) == '/')))
return (FNM_NOMATCH);
switch (rangematch(pattern, *string, flags, &newp)) {
case RANGE_ERROR:
goto norm;
case RANGE_MATCH:
pattern = newp;
break;
case RANGE_NOMATCH:
return (FNM_NOMATCH);
}
++string;
break;
case '\\':
if (!(flags & FNM_NOESCAPE)) {
if ((c = *pattern++) == EOS) {
c = '\\';
--pattern;
}
}
/* FALLTHROUGH */
default:
norm:
if (c == *string)
;
else if ((flags & FNM_CASEFOLD) &&
(tolower((unsigned char)c) ==
tolower((unsigned char)*string)))
;
else
return (FNM_NOMATCH);
string++;
break;
}
/* NOTREACHED */
}
static int
rangematch(pattern, test, flags, newp)
const char *pattern;
char test;
int flags;
char **newp;
{
int negate, ok;
char c, c2;
/*
* A bracket expression starting with an unquoted circumflex
* character produces unspecified results (IEEE 1003.2-1992,
* 3.13.2). This implementation treats it like '!', for
* consistency with the regular expression syntax.
* J.T. Conklin (conklin@ngai.kaleida.com)
*/
if ( (negate = (*pattern == '!' || *pattern == '^')) )
++pattern;
if (flags & FNM_CASEFOLD)
test = tolower((unsigned char)test);
/*
* A right bracket shall lose its special meaning and represent
* itself in a bracket expression if it occurs first in the list.
* -- POSIX.2 2.8.3.2
*/
ok = 0;
c = *pattern++;
do {
if (c == '\\' && !(flags & FNM_NOESCAPE))
c = *pattern++;
if (c == EOS)
return (RANGE_ERROR);
if (c == '/' && (flags & FNM_PATHNAME))
return (RANGE_NOMATCH);
if (flags & FNM_CASEFOLD)
c = tolower((unsigned char)c);
if (*pattern == '-'
&& (c2 = *(pattern+1)) != EOS && c2 != ']') {
pattern += 2;
if (c2 == '\\' && !(flags & FNM_NOESCAPE))
c2 = *pattern++;
if (c2 == EOS)
return (RANGE_ERROR);
if (flags & FNM_CASEFOLD)
c2 = tolower((unsigned char)c2);
if (__collate_load_error ?
c <= test && test <= c2 :
__collate_range_cmp(c, test) <= 0
&& __collate_range_cmp(test, c2) <= 0
)
ok = 1;
} else if (c == test)
ok = 1;
} while ((c = *pattern++) != ']');
*newp = (char *)pattern;
return (ok == negate ? RANGE_NOMATCH : RANGE_MATCH);
}
#endif /* !_NO_FNMATCH */

View File

@ -0,0 +1,56 @@
/*-
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD: src/include/fnmatch.h,v 1.10 2002/03/23 17:24:53 imp Exp $
* @(#)fnmatch.h 8.1 (Berkeley) 6/2/93
*/
#ifndef _FNMATCH_H_
#define _FNMATCH_H_
#define FNM_NOMATCH 1 /* Match failed. */
#define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */
#define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */
#define FNM_PERIOD 0x04 /* Period must be matched by period. */
#if defined(_GNU_SOURCE) || !defined(_ANSI_SOURCE) && !defined(_POSIX_SOURCE)
#define FNM_LEADING_DIR 0x08 /* Ignore /<tail> after Imatch. */
#define FNM_CASEFOLD 0x10 /* Case insensitive search. */
#define FNM_IGNORECASE FNM_CASEFOLD
#define FNM_FILE_NAME FNM_PATHNAME
#endif
//todo: #include <sys/cdefs.h>
//#include <cdefs.h>
//__BEGIN_DECLS
int fnmatch(const char *, const char *, int);
//__END_DECLS
#endif /* !_FNMATCH_H_ */

View File

@ -0,0 +1,63 @@
/** @file cfstore_list.h
*
* mbed Microcontroller Library
* Copyright (c) 2006-2016 ARM Limited
*
* 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.
*/
#ifndef _CFSTORE_LIST_H_
#define _CFSTORE_LIST_H_
/*
* Doubly linked list implementation based on the following design
* and psuedo-code:
* Introduction to Algorithms, TH Cormen, CE Leiserson, Rl Rivest,
* ISBN 0-262-03141-8 (1989), Pages 206-207.
*/
typedef struct cfstore_list_node_t
{
struct cfstore_list_node_t *next;
struct cfstore_list_node_t *prev;
} cfstore_list_node_t;
#define CFSTORE_ZERO_NODE(_node_cFStOrE) \
do{ \
(_node_cFStOrE)->next=NULL; \
(_node_cFStOrE)->prev=NULL; \
}while(0)
#define CFSTORE_INIT_LIST_HEAD(_node_cFStOrE) \
do { \
(_node_cFStOrE)->next = (_node_cFStOrE); \
(_node_cFStOrE)->prev = (_node_cFStOrE); \
} while (0)
/* brief insert the new_node between 2 other nodes, the one before being node_before, the one after being node_after */
static inline void cfstore_listAdd(cfstore_list_node_t* node_before, cfstore_list_node_t * new_node, cfstore_list_node_t* node_after)
{
/* init new node before insertion */
new_node->next = node_after;
new_node->prev = node_before;
node_before->next = new_node;
node_after->prev = new_node;
}
/* brief remove the node D from the list by making the nodes before and after D point to each other */
static inline void cfstore_listDel(cfstore_list_node_t *node)
{
node->prev->next = node->next;
node->next->prev = node->prev;
CFSTORE_ZERO_NODE(node);
}
#endif /* _CFSTORE_LIST_H_ */

View File

@ -0,0 +1,564 @@
/* @file cfstore_test.c
*
* mbed Microcontroller Library
* Copyright (c) 2006-2016 ARM Limited
*
* 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.
*
* test support code implementation file.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <inttypes.h>
#include "cfstore_config.h"
#include "cfstore_debug.h"
#include "cfstore_test.h"
#include <configuration-store/configuration_store.h>
/* ruler for measuring text strings */
/* 1 1 1 1 1 1 1 1 1 1 2 2 2 */
/* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 */
/* 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890 */
const uint8_t cfstore_test_byte_data_table[CFSTORE_TEST_BYTE_DATA_TABLE_SIZE] = {
0x2d, 0xf3, 0x31, 0x4c, 0x11, 0x4f, 0xde, 0x0d, 0xbd, 0xbc, 0xa6, 0x78, 0x36, 0x5c, 0x1d, 0x28,
0x5f, 0xa9, 0x10, 0x65, 0x54, 0x45, 0x21, 0x1a, 0x88, 0xfe, 0x76, 0x45, 0xb9, 0xac, 0x65, 0x9a,
0x34, 0x9d, 0x73, 0x10, 0xb4, 0xa9, 0x2e, 0x90, 0x95, 0x68, 0xac, 0xfe, 0xc5, 0x2d, 0x15, 0x03,
0x34, 0x70, 0xf1, 0x1d, 0x48, 0xa1, 0xa0, 0xed, 0x5c, 0x2f, 0xf5, 0x2b, 0xb9, 0x84, 0xbb, 0x45,
0x32, 0xdd, 0xb1, 0x33, 0x95, 0x2a, 0xbc, 0x26, 0xf0, 0x89, 0xba, 0xf4, 0xbd, 0xf9, 0x5d, 0x2e,
0x6e, 0x11, 0xc6, 0xa7, 0x78, 0xfc, 0xc9, 0x0e, 0x6b, 0x38, 0xba, 0x14, 0x1b, 0xab, 0x4c, 0x20,
0x91, 0xe4, 0xb0, 0xf1, 0x2b, 0x14, 0x07, 0x6b, 0xb5, 0xcd, 0xe3, 0x49, 0x75, 0xac, 0xe8, 0x98,
0xf1, 0x58, 0x8f, 0xd9, 0xc4, 0x8f, 0x00, 0x17, 0xb5, 0x06, 0x6a, 0x33, 0xbd, 0xa7, 0x40, 0x5a,
0xbf, 0x49, 0xf7, 0x27, 0x1b, 0x4c, 0x3e, 0x6f, 0xe3, 0x08, 0x1f, 0xfd, 0xa6, 0xd4, 0xc7, 0x5f,
0xa4, 0xa6, 0x82, 0xad, 0x19, 0xd5, 0x5c, 0xd8, 0x3a, 0x49, 0x85, 0xc9, 0x21, 0x83, 0xf6, 0xc6,
0x84, 0xf9, 0x76, 0x89, 0xf3, 0x2d, 0x17, 0x50, 0x97, 0x38, 0x48, 0x9a, 0xe1, 0x82, 0xcd, 0xac,
0xa8, 0x1d, 0xd7, 0x96, 0x5e, 0xb3, 0x08, 0xa8, 0x3a, 0xc7, 0x2b, 0x05, 0xaf, 0xdc, 0x16, 0xdf,
0x48, 0x0f, 0x2a, 0x7e, 0x3a, 0x82, 0xd7, 0x80, 0xd6, 0x49, 0x27, 0x5d, 0xe3, 0x07, 0x62, 0xb3,
0xc3, 0x6c, 0xba, 0xb2, 0xaa, 0x9f, 0xd9, 0x03, 0x0d, 0x27, 0xa8, 0xe0, 0xd6, 0xee, 0x79, 0x4b,
0xd6, 0x97, 0x99, 0xb7, 0x11, 0xd6, 0x0d, 0x34, 0xae, 0x99, 0x4a, 0x93, 0x95, 0xd0, 0x5a, 0x34,
0x19, 0xa2, 0x69, 0x57, 0xcf, 0x7c, 0x3d, 0x98, 0x88, 0x5d, 0x04, 0xf2, 0xd7, 0xac, 0xa5, 0x63
};
/* @brief set of test data for sequential write tests */
cfstore_test_rw_data_entry_t cfstore_test_rw_data_table[] =
{
{ 25, 'z' },
{ 00, 'a' },
{ 24, 'y' },
{ 01, 'b' },
{ 23, 'x' },
{ 02, 'c' },
{ 22, 'w' },
{ 03, 'd' },
{ 21, 'v' },
{ 04, 'e' },
{ 20, 'u' },
{ 05, 'f' },
{ 19, 't' },
{ 06, 'g' },
{ 18, 's' },
{ 07, 'h' },
{ 17, 'r' },
{ 8, 'i' },
{ 16, 'q' },
{ 9, 'j' },
{ 15, 'p' },
{ 10, 'k' },
{ 14, 'o' },
{ 11, 'l' },
{ 13, 'n' },
{ 12, 'm' },
{ CFSTORE_TEST_RW_TABLE_SENTINEL, '@' },
};
const char* cfstore_test_opcode_str[] =
{
"UNDEFINED",
"CFSTORE_OPCODE_CLOSE",
"CFSTORE_OPCODE_CREATE",
"CFSTORE_OPCODE_DELETE",
"CFSTORE_OPCODE_FIND",
"CFSTORE_OPCODE_FLUSH",
"CFSTORE_OPCODE_GET_KEY_NAME",
"CFSTORE_OPCODE_GET_STATUS",
"CFSTORE_OPCODE_GET_VALUE_LEN",
"CFSTORE_OPCODE_INITIALIZE",
"CFSTORE_OPCODE_OPEN",
"CFSTORE_OPCODE_POWER_CONTROL",
"CFSTORE_OPCODE_READ",
"CFSTORE_OPCODE_RSEEK",
"CFSTORE_OPCODE_UNINITIALIZE",
"CFSTORE_OPCODE_WRITE",
"CFSTORE_OPCODE_MAX"
};
/* @brief test utility function to check a node appears correctly in the cfstore
* @note this function expects cfstore to have been initialised with
* a call to ARM_CFSTORE_DRIVER::Initialize()
*/
int32_t cfstore_test_check_node_correct(const cfstore_kv_data_t* node)
{
char* read_buf;
int32_t ret = ARM_DRIVER_ERROR;
ARM_CFSTORE_SIZE len = 0;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
ARM_CFSTORE_HANDLE_INIT(hkey);
ARM_CFSTORE_FMODE flags;
CFSTORE_FENTRYLOG("%s:entered\r\n", __func__);
memset(&flags, 0, sizeof(flags));
ret = drv->Open(node->key_name, flags, hkey);
if(ret < ARM_DRIVER_OK){
CFSTORE_ERRLOG("%s:Error: failed to open node (key_name=\"%s\", value=\"%s\")(ret=%d)\r\n", __func__, node->key_name, node->value, (int) ret);
goto out0;
}
len = strlen(node->value) + 1;
read_buf = (char*) malloc(len);
if(read_buf == NULL) {
CFSTORE_ERRLOG("%s:Error: failed to allocated read buffer \r\n", __func__);
goto out1;
}
memset(read_buf, 0, len);
ret = drv->Read(hkey, read_buf, &len);
if(ret < ARM_DRIVER_OK){
CFSTORE_ERRLOG("%s:Error: failed to write key (key_name=\"%s\", value=\"%s\")\r\n", __func__, node->key_name, node->value);
goto out2;
}
/* check read data is as expected */
if(strncmp(read_buf, node->value, strlen(node->value)) != 0){
CFSTORE_ERRLOG("%s:Error: read value data (%s) != KV value data (key_name=\"%s\", value=\"%s\")\r\n", __func__, read_buf, node->key_name, node->value);
ret = ARM_DRIVER_ERROR;
}
out2:
if(read_buf) free(read_buf);
out1:
drv->Close(hkey);
hkey = NULL;
out0:
return ret;
}
/* @brief test utility function to delete the cfstore key identified by key_name
* @note this function expects cfstore to have been initialised with
* a call to ARM_CFSTORE_DRIVER::Initialize()
*/
int32_t cfstore_test_delete(const char* key_name)
{
int32_t ret = ARM_DRIVER_ERROR;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
ARM_CFSTORE_HANDLE_INIT(hkey);
ARM_CFSTORE_FMODE flags;
CFSTORE_FENTRYLOG("%s:entered.\r\n", __func__);
memset(&flags, 0, sizeof(flags));
ret = drv->Open(key_name, flags, hkey);
if(ret < ARM_DRIVER_OK){
return ret;
}
if(hkey != NULL){
ret = drv->Delete(hkey);
drv->Close(hkey);
}
return ret;
}
/* @brief test utility function to delete all of the KVs in the cfstore
* @note this function expects cfstore to have been initialised with
* a call to ARM_CFSTORE_DRIVER::Initialize()
*/
int32_t cfstore_test_delete_all(void)
{
const char* key_name_query = "*";
char key_name[CFSTORE_KEY_NAME_MAX_LENGTH+1];
uint8_t len = CFSTORE_KEY_NAME_MAX_LENGTH+1;
int32_t ret = ARM_DRIVER_ERROR;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
ARM_CFSTORE_HANDLE_INIT(next);
ARM_CFSTORE_HANDLE_INIT(prev);
CFSTORE_FENTRYLOG("%s:entered.\r\n", __func__);
while((ret = drv->Find(key_name_query, prev, next)) == ARM_DRIVER_OK)
{
len = CFSTORE_KEY_NAME_MAX_LENGTH+1;
drv->GetKeyName(next, key_name, &len);
CFSTORE_TP(CFSTORE_TP_DELETE, "%s:deleting key_name=%s, len=%d\r\n", __func__, key_name, (int) len);
ret = drv->Delete(next);
if(ret < ARM_DRIVER_OK){
CFSTORE_ERRLOG("%s:Error: failed to delete key_name=%s, len=%d\r\n", __func__, key_name, (int) len);
return ret;
}
CFSTORE_HANDLE_SWAP(prev, next);
}
if(ret == ARM_CFSTORE_DRIVER_ERROR_KEY_NOT_FOUND) {
/* as expected, no more keys have been found by the Find()*/
ret = ARM_DRIVER_OK;
}
// todo: find portable format specification CFSTORE_FENTRYLOG("%s:exiting (ret=%ld).\r\n", __func__, ret);
CFSTORE_FENTRYLOG("%s:exiting (ret=%" PRId32 ").\r\n", __func__, ret);
return ret;
}
/* @brief test utility function to create a KV in the cfstore
* @note this function expects cfstore to have been initialised with
* a call to ARM_CFSTORE_DRIVER::Initialize()
*/
int32_t cfstore_test_create(const char* key_name, const char* data, ARM_CFSTORE_SIZE* len, ARM_CFSTORE_KEYDESC* kdesc)
{
int32_t ret = ARM_DRIVER_ERROR;
ARM_CFSTORE_SIZE value_len = 0;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
ARM_CFSTORE_HANDLE_INIT(hkey);
CFSTORE_FENTRYLOG("%s:entered.\r\n", __func__);
value_len = *len;
kdesc->drl = ARM_RETENTION_WHILE_DEVICE_ACTIVE;
ret = drv->Create(key_name, value_len, kdesc, hkey);
if(ret < ARM_DRIVER_OK){
return ret;
}
value_len = *len;
ret = drv->Write(hkey, data, &value_len);
if(ret < ARM_DRIVER_OK){
drv->Close(hkey);
return ret;
}
if(value_len != *len){
drv->Close(hkey);
return ARM_DRIVER_ERROR;
}
drv->Close(hkey);
return ret;
}
/* @brief test utility function to create KVs from the supplied table
* @note this function expects cfstore to have been initialised with
* a call to ARM_CFSTORE_DRIVER::Initialize()
*/
int32_t cfstore_test_create_table(const cfstore_kv_data_t* table)
{
int32_t ret = ARM_DRIVER_ERROR;
ARM_CFSTORE_SIZE len = 0;
cfstore_kv_data_t* node = NULL;
ARM_CFSTORE_KEYDESC kdesc;
CFSTORE_FENTRYLOG("%s:entered.\r\n", __func__);
memset(&kdesc, 0, sizeof(kdesc));
kdesc.drl = ARM_RETENTION_WHILE_DEVICE_ACTIVE;
while(table->key_name != NULL)
{
len = strlen(table->value);
ret = cfstore_test_create(table->key_name, table->value, &len, &kdesc);
if(ret < ARM_DRIVER_OK){
CFSTORE_ERRLOG("%s:Error: failed to create node (key_name=\"%s\", value=\"%s\")\r\n", __func__, node->key_name, node->value);
return ret;
}
table++;
}
return ret;
}
cfstore_kv_data_t cfstore_test_init_1_data[] = {
CFSTORE_INIT_1_TABLE_HEAD,
{ "b", "1"},
{ "c", "12"},
{ "d", "123"},
{ "e", "1234"},
{ "g", "12345"},
{ "h", "123456"},
{ "i", "1234567"},
{ "j", "12345678"},
{ "k", "123456789"},
{ "l", "1234567890"},
{ "m", "12345678901"},
{ "n", "123456789012"},
{ "o", "1234567890123"},
{ "p", "12345678901234"},
{ "q", "123456789012345"},
{ "r", "1234567890123456"},
{ "0", "a"},
{ "01", "ab"},
{ "012", "abc"},
{ "0123", "abcd"},
{ "01234", "abcde"},
{ "012345", "abcdef"},
{ "0123456", "abcdefg"},
{ "01234567", "abcdefgh"},
{ "012345678", "abcdefghi"},
{ "0123456789", "abcdefghj"},
{ "0123456789a", "abcdefghjk"},
{ "0123456789ab", "abcdefghjkl"},
{ "0123456789abc", "abcdefghjklm"},
{ "0123456789abcd", "abcdefghjklmn"},
{ "0123456789abcde", "abcdefghjklmno"},
{ "0123456789abcdef", "abcdefghjklmnop"},
{ "0123456789abcdef0", "abcdefghjklmnopq"},
{ "0123456789abcdef01", "abcdefghjklmnopqr"},
{ "0123456789abcdef012", "abcdefghjklmnopqrs"},
{ "0123456789abcdef0123", "abcdefghjklmnopqrst"},
{ "0123456789abcdef01234", "abcdefghjklmnopqrstu"},
{ "0123456789abcdef012345", "abcdefghjklmnopqrstuv"},
CFSTORE_INIT_1_TABLE_MID_NODE,
{ "0123456789abcdef01234567", "abcdefghjklmnopqrstuvwx"},
{ "0123456789abcdef012345678", "abcdefghjklmnopqrstuvwxy"},
{ "0123456789abcdef0123456789", "abcdefghjklmnopqrstuvwxyz"},
{ "0123456789abcdef0123456789a", "b"},
{ "0123456789abcdef0123456789ab", "c"},
{ "0123456789abcdef0123456789abc", "d"},
{ "0123456789abcdef0123456789abcd", "e"},
{ "0123456789abcdef0123456789abcde", "f"},
{ "0123456789abcdef0123456789abcdef", "g"},
{ "com.arm.mbed.wifi.accesspoint.essid", ""},
{ "com.arm.mbed.wifi.accesspoint.essid2", ""},
{ "yotta.your-yotta-registry-module-name.module1", ""},
{ "yotta.hello-world.animal{wobbly-dog}{foot}frontLeft", "missing"},
{ "yotta.hello-world.animal{wobbly-dog}{foot}frontRight", "present"},
{ "yotta.hello-world.animal{wobbly-dog}{foot}backLeft", "half present"},
{ "piety.demands.us.to.honour.truth.above.our.friends", "Aristotle"},
{ "basement.medicine.pavement.government.trenchcoat.off.cough.off.kid.did.when.again.alleyway.friend.cap.pen.dollarbills.ten.foot.soot.put.but.anyway.say.May.DA.kid.did.toes.bows.those.hose.nose.clothes.man.blows.well.well", "TheRollingStone" },
CFSTORE_INIT_1_TABLE_TAIL,
{ NULL, NULL},
};
/* @brief utility test function to initialise cfstore sram area with some
* KV's to manipulate
* @note this function expects cfstore to have been initialised with
* a call to ARM_CFSTORE_DRIVER::Initialize()
*/
int32_t cfstore_test_init_1(void)
{
char* read_buf = NULL;
const uint8_t key_name_max_len = CFSTORE_KEY_NAME_MAX_LENGTH+1;
uint8_t key_name_len = 0;
char key_name_buf[key_name_max_len];
int32_t ret = ARM_DRIVER_ERROR;
ARM_CFSTORE_SIZE len = 0;
ARM_CFSTORE_SIZE max_len = 0;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
cfstore_kv_data_t* node = NULL;
ARM_CFSTORE_KEYDESC kdesc;
ARM_CFSTORE_HANDLE_INIT(hkey);
CFSTORE_FENTRYLOG("%s:entered\r\n", __func__);
memset(&kdesc, 0, sizeof(kdesc));
memset(key_name_buf, 0, CFSTORE_KEY_NAME_MAX_LENGTH+1);
/*scan for max length of value blob*/
node = cfstore_test_init_1_data;
while(node->key_name != NULL)
{
len = strlen(node->value);
if(len > max_len){
max_len = len;
max_len++;
}
node++;
}
read_buf = (char*) malloc(max_len);
if(read_buf == NULL) {
CFSTORE_ERRLOG("%s:Error: failed to allocated read buffer \r\n", __func__);
return ret;
}
kdesc.drl = ARM_RETENTION_WHILE_DEVICE_ACTIVE;
node = cfstore_test_init_1_data;
while(node->key_name != NULL)
{
CFSTORE_DBGLOG("%s:About to create new node (key_name=\"%s\", value=\"%s\")\r\n", __func__, node->key_name, node->value);
ret = drv->Create(node->key_name, strlen(node->value), &kdesc, hkey);
if(ret < ARM_DRIVER_OK){
CFSTORE_ERRLOG("%s:Error: failed to create node (key_name=\"%s\", value=\"%s\")\r\n", __func__, node->key_name, node->value);
return ret;
}
CFSTORE_DBGLOG("%s:length of KV=%d (key_name=\"%s\", value=\"%s\")\r\n", __func__, (int) len, node->key_name, node->value);
len = strlen(node->value);
ret = drv->Write(hkey, (char*) node->value, &len);
if(ret < ARM_DRIVER_OK){
CFSTORE_ERRLOG("%s:Error: failed to write key (key_name=\"%s\", value=\"%s\")\r\n", __func__, node->key_name, node->value);
drv->Close(hkey);
return ret;
}
if(len != strlen(node->value)){
CFSTORE_ERRLOG("%s:Error: failed to write full value data (key_name=\"%s\", value=\"%s\"), len=%d\r\n", __func__, node->key_name, node->value, (int) len);
drv->Close(hkey);
return ARM_DRIVER_ERROR;
}
/* read the data back*/
len = strlen(node->value);
memset(read_buf, 0, max_len);
ret = drv->Read(hkey, read_buf, &len);
if(ret < ARM_DRIVER_OK){
CFSTORE_ERRLOG("%s:Error: failed to read key (key_name=\"%s\", value=\"%s\")\r\n", __func__, node->key_name, node->value);
drv->Close(hkey);
return ret;
}
if(len != strlen(node->value)){
CFSTORE_ERRLOG("%s:Error: failed to read full value data (key_name=\"%s\", value=\"%s\"), len=%d, ret=%d\r\n", __func__, node->key_name, node->value, (int) len, (int) ret);
drv->Close(hkey);
return ARM_DRIVER_ERROR;
}
key_name_len = key_name_max_len;
memset(key_name_buf, 0, key_name_len);
drv->GetKeyName(hkey, key_name_buf, &key_name_len);
if(len != strlen(node->value)){
CFSTORE_ERRLOG("%s:Error: failed to GetKeyName() (key_name=\"%s\", value=\"%s\"), len=%d\r\n", __func__, node->key_name, node->value, (int) len);
drv->Close(hkey);
return ARM_DRIVER_ERROR;
}
CFSTORE_LOG("Created KV successfully (key_name=\"%s\", value=\"%s\")\r\n", key_name_buf, read_buf);
drv->Close(hkey);
node++;
}
free(read_buf);
return ret;
}
/* @brief test utility function to check a particular KV exists in the
* cfstore using Find() interface
* @note this function expects cfstore to have been initialised with
* a call to ARM_CFSTORE_DRIVER::Initialize()
*/
int32_t cfstore_test_kv_is_found(const char* key_name, bool* bfound)
{
CFSTORE_FENTRYLOG("%s:entered.\r\n", __func__);
int32_t ret = ARM_DRIVER_ERROR;
ARM_CFSTORE_HANDLE_INIT(prev);
ARM_CFSTORE_HANDLE_INIT(next);
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
CFSTORE_ASSERT(bfound != NULL);
CFSTORE_ASSERT(key_name != NULL);
*bfound = 0;
ret = drv->Find(key_name, prev, next);
if(ret == ARM_DRIVER_OK){
*bfound = 1;
CFSTORE_DBGLOG("%s:Found key_name=\"%s\", about to call close.\r\n", __func__, key_name);
drv->Close(next);
}
return ret;
}
/* @brief support function for generating a kv_name
* @param name buffer to hold kv name
* @param len length of kv name to generate
* @note braces are not included in the generated names as the names are
* of varible length and theyre may be unmatched
*
*/
#define CFSTORE_TEST_KV_NAME_BUF_MAX_DATA (10+26+26+4)
int32_t cfstore_test_kv_name_gen(char* name, const size_t len)
{
size_t i;
const char buf[CFSTORE_TEST_KV_NAME_BUF_MAX_DATA+1] = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ.-_@";
CFSTORE_FENTRYLOG("%s:entered\n", __func__);
for(i = 0; i < len; i++)
{
name[i] = buf[i % CFSTORE_TEST_KV_NAME_BUF_MAX_DATA];
}
return ARM_DRIVER_OK;
}
/* @brief test utility function to read the value blob of a specified KV
* @note this function expects cfstore to have been initialised with
* a call to ARM_CFSTORE_DRIVER::Initialize()
*/
int32_t cfstore_test_read(const char* key_name, char* data, ARM_CFSTORE_SIZE* len)
{
int32_t ret = ARM_DRIVER_ERROR;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
ARM_CFSTORE_HANDLE_INIT(hkey);
ARM_CFSTORE_FMODE flags;
CFSTORE_FENTRYLOG("%s:entered\r\n", __func__);
memset(&flags, 0, sizeof(flags));
if(key_name == NULL) {
CFSTORE_ERRLOG("%s:invalid key_name argument \r\n", __func__);
goto out0;
}
if(data == NULL) {
CFSTORE_ERRLOG("%s:invalid data argument \r\n", __func__);
goto out0;
}
if(len == NULL) {
CFSTORE_ERRLOG("%s:invalid len argument \r\n", __func__);
goto out0;
}
ret = drv->Open(key_name, flags, hkey);
if(ret < ARM_DRIVER_OK){
CFSTORE_ERRLOG("%s:Error: failed to open node (key_name=\"%s\")(ret=%d)\r\n", __func__, key_name, (int) ret);
goto out1;
}
ret = drv->Read(hkey, data, len);
if(ret < ARM_DRIVER_OK){
CFSTORE_ERRLOG("%s:Error: failed to read key (key_name=\"%s\"\r\n", __func__, key_name);
goto out2;
}
out2:
drv->Close(hkey);
out1:
out0:
return ret;
}
/* @brief write the value blob of a specified KV
* @note this function expects cfstore to have been initialised with
* a call to ARM_CFSTORE_DRIVER::Initialize()
*/
int32_t cfstore_test_write(const char* key_name, const char* data, ARM_CFSTORE_SIZE* len)
{
int32_t ret = ARM_DRIVER_ERROR;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
ARM_CFSTORE_HANDLE_INIT(hkey);
ARM_CFSTORE_FMODE flags;
CFSTORE_FENTRYLOG("%s:entered\r\n", __func__);
memset(&flags, 0, sizeof(flags));
if(key_name == NULL) {
CFSTORE_ERRLOG("%s:Error: invalid key_name argument \r\n", __func__);
goto out0;
}
if(data == NULL) {
CFSTORE_ERRLOG("%s:Error: invalid data argument \r\n", __func__);
goto out0;
}
if(len == NULL) {
CFSTORE_ERRLOG("%s:Error: invalid len argument \r\n", __func__);
goto out0;
}
flags.write = 1;
ret = drv->Open(key_name, flags, hkey);
if(ret < ARM_DRIVER_OK){
CFSTORE_ERRLOG("%s:Error: failed to open node (key_name=\"%s\")(ret=%d)\r\n", __func__, key_name, (int) ret);
goto out1;
}
ret = drv->Write(hkey, data, len);
if(ret < ARM_DRIVER_OK){
CFSTORE_ERRLOG("%s:Error: failed to write key (key_name=\"%s\")\r\n", __func__, key_name);
goto out2;
}
out2:
drv->Close(hkey);
out1:
out0:
return ret;
}

View File

@ -0,0 +1,84 @@
/** @file cfstore_test.h
*
* mbed Microcontroller Library
* Copyright (c) 2006-2016 ARM Limited
*
* 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.
*
* Header file for test support data structures and function API.
*/
#ifndef __CFSTORE_TEST_H
#define __CFSTORE_TEST_H
#ifdef __cplusplus
extern "C" {
#endif
#include "configuration-store/configuration_store.h"
/* Defines */
#define CFSTORE_INIT_1_TABLE_HEAD { "a", ""}
#define CFSTORE_INIT_1_TABLE_MID_NODE { "0123456789abcdef0123456", "abcdefghijklmnopqrstuvwxyz"}
#define CFSTORE_INIT_1_TABLE_TAIL { "yotta.hello-world.animal{wobbly-dog}{foot}backRight", "present"}
#define CFSTORE_TEST_RW_TABLE_SENTINEL 0xffffffff
#define CFSTORE_TEST_BYTE_DATA_TABLE_SIZE 256
#define CFSTORE_UTEST_MSG_BUF_SIZE 256
#define CFSTORE_UTEST_DEFAULT_TIMEOUT_MS 10000
#define CFSTORE_MBED_HOSTTEST_TIMEOUT 60
/* support macro for make string for utest _MESSAGE macros, which dont support formatted output */
#define CFSTORE_TEST_UTEST_MESSAGE(_buf, _max_len, _fmt, ...) \
do \
{ \
snprintf((_buf), (_max_len), (_fmt), __VA_ARGS__); \
}while(0);
/*
* Structures
*/
/* kv data for test */
typedef struct cfstore_kv_data_t {
const char* key_name;
const char* value;
} cfstore_kv_data_t;
typedef struct cfstore_test_rw_data_entry_t
{
uint32_t offset;
char rw_char;
} cfstore_test_rw_data_entry_t;
extern cfstore_kv_data_t cfstore_test_init_1_data[];
extern cfstore_test_rw_data_entry_t cfstore_test_rw_data_table[];
extern const char* cfstore_test_opcode_str[];
extern const uint8_t cfstore_test_byte_data_table[CFSTORE_TEST_BYTE_DATA_TABLE_SIZE];
int32_t cfstore_test_check_node_correct(const cfstore_kv_data_t* node);
int32_t cfstore_test_create(const char* key_name, const char* data, size_t* len, ARM_CFSTORE_KEYDESC* kdesc);
int32_t cfstore_test_create_table(const cfstore_kv_data_t* table);
int32_t cfstore_test_delete(const char* key_name);
int32_t cfstore_test_delete_all(void);
int32_t cfstore_test_init_1(void);
int32_t cfstore_test_kv_is_found(const char* key_name, bool* bfound);
int32_t cfstore_test_kv_name_gen(char* name, const size_t len);
int32_t cfstore_test_read(const char* key_name, char* data, size_t* len);
int32_t cfstore_test_write(const char* key_name, const char* data, size_t* len);
#ifdef __cplusplus
}
#endif
#endif /* __CFSTORE_TEST_H */

View File

@ -0,0 +1,76 @@
/** @file cfstore_test.h
*
* mbed Microcontroller Library
* Copyright (c) 2006-2016 ARM Limited
*
* 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.
*
* Header file for test support data structures and function API.
*/
#ifndef __CFSTORE_UTEST_H
#define __CFSTORE_UTEST_H
#include <inttypes.h>
#include "cfstore_debug.h"
#include "cfstore_test.h"
using namespace utest::v1;
void cfstore_utest_default_callback(int32_t status, ARM_CFSTORE_OPCODE cmd_code, void *client_context, ARM_CFSTORE_HANDLE handle)
{
(void) status;
(void) client_context;
(void) handle;
CFSTORE_FENTRYLOG("%s:entered: status=%d, cmd_code=%d (%s) handle=%p\n", __func__, (int) status, (int) cmd_code, cfstore_test_opcode_str[cmd_code], handle);
switch(cmd_code)
{
case CFSTORE_OPCODE_INITIALIZE:
case CFSTORE_OPCODE_FLUSH:
case CFSTORE_OPCODE_UNINITIALIZE:
case CFSTORE_OPCODE_CLOSE:
case CFSTORE_OPCODE_CREATE:
case CFSTORE_OPCODE_DELETE:
case CFSTORE_OPCODE_FIND:
case CFSTORE_OPCODE_GET_KEY_NAME:
case CFSTORE_OPCODE_GET_STATUS:
case CFSTORE_OPCODE_GET_VALUE_LEN:
case CFSTORE_OPCODE_OPEN:
case CFSTORE_OPCODE_POWER_CONTROL:
case CFSTORE_OPCODE_READ:
case CFSTORE_OPCODE_RSEEK:
case CFSTORE_OPCODE_WRITE:
default:
CFSTORE_DBGLOG("%s:debug: received asynchronous notification for opcode=%d (%s)", __func__, cmd_code, cmd_code < CFSTORE_OPCODE_MAX ? cfstore_test_opcode_str[cmd_code] : "unknown");
}
CFSTORE_DBGLOG("%s:about to validate callback\n", __func__);
Harness::validate_callback();
return;
}
static control_t cfstore_utest_default_start(const size_t call_count)
{
int32_t ret = ARM_DRIVER_ERROR;
ARM_CFSTORE_DRIVER* drv = &cfstore_driver;
char cfstore_utest_msg[CFSTORE_UTEST_MSG_BUF_SIZE];
CFSTORE_FENTRYLOG("%s:entered\n", __func__);
(void) call_count;
ret = drv->Initialize(cfstore_utest_default_callback, NULL);
CFSTORE_TEST_UTEST_MESSAGE(cfstore_utest_msg, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to initialize CFSTORE (ret=%" PRId32 ")\n", __func__, ret);
TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_utest_msg);
return CaseTimeout(CFSTORE_UTEST_DEFAULT_TIMEOUT_MS);
}
#endif /* __CFSTORE_UTEST_H */

View File

@ -0,0 +1,121 @@
/*
* Copyright (c) 2013-2016, 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.
*/
#ifndef __CFSTORE_UVISOR_H__
#define __CFSTORE_UVISOR_H__
/* target specifc ACLs */
#if defined(TARGET_LIKE_FRDM_K64F)
#define CFSTORE_UVISOR_LED_ON false
#define CFSTORE_UVISOR_LED_OFF true
#define CFSTORE_UVISOR_MAIN_LED LED_BLUE
#define CFSTORE_UVISOR_MAIN_BTN SW2
#define CFSTORE_UVISOR_MAIN_BTN_PUPD PullUp
#define CFSTORE_UVISOR_MAIN_ACL(acl_list_name) \
static const UvisorBoxAclItem acl_list_name[] = { \
{MCG, sizeof(*MCG), UVISOR_TACLDEF_PERIPH}, \
{SIM, sizeof(*SIM), UVISOR_TACLDEF_PERIPH}, \
{PORTB, sizeof(*PORTB), UVISOR_TACLDEF_PERIPH}, \
{PORTC, sizeof(*PORTC), UVISOR_TACLDEF_PERIPH}, \
{RTC, sizeof(*RTC), UVISOR_TACLDEF_PERIPH}, \
{LPTMR0, sizeof(*LPTMR0), UVISOR_TACLDEF_PERIPH}, \
{PIT, sizeof(*PIT), UVISOR_TACLDEF_PERIPH}, \
{SMC, sizeof(*SMC), UVISOR_TACLDEF_PERIPH}, \
{UART0, sizeof(*UART0), UVISOR_TACLDEF_PERIPH}, \
}
#elif defined(TARGET_LIKE_STM32F429I_DISCO)
#define CFSTORE_UVISOR_LED_ON false
#define CFSTORE_UVISOR_LED_OFF true
#define CFSTORE_UVISOR_MAIN_LED LED1
#define CFSTORE_UVISOR_MAIN_BTN USER_BUTTON
#define CFSTORE_UVISOR_MAIN_BTN_PUPD PullDown
#define CFSTORE_UVISOR_MAIN_ACL(acl_list_name) \
static const UvisorBoxAclItem acl_list_name[] = { \
{TIM2, sizeof(*TIM2), UVISOR_TACLDEF_PERIPH}, \
{TIM5, sizeof(*TIM5), UVISOR_TACLDEF_PERIPH}, \
{GPIOA, sizeof(*GPIOA), UVISOR_TACLDEF_PERIPH}, \
{GPIOG, sizeof(*GPIOG), UVISOR_TACLDEF_PERIPH}, \
/* FIXME: secure RCC/EXTI/SYSCFG/FLASH */ \
{RCC, sizeof(*RCC), UVISOR_TACLDEF_PERIPH}, \
{EXTI, sizeof(*EXTI), UVISOR_TACLDEF_PERIPH}, \
{SYSCFG, sizeof(*SYSCFG), UVISOR_TACLDEF_PERIPH}, \
{FLASH, sizeof(*FLASH), UVISOR_TACLDEF_PERIPH}, \
{PWR, sizeof(*PWR), UVISOR_TACLDEF_PERIPH}, \
{USART1, sizeof(*USART1), UVISOR_TACLDEF_PERIPH}, \
{(void *) 0x42470000, 0x1000, UVISOR_TACLDEF_PERIPH}, \
}
#elif defined(TARGET_LIKE_EFM32GG_STK) \
|| defined(TARGET_LIKE_EFM32LG_STK) \
|| defined(TARGET_LIKE_EFM32WG_STK)
#define CFSTORE_UVISOR_LED_ON false
#define CFSTORE_UVISOR_LED_OFF true
#define CFSTORE_UVISOR_MAIN_LED LED1
#define CFSTORE_UVISOR_MAIN_BTN BTN0
#define CFSTORE_UVISOR_MAIN_BTN_PUPD PullUp
#define CFSTORE_UVISOR_MAIN_ACL(acl_list_name) \
static const UvisorBoxAclItem acl_list_name[] = { \
{GPIO, sizeof(*GPIO), UVISOR_TACLDEF_PERIPH}, \
{UART0, sizeof(*UART0), UVISOR_TACLDEF_PERIPH}, \
{TIMER0, sizeof(*TIMER0), UVISOR_TACLDEF_PERIPH}, \
/* FIXME: Secure CMU */ \
{CMU, sizeof(*CMU), UVISOR_TACLDEF_PERIPH}, \
{RTC, sizeof(*RTC), UVISOR_TACLDEF_PERIPH}, \
/* FIXME: Secure MSC */ \
{MSC, sizeof(*MSC), UVISOR_TACLDEF_PERIPH}, \
/* mbed-hal-silabs requires the DI page to be readable */ \
{(void*) 0x0FE08000, 0x1000, UVISOR_TACLDEF_SECURE_CONST}, \
}
#elif defined(TARGET_LIKE_EFM32PG_STK)
#define CFSTORE_UVISOR_LED_ON false
#define CFSTORE_UVISOR_LED_OFF true
#define CFSTORE_UVISOR_MAIN_LED LED1
#define CFSTORE_UVISOR_MAIN_BTN BTN0
#define CFSTORE_UVISOR_MAIN_BTN_PUPD PullUp
#define CFSTORE_UVISOR_MAIN_ACL(acl_list_name) \
static const UvisorBoxAclItem acl_list_name[] = { \
{GPIO, sizeof(*GPIO), UVISOR_TACLDEF_PERIPH}, \
{USART0, sizeof(*USART0), UVISOR_TACLDEF_PERIPH}, \
{TIMER0, sizeof(*TIMER0), UVISOR_TACLDEF_PERIPH}, \
/* FIXME: Secure CMU */ \
{CMU, sizeof(*CMU), UVISOR_TACLDEF_PERIPH}, \
{EMU, sizeof(*EMU), UVISOR_TACLDEF_PERIPH}, \
{RTCC, sizeof(*RTCC), UVISOR_TACLDEF_PERIPH}, \
/* FIXME: Secure MSC */ \
{MSC, sizeof(*MSC), UVISOR_TACLDEF_PERIPH}, \
/* mbed-hal-silabs requires the DI page to be readable */ \
{(void*) 0x0FE08000, 0x1000, UVISOR_TACLDEF_SECURE_CONST}, \
}
#else
#define CFSTORE_UVISOR_LED_ON true
#define CFSTORE_UVISOR_LED_OFF false
#define CFSTORE_UVISOR_MAIN_LED NC
#define CFSTORE_UVISOR_MAIN_BTN NC
#define CFSTORE_UVISOR_MAIN_BTN_PUPD PullNone
#define CFSTORE_UVISOR_MAIN_ACL(acl_list_name) \
static const UvisorBoxAclItem acl_list_name[] = {}
#endif
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,30 @@
/* In order to support ARM toolchain and simplify the number of newlib posix files used,
* this have been copied from collate.c, and the license for this code has been included at the
* here:
*
* Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua>
* at Electronni Visti IA, Kiev, Ukraine.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*/