Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
flash.cpp
00001 /* 00002 * mbed Microcontroller Library 00003 * Copyright (c) 2006-2016 ARM Limited 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 00018 /** @file flash.cpp Test cases to flush KVs in the CFSTORE using the Flash-Journal interface. 00019 * 00020 * Please consult the documentation under the test-case functions for 00021 * a description of the individual test case. 00022 */ 00023 00024 #include "cfstore_config.h" 00025 #include "cfstore_test.h" 00026 #include "cfstore_debug.h" 00027 #include "Driver_Common.h" 00028 #include "configuration_store.h" 00029 #include "utest/utest.h" 00030 #include "unity/unity.h" 00031 #include "greentea-client/test_env.h" 00032 00033 #ifdef CFSTORE_CONFIG_BACKEND_FLASH_ENABLED 00034 #include "flash_journal_strategy_sequential.h" 00035 #include "flash_journal.h" 00036 #include "Driver_Common.h" 00037 #endif /* CFSTORE_CONFIG_BACKEND_FLASH_ENABLED */ 00038 00039 00040 #include <stdio.h> 00041 #include <stdlib.h> 00042 #include <string.h> 00043 #include <inttypes.h> 00044 00045 using namespace utest::v1; 00046 00047 00048 00049 00050 /* shared code common to both sync and async test cases */ 00051 00052 /* 00053 * Defines 00054 * 00055 */ 00056 /// @cond CFSTORE_DOXYGEN_DISABLE 00057 #define CFSTORE_FREE free 00058 #define CFSTORE_MALLOC malloc 00059 #define CFSTORE_REALLOC realloc 00060 #define CFSTORE_FLASH_STACK_BUF_SIZE 64 00061 #define CFSTORE_FLASH_K64F_CURRENT_PROGRAM_UNIT_SIZE 8 00062 #define CFSTORE_TEST_DATA_KEYNAME "com.arm.mbed.configurationstore.test.flush.cfstoreflushtest02" 00063 #define CFSTORE_TEST_DATA_KEYNAME_SHORT "com.arm" 00064 #define CFSTORE_TEST_DATA_VALUE_INIT "\1" 00065 #define CFSTORE_TEST_DATA_KEYNAME_SIZE (sizeof(CFSTORE_TEST_DATA_KEYNAME) - 1) 00066 #define CFSTORE_TEST_DATA_VALUE_SIZE (sizeof(CFSTORE_TEST_DATA_VALUE_INIT) - 1) 00067 #define CFSTORE_FLASH_UTEST_MSG_BUF_SIZE 256 00068 #define CFSTORE_FLASH_MTD_ASYNC_OPS_ON 1 00069 #define CFSTORE_FLASH_MTD_ASYNC_OPS_OFF 0 00070 #define CFSTORE_FLASH_CASE_TIMEOUT_MS 5000 00071 /// @endcond 00072 00073 /* 00074 * Globals 00075 */ 00076 00077 /// @cond CFSTORE_DOXYGEN_DISABLE 00078 char cfstore_flash_utest_msg_g[CFSTORE_FLASH_UTEST_MSG_BUF_SIZE]; 00079 /// @endcond 00080 00081 #ifdef CFSTORE_CONFIG_BACKEND_FLASH_ENABLED 00082 uint16_t cfstore_flash_mtd_async_ops_g = 0; 00083 extern ARM_DRIVER_STORAGE ARM_Driver_Storage_MTD_K64F; 00084 00085 00086 /* KV data for test_01 */ 00087 static cfstore_kv_data_t cfstore_flush_test_01_kv_data[] = { 00088 { CFSTORE_TEST_DATA_KEYNAME, CFSTORE_TEST_DATA_VALUE_INIT}, 00089 { NULL, NULL}, 00090 }; 00091 00092 00093 /* @brief key value header structure defining key_name length, value length 00094 * @note 00095 * 8 bytes long */ 00096 typedef struct cfstore_area_header_t 00097 { 00098 uint32_t vlength; 00099 uint8_t klength; 00100 uint8_t perm_owner_read : 1; 00101 uint8_t perm_owner_write : 1; 00102 uint8_t perm_owner_execute : 1; 00103 uint8_t perm_other_read : 1; 00104 uint8_t perm_other_write : 1; 00105 uint8_t perm_other_execute : 1; 00106 uint8_t reserved : 2; 00107 uint8_t refcount; 00108 struct flags_t { 00109 uint8_t deleting : 1; 00110 uint8_t reserved : 7; 00111 } flags ; 00112 } cfstore_area_header_t ; 00113 00114 00115 /* @brief data structure for managing test data */ 00116 typedef struct cfstore_flash_data_blob_t { 00117 cfstore_area_header_t hdr; 00118 uint8_t data[CFSTORE_TEST_DATA_KEYNAME_SIZE + CFSTORE_TEST_DATA_VALUE_SIZE]; /* 61 bytes for key_name, 1 byte for value */ 00119 } cfstore_flash_data_blob_t; 00120 00121 /* 00122 * Defines 00123 * 00124 * CFSTORE_FLASH_AREA_SIZE_MIN 00125 * valid sizes of areas should always be greater than the size of the header, and therefore 00126 * greater than this value, which is defined as smaller than the header size 00127 */ 00128 #define CFSTORE_FLASH_AREA_SIZE_MIN (sizeof(cfstore_area_header_t) - 1) 00129 00130 /* 00131 * Shared implementation between sync and async tests 00132 */ 00133 00134 /* print key name string from area where key_name is not null terminated*/ 00135 static void cfstore_dump_key_name(uint8_t* keyname, uint8_t len, const char* tag) 00136 { 00137 char blob_data[CFSTORE_KEY_NAME_MAX_LENGTH]; 00138 00139 (void) tag; 00140 assert(keyname != NULL); 00141 assert(tag != NULL); 00142 assert(len > 0); 00143 memcpy(blob_data, keyname, len); 00144 blob_data[len] = '\0'; 00145 CFSTORE_DBGLOG("%s:keyname=%s\r\n", tag, blob_data); 00146 } 00147 00148 /* @brief test fsm states and events */ 00149 typedef enum cfstore_flash_fsm_state_t { 00150 cfstore_flash_fsm_state_initializing = 0, 00151 cfstore_flash_fsm_state_reading, 00152 cfstore_flash_fsm_state_writing, 00153 cfstore_flash_fsm_state_committing, 00154 cfstore_flash_fsm_state_max 00155 } cfstore_flash_fsm_state_t; 00156 00157 /* @brief test fsm events */ 00158 typedef enum cfstore_flash_fsm_event_t { 00159 cfstore_flash_fsm_event_init_done = 0, 00160 cfstore_flash_fsm_event_read_done, 00161 cfstore_flash_fsm_event_write_done, 00162 cfstore_flash_fsm_event_commit_done, 00163 cfstore_flash_fsm_event_max, 00164 } cfstore_flash_fsm_event_t; 00165 00166 typedef void (*cfstore_flash_fsm_handler)(void* ctx); 00167 00168 typedef struct cfstore_fsm_t 00169 { 00170 cfstore_flash_fsm_state_t state; 00171 cfstore_flash_fsm_event_t event; 00172 } cfstore_fsm_t; 00173 00174 typedef struct cfstore_flash_ctx_t 00175 { 00176 uint8_t* area_0_head; 00177 uint8_t* area_0_tail; 00178 FlashJournal_t jrnl; 00179 uint64_t expected_blob_size; 00180 cfstore_fsm_t fsm; 00181 int32_t status; 00182 FlashJournal_OpCode_t cmd_code; 00183 uint64_t expected_read_size; 00184 } cfstore_flash_ctx_t; 00185 00186 /* 00187 * Globals 00188 */ 00189 static cfstore_flash_ctx_t cfstore_flash_ctx_g; 00190 static const char* cfstore_flash_opcode_str[] = 00191 { 00192 "FLASH_JOURNAL_OPCODE_INITIALIZE", 00193 "FLASH_JOURNAL_OPCODE_GET_INFO", 00194 "FLASH_JOURNAL_OPCODE_READ_BLOB", 00195 "FLASH_JOURNAL_OPCODE_LOG_BLOB", 00196 "FLASH_JOURNAL_OPCODE_COMMIT", 00197 "FLASH_JOURNAL_OPCODE_RESET", 00198 }; 00199 00200 #ifdef CFSTORE_DEBUG 00201 static const char* cfstore_flash_state_str[] = 00202 { 00203 "initializing", 00204 "reading", 00205 "writing", 00206 "committing", 00207 "unknown" 00208 }; 00209 00210 static const char* cfstore_flash_event_str[] = 00211 { 00212 "init_done", 00213 "read_done", 00214 "write_done", 00215 "commit_done", 00216 "unknown" 00217 }; 00218 #endif /* CFSTORE_DEBUG */ 00219 00220 /* 00221 * Forward decl 00222 */ 00223 static void cfstore_fsm_state_handle_event(cfstore_fsm_t* fsm, cfstore_flash_fsm_event_t event, void* context); 00224 static void cfstore_fsm_state_set(cfstore_fsm_t* fsm, cfstore_flash_fsm_state_t new_state, void* ctx); 00225 00226 /* 00227 * context related methods 00228 */ 00229 00230 /* @brief get a pointer to the global context data structure */ 00231 static cfstore_flash_ctx_t* cfstore_flash_ctx_get(void) 00232 { 00233 return &cfstore_flash_ctx_g; 00234 } 00235 00236 00237 /* @brief flash journal asynchronous callback handler */ 00238 void cfstore_flash_test_01_callback(int32_t status, FlashJournal_OpCode_t cmd_code) 00239 { 00240 cfstore_flash_ctx_t* ctx = cfstore_flash_ctx_get(); 00241 00242 CFSTORE_FENTRYLOG("%s:entered: status=%d, cmd_code=%d (%s)\r\n", __func__, (int) status, (int) cmd_code, cfstore_flash_opcode_str[cmd_code]); 00243 switch(cmd_code) 00244 { 00245 case FLASH_JOURNAL_OPCODE_INITIALIZE: 00246 ctx->fsm.event = cfstore_flash_fsm_event_init_done; 00247 break; 00248 case FLASH_JOURNAL_OPCODE_READ_BLOB: 00249 ctx->fsm.event = cfstore_flash_fsm_event_read_done; 00250 break; 00251 case FLASH_JOURNAL_OPCODE_LOG_BLOB: 00252 ctx->fsm.event = cfstore_flash_fsm_event_write_done; 00253 break; 00254 case FLASH_JOURNAL_OPCODE_COMMIT: 00255 ctx->fsm.event = cfstore_flash_fsm_event_commit_done; 00256 break; 00257 case FLASH_JOURNAL_OPCODE_GET_INFO: 00258 case FLASH_JOURNAL_OPCODE_RESET: 00259 default: 00260 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"); 00261 TEST_ASSERT_MESSAGE(false, cfstore_flash_utest_msg_g) 00262 return; 00263 } 00264 ctx->status = status; 00265 ctx->cmd_code = cmd_code; 00266 cfstore_fsm_state_handle_event(&ctx->fsm, ctx->fsm.event, (void*) ctx); 00267 return; 00268 } 00269 00270 00271 /* @brief fsm handler called on entry to initializing state */ 00272 static void cfstore_flash_fsm_init_on_entry(void* context) 00273 { 00274 /* round up cfstore_flash_data_blob_t to nearest k64f program unit size */ 00275 const ARM_DRIVER_STORAGE *drv = &ARM_Driver_Storage_MTD_K64F; 00276 FlashJournal_Info_t info; 00277 FlashJournal_Status_t status = JOURNAL_STATUS_ERROR; 00278 cfstore_flash_ctx_t* ctx = (cfstore_flash_ctx_t*) context; 00279 00280 /* check that the mtd is in synchronous mode */ 00281 CFSTORE_FENTRYLOG("%s:entered: \r\n", __func__); 00282 memset(&info, 0, sizeof(info)); 00283 00284 /* FlashJournal_initialize() is potentially asynchronous */ 00285 status = (FlashJournal_Status_t) FlashJournal_initialize(&ctx->jrnl, drv, &FLASH_JOURNAL_STRATEGY_SEQUENTIAL, cfstore_flash_test_01_callback); 00286 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); 00287 TEST_ASSERT_MESSAGE(status >= JOURNAL_STATUS_OK, cfstore_flash_utest_msg_g); 00288 /* if status > 0, expect async callback, otherwise initialisation has been completed */ 00289 if(status > 0) { 00290 cfstore_flash_test_01_callback(status, FLASH_JOURNAL_OPCODE_INITIALIZE); 00291 } 00292 return; 00293 } 00294 00295 /* brief callback handler when in state initializing */ 00296 static void cfstore_flash_fsm_initializing(void* context) 00297 { 00298 cfstore_flash_ctx_t* ctx = (cfstore_flash_ctx_t*) context; 00299 00300 CFSTORE_FENTRYLOG("%s:entered\r\n", __func__); 00301 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); 00302 TEST_ASSERT_MESSAGE(ctx->fsm.state == cfstore_flash_fsm_state_initializing, cfstore_flash_utest_msg_g); 00303 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); 00304 TEST_ASSERT_MESSAGE(ctx->cmd_code == FLASH_JOURNAL_OPCODE_INITIALIZE, cfstore_flash_utest_msg_g); 00305 CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: status=%d\r\n", __func__, (int) ctx->status); 00306 TEST_ASSERT_MESSAGE(ctx->status >= JOURNAL_STATUS_OK, cfstore_flash_utest_msg_g); 00307 /* only change state if status > 0*/ 00308 if(ctx->status > 0){ 00309 cfstore_fsm_state_set(&ctx->fsm, cfstore_flash_fsm_state_reading, ctx); 00310 } 00311 } 00312 00313 /* static void cfstore_flash_fsm_init_on_exit(void* context){ (void) context;} */ 00314 00315 /* brief callback handler called when entering the reading state 00316 * note 00317 * flash journal has initialised successfully. now 00318 */ 00319 static void cfstore_flash_fsm_read_on_entry(void* context) 00320 { 00321 uint8_t* ptr = NULL; 00322 int32_t ret = 0; 00323 FlashJournal_Info_t info; 00324 FlashJournal_Status_t status = JOURNAL_STATUS_ERROR; 00325 cfstore_flash_ctx_t* ctx = (cfstore_flash_ctx_t*) context; 00326 00327 CFSTORE_FENTRYLOG("%s:entered\r\n", __func__); 00328 CFSTORE_ASSERT(ctx != NULL); 00329 /* drv->GetInfo() is synchronous */ 00330 status = FlashJournal_getInfo(&ctx->jrnl, &info); 00331 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); 00332 TEST_ASSERT_MESSAGE(status == JOURNAL_STATUS_OK, cfstore_flash_utest_msg_g); 00333 CFSTORE_DBGLOG("%s:FlashJournal_getInfo() done. info.sizeofJournaledBlob=%lu\r\n", __func__, (long unsigned int) info.sizeofJournaledBlob); 00334 00335 if(info.sizeofJournaledBlob > 0) 00336 { 00337 /* setup the expected blob size for writing 00338 * This is a multiple of program unit so the write doesnt fail due to unaligned log */ 00339 ctx->expected_blob_size = sizeof(cfstore_flash_data_blob_t); 00340 if(ctx->expected_blob_size % CFSTORE_FLASH_K64F_CURRENT_PROGRAM_UNIT_SIZE > 0){ 00341 ctx->expected_blob_size += (CFSTORE_FLASH_K64F_CURRENT_PROGRAM_UNIT_SIZE - (sizeof(cfstore_flash_data_blob_t) % CFSTORE_FLASH_K64F_CURRENT_PROGRAM_UNIT_SIZE)); 00342 } 00343 /* test that a blob size is the expected size for flash data that has been written before */ 00344 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); 00345 TEST_ASSERT_EQUAL_INT64_MESSAGE(ctx->expected_blob_size, info.sizeofJournaledBlob, cfstore_flash_utest_msg_g); 00346 00347 /* grow the area by the size of the stored blob */ 00348 ptr = (uint8_t*) CFSTORE_REALLOC((void*) ctx->area_0_head, ctx->expected_blob_size); 00349 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); 00350 TEST_ASSERT_MESSAGE(ptr != NULL, cfstore_flash_utest_msg_g); 00351 memset(ptr, 0, ctx->expected_blob_size); 00352 if(ptr != ctx->area_0_head){ 00353 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); 00354 ctx->area_0_head = ptr; 00355 ctx->area_0_tail = ctx->area_0_head + info.sizeofJournaledBlob; 00356 } 00357 ret = FlashJournal_read(&ctx->jrnl, (void*) ctx->area_0_head, info.sizeofJournaledBlob); 00358 CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: unable to read flash journal (ret=%d. info.sizeofJournaledBlob=%d)\r\n", __func__, (int) ret, (int) info.sizeofJournaledBlob); 00359 TEST_ASSERT_MESSAGE(ret >= JOURNAL_STATUS_OK, cfstore_flash_utest_msg_g); 00360 if(ret > 0){ 00361 /* read has completed synchronously*/ 00362 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=%d)\r\n", __func__, (unsigned long int)info.sizeofJournaledBlob, (int) ret); 00363 TEST_ASSERT_EQUAL_INT32_MESSAGE( (int32_t) info.sizeofJournaledBlob, ret, cfstore_flash_utest_msg_g); 00364 cfstore_flash_test_01_callback(ret, FLASH_JOURNAL_OPCODE_READ_BLOB); 00365 } 00366 } else { 00367 /* there is no blob, move to next state. need a +ve status value to indicate async completion 00368 * to the fsm reading state handler. use CFSTORE_FLASH_AREA_SIZE_MIN for this value */ 00369 ctx->expected_blob_size = CFSTORE_FLASH_AREA_SIZE_MIN; 00370 status = (FlashJournal_Status_t) CFSTORE_FLASH_AREA_SIZE_MIN; 00371 cfstore_flash_test_01_callback(status, FLASH_JOURNAL_OPCODE_READ_BLOB); 00372 } 00373 return; 00374 } 00375 00376 /* @brief fsm handler when in reading state */ 00377 void cfstore_flash_fsm_reading(void* context) 00378 { 00379 int32_t ret = 0; 00380 cfstore_flash_ctx_t* ctx = (cfstore_flash_ctx_t*) context; 00381 cfstore_flash_data_blob_t *blob = NULL; 00382 00383 CFSTORE_FENTRYLOG("%s:entered\r\n", __func__); 00384 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); 00385 TEST_ASSERT_MESSAGE(ctx->fsm.state == cfstore_flash_fsm_state_reading, cfstore_flash_utest_msg_g); 00386 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); 00387 TEST_ASSERT_MESSAGE(ctx->cmd_code == FLASH_JOURNAL_OPCODE_READ_BLOB, cfstore_flash_utest_msg_g); 00388 CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: status=%d\r\n", __func__, (int) ctx->status); 00389 TEST_ASSERT_MESSAGE(ctx->status >= JOURNAL_STATUS_OK, cfstore_flash_utest_msg_g); 00390 00391 if(ctx->status > 0) 00392 { 00393 if(ctx->status > (int32_t) CFSTORE_FLASH_AREA_SIZE_MIN) 00394 { 00395 /* check the correct amount of data was read, which is the status code */ 00396 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=%d)\r\n", __func__, (unsigned long int) ctx->expected_blob_size, (int) ctx->status); 00397 /* ctx->status contains the status of the read that was completed */ 00398 TEST_ASSERT_EQUAL_INT64_MESSAGE(ctx->expected_blob_size, (int32_t) ctx->status, cfstore_flash_utest_msg_g); 00399 if(ctx->area_0_head != NULL) 00400 { 00401 /* check the key_name read from flash is correct */ 00402 blob = (cfstore_flash_data_blob_t*) ctx->area_0_head; 00403 cfstore_dump_key_name(blob->data, CFSTORE_TEST_DATA_KEYNAME_SIZE, __func__); 00404 ret = memcmp(blob->data, cfstore_flush_test_01_kv_data[0].key_name, strlen(cfstore_flush_test_01_kv_data[0].key_name)); 00405 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__); 00406 TEST_ASSERT_EQUAL_INT_MESSAGE(0, ret, cfstore_flash_utest_msg_g); 00407 } 00408 } 00409 cfstore_fsm_state_set(&ctx->fsm, cfstore_flash_fsm_state_writing, ctx); 00410 } 00411 } 00412 00413 /* void cfstore_flash_fsm_read_on_exit(void* context){ (void) context;} */ 00414 00415 /* @brief on entry to writing state, update value */ 00416 void cfstore_flash_fsm_write_on_entry(void* context) 00417 { 00418 uint8_t value = 0; 00419 int32_t ret = 0; 00420 cfstore_flash_ctx_t* ctx = (cfstore_flash_ctx_t*) context; 00421 cfstore_flash_data_blob_t *blob = NULL; 00422 00423 CFSTORE_FENTRYLOG("%s:entered:\r\n", __func__); 00424 /* allocate memory for data if not already done so */ 00425 if(ctx->area_0_head == NULL) 00426 { 00427 /* This is a multiple of program unit so the write doesnt fail due to unaligned log */ 00428 ctx->expected_blob_size = sizeof(cfstore_flash_data_blob_t); 00429 if(ctx->expected_blob_size % CFSTORE_FLASH_K64F_CURRENT_PROGRAM_UNIT_SIZE > 0){ 00430 ctx->expected_blob_size += (CFSTORE_FLASH_K64F_CURRENT_PROGRAM_UNIT_SIZE - (sizeof(cfstore_flash_data_blob_t) % CFSTORE_FLASH_K64F_CURRENT_PROGRAM_UNIT_SIZE)); 00431 } 00432 ctx->area_0_head = (uint8_t*) CFSTORE_REALLOC((void*) ctx->area_0_head, ctx->expected_blob_size); 00433 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__); 00434 TEST_ASSERT_MESSAGE(ctx->area_0_head != NULL, cfstore_flash_utest_msg_g); 00435 ctx->area_0_tail = ctx->area_0_head + ctx->expected_blob_size; 00436 memset(ctx->area_0_head, 0, ctx->expected_blob_size); 00437 /* setup data to write to flash */ 00438 blob = (cfstore_flash_data_blob_t*) ctx->area_0_head; 00439 blob->hdr.klength = strlen(cfstore_flush_test_01_kv_data->key_name); 00440 blob->hdr.vlength= 1; 00441 blob->hdr.perm_owner_read = true; 00442 blob->hdr.perm_owner_write = true; 00443 blob->hdr.refcount = 1; 00444 memcpy((void*) blob->data, (const void*) cfstore_flush_test_01_kv_data->key_name, strlen(cfstore_flush_test_01_kv_data->key_name)); 00445 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)); 00446 } 00447 if(ctx->area_0_head != NULL) 00448 { 00449 /* data has been read */ 00450 /* check the key_name read from flash is correct */ 00451 blob = (cfstore_flash_data_blob_t*) ctx->area_0_head; 00452 value = (uint8_t) blob->data[CFSTORE_TEST_DATA_KEYNAME_SIZE]; 00453 CFSTORE_DBGLOG("INFO: value read from flash = %u\r\n", value); 00454 /* update the value */ 00455 value++; 00456 memcpy((void*) &blob->data[CFSTORE_TEST_DATA_KEYNAME_SIZE], (const void*) &value, sizeof(uint8_t)); 00457 } 00458 00459 ret = FlashJournal_log(&ctx->jrnl, (const void*) ctx->area_0_head, ctx->expected_blob_size); 00460 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__); 00461 TEST_ASSERT_MESSAGE(ret != (int32_t) JOURNAL_STATUS_SMALL_LOG_REQUEST, cfstore_flash_utest_msg_g); 00462 00463 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=%d)\r\n", __func__, (int) ret); 00464 TEST_ASSERT_MESSAGE(ret >= 0, cfstore_flash_utest_msg_g); 00465 if(ret > 0){ 00466 /* write has completed synchronously*/ 00467 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); 00468 TEST_ASSERT_EQUAL_INT32_MESSAGE(ret, (int32_t) ctx->expected_blob_size, cfstore_flash_utest_msg_g); 00469 cfstore_flash_test_01_callback(ret, FLASH_JOURNAL_OPCODE_LOG_BLOB); 00470 } 00471 /* wait for async completion handler*/ 00472 } 00473 00474 /* @brief fsm handler when in reading state */ 00475 void cfstore_flash_fsm_writing(void* context) 00476 { 00477 cfstore_flash_ctx_t* ctx = (cfstore_flash_ctx_t*) context; 00478 00479 CFSTORE_FENTRYLOG("%s:entered:\r\n", __func__); 00480 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); 00481 TEST_ASSERT_MESSAGE(ctx->fsm.state == cfstore_flash_fsm_state_writing, cfstore_flash_utest_msg_g); 00482 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); 00483 TEST_ASSERT_MESSAGE(ctx->cmd_code == FLASH_JOURNAL_OPCODE_LOG_BLOB, cfstore_flash_utest_msg_g); 00484 CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: status=%d\r\n", __func__, (int) ctx->status); 00485 TEST_ASSERT_MESSAGE(ctx->status >= JOURNAL_STATUS_OK, cfstore_flash_utest_msg_g); 00486 00487 if(ctx->status > 0){ 00488 /* check the correct amount of data was written */ 00489 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) ctx->status); 00490 TEST_ASSERT_EQUAL_INT64_MESSAGE(ctx->expected_blob_size, ctx->status, cfstore_flash_utest_msg_g); 00491 cfstore_fsm_state_set(&ctx->fsm, cfstore_flash_fsm_state_committing, ctx); 00492 } 00493 return; 00494 } 00495 00496 /* void cfstore_flash_fsm_write_on_exit(void* ctx){(void) ctx;} */ 00497 00498 /* @brief fsm handler when entering committing state */ 00499 void cfstore_flash_fsm_commit_on_entry(void* context) 00500 { 00501 int32_t ret = 0; 00502 cfstore_flash_ctx_t* ctx = (cfstore_flash_ctx_t*) context; 00503 00504 CFSTORE_FENTRYLOG("%s:entered:\r\n", __func__); 00505 ret = FlashJournal_commit(&ctx->jrnl); 00506 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); 00507 TEST_ASSERT_MESSAGE(ret >= (int32_t) JOURNAL_STATUS_OK, cfstore_flash_utest_msg_g); 00508 /* for flash-journal-strategy-sequential version >0.4.0, commit() return no longer reports size of commit block */ 00509 if(ret > 0){ 00510 Harness::validate_callback(); 00511 } 00512 /* wait for async completion handler*/ 00513 return; 00514 } 00515 00516 00517 /* @brief fsm handler when in committing state */ 00518 void cfstore_flash_fsm_committing(void* context) 00519 { 00520 cfstore_flash_ctx_t* ctx = (cfstore_flash_ctx_t*) context; 00521 00522 CFSTORE_FENTRYLOG("%s:entered\r\n", __func__); 00523 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); 00524 TEST_ASSERT_MESSAGE(ctx->fsm.state == cfstore_flash_fsm_state_committing, cfstore_flash_utest_msg_g); 00525 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); 00526 TEST_ASSERT_MESSAGE(ctx->cmd_code == FLASH_JOURNAL_OPCODE_COMMIT, cfstore_flash_utest_msg_g); 00527 CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_FLASH_UTEST_MSG_BUF_SIZE, "%s:Error: status=%d\r\n", __func__, (int) ctx->status); 00528 TEST_ASSERT_MESSAGE(ctx->status >= JOURNAL_STATUS_OK, cfstore_flash_utest_msg_g); 00529 00530 /* check the correct amount of data was written */ 00531 /* for flash-journal-strategy-sequential version >0.4.0, commit() return no longer reports size of commit block */ 00532 Harness::validate_callback(); 00533 } 00534 00535 /* @brief fsm handler when exiting committing state */ 00536 void cfstore_flash_fsm_commit_on_exit(void* context) 00537 { 00538 cfstore_flash_ctx_t* ctx = (cfstore_flash_ctx_t*) context; 00539 00540 CFSTORE_FENTRYLOG("%s:entered\r\n", __func__); 00541 /* test done. clean up*/ 00542 if(ctx->area_0_head){ 00543 CFSTORE_FREE(ctx->area_0_head); 00544 ctx->area_0_head = NULL; 00545 } 00546 Harness::validate_callback(); 00547 } 00548 00549 #define cfstore_flash_fsm_null NULL 00550 00551 /* handler functions while in state */ 00552 static cfstore_flash_fsm_handler cfstore_flash_fsm[cfstore_flash_fsm_state_max][cfstore_flash_fsm_event_max] = 00553 { 00554 /* state\event: init_done read_done write_done commit_done */ 00555 /* initialising */ {cfstore_flash_fsm_initializing, cfstore_flash_fsm_null, cfstore_flash_fsm_null, cfstore_flash_fsm_null }, 00556 /* reading */ {cfstore_flash_fsm_null, cfstore_flash_fsm_reading, cfstore_flash_fsm_null, cfstore_flash_fsm_null }, 00557 /* writing */ {cfstore_flash_fsm_null, cfstore_flash_fsm_null, cfstore_flash_fsm_writing, cfstore_flash_fsm_null }, 00558 /* committing */ {cfstore_flash_fsm_null, cfstore_flash_fsm_null, cfstore_flash_fsm_null, cfstore_flash_fsm_committing }, 00559 }; 00560 00561 00562 /* handler functions for entering the state*/ 00563 cfstore_flash_fsm_handler cfstore_flash_fsm_on_entry[cfstore_flash_fsm_state_max] = 00564 { 00565 cfstore_flash_fsm_init_on_entry, 00566 cfstore_flash_fsm_read_on_entry, 00567 cfstore_flash_fsm_write_on_entry, 00568 cfstore_flash_fsm_commit_on_entry, 00569 }; 00570 00571 /* handler functions for exiting state, currently none used */ 00572 cfstore_flash_fsm_handler cfstore_flash_fsm_on_exit[cfstore_flash_fsm_state_max] = 00573 { 00574 NULL, NULL, NULL, NULL, 00575 }; 00576 00577 00578 /* @brief inject event into fsm */ 00579 static void cfstore_fsm_state_handle_event(cfstore_fsm_t* fsm, cfstore_flash_fsm_event_t event, void* context) 00580 { 00581 cfstore_flash_ctx_t* ctx = (cfstore_flash_ctx_t*) context; 00582 00583 CFSTORE_FENTRYLOG("%s:entered: fsm=%p, event=%d (%s), ctx=%p\r\n", __func__, fsm, (int) event, cfstore_flash_event_str[event], ctx); 00584 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); 00585 TEST_ASSERT_MESSAGE(event < cfstore_flash_fsm_event_max, cfstore_flash_utest_msg_g); 00586 fsm->event = event; 00587 if(cfstore_flash_fsm[fsm->state][fsm->event] != NULL){ 00588 cfstore_flash_fsm[fsm->state][fsm->event](ctx); 00589 } 00590 00591 /* do not clear context data set by caller as it may be used later 00592 * fsm->event = cfstore_flash_fsm_event_max; 00593 * ctx->status = 0; 00594 * ctx->cmd_code = (FlashJournal_OpCode_t)((int) FLASH_JOURNAL_OPCODE_RESET+1); 00595 */ 00596 return; 00597 } 00598 00599 00600 /* @brief function to move to new fsm state, calling state exit function for old state and entry function for new state */ 00601 static void cfstore_fsm_state_set(cfstore_fsm_t* fsm, cfstore_flash_fsm_state_t new_state, void* ctx) 00602 { 00603 CFSTORE_FENTRYLOG("%s:entered: fsm=%p, new_state=%d, ctx=%p\r\n", __func__, fsm, (int) new_state, ctx); 00604 CFSTORE_DBGLOG("%s:FSM:REQ RX:%s:%s\r\n", __func__, cfstore_flash_state_str[fsm->state], cfstore_flash_state_str[new_state]); 00605 TEST_ASSERT_MESSAGE(fsm != NULL, "fsm is not a valid pointer"); 00606 TEST_ASSERT_MESSAGE(new_state < cfstore_flash_fsm_state_max, "new_state is not a valid state"); 00607 TEST_ASSERT_MESSAGE(ctx != NULL, "ctx is not a valid pointer"); 00608 TEST_ASSERT_MESSAGE(fsm->state < cfstore_flash_fsm_state_max, "fsm->state is not a valid state"); 00609 00610 if(cfstore_flash_fsm_on_exit[fsm->state] != NULL){ 00611 cfstore_flash_fsm_on_exit[fsm->state](ctx); 00612 } 00613 fsm->state = new_state; 00614 if(cfstore_flash_fsm_on_entry[new_state] != NULL){ 00615 cfstore_flash_fsm_on_entry[new_state](ctx); 00616 } 00617 CFSTORE_DBGLOG("%s:FSM:REQ DONE:\r\n", __func__); 00618 return; 00619 } 00620 00621 /* @brief initialize global context data structure */ 00622 static void cfstore_flash_ctx_init(cfstore_flash_ctx_t* ctx) 00623 { 00624 TEST_ASSERT_MESSAGE(ctx != NULL, "ctx is NULL"); 00625 00626 CFSTORE_FENTRYLOG("%s:entered\r\n", __func__); 00627 memset(&cfstore_flash_ctx_g, 0, sizeof(cfstore_flash_ctx_g)); 00628 } 00629 00630 00631 /* @brief asynchronous test 01 */ 00632 static control_t cfstore_flash_journal_async_test_01(void) 00633 { 00634 cfstore_flash_ctx_t* ctx = cfstore_flash_ctx_get(); 00635 00636 CFSTORE_FENTRYLOG("%s:entered: \r\n", __func__); 00637 cfstore_flash_mtd_async_ops_g = CFSTORE_FLASH_MTD_ASYNC_OPS_ON; 00638 cfstore_flash_ctx_init(ctx); 00639 cfstore_fsm_state_set(&ctx->fsm, cfstore_flash_fsm_state_initializing, ctx); 00640 00641 /* allow time for work to be done */ 00642 return CaseTimeout(CFSTORE_FLASH_CASE_TIMEOUT_MS); 00643 } 00644 00645 #endif /* CFSTORE_CONFIG_BACKEND_FLASH_ENABLED */ 00646 00647 00648 /* report whether built/configured for flash sync or async mode */ 00649 static control_t cfstore_flash_test_00(const size_t call_count) 00650 { 00651 int32_t ret = ARM_DRIVER_ERROR; 00652 00653 (void) call_count; 00654 ret = cfstore_test_startup(); 00655 CFSTORE_TEST_UTEST_MESSAGE(cfstore_flash_utest_msg_g, CFSTORE_UTEST_MSG_BUF_SIZE, "%s:Error: failed to perform test startup (ret=%d).\n", __func__, (int) ret); 00656 TEST_ASSERT_MESSAGE(ret >= ARM_DRIVER_OK, cfstore_flash_utest_msg_g); 00657 00658 #ifndef CFSTORE_CONFIG_BACKEND_FLASH_ENABLED 00659 CFSTORE_LOG("INITIALIZING: BACKEND=SRAM. Skipping flash test%s", "\n"); 00660 #endif 00661 return CaseNext; 00662 } 00663 00664 /// @cond CFSTORE_DOXYGEN_DISABLE 00665 /* Specify all your test cases here */ 00666 Case cases[] = { 00667 Case("flash_journal_async_test_00", cfstore_flash_test_00), 00668 #ifdef CFSTORE_CONFIG_BACKEND_FLASH_ENABLED 00669 Case("flash_journal_async_test_01", cfstore_flash_journal_async_test_01), 00670 #endif 00671 }; 00672 00673 00674 utest::v1::status_t greentea_setup(const size_t number_of_cases) 00675 { 00676 GREENTEA_SETUP(100, "default_auto"); 00677 return greentea_test_setup_handler(number_of_cases); 00678 } 00679 00680 /* Declare your test specification with a custom setup handler */ 00681 Specification specification(greentea_setup, cases); 00682 00683 00684 int main() 00685 { 00686 return !Harness::run(specification); 00687 } 00688 /// @endcond
Generated on Tue Aug 9 2022 00:37:07 by
1.7.2