Rtos API example

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers basicAPI.cpp Source File

basicAPI.cpp

00001 /*
00002  * Copyright (c) 2006-2016, ARM Limited, All Rights Reserved
00003  * SPDX-License-Identifier: Apache-2.0
00004  *
00005  * Licensed under the Apache License, Version 2.0 (the "License"); you may
00006  * 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, WITHOUT
00013  * 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 #ifdef TARGET_LIKE_POSIX
00019 #define AVOID_GREENTEA
00020 #endif
00021 
00022 #ifndef AVOID_GREENTEA
00023 #include "greentea-client/test_env.h"
00024 #endif
00025 #include "utest/utest.h"
00026 #include "unity/unity.h"
00027 
00028 #include "storage-volume-manager/storage_volume_manager.h"
00029 #include <string.h>
00030 #include <inttypes.h>
00031 
00032 using namespace utest::v1;
00033 
00034 /* redefine tr_info() to a printf() equivalent to emit trace */
00035 #define tr_info(...)                                ((void) 0)
00036 #define mbed_trace_init(...)                        ((void) 0)
00037 #define mbed_trace_config_set(...)                  ((void) 0)
00038 
00039 #ifdef TARGET_LIKE_X86_LINUX_NATIVE
00040 extern ARM_DRIVER_STORAGE ARM_Driver_Storage_MTD_RAM;
00041 ARM_DRIVER_STORAGE *drv = &ARM_Driver_Storage_MTD_RAM;
00042 #elif defined TARGET_LIKE_FRDM_K64F
00043 extern ARM_DRIVER_STORAGE ARM_Driver_Storage_MTD_K64F;
00044 ARM_DRIVER_STORAGE *drv = &ARM_Driver_Storage_MTD_K64F;
00045 #else
00046 extern ARM_DRIVER_STORAGE ARM_Driver_Storage_MTD_K64F;
00047 ARM_DRIVER_STORAGE *drv = &ARM_Driver_Storage_MTD_K64F;
00048 #endif
00049 
00050 /* temporary buffer to hold data for testing. */
00051 static const unsigned BUFFER_SIZE = 16384;
00052 static uint8_t buffer[BUFFER_SIZE];
00053 
00054 static int32_t callbackStatus;
00055 static int32_t virtualVolumeCallbackStatus;
00056 
00057 #ifndef AVOID_GREENTEA
00058 // Custom setup handler required for proper Greentea support
00059 utest::v1::status_t greentea_setup(const size_t number_of_cases)
00060 {
00061     GREENTEA_SETUP(30, "default_auto");
00062     // Call the default reporting function
00063     return greentea_test_setup_handler(number_of_cases);
00064 }
00065 #endif
00066 
00067 /* used only for the initialization of the volume-manager. */
00068 void initializeCallbackHandler(int32_t status)
00069 {
00070     tr_info("in initializeCallbackHandler\r\n");
00071     Harness::validate_callback();
00072 }
00073 
00074 /* used only when accessing MTD directly (for verification) */
00075 void mtdCallbackHandler(int32_t status, ARM_STORAGE_OPERATION operation)
00076 {
00077     tr_info("in mtdCallbackHandler");
00078     callbackStatus = status;
00079     Harness::validate_callback();
00080 }
00081 
00082 /* the normal callback handler for the virtual volume */
00083 void virtualMTDCallbackHandler(int32_t status, ARM_STORAGE_OPERATION operation)
00084 {
00085     tr_info("in virtualMTDCallbackHandler");
00086     virtualVolumeCallbackStatus = status;
00087     Harness::validate_callback();
00088 }
00089 
00090 control_t test_initialize(const size_t call_count)
00091 {
00092     tr_info("test_initialize: called with call_count %lu", call_count);
00093     static StorageVolumeManager volumeManager;
00094 
00095     if (call_count == 1) {
00096         int32_t rc = volumeManager.initialize(drv, initializeCallbackHandler);
00097         TEST_ASSERT(rc >= ARM_DRIVER_OK);
00098         if (rc == ARM_DRIVER_OK) {
00099             TEST_ASSERT_EQUAL(1,  drv->GetCapabilities().asynchronous_ops);
00100             return CaseTimeout(200) + CaseRepeatAll;
00101         }
00102 
00103         /* synchronous completion */
00104         TEST_ASSERT(rc == 1);
00105     }
00106 
00107     TEST_ASSERT_EQUAL(true, volumeManager.isInitialized());
00108     TEST_ASSERT(volumeManager.getStorageInfo().total_storage > 0);
00109     for (size_t index = 0; index < MAX_VOLUMES; index++) {
00110         TEST_ASSERT_EQUAL(false, volumeManager.volumeAtIndex(index)->isAllocated());
00111     }
00112 
00113     return CaseNext;
00114 }
00115 
00116 template <uint64_t OFFSET>
00117 control_t test_againstSingleVolumeAtOffset(const size_t call_count)
00118 {
00119     tr_info("test_againstSingleVolumeAtOffset: called with call_count %lu", call_count);
00120     static StorageVolumeManager volumeManager;
00121     static StorageVolume *volumeP = NULL;
00122     static ARM_STORAGE_INFO info;
00123     static size_t sizeofDataOperation;
00124 
00125     const uint8_t PATTERN_FOR_PROGRAM_DATA = 0xAA;
00126 
00127     static enum {
00128         VOLUME_MANAGER_INITIALIZE = 1,
00129         BASIC_SYNCHRONOUS_API_TESTING,
00130         READ_DATA,
00131         ERASE,
00132         READ_AFTER_ERASE,
00133         PROGRAM_DATA,
00134         READ_AFTER_PROGRAM_DATA,
00135         VERIFY_PROGRAM_DATA,
00136         DISCONNECT_VOLUME_MANAGER_CALLBACK,
00137         READ_FROM_DRV_AFTER_PROGRAM_DATA,
00138         VERIFY_PROGRAM_DATA2,
00139     } state = VOLUME_MANAGER_INITIALIZE;
00140     tr_info("came in with state %u", state);
00141 
00142     int32_t rc;
00143     ARM_STORAGE_BLOCK firstBlock;
00144     rc = drv->GetNextBlock(NULL, &firstBlock);
00145     TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00146     TEST_ASSERT(ARM_STORAGE_VALID_BLOCK(&firstBlock));
00147 
00148     switch (state) {
00149         case VOLUME_MANAGER_INITIALIZE:
00150             rc = volumeManager.initialize(drv, initializeCallbackHandler);
00151             TEST_ASSERT(rc >= ARM_DRIVER_OK);
00152             if (rc == ARM_DRIVER_OK) {
00153                 TEST_ASSERT_EQUAL(1,  drv->GetCapabilities().asynchronous_ops);
00154                 state = BASIC_SYNCHRONOUS_API_TESTING;
00155                 return CaseTimeout(200) + CaseRepeatAll;
00156             }
00157 
00158             /* synchronous completion */
00159             TEST_ASSERT(rc == 1);
00160 
00161             /* intentional fall-through */
00162 
00163         case BASIC_SYNCHRONOUS_API_TESTING:
00164             TEST_ASSERT_EQUAL(true, volumeManager.isInitialized());
00165 
00166             rc = drv->GetInfo(&info);
00167             TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00168             TEST_ASSERT(info.total_storage > 0);
00169 
00170             { /* add volume */
00171                 rc = volumeManager.addVolume(firstBlock.addr + OFFSET /*addr*/, info.total_storage - OFFSET /*size*/ , &volumeP);
00172                 TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00173 
00174                 TEST_ASSERT_EQUAL(true, volumeManager.volumeAtIndex(0)->isAllocated());
00175                 for (size_t index = 1; index < MAX_VOLUMES; index++) {
00176                     TEST_ASSERT_EQUAL(false, volumeManager.volumeAtIndex(index)->isAllocated());
00177                 }
00178             }
00179 
00180             { /* GetVersion */
00181                 TEST_ASSERT_EQUAL(drv->GetVersion().api, volumeP->GetVersion().api);
00182                 TEST_ASSERT_EQUAL(drv->GetVersion().drv, volumeP->GetVersion().drv);
00183             }
00184 
00185             { /* GetCapabilities */
00186                 TEST_ASSERT_EQUAL(drv->GetCapabilities().asynchronous_ops, volumeP->GetCapabilities().asynchronous_ops);
00187                 TEST_ASSERT_EQUAL(drv->GetCapabilities().erase_all,        volumeP->GetCapabilities().erase_all);
00188             }
00189 
00190             { /* Initialize */
00191                 rc = volumeP->Initialize(virtualMTDCallbackHandler);
00192                 TEST_ASSERT_EQUAL(1, rc);
00193             }
00194 
00195             { /* GetStatus */
00196                 ARM_STORAGE_STATUS status = volumeP->GetStatus();
00197                 TEST_ASSERT_EQUAL(0, status.busy);
00198                 TEST_ASSERT_EQUAL(0, status.error);
00199             }
00200 
00201             { /* GetInfo */
00202                 ARM_STORAGE_INFO volumeInfo;
00203                 rc = volumeP->GetInfo(&volumeInfo);
00204                 TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00205 
00206                 TEST_ASSERT_EQUAL(info.total_storage - OFFSET, volumeInfo.total_storage);
00207                 TEST_ASSERT_EQUAL(info.program_unit,           volumeInfo.program_unit);
00208                 TEST_ASSERT_EQUAL(info.optimal_program_unit,   volumeInfo.optimal_program_unit);
00209                 TEST_ASSERT_EQUAL(info.program_cycles,         volumeInfo.program_cycles);
00210                 TEST_ASSERT_EQUAL(info.erased_value,           volumeInfo.erased_value);
00211                 TEST_ASSERT_EQUAL(info.memory_mapped,          volumeInfo.memory_mapped);
00212                 TEST_ASSERT_EQUAL(info.programmability,        volumeInfo.programmability);
00213                 TEST_ASSERT_EQUAL(info.retention_level,        volumeInfo.retention_level);
00214                 TEST_ASSERT_EQUAL(info.reserved,               volumeInfo.reserved);
00215                 TEST_ASSERT_EQUAL(0, memcmp(&info.security, &volumeInfo.security, sizeof(ARM_STORAGE_SECURITY_FEATURES)));
00216             }
00217 
00218             { /* resolve address */
00219                 TEST_ASSERT_EQUAL(firstBlock.addr + OFFSET, volumeP->ResolveAddress(0));
00220                 TEST_ASSERT_EQUAL(firstBlock.addr + OFFSET + info.total_storage, volumeP->ResolveAddress(info.total_storage));
00221                 TEST_ASSERT_EQUAL(firstBlock.addr + OFFSET + info.total_storage / 2, volumeP->ResolveAddress(info.total_storage / 2));
00222             }
00223 
00224             { /* GetNextBlock */
00225                 rc = volumeP->GetNextBlock(NULL, NULL);
00226                 TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00227                 ARM_STORAGE_BLOCK block;
00228                 rc = volumeP->GetNextBlock(NULL, &block);
00229                 TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00230                 TEST_ASSERT_EQUAL(0, block.addr);
00231                 TEST_ASSERT_EQUAL(info.total_storage - OFFSET, block.size);
00232 
00233                 rc = volumeP->GetNextBlock(&block, NULL);
00234                 TEST_ASSERT(rc < ARM_DRIVER_OK);
00235                 rc = volumeP->GetNextBlock(&block, &block);
00236                 TEST_ASSERT(rc < ARM_DRIVER_OK);
00237             }
00238 
00239             { /* GetBlock */
00240                 ARM_STORAGE_BLOCK block;
00241                 rc = volumeP->GetBlock(0, &block);
00242                 TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00243                 TEST_ASSERT_EQUAL(0, block.addr);
00244                 TEST_ASSERT_EQUAL(info.total_storage - OFFSET, block.size);
00245 
00246                 rc = volumeP->GetBlock((info.total_storage / 2), &block);
00247                 TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00248                 TEST_ASSERT_EQUAL(0, block.addr);
00249                 TEST_ASSERT_EQUAL(info.total_storage - OFFSET, block.size);
00250 
00251                 rc = volumeP->GetBlock(info.total_storage, &block);
00252                 TEST_ASSERT(rc < ARM_DRIVER_OK);
00253             }
00254 
00255             state = READ_DATA;
00256             /* intentional fallthrough */
00257 
00258         case READ_DATA:
00259             sizeofDataOperation = ((info.total_storage - OFFSET) > BUFFER_SIZE) ? BUFFER_SIZE : (info.total_storage - OFFSET);
00260             TEST_ASSERT(sizeofDataOperation <= BUFFER_SIZE);
00261 
00262             /* ReadData */
00263             rc = volumeP->ReadData(0, buffer, sizeofDataOperation);
00264             TEST_ASSERT(rc >= ARM_DRIVER_OK);
00265             if (rc == ARM_DRIVER_OK) {
00266                 TEST_ASSERT_EQUAL(1, volumeP->GetCapabilities().asynchronous_ops);
00267                 state = ERASE;
00268                 return CaseTimeout(200) + CaseRepeatAll;
00269             }
00270 
00271             virtualVolumeCallbackStatus = rc;
00272             /* intentional fallthrough */
00273 
00274         case ERASE:
00275             TEST_ASSERT_EQUAL(sizeofDataOperation, virtualVolumeCallbackStatus);
00276 
00277             /* Erase */
00278             rc = volumeP->Erase(0, sizeofDataOperation);
00279             TEST_ASSERT(rc >= ARM_DRIVER_OK);
00280             if (rc == ARM_DRIVER_OK) {
00281                 TEST_ASSERT_EQUAL(1, volumeP->GetCapabilities().asynchronous_ops);
00282                 state = READ_AFTER_ERASE;
00283                 return CaseTimeout(200) + CaseRepeatAll;
00284             }
00285 
00286             virtualVolumeCallbackStatus = rc;
00287             /* intentional fallthrough */
00288 
00289         case READ_AFTER_ERASE:
00290             TEST_ASSERT_EQUAL(sizeofDataOperation, virtualVolumeCallbackStatus);
00291 
00292             /* Read after Erase */
00293             rc = volumeP->ReadData(0, buffer, sizeofDataOperation);
00294             TEST_ASSERT(rc >= ARM_DRIVER_OK);
00295             if (rc == ARM_DRIVER_OK) {
00296                 TEST_ASSERT_EQUAL(1, volumeP->GetCapabilities().asynchronous_ops);
00297                 state = PROGRAM_DATA;
00298                 return CaseTimeout(200) + CaseRepeatAll;
00299             }
00300 
00301             virtualVolumeCallbackStatus = rc;
00302             /* intentional fallthrough */
00303 
00304         case PROGRAM_DATA:
00305             TEST_ASSERT_EQUAL(sizeofDataOperation, virtualVolumeCallbackStatus);
00306             for (size_t index = 0; index < sizeofDataOperation; index++) {
00307                 // if (bytePattern != (buffer)[index]) {
00308                 //     tr_info("%u: expected %x, found %x", index, bytePattern, buffer[index]);
00309                 // }
00310                 TEST_ASSERT_EQUAL(info.erased_value ? (uint8_t)0xFF : (uint8_t)0, buffer[index]);
00311             }
00312 
00313             /* ProgramData */
00314             memset(buffer, PATTERN_FOR_PROGRAM_DATA, sizeofDataOperation);
00315             rc = volumeP->ProgramData(0, buffer, sizeofDataOperation);
00316             TEST_ASSERT(rc >= ARM_DRIVER_OK);
00317             if (rc == ARM_DRIVER_OK) {
00318                 TEST_ASSERT_EQUAL(1, volumeP->GetCapabilities().asynchronous_ops);
00319                 state = READ_AFTER_PROGRAM_DATA;
00320                 return CaseTimeout(200) + CaseRepeatAll;
00321             }
00322 
00323             virtualVolumeCallbackStatus = rc;
00324             /* intentional fallthrough */
00325 
00326         case READ_AFTER_PROGRAM_DATA:
00327             TEST_ASSERT_EQUAL(sizeofDataOperation, virtualVolumeCallbackStatus);
00328 
00329             /* Read after Program */
00330             rc = volumeP->ReadData(0, buffer, sizeofDataOperation);
00331             TEST_ASSERT(rc >= ARM_DRIVER_OK);
00332             if (rc == ARM_DRIVER_OK) {
00333                 TEST_ASSERT_EQUAL(1, volumeP->GetCapabilities().asynchronous_ops);
00334                 state = VERIFY_PROGRAM_DATA;
00335                 return CaseTimeout(200) + CaseRepeatAll;
00336             }
00337 
00338             virtualVolumeCallbackStatus = rc;
00339             /* intentional fallthrough */
00340 
00341         case VERIFY_PROGRAM_DATA:
00342             TEST_ASSERT_EQUAL(sizeofDataOperation, virtualVolumeCallbackStatus);
00343             for (uint32_t index = 0; index < sizeofDataOperation; index++) {
00344                 if ((buffer)[index] != PATTERN_FOR_PROGRAM_DATA) {
00345                     tr_info("%s:%u: %" PRIu32 ": expected 0x%02x, found 0x%02x", __FUNCTION__, __LINE__, index, PATTERN_FOR_PROGRAM_DATA, buffer[index]);
00346                 }
00347                 TEST_ASSERT_EQUAL(PATTERN_FOR_PROGRAM_DATA, buffer[index]);
00348             }
00349             /* intentional fallthrough */
00350 
00351         case DISCONNECT_VOLUME_MANAGER_CALLBACK:
00352             rc = drv->Initialize(mtdCallbackHandler);
00353             TEST_ASSERT_EQUAL(1, rc); /* expect synchronous completion */
00354             /* intentional fallthrough */
00355 
00356         case READ_FROM_DRV_AFTER_PROGRAM_DATA:
00357             /* Read after Program */
00358             rc = drv->ReadData(firstBlock.addr + OFFSET, buffer, sizeofDataOperation);
00359             TEST_ASSERT(rc >= ARM_DRIVER_OK);
00360             if (rc == ARM_DRIVER_OK) {
00361                 TEST_ASSERT_EQUAL(1, volumeP->GetCapabilities().asynchronous_ops);
00362                 state = VERIFY_PROGRAM_DATA2;
00363                 return CaseTimeout(200) + CaseRepeatAll;
00364             }
00365 
00366             callbackStatus = rc;
00367             /* intentional fallthrough */
00368 
00369         case VERIFY_PROGRAM_DATA2:
00370             TEST_ASSERT_EQUAL(sizeofDataOperation, callbackStatus);
00371             for (uint32_t index = 0; index < sizeofDataOperation; index++) {
00372                 if ((buffer)[index] != PATTERN_FOR_PROGRAM_DATA) {
00373                     tr_info("%s:%u: %" PRIu32 ": expected 0x%02x, found 0x%02x", __FUNCTION__, __LINE__, index, PATTERN_FOR_PROGRAM_DATA, buffer[index]);
00374                 }
00375                 TEST_ASSERT_EQUAL(PATTERN_FOR_PROGRAM_DATA, buffer[index]);
00376             }
00377             break;
00378 
00379         default:
00380             TEST_ASSERT(false);
00381     }
00382 
00383     return CaseNext;
00384 }
00385 
00386 template <uint64_t OFFSET>
00387 control_t test_againstSingleCStorageAtOffset(const size_t call_count)
00388 {
00389     tr_info("test_againstSingleCStorageAtOffset: called with call_count %lu", call_count);
00390     static StorageVolumeManager volumeManager;
00391     static _ARM_DRIVER_STORAGE mtd = {};
00392     static ARM_STORAGE_INFO info;
00393     static size_t sizeofDataOperation;
00394 
00395     const uint8_t PATTERN_FOR_PROGRAM_DATA = 0xAA;
00396 
00397     static enum {
00398         VOLUME_MANAGER_INITIALIZE = 1,
00399         BASIC_SYNCHRONOUS_API_TESTING,
00400         READ_DATA,
00401         ERASE,
00402         READ_AFTER_ERASE,
00403         PROGRAM_DATA,
00404         READ_AFTER_PROGRAM_DATA,
00405         VERIFY_PROGRAM_DATA,
00406         DISCONNECT_VOLUME_MANAGER_CALLBACK,
00407         READ_FROM_DRV_AFTER_PROGRAM_DATA,
00408         VERIFY_PROGRAM_DATA2,
00409     } state = VOLUME_MANAGER_INITIALIZE;
00410     tr_info("came in with state %u", state);
00411 
00412     int32_t rc;
00413     rc = drv->GetNextBlock(NULL, NULL);
00414     TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00415     ARM_STORAGE_BLOCK firstBlock;
00416     rc = drv->GetNextBlock(NULL, &firstBlock);
00417     TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00418     TEST_ASSERT(ARM_STORAGE_VALID_BLOCK(&firstBlock));
00419 
00420     switch (state) {
00421         case VOLUME_MANAGER_INITIALIZE:
00422             rc = volumeManager.initialize(drv, initializeCallbackHandler);
00423             TEST_ASSERT(rc >= ARM_DRIVER_OK);
00424             if (rc == ARM_DRIVER_OK) {
00425                 TEST_ASSERT_EQUAL(1,  drv->GetCapabilities().asynchronous_ops);
00426                 state = BASIC_SYNCHRONOUS_API_TESTING;
00427                 return CaseTimeout(200) + CaseRepeatAll;
00428             }
00429 
00430             /* synchronous completion */
00431             TEST_ASSERT(rc == 1);
00432 
00433             /* intentional fall-through */
00434 
00435         case BASIC_SYNCHRONOUS_API_TESTING:
00436             TEST_ASSERT_EQUAL(true, volumeManager.isInitialized());
00437 
00438             rc = drv->GetInfo(&info);
00439             TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00440             TEST_ASSERT(info.total_storage > 0);
00441 
00442             { /* add volume */
00443                 rc = volumeManager.addVolume_C(firstBlock.addr + OFFSET /*addr*/, info.total_storage - OFFSET /*size*/ , &mtd);
00444                 TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00445 
00446                 TEST_ASSERT_EQUAL(true, volumeManager.volumeAtIndex(0)->isAllocated());
00447                 for (size_t index = 1; index < MAX_VOLUMES; index++) {
00448                     TEST_ASSERT_EQUAL(false, volumeManager.volumeAtIndex(index)->isAllocated());
00449                 }
00450             }
00451 
00452             { /* GetVersion */
00453                 TEST_ASSERT_EQUAL(drv->GetVersion().api, mtd.GetVersion().api);
00454                 TEST_ASSERT_EQUAL(drv->GetVersion().drv, mtd.GetVersion().drv);
00455             }
00456 
00457             { /* GetCapabilities */
00458                 TEST_ASSERT_EQUAL(drv->GetCapabilities().asynchronous_ops, mtd.GetCapabilities().asynchronous_ops);
00459                 TEST_ASSERT_EQUAL(drv->GetCapabilities().erase_all,        mtd.GetCapabilities().erase_all);
00460             }
00461 
00462             { /* Initialize */
00463                 rc = mtd.Initialize(virtualMTDCallbackHandler);
00464                 TEST_ASSERT_EQUAL(1, rc);
00465             }
00466 
00467             { /* GetStatus */
00468                 ARM_STORAGE_STATUS status = mtd.GetStatus();
00469                 TEST_ASSERT_EQUAL(0, status.busy);
00470                 TEST_ASSERT_EQUAL(0, status.error);
00471             }
00472 
00473             { /* GetInfo */
00474                 ARM_STORAGE_INFO volumeInfo;
00475                 rc = mtd.GetInfo(&volumeInfo);
00476                 TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00477 
00478                 TEST_ASSERT_EQUAL(info.total_storage - OFFSET, volumeInfo.total_storage);
00479                 TEST_ASSERT_EQUAL(info.program_unit,           volumeInfo.program_unit);
00480                 TEST_ASSERT_EQUAL(info.optimal_program_unit,   volumeInfo.optimal_program_unit);
00481                 TEST_ASSERT_EQUAL(info.program_cycles,         volumeInfo.program_cycles);
00482                 TEST_ASSERT_EQUAL(info.erased_value,           volumeInfo.erased_value);
00483                 TEST_ASSERT_EQUAL(info.memory_mapped,          volumeInfo.memory_mapped);
00484                 TEST_ASSERT_EQUAL(info.programmability,        volumeInfo.programmability);
00485                 TEST_ASSERT_EQUAL(info.retention_level,        volumeInfo.retention_level);
00486                 TEST_ASSERT_EQUAL(info.reserved,               volumeInfo.reserved);
00487                 TEST_ASSERT_EQUAL(0, memcmp(&info.security, &volumeInfo.security, sizeof(ARM_STORAGE_SECURITY_FEATURES)));
00488             }
00489 
00490             { /* resolve address */
00491                 TEST_ASSERT_EQUAL(firstBlock.addr + OFFSET, mtd.ResolveAddress(0));
00492                 TEST_ASSERT_EQUAL(firstBlock.addr + OFFSET + info.total_storage, mtd.ResolveAddress(info.total_storage));
00493                 TEST_ASSERT_EQUAL(firstBlock.addr + OFFSET + info.total_storage / 2, mtd.ResolveAddress(info.total_storage / 2));
00494             }
00495 
00496             { /* GetNextBlock */
00497                 rc = mtd.GetNextBlock(NULL, NULL);
00498                 TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00499                 ARM_STORAGE_BLOCK block;
00500                 rc = mtd.GetNextBlock(NULL, &block);
00501                 TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00502                 TEST_ASSERT_EQUAL(0, block.addr);
00503                 TEST_ASSERT_EQUAL(info.total_storage - OFFSET, block.size);
00504 
00505                 rc = mtd.GetNextBlock(&block, NULL);
00506                 TEST_ASSERT(rc < ARM_DRIVER_OK);
00507                 rc = mtd.GetNextBlock(&block, &block);
00508                 TEST_ASSERT(rc < ARM_DRIVER_OK);
00509             }
00510 
00511             { /* GetBlock */
00512                 rc = mtd.GetBlock(0, NULL);
00513                 TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00514                 ARM_STORAGE_BLOCK block;
00515                 rc = mtd.GetBlock(0, &block);
00516                 TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00517                 TEST_ASSERT_EQUAL(0, block.addr);
00518                 TEST_ASSERT_EQUAL(info.total_storage - OFFSET, block.size);
00519 
00520                 rc = mtd.GetBlock((info.total_storage / 2), NULL);
00521                 TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00522                 rc = mtd.GetBlock((info.total_storage / 2), &block);
00523                 TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00524                 TEST_ASSERT_EQUAL(0, block.addr);
00525                 TEST_ASSERT_EQUAL(info.total_storage - OFFSET, block.size);
00526 
00527                 rc = mtd.GetBlock(info.total_storage, NULL);
00528                 TEST_ASSERT(rc < ARM_DRIVER_OK);
00529                 rc = mtd.GetBlock(info.total_storage, &block);
00530                 TEST_ASSERT(rc < ARM_DRIVER_OK);
00531             }
00532 
00533             state = READ_DATA;
00534             /* intentional fallthrough */
00535 
00536         case READ_DATA:
00537             sizeofDataOperation = ((info.total_storage - OFFSET) > BUFFER_SIZE) ? BUFFER_SIZE : (info.total_storage - OFFSET);
00538             TEST_ASSERT(sizeofDataOperation <= BUFFER_SIZE);
00539 
00540             /* ReadData */
00541             rc = mtd.ReadData(0, buffer, sizeofDataOperation);
00542             TEST_ASSERT(rc >= ARM_DRIVER_OK);
00543             if (rc == ARM_DRIVER_OK) {
00544                 TEST_ASSERT_EQUAL(1, mtd.GetCapabilities().asynchronous_ops);
00545                 state = ERASE;
00546                 return CaseTimeout(200) + CaseRepeatAll;
00547             }
00548 
00549             virtualVolumeCallbackStatus = rc;
00550             /* intentional fallthrough */
00551 
00552         case ERASE:
00553             TEST_ASSERT_EQUAL(sizeofDataOperation, virtualVolumeCallbackStatus);
00554 
00555             /* Erase */
00556             rc = mtd.Erase(0, sizeofDataOperation);
00557             TEST_ASSERT(rc >= ARM_DRIVER_OK);
00558             if (rc == ARM_DRIVER_OK) {
00559                 TEST_ASSERT_EQUAL(1, mtd.GetCapabilities().asynchronous_ops);
00560                 state = READ_AFTER_ERASE;
00561                 return CaseTimeout(200) + CaseRepeatAll;
00562             }
00563 
00564             virtualVolumeCallbackStatus = rc;
00565             /* intentional fallthrough */
00566 
00567         case READ_AFTER_ERASE:
00568             TEST_ASSERT_EQUAL(sizeofDataOperation, virtualVolumeCallbackStatus);
00569 
00570             /* Read after Erase */
00571             rc = mtd.ReadData(0, buffer, sizeofDataOperation);
00572             TEST_ASSERT(rc >= ARM_DRIVER_OK);
00573             if (rc == ARM_DRIVER_OK) {
00574                 TEST_ASSERT_EQUAL(1, mtd.GetCapabilities().asynchronous_ops);
00575                 state = PROGRAM_DATA;
00576                 return CaseTimeout(200) + CaseRepeatAll;
00577             }
00578 
00579             virtualVolumeCallbackStatus = rc;
00580             /* intentional fallthrough */
00581 
00582         case PROGRAM_DATA:
00583             TEST_ASSERT_EQUAL(sizeofDataOperation, virtualVolumeCallbackStatus);
00584             for (size_t index = 0; index < sizeofDataOperation; index++) {
00585                 // if (bytePattern != (buffer)[index]) {
00586                 //     tr_info("%u: expected %x, found %x", index, bytePattern, buffer[index]);
00587                 // }
00588                 TEST_ASSERT_EQUAL(info.erased_value ? (uint8_t)0xFF : (uint8_t)0, buffer[index]);
00589             }
00590 
00591             /* ProgramData */
00592             memset(buffer, PATTERN_FOR_PROGRAM_DATA, sizeofDataOperation);
00593             rc = mtd.ProgramData(0, buffer, sizeofDataOperation);
00594             TEST_ASSERT(rc >= ARM_DRIVER_OK);
00595             if (rc == ARM_DRIVER_OK) {
00596                 TEST_ASSERT_EQUAL(1, mtd.GetCapabilities().asynchronous_ops);
00597                 state = READ_AFTER_PROGRAM_DATA;
00598                 return CaseTimeout(200) + CaseRepeatAll;
00599             }
00600 
00601             virtualVolumeCallbackStatus = rc;
00602             /* intentional fallthrough */
00603 
00604         case READ_AFTER_PROGRAM_DATA:
00605             TEST_ASSERT_EQUAL(sizeofDataOperation, virtualVolumeCallbackStatus);
00606 
00607             /* Read after Program */
00608             rc = mtd.ReadData(0, buffer, sizeofDataOperation);
00609             TEST_ASSERT(rc >= ARM_DRIVER_OK);
00610             if (rc == ARM_DRIVER_OK) {
00611                 TEST_ASSERT_EQUAL(1, mtd.GetCapabilities().asynchronous_ops);
00612                 state = VERIFY_PROGRAM_DATA;
00613                 return CaseTimeout(200) + CaseRepeatAll;
00614             }
00615 
00616             virtualVolumeCallbackStatus = rc;
00617             /* intentional fallthrough */
00618 
00619         case VERIFY_PROGRAM_DATA:
00620             TEST_ASSERT_EQUAL(sizeofDataOperation, virtualVolumeCallbackStatus);
00621             for (uint32_t index = 0; index < sizeofDataOperation; index++) {
00622                 if ((buffer)[index] != PATTERN_FOR_PROGRAM_DATA) {
00623                     tr_info("%s:%u: %" PRIu32 ": expected 0x%02x, found 0x%02x", __FUNCTION__, __LINE__, index, PATTERN_FOR_PROGRAM_DATA, buffer[index]);
00624                 }
00625                 TEST_ASSERT_EQUAL(PATTERN_FOR_PROGRAM_DATA, buffer[index]);
00626             }
00627             /* intentional fallthrough */
00628 
00629         case DISCONNECT_VOLUME_MANAGER_CALLBACK:
00630             rc = drv->Initialize(mtdCallbackHandler);
00631             TEST_ASSERT_EQUAL(1, rc); /* expect synchronous completion */
00632             /* intentional fallthrough */
00633 
00634         case READ_FROM_DRV_AFTER_PROGRAM_DATA:
00635             /* Read after Program */
00636             rc = drv->ReadData(firstBlock.addr + OFFSET, buffer, sizeofDataOperation);
00637             TEST_ASSERT(rc >= ARM_DRIVER_OK);
00638             if (rc == ARM_DRIVER_OK) {
00639                 TEST_ASSERT_EQUAL(1, mtd.GetCapabilities().asynchronous_ops);
00640                 state = VERIFY_PROGRAM_DATA2;
00641                 return CaseTimeout(200) + CaseRepeatAll;
00642             }
00643 
00644             callbackStatus = rc;
00645             /* intentional fallthrough */
00646 
00647         case VERIFY_PROGRAM_DATA2:
00648             TEST_ASSERT_EQUAL(sizeofDataOperation, callbackStatus);
00649             for (uint32_t index = 0; index < sizeofDataOperation; index++) {
00650                 if ((buffer)[index] != PATTERN_FOR_PROGRAM_DATA) {
00651                     tr_info("%s:%u: %" PRIu32 ": expected 0x%02x, found 0x%02x", __FUNCTION__, __LINE__, index, PATTERN_FOR_PROGRAM_DATA, buffer[index]);
00652                 }
00653                 TEST_ASSERT_EQUAL(PATTERN_FOR_PROGRAM_DATA, buffer[index]);
00654             }
00655             break;
00656 
00657         default:
00658             TEST_ASSERT(false);
00659     }
00660 
00661     return CaseNext;
00662 }
00663 
00664 template <uint64_t OFFSET1, uint64_t SIZE1, uint64_t OFFSET2, uint64_t SIZE2>
00665 control_t test_concurrentAccessFromTwoVolumes(const size_t call_count)
00666 {
00667     tr_info("test_concurrentAccessFromTwoVolumes: called with call_count %lu", call_count);
00668 
00669     if (MAX_VOLUMES <= 1) {
00670         return CaseNext;
00671     }
00672 
00673     static StorageVolumeManager volumeManager;
00674     static StorageVolume *volume1P = NULL;
00675     static StorageVolume *volume2P = NULL;
00676     static ARM_STORAGE_INFO info;
00677     static size_t sizeofDataOperation;
00678 
00679     const uint8_t PATTERN_FOR_PROGRAM_DATA = 0xAA;
00680 
00681     static enum {
00682         VOLUME_MANAGER_INITIALIZE = 1,
00683         ADD_VOLUMES,
00684         ERASE1,
00685         PROGRAM_DATA1,
00686         ERASE2,
00687         PROGRAM_DATA2,
00688         DISCONNECT_VOLUME_MANAGER_CALLBACK,
00689         READ_FROM_DRV_AFTER_PROGRAM_DATA1,
00690         VERIFY_PROGRAM_DATA1,
00691         READ_FROM_DRV_AFTER_PROGRAM_DATA2,
00692         VERIFY_PROGRAM_DATA2,
00693     } state = VOLUME_MANAGER_INITIALIZE;
00694     tr_info("came in with state %u", state);
00695 
00696     int32_t rc;
00697     switch (state) {
00698         case VOLUME_MANAGER_INITIALIZE:
00699             rc = volumeManager.initialize(drv, initializeCallbackHandler);
00700             TEST_ASSERT(rc >= ARM_DRIVER_OK);
00701             if (rc == ARM_DRIVER_OK) {
00702                 TEST_ASSERT_EQUAL(1,  drv->GetCapabilities().asynchronous_ops);
00703                 state = ADD_VOLUMES;
00704                 return CaseTimeout(200) + CaseRepeatAll;
00705             }
00706 
00707             /* synchronous completion */
00708             TEST_ASSERT(rc == 1);
00709 
00710             /* intentional fall-through */
00711 
00712         case ADD_VOLUMES:
00713             TEST_ASSERT_EQUAL(true, volumeManager.isInitialized());
00714 
00715             rc = drv->GetInfo(&info);
00716             TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00717             TEST_ASSERT(info.total_storage > 0);
00718 
00719             { /* add volume1 */
00720                 rc = drv->GetBlock(OFFSET1, NULL);
00721                 TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00722                 ARM_STORAGE_BLOCK block1;
00723                 rc = drv->GetBlock(OFFSET1, &block1);
00724                 TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00725                 rc = drv->GetBlock(OFFSET1 + SIZE1 - 1, NULL);
00726                 TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00727                 rc = drv->GetBlock(OFFSET1 + SIZE1 - 1, &block1);
00728                 TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00729 
00730                 rc = volumeManager.addVolume(OFFSET1 /*addr*/, SIZE1 /*size*/ , &volume1P);
00731                 TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00732 
00733                 TEST_ASSERT_EQUAL(true, volumeManager.volumeAtIndex(0)->isAllocated());
00734                 for (size_t index = 1; index < MAX_VOLUMES; index++) {
00735                     TEST_ASSERT_EQUAL(false, volumeManager.volumeAtIndex(index)->isAllocated());
00736                 }
00737 
00738                 { /* Initialize */
00739                     rc = volume1P->Initialize(virtualMTDCallbackHandler);
00740                     TEST_ASSERT_EQUAL(1, rc);
00741                 }
00742             }
00743             { /* add volume2 */
00744                 rc = drv->GetBlock(OFFSET2, NULL);
00745                 TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00746                 ARM_STORAGE_BLOCK block2;
00747                 rc = drv->GetBlock(OFFSET2, &block2);
00748                 TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00749                 rc = drv->GetBlock(OFFSET2 + SIZE2 - 2, NULL);
00750                 TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00751                 rc = drv->GetBlock(OFFSET2 + SIZE2 - 2, &block2);
00752                 TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00753 
00754                 rc = volumeManager.addVolume(OFFSET2 /*addr*/, SIZE2 /*size*/ , &volume2P);
00755                 TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00756 
00757                 TEST_ASSERT_EQUAL(true, volumeManager.volumeAtIndex(1)->isAllocated());
00758                 for (size_t index = 2; index < MAX_VOLUMES; index++) {
00759                     TEST_ASSERT_EQUAL(false, volumeManager.volumeAtIndex(index)->isAllocated());
00760                 }
00761 
00762                 { /* Initialize */
00763                     rc = volume2P->Initialize(virtualMTDCallbackHandler);
00764                     TEST_ASSERT_EQUAL(1, rc);
00765                 }
00766             }
00767 
00768             sizeofDataOperation = (SIZE1 > BUFFER_SIZE) ? BUFFER_SIZE : SIZE1;
00769             sizeofDataOperation = (SIZE2 > sizeofDataOperation) ? sizeofDataOperation : SIZE2;
00770             TEST_ASSERT((sizeofDataOperation > 0) && (sizeofDataOperation <= BUFFER_SIZE));
00771             memset(buffer, PATTERN_FOR_PROGRAM_DATA, sizeofDataOperation);
00772 
00773             /* intentional fall-through */
00774 
00775         case ERASE1:
00776             rc = volume1P->Erase(0, sizeofDataOperation);
00777             TEST_ASSERT(rc >= ARM_DRIVER_OK);
00778             if (rc == ARM_DRIVER_OK) {
00779                 TEST_ASSERT_EQUAL(1, volume1P->GetCapabilities().asynchronous_ops);
00780                 state = PROGRAM_DATA1;
00781                 return CaseTimeout(200) + CaseRepeatAll;
00782             }
00783 
00784             virtualVolumeCallbackStatus = rc;
00785             /* intentional fallthrough */
00786 
00787         case PROGRAM_DATA1:
00788             TEST_ASSERT_EQUAL(sizeofDataOperation, virtualVolumeCallbackStatus);
00789 
00790             tr_info("PROGRAM_DATA1");
00791             rc = volume1P->ProgramData(0, buffer, sizeofDataOperation);
00792             TEST_ASSERT(rc >= ARM_DRIVER_OK);
00793             if (rc == ARM_DRIVER_OK) {
00794                 TEST_ASSERT_EQUAL(1, volume1P->GetCapabilities().asynchronous_ops);
00795 
00796                 ARM_STORAGE_STATUS status;
00797                 status = drv->GetStatus();
00798                 TEST_ASSERT_EQUAL(1, status.busy);
00799                 TEST_ASSERT_EQUAL(0, status.error);
00800                 status = volume1P->GetStatus();
00801                 TEST_ASSERT_EQUAL(1, status.busy);
00802                 TEST_ASSERT_EQUAL(0, status.error);
00803                 status = volume2P->GetStatus();
00804                 TEST_ASSERT_EQUAL(1, status.busy);
00805                 TEST_ASSERT_EQUAL(0, status.error);
00806 
00807                 rc = volume2P->ProgramData(0, buffer, sizeofDataOperation);
00808                 TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_BUSY, rc);
00809                 rc = volume1P->ProgramData(0, buffer, sizeofDataOperation);
00810                 TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_BUSY, rc);
00811                 rc = volume1P->ReadData(0, buffer, sizeofDataOperation);
00812                 TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_BUSY, rc);
00813                 rc = volume1P->Erase(0, sizeofDataOperation);
00814                 TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_BUSY, rc);
00815 
00816                 state = ERASE2;
00817                 return CaseTimeout(200) + CaseRepeatAll;
00818             }
00819 
00820             virtualVolumeCallbackStatus = rc;
00821             /* intentional fallthrough */
00822 
00823         case ERASE2:
00824             TEST_ASSERT_EQUAL(sizeofDataOperation, virtualVolumeCallbackStatus);
00825 
00826             rc = volume2P->Erase(0, sizeofDataOperation);
00827             TEST_ASSERT(rc >= ARM_DRIVER_OK);
00828             if (rc == ARM_DRIVER_OK) {
00829                 TEST_ASSERT_EQUAL(1, volume2P->GetCapabilities().asynchronous_ops);
00830                 state = PROGRAM_DATA2;
00831                 return CaseTimeout(200) + CaseRepeatAll;
00832             }
00833 
00834             virtualVolumeCallbackStatus = rc;
00835             /* intentional fallthrough */
00836 
00837         case PROGRAM_DATA2:
00838             TEST_ASSERT_EQUAL(sizeofDataOperation, virtualVolumeCallbackStatus);
00839 
00840             tr_info("PROGRAM_DATA2");
00841             rc = volume2P->ProgramData(0, buffer, sizeofDataOperation);
00842             TEST_ASSERT(rc >= ARM_DRIVER_OK);
00843             if (rc == ARM_DRIVER_OK) {
00844                 TEST_ASSERT_EQUAL(1, volume2P->GetCapabilities().asynchronous_ops);
00845 
00846                 ARM_STORAGE_STATUS status;
00847                 status = drv->GetStatus();
00848                 TEST_ASSERT_EQUAL(1, status.busy);
00849                 TEST_ASSERT_EQUAL(0, status.error);
00850                 status = volume2P->GetStatus();
00851                 TEST_ASSERT_EQUAL(1, status.busy);
00852                 TEST_ASSERT_EQUAL(0, status.error);
00853                 status = volume1P->GetStatus();
00854                 TEST_ASSERT_EQUAL(1, status.busy);
00855                 TEST_ASSERT_EQUAL(0, status.error);
00856 
00857                 rc = volume1P->ProgramData(0, buffer, sizeofDataOperation);
00858                 TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_BUSY, rc);
00859                 rc = volume2P->ProgramData(0, buffer, sizeofDataOperation);
00860                 TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_BUSY, rc);
00861                 rc = volume2P->ReadData(0, buffer, sizeofDataOperation);
00862                 TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_BUSY, rc);
00863                 rc = volume2P->Erase(0, sizeofDataOperation);
00864                 TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_BUSY, rc);
00865 
00866                 state = DISCONNECT_VOLUME_MANAGER_CALLBACK;
00867                 return CaseTimeout(200) + CaseRepeatAll;
00868             }
00869 
00870             virtualVolumeCallbackStatus = rc;
00871             /* intentional fallthrough */
00872 
00873         case DISCONNECT_VOLUME_MANAGER_CALLBACK:
00874             tr_info("DISCONNECT_VOLUME_MANAGER_CALLBACK");
00875             rc = drv->Initialize(mtdCallbackHandler);
00876             TEST_ASSERT_EQUAL(1, rc); /* expect synchronous completion */
00877             /* intentional fallthrough */
00878 
00879         case READ_FROM_DRV_AFTER_PROGRAM_DATA1:
00880             tr_info("verifying state");
00881             /* Read after Program */
00882             rc = drv->ReadData(OFFSET1, buffer, sizeofDataOperation);
00883             TEST_ASSERT(rc >= ARM_DRIVER_OK);
00884             if (rc == ARM_DRIVER_OK) {
00885                 TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00886                 state = VERIFY_PROGRAM_DATA1;
00887                 return CaseTimeout(200) + CaseRepeatAll;
00888             }
00889 
00890             virtualVolumeCallbackStatus = rc;
00891             /* intentional fallthrough */
00892 
00893         case VERIFY_PROGRAM_DATA1:
00894             TEST_ASSERT_EQUAL(sizeofDataOperation, virtualVolumeCallbackStatus);
00895 
00896             for (uint32_t index = 0; index < sizeofDataOperation; index++) {
00897                 if ((buffer)[index] != PATTERN_FOR_PROGRAM_DATA) {
00898                     tr_info("%s:%u: %" PRIu32 ": expected 0x%02x, found 0x%02x", __FUNCTION__, __LINE__, index, PATTERN_FOR_PROGRAM_DATA, buffer[index]);
00899                 }
00900                 TEST_ASSERT_EQUAL(PATTERN_FOR_PROGRAM_DATA, buffer[index]);
00901             }
00902             /* intentional fallthrough */
00903 
00904         case READ_FROM_DRV_AFTER_PROGRAM_DATA2:
00905             /* Read after Program */
00906             rc = drv->ReadData(OFFSET2, buffer, sizeofDataOperation);
00907             TEST_ASSERT(rc >= ARM_DRIVER_OK);
00908             if (rc == ARM_DRIVER_OK) {
00909                 TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00910                 state = VERIFY_PROGRAM_DATA2;
00911                 return CaseTimeout(200) + CaseRepeatAll;
00912             }
00913 
00914             virtualVolumeCallbackStatus = rc;
00915             /* intentional fallthrough */
00916 
00917         case VERIFY_PROGRAM_DATA2:
00918             TEST_ASSERT_EQUAL(sizeofDataOperation, virtualVolumeCallbackStatus);
00919 
00920             for (uint32_t index = 0; index < sizeofDataOperation; index++) {
00921                 if ((buffer)[index] != PATTERN_FOR_PROGRAM_DATA) {
00922                     tr_info("%s:%u: %" PRIu32 ": expected 0x%02x, found 0x%02x", __FUNCTION__, __LINE__, index, PATTERN_FOR_PROGRAM_DATA, buffer[index]);
00923                 }
00924                 TEST_ASSERT_EQUAL(PATTERN_FOR_PROGRAM_DATA, buffer[index]);
00925             }
00926             break;
00927 
00928         default:
00929             TEST_ASSERT(false);
00930     }
00931 
00932     return CaseNext;
00933 }
00934 
00935 template <uint64_t OFFSET1, uint64_t SIZE1, uint64_t OFFSET2, uint64_t SIZE2>
00936 control_t test_concurrentAccessFromTwoCStorageDevices(const size_t call_count)
00937 {
00938     tr_info("test_concurrentAccessFromTwoCStorageDevices: called with call_count %lu", call_count);
00939 
00940     if (MAX_VOLUMES <= 1) {
00941         return CaseNext;
00942     }
00943 
00944     static StorageVolumeManager volumeManager;
00945     static _ARM_DRIVER_STORAGE mtd1 = {};
00946     static _ARM_DRIVER_STORAGE mtd2 = {};
00947     static ARM_STORAGE_INFO info;
00948     static size_t sizeofDataOperation;
00949 
00950     const uint8_t PATTERN_FOR_PROGRAM_DATA = 0xAA;
00951 
00952     static enum {
00953         VOLUME_MANAGER_INITIALIZE = 1,
00954         ADD_VOLUMES,
00955         ERASE1,
00956         PROGRAM_DATA1,
00957         ERASE2,
00958         PROGRAM_DATA2,
00959         DISCONNECT_VOLUME_MANAGER_CALLBACK,
00960         READ_FROM_DRV_AFTER_PROGRAM_DATA1,
00961         VERIFY_PROGRAM_DATA1,
00962         READ_FROM_DRV_AFTER_PROGRAM_DATA2,
00963         VERIFY_PROGRAM_DATA2,
00964     } state = VOLUME_MANAGER_INITIALIZE;
00965     tr_info("came in with state %u", state);
00966 
00967     int32_t rc;
00968     switch (state) {
00969         case VOLUME_MANAGER_INITIALIZE:
00970             rc = volumeManager.initialize(drv, initializeCallbackHandler);
00971             TEST_ASSERT(rc >= ARM_DRIVER_OK);
00972             if (rc == ARM_DRIVER_OK) {
00973                 TEST_ASSERT_EQUAL(1,  drv->GetCapabilities().asynchronous_ops);
00974                 state = ADD_VOLUMES;
00975                 return CaseTimeout(200) + CaseRepeatAll;
00976             }
00977 
00978             /* synchronous completion */
00979             TEST_ASSERT(rc == 1);
00980 
00981             /* intentional fall-through */
00982 
00983         case ADD_VOLUMES:
00984             TEST_ASSERT_EQUAL(true, volumeManager.isInitialized());
00985 
00986             rc = drv->GetInfo(&info);
00987             TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00988             TEST_ASSERT(info.total_storage > 0);
00989 
00990             { /* add C_Storage device 1 */
00991                 ARM_STORAGE_BLOCK block1;
00992                 rc = drv->GetBlock(OFFSET1, &block1);
00993                 TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00994                 rc = drv->GetBlock(OFFSET1 + SIZE1 - 1, &block1);
00995                 TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00996 
00997                 rc = volumeManager.addVolume_C(OFFSET1 /*addr*/, SIZE1 /*size*/ , &mtd1);
00998                 TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00999 
01000                 TEST_ASSERT_EQUAL(true, volumeManager.volumeAtIndex(0)->isAllocated());
01001                 for (size_t index = 1; index < MAX_VOLUMES; index++) {
01002                     TEST_ASSERT_EQUAL(false, volumeManager.volumeAtIndex(index)->isAllocated());
01003                 }
01004 
01005                 { /* Initialize */
01006                     rc = mtd1.Initialize(virtualMTDCallbackHandler);
01007                     TEST_ASSERT_EQUAL(1, rc);
01008                 }
01009             }
01010             { /* add C_Storage device 2 */
01011                 ARM_STORAGE_BLOCK block2;
01012                 rc = drv->GetBlock(OFFSET2, &block2);
01013                 TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
01014                 rc = drv->GetBlock(OFFSET2 + SIZE2 - 2, &block2);
01015                 TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
01016 
01017                 rc = volumeManager.addVolume_C(OFFSET2 /*addr*/, SIZE2 /*size*/ , &mtd2);
01018                 TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
01019 
01020                 TEST_ASSERT_EQUAL(true, volumeManager.volumeAtIndex(1)->isAllocated());
01021                 for (size_t index = 2; index < MAX_VOLUMES; index++) {
01022                     TEST_ASSERT_EQUAL(false, volumeManager.volumeAtIndex(index)->isAllocated());
01023                 }
01024 
01025                 { /* Initialize */
01026                     rc = mtd2.Initialize(virtualMTDCallbackHandler);
01027                     TEST_ASSERT_EQUAL(1, rc);
01028                 }
01029             }
01030 
01031             sizeofDataOperation = (SIZE1 > BUFFER_SIZE) ? BUFFER_SIZE : SIZE1;
01032             sizeofDataOperation = (SIZE2 > sizeofDataOperation) ? sizeofDataOperation : SIZE2;
01033             TEST_ASSERT((sizeofDataOperation > 0) && (sizeofDataOperation <= BUFFER_SIZE));
01034             memset(buffer, PATTERN_FOR_PROGRAM_DATA, sizeofDataOperation);
01035 
01036             /* intentional fall-through */
01037 
01038         case ERASE1:
01039             rc = mtd1.Erase(0, sizeofDataOperation);
01040             TEST_ASSERT(rc >= ARM_DRIVER_OK);
01041             if (rc == ARM_DRIVER_OK) {
01042                 TEST_ASSERT_EQUAL(1, mtd1.GetCapabilities().asynchronous_ops);
01043                 state = PROGRAM_DATA1;
01044                 return CaseTimeout(200) + CaseRepeatAll;
01045             }
01046 
01047             virtualVolumeCallbackStatus = rc;
01048             /* intentional fallthrough */
01049 
01050         case PROGRAM_DATA1:
01051             TEST_ASSERT_EQUAL(sizeofDataOperation, virtualVolumeCallbackStatus);
01052 
01053             tr_info("PROGRAM_DATA1");
01054             rc = mtd1.ProgramData(0, buffer, sizeofDataOperation);
01055             TEST_ASSERT(rc >= ARM_DRIVER_OK);
01056             if (rc == ARM_DRIVER_OK) {
01057                 TEST_ASSERT_EQUAL(1, mtd1.GetCapabilities().asynchronous_ops);
01058 
01059                 ARM_STORAGE_STATUS status;
01060                 status = drv->GetStatus();
01061                 TEST_ASSERT_EQUAL(1, status.busy);
01062                 TEST_ASSERT_EQUAL(0, status.error);
01063                 status = mtd1.GetStatus();
01064                 TEST_ASSERT_EQUAL(1, status.busy);
01065                 TEST_ASSERT_EQUAL(0, status.error);
01066                 status = mtd2.GetStatus();
01067                 TEST_ASSERT_EQUAL(1, status.busy);
01068                 TEST_ASSERT_EQUAL(0, status.error);
01069 
01070                 rc = mtd2.ProgramData(0, buffer, sizeofDataOperation);
01071                 TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_BUSY, rc);
01072                 rc = mtd1.ProgramData(0, buffer, sizeofDataOperation);
01073                 TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_BUSY, rc);
01074                 rc = mtd1.ReadData(0, buffer, sizeofDataOperation);
01075                 TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_BUSY, rc);
01076                 rc = mtd1.Erase(0, sizeofDataOperation);
01077                 TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_BUSY, rc);
01078 
01079                 state = ERASE2;
01080                 return CaseTimeout(200) + CaseRepeatAll;
01081             }
01082 
01083             virtualVolumeCallbackStatus = rc;
01084             /* intentional fallthrough */
01085 
01086         case ERASE2:
01087             TEST_ASSERT_EQUAL(sizeofDataOperation, virtualVolumeCallbackStatus);
01088 
01089             rc = mtd2.Erase(0, sizeofDataOperation);
01090             TEST_ASSERT(rc >= ARM_DRIVER_OK);
01091             if (rc == ARM_DRIVER_OK) {
01092                 TEST_ASSERT_EQUAL(1, mtd2.GetCapabilities().asynchronous_ops);
01093                 state = PROGRAM_DATA2;
01094                 return CaseTimeout(200) + CaseRepeatAll;
01095             }
01096 
01097             virtualVolumeCallbackStatus = rc;
01098             /* intentional fallthrough */
01099 
01100         case PROGRAM_DATA2:
01101             TEST_ASSERT_EQUAL(sizeofDataOperation, virtualVolumeCallbackStatus);
01102 
01103             tr_info("PROGRAM_DATA2");
01104             rc = mtd2.ProgramData(0, buffer, sizeofDataOperation);
01105             TEST_ASSERT(rc >= ARM_DRIVER_OK);
01106             if (rc == ARM_DRIVER_OK) {
01107                 TEST_ASSERT_EQUAL(1, mtd2.GetCapabilities().asynchronous_ops);
01108 
01109                 ARM_STORAGE_STATUS status;
01110                 status = drv->GetStatus();
01111                 TEST_ASSERT_EQUAL(1, status.busy);
01112                 TEST_ASSERT_EQUAL(0, status.error);
01113                 status = mtd2.GetStatus();
01114                 TEST_ASSERT_EQUAL(1, status.busy);
01115                 TEST_ASSERT_EQUAL(0, status.error);
01116                 status = mtd1.GetStatus();
01117                 TEST_ASSERT_EQUAL(1, status.busy);
01118                 TEST_ASSERT_EQUAL(0, status.error);
01119 
01120                 rc = mtd1.ProgramData(0, buffer, sizeofDataOperation);
01121                 TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_BUSY, rc);
01122                 rc = mtd2.ProgramData(0, buffer, sizeofDataOperation);
01123                 TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_BUSY, rc);
01124                 rc = mtd2.ReadData(0, buffer, sizeofDataOperation);
01125                 TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_BUSY, rc);
01126                 rc = mtd2.Erase(0, sizeofDataOperation);
01127                 TEST_ASSERT_EQUAL(ARM_DRIVER_ERROR_BUSY, rc);
01128 
01129                 state = DISCONNECT_VOLUME_MANAGER_CALLBACK;
01130                 return CaseTimeout(200) + CaseRepeatAll;
01131             }
01132 
01133             virtualVolumeCallbackStatus = rc;
01134             /* intentional fallthrough */
01135 
01136         case DISCONNECT_VOLUME_MANAGER_CALLBACK:
01137             tr_info("DISCONNECT_VOLUME_MANAGER_CALLBACK");
01138             rc = drv->Initialize(mtdCallbackHandler);
01139             TEST_ASSERT_EQUAL(1, rc); /* expect synchronous completion */
01140             /* intentional fallthrough */
01141 
01142         case READ_FROM_DRV_AFTER_PROGRAM_DATA1:
01143             tr_info("verifying state");
01144             /* Read after Program */
01145             rc = drv->ReadData(OFFSET1, buffer, sizeofDataOperation);
01146             TEST_ASSERT(rc >= ARM_DRIVER_OK);
01147             if (rc == ARM_DRIVER_OK) {
01148                 TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
01149                 state = VERIFY_PROGRAM_DATA1;
01150                 return CaseTimeout(200) + CaseRepeatAll;
01151             }
01152 
01153             virtualVolumeCallbackStatus = rc;
01154             /* intentional fallthrough */
01155 
01156         case VERIFY_PROGRAM_DATA1:
01157             TEST_ASSERT_EQUAL(sizeofDataOperation, virtualVolumeCallbackStatus);
01158 
01159             for (uint32_t index = 0; index < sizeofDataOperation; index++) {
01160                 if ((buffer)[index] != PATTERN_FOR_PROGRAM_DATA) {
01161                     tr_info("%s:%u: %" PRIu32 ": expected 0x%02x, found 0x%02x", __FUNCTION__, __LINE__, index, PATTERN_FOR_PROGRAM_DATA, buffer[index]);
01162                 }
01163                 TEST_ASSERT_EQUAL(PATTERN_FOR_PROGRAM_DATA, buffer[index]);
01164             }
01165             /* intentional fallthrough */
01166 
01167         case READ_FROM_DRV_AFTER_PROGRAM_DATA2:
01168             /* Read after Program */
01169             rc = drv->ReadData(OFFSET2, buffer, sizeofDataOperation);
01170             TEST_ASSERT(rc >= ARM_DRIVER_OK);
01171             if (rc == ARM_DRIVER_OK) {
01172                 TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
01173                 state = VERIFY_PROGRAM_DATA2;
01174                 return CaseTimeout(200) + CaseRepeatAll;
01175             }
01176 
01177             virtualVolumeCallbackStatus = rc;
01178             /* intentional fallthrough */
01179 
01180         case VERIFY_PROGRAM_DATA2:
01181             TEST_ASSERT_EQUAL(sizeofDataOperation, virtualVolumeCallbackStatus);
01182 
01183             for (uint32_t index = 0; index < sizeofDataOperation; index++) {
01184                 if ((buffer)[index] != PATTERN_FOR_PROGRAM_DATA) {
01185                     tr_info("%s:%u: %" PRIu32 ": expected 0x%02x, found 0x%02x", __FUNCTION__, __LINE__, index, PATTERN_FOR_PROGRAM_DATA, buffer[index]);
01186                 }
01187                 TEST_ASSERT_EQUAL(PATTERN_FOR_PROGRAM_DATA, buffer[index]);
01188             }
01189             break;
01190 
01191         default:
01192             TEST_ASSERT(false);
01193     }
01194 
01195     return CaseNext;
01196 }
01197 
01198 // Specify all your test cases here
01199 Case cases[] = {
01200     Case("initialize",                                    test_initialize),
01201     Case("Against a single volume at offset",             test_againstSingleVolumeAtOffset<0>),
01202     Case("Against a single volume at offset",             test_againstSingleVolumeAtOffset<4096>),
01203     Case("Against a single volume at offset",             test_againstSingleVolumeAtOffset<8192>),
01204     Case("Against a single volume at offset",             test_againstSingleVolumeAtOffset<65536>),
01205     Case("Against a single C_Storage at offset",          test_againstSingleCStorageAtOffset<0>),
01206     Case("Against a single C_Storage at offset",          test_againstSingleCStorageAtOffset<4096>),
01207     Case("Against a single C_Storage at offset",          test_againstSingleCStorageAtOffset<8192>),
01208     Case("Against a single C_Storage at offset",          test_againstSingleCStorageAtOffset<65536>),
01209 
01210     /* note: the following tests are unportable in the sense that they require the underlying storage device to support certain address ranges. */
01211     Case("Concurrent accesss from two volumes",           test_concurrentAccessFromTwoVolumes<512*1024, 128*1024, (512+128)*1024, 128*1024>),
01212     Case("Concurrent accesss from two volumes",           test_concurrentAccessFromTwoVolumes<512*1024, 128*1024, (512+128)*1024, 128*1024>),
01213     Case("Concurrent accesss from two volumes",           test_concurrentAccessFromTwoVolumes<512*1024, 128*1024, (512+256)*1024, 128*1024>),
01214     Case("Concurrent accesss from two volumes",           test_concurrentAccessFromTwoVolumes<512*1024, 128*1024, (512+384)*1024, 128*1024>),
01215     Case("Concurrent accesss from two C_Storage devices", test_concurrentAccessFromTwoCStorageDevices<512*1024, 128*1024, (512+128)*1024, 128*1024>),
01216     Case("Concurrent accesss from two C_Storage devices", test_concurrentAccessFromTwoCStorageDevices<512*1024, 128*1024, (512+256)*1024, 128*1024>),
01217     Case("Concurrent accesss from two C_Storage devices", test_concurrentAccessFromTwoCStorageDevices<512*1024, 128*1024, (512+384)*1024, 128*1024>),
01218 };
01219 
01220 // Declare your test specification with a custom setup handler
01221 #ifndef AVOID_GREENTEA
01222 Specification specification(greentea_setup, cases);
01223 #else
01224 Specification specification([](const size_t) {return STATUS_CONTINUE;}, cases);
01225 #endif
01226 
01227 int main(int argc, char** argv)
01228 {
01229     mbed_trace_init();       // initialize the trace library
01230     mbed_trace_config_set(TRACE_MODE_COLOR | TRACE_ACTIVE_LEVEL_INFO | TRACE_CARRIAGE_RETURN);
01231 
01232     // Run the test specification
01233     Harness::run(specification);
01234 }