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 "flash-journal-strategy-sequential/flash_journal_crc.h"
00029 #include "flash-journal-strategy-sequential/flash_journal_strategy_sequential.h"
00030 #include "flash-journal-strategy-sequential/flash_journal_private.h"
00031 #include <string.h>
00032 #include <inttypes.h>
00033 
00034 using namespace utest::v1;
00035 
00036 extern ARM_DRIVER_STORAGE ARM_Driver_Storage_MTD_K64F;
00037 const ARM_DRIVER_STORAGE *drv = &ARM_Driver_Storage_MTD_K64F;
00038 
00039 FlashJournal_t      journal;
00040 
00041 static const size_t BUFFER_SIZE = 8192;
00042 static uint8_t      buffer[BUFFER_SIZE];
00043 
00044 static const size_t SIZEOF_SMALL_WRITE = 8;
00045 static const size_t SIZEOF_LARGE_WRITE = BUFFER_SIZE;
00046 static int32_t      callbackStatus;
00047 
00048 void callbackHandler(int32_t status, FlashJournal_OpCode_t cmd_code)
00049 {
00050     callbackStatus = status;
00051 
00052     switch (cmd_code) {
00053         case FLASH_JOURNAL_OPCODE_INITIALIZE:
00054             //printf("journal_callbackHandler: callback for init with status %" PRId32 "\n", status);
00055             break;
00056 
00057         case FLASH_JOURNAL_OPCODE_READ_BLOB:
00058             //printf("journal_callbackHandler: callback for read with status %" PRId32 "\n", status);
00059             break;
00060 
00061         case FLASH_JOURNAL_OPCODE_LOG_BLOB:
00062             //printf("journal_callbackHandler: callback for log with status %" PRId32 "\n", status);
00063             break;
00064 
00065         case FLASH_JOURNAL_OPCODE_COMMIT:
00066             //printf("journal_callbackHandler: callback for commit with status %" PRId32 "\n", status);
00067             break;
00068 
00069         case FLASH_JOURNAL_OPCODE_RESET:
00070             //printf("journal_callbackHandler: callback for reset with status %" PRId32 "\n", status);
00071             break;
00072 
00073         case FLASH_JOURNAL_OPCODE_FORMAT:
00074             //printf("journal_callbackHandler: callback for format with status %" PRId32 "\n", status);
00075             break;
00076 
00077         default:
00078             //printf("journal_callbackHandler: callback for opcode %u with status %" PRId32 "\n", cmd_code, status);
00079             break;
00080     }
00081     Harness::validate_callback(); // Validate the callback
00082 }
00083 
00084 control_t test_format(const size_t call_count)
00085 {
00086     int32_t rc;
00087     //printf("test_format: entered with call_count %" PRIu32 "\n", (uint32_t)call_count);
00088 
00089     ARM_STORAGE_INFO mtdInfo;
00090     rc = drv->GetInfo(&mtdInfo);
00091     TEST_ASSERT_EQUAL(ARM_DRIVER_OK, rc);
00092     TEST_ASSERT(mtdInfo.total_storage > 0);
00093 
00094     if (call_count == 1) {
00095         rc = flashJournalStrategySequential_format(drv, 4 /* numSlots */, callbackHandler);
00096         TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00097         if (rc == JOURNAL_STATUS_OK) {
00098             return CaseTimeout(200) + CaseRepeatAll;
00099         }
00100         TEST_ASSERT_EQUAL(1, rc); /* synchronous completion is expected to return 1. */
00101     }
00102 
00103     return CaseNext;
00104 }
00105 
00106 void test_initializeBeforeCreate()
00107 {
00108     int32_t rc = FlashJournal_initialize(&journal, drv, &FLASH_JOURNAL_STRATEGY_SEQUENTIAL, callbackHandler);
00109     TEST_ASSERT((rc == 1) || (rc == JOURNAL_STATUS_NOT_FORMATTED));
00110 }
00111 
00112 control_t test_initialize()
00113 {
00114     int32_t rc = FlashJournal_initialize(&journal, drv, &FLASH_JOURNAL_STRATEGY_SEQUENTIAL, callbackHandler);
00115     TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00116     if (rc == JOURNAL_STATUS_OK) {
00117         return CaseTimeout(200);
00118     }
00119 
00120     /* ensure that something got written into the memory of journal_t */
00121     FlashJournal_t mockJournal;
00122     memset(&mockJournal, 0, sizeof(FlashJournal_t));
00123     TEST_ASSERT_NOT_EQUAL(0, memcmp(&mockJournal, &journal, sizeof(FlashJournal_t)));
00124 
00125     FlashJournal_Info_t info;
00126     rc = FlashJournal_getInfo(&journal, &info);
00127     TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
00128     TEST_ASSERT(info.capacity > 0);
00129 
00130     return CaseNext;
00131 }
00132 
00133 control_t test_resetAndInitialize(const size_t call_count)
00134 {
00135     int32_t rc;
00136     FlashJournal_Info_t info;
00137     SequentialFlashJournal_t *sequentialJournal = (SequentialFlashJournal_t *)&journal;
00138 
00139     static uint64_t previousCapacity;
00140 
00141     static enum {
00142         NEEDS_INITIAL_RESET,
00143         NEEDS_INITIALIZE_FOLLOWING_RESET,
00144         NEEDS_VERIFICATION_FOLLOWING_INITIALIZE,
00145     } state;
00146 
00147     //printf("test_resetAndInitialize: entered with call_count %" PRIu32 "\n", (uint32_t)call_count);
00148     if (call_count == 1) {
00149         state = NEEDS_INITIAL_RESET;
00150     }
00151 
00152     switch (state) {
00153         case NEEDS_INITIAL_RESET:
00154             rc = FlashJournal_getInfo(&journal, &info);
00155             TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
00156             TEST_ASSERT(info.capacity > 0);
00157             previousCapacity = info.capacity;
00158 
00159             //printf("test_resetAndInitialize: calling reset()\n");
00160             rc = FlashJournal_reset(&journal);
00161             TEST_ASSERT_NOT_EQUAL(JOURNAL_STATUS_UNSUPPORTED, rc);
00162             TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00163             state = NEEDS_INITIALIZE_FOLLOWING_RESET;
00164             if (rc == JOURNAL_STATUS_OK) {
00165                 TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00166                 return CaseTimeout(1000) + CaseRepeatAll;
00167             }
00168             TEST_ASSERT_EQUAL(1, rc); /* synchronous completion of reset() is expected to return 1 */
00169 
00170             /* fall through */
00171         case NEEDS_INITIALIZE_FOLLOWING_RESET:
00172             /* ensure that the journal has been re-initialized */
00173             TEST_ASSERT_EQUAL(0, sequentialJournal->nextSequenceNumber);
00174             TEST_ASSERT_EQUAL((uint32_t)-1, sequentialJournal->currentBlobIndex);
00175             TEST_ASSERT_EQUAL(SEQUENTIAL_JOURNAL_STATE_INITIALIZED, sequentialJournal->state);
00176 
00177             rc = FlashJournal_getInfo(&journal, &info);
00178             TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
00179             TEST_ASSERT(info.capacity > 0);
00180             TEST_ASSERT_EQUAL(previousCapacity, info.capacity);
00181             TEST_ASSERT_EQUAL(0, info.sizeofJournaledBlob);
00182 
00183             /* attempt an initialize following reset() */
00184             //printf("test_resetAndInitialize: calling initialize() after reset\n");
00185             rc = FlashJournal_initialize(&journal, drv, &FLASH_JOURNAL_STRATEGY_SEQUENTIAL, callbackHandler);
00186             TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00187             state = NEEDS_VERIFICATION_FOLLOWING_INITIALIZE;
00188             if (rc == JOURNAL_STATUS_OK) {
00189                 return CaseTimeout(200);
00190             }
00191             TEST_ASSERT_EQUAL(1, rc); /* synchronous completion of initialize() is expected to return 1 */
00192 
00193             /* fall through */
00194         case NEEDS_VERIFICATION_FOLLOWING_INITIALIZE:
00195         default:
00196             //printf("test_resetAndInitialize: verification\n");
00197             TEST_ASSERT_EQUAL(0, sequentialJournal->nextSequenceNumber);
00198             TEST_ASSERT_EQUAL((uint32_t)-1, sequentialJournal->currentBlobIndex);
00199             TEST_ASSERT_EQUAL(SEQUENTIAL_JOURNAL_STATE_INITIALIZED, sequentialJournal->state);
00200 
00201             rc = FlashJournal_getInfo(&journal, &info);
00202             TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
00203             TEST_ASSERT(info.capacity > 0);
00204             TEST_ASSERT_EQUAL(previousCapacity, info.capacity);
00205             TEST_ASSERT_EQUAL(0, info.sizeofJournaledBlob);
00206             break;
00207     }
00208 
00209     return CaseNext;
00210 }
00211 
00212 control_t test_commitWithoutLogs(const size_t call_count)
00213 {
00214     int32_t rc;
00215 
00216     //printf("test_commitWithoutLogs: entered with call_count %" PRIu32 "\n", (uint32_t)call_count);
00217 
00218     switch (call_count) {
00219         case 1:
00220             /* initialize */
00221             rc = FlashJournal_initialize(&journal, drv, &FLASH_JOURNAL_STRATEGY_SEQUENTIAL, callbackHandler);
00222             TEST_ASSERT(rc >= ARM_DRIVER_OK);
00223             if (rc == ARM_DRIVER_OK) {
00224                 return CaseTimeout(200) + CaseRepeatAll;
00225             }
00226             TEST_ASSERT_EQUAL(1, rc); /* synchronous completion of initialize() is expected to return 1 */
00227             return CaseRepeatAll;
00228 
00229         case 2:
00230             rc = FlashJournal_commit(&journal);
00231             //printf("commit returned %" PRId32 "\r\n", rc);
00232             TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00233             if (rc == JOURNAL_STATUS_OK) {
00234                 TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00235                 return CaseTimeout(500) + CaseRepeatAll;
00236             }
00237 
00238             /* intentional fall through*/
00239             callbackStatus = rc;
00240 
00241         case 3:
00242             TEST_ASSERT_EQUAL(1, callbackStatus);
00243             break;
00244     }
00245 
00246     return CaseNext;
00247 }
00248 
00249 control_t test_logSmallWithoutCommit(const size_t call_count)
00250 {
00251     int32_t rc;
00252 
00253     //printf("test_logSmallWithoutCommit: entered with call_count %" PRIu32 "\n", (uint32_t)call_count);
00254 
00255     switch (call_count) {
00256         case 1:
00257             /* initialize */
00258             rc = FlashJournal_initialize(&journal, drv, &FLASH_JOURNAL_STRATEGY_SEQUENTIAL, callbackHandler);
00259             TEST_ASSERT(rc >= ARM_DRIVER_OK);
00260             if (rc == ARM_DRIVER_OK) {
00261                 return CaseTimeout(200) + CaseRepeatAll;
00262             }
00263             TEST_ASSERT_EQUAL(1, rc); /* synchronous completion of initialize() is expected to return 1 */
00264             return CaseRepeatAll;
00265 
00266         case 2:
00267             /* log without commit */
00268             memset(buffer, 0xAA, SIZEOF_SMALL_WRITE);
00269             rc = FlashJournal_log(&journal, buffer, SIZEOF_SMALL_WRITE);
00270             TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00271             if (rc == JOURNAL_STATUS_OK) {
00272                 TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00273                 return CaseTimeout(500) + CaseRepeatAll;
00274             }
00275             /* else, fall through to synchronous verification */
00276 
00277         default:
00278             rc = FlashJournal_read(&journal, buffer, SIZEOF_SMALL_WRITE);
00279             TEST_ASSERT(rc < JOURNAL_STATUS_OK);
00280             return CaseNext;
00281     }
00282 }
00283 
00284 template <uint8_t PATTERN>
00285 control_t test_logSmallAndCommit(const size_t call_count)
00286 {
00287     int32_t rc;
00288 
00289     //printf("test_logSmallAndCommit: entered with call_count %" PRIu32 "\n", (uint32_t)call_count);
00290 
00291     switch (call_count) {
00292         case 1:
00293             memset(buffer, PATTERN, SIZEOF_SMALL_WRITE);
00294             rc = FlashJournal_log(&journal, buffer, SIZEOF_SMALL_WRITE);
00295             TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00296             if (rc == JOURNAL_STATUS_OK) {
00297                 TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00298                 return CaseTimeout(500) + CaseRepeatAll;
00299             }
00300             /* else, fall through to synchronous verification */
00301 
00302         case 2:
00303             rc = FlashJournal_commit(&journal);
00304             TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00305             if (rc == JOURNAL_STATUS_OK) {
00306                 TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00307                 return CaseTimeout(500) + CaseRepeatAll;
00308             }
00309             /* else, fall through to synchronous verification */
00310 
00311         case 3:
00312             {
00313                 FlashJournal_Info_t info;
00314                 rc = FlashJournal_getInfo(&journal, &info);
00315                 TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
00316                 TEST_ASSERT_EQUAL(SIZEOF_SMALL_WRITE, info.sizeofJournaledBlob);
00317             }
00318 
00319             rc = FlashJournal_read(&journal, buffer, SIZEOF_SMALL_WRITE);
00320             TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00321             if (rc == JOURNAL_STATUS_OK) {
00322                 TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00323                 return CaseTimeout(500) + CaseRepeatAll;
00324             }
00325 
00326             TEST_ASSERT_EQUAL(SIZEOF_SMALL_WRITE, rc);
00327             /* intentional fall-through */
00328 
00329         default:
00330             for (unsigned i = 0; i < SIZEOF_SMALL_WRITE; i++) {
00331                 // printf("index %u value %x\n", i, buffer[i]);
00332                 TEST_ASSERT_EQUAL(PATTERN, buffer[i]);
00333             }
00334 
00335             return CaseNext;
00336     }
00337 }
00338 
00339 control_t test_initializeAfterLogSmallAndCommit(const size_t call_count)
00340 {
00341     int32_t rc;
00342 
00343     //printf("test_initializeAfterLogSmallAndCommit: entered with call_count %" PRIu32 "\n", (uint32_t)call_count);
00344 
00345     if (call_count == 1) {
00346         rc = FlashJournal_initialize(&journal, drv, &FLASH_JOURNAL_STRATEGY_SEQUENTIAL, callbackHandler);
00347         TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00348         if (rc == JOURNAL_STATUS_OK) {
00349             //printf("asynchronous_ops for init\n");
00350             return CaseTimeout(200) + CaseRepeatAll;
00351         }
00352         TEST_ASSERT_EQUAL(1, rc); /* synchronous completion of initialize() is expected to return 1 */
00353     }
00354 
00355     FlashJournal_Info_t info;
00356     rc = FlashJournal_getInfo(&journal, &info);
00357     TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
00358     TEST_ASSERT_EQUAL(SIZEOF_SMALL_WRITE, info.sizeofJournaledBlob);
00359 
00360     return CaseNext;
00361 }
00362 
00363 control_t test_logLargeWithoutCommit(const size_t call_count)
00364 {
00365     int32_t rc;
00366 
00367     //printf("test_logLargeWithoutCommit: entered with call_count %" PRIu32 "\n", (uint32_t)call_count);
00368 
00369     switch (call_count) {
00370         case 1:
00371             rc = FlashJournal_initialize(&journal, drv, &FLASH_JOURNAL_STRATEGY_SEQUENTIAL, callbackHandler);
00372             TEST_ASSERT(rc >= ARM_DRIVER_OK);
00373             if (rc == ARM_DRIVER_OK) {
00374                 return CaseTimeout(200) + CaseRepeatAll;
00375             }
00376             TEST_ASSERT_EQUAL(1, rc); /* synchronous completion of initialize() is expected to return 1 */
00377             return CaseRepeatAll;
00378 
00379         case 2:
00380             memset(buffer, 0xAA, SIZEOF_LARGE_WRITE);
00381             rc = FlashJournal_log(&journal, buffer, SIZEOF_LARGE_WRITE);
00382             TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00383             if (rc == JOURNAL_STATUS_OK) {
00384                 TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00385                 return CaseTimeout(5000) + CaseRepeatAll;
00386             }
00387             /* intentional fall-through */
00388 
00389         case 3:
00390         default:
00391             rc = FlashJournal_read(&journal, buffer, SIZEOF_LARGE_WRITE);
00392             TEST_ASSERT(rc < JOURNAL_STATUS_OK);
00393             return CaseNext;
00394     }
00395 }
00396 
00397 template<uint8_t PATTERN>
00398 control_t test_logLargeAndCommit(const size_t call_count)
00399 {
00400     int32_t rc;
00401 
00402     //printf("test_logLargeAndCommit: entered with call_count %" PRIu32 "\n", (uint32_t)call_count);
00403 
00404     switch (call_count) {
00405         case 1:
00406             memset(buffer, PATTERN, SIZEOF_LARGE_WRITE);
00407             rc = FlashJournal_log(&journal, buffer, SIZEOF_LARGE_WRITE);
00408             TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00409             if (rc == JOURNAL_STATUS_OK) {
00410                 TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00411                 return CaseTimeout(500) + CaseRepeatAll;
00412             }
00413             /* intentional fall-through */
00414 
00415         case 2:
00416             rc = FlashJournal_commit(&journal);
00417             TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00418             if (rc == JOURNAL_STATUS_OK) {
00419                 TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00420                 return CaseTimeout(500) + CaseRepeatAll;
00421             }
00422             /* intentional fall-through */
00423 
00424         case 3:
00425             {
00426                 FlashJournal_Info_t info;
00427                 rc = FlashJournal_getInfo(&journal, &info);
00428                 TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
00429                 TEST_ASSERT_EQUAL(SIZEOF_LARGE_WRITE, info.sizeofJournaledBlob);
00430             }
00431 
00432             rc = FlashJournal_read(&journal, buffer, SIZEOF_LARGE_WRITE);
00433             TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00434             if (rc == JOURNAL_STATUS_OK) {
00435                 TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00436                 return CaseTimeout(500) + CaseRepeatAll;
00437             }
00438 
00439             TEST_ASSERT_EQUAL(SIZEOF_LARGE_WRITE, rc);
00440             /* intentional fall-through */
00441 
00442         default:
00443             for (unsigned i = 0; i < SIZEOF_LARGE_WRITE; i++) {
00444                 // printf("index %u value %x\n", i, buffer[i]);
00445                 TEST_ASSERT_EQUAL(PATTERN, buffer[i]);
00446             }
00447 
00448             return CaseNext;
00449     }
00450 }
00451 
00452 control_t test_initializeAfterLogLargeAndCommit(const size_t call_count)
00453 {
00454     int32_t rc;
00455 
00456     //printf("test_initializeAfterLogLargeAndCommit: entered with call_count %" PRIu32 "\n", (uint32_t)call_count);
00457 
00458     if (call_count == 1) {
00459         rc = FlashJournal_initialize(&journal, drv, &FLASH_JOURNAL_STRATEGY_SEQUENTIAL, callbackHandler);
00460         TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00461         if (rc == JOURNAL_STATUS_OK) {
00462             //printf("test_initializeAfterLogLargeAndCommit: asynchronous_ops for init\n");
00463             return CaseTimeout(200) + CaseRepeatAll;
00464         }
00465         TEST_ASSERT_EQUAL(1, rc); /* synchronous completion of initialize() is expected to return 1 */
00466     }
00467 
00468     FlashJournal_Info_t info;
00469     rc = FlashJournal_getInfo(&journal, &info);
00470     TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
00471     TEST_ASSERT_EQUAL(SIZEOF_LARGE_WRITE, info.sizeofJournaledBlob);
00472 
00473     return CaseNext;
00474 }
00475 
00476 template<uint8_t PATTERN>
00477 control_t test_logLargeAndReadSmallChunks(const size_t call_count)
00478 {
00479     int32_t rc;
00480 
00481     //printf("test_logLargeAndReadSmallChunks: entered with call_count %" PRIu32 "\n", (uint32_t)call_count);
00482 
00483     static const size_t SMALL_CHUNK_COUNT = 4;
00484 
00485     switch (call_count) {
00486         case 1:
00487             memset(buffer, PATTERN, SIZEOF_LARGE_WRITE);
00488             rc = FlashJournal_log(&journal, buffer, SIZEOF_LARGE_WRITE);
00489             TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00490             if (rc == JOURNAL_STATUS_OK) {
00491                 TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00492                 return CaseTimeout(500) + CaseRepeatAll;
00493             }
00494             /* intentional fall-through */
00495 
00496         case 2:
00497             rc = FlashJournal_commit(&journal);
00498             TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00499             if (rc == JOURNAL_STATUS_OK) {
00500                 TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00501                 return CaseTimeout(500) + CaseRepeatAll;
00502             }
00503             /* intentional fall-through */
00504 
00505         case 3:
00506             {
00507                 FlashJournal_Info_t info;
00508                 rc = FlashJournal_getInfo(&journal, &info);
00509                 TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
00510                 TEST_ASSERT_EQUAL(SIZEOF_LARGE_WRITE, info.sizeofJournaledBlob);
00511             }
00512             /* intentional fall-through */
00513 
00514         default:
00515             break;
00516     }
00517 
00518     if (call_count > 3) {
00519         if (drv->GetCapabilities().asynchronous_ops) {
00520             if (callbackStatus == 0) {
00521                 return CaseNext; /* termination condition */
00522             }
00523             TEST_ASSERT_EQUAL(SIZEOF_LARGE_WRITE / SMALL_CHUNK_COUNT, callbackStatus);
00524         }
00525 
00526         for (unsigned i = 0; i < SIZEOF_LARGE_WRITE / SMALL_CHUNK_COUNT; i++) {
00527             // printf("index %u value %x\n", i, buffer[i]);
00528             TEST_ASSERT_EQUAL(PATTERN, buffer[i]);
00529         }
00530     }
00531 
00532     while ((rc = FlashJournal_read(&journal, buffer, SIZEOF_LARGE_WRITE / SMALL_CHUNK_COUNT)) != JOURNAL_STATUS_EMPTY) {
00533         // printf("read returned %" PRId32 "\n", rc);
00534         TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00535         if (rc == JOURNAL_STATUS_OK) {
00536             TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00537             return CaseTimeout(500) + CaseRepeatAll;
00538         }
00539 
00540         TEST_ASSERT_EQUAL(SIZEOF_LARGE_WRITE / SMALL_CHUNK_COUNT, rc);
00541         for (unsigned i = 0; i < SIZEOF_LARGE_WRITE / SMALL_CHUNK_COUNT; i++) {
00542             // printf("index %u value %x\n", i, buffer[i]);
00543             TEST_ASSERT_EQUAL(PATTERN, buffer[i]);
00544         }
00545     };
00546 
00547     return CaseNext;
00548 }
00549 
00550 template<uint8_t PATTERN, size_t SIZEOF_READS>
00551 control_t test_readLargeInSmallOddChunks(const size_t call_count)
00552 {
00553     int32_t rc;
00554 
00555     //printf("test_readLargeInSmallOddChunks<0x%02x, %" PRIu32 ">: entered with call_count %" PRIu32 "\n", PATTERN, (uint32_t)SIZEOF_READS, (uint32_t)call_count);
00556 
00557     if (call_count == 1) {
00558         FlashJournal_Info_t info;
00559         rc = FlashJournal_getInfo(&journal, &info);
00560         TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
00561         TEST_ASSERT_EQUAL(SIZEOF_LARGE_WRITE, info.sizeofJournaledBlob);
00562         TEST_ASSERT(SIZEOF_READS < info.sizeofJournaledBlob);
00563     } else {
00564         if (drv->GetCapabilities().asynchronous_ops) {
00565             if (callbackStatus == 0) {
00566                 return CaseNext; /* termination condition */
00567             }
00568             TEST_ASSERT_EQUAL(SIZEOF_READS, callbackStatus);
00569         }
00570 
00571         for (unsigned i = 0; i < SIZEOF_READS; i++) {
00572             // printf("index %u value %x\n", i, buffer[i]);
00573             TEST_ASSERT_EQUAL(PATTERN, buffer[i]);
00574         }
00575     }
00576 
00577     while ((rc = FlashJournal_read(&journal, buffer, SIZEOF_READS)) != JOURNAL_STATUS_EMPTY) {
00578         // printf("read returned %" PRId32 "\n", rc);
00579         TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00580         if (rc == JOURNAL_STATUS_OK) {
00581             TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00582             return CaseTimeout(500) + CaseRepeatAll;
00583         }
00584 
00585         TEST_ASSERT(rc <= (int32_t)SIZEOF_READS);
00586         for (unsigned i = 0; i < (unsigned)rc; i++) {
00587             // printf("index %u value %x\n", i, buffer[i]);
00588             TEST_ASSERT_EQUAL(PATTERN, buffer[i]);
00589         }
00590     };
00591 
00592     return CaseNext;
00593 }
00594 
00595 template<uint8_t PATTERN>
00596 control_t test_logPattern(size_t call_count)
00597 {
00598     int32_t rc = JOURNAL_STATUS_OK;
00599 
00600     //printf("test_logpattern: entered with call_count %" PRIu32 "\n", (uint32_t)call_count);
00601 
00602     switch (call_count) {
00603         case 1:
00604             for (unsigned index = 0; index < SIZEOF_LARGE_WRITE; index++) {
00605                 buffer[index] = (uint8_t)(PATTERN ^ index);
00606             }
00607             rc = FlashJournal_log(&journal, buffer, SIZEOF_LARGE_WRITE);
00608             TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00609             if (rc == JOURNAL_STATUS_OK) {
00610                 TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00611                 return CaseTimeout(500) + CaseRepeatAll;
00612             }
00613             /* intentional fall-through */
00614             call_count = 2;
00615 
00616         case 2:
00617             rc = FlashJournal_commit(&journal);
00618             TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00619             if (rc == JOURNAL_STATUS_OK) {
00620                 TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00621                 return CaseTimeout(500) + CaseRepeatAll;
00622             }
00623             callbackStatus = rc;
00624             /* intentional fall-through */
00625             call_count = 3;
00626 
00627         case 3:
00628             {
00629                 FlashJournal_Info_t info;
00630                 rc = FlashJournal_getInfo(&journal, &info);
00631                 TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
00632                 TEST_ASSERT_EQUAL(SIZEOF_LARGE_WRITE, info.sizeofJournaledBlob);
00633             }
00634             /* intentional fall-through */
00635             call_count = 4;
00636 
00637         case 4:
00638             TEST_ASSERT_EQUAL(1, callbackStatus);
00639 
00640             rc = FlashJournal_read(&journal, buffer, SIZEOF_LARGE_WRITE);
00641             TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00642             if (rc == JOURNAL_STATUS_OK) {
00643                 TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00644                 return CaseTimeout(500) + CaseRepeatAll;
00645             }
00646             callbackStatus = rc;
00647             /* intentional fall-through */
00648             call_count = 4;
00649 
00650         case 5:
00651             TEST_ASSERT_EQUAL(SIZEOF_LARGE_WRITE, rc);
00652             for (unsigned i = 0; i < SIZEOF_LARGE_WRITE; i++) {
00653                 // printf("index %u value %x\n", i, buffer[i]);
00654                 TEST_ASSERT_EQUAL((uint8_t)(PATTERN ^ i), buffer[i]);
00655             }
00656             break;
00657 
00658         default:
00659             TEST_ASSERT(false);
00660             break;
00661     }
00662 
00663     return CaseNext;
00664 }
00665 
00666 template<uint8_t PATTERN, size_t SIZEOF_READS>
00667 control_t test_readFromInReverse(const size_t call_count)
00668 {
00669     int32_t rc;
00670     static size_t offset = SIZEOF_LARGE_WRITE;
00671 
00672     //printf("test_readFrom<0x%02x, %" PRIu32 ">: entered with call_count %" PRIu32 "\n", PATTERN, (uint32_t)SIZEOF_READS, (uint32_t)call_count);
00673 
00674     if (call_count == 1) {
00675         FlashJournal_Info_t info;
00676         rc = FlashJournal_getInfo(&journal, &info);
00677         TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
00678         TEST_ASSERT_EQUAL(SIZEOF_LARGE_WRITE, info.sizeofJournaledBlob);
00679         TEST_ASSERT(SIZEOF_READS <= info.sizeofJournaledBlob);
00680 
00681         rc = FlashJournal_readFrom(&journal, offset + 1, buffer, SIZEOF_READS);
00682         TEST_ASSERT_EQUAL(JOURNAL_STATUS_EMPTY, rc);
00683         rc = FlashJournal_readFrom(&journal, offset, buffer, SIZEOF_READS);
00684         TEST_ASSERT_EQUAL(JOURNAL_STATUS_EMPTY, rc);
00685         offset -= SIZEOF_READS;
00686     } else {
00687         if (drv->GetCapabilities().asynchronous_ops) {
00688             if (callbackStatus == 0) {
00689                 return CaseNext; /* termination condition */
00690             }
00691             TEST_ASSERT_EQUAL(SIZEOF_READS, callbackStatus);
00692         }
00693 
00694         for (unsigned i = 0; i < SIZEOF_READS; i++) {
00695             // printf("index %u value %x\n", i, buffer[i]);
00696             TEST_ASSERT_EQUAL((uint8_t)(PATTERN ^ (offset + i)), buffer[i]);
00697         }
00698         if (offset == 0) {
00699             return CaseNext;
00700         }
00701         if (offset >= SIZEOF_READS) {
00702             offset -= SIZEOF_READS;
00703         } else {
00704             offset = 0;
00705         }
00706     }
00707 
00708     // printf("test_readFrom: issuing read at offset %lu\n", offset);
00709     while ((rc = FlashJournal_readFrom(&journal, offset, buffer, SIZEOF_READS)) != JOURNAL_STATUS_EMPTY) {
00710         // printf("read returned %" PRId32 "\n", rc);
00711         TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00712         if (rc == JOURNAL_STATUS_OK) {
00713             TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00714             return CaseTimeout(500) + CaseRepeatAll;
00715         }
00716 
00717         TEST_ASSERT(rc <= (int32_t)SIZEOF_READS);
00718         for (unsigned i = 0; i < (unsigned)rc; i++) {
00719             // printf("index %u value %x\n", i, buffer[i]);
00720             TEST_ASSERT_EQUAL((uint8_t)(PATTERN ^ (offset + i)), buffer[i]);
00721         }
00722         if (offset == 0) {
00723             return CaseNext;
00724         }
00725         if (offset >= SIZEOF_READS) {
00726             offset -= SIZEOF_READS;
00727         } else {
00728             offset = 0;
00729         }
00730         // printf("test_readFrom: issuing read at offset %lu\n", offset);
00731     };
00732 
00733     return CaseNext;
00734 }
00735 
00736 template<uint8_t PATTERN, size_t SIZEOF_READS>
00737 control_t test_readFromFollowedByReads(size_t call_count)
00738 {
00739     //printf("test_readFrom<0x%02x, %" PRIu32 ">: entered with call_count %" PRIu32 "\n", PATTERN, (uint32_t)SIZEOF_READS, (uint32_t)call_count);
00740 
00741     int32_t rc;
00742     static size_t offset = SIZEOF_LARGE_WRITE / 2;
00743 
00744     FlashJournal_Info_t info;
00745     switch (call_count) {
00746         case 1:
00747             rc = FlashJournal_getInfo(&journal, &info);
00748             TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
00749             TEST_ASSERT_EQUAL(SIZEOF_LARGE_WRITE, info.sizeofJournaledBlob);
00750             TEST_ASSERT(SIZEOF_READS <= (info.sizeofJournaledBlob - offset));
00751 
00752             rc = FlashJournal_readFrom(&journal, offset, buffer, SIZEOF_READS);
00753             TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00754             if (rc == JOURNAL_STATUS_OK) {
00755                 TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00756                 return CaseTimeout(500) + CaseRepeatAll;
00757             }
00758             callbackStatus = rc;
00759             /* intentional fall-through */
00760             call_count = 2;
00761 
00762         case 2:
00763             /* verify the previous readFrom */
00764             TEST_ASSERT_EQUAL(SIZEOF_READS, callbackStatus);
00765             for (unsigned i = 0; i < (unsigned)callbackStatus; i++) {
00766                 // printf("index %u value %x\n", i, buffer[i]);
00767                 TEST_ASSERT_EQUAL((uint8_t)(PATTERN ^ (offset + i)), buffer[i]);
00768             }
00769 
00770             /* issue a sequential read to follow the previous readFrom */
00771             rc = FlashJournal_read(&journal, buffer, SIZEOF_READS);
00772             TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00773             if (rc == JOURNAL_STATUS_OK) {
00774                 TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00775                 return CaseTimeout(500) + CaseRepeatAll;
00776             }
00777             callbackStatus = rc;
00778             /* intentional fall-through */
00779             call_count = 3;
00780 
00781         case 3:
00782             TEST_ASSERT_EQUAL(SIZEOF_READS, callbackStatus);
00783 
00784             for (unsigned i = 0; i < (unsigned)callbackStatus; i++) {
00785                 // printf("index %u value %x\n", i, buffer[i]);
00786                 TEST_ASSERT_EQUAL((uint8_t)(PATTERN ^ (offset + SIZEOF_READS + i)), buffer[i]);
00787             }
00788             break;
00789     }
00790 
00791     return CaseNext;
00792 }
00793 
00794 template<size_t SIZEOF_ODD_CHUNK, size_t N_WRITES>
00795 control_t test_logSeveralOddSizedChunks(size_t call_count)
00796 {
00797     TEST_ASSERT(N_WRITES >= 1);
00798 
00799     int32_t rc;
00800 
00801     static const uint8_t PATTERN = 0xAA;
00802     static size_t totalDataLogged = 0;
00803 
00804     //printf("test_logSeveralOddSizedChunks<%" PRIu32 ", %" PRIu32 ">: entered with call_count %" PRIu32 "\n", (uint32_t)SIZEOF_ODD_CHUNK, (uint32_t)N_WRITES, (uint32_t)call_count);
00805     TEST_ASSERT(SIZEOF_ODD_CHUNK <= BUFFER_SIZE);
00806 
00807     /* check the status of the previous asynchronous operation */
00808     if ((call_count > 1) && (call_count <= (N_WRITES + 1))) {
00809         TEST_ASSERT((callbackStatus >= JOURNAL_STATUS_OK) || (callbackStatus == JOURNAL_STATUS_SMALL_LOG_REQUEST));
00810         if (callbackStatus == JOURNAL_STATUS_SMALL_LOG_REQUEST) {
00811             FlashJournal_Info_t info;
00812             rc = FlashJournal_getInfo(&journal, &info);
00813             TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
00814             TEST_ASSERT(SIZEOF_ODD_CHUNK < info.program_unit);
00815             //printf("test_logSeveralOddSizedChunks: RETURNING CaseNext\n");
00816             return CaseNext;
00817         }
00818 
00819         size_t sizeofLoggedData = callbackStatus;
00820         TEST_ASSERT((size_t)sizeofLoggedData <= SIZEOF_ODD_CHUNK);
00821         if (sizeofLoggedData < SIZEOF_ODD_CHUNK) {
00822             FlashJournal_Info_t info;
00823             rc = FlashJournal_getInfo(&journal, &info);
00824             TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
00825             TEST_ASSERT((sizeofLoggedData % info.program_unit) == 0);
00826         }
00827         totalDataLogged += sizeofLoggedData;
00828     }
00829 
00830     while (call_count <= N_WRITES) {
00831         //printf("test_logSeveralOddSizedChunks: iteration with call_count %" PRIu32 "\n", (uint32_t)call_count);
00832         memset(buffer, PATTERN, SIZEOF_ODD_CHUNK);
00833         rc = FlashJournal_log(&journal, buffer, SIZEOF_ODD_CHUNK);
00834         // printf("test_logSeveralOddSizedChunks: called FlashJournal_log(): rc = %" PRId32 "\n", rc);
00835         TEST_ASSERT((rc >= JOURNAL_STATUS_OK) || (rc == JOURNAL_STATUS_SMALL_LOG_REQUEST));
00836         if (rc == JOURNAL_STATUS_OK) {
00837             TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00838             return CaseTimeout(500) + CaseRepeatAll;
00839         }
00840 
00841         if (rc == JOURNAL_STATUS_SMALL_LOG_REQUEST) {
00842             FlashJournal_Info_t info;
00843             rc = FlashJournal_getInfo(&journal, &info);
00844             TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
00845             TEST_ASSERT(SIZEOF_ODD_CHUNK < info.program_unit);
00846             return CaseNext;
00847         }
00848 
00849         size_t sizeofLoggedData = rc;
00850         TEST_ASSERT(sizeofLoggedData <= SIZEOF_ODD_CHUNK); /* the amount actually written is expected to be less than the original */
00851         if (sizeofLoggedData < SIZEOF_ODD_CHUNK) {
00852             FlashJournal_Info_t info;
00853             rc = FlashJournal_getInfo(&journal, &info);
00854             TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
00855             TEST_ASSERT((sizeofLoggedData % info.program_unit) == 0);
00856         }
00857 
00858         totalDataLogged += sizeofLoggedData;
00859         ++call_count; /* simulate CaseRepeatAll for the synchronous case */
00860     }
00861 
00862     if (call_count == (N_WRITES + 1)) {
00863         rc = FlashJournal_commit(&journal);
00864         TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00865         if (rc == JOURNAL_STATUS_OK) {
00866             TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00867             return CaseTimeout(500) + CaseRepeatAll;
00868         }
00869 
00870         callbackStatus = rc;
00871     }
00872 
00873     TEST_ASSERT_EQUAL(1, callbackStatus);
00874     {
00875         FlashJournal_Info_t info;
00876         rc = FlashJournal_getInfo(&journal, &info);
00877         TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
00878         TEST_ASSERT_EQUAL(totalDataLogged, info.sizeofJournaledBlob);
00879     }
00880 
00881     return CaseNext;
00882 }
00883 
00884 control_t test_multipleWritesFollowedByCommitFollowedByMultipleReads(const size_t call_count)
00885 {
00886     int32_t rc;
00887 
00888     static const uint8_t PATTERN      = 0xAA;
00889     static const size_t  N_WRITES     = 4;
00890     static const size_t  N_READS      = N_WRITES;
00891     static const size_t  SIZEOF_WRITE = BUFFER_SIZE / N_WRITES;
00892     static const size_t  SIZEOF_READ  = BUFFER_SIZE / N_READS;
00893 
00894     //printf("test_multipleWritesFollowedByCommitFollowedByMultipleReads: entered with call_count %" PRIu32 "\n", (uint32_t)call_count);
00895 
00896     if (call_count <= N_WRITES) {
00897         //printf("writing pattern %02" PRIx8 "\n", (uint8_t)(PATTERN ^ call_count));
00898         memset(buffer, (PATTERN ^ call_count), SIZEOF_WRITE);
00899         rc = FlashJournal_log(&journal, buffer, SIZEOF_WRITE);
00900         //printf("test_multipleWritesFollowedByCommitFollowedByMultipleReads: log returned %" PRId32 "\n", rc);
00901         TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00902         if (rc == JOURNAL_STATUS_OK) {
00903             TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00904             return CaseTimeout(500) + CaseRepeatAll;
00905         }
00906         TEST_ASSERT_EQUAL(SIZEOF_WRITE, rc);
00907         return CaseRepeatAll;
00908     } else if (call_count == (N_WRITES + 1)) {
00909         rc = FlashJournal_commit(&journal);
00910         TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00911         if (rc == JOURNAL_STATUS_OK) {
00912             TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00913             return CaseTimeout(500) + CaseRepeatAll;
00914         }
00915         //printf("test_multipleWritesFollowedByCommitFollowedByMultipleReads: commit returned %" PRId32 "\n", rc);
00916         callbackStatus = rc; /* pass forward the return value so that the next iteration can check callbackStatus */
00917         return CaseRepeatAll;
00918     } else if (call_count < (N_WRITES + 1 + N_READS + 1)) {
00919         unsigned readIteration = call_count - (N_WRITES + 1);
00920         //printf("test_multipleWritesFollowedByCommitFollowedByMultipleReads: read iteration %u\n", readIteration);
00921         if (call_count == (N_WRITES + 1 /* commit */ + 1 /* first iteration after commit */)) {
00922             TEST_ASSERT_EQUAL(1, callbackStatus);
00923 
00924             FlashJournal_Info_t info;
00925             rc = FlashJournal_getInfo(&journal, &info);
00926             TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
00927             TEST_ASSERT_EQUAL(BUFFER_SIZE, info.sizeofJournaledBlob);
00928         } else {
00929             TEST_ASSERT_EQUAL(SIZEOF_READ, callbackStatus);
00930             for (unsigned i = 0; i < SIZEOF_READ; i++) {
00931                 // printf("test_multipleWritesFollowedByCommitFollowedByMultipleReads: index %u value %x\n", i, buffer[i]);
00932                 TEST_ASSERT_EQUAL(PATTERN ^ (readIteration - 1), buffer[i]);
00933             }
00934         }
00935 
00936         while ((rc = FlashJournal_read(&journal, buffer, SIZEOF_READ)) != JOURNAL_STATUS_EMPTY) {
00937             // printf("test_multipleWritesFollowedByCommitFollowedByMultipleReads: read returned %" PRId32 "\n", rc);
00938             TEST_ASSERT((rc == JOURNAL_STATUS_OK) || (rc == SIZEOF_READ));
00939             if (rc == JOURNAL_STATUS_OK) {
00940                 TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00941                 return CaseTimeout(500) + CaseRepeatAll;
00942             }
00943 
00944             TEST_ASSERT_EQUAL(SIZEOF_READ, rc);
00945             //printf("test_multipleWritesFollowedByCommitFollowedByMultipleReads: checking for pattern %02x\n", PATTERN ^ readIteration);
00946             for (unsigned i = 0; i < SIZEOF_READ; i++) {
00947                 // printf("index %u value %x\n", i, buffer[i]);
00948                 TEST_ASSERT_EQUAL(PATTERN ^ readIteration, buffer[i]);
00949             }
00950             ++readIteration;
00951         };
00952         TEST_ASSERT_EQUAL(N_READS + 1, readIteration);
00953     }
00954 
00955     return CaseNext;
00956 }
00957 
00958 control_t test_failedSmallWriteFollowedByPaddedWrite(const size_t call_count)
00959 {
00960     int32_t rc;
00961 
00962     static const uint8_t PATTERN = 0xAA;
00963 
00964     //printf("test_failedSmallWriteFollowedByPaddedWrite: entered with call_count %" PRIu32 "\n", (uint32_t)call_count);
00965 
00966     FlashJournal_Info_t info;
00967     rc = FlashJournal_getInfo(&journal, &info);
00968     TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
00969     TEST_ASSERT(info.program_unit >= 1);
00970     if (info.program_unit == 1) {
00971         return CaseNext;
00972     }
00973 
00974     static const size_t SMALL_CONSTANT = 8 * info.program_unit;
00975     static const size_t SIZEOF_WRITE   = (info.program_unit - 1) + SMALL_CONSTANT;
00976     TEST_ASSERT(SIZEOF_WRITE <= BUFFER_SIZE);
00977 
00978     memset(buffer, PATTERN, SIZEOF_WRITE);
00979 
00980     if (call_count == 1) {
00981         rc = FlashJournal_log(&journal, buffer, SIZEOF_WRITE);
00982         TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
00983         if (rc == JOURNAL_STATUS_OK) {
00984             TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
00985             return CaseTimeout(500) + CaseRepeatAll;
00986         }
00987         TEST_ASSERT_EQUAL(SMALL_CONSTANT, rc);
00988         callbackStatus = rc;
00989         return CaseRepeatAll;
00990     } else if (call_count == 2) {
00991         TEST_ASSERT_EQUAL(SMALL_CONSTANT, callbackStatus);
00992         rc = FlashJournal_log(&journal, buffer, SIZEOF_WRITE - callbackStatus);
00993         TEST_ASSERT_EQUAL(JOURNAL_STATUS_SMALL_LOG_REQUEST, rc);
00994 
00995         rc = FlashJournal_getInfo(&journal, &info);
00996         TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
00997         TEST_ASSERT(info.program_unit >= 1);
00998         TEST_ASSERT(info.program_unit <= BUFFER_SIZE);
00999 
01000         rc = FlashJournal_log(&journal, buffer, info.program_unit);
01001         TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
01002         if (rc == JOURNAL_STATUS_OK) {
01003             TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
01004             return CaseTimeout(500) + CaseRepeatAll;
01005         }
01006         TEST_ASSERT_EQUAL(info.program_unit, rc);
01007         callbackStatus = rc;
01008         return CaseRepeatAll;
01009     } else if (call_count == 3) {
01010         rc = FlashJournal_commit(&journal);
01011         TEST_ASSERT(rc >= JOURNAL_STATUS_OK);
01012         if (rc == JOURNAL_STATUS_OK) {
01013             TEST_ASSERT_EQUAL(1, drv->GetCapabilities().asynchronous_ops);
01014             return CaseTimeout(500) + CaseRepeatAll;
01015         }
01016         TEST_ASSERT_EQUAL(1, rc);
01017         callbackStatus = rc;
01018         return CaseRepeatAll;
01019     } else {
01020         TEST_ASSERT_EQUAL(1, callbackStatus);
01021 
01022         rc = FlashJournal_getInfo(&journal, &info);
01023         TEST_ASSERT_EQUAL(JOURNAL_STATUS_OK, rc);
01024         TEST_ASSERT_EQUAL((SIZEOF_WRITE + 1), info.sizeofJournaledBlob);
01025     }
01026 
01027     return CaseNext;
01028 }
01029 
01030 void test_crc32()
01031 {
01032     const unsigned char dummyMsg[] = "ahello world";
01033     flashJournalCrcReset(); TEST_ASSERT_EQUAL(0xe8b7be43, flashJournalCrcCummulative(dummyMsg, 1));
01034     flashJournalCrcReset(); TEST_ASSERT_EQUAL(0x7e56a173, flashJournalCrcCummulative(dummyMsg, 2));
01035     flashJournalCrcReset(); TEST_ASSERT_EQUAL(0x26a80c7d, flashJournalCrcCummulative(dummyMsg, 3));
01036     flashJournalCrcReset(); TEST_ASSERT_EQUAL(0xb8946773, flashJournalCrcCummulative(dummyMsg, 4));
01037     flashJournalCrcReset(); TEST_ASSERT_EQUAL(0x5fb2761f, flashJournalCrcCummulative(dummyMsg, 5));
01038     flashJournalCrcReset(); TEST_ASSERT_EQUAL(0x82582cc7, flashJournalCrcCummulative(dummyMsg, 6));
01039     flashJournalCrcReset(); TEST_ASSERT_EQUAL(0xeceec07a, flashJournalCrcCummulative(dummyMsg, 7));
01040     flashJournalCrcReset(); TEST_ASSERT_EQUAL(0xac5f7df0, flashJournalCrcCummulative(dummyMsg, 8));
01041     flashJournalCrcReset(); TEST_ASSERT_EQUAL(0xb21e3e25, flashJournalCrcCummulative(dummyMsg, 9));
01042     flashJournalCrcReset(); TEST_ASSERT_EQUAL(0x27bf35e4, flashJournalCrcCummulative(dummyMsg, 10));
01043     flashJournalCrcReset(); TEST_ASSERT_EQUAL(0x31465baa, flashJournalCrcCummulative(dummyMsg, 11));
01044     flashJournalCrcReset(); TEST_ASSERT_EQUAL(0xaeef4661, flashJournalCrcCummulative(dummyMsg, 12));
01045 
01046     /* check for composability */
01047     uint32_t crc;
01048     for (unsigned msgLen = 1; msgLen < strlen((const char *)dummyMsg); msgLen++) {
01049         for (unsigned partitionIndex = 1; partitionIndex < msgLen; partitionIndex++) {
01050             flashJournalCrcReset(); crc = flashJournalCrcCummulative(dummyMsg, partitionIndex); crc = flashJournalCrcCummulative(dummyMsg + partitionIndex, msgLen - partitionIndex);
01051             flashJournalCrcReset(); TEST_ASSERT_EQUAL(flashJournalCrcCummulative(dummyMsg, msgLen), crc);
01052         }
01053     }
01054 }
01055 
01056 #ifndef AVOID_GREENTEA
01057 // Custom setup handler required for proper Greentea support
01058 utest::v1::status_t greentea_setup(const size_t number_of_cases)
01059 {
01060     GREENTEA_SETUP(60, "default_auto");
01061     // Call the default reporting function
01062     return greentea_test_setup_handler(number_of_cases);
01063 }
01064 #else
01065 status_t default_setup(const size_t)
01066 {
01067     return STATUS_CONTINUE;
01068 }
01069 #endif
01070 
01071 // Specify all your test cases here
01072 Case cases[] = {
01073 
01074     Case("initializeBeforeCreate",                      test_initializeBeforeCreate),
01075     Case("format",                                      test_format),
01076     Case("initialize",                                  test_initialize),
01077     Case("reset and initialize1",                       test_resetAndInitialize),
01078 
01079     Case("log small item without commit",               test_logSmallWithoutCommit),
01080     Case("reset and initialize2",                       test_resetAndInitialize),
01081 
01082     Case("commit without logs",                         test_commitWithoutLogs),
01083     Case("initialize",                                  test_initialize),
01084 
01085     /* log small item, and reinitialize */
01086     Case("log small item and commit1",                  test_logSmallAndCommit<0xAA>),
01087     Case("initialize after small log and commit1",      test_initializeAfterLogSmallAndCommit),
01088     Case("log small item and commit2",                  test_logSmallAndCommit<0x11>),
01089     Case("initialize after small log and commit2",      test_initializeAfterLogSmallAndCommit),
01090     Case("log small item and commit3",                  test_logSmallAndCommit<0x22>),
01091     Case("initialize after small log and commit3",      test_initializeAfterLogSmallAndCommit),
01092     Case("log small item and commit4",                  test_logSmallAndCommit<0x55>),
01093     Case("initialize after small log and commit4",      test_initializeAfterLogSmallAndCommit),
01094     Case("log small item and commit5",                  test_logSmallAndCommit<0xAB>),
01095     Case("initialize after small log and commit5",      test_initializeAfterLogSmallAndCommit),
01096     Case("reset and initialize3",                       test_resetAndInitialize),
01097 
01098     Case("log large item without commit",               test_logLargeWithoutCommit),
01099 
01100     /* initialize, log large item, and reinitialize */
01101     Case("initialize2",                                 test_initialize),
01102     Case("reset and initialize4",                       test_resetAndInitialize),
01103     Case("log large item and commit1",                  test_logLargeAndCommit<0xAA>),
01104     Case("initialize after large log and commit1",      test_initializeAfterLogLargeAndCommit),
01105     Case("log large item and commit2",                  test_logLargeAndCommit<0x55>),
01106     Case("initialize after large log and commit2",      test_initializeAfterLogLargeAndCommit),
01107     Case("log large item and commit3",                  test_logLargeAndCommit<0x11>),
01108     Case("initialize after large log and commit3",      test_initializeAfterLogLargeAndCommit),
01109     Case("log large item and commit4",                  test_logLargeAndCommit<0xAB>),
01110     Case("initialize after large log and commit4",      test_initializeAfterLogLargeAndCommit),
01111     Case("log large item and commit5",                  test_logLargeAndCommit<0x22>),
01112     Case("initialize after large log and commit5",      test_initializeAfterLogLargeAndCommit),
01113     Case("reset and initialize5",                       test_resetAndInitialize),
01114 
01115     Case("log large item and read smaller chunks",      test_logLargeAndReadSmallChunks<0xAA>),
01116     Case("read large item in small, odd-sized chunks1", test_readLargeInSmallOddChunks<0xAA, ((BUFFER_SIZE / 2) - 1)>),
01117     Case("read large item in small, odd-sized chunks2", test_readLargeInSmallOddChunks<0xAA, 255>),
01118     Case("read large item in small, odd-sized chunks3", test_readLargeInSmallOddChunks<0xAA, 1021>),
01119     Case("read large item in small, odd-sized chunks4", test_readLargeInSmallOddChunks<0xAA, 2401>),
01120 
01121     Case("log pattern",                                 test_logPattern<0x55>),
01122     Case("readFrom",                                    test_readFromInReverse<0x55, 255>),
01123     Case("readFrom",                                    test_readFromInReverse<0x55, 512>),
01124     Case("readFrom",                                    test_readFromInReverse<0x55, ((BUFFER_SIZE / 2) - 1)>),
01125     Case("readFrom",                                    test_readFromInReverse<0x55, BUFFER_SIZE>),
01126     Case("readFrom followed by sequential reads",       test_readFromFollowedByReads<0x55, 255>),
01127     Case("readFrom followed by sequential reads",       test_readFromFollowedByReads<0x55, 511>),
01128     Case("readFrom followed by sequential reads",       test_readFromFollowedByReads<0x55, 512>),
01129     Case("readFrom followed by sequential reads",       test_readFromFollowedByReads<0x55, 513>),
01130     Case("readFrom followed by sequential reads",       test_readFromFollowedByReads<0x55, 1024>),
01131 
01132     /* log odd-sized blocks which wouldn't align with program_unit at the tail */
01133     Case("initialize3",                                 test_initialize),
01134     Case("log odd-sized chunk",                         test_logSeveralOddSizedChunks<1, 1>),
01135     Case("log odd-sized chunk",                         test_logSeveralOddSizedChunks<101, 11>),
01136     Case("log odd-sized chunk",                         test_logSeveralOddSizedChunks<1217, 4>),
01137     Case("log odd-sized chunk",                         test_logSeveralOddSizedChunks<2402, 5>),
01138     Case("log odd-sized chunk",                         test_logSeveralOddSizedChunks<4803, 3>),
01139     Case("log odd-sized chunk",                         test_logSeveralOddSizedChunks<(BUFFER_SIZE-1), 7>),
01140 
01141     Case("initialize4",                                 test_initialize),
01142     Case("multiple writes, commit, multiple reads",     test_multipleWritesFollowedByCommitFollowedByMultipleReads),
01143 
01144     Case("failed small write followed by padded write", test_failedSmallWriteFollowedByPaddedWrite),
01145 
01146     Case("reset and initialize6",                       test_resetAndInitialize),
01147     Case("crc32",                                       test_crc32),
01148     // Case("uninitialize", test_uninitialize),
01149 };
01150 
01151 // Declare your test specification with a custom setup handler
01152 #ifndef AVOID_GREENTEA
01153 Specification specification(greentea_setup, cases);
01154 #else
01155 Specification specification(default_setup, cases);
01156 #endif
01157 
01158 int main(int argc, char** argv)
01159 {
01160     // Run the test specification
01161     Harness::run(specification);
01162 }