/* * 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. * */ /** @file add_del.cpp Test cases to add and delete key-value pairs in the CFSTORE. * * Please consult the documentation under the test-case functions for * a description of the individual test case. */ #include "mbed.h" #include "cfstore_config.h" #include "Driver_Common.h" #include "cfstore_debug.h" #include "cfstore_test.h" #include "configuration_store.h" #include "utest/utest.h" #include "unity/unity.h" #include "greentea-client/test_env.h" #include "cfstore_utest.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <inttypes.h> using namespace utest::v1; #define CFSTORE_ADD_DEL_MALLOC_SIZE 1024 static char cfstore_add_del_utest_msg_g[CFSTORE_UTEST_MSG_BUF_SIZE]; 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) { int32_t ret = ARM_DRIVER_ERROR; (void) call_count; ret = cfstore_test_startup(); CFSTORE_TEST_UTEST_MESSAGE(cfstore_add_del_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to perform test startup (ret=%d).\n", __func__, (int) ret); TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_add_del_utest_msg_g); return CaseNext; } /** @brief * * This test case does the following: * - creates a KV. * - deletes the KV. * - checks that the deleted KV can no longer be found in the store. * * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. */ 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; 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=%d).\n", __func__, (int) 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=%d).\n", __func__, (int) 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 */ /* revert to CFSTORE_LOG if more trace required */ CFSTORE_DBGLOG("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=%d).\n", __func__, (int) 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 * * This test case adds a small number of KVs (~3), and then delete them. * - add key(s) * - delete key(s) * - make sure can't find key in cfstore * - loop over the above a number of times. * * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. */ 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; 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); /* revert CFSTORE_LOG for more trace */ CFSTORE_DBGLOG("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); /* revert CFSTORE_LOG for more trace */ CFSTORE_DBGLOG("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 * * This test case adds ~50 KVs, and then delete entries at the start, * middle and end of list. * * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. */ 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=%d).\n", __func__, (int) ret); TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_add_del_utest_msg_g); /* revert CFSTORE_LOG for more trace */ CFSTORE_DBGLOG("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=%d).\n", __func__, (int) 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=%d).\n", __func__, (int) 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=%d)\n", __func__, (int) ret); TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_add_del_utest_msg_g); return CaseNext; } /** @brief * * This test case is as per test_03 but using delete_all() on all init_1 data. * This test case is yet to be implemented. * * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. */ 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_DBGLOG("%s: WARN: requires implementation\n", __func__); TEST_ASSERT_MESSAGE(true, cfstore_add_del_utest_msg_g); return CaseNext; } /** @brief Delete an attribute after an internal realloc of the cfstore memory area * * This test case goes through the following steps: * 1. Creates attribute att_1 of size x, and write some data. This causes an internal * cfstore realloc to allocate heap memory for the attribute. * 2. Allocates some memory on the heap. Typically, this will be immediately after the * memory used by cfstore for the KV area. This means that if any cfstore reallocs are * made to increase size the memory area will have to move. * 3. Creates attribute att_2 of size y. This causes an internal cfstore realloc to move * the KV memory area to a new location. * 4. Delete att_1. This causes an internal realloc to shrink the area and tests that the * internal data structures that contain pointers to different parts of the KV area * are updated correctly. * 5. Allocates some memory on the heap. If the heap has been corrupted, this will likely trigger * a crash * * @return on success returns CaseNext to continue to next test case, otherwise will assert on errors. */ control_t cfstore_add_del_test_05_end(const size_t call_count) { char data[] = "some test data"; char filename[] = "file1"; char filename2[] = "file2"; int32_t ret = ARM_DRIVER_ERROR; void *test_buf1 = NULL; void *test_buf2 = NULL; ARM_CFSTORE_DRIVER *cfstoreDriver = &cfstore_driver; ARM_CFSTORE_KEYDESC keyDesc1; ARM_CFSTORE_HANDLE_INIT(hkey1); ARM_CFSTORE_KEYDESC keyDesc2; ARM_CFSTORE_HANDLE_INIT(hkey2); ARM_CFSTORE_SIZE count = sizeof(data); CFSTORE_FENTRYLOG("%s:entered\n", __func__); (void) call_count; /* step 1 */ memset(&keyDesc1, 0, sizeof(keyDesc1)); keyDesc1.drl = ARM_RETENTION_NVM; keyDesc1.flags.read = true; keyDesc1.flags.write = true; ret = cfstoreDriver->Create(filename, 1024, &keyDesc1, hkey1); CFSTORE_TEST_UTEST_MESSAGE(cfstore_add_del_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create attribute 1 (ret=%d)\n", __func__, (int) ret); TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_add_del_utest_msg_g); /* Write data to file */ ret = cfstoreDriver->Write(hkey1, (const char *)data, &count); CFSTORE_TEST_UTEST_MESSAGE(cfstore_add_del_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to write to attribute 1 (ret=%d)\n", __func__, (int) ret); TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_add_del_utest_msg_g); /* step 2 */ test_buf1 = malloc(CFSTORE_ADD_DEL_MALLOC_SIZE); CFSTORE_TEST_UTEST_MESSAGE(cfstore_add_del_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to allocate memory (test_buf1=%p)\n", __func__, test_buf1); TEST_ASSERT_MESSAGE(test_buf1 != NULL, cfstore_add_del_utest_msg_g); /* step 3 */ memset(&keyDesc2, 0, sizeof(keyDesc2)); keyDesc2.drl = ARM_RETENTION_NVM; keyDesc2.flags.read = true; keyDesc2.flags.write = true; ret = cfstoreDriver->Create(filename2, 1024, &keyDesc2, hkey2); CFSTORE_TEST_UTEST_MESSAGE(cfstore_add_del_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to create attribute 2 (ret=%d)\n", __func__, (int) ret); TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_add_del_utest_msg_g); /* Write data to file */ count = sizeof(data); ret = cfstoreDriver->Write(hkey2, (const char *)data, &count); CFSTORE_TEST_UTEST_MESSAGE(cfstore_add_del_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to write to attribute 2 (ret=%d)\n", __func__, (int) ret); TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_add_del_utest_msg_g); /* step 4 */ ret = cfstoreDriver->Delete(hkey1); CFSTORE_TEST_UTEST_MESSAGE(cfstore_add_del_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to delete to attribute 1 (ret=%d)\n", __func__, (int) ret); TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_add_del_utest_msg_g); ret = cfstoreDriver->Close(hkey1); CFSTORE_TEST_UTEST_MESSAGE(cfstore_add_del_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to close to attribute 1 (ret=%d)\n", __func__, (int) ret); TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_add_del_utest_msg_g); /* step 5 */ test_buf2 = malloc(CFSTORE_ADD_DEL_MALLOC_SIZE); CFSTORE_TEST_UTEST_MESSAGE(cfstore_add_del_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to allocate memory (test_buf2=%p)\n", __func__, test_buf2); TEST_ASSERT_MESSAGE(test_buf2 != NULL, cfstore_add_del_utest_msg_g); /* clean up */ ret = cfstoreDriver->Close(hkey2); CFSTORE_TEST_UTEST_MESSAGE(cfstore_add_del_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to close to attribute 2 (ret=%d)\n", __func__, (int) ret); TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_add_del_utest_msg_g); free(test_buf2); free(test_buf1); return CaseNext; } /// @cond CFSTORE_DOXYGEN_DISABLE utest::v1::status_t greentea_setup(const size_t number_of_cases) { GREENTEA_SETUP(300, "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), Case("ADD_DEL_test_05_start", cfstore_utest_default_start), Case("ADD_DEL_test_05_end", cfstore_add_del_test_05_end), }; /* Declare your test specification with a custom setup handler */ Specification specification(greentea_setup, cases); int main() { return !Harness::run(specification); } /// @endcond