dhgdh

Dependencies:   MAX44000 PWM_Tone_Library nexpaq_mdk

Fork of LED_Demo by joey shelton

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 #if !DEVICE_STORAGE
00019     #error [NOT_SUPPORTED] Storage not supported for this target
00020 #endif
00021 
00022 #ifdef TARGET_LIKE_POSIX
00023 #define AVOID_GREENTEA
00024 #endif
00025 
00026 #ifndef AVOID_GREENTEA
00027 #include "greentea-client/test_env.h"
00028 #endif
00029 #include "utest/utest.h"
00030 #include "unity/unity.h"
00031 
00032 #include "flash-journal-strategy-sequential/flash_journal_strategy_sequential.h"
00033 #include "flash-journal-strategy-sequential/flash_journal_private.h"
00034 #include <string.h>
00035 #include <inttypes.h>
00036 
00037 using namespace utest::v1;
00038 
00039 extern ARM_DRIVER_STORAGE ARM_Driver_Storage_(0);
00040 ARM_DRIVER_STORAGE *drv = &ARM_Driver_Storage_(0);
00041 
00042 FlashJournal_t      journal;
00043 
00044 static const size_t BUFFER_SIZE = 8192;
00045 static uint8_t      buffer[BUFFER_SIZE];
00046 
00047 static const size_t SIZEOF_SMALL_WRITE = 8;
00048 static const size_t SIZEOF_LARGE_WRITE = BUFFER_SIZE;
00049 static int32_t      callbackStatus;
00050 
00051 void callbackHandler(int32_t status, FlashJournal_OpCode_t cmd_code)
00052 {
00053     callbackStatus = status;
00054 
00055     switch (cmd_code) {
00056         case FLASH_JOURNAL_OPCODE_INITIALIZE:
00057             // printf("journal_callbackHandler: callback for init with status %" PRId32 "\n", status);
00058             break;
00059 
00060         case FLASH_JOURNAL_OPCODE_READ_BLOB:
00061             // printf("journal_callbackHandler: callback for read with status %" PRId32 "\n", status);
00062             break;
00063 
00064         case FLASH_JOURNAL_OPCODE_LOG_BLOB:
00065             // printf("journal_callbackHandler: callback for log with status %" PRId32 "\n", status);
00066             break;
00067 
00068         case FLASH_JOURNAL_OPCODE_COMMIT:
00069             // printf("journal_callbackHandler: callback for commit with status %" PRId32 "\n", status);
00070             break;
00071 
00072         case FLASH_JOURNAL_OPCODE_RESET:
00073             // printf("journal_callbackHandler: callback for reset with status %" PRId32 "\n", status);
00074             break;
00075 
00076         default:
00077             // printf("journal_callbackHandler: callback for opcode %u with status %" PRId32 "\n", cmd_code, status);
00078             break;
00079     }
00080     Harness::validate_callback(); // Validate the callback
00081 }
00082 
00083 control_t test_initialize()
00084 {
00085     int32_t rc = FlashJournal_initialize(&journal, drv, &FLASH_JOURNAL_STRATEGY_SEQUENTIAL, callbackHandler);
00086     TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00087     if (rc == JOURNAL_STATUS_OK) {
00088         return CaseTimeout(200);
00089     }
00090 
00091     /* ensure that something got written into the memory of journal_t */
00092     FlashJournal_t mockJournal;
00093     memset(&mockJournal, 0, sizeof(FlashJournal_t));
00094     TEST_ASSERT_NOT_EQUAL(0, memcmp(&mockJournal, &journal, sizeof(FlashJournal_t)));
00095 
00096     FlashJournal_Info_t info;
00097     rc = FlashJournal_getInfo(&journal, &info);
00098     TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
00099     TEST_ASSERT(info.capacity > 0);
00100 
00101     return CaseNext;
00102 }
00103 
00104 control_t test_resetAndInitialize(const size_t call_count)
00105 {
00106     int32_t rc;
00107     FlashJournal_Info_t info;
00108     SequentialFlashJournal_t *sequentialJournal = (SequentialFlashJournal_t *)&journal;
00109 
00110     static uint64_t previousCapacity;
00111 
00112     static enum {
00113         NEEDS_INITIAL_RESET,
00114         NEEDS_INITIALIZE_FOLLOWING_RESET,
00115         NEEDS_VERIFICATION_FOLLOWING_INITIALIZE,
00116     } state;
00117 
00118     printf("test_resetAndInitialize: entered with call_count %u\n", call_count);
00119     if (call_count == 1) {
00120         state = NEEDS_INITIAL_RESET;
00121     }
00122 
00123     switch (state) {
00124         case NEEDS_INITIAL_RESET:
00125             rc = FlashJournal_getInfo(&journal, &info);
00126             TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
00127             TEST_ASSERT(info.capacity > 0);
00128             previousCapacity = info.capacity;
00129 
00130             printf("test_resetAndInitialize: calling reset()\n");
00131             rc = FlashJournal_reset(&journal);
00132             TEST_ASSERT_NOT_EQUAL(JOURNAL_STATUS_UNSUPPORTED, rc);
00133             TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00134             state = NEEDS_INITIALIZE_FOLLOWING_RESET;
00135             if (rc == JOURNAL_STATUS_OK) {
00136                 TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00137                 return CaseTimeout(1000) + CaseRepeatAll;
00138             }
00139             TEST_ASSERT_EQUAL(1, rc); /* synchronous completion of reset() is expected to return 1 */
00140 
00141             /* fall through */
00142         case NEEDS_INITIALIZE_FOLLOWING_RESET:
00143             /* ensure that the journal has been re-initialized */
00144             TEST_ASSERT_EQUAL(0, sequentialJournal->nextSequenceNumber);
00145             TEST_ASSERT_EQUAL((uint32_t)-1, sequentialJournal->currentBlobIndex);
00146             TEST_ASSERT_EQUAL(SEQUENTIAL_JOURNAL_STATE_INITIALIZED, sequentialJournal->state);
00147 
00148             rc = FlashJournal_getInfo(&journal, &info);
00149             TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
00150             TEST_ASSERT(info.capacity > 0);
00151             TEST_ASSERT_EQUAL(previousCapacity, info.capacity);
00152             TEST_ASSERT_EQUAL(0, info.sizeofJournaledBlob);
00153 
00154             /* attempt an initialize following reset() */
00155             printf("test_resetAndInitialize: calling initialize() after reset\n");
00156             rc = FlashJournal_initialize(&journal, drv, &FLASH_JOURNAL_STRATEGY_SEQUENTIAL, callbackHandler);
00157             TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00158             state = NEEDS_VERIFICATION_FOLLOWING_INITIALIZE;
00159             if (rc == JOURNAL_STATUS_OK) {
00160                 return CaseTimeout(200);
00161             }
00162             TEST_ASSERT_EQUAL(1, rc); /* synchronous completion of initialize() is expected to return 1 */
00163 
00164             /* fall through */
00165         case NEEDS_VERIFICATION_FOLLOWING_INITIALIZE:
00166         default:
00167             printf("test_resetAndInitialize: verification\n");
00168             TEST_ASSERT_EQUAL(0, sequentialJournal->nextSequenceNumber);
00169             TEST_ASSERT_EQUAL((uint32_t)-1, sequentialJournal->currentBlobIndex);
00170             TEST_ASSERT_EQUAL(SEQUENTIAL_JOURNAL_STATE_INITIALIZED, sequentialJournal->state);
00171 
00172             rc = FlashJournal_getInfo(&journal, &info);
00173             TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
00174             TEST_ASSERT(info.capacity > 0);
00175             TEST_ASSERT_EQUAL(previousCapacity, info.capacity);
00176             TEST_ASSERT_EQUAL(0, info.sizeofJournaledBlob);
00177             break;
00178     }
00179 
00180     return CaseNext;
00181 }
00182 
00183 control_t test_commitWithoutLogs(const size_t call_count)
00184 {
00185     int32_t rc;
00186 
00187     printf("test_commitWithoutLogs: entered with call_count %u\n", call_count);
00188 
00189     switch (call_count) {
00190         case 1:
00191             /* initialize */
00192             rc = FlashJournal_initialize(&journal, drv, &FLASH_JOURNAL_STRATEGY_SEQUENTIAL, callbackHandler);
00193             TEST_ASSERT(rc >= ARM_DRIVER_OK);
00194             if (rc == ARM_DRIVER_OK) {
00195                 return CaseTimeout(200) + CaseRepeatAll;
00196             }
00197             TEST_ASSERT_EQUAL(1, rc); /* synchronous completion of initialize() is expected to return 1 */
00198             return CaseRepeatAll;
00199 
00200         case 2:
00201             rc = FlashJournal_commit(&journal);
00202             // printf("commit returned %" PRId32 "\r\n", rc);
00203             TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00204             if (rc == JOURNAL_STATUS_OK) {
00205                 TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00206                 return CaseTimeout(500) + CaseRepeatAll;
00207             }
00208 
00209             /* intentional fall through*/
00210             callbackStatus = rc;
00211 
00212         case 3:
00213             TEST_ASSERT_EQUAL(1, callbackStatus);
00214             break;
00215     }
00216 
00217     return CaseNext;
00218 }
00219 
00220 control_t test_logSmallWithoutCommit(const size_t call_count)
00221 {
00222     int32_t rc;
00223 
00224     printf("test_logSmallWithoutCommit: entered with call_count %u\n", call_count);
00225 
00226     switch (call_count) {
00227         case 1:
00228             /* initialize */
00229             rc = FlashJournal_initialize(&journal, drv, &FLASH_JOURNAL_STRATEGY_SEQUENTIAL, callbackHandler);
00230             TEST_ASSERT(rc >= ARM_DRIVER_OK);
00231             if (rc == ARM_DRIVER_OK) {
00232                 return CaseTimeout(200) + CaseRepeatAll;
00233             }
00234             TEST_ASSERT_EQUAL(1, rc); /* synchronous completion of initialize() is expected to return 1 */
00235             return CaseRepeatAll;
00236 
00237         case 2:
00238             /* log without commit */
00239             memset(buffer, 0xAA, SIZEOF_SMALL_WRITE);
00240             rc = FlashJournal_log(&journal, buffer, SIZEOF_SMALL_WRITE);
00241             TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00242             if (rc == JOURNAL_STATUS_OK) {
00243                 TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00244                 return CaseTimeout(500) + CaseRepeatAll;
00245             }
00246             /* else, fall through to synchronous verification */
00247 
00248         default:
00249             rc = FlashJournal_read(&journal, buffer, SIZEOF_SMALL_WRITE);
00250             TEST_ASSERT(rc < JOURNAL_STATUS_OK);
00251             return CaseNext;
00252     }
00253 }
00254 
00255 template <uint8_t PATTERN>
00256 control_t test_logSmallAndCommit(const size_t call_count)
00257 {
00258     int32_t rc;
00259 
00260     printf("test_logSmallAndCommit: entered with call_count %u\n", call_count);
00261 
00262     switch (call_count) {
00263         case 1:
00264             memset(buffer, PATTERN, SIZEOF_SMALL_WRITE);
00265             rc = FlashJournal_log(&journal, buffer, SIZEOF_SMALL_WRITE);
00266             TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00267             if (rc == JOURNAL_STATUS_OK) {
00268                 TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00269                 return CaseTimeout(500) + CaseRepeatAll;
00270             }
00271             /* else, fall through to synchronous verification */
00272 
00273         case 2:
00274             rc = FlashJournal_commit(&journal);
00275             TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00276             if (rc == JOURNAL_STATUS_OK) {
00277                 TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00278                 return CaseTimeout(500) + CaseRepeatAll;
00279             }
00280             /* else, fall through to synchronous verification */
00281 
00282         case 3:
00283             {
00284                 FlashJournal_Info_t info;
00285                 rc = FlashJournal_getInfo(&journal, &info);
00286                 TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
00287                 TEST_ASSERT_EQUAL(SIZEOF_SMALL_WRITE, info.sizeofJournaledBlob);
00288             }
00289 
00290             rc = FlashJournal_read(&journal, buffer, SIZEOF_SMALL_WRITE);
00291             TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00292             if (rc == JOURNAL_STATUS_OK) {
00293                 TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00294                 return CaseTimeout(500) + CaseRepeatAll;
00295             }
00296 
00297             TEST_ASSERT_EQUAL(SIZEOF_SMALL_WRITE, rc);
00298             /* intentional fall-through */
00299 
00300         default:
00301             for (unsigned i = 0; i < SIZEOF_SMALL_WRITE; i++) {
00302                 // printf("index %u value %x\n", i, buffer[i]);
00303                 TEST_ASSERT_EQUAL(PATTERN, buffer[i]);
00304             }
00305 
00306             return CaseNext;
00307     }
00308 }
00309 
00310 control_t test_initializeAfterLogSmallAndCommit(const size_t call_count)
00311 {
00312     int32_t rc;
00313 
00314     printf("test_initializeAfterLogSmallAndCommit: entered with call_count %u\n", call_count);
00315 
00316     if (call_count == 1) {
00317         rc = FlashJournal_initialize(&journal, drv, &FLASH_JOURNAL_STRATEGY_SEQUENTIAL, callbackHandler);
00318         TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00319         if (rc == JOURNAL_STATUS_OK) {
00320             printf("asynchronous_ops for init\n");
00321             return CaseTimeout(200) + CaseRepeatAll;
00322         }
00323         TEST_ASSERT_EQUAL(1, rc); /* synchronous completion of initialize() is expected to return 1 */
00324     }
00325 
00326     FlashJournal_Info_t info;
00327     rc = FlashJournal_getInfo(&journal, &info);
00328     TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
00329     TEST_ASSERT_EQUAL(SIZEOF_SMALL_WRITE, info.sizeofJournaledBlob);
00330 
00331     return CaseNext;
00332 }
00333 
00334 control_t test_logLargeWithoutCommit(const size_t call_count)
00335 {
00336     int32_t rc;
00337 
00338     printf("test_logLargeWithoutCommit: entered with call_count %u\n", call_count);
00339 
00340     switch (call_count) {
00341         case 1:
00342             rc = FlashJournal_initialize(&journal, drv, &FLASH_JOURNAL_STRATEGY_SEQUENTIAL, callbackHandler);
00343             TEST_ASSERT(rc >= ARM_DRIVER_OK);
00344             if (rc == ARM_DRIVER_OK) {
00345                 return CaseTimeout(200) + CaseRepeatAll;
00346             }
00347             TEST_ASSERT_EQUAL(1, rc); /* synchronous completion of initialize() is expected to return 1 */
00348             return CaseRepeatAll;
00349 
00350         case 2:
00351             memset(buffer, 0xAA, SIZEOF_LARGE_WRITE);
00352             rc = FlashJournal_log(&journal, buffer, SIZEOF_LARGE_WRITE);
00353             TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00354             if (rc == JOURNAL_STATUS_OK) {
00355                 TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00356                 return CaseTimeout(5000) + CaseRepeatAll;
00357             }
00358             /* intentional fall-through */
00359 
00360         case 3:
00361         default:
00362             rc = FlashJournal_read(&journal, buffer, SIZEOF_LARGE_WRITE);
00363             TEST_ASSERT(rc < JOURNAL_STATUS_OK);
00364             return CaseNext;
00365     }
00366 }
00367 
00368 template<uint8_t PATTERN>
00369 control_t test_logLargeAndCommit(const size_t call_count)
00370 {
00371     int32_t rc;
00372 
00373     printf("test_logLargeAndCommit: entered with call_count %u\n", call_count);
00374 
00375     switch (call_count) {
00376         case 1:
00377             memset(buffer, PATTERN, SIZEOF_LARGE_WRITE);
00378             rc = FlashJournal_log(&journal, buffer, SIZEOF_LARGE_WRITE);
00379             TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00380             if (rc == JOURNAL_STATUS_OK) {
00381                 TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00382                 return CaseTimeout(500) + CaseRepeatAll;
00383             }
00384             /* intentional fall-through */
00385 
00386         case 2:
00387             rc = FlashJournal_commit(&journal);
00388             TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00389             if (rc == JOURNAL_STATUS_OK) {
00390                 TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00391                 return CaseTimeout(500) + CaseRepeatAll;
00392             }
00393             /* intentional fall-through */
00394 
00395         case 3:
00396             {
00397                 FlashJournal_Info_t info;
00398                 rc = FlashJournal_getInfo(&journal, &info);
00399                 TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
00400                 TEST_ASSERT_EQUAL(SIZEOF_LARGE_WRITE, info.sizeofJournaledBlob);
00401             }
00402 
00403             rc = FlashJournal_read(&journal, buffer, SIZEOF_LARGE_WRITE);
00404             TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00405             if (rc == JOURNAL_STATUS_OK) {
00406                 TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00407                 return CaseTimeout(500) + CaseRepeatAll;
00408             }
00409 
00410             TEST_ASSERT_EQUAL(SIZEOF_LARGE_WRITE, rc);
00411             /* intentional fall-through */
00412 
00413         default:
00414             for (unsigned i = 0; i < SIZEOF_LARGE_WRITE; i++) {
00415                 // printf("index %u value %x\n", i, buffer[i]);
00416                 TEST_ASSERT_EQUAL(PATTERN, buffer[i]);
00417             }
00418 
00419             return CaseNext;
00420     }
00421 }
00422 
00423 control_t test_initializeAfterLogLargeAndCommit(const size_t call_count)
00424 {
00425     int32_t rc;
00426 
00427     printf("test_initializeAfterLogLargeAndCommit: entered with call_count %u\n", call_count);
00428 
00429     if (call_count == 1) {
00430         rc = FlashJournal_initialize(&journal, drv, &FLASH_JOURNAL_STRATEGY_SEQUENTIAL, callbackHandler);
00431         TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00432         if (rc == JOURNAL_STATUS_OK) {
00433             printf("test_initializeAfterLogLargeAndCommit: asynchronous_ops for init\n");
00434             return CaseTimeout(200) + CaseRepeatAll;
00435         }
00436         TEST_ASSERT_EQUAL(1, rc); /* synchronous completion of initialize() is expected to return 1 */
00437     }
00438 
00439     FlashJournal_Info_t info;
00440     rc = FlashJournal_getInfo(&journal, &info);
00441     TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
00442     TEST_ASSERT_EQUAL(SIZEOF_LARGE_WRITE, info.sizeofJournaledBlob);
00443 
00444     return CaseNext;
00445 }
00446 
00447 template<uint8_t PATTERN>
00448 control_t test_logLargeAndReadSmallChunks(const size_t call_count)
00449 {
00450     int32_t rc;
00451 
00452     printf("test_logLargeAndReadSmallChunks: entered with call_count %u\n", call_count);
00453 
00454     static const size_t SMALL_CHUNK_COUNT = 4;
00455 
00456     switch (call_count) {
00457         case 1:
00458             memset(buffer, PATTERN, SIZEOF_LARGE_WRITE);
00459             rc = FlashJournal_log(&journal, buffer, SIZEOF_LARGE_WRITE);
00460             TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00461             if (rc == JOURNAL_STATUS_OK) {
00462                 TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00463                 return CaseTimeout(500) + CaseRepeatAll;
00464             }
00465             /* intentional fall-through */
00466 
00467         case 2:
00468             rc = FlashJournal_commit(&journal);
00469             TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00470             if (rc == JOURNAL_STATUS_OK) {
00471                 TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00472                 return CaseTimeout(500) + CaseRepeatAll;
00473             }
00474             /* intentional fall-through */
00475 
00476         case 3:
00477             {
00478                 FlashJournal_Info_t info;
00479                 rc = FlashJournal_getInfo(&journal, &info);
00480                 TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
00481                 TEST_ASSERT_EQUAL(SIZEOF_LARGE_WRITE, info.sizeofJournaledBlob);
00482             }
00483             /* intentional fall-through */
00484 
00485         default:
00486             break;
00487     }
00488 
00489     if (call_count > 3) {
00490         if (drv->GetCapabilities().asynchronous_ops) {
00491             if (callbackStatus == 0) {
00492                 return CaseNext; /* termination condition */
00493             }
00494             TEST_ASSERT_EQUAL(SIZEOF_LARGE_WRITE / SMALL_CHUNK_COUNT, callbackStatus);
00495         }
00496 
00497         for (unsigned i = 0; i < SIZEOF_LARGE_WRITE / SMALL_CHUNK_COUNT; i++) {
00498             // printf("index %u value %x\n", i, buffer[i]);
00499             TEST_ASSERT_EQUAL(PATTERN, buffer[i]);
00500         }
00501     }
00502 
00503     while ((rc = FlashJournal_read(&journal, buffer, SIZEOF_LARGE_WRITE / SMALL_CHUNK_COUNT)) != JOURNAL_STATUS_EMPTY) {
00504         // printf("read returned %ld\n", rc);
00505         TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00506         if (rc == JOURNAL_STATUS_OK) {
00507             TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00508             return CaseTimeout(500) + CaseRepeatAll;
00509         }
00510 
00511         TEST_ASSERT_EQUAL(SIZEOF_LARGE_WRITE / SMALL_CHUNK_COUNT, rc);
00512         for (unsigned i = 0; i < SIZEOF_LARGE_WRITE / SMALL_CHUNK_COUNT; i++) {
00513             // printf("index %u value %x\n", i, buffer[i]);
00514             TEST_ASSERT_EQUAL(PATTERN, buffer[i]);
00515         }
00516     };
00517 
00518     return CaseNext;
00519 }
00520 
00521 template<uint8_t PATTERN, size_t SIZEOF_READS>
00522 control_t test_readLargeInSmallOddChunks(const size_t call_count)
00523 {
00524     int32_t rc;
00525 
00526     printf("test_readLargeInSmallOddChunks<0x%02x, %u>: entered with call_count %u\n", PATTERN, SIZEOF_READS, call_count);
00527 
00528     if (call_count == 1) {
00529         FlashJournal_Info_t info;
00530         rc = FlashJournal_getInfo(&journal, &info);
00531         TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
00532         TEST_ASSERT_EQUAL(SIZEOF_LARGE_WRITE, info.sizeofJournaledBlob);
00533         TEST_ASSERT(SIZEOF_READS < info.sizeofJournaledBlob);
00534     } else {
00535         if (drv->GetCapabilities().asynchronous_ops) {
00536             if (callbackStatus == 0) {
00537                 return CaseNext; /* termination condition */
00538             }
00539             TEST_ASSERT_EQUAL(SIZEOF_READS, callbackStatus);
00540         }
00541 
00542         for (unsigned i = 0; i < SIZEOF_READS; i++) {
00543             // printf("index %u value %x\n", i, buffer[i]);
00544             TEST_ASSERT_EQUAL(PATTERN, buffer[i]);
00545         }
00546     }
00547 
00548     while ((rc = FlashJournal_read(&journal, buffer, SIZEOF_READS)) != JOURNAL_STATUS_EMPTY) {
00549         // printf("read returned %ld\n", rc);
00550         TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00551         if (rc == JOURNAL_STATUS_OK) {
00552             TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00553             return CaseTimeout(500) + CaseRepeatAll;
00554         }
00555 
00556         TEST_ASSERT(rc <= (int32_t)SIZEOF_READS);
00557         for (unsigned i = 0; i < (unsigned)rc; i++) {
00558             // printf("index %u value %x\n", i, buffer[i]);
00559             TEST_ASSERT_EQUAL(PATTERN, buffer[i]);
00560         }
00561     };
00562 
00563     return CaseNext;
00564 }
00565 
00566 template<size_t SIZEOF_ODD_CHUNK, size_t N_WRITES>
00567 control_t test_logSeveralOddSizedChunks(size_t call_count)
00568 {
00569     TEST_ASSERT(N_WRITES >= 1);
00570 
00571     int32_t rc;
00572 
00573     static const uint8_t PATTERN = 0xAA;
00574     static size_t totalDataLogged = 0;
00575 
00576     printf("test_logSeveralOddSizedChunks<%u, %u>: entered with call_count %u\n", SIZEOF_ODD_CHUNK, N_WRITES, call_count);
00577     TEST_ASSERT(SIZEOF_ODD_CHUNK <= BUFFER_SIZE);
00578 
00579     /* check the status of the previous asynchronous operation */
00580     if ((call_count > 1) && (call_count <= (N_WRITES + 1))) {
00581         TEST_ASSERT((callbackStatus >= JOURNAL_STATUS_OK) || (callbackStatus == JOURNAL_STATUS_SMALL_LOG_REQUEST));
00582         if (callbackStatus == JOURNAL_STATUS_SMALL_LOG_REQUEST) {
00583             FlashJournal_Info_t info;
00584             rc = FlashJournal_getInfo(&journal, &info);
00585             TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
00586             TEST_ASSERT(SIZEOF_ODD_CHUNK < info.program_unit);
00587             printf("test_logSeveralOddSizedChunks: RETURNING CaseNext\n");
00588             return CaseNext;
00589         }
00590 
00591         size_t sizeofLoggedData = callbackStatus;
00592         TEST_ASSERT((size_t)sizeofLoggedData <= SIZEOF_ODD_CHUNK);
00593         if (sizeofLoggedData < SIZEOF_ODD_CHUNK) {
00594             FlashJournal_Info_t info;
00595             rc = FlashJournal_getInfo(&journal, &info);
00596             TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
00597             TEST_ASSERT((sizeofLoggedData % info.program_unit) == 0);
00598         }
00599         totalDataLogged += sizeofLoggedData;
00600     }
00601 
00602     while (call_count <= N_WRITES) {
00603         printf("test_logSeveralOddSizedChunks: iteration with call_count %u\n", call_count);
00604         memset(buffer, PATTERN, SIZEOF_ODD_CHUNK);
00605         rc = FlashJournal_log(&journal, buffer, SIZEOF_ODD_CHUNK);
00606         // printf("test_logSeveralOddSizedChunks: called FlashJournal_log(): rc = %" PRId32 "\n", rc);
00607         TEST_ASSERT((rc >= JOURNAL_STATUS_OK) || (rc == JOURNAL_STATUS_SMALL_LOG_REQUEST));
00608         if (rc == JOURNAL_STATUS_OK) {
00609             TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00610             return CaseTimeout(500) + CaseRepeatAll;
00611         }
00612 
00613         if (rc == JOURNAL_STATUS_SMALL_LOG_REQUEST) {
00614             FlashJournal_Info_t info;
00615             rc = FlashJournal_getInfo(&journal, &info);
00616             TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
00617             TEST_ASSERT(SIZEOF_ODD_CHUNK < info.program_unit);
00618             return CaseNext;
00619         }
00620 
00621         size_t sizeofLoggedData = rc;
00622         TEST_ASSERT(sizeofLoggedData <= SIZEOF_ODD_CHUNK); /* the amount actually written is expected to be less than the original */
00623         if (sizeofLoggedData < SIZEOF_ODD_CHUNK) {
00624             FlashJournal_Info_t info;
00625             rc = FlashJournal_getInfo(&journal, &info);
00626             TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
00627             TEST_ASSERT((sizeofLoggedData % info.program_unit) == 0);
00628         }
00629 
00630         totalDataLogged += sizeofLoggedData;
00631         ++call_count; /* simulate CaseRepeatAll for the synchronous case */
00632     }
00633 
00634     if (call_count == (N_WRITES + 1)) {
00635         rc = FlashJournal_commit(&journal);
00636         TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00637         if (rc == JOURNAL_STATUS_OK) {
00638             TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00639             return CaseTimeout(500) + CaseRepeatAll;
00640         }
00641 
00642         callbackStatus = rc;
00643     }
00644 
00645     TEST_ASSERT_EQUAL(1, callbackStatus);
00646     {
00647         FlashJournal_Info_t info;
00648         rc = FlashJournal_getInfo(&journal, &info);
00649         TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
00650         TEST_ASSERT_EQUAL(totalDataLogged, info.sizeofJournaledBlob);
00651     }
00652 
00653     return CaseNext;
00654 }
00655 
00656 control_t test_multipleWritesFollowedByCommitFollowedByMultipleReads(const size_t call_count)
00657 {
00658     int32_t rc;
00659 
00660     static const uint8_t PATTERN      = 0xAA;
00661     static const size_t  N_WRITES     = 4;
00662     static const size_t  N_READS      = N_WRITES;
00663     static const size_t  SIZEOF_WRITE = BUFFER_SIZE / N_WRITES;
00664     static const size_t  SIZEOF_READ  = BUFFER_SIZE / N_READS;
00665 
00666     printf("test_multipleWritesFollowedByCommitFollowedByMultipleReads: entered with call_count %u\n", call_count);
00667 
00668     if (call_count <= N_WRITES) {
00669         printf("writing pattern %02x\n", PATTERN ^ call_count);
00670         memset(buffer, (PATTERN ^ call_count), SIZEOF_WRITE);
00671         rc = FlashJournal_log(&journal, buffer, SIZEOF_WRITE);
00672         // printf("test_multipleWritesFollowedByCommitFollowedByMultipleReads: log returned %" PRId32 "\n", rc);
00673         TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00674         if (rc == JOURNAL_STATUS_OK) {
00675             TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00676             return CaseTimeout(500) + CaseRepeatAll;
00677         }
00678         TEST_ASSERT_EQUAL(SIZEOF_WRITE, rc);
00679         return CaseRepeatAll;
00680     } else if (call_count == (N_WRITES + 1)) {
00681         rc = FlashJournal_commit(&journal);
00682         TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00683         if (rc == JOURNAL_STATUS_OK) {
00684             TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00685             return CaseTimeout(500) + CaseRepeatAll;
00686         }
00687         // printf("test_multipleWritesFollowedByCommitFollowedByMultipleReads: commit returned %" PRId32 "\n", rc);
00688         callbackStatus = rc; /* pass forward the return value so that the next iteration can check callbackStatus */
00689         return CaseRepeatAll;
00690     } else if (call_count < (N_WRITES + 1 + N_READS + 1)) {
00691         unsigned readIteration = call_count - (N_WRITES + 1);
00692         printf("test_multipleWritesFollowedByCommitFollowedByMultipleReads: read iteration %u\n", readIteration);
00693         if (call_count == (N_WRITES + 1 /* commit */ + 1 /* first iteration after commit */)) {
00694             TEST_ASSERT_EQUAL(1, callbackStatus);
00695 
00696             FlashJournal_Info_t info;
00697             rc = FlashJournal_getInfo(&journal, &info);
00698             TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
00699             TEST_ASSERT_EQUAL(BUFFER_SIZE, info.sizeofJournaledBlob);
00700         } else {
00701             TEST_ASSERT_EQUAL(SIZEOF_READ, callbackStatus);
00702             for (unsigned i = 0; i < SIZEOF_READ; i++) {
00703                 // printf("test_multipleWritesFollowedByCommitFollowedByMultipleReads: index %u value %x\n", i, buffer[i]);
00704                 TEST_ASSERT_EQUAL(PATTERN ^ (readIteration - 1), buffer[i]);
00705             }
00706         }
00707 
00708         while ((rc = FlashJournal_read(&journal, buffer, SIZEOF_READ)) != JOURNAL_STATUS_EMPTY) {
00709             // printf("test_multipleWritesFollowedByCommitFollowedByMultipleReads: read returned %ld\n", rc);
00710             TEST_ASSERT((rc == JOURNAL_STATUS_OK) || (rc == SIZEOF_READ));
00711             if (rc == JOURNAL_STATUS_OK) {
00712                 TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00713                 return CaseTimeout(500) + CaseRepeatAll;
00714             }
00715 
00716             TEST_ASSERT_EQUAL(SIZEOF_READ, rc);
00717             printf("test_multipleWritesFollowedByCommitFollowedByMultipleReads: checking for pattern %02x\n", PATTERN ^ readIteration);
00718             for (unsigned i = 0; i < SIZEOF_READ; i++) {
00719                 // printf("index %u value %x\n", i, buffer[i]);
00720                 TEST_ASSERT_EQUAL(PATTERN ^ readIteration, buffer[i]);
00721             }
00722             ++readIteration;
00723         };
00724         TEST_ASSERT_EQUAL(N_READS + 1, readIteration);
00725     }
00726 
00727     return CaseNext;
00728 }
00729 
00730 control_t test_failedSmallWriteFollowedByPaddedWrite(const size_t call_count)
00731 {
00732     int32_t rc;
00733 
00734     static const uint8_t PATTERN = 0xAA;
00735 
00736     printf("test_failedSmallWriteFollowedByPaddedWrite: entered with call_count %u\n", call_count);
00737 
00738     FlashJournal_Info_t info;
00739     rc = FlashJournal_getInfo(&journal, &info);
00740     TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
00741     TEST_ASSERT(info.program_unit >= 1);
00742     if (info.program_unit == 1) {
00743         return CaseNext;
00744     }
00745 
00746     static const size_t SMALL_CONSTANT = 8 * info.program_unit;
00747     static const size_t SIZEOF_WRITE   = (info.program_unit - 1) + SMALL_CONSTANT;
00748     TEST_ASSERT(SIZEOF_WRITE <= BUFFER_SIZE);
00749 
00750     memset(buffer, PATTERN, SIZEOF_WRITE);
00751 
00752     if (call_count == 1) {
00753         rc = FlashJournal_log(&journal, buffer, SIZEOF_WRITE);
00754         TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00755         if (rc == JOURNAL_STATUS_OK) {
00756             TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00757             return CaseTimeout(500) + CaseRepeatAll;
00758         }
00759         TEST_ASSERT_EQUAL(SMALL_CONSTANT, rc);
00760         callbackStatus = rc;
00761         return CaseRepeatAll;
00762     } else if (call_count == 2) {
00763         TEST_ASSERT_EQUAL(SMALL_CONSTANT, callbackStatus);
00764         rc = FlashJournal_log(&journal, buffer, SIZEOF_WRITE - callbackStatus);
00765         TEST_ASSERT_EQUAL(JOURNAL_STATUS_SMALL_LOG_REQUEST, rc);
00766 
00767         rc = FlashJournal_getInfo(&journal, &info);
00768         TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
00769         TEST_ASSERT(info.program_unit >= 1);
00770         TEST_ASSERT(info.program_unit <= BUFFER_SIZE);
00771 
00772         rc = FlashJournal_log(&journal, buffer, info.program_unit);
00773         TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00774         if (rc == JOURNAL_STATUS_OK) {
00775             TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00776             return CaseTimeout(500) + CaseRepeatAll;
00777         }
00778         TEST_ASSERT_EQUAL(info.program_unit, rc);
00779         callbackStatus = rc;
00780         return CaseRepeatAll;
00781     } else if (call_count == 3) {
00782         rc = FlashJournal_commit(&journal);
00783         TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00784         if (rc == JOURNAL_STATUS_OK) {
00785             TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00786             return CaseTimeout(500) + CaseRepeatAll;
00787         }
00788         TEST_ASSERT_EQUAL(1, rc);
00789         callbackStatus = rc;
00790         return CaseRepeatAll;
00791     } else {
00792         TEST_ASSERT_EQUAL(1, callbackStatus);
00793 
00794         rc = FlashJournal_getInfo(&journal, &info);
00795         TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
00796         TEST_ASSERT_EQUAL((SIZEOF_WRITE + 1), info.sizeofJournaledBlob);
00797     }
00798 
00799     return CaseNext;
00800 }
00801 
00802 #ifndef AVOID_GREENTEA
00803 // Custom setup handler required for proper Greentea support
00804 utest::v1::status_t greentea_setup(const size_t number_of_cases)
00805 {
00806     GREENTEA_SETUP(60, "default_auto");
00807     // Call the default reporting function
00808     return greentea_test_setup_handler(number_of_cases);
00809 }
00810 #else
00811 status_t default_setup(const size_t)
00812 {
00813     return STATUS_CONTINUE;
00814 }
00815 #endif
00816 
00817 // Specify all your test cases here
00818 Case cases[] = {
00819     Case("initialize",                                  test_initialize),
00820     Case("reset and initialize1",                       test_resetAndInitialize),
00821 
00822     Case("log small item without commit",               test_logSmallWithoutCommit),
00823     Case("reset and initialize2",                       test_resetAndInitialize),
00824 
00825     Case("commit without logs",                         test_commitWithoutLogs),
00826     Case("initialize",                                  test_initialize),
00827 
00828     /* log small item, and reinitialize */
00829     Case("log small item and commit1",                  test_logSmallAndCommit<0xAA>),
00830     Case("initialize after small log and commit1",      test_initializeAfterLogSmallAndCommit),
00831     Case("log small item and commit2",                  test_logSmallAndCommit<0x11>),
00832     Case("initialize after small log and commit2",      test_initializeAfterLogSmallAndCommit),
00833     Case("log small item and commit3",                  test_logSmallAndCommit<0x22>),
00834     Case("initialize after small log and commit3",      test_initializeAfterLogSmallAndCommit),
00835     Case("log small item and commit4",                  test_logSmallAndCommit<0x55>),
00836     Case("initialize after small log and commit4",      test_initializeAfterLogSmallAndCommit),
00837     Case("log small item and commit5",                  test_logSmallAndCommit<0xAB>),
00838     Case("initialize after small log and commit5",      test_initializeAfterLogSmallAndCommit),
00839     Case("reset and initialize3",                       test_resetAndInitialize),
00840 
00841     Case("log large item without commit",               test_logLargeWithoutCommit),
00842 
00843     /* initialize, log large item, and reinitialize */
00844     Case("initialize2",                                 test_initialize),
00845     Case("reset and initialize4",                       test_resetAndInitialize),
00846     Case("log large item and commit1",                  test_logLargeAndCommit<0xAA>),
00847     Case("initialize after large log and commit1",      test_initializeAfterLogLargeAndCommit),
00848     Case("log large item and commit2",                  test_logLargeAndCommit<0x55>),
00849     Case("initialize after large log and commit2",      test_initializeAfterLogLargeAndCommit),
00850     Case("log large item and commit3",                  test_logLargeAndCommit<0x11>),
00851     Case("initialize after large log and commit3",      test_initializeAfterLogLargeAndCommit),
00852     Case("log large item and commit4",                  test_logLargeAndCommit<0xAB>),
00853     Case("initialize after large log and commit4",      test_initializeAfterLogLargeAndCommit),
00854     Case("log large item and commit5",                  test_logLargeAndCommit<0x22>),
00855     Case("initialize after large log and commit5",      test_initializeAfterLogLargeAndCommit),
00856     Case("reset and initialize5",                       test_resetAndInitialize),
00857 
00858     Case("log large item and read smaller chunks",      test_logLargeAndReadSmallChunks<0xAA>),
00859     Case("read large item in small, odd-sized chunks1", test_readLargeInSmallOddChunks<0xAA, ((BUFFER_SIZE / 2) - 1)>),
00860     Case("read large item in small, odd-sized chunks2", test_readLargeInSmallOddChunks<0xAA, 255>),
00861     Case("read large item in small, odd-sized chunks3", test_readLargeInSmallOddChunks<0xAA, 1021>),
00862     Case("read large item in small, odd-sized chunks4", test_readLargeInSmallOddChunks<0xAA, 2401>),
00863 
00864     /* log odd-sized blocks which wouldn't align with program_unit at the tail */
00865     Case("initialize3",                                 test_initialize),
00866     Case("log odd-sized chunk",                         test_logSeveralOddSizedChunks<1, 1>),
00867     Case("log odd-sized chunk",                         test_logSeveralOddSizedChunks<101, 11>),
00868     Case("log odd-sized chunk",                         test_logSeveralOddSizedChunks<1217, 4>),
00869     Case("log odd-sized chunk",                         test_logSeveralOddSizedChunks<2402, 5>),
00870     Case("log odd-sized chunk",                         test_logSeveralOddSizedChunks<4803, 3>),
00871     Case("log odd-sized chunk",                         test_logSeveralOddSizedChunks<(BUFFER_SIZE-1), 7>),
00872 
00873     Case("initialize4",                                 test_initialize),
00874     Case("multiple writes, commit, multiple reads",     test_multipleWritesFollowedByCommitFollowedByMultipleReads),
00875 
00876     Case("failed small write followed by padded write", test_failedSmallWriteFollowedByPaddedWrite),
00877 
00878     Case("reset and initialize6",                       test_resetAndInitialize),
00879     // Case("uninitialize", test_uninitialize),
00880 };
00881 
00882 // Declare your test specification with a custom setup handler
00883 #ifndef AVOID_GREENTEA
00884 Specification specification(greentea_setup, cases);
00885 #else
00886 Specification specification(default_setup, cases);
00887 #endif
00888 
00889 int main(int argc, char** argv)
00890 {
00891     // Run the test specification
00892     Harness::run(specification);
00893 }