aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorGiovanni Di Sirio <gdisirio@gmail.com>2017-11-16 14:23:28 +0000
committerGiovanni Di Sirio <gdisirio@gmail.com>2017-11-16 14:23:28 +0000
commitd7ce59dc3cb5f1ea14807320ca7031f1e17e8f37 (patch)
treed867972d5ed03e7fb29c47a94b9e67c97c5b0835 /test
parent7037d2fa6cb8326a05852bf22062257dba0c5a48 (diff)
downloadChibiOS-d7ce59dc3cb5f1ea14807320ca7031f1e17e8f37.tar.gz
ChibiOS-d7ce59dc3cb5f1ea14807320ca7031f1e17e8f37.tar.bz2
ChibiOS-d7ce59dc3cb5f1ea14807320ca7031f1e17e8f37.zip
First MFS test sequence complete, starting debug.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@11017 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'test')
-rw-r--r--test/mfs/.cproject2
-rw-r--r--test/mfs/configuration.xml678
-rw-r--r--test/mfs/mfs_test.mk6
-rw-r--r--test/mfs/nil_test.mk9
-rw-r--r--test/mfs/source/test/mfs_test_root.c120
-rw-r--r--test/mfs/source/test/mfs_test_root.h64
-rw-r--r--test/mfs/source/test/mfs_test_sequence_001.c804
-rw-r--r--test/mfs/source/test/mfs_test_sequence_001.h27
8 files changed, 1363 insertions, 347 deletions
diff --git a/test/mfs/.cproject b/test/mfs/.cproject
index 896066e66..83bf700ca 100644
--- a/test/mfs/.cproject
+++ b/test/mfs/.cproject
@@ -36,8 +36,8 @@
</toolChain>
</folderInfo>
<sourceEntries>
- <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="source"/>
<entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="components"/>
+ <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="source"/>
</sourceEntries>
</configuration>
</storageModule>
diff --git a/test/mfs/configuration.xml b/test/mfs/configuration.xml
index 20f7362b7..3b8a2b56c 100644
--- a/test/mfs/configuration.xml
+++ b/test/mfs/configuration.xml
@@ -38,68 +38,77 @@
<value>mfs_</value>
</code_prefix>
<global_definitions>
- <value><![CDATA[#define TEST_SUITE_NAME "ChibiOS/HAL MFS Test Suite"
+ <value><![CDATA[#include "mfs.h"
-#define TEST_REPORT_HOOK_HEADER test_print_port_info();
+#define TEST_SUITE_NAME "ChibiOS/HAL MFS Test Suite"
-extern semaphore_t gsem1, gsem2;
-extern thread_reference_t gtr1;
-extern THD_WORKING_AREA(wa_test_support, 128);
+#define TEST_REPORT_HOOK_HEADER test_print_mfs_info();
-void test_print_port_info(void);
-THD_FUNCTION(test_support, arg);]]></value>
+extern const MFSConfig mfscfg1;
+extern MFSDriver mfs1;
+extern uint8_t mfs_buffer[512];
+
+flash_error_t bank_erase(mfs_bank_t bank);
+flash_error_t bank_verify_erased(mfs_bank_t bank);
+void test_print_mfs_info(void);]]></value>
</global_definitions>
<global_code>
- <value><![CDATA[void test_print_port_info(void) {
-
-#ifdef PORT_COMPILER_NAME
- test_print("*** Compiler: ");
- test_println(PORT_COMPILER_NAME);
-#endif
- test_print("*** Architecture: ");
- test_println(PORT_ARCHITECTURE_NAME);
-#ifdef PORT_CORE_VARIANT_NAME
- test_print("*** Core Variant: ");
- test_println(PORT_CORE_VARIANT_NAME);
-#endif
-#ifdef PORT_INFO
- test_print("*** Port Info: ");
- test_println(PORT_INFO);
-#endif
+ <value><![CDATA[#include "mfs.h"
+
+MFSDriver mfs1;
+uint8_t mfs_buffer[512];
+
+void test_print_mfs_info(void) {
+
+}
+
+flash_error_t bank_erase(mfs_bank_t bank) {
+ flash_sector_t sector, end;
+
+ if (bank == MFS_BANK_0) {
+ sector = mfscfg1.bank0_start;
+ end = mfscfg1.bank0_start + mfscfg1.bank0_sectors;
+ }
+ else {
+ sector = mfscfg1.bank1_start;
+ end = mfscfg1.bank1_start + mfscfg1.bank0_sectors;
+ }
+
+ while (sector < end) {
+ flash_error_t ferr;
+
+ ferr = flashStartEraseSector(mfscfg1.flashp, sector);
+ if (ferr != FLASH_NO_ERROR)
+ return ferr;
+ ferr = flashWaitErase(mfscfg1.flashp);
+ if (ferr != FLASH_NO_ERROR)
+ return ferr;
+ sector++;
+ }
+ return FLASH_NO_ERROR;
}
-semaphore_t gsem1, gsem2;
-thread_reference_t gtr1;
-
-/*
- * Support thread.
- */
-THD_WORKING_AREA(wa_test_support, 128);
-THD_FUNCTION(test_support, arg) {
-#if CH_CFG_USE_EVENTS == TRUE
- thread_t *tp = (thread_t *)arg;
-#else
- (void)arg;
-#endif
-
- /* Initializing global resources.*/
- chSemObjectInit(&gsem1, 0);
- chSemObjectInit(&gsem2, 0);
-
- while (true) {
- chSysLock();
- if (chSemGetCounterI(&gsem1) < 0)
- chSemSignalI(&gsem1);
- chSemResetI(&gsem2, 0);
- chThdResumeI(&gtr1, MSG_OK);
-#if CH_CFG_USE_EVENTS == TRUE
- chEvtSignalI(tp, 0x55);
-#endif
- chSchRescheduleS();
- chSysUnlock();
-
- chThdSleepMilliseconds(250);
+flash_error_t bank_verify_erased(mfs_bank_t bank) {
+ flash_sector_t sector, end;
+
+ if (bank == MFS_BANK_0) {
+ sector = mfscfg1.bank0_start;
+ end = mfscfg1.bank0_start + mfscfg1.bank0_sectors;
+ }
+ else {
+ sector = mfscfg1.bank1_start;
+ end = mfscfg1.bank1_start + mfscfg1.bank0_sectors;
+ }
+
+ while (sector < end) {
+ flash_error_t ferr;
+
+ ferr = flashVerifyErase(mfscfg1.flashp, sector);
+ if (ferr != FLASH_NO_ERROR)
+ return ferr;
+ sector++;
}
+ return FLASH_NO_ERROR;
}]]></value>
</global_code>
</global_data_and_code>
@@ -119,7 +128,7 @@ THD_FUNCTION(test_support, arg) {
</condition>
<shared_code>
<value><![CDATA[#include <string.h>
-#include "key_storage.h"
+#include "mfs.h"
static const uint8_t pattern1[] = {
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
@@ -172,7 +181,7 @@ static const uint8_t pattern512[] = {
<cases>
<case>
<brief>
- <value>Testing ksInit() behavior.</value>
+ <value>Testing mfsStart() behavior.</value>
</brief>
<description>
<value>The initialization function is tested. This function can fail only in case of Flash Array failures or in case of unexpected internal errors.</value>
@@ -182,10 +191,10 @@ static const uint8_t pattern512[] = {
</condition>
<various_code>
<setup_code>
- <value />
+ <value><![CDATA[mfsObjectInit(&mfs1);]]></value>
</setup_code>
<teardown_code>
- <value><![CDATA[ksDeinit();]]></value>
+ <value><![CDATA[mfsStop(&mfs1);]]></value>
</teardown_code>
<local_variables>
<value />
@@ -200,61 +209,60 @@ static const uint8_t pattern512[] = {
<value />
</tags>
<code>
- <value><![CDATA[bool result;
+ <value><![CDATA[flash_error_t ferr;
-ks_lld_init();
-result = ks_lld_block_erase(KS_BLOCK0);
-test_assert(!result, "Block 0 erase failure");
-result = ks_lld_block_erase(KS_BLOCK1);
-test_assert(!result, "Block 1 erase failure");]]></value>
+ferr = bank_erase(MFS_BANK_0);
+test_assert(ferr == FLASH_NO_ERROR, "Bank 0 erase failure");
+ferr = bank_erase(MFS_BANK_1);
+test_assert(ferr == FLASH_NO_ERROR, "Bank 1 erase failure");]]></value>
</code>
</step>
<step>
<description>
- <value>Calling ksInit() on an uninitialized flash array, KS_NOERROR is expected.</value>
+ <value>Calling mfsStart() on an uninitialized flash array, MFS_NO_ERROR is expected.</value>
</description>
<tags>
<value />
</tags>
<code>
- <value><![CDATA[kserror_t error;
+ <value><![CDATA[mfs_error_t err;
-error = ksInit();
-test_assert(error == KS_NOERROR, "initialization error with erased flash");]]></value>
+err = mfsStart(&mfs1, &mfscfg1);
+test_assert(err == MFS_NO_ERROR, "initialization error with erased flash");]]></value>
</code>
</step>
<step>
<description>
- <value>Calling ksInit() on a newly initialized flash array, KS_NOERROR is expected.</value>
+ <value>Calling mfsStart() on a newly initialized flash array, MFS_NO_ERROR is expected.</value>
</description>
<tags>
<value />
</tags>
<code>
- <value><![CDATA[kserror_t error;
+ <value><![CDATA[mfs_error_t err;
-error = ksInit();
-test_assert(error == KS_NOERROR, "initialization error with initialized flash");]]></value>
+err = mfsStart(&mfs1, &mfscfg1);
+test_assert(err == MFS_NO_ERROR, "initialization error with initialized flash");]]></value>
</code>
</step>
</steps>
</case>
<case>
<brief>
- <value>Checking for non existing keys.</value>
+ <value>Checking for non existing record.</value>
</brief>
<description>
- <value>The keys space is explored with an initialized but empty keys storage, no key should exist.</value>
+ <value>The records space is explored with an initialized but empty managed storage, no record should exist.</value>
</description>
<condition>
<value />
</condition>
<various_code>
<setup_code>
- <value><![CDATA[ksInit();]]></value>
+ <value><![CDATA[mfsStart(&mfs1, &mfscfg1);]]></value>
</setup_code>
<teardown_code>
- <value><![CDATA[ksDeinit();]]></value>
+ <value><![CDATA[mfsStop(&mfs1);]]></value>
</teardown_code>
<local_variables>
<value />
@@ -263,21 +271,21 @@ test_assert(error == KS_NOERROR, "initialization error with initialized flash");
<steps>
<step>
<description>
- <value>Exploring the keys space, KS_KEY_NOT_FOUND is expected for each key.</value>
+ <value>Exploring the records space, MFS_ERR_NOT_FOUND is expected for each index.</value>
</description>
<tags>
<value />
</tags>
<code>
- <value><![CDATA[kserror_t error;
-kskey_t key;
+ <value><![CDATA[mfs_error_t err;
+mfs_id_t id;
size_t size;
-uint8_t *keyp;
-for (key = 0; key < KS_CFG_NUM_KEYS; key++) {
- error = ksGetKey(key, &size, &keyp);
- test_assert(error == KS_KEY_NOT_FOUND,
- "found a key that should not exists");
+for (id = 1; id <= MFS_CFG_MAX_RECORDS; id++) {
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, id, &size, mfs_buffer);
+ test_assert(err == MFS_ERR_NOT_FOUND,
+ "found a record that should not exists");
}]]></value>
</code>
</step>
@@ -285,107 +293,92 @@ for (key = 0; key < KS_CFG_NUM_KEYS; key++) {
</case>
<case>
<brief>
- <value>Creating, updating and erasing a key.</value>
+ <value>Creating, updating and erasing a record.</value>
</brief>
<description>
- <value>A key is created, updated several times with different payloads and finally erased.</value>
+ <value>A record is created, updated several times with different payloads and finally erased.</value>
</description>
<condition>
<value />
</condition>
<various_code>
<setup_code>
- <value><![CDATA[ksInit();]]></value>
+ <value><![CDATA[mfsStart(&mfs1, &mfscfg1);]]></value>
</setup_code>
<teardown_code>
- <value><![CDATA[ksDeinit();]]></value>
+ <value><![CDATA[mfsStop(&mfs1);]]></value>
</teardown_code>
<local_variables>
- <value><![CDATA[size_t size;
-uint8_t *keyp;]]></value>
+ <value><![CDATA[size_t size;]]></value>
</local_variables>
</various_code>
<steps>
<step>
<description>
- <value>The key must not already exists, KS_KEY_NOT_FOUND is expected.</value>
+ <value>The record must not already exists, MFS_ERR_NOT_FOUND is expected.</value>
</description>
<tags>
<value />
</tags>
<code>
- <value><![CDATA[kserror_t error = ksGetKey(0, &size, &keyp);
-test_assert(error == KS_KEY_NOT_FOUND, "key was already present");]]></value>
+ <value><![CDATA[size = sizeof mfs_buffer;
+mfs_error_t err = mfsReadRecord(&mfs1, 1, &size, mfs_buffer);
+test_assert(err == MFS_ERR_NOT_FOUND , "record was already present");]]></value>
</code>
</step>
<step>
<description>
- <value>Creating the key then retrieving it again, KS_KEY_NOT_FOUND is expected, key content and size are compared with the original.</value>
+ <value>Creating the record then retrieving it again, MFS_ERR_NOT_FOUND is expected, record content and size are compared with the original.</value>
</description>
<tags>
<value />
</tags>
<code>
- <value><![CDATA[kserror_t error;
-
-error = ksWriteKey(0, sizeof(pattern1), pattern1);
-test_assert(error == KS_NOERROR, "error creating the key");
-error = ksGetKey(0, &size, &keyp);
-test_assert(error == KS_NOERROR, "key not found");
-test_assert(size == sizeof(pattern1), "unexpected key length");
-test_assert(memcmp(pattern1, keyp, size) == 0, "wrong key content");]]></value>
+ <value><![CDATA[mfs_error_t err;
+
+err = mfsWriteRecord(&mfs1, 1, sizeof pattern1, pattern1);
+test_assert(err == MFS_NO_ERROR, "error creating the record");
+size = sizeof mfs_buffer;
+err = mfsReadRecord(&mfs1, 1, &size, mfs_buffer);
+test_assert(err == MFS_NO_ERROR, "record not found");
+test_assert(size == sizeof pattern1, "unexpected record length");
+test_assert(memcmp(pattern1, mfs_buffer, size) == 0, "wrong record content");]]></value>
</code>
</step>
<step>
<description>
- <value>Updating the key then retrieving it again, KS_NOERROR is expected, key content and size are compared with the original.</value>
+ <value>Updating the record then retrieving it again, MFS_NO_ERROR is expected, record content and size are compared with the original.</value>
</description>
<tags>
<value />
</tags>
<code>
- <value><![CDATA[kserror_t error;
-
-error = ksWriteKey(0, sizeof(pattern2), pattern2);
-test_assert(error == KS_NOERROR, "error updating the key");
-error = ksGetKey(0, &size, &keyp);
-test_assert(error == KS_NOERROR, "key not found");
-test_assert(size == sizeof(pattern2), "unexpected key length");
-test_assert(memcmp(pattern2, keyp, size) == 0, "wrong key content");]]></value>
+ <value><![CDATA[mfs_error_t err;
+
+err = mfsWriteRecord(&mfs1, 1, sizeof pattern2, pattern2);
+test_assert(err == MFS_NO_ERROR, "error updating the record");
+size = sizeof mfs_buffer;
+err = mfsReadRecord(&mfs1, 1, &size, mfs_buffer);
+test_assert(err == MFS_NO_ERROR, "record not found");
+test_assert(size == sizeof pattern2, "unexpected record length");
+test_assert(memcmp(pattern2, mfs_buffer, size) == 0, "wrong record content");]]></value>
</code>
</step>
<step>
<description>
- <value>Updating the key again with an unaligned key size then retrieving it again, KS_NOERROR is expected, key content and size are compared with the original.</value>
+ <value>Erasing the record then trying to retrieve it again, MFS_NO_ERROR is expected on erase, MFS_ERR_NOT_FOUND is expected on retrieve.</value>
</description>
<tags>
<value />
</tags>
<code>
- <value><![CDATA[kserror_t error;
-
-error = ksWriteKey(0, sizeof(pattern3), pattern3);
-test_assert(error == KS_NOERROR, "error updating the key");
-error = ksGetKey(0, &size, &keyp);
-test_assert(error == KS_NOERROR, "key not found");
-test_assert(size == sizeof(pattern3), "unexpected key length");
-test_assert(memcmp(pattern3, keyp, size) == 0, "wrong key content");]]></value>
- </code>
- </step>
- <step>
- <description>
- <value>Erasing the key the then retrieving it, KS_NOERROR is expected on erase, KS_KEY_NOT_FOUND is expected on retrieve.</value>
- </description>
- <tags>
- <value />
- </tags>
- <code>
- <value><![CDATA[kserror_t error;
+ <value><![CDATA[mfs_error_t err;
-error = ksEraseKey(0);
-test_assert(error == KS_NOERROR, "error erasing the key");
-error = ksGetKey(0, &size, &keyp);
-test_assert(error == KS_KEY_NOT_FOUND, "key not erased");]]></value>
+err = mfsEraseRecord(&mfs1, 1);
+test_assert(err == MFS_NO_ERROR, "error erasing the record");
+size = sizeof mfs_buffer;
+err = mfsReadRecord(&mfs1, 1, &size, mfs_buffer);
+test_assert(err == MFS_ERR_NOT_FOUND, "record not erased");]]></value>
</code>
</step>
</steps>
@@ -395,19 +388,19 @@ test_assert(error == KS_KEY_NOT_FOUND, "key not erased");]]></value>
<value>Erasing the whole storage.</value>
</brief>
<description>
- <value>The key storage is erased and re-initialized.</value>
+ <value>The managed storage is erased and re-initialized.</value>
</description>
<condition>
<value />
</condition>
<various_code>
<setup_code>
- <value><![CDATA[ks_lld_block_erase(KS_BLOCK0);
-ks_lld_block_erase(KS_BLOCK1);
-ksInit();]]></value>
+ <value><![CDATA[bank_erase(MFS_BANK_0);
+bank_erase(MFS_BANK_1);
+mfsStart(&mfs1, &mfscfg1);]]></value>
</setup_code>
<teardown_code>
- <value><![CDATA[ksDeinit();]]></value>
+ <value><![CDATA[mfsStop(&mfs1);]]></value>
</teardown_code>
<local_variables>
<value />
@@ -416,42 +409,44 @@ ksInit();]]></value>
<steps>
<step>
<description>
- <value>Creating keys 0, 1 and 2, KS_NOERROR is expected.</value>
+ <value>Creating records 1, 2 and 3, MFS_NO_ERROR is expected.</value>
</description>
<tags>
<value />
</tags>
<code>
- <value><![CDATA[kserror_t error;
-
-error = ksWriteKey(0, sizeof(pattern1), pattern1);
-test_assert(error == KS_NOERROR, "error creating the key");
-error = ksWriteKey(1, sizeof(pattern2), pattern2);
-test_assert(error == KS_NOERROR, "error creating the key");
-error = ksWriteKey(2, sizeof(pattern3), pattern3);
-test_assert(error == KS_NOERROR, "error creating the key");]]></value>
+ <value><![CDATA[mfs_error_t err;
+
+err = mfsWriteRecord(&mfs1, 1, sizeof pattern1, pattern1);
+test_assert(err == MFS_NO_ERROR, "error creating record 1");
+err = mfsWriteRecord(&mfs1, 2, sizeof pattern2, pattern2);
+test_assert(err == MFS_NO_ERROR, "error creating record 2");
+err = mfsWriteRecord(&mfs1, 3, sizeof pattern3, pattern3);
+test_assert(err == MFS_NO_ERROR, "error creating record 3");]]></value>
</code>
</step>
<step>
<description>
- <value>Erasing storage and verify that the keys have been removed, KS_NOERROR is expected on erase, KS_KEY_NOT_FOUND is expected on retrieve.</value>
+ <value>Erasing storage and verify that the records have been removed, MFS_NO_ERROR is expected on erase, MFS_ERR_NOT_FOUND is expected on retrieve.</value>
</description>
<tags>
<value />
</tags>
<code>
- <value><![CDATA[kserror_t error;
+ <value><![CDATA[mfs_error_t err;
size_t size;
-uint8_t *keyp;
-
-error = ksErase();
-test_assert(error == KS_NOERROR, "storage erase error");
-error = ksGetKey(0, &size, &keyp);
-test_assert(error == KS_KEY_NOT_FOUND, "key 0 still present");
-error = ksGetKey(1, &size, &keyp);
-test_assert(error == KS_KEY_NOT_FOUND, "key 1 still present");
-error = ksGetKey(2, &size, &keyp);
-test_assert(error == KS_KEY_NOT_FOUND, "key 2 still present");]]></value>
+
+err = mfsErase(&mfs1);
+test_assert(err == MFS_NO_ERROR, "storage erase error");
+size = sizeof mfs_buffer;
+err = mfsReadRecord(&mfs1, 1, &size, mfs_buffer);
+test_assert(err == MFS_ERR_NOT_FOUND, "record 0 still present");
+size = sizeof mfs_buffer;
+err = mfsReadRecord(&mfs1, 2, &size, mfs_buffer);
+test_assert(err == MFS_ERR_NOT_FOUND, "record 1 still present");
+size = sizeof mfs_buffer;
+err = mfsReadRecord(&mfs1, 3, &size, mfs_buffer);
+test_assert(err == MFS_ERR_NOT_FOUND, "record 2 still present");]]></value>
</code>
</step>
</steps>
@@ -461,18 +456,18 @@ test_assert(error == KS_KEY_NOT_FOUND, "key 2 still present");]]></value>
<value>Testing storage size limit.</value>
</brief>
<description>
- <value>The storage is entirely filled with different keys and the final error is tested.</value>
+ <value>The storage is entirely filled with different records and the final error is tested.</value>
</description>
<condition>
<value />
</condition>
<various_code>
<setup_code>
- <value><![CDATA[ksInit();
-ksErase();]]></value>
+ <value><![CDATA[mfsStart(&mfs1, &mfscfg1);
+mfsErase(&mfs1);]]></value>
</setup_code>
<teardown_code>
- <value><![CDATA[ksDeinit();]]></value>
+ <value><![CDATA[mfsStop(&mfs1);]]></value>
</teardown_code>
<local_variables>
<value />
@@ -481,82 +476,86 @@ ksErase();]]></value>
<steps>
<step>
<description>
- <value>Filling up the storage by writing keys with increasing IDs, KS_NOERROR is expected.</value>
+ <value>Filling up the storage by writing records with increasing IDs, MFS_NO_ERROR is expected.</value>
</description>
<tags>
<value />
</tags>
<code>
- <value><![CDATA[kskey_t key;
-kskey_t kmax = (KS_LLD_BLOCKS_SIZE - sizeof(kskeyheader_t)) /
- (sizeof(kskeyheader_t) + sizeof(pattern512));
+ <value><![CDATA[mfs_id_t id;
+mfs_id_t id_max = (mfscfg1.bank_size - sizeof (mfs_bank_header_t)) /
+ (sizeof (mfs_data_header_t) + sizeof pattern512);
-for (key = 0; key < kmax; key++) {
- kserror_t error;
+for (id = 1; id <= id_max; id++) {
+ mfs_error_t err;
size_t size;
- uint8_t *keyp;
-
- error = ksWriteKey(key, sizeof(pattern512), pattern512);
- test_assert(error == KS_NOERROR, "error creating the key");
- error = ksGetKey(key, &size, &keyp);
- test_assert(error == KS_NOERROR, "key not found");
- test_assert(size == sizeof(pattern512), "unexpected key length");
- test_assert(memcmp(pattern512, keyp, size) == 0, "wrong key content");
+
+ err = mfsWriteRecord(&mfs1, id, sizeof pattern512, pattern512);
+ test_assert(err == MFS_NO_ERROR, "error creating the record");
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, id, &size, mfs_buffer);
+ test_assert(err == MFS_NO_ERROR,
+ "record not found");
+ test_assert(size == sizeof pattern512,
+ "unexpected record length");
+ test_assert(memcmp(pattern512, mfs_buffer, size) == 0,
+ "wrong record content");
}]]></value>
</code>
</step>
<step>
<description>
- <value>Creating one more key, should fail, KS_OUT_OF_MEM is expected.</value>
+ <value>Creating one more record, should fail, MFS_ERR_OUT_OF_MEM is expected.</value>
</description>
<tags>
<value />
</tags>
<code>
- <value><![CDATA[kserror_t error;
-kskey_t kmax = (KS_LLD_BLOCKS_SIZE - sizeof(kskeyheader_t)) /
- (sizeof(kskeyheader_t) + sizeof(pattern512));
+ <value><![CDATA[mfs_error_t err;
+mfs_id_t id_max = (mfscfg1.bank_size - sizeof (mfs_bank_header_t)) /
+ (sizeof (mfs_data_header_t) + sizeof pattern512);
-error = ksWriteKey(kmax, sizeof(pattern512), pattern512);
-test_assert(error == KS_OUT_OF_MEM, "creation didn't fail");]]></value>
+err = mfsWriteRecord(&mfs1, id_max, sizeof pattern512 , pattern512);
+test_assert(err == MFS_ERR_OUT_OF_MEM, "creation didn't fail");]]></value>
</code>
</step>
<step>
<description>
- <value>Adding a smaller key to fill the final gap. A reinitialization is performed and KS_NOERROR is expected.</value>
+ <value>Adding a smaller record to fill the final gap. A reinitialization is performed and MFS_NO_ERROR is expected.</value>
</description>
<tags>
<value />
</tags>
<code>
- <value><![CDATA[kserror_t error;
+ <value><![CDATA[mfs_error_t err;
size_t remaining;
-remaining = KS_LLD_BLOCK0_ADDRESS + KS_LLD_BLOCKS_SIZE - (size_t)ks.free_next;
-test_assert(remaining >= sizeof(kskeyheader_t), "not enough space");
-test_assert((remaining & KS_LLD_PAGE_SIZE) == 0, "unaligned space");
+remaining = (size_t)flashGetSectorOffset(mfscfg1.flashp, mfscfg1.bank0_start) +
+ (size_t)mfscfg1.bank_size - (size_t)mfs1.next_offset;
+test_assert(remaining >= sizeof (mfs_data_header_t), "not enough space");
-if (remaining > sizeof(kskeyheader_t) * 2) {
- error = ksWriteKey(KS_CFG_NUM_KEYS - 1,
- remaining - (sizeof(kskeyheader_t) * 2),
- pattern512);
- test_assert(error == KS_NOERROR, "error filling remaining space");
+if (remaining > sizeof (mfs_data_header_t) * 2U) {
+ err = mfsWriteRecord(&mfs1, MFS_CFG_MAX_RECORDS - 1U,
+ remaining - (sizeof (mfs_data_header_t) * 2U),
+ pattern512);
+ test_assert(err == MFS_NO_ERROR, "error filling remaining space");
}
else {
- if (remaining == sizeof(kskeyheader_t) * 2) {
- error = ksEraseKey(1);
- test_assert(error == KS_NOERROR, "error filling remaining space");
+ if (remaining == sizeof (mfs_data_header_t) * 2U) {
+ err = mfsEraseRecord(&mfs1, 2);
+ test_assert(err == MFS_NO_ERROR, "error filling remaining space");
}
- error = ksEraseKey(0);
- test_assert(error == KS_NOERROR, "error filling remaining space");
+ err = mfsEraseRecord(&mfs1, 1);
+ test_assert(err == MFS_NO_ERROR, "error filling remaining space");
}
-remaining = KS_LLD_BLOCK0_ADDRESS + KS_LLD_BLOCKS_SIZE - (size_t)ks.free_next;
-test_assert(remaining == 0, "remaining space not zero");
+remaining = (size_t)flashGetSectorOffset(mfscfg1.flashp, mfscfg1.bank0_start) +
+ (size_t)mfscfg1.bank_size - (size_t)mfs1.next_offset;
+test_assert(remaining == 0U, "remaining space not zero");
-ksDeinit();
-error = ksInit();
-test_assert(error == KS_NOERROR, "initialization error");]]></value>
+mfsStop(&mfs1);
+err = mfsStart(&mfs1, &mfscfg1);
+test_assert(err == MFS_NO_ERROR, "initialization error");]]></value>
</code>
</step>
</steps>
@@ -573,11 +572,11 @@ test_assert(error == KS_NOERROR, "initialization error");]]></value>
</condition>
<various_code>
<setup_code>
- <value><![CDATA[ksInit();
-ksErase();]]></value>
+ <value><![CDATA[mfsStart(&mfs1, &mfscfg1);
+mfsErase(&mfs1);]]></value>
</setup_code>
<teardown_code>
- <value><![CDATA[ksDeinit();]]></value>
+ <value><![CDATA[mfsStop(&mfs1);]]></value>
</teardown_code>
<local_variables>
<value />
@@ -586,170 +585,175 @@ ksErase();]]></value>
<steps>
<step>
<description>
- <value>Filling up the storage by writing keys with increasing IDs, KS_NOERROR is expected.</value>
+ <value>Filling up the storage by writing records with increasing IDs, MFS_NO_ERROR is expected.</value>
</description>
<tags>
<value />
</tags>
<code>
- <value><![CDATA[kskey_t key;
-kskey_t kmax = (KS_LLD_BLOCKS_SIZE - sizeof(kskeyheader_t)) /
- (sizeof(kskeyheader_t) + sizeof(pattern512));
+ <value><![CDATA[mfs_id_t id;
+mfs_id_t id_max = (mfscfg1.bank_size - sizeof (mfs_bank_header_t)) /
+ (sizeof (mfs_data_header_t) + sizeof pattern512);
-for (key = 0; key < kmax; key++) {
- kserror_t error;
+for (id = 1; id <= id_max; id++) {
+ mfs_error_t err;
size_t size;
- uint8_t *keyp;
-
- error = ksWriteKey(key, sizeof(pattern512), pattern512);
- test_assert(error == KS_NOERROR, "error creating the key");
- error = ksGetKey(key, &size, &keyp);
- test_assert(error == KS_NOERROR, "key not found");
- test_assert(size == sizeof(pattern512), "unexpected key length");
- test_assert(memcmp(pattern512, keyp, size) == 0, "wrong key content");
+
+ err = mfsWriteRecord(&mfs1, id, sizeof pattern512, pattern512);
+ test_assert(err == MFS_NO_ERROR, "error creating the record");
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, id, &size, mfs_buffer);
+ test_assert(err == MFS_NO_ERROR,
+ "record not found");
+ test_assert(size == sizeof pattern512,
+ "unexpected record length");
+ test_assert(memcmp(pattern512, mfs_buffer, size) == 0,
+ "wrong record content");
}]]></value>
</code>
</step>
<step>
<description>
- <value>Erasing one key in the middle, KS_NOERROR is expected.</value>
+ <value>Erasing one record in the middle, MFS_NO_ERROR is expected.</value>
</description>
<tags>
<value />
</tags>
<code>
- <value><![CDATA[kserror_t error;
+ <value><![CDATA[mfs_error_t err;
size_t size;
-uint8_t *keyp;
-error = ksEraseKey(16);
-test_assert(error == KS_NOERROR, "error erasing the key");
-error = ksGetKey(16, &size, &keyp);
-test_assert(error == KS_KEY_NOT_FOUND, "key not erased");]]></value>
+err = mfsEraseRecord(&mfs1, MFS_CFG_MAX_RECORDS / 2);
+test_assert(err == MFS_NO_ERROR, "error erasing the record");
+size = sizeof mfs_buffer;
+err = mfsReadRecord(&mfs1, MFS_CFG_MAX_RECORDS / 2, &size, mfs_buffer);
+test_assert(err == MFS_ERR_NOT_FOUND, "record not erased");]]></value>
</code>
</step>
<step>
<description>
- <value>Writing one more key triggers garbage collection, KS_WARNING is expected, KS state is checked for correctness after the operation.</value>
+ <value>Writing one more record triggers garbage collection, MFS_WARN_GC is expected, KS state is checked for correctness after the operation.</value>
</description>
<tags>
<value />
</tags>
<code>
- <value><![CDATA[kserror_t error;
+ <value><![CDATA[mfs_error_t err;
size_t size;
-uint8_t *keyp;
-
-test_assert(ks.header->fields.instance == 1, "not first instance");
-error = ksWriteKey(16, sizeof(pattern512), pattern512);
-test_assert(error == KS_WARNING, "error creating the key");
-test_assert(ks.header->fields.instance == 2, "not second instance");
-error = ksGetKey(16, &size, &keyp);
-test_assert(error == KS_NOERROR, "key not found");
-test_assert(size == sizeof(pattern512), "unexpected key length");
-test_assert(memcmp(pattern512, keyp, size) == 0, "wrong key content");
-test_assert(ks.block == KS_BLOCK1, "unexpected block");
-test_assert(ks_lld_is_block_erased(KS_BLOCK0) == true, "block 0 not erased");]]></value>
+
+test_assert(mfs1.current_counter == 1, "not first instance");
+err = mfsWriteRecord(&mfs1, 16, sizeof pattern512, pattern512);
+test_assert(err == MFS_WARN_GC, "error creating the record");
+test_assert(mfs1.current_counter == 2, "not second instance");
+size = sizeof mfs_buffer;
+err = mfsReadRecord(&mfs1, 16, &size, mfs_buffer);
+test_assert(err == MFS_NO_ERROR, "record not found");
+test_assert(size == sizeof pattern512, "unexpected record length");
+test_assert(memcmp(pattern512, mfs_buffer, size) == 0, "wrong record content");
+test_assert(mfs1.current_bank == MFS_BANK_1, "unexpected bank");
+test_assert(bank_verify_erased(MFS_BANK_0) == FLASH_NO_ERROR, "bank 0 not erased");]]></value>
</code>
</step>
<step>
<description>
- <value>Checking for all keys in the new bank, KS_NOERROR is expected for each key.</value>
+ <value>Checking for all records in the new bank, MFS_NOERROR is expected for each record.</value>
</description>
<tags>
<value />
</tags>
<code>
- <value><![CDATA[kskey_t key;
-kskey_t kmax = (KS_LLD_BLOCKS_SIZE - sizeof(kskeyheader_t)) /
- (sizeof(kskeyheader_t) + sizeof(pattern512));
+ <value><![CDATA[mfs_id_t id;
+mfs_id_t id_max = (mfscfg1.bank_size - sizeof (mfs_bank_header_t)) /
+ (sizeof (mfs_data_header_t) + sizeof pattern512);
-for (key = 0; key < KS_CFG_NUM_KEYS; key++) {
- kserror_t error;
+for (id = 1; id <= id_max; id++) {
+ mfs_error_t err;
size_t size;
- uint8_t *keyp;
- if (key < kmax) {
- error = ksGetKey(key, &size, &keyp);
- test_assert(error == KS_NOERROR, "key not found");
- test_assert(size == sizeof(pattern512), "unexpected key length");
- test_assert(memcmp(pattern512, keyp, size) == 0, "wrong key content");
+ if (id < id_max) {
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, id, &size, mfs_buffer);
+ test_assert(err == MFS_NO_ERROR, "record not found");
+ test_assert(size == sizeof pattern512, "unexpected record length");
+ test_assert(memcmp(pattern512, mfs_buffer, size) == 0, "wrong record content");
}
else {
- error = ksGetKey(key, &size, &keyp);
- test_assert(error == KS_KEY_NOT_FOUND, "found unexpected key");
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, id, &size, mfs_buffer);
+ test_assert(err == MFS_ERR_NOT_FOUND, "found unexpected record");
}
}]]></value>
</code>
</step>
<step>
<description>
- <value>Erasing one key in the middle, KS_NOERROR is expected.</value>
+ <value>Erasing one record in the middle, MFS_NO_ERROR is expected.</value>
</description>
<tags>
<value />
</tags>
<code>
- <value><![CDATA[kserror_t error;
+ <value><![CDATA[mfs_error_t err;
size_t size;
-uint8_t *keyp;
-error = ksEraseKey(16);
-test_assert(error == KS_NOERROR, "error erasing the key");
-error = ksGetKey(16, &size, &keyp);
-test_assert(error == KS_KEY_NOT_FOUND, "key not erased");]]></value>
+err = mfsEraseRecord(&mfs1, MFS_CFG_MAX_RECORDS / 2);
+test_assert(err == MFS_NO_ERROR, "error erasing the record");
+size = sizeof mfs_buffer;
+err = mfsReadRecord(&mfs1, MFS_CFG_MAX_RECORDS / 2, &size, mfs_buffer);
+test_assert(err == MFS_ERR_NOT_FOUND, "record not erased");]]></value>
</code>
</step>
<step>
<description>
- <value>Writing one more key triggers garbage collection, KS_WARNING is expected, KS state is checked for correctness after the operation.</value>
+ <value>Writing one more record triggers garbage collection, MFS_WARN_GC is expected, MFS object state is checked for correctness after the operation.</value>
</description>
<tags>
<value />
</tags>
<code>
- <value><![CDATA[kserror_t error;
+ <value><![CDATA[mfs_error_t err;
size_t size;
-uint8_t *keyp;
-
-test_assert(ks.header->fields.instance == 2, "not second instance");
-error = ksWriteKey(16, sizeof(pattern512), pattern512);
-test_assert(error == KS_WARNING, "error creating the key");
-test_assert(ks.header->fields.instance == 3, "not third instance");
-error = ksGetKey(16, &size, &keyp);
-test_assert(error == KS_NOERROR, "key not found");
-test_assert(size == sizeof(pattern512), "unexpected key length");
-test_assert(memcmp(pattern512, keyp, size) == 0, "wrong key content");
-test_assert(ks.block == KS_BLOCK0, "unexpected block");
-test_assert(ks_lld_is_block_erased(KS_BLOCK1) == true, "block 0 not erased");]]></value>
+
+test_assert(mfs1.current_counter == 2, "not second instance");
+err = mfsWriteRecord(&mfs1, MFS_CFG_MAX_RECORDS / 2, sizeof pattern512, pattern512);
+test_assert(err == MFS_WARN_GC, "error creating the record");
+test_assert(mfs1.current_counter == 3, "not third instance");
+size = sizeof mfs_buffer;
+err = mfsReadRecord(&mfs1, MFS_CFG_MAX_RECORDS / 2, &size, mfs_buffer);
+test_assert(err == MFS_NO_ERROR, "record not found");
+test_assert(size == sizeof pattern512, "unexpected record length");
+test_assert(memcmp(pattern512, mfs_buffer, size) == 0, "wrong record content");
+test_assert(mfs1.current_bank == MFS_BANK_0, "unexpected bank");
+test_assert(bank_verify_erased(MFS_BANK_1) == FLASH_NO_ERROR, "bank 1 not erased");]]></value>
</code>
</step>
<step>
<description>
- <value>Checking for all keys in the new bank, KS_NOERROR is expected for each key.</value>
+ <value>Checking for all records in the new bank, MFS_NO_ERROR is expected for each key.</value>
</description>
<tags>
<value />
</tags>
<code>
- <value><![CDATA[kskey_t key;
-kskey_t kmax = (KS_LLD_BLOCKS_SIZE - sizeof(kskeyheader_t)) /
- (sizeof(kskeyheader_t) + sizeof(pattern512));
+ <value><![CDATA[mfs_id_t id;
+mfs_id_t id_max = (mfscfg1.bank_size - sizeof (mfs_bank_header_t)) /
+ (sizeof (mfs_data_header_t) + sizeof pattern512);
-for (key = 0; key < KS_CFG_NUM_KEYS; key++) {
- kserror_t error;
+for (id = 1; id <= MFS_CFG_MAX_RECORDS; id++) {
+ mfs_error_t err;
size_t size;
- uint8_t *keyp;
- if (key < kmax) {
- error = ksGetKey(key, &size, &keyp);
- test_assert(error == KS_NOERROR, "key not found");
- test_assert(size == sizeof(pattern512), "unexpected key length");
- test_assert(memcmp(pattern512, keyp, size) == 0, "wrong key content");
+ if (id < id_max) {
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, id, &size, mfs_buffer);
+ test_assert(err == MFS_NO_ERROR, "record not found");
+ test_assert(size == sizeof pattern512, "unexpected record length");
+ test_assert(memcmp(pattern512, mfs_buffer, size) == 0, "wrong record content");
}
else {
- error = ksGetKey(key, &size, &keyp);
- test_assert(error == KS_KEY_NOT_FOUND, "found unexpected key");
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, id, &size, mfs_buffer);
+ test_assert(err == MFS_ERR_NOT_FOUND, "found unexpected record");
}
}]]></value>
</code>
@@ -761,18 +765,18 @@ for (key = 0; key < KS_CFG_NUM_KEYS; key++) {
<value>Testing garbage collection by erasing</value>
</brief>
<description>
- <value>The garbage collection procedure is triggeredby an erase operation and the state of both banks is checked.</value>
+ <value>The garbage collection procedure is triggered by an erase operation and the state of both banks is checked.</value>
</description>
<condition>
<value />
</condition>
<various_code>
<setup_code>
- <value><![CDATA[ksInit();
-ksErase();]]></value>
+ <value><![CDATA[mfsStart(&mfs1, &mfscfg1);
+mfsErase(&mfs1);]]></value>
</setup_code>
<teardown_code>
- <value><![CDATA[ksDeinit();]]></value>
+ <value><![CDATA[mfsStop(&mfs1);]]></value>
</teardown_code>
<local_variables>
<value />
@@ -781,76 +785,76 @@ ksErase();]]></value>
<steps>
<step>
<description>
- <value>Filling up the storage by writing keys with increasing IDs, KS_NOERROR is expected.</value>
+ <value>Filling up the storage by writing records with increasing IDs, MFS_NO_ERROR is expected.</value>
</description>
<tags>
<value />
</tags>
<code>
- <value><![CDATA[kskey_t key;
-kskey_t kmax = (KS_LLD_BLOCKS_SIZE - sizeof(kskeyheader_t)) /
- (sizeof(kskeyheader_t) + sizeof(pattern512));
+ <value><![CDATA[mfs_id_t id;
+mfs_id_t id_max = (mfscfg1.bank_size - sizeof (mfs_bank_header_t)) /
+ (sizeof (mfs_data_header_t) + sizeof pattern512);
-for (key = 0; key < kmax; key++) {
- kserror_t error;
+for (id = 1; id <= id_max; id++) {
+ mfs_error_t err;
size_t size;
- uint8_t *keyp;
-
- error = ksWriteKey(key, sizeof(pattern512), pattern512);
- test_assert(error == KS_NOERROR, "error creating the key");
- error = ksGetKey(key, &size, &keyp);
- test_assert(error == KS_NOERROR, "key not found");
- test_assert(size == sizeof(pattern512), "unexpected key length");
- test_assert(memcmp(pattern512, keyp, size) == 0, "wrong key content");
+
+ err = mfsWriteRecord(&mfs1, id, sizeof pattern512, pattern512);
+ test_assert(err == MFS_NO_ERROR, "error creating the record");
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, id, &size, mfs_buffer);
+ test_assert(err == MFS_NO_ERROR, "record not found");
+ test_assert(size == sizeof pattern512, "unexpected record length");
+ test_assert(memcmp(pattern512, mfs_buffer, size) == 0, "wrong record content");
}]]></value>
</code>
</step>
<step>
<description>
- <value>Erase keys until the flash bank is filled entirely.</value>
+ <value>Erase records until the flash bank is filled entirely.</value>
</description>
<tags>
<value />
</tags>
<code>
- <value><![CDATA[kserror_t error;
+ <value><![CDATA[mfs_error_t err;
size_t size;
-uint8_t *keyp;
-kskey_t key;
-kskey_t kmax = (KS_LLD_BLOCKS_SIZE - sizeof(kskeyheader_t)) /
- (sizeof(kskeyheader_t) + sizeof(pattern512));
-kskey_t n = ((KS_LLD_BLOCKS_SIZE - sizeof(kskeyheader_t)) -
- (kmax * (sizeof(kskeyheader_t) + sizeof(pattern512)))) /
- sizeof(kskeyheader_t);
-
-for (key = 0; key < n; key++) {
- error = ksEraseKey(key);
- test_assert(error == KS_NOERROR, "error erasing the key");
- error = ksGetKey(key, &size, &keyp);
- test_assert(error == KS_KEY_NOT_FOUND, "key not erased");
+mfs_id_t id;
+mfs_id_t id_max = (mfscfg1.bank_size - sizeof (mfs_bank_header_t)) /
+ (sizeof (mfs_data_header_t) + sizeof pattern512);
+mfs_id_t n = ((mfscfg1.bank_size - sizeof (mfs_bank_header_t)) -
+ (id_max * (sizeof (mfs_data_header_t) + sizeof pattern512))) /
+ sizeof (mfs_data_header_t);
+
+for (id = 1; id <= n; id++) {
+ err = mfsEraseRecord(&mfs1, id);
+ test_assert(err == MFS_NO_ERROR, "error erasing the record");
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, id, &size, mfs_buffer);
+ test_assert(err == MFS_ERR_NOT_FOUND, "record not erased");
}]]></value>
</code>
</step>
<step>
<description>
- <value>Erasing one more key triggers garbage collection, KS_WARNING is expected, KS state is checked for correctness after the operation.</value>
+ <value>Erasing one more record triggers garbage collection, MFS_WARN_GC is expected, KS state is checked for correctness after the operation.</value>
</description>
<tags>
<value />
</tags>
<code>
- <value><![CDATA[kserror_t error;
+ <value><![CDATA[mfs_error_t err;
size_t size;
-uint8_t *keyp;
-
-test_assert(ks.header->fields.instance == 1, "not first instance");
-error = ksEraseKey(16);
-test_assert(error == KS_WARNING, "error erasing the key");
-test_assert(ks.header->fields.instance == 2, "not second instance");
-error = ksGetKey(16, &size, &keyp);
-test_assert(error == KS_KEY_NOT_FOUND, "key not erased");
-test_assert(ks.block == KS_BLOCK1, "unexpected block");
-test_assert(ks_lld_is_block_erased(KS_BLOCK0) == true, "block 0 not erased");]]></value>
+
+test_assert(mfs1.current_counter == 1, "not first instance");
+err = mfsEraseRecord(&mfs1, MFS_CFG_MAX_RECORDS / 2);
+test_assert(err == MFS_WARN_GC, "error erasing the record");
+test_assert(mfs1.current_counter == 2, "not second instance");
+size = sizeof mfs_buffer;
+err = mfsReadRecord(&mfs1, MFS_CFG_MAX_RECORDS / 2, &size, mfs_buffer);
+test_assert(err == MFS_ERR_NOT_FOUND, "record not erased");
+test_assert(mfs1.current_bank == MFS_BANK_1, "unexpected bank");
+test_assert(bank_verify_erased(MFS_BANK_0) == FLASH_NO_ERROR, "bank 0 not erased");]]></value>
</code>
</step>
</steps>
diff --git a/test/mfs/mfs_test.mk b/test/mfs/mfs_test.mk
new file mode 100644
index 000000000..fda8965c3
--- /dev/null
+++ b/test/mfs/mfs_test.mk
@@ -0,0 +1,6 @@
+# List of all the ChibiOS/HAL MFS test files.
+TESTSRC += ${CHIBIOS}/test/mfs/source/test/mfs_test_root.c \
+ ${CHIBIOS}/test/mfs/source/test/mfs_test_sequence_001.c
+
+# Required include directories
+TESTINC += ${CHIBIOS}/test/mfs/source/test
diff --git a/test/mfs/nil_test.mk b/test/mfs/nil_test.mk
deleted file mode 100644
index c49541d73..000000000
--- a/test/mfs/nil_test.mk
+++ /dev/null
@@ -1,9 +0,0 @@
-# List of all the ChibiOS/NIL test files.
-TESTSRC += ${CHIBIOS}/test/nil/source/test/nil_test_root.c \
- ${CHIBIOS}/test/nil/source/test/nil_test_sequence_001.c \
- ${CHIBIOS}/test/nil/source/test/nil_test_sequence_002.c \
- ${CHIBIOS}/test/nil/source/test/nil_test_sequence_003.c \
- ${CHIBIOS}/test/nil/source/test/nil_test_sequence_004.c
-
-# Required include directories
-TESTINC += ${CHIBIOS}/test/nil/source/test
diff --git a/test/mfs/source/test/mfs_test_root.c b/test/mfs/source/test/mfs_test_root.c
new file mode 100644
index 000000000..39a5d472b
--- /dev/null
+++ b/test/mfs/source/test/mfs_test_root.c
@@ -0,0 +1,120 @@
+/*
+ ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @mainpage Test Suite Specification
+ * Test suite for ChibiOS/HAL MFS. The purpose of this suite is to
+ * perform unit tests on the MFS module and to converge to 100% code
+ * coverage through successive improvements.
+ *
+ * <h2>Test Sequences</h2>
+ * - @subpage mfs_test_sequence_001
+ * .
+ */
+
+/**
+ * @file mfs_test_root.c
+ * @brief Test Suite root structures code.
+ */
+
+#include "hal.h"
+#include "mfs_test_root.h"
+
+#if !defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* Module exported variables. */
+/*===========================================================================*/
+
+/**
+ * @brief Array of test sequences.
+ */
+const testsequence_t * const mfs_test_suite_array[] = {
+ &mfs_test_sequence_001,
+ NULL
+};
+
+/**
+ * @brief Test suite root structure.
+ */
+const testsuite_t mfs_test_suite = {
+ "ChibiOS/HAL MFS Test Suite",
+ mfs_test_suite_array
+};
+
+/*===========================================================================*/
+/* Shared code. */
+/*===========================================================================*/
+
+#include "mfs.h"
+
+MFSDriver mfs1;
+uint8_t mfs_buffer[512];
+
+void test_print_mfs_info(void) {
+
+}
+
+flash_error_t bank_erase(mfs_bank_t bank) {
+ flash_sector_t sector, end;
+
+ if (bank == MFS_BANK_0) {
+ sector = mfscfg1.bank0_start;
+ end = mfscfg1.bank0_start + mfscfg1.bank0_sectors;
+ }
+ else {
+ sector = mfscfg1.bank1_start;
+ end = mfscfg1.bank1_start + mfscfg1.bank0_sectors;
+ }
+
+ while (sector < end) {
+ flash_error_t ferr;
+
+ ferr = flashStartEraseSector(mfscfg1.flashp, sector);
+ if (ferr != FLASH_NO_ERROR)
+ return ferr;
+ ferr = flashWaitErase(mfscfg1.flashp);
+ if (ferr != FLASH_NO_ERROR)
+ return ferr;
+ sector++;
+ }
+ return FLASH_NO_ERROR;
+}
+
+flash_error_t bank_verify_erased(mfs_bank_t bank) {
+ flash_sector_t sector, end;
+
+ if (bank == MFS_BANK_0) {
+ sector = mfscfg1.bank0_start;
+ end = mfscfg1.bank0_start + mfscfg1.bank0_sectors;
+ }
+ else {
+ sector = mfscfg1.bank1_start;
+ end = mfscfg1.bank1_start + mfscfg1.bank0_sectors;
+ }
+
+ while (sector < end) {
+ flash_error_t ferr;
+
+ ferr = flashVerifyErase(mfscfg1.flashp, sector);
+ if (ferr != FLASH_NO_ERROR)
+ return ferr;
+ sector++;
+ }
+ return FLASH_NO_ERROR;
+}
+
+#endif /* !defined(__DOXYGEN__) */
diff --git a/test/mfs/source/test/mfs_test_root.h b/test/mfs/source/test/mfs_test_root.h
new file mode 100644
index 000000000..18c12ee8f
--- /dev/null
+++ b/test/mfs/source/test/mfs_test_root.h
@@ -0,0 +1,64 @@
+/*
+ ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file mfs_test_root.h
+ * @brief Test Suite root structures header.
+ */
+
+#ifndef MFS_TEST_ROOT_H
+#define MFS_TEST_ROOT_H
+
+#include "ch_test.h"
+
+#include "mfs_test_sequence_001.h"
+
+#if !defined(__DOXYGEN__)
+
+/*===========================================================================*/
+/* External declarations. */
+/*===========================================================================*/
+
+extern const testsuite_t mfs_test_suite;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#ifdef __cplusplus
+}
+#endif
+
+/*===========================================================================*/
+/* Shared definitions. */
+/*===========================================================================*/
+
+#include "mfs.h"
+
+#define TEST_SUITE_NAME "ChibiOS/HAL MFS Test Suite"
+
+#define TEST_REPORT_HOOK_HEADER test_print_mfs_info();
+
+extern const MFSConfig mfscfg1;
+extern MFSDriver mfs1;
+extern uint8_t mfs_buffer[512];
+
+flash_error_t bank_erase(mfs_bank_t bank);
+flash_error_t bank_verify_erased(mfs_bank_t bank);
+void test_print_mfs_info(void);
+
+#endif /* !defined(__DOXYGEN__) */
+
+#endif /* MFS_TEST_ROOT_H */
diff --git a/test/mfs/source/test/mfs_test_sequence_001.c b/test/mfs/source/test/mfs_test_sequence_001.c
new file mode 100644
index 000000000..5ff4e7958
--- /dev/null
+++ b/test/mfs/source/test/mfs_test_sequence_001.c
@@ -0,0 +1,804 @@
+/*
+ ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+#include "hal.h"
+#include "mfs_test_root.h"
+
+/**
+ * @file mfs_test_sequence_001.c
+ * @brief Test Sequence 001 code.
+ *
+ * @page mfs_test_sequence_001 [1] Functional tests
+ *
+ * File: @ref mfs_test_sequence_001.c
+ *
+ * <h2>Description</h2>
+ * The APIs are tested for functionality, correct cases and expected
+ * error cases are tested.
+ *
+ * <h2>Test Cases</h2>
+ * - @subpage mfs_test_001_001
+ * - @subpage mfs_test_001_002
+ * - @subpage mfs_test_001_003
+ * - @subpage mfs_test_001_004
+ * - @subpage mfs_test_001_005
+ * - @subpage mfs_test_001_006
+ * - @subpage mfs_test_001_007
+ * .
+ */
+
+/****************************************************************************
+ * Shared code.
+ ****************************************************************************/
+
+#include <string.h>
+#include "mfs.h"
+
+static const uint8_t pattern1[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
+};
+
+static const uint8_t pattern2[] = {
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47
+};
+
+static const uint8_t pattern3[] = {
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57
+};
+
+static const uint8_t pattern512[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63
+};
+
+/****************************************************************************
+ * Test cases.
+ ****************************************************************************/
+
+/**
+ * @page mfs_test_001_001 [1.1] Testing mfsStart() behavior
+ *
+ * <h2>Description</h2>
+ * The initialization function is tested. This function can fail only
+ * in case of Flash Array failures or in case of unexpected internal
+ * errors.
+ *
+ * <h2>Test Steps</h2>
+ * - [1.1.1] Erasing the flash array using a low level function.
+ * - [1.1.2] Calling mfsStart() on an uninitialized flash array,
+ * MFS_NO_ERROR is expected.
+ * - [1.1.3] Calling mfsStart() on a newly initialized flash array,
+ * MFS_NO_ERROR is expected.
+ * .
+ */
+
+static void mfs_test_001_001_setup(void) {
+ mfsObjectInit(&mfs1);
+}
+
+static void mfs_test_001_001_teardown(void) {
+ mfsStop(&mfs1);
+}
+
+static void mfs_test_001_001_execute(void) {
+
+ /* [1.1.1] Erasing the flash array using a low level function.*/
+ test_set_step(1);
+ {
+ flash_error_t ferr;
+
+ ferr = bank_erase(MFS_BANK_0);
+ test_assert(ferr == FLASH_NO_ERROR, "Bank 0 erase failure");
+ ferr = bank_erase(MFS_BANK_1);
+ test_assert(ferr == FLASH_NO_ERROR, "Bank 1 erase failure");
+ }
+
+ /* [1.1.2] Calling mfsStart() on an uninitialized flash array,
+ MFS_NO_ERROR is expected.*/
+ test_set_step(2);
+ {
+ mfs_error_t err;
+
+ err = mfsStart(&mfs1, &mfscfg1);
+ test_assert(err == MFS_NO_ERROR, "initialization error with erased flash");
+ }
+
+ /* [1.1.3] Calling mfsStart() on a newly initialized flash array,
+ MFS_NO_ERROR is expected.*/
+ test_set_step(3);
+ {
+ mfs_error_t err;
+
+ err = mfsStart(&mfs1, &mfscfg1);
+ test_assert(err == MFS_NO_ERROR, "initialization error with initialized flash");
+ }
+}
+
+static const testcase_t mfs_test_001_001 = {
+ "Testing mfsStart() behavior",
+ mfs_test_001_001_setup,
+ mfs_test_001_001_teardown,
+ mfs_test_001_001_execute
+};
+
+/**
+ * @page mfs_test_001_002 [1.2] Checking for non existing record
+ *
+ * <h2>Description</h2>
+ * The records space is explored with an initialized but empty managed
+ * storage, no record should exist.
+ *
+ * <h2>Test Steps</h2>
+ * - [1.2.1] Exploring the records space, MFS_ERR_NOT_FOUND is expected
+ * for each index.
+ * .
+ */
+
+static void mfs_test_001_002_setup(void) {
+ mfsStart(&mfs1, &mfscfg1);
+}
+
+static void mfs_test_001_002_teardown(void) {
+ mfsStop(&mfs1);
+}
+
+static void mfs_test_001_002_execute(void) {
+
+ /* [1.2.1] Exploring the records space, MFS_ERR_NOT_FOUND is expected
+ for each index.*/
+ test_set_step(1);
+ {
+ mfs_error_t err;
+ mfs_id_t id;
+ size_t size;
+
+ for (id = 1; id <= MFS_CFG_MAX_RECORDS; id++) {
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, id, &size, mfs_buffer);
+ test_assert(err == MFS_ERR_NOT_FOUND,
+ "found a record that should not exists");
+ }
+ }
+}
+
+static const testcase_t mfs_test_001_002 = {
+ "Checking for non existing record",
+ mfs_test_001_002_setup,
+ mfs_test_001_002_teardown,
+ mfs_test_001_002_execute
+};
+
+/**
+ * @page mfs_test_001_003 [1.3] Creating, updating and erasing a record
+ *
+ * <h2>Description</h2>
+ * A record is created, updated several times with different payloads
+ * and finally erased.
+ *
+ * <h2>Test Steps</h2>
+ * - [1.3.1] The record must not already exists, MFS_ERR_NOT_FOUND is
+ * expected.
+ * - [1.3.2] Creating the record then retrieving it again,
+ * MFS_ERR_NOT_FOUND is expected, record content and size are
+ * compared with the original.
+ * - [1.3.3] Updating the record then retrieving it again, MFS_NO_ERROR
+ * is expected, record content and size are compared with the
+ * original.
+ * - [1.3.4] Erasing the record then trying to retrieve it again,
+ * MFS_NO_ERROR is expected on erase, MFS_ERR_NOT_FOUND is expected
+ * on retrieve.
+ * .
+ */
+
+static void mfs_test_001_003_setup(void) {
+ mfsStart(&mfs1, &mfscfg1);
+}
+
+static void mfs_test_001_003_teardown(void) {
+ mfsStop(&mfs1);
+}
+
+static void mfs_test_001_003_execute(void) {
+ size_t size;
+
+ /* [1.3.1] The record must not already exists, MFS_ERR_NOT_FOUND is
+ expected.*/
+ test_set_step(1);
+ {
+ size = sizeof mfs_buffer;
+ mfs_error_t err = mfsReadRecord(&mfs1, 1, &size, mfs_buffer);
+ test_assert(err == MFS_ERR_NOT_FOUND , "record was already present");
+ }
+
+ /* [1.3.2] Creating the record then retrieving it again,
+ MFS_ERR_NOT_FOUND is expected, record content and size are
+ compared with the original.*/
+ test_set_step(2);
+ {
+ mfs_error_t err;
+
+ err = mfsWriteRecord(&mfs1, 1, sizeof pattern1, pattern1);
+ test_assert(err == MFS_NO_ERROR, "error creating the record");
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, 1, &size, mfs_buffer);
+ test_assert(err == MFS_NO_ERROR, "record not found");
+ test_assert(size == sizeof pattern1, "unexpected record length");
+ test_assert(memcmp(pattern1, mfs_buffer, size) == 0, "wrong record content");
+ }
+
+ /* [1.3.3] Updating the record then retrieving it again, MFS_NO_ERROR
+ is expected, record content and size are compared with the
+ original.*/
+ test_set_step(3);
+ {
+ mfs_error_t err;
+
+ err = mfsWriteRecord(&mfs1, 1, sizeof pattern2, pattern2);
+ test_assert(err == MFS_NO_ERROR, "error updating the record");
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, 1, &size, mfs_buffer);
+ test_assert(err == MFS_NO_ERROR, "record not found");
+ test_assert(size == sizeof pattern2, "unexpected record length");
+ test_assert(memcmp(pattern2, mfs_buffer, size) == 0, "wrong record content");
+ }
+
+ /* [1.3.4] Erasing the record then trying to retrieve it again,
+ MFS_NO_ERROR is expected on erase, MFS_ERR_NOT_FOUND is expected
+ on retrieve.*/
+ test_set_step(4);
+ {
+ mfs_error_t err;
+
+ err = mfsEraseRecord(&mfs1, 1);
+ test_assert(err == MFS_NO_ERROR, "error erasing the record");
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, 1, &size, mfs_buffer);
+ test_assert(err == MFS_ERR_NOT_FOUND, "record not erased");
+ }
+}
+
+static const testcase_t mfs_test_001_003 = {
+ "Creating, updating and erasing a record",
+ mfs_test_001_003_setup,
+ mfs_test_001_003_teardown,
+ mfs_test_001_003_execute
+};
+
+/**
+ * @page mfs_test_001_004 [1.4] Erasing the whole storage
+ *
+ * <h2>Description</h2>
+ * The managed storage is erased and re-initialized.
+ *
+ * <h2>Test Steps</h2>
+ * - [1.4.1] Creating records 1, 2 and 3, MFS_NO_ERROR is expected.
+ * - [1.4.2] Erasing storage and verify that the records have been
+ * removed, MFS_NO_ERROR is expected on erase, MFS_ERR_NOT_FOUND is
+ * expected on retrieve.
+ * .
+ */
+
+static void mfs_test_001_004_setup(void) {
+ bank_erase(MFS_BANK_0);
+ bank_erase(MFS_BANK_1);
+ mfsStart(&mfs1, &mfscfg1);
+}
+
+static void mfs_test_001_004_teardown(void) {
+ mfsStop(&mfs1);
+}
+
+static void mfs_test_001_004_execute(void) {
+
+ /* [1.4.1] Creating records 1, 2 and 3, MFS_NO_ERROR is expected.*/
+ test_set_step(1);
+ {
+ mfs_error_t err;
+
+ err = mfsWriteRecord(&mfs1, 1, sizeof pattern1, pattern1);
+ test_assert(err == MFS_NO_ERROR, "error creating record 1");
+ err = mfsWriteRecord(&mfs1, 2, sizeof pattern2, pattern2);
+ test_assert(err == MFS_NO_ERROR, "error creating record 2");
+ err = mfsWriteRecord(&mfs1, 3, sizeof pattern3, pattern3);
+ test_assert(err == MFS_NO_ERROR, "error creating record 3");
+ }
+
+ /* [1.4.2] Erasing storage and verify that the records have been
+ removed, MFS_NO_ERROR is expected on erase, MFS_ERR_NOT_FOUND is
+ expected on retrieve.*/
+ test_set_step(2);
+ {
+ mfs_error_t err;
+ size_t size;
+
+ err = mfsErase(&mfs1);
+ test_assert(err == MFS_NO_ERROR, "storage erase error");
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, 1, &size, mfs_buffer);
+ test_assert(err == MFS_ERR_NOT_FOUND, "record 0 still present");
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, 2, &size, mfs_buffer);
+ test_assert(err == MFS_ERR_NOT_FOUND, "record 1 still present");
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, 3, &size, mfs_buffer);
+ test_assert(err == MFS_ERR_NOT_FOUND, "record 2 still present");
+ }
+}
+
+static const testcase_t mfs_test_001_004 = {
+ "Erasing the whole storage",
+ mfs_test_001_004_setup,
+ mfs_test_001_004_teardown,
+ mfs_test_001_004_execute
+};
+
+/**
+ * @page mfs_test_001_005 [1.5] Testing storage size limit
+ *
+ * <h2>Description</h2>
+ * The storage is entirely filled with different records and the final
+ * error is tested.
+ *
+ * <h2>Test Steps</h2>
+ * - [1.5.1] Filling up the storage by writing records with increasing
+ * IDs, MFS_NO_ERROR is expected.
+ * - [1.5.2] Creating one more record, should fail, MFS_ERR_OUT_OF_MEM
+ * is expected.
+ * - [1.5.3] Adding a smaller record to fill the final gap. A
+ * reinitialization is performed and MFS_NO_ERROR is expected.
+ * .
+ */
+
+static void mfs_test_001_005_setup(void) {
+ mfsStart(&mfs1, &mfscfg1);
+ mfsErase(&mfs1);
+}
+
+static void mfs_test_001_005_teardown(void) {
+ mfsStop(&mfs1);
+}
+
+static void mfs_test_001_005_execute(void) {
+
+ /* [1.5.1] Filling up the storage by writing records with increasing
+ IDs, MFS_NO_ERROR is expected.*/
+ test_set_step(1);
+ {
+ mfs_id_t id;
+ mfs_id_t id_max = (mfscfg1.bank_size - sizeof (mfs_bank_header_t)) /
+ (sizeof (mfs_data_header_t) + sizeof pattern512);
+
+ for (id = 1; id <= id_max; id++) {
+ mfs_error_t err;
+ size_t size;
+
+ err = mfsWriteRecord(&mfs1, id, sizeof pattern512, pattern512);
+ test_assert(err == MFS_NO_ERROR, "error creating the record");
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, id, &size, mfs_buffer);
+ test_assert(err == MFS_NO_ERROR,
+ "record not found");
+ test_assert(size == sizeof pattern512,
+ "unexpected record length");
+ test_assert(memcmp(pattern512, mfs_buffer, size) == 0,
+ "wrong record content");
+ }
+ }
+
+ /* [1.5.2] Creating one more record, should fail, MFS_ERR_OUT_OF_MEM
+ is expected.*/
+ test_set_step(2);
+ {
+ mfs_error_t err;
+ mfs_id_t id_max = (mfscfg1.bank_size - sizeof (mfs_bank_header_t)) /
+ (sizeof (mfs_data_header_t) + sizeof pattern512);
+
+ err = mfsWriteRecord(&mfs1, id_max, sizeof pattern512 , pattern512);
+ test_assert(err == MFS_ERR_OUT_OF_MEM, "creation didn't fail");
+ }
+
+ /* [1.5.3] Adding a smaller record to fill the final gap. A
+ reinitialization is performed and MFS_NO_ERROR is expected.*/
+ test_set_step(3);
+ {
+ mfs_error_t err;
+ size_t remaining;
+
+ remaining = (size_t)flashGetSectorOffset(mfscfg1.flashp, mfscfg1.bank0_start) +
+ (size_t)mfscfg1.bank_size - (size_t)mfs1.next_offset;
+ test_assert(remaining >= sizeof (mfs_data_header_t), "not enough space");
+
+ if (remaining > sizeof (mfs_data_header_t) * 2U) {
+ err = mfsWriteRecord(&mfs1, MFS_CFG_MAX_RECORDS - 1U,
+ remaining - (sizeof (mfs_data_header_t) * 2U),
+ pattern512);
+ test_assert(err == MFS_NO_ERROR, "error filling remaining space");
+ }
+ else {
+ if (remaining == sizeof (mfs_data_header_t) * 2U) {
+ err = mfsEraseRecord(&mfs1, 2);
+ test_assert(err == MFS_NO_ERROR, "error filling remaining space");
+ }
+ err = mfsEraseRecord(&mfs1, 1);
+ test_assert(err == MFS_NO_ERROR, "error filling remaining space");
+ }
+
+ remaining = (size_t)flashGetSectorOffset(mfscfg1.flashp, mfscfg1.bank0_start) +
+ (size_t)mfscfg1.bank_size - (size_t)mfs1.next_offset;
+ test_assert(remaining == 0U, "remaining space not zero");
+
+ mfsStop(&mfs1);
+ err = mfsStart(&mfs1, &mfscfg1);
+ test_assert(err == MFS_NO_ERROR, "initialization error");
+ }
+}
+
+static const testcase_t mfs_test_001_005 = {
+ "Testing storage size limit",
+ mfs_test_001_005_setup,
+ mfs_test_001_005_teardown,
+ mfs_test_001_005_execute
+};
+
+/**
+ * @page mfs_test_001_006 [1.6] Testing garbage collection by writing
+ *
+ * <h2>Description</h2>
+ * The garbage collection procedure is triggeredby a write operation
+ * and the state of both banks is checked.
+ *
+ * <h2>Test Steps</h2>
+ * - [1.6.1] Filling up the storage by writing records with increasing
+ * IDs, MFS_NO_ERROR is expected.
+ * - [1.6.2] Erasing one record in the middle, MFS_NO_ERROR is
+ * expected.
+ * - [1.6.3] Writing one more record triggers garbage collection,
+ * MFS_WARN_GC is expected, KS state is checked for correctness after
+ * the operation.
+ * - [1.6.4] Checking for all records in the new bank, MFS_NOERROR is
+ * expected for each record.
+ * - [1.6.5] Erasing one record in the middle, MFS_NO_ERROR is
+ * expected.
+ * - [1.6.6] Writing one more record triggers garbage collection,
+ * MFS_WARN_GC is expected, MFS object state is checked for
+ * correctness after the operation.
+ * - [1.6.7] Checking for all records in the new bank, MFS_NO_ERROR is
+ * expected for each key.
+ * .
+ */
+
+static void mfs_test_001_006_setup(void) {
+ mfsStart(&mfs1, &mfscfg1);
+ mfsErase(&mfs1);
+}
+
+static void mfs_test_001_006_teardown(void) {
+ mfsStop(&mfs1);
+}
+
+static void mfs_test_001_006_execute(void) {
+
+ /* [1.6.1] Filling up the storage by writing records with increasing
+ IDs, MFS_NO_ERROR is expected.*/
+ test_set_step(1);
+ {
+ mfs_id_t id;
+ mfs_id_t id_max = (mfscfg1.bank_size - sizeof (mfs_bank_header_t)) /
+ (sizeof (mfs_data_header_t) + sizeof pattern512);
+
+ for (id = 1; id <= id_max; id++) {
+ mfs_error_t err;
+ size_t size;
+
+ err = mfsWriteRecord(&mfs1, id, sizeof pattern512, pattern512);
+ test_assert(err == MFS_NO_ERROR, "error creating the record");
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, id, &size, mfs_buffer);
+ test_assert(err == MFS_NO_ERROR,
+ "record not found");
+ test_assert(size == sizeof pattern512,
+ "unexpected record length");
+ test_assert(memcmp(pattern512, mfs_buffer, size) == 0,
+ "wrong record content");
+ }
+ }
+
+ /* [1.6.2] Erasing one record in the middle, MFS_NO_ERROR is
+ expected.*/
+ test_set_step(2);
+ {
+ mfs_error_t err;
+ size_t size;
+
+ err = mfsEraseRecord(&mfs1, MFS_CFG_MAX_RECORDS / 2);
+ test_assert(err == MFS_NO_ERROR, "error erasing the record");
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, MFS_CFG_MAX_RECORDS / 2, &size, mfs_buffer);
+ test_assert(err == MFS_ERR_NOT_FOUND, "record not erased");
+ }
+
+ /* [1.6.3] Writing one more record triggers garbage collection,
+ MFS_WARN_GC is expected, KS state is checked for correctness after
+ the operation.*/
+ test_set_step(3);
+ {
+ mfs_error_t err;
+ size_t size;
+
+ test_assert(mfs1.current_counter == 1, "not first instance");
+ err = mfsWriteRecord(&mfs1, 16, sizeof pattern512, pattern512);
+ test_assert(err == MFS_WARN_GC, "error creating the record");
+ test_assert(mfs1.current_counter == 2, "not second instance");
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, 16, &size, mfs_buffer);
+ test_assert(err == MFS_NO_ERROR, "record not found");
+ test_assert(size == sizeof pattern512, "unexpected record length");
+ test_assert(memcmp(pattern512, mfs_buffer, size) == 0, "wrong record content");
+ test_assert(mfs1.current_bank == MFS_BANK_1, "unexpected bank");
+ test_assert(bank_verify_erased(MFS_BANK_0) == FLASH_NO_ERROR, "bank 0 not erased");
+ }
+
+ /* [1.6.4] Checking for all records in the new bank, MFS_NOERROR is
+ expected for each record.*/
+ test_set_step(4);
+ {
+ mfs_id_t id;
+ mfs_id_t id_max = (mfscfg1.bank_size - sizeof (mfs_bank_header_t)) /
+ (sizeof (mfs_data_header_t) + sizeof pattern512);
+
+ for (id = 1; id <= id_max; id++) {
+ mfs_error_t err;
+ size_t size;
+
+ if (id < id_max) {
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, id, &size, mfs_buffer);
+ test_assert(err == MFS_NO_ERROR, "record not found");
+ test_assert(size == sizeof pattern512, "unexpected record length");
+ test_assert(memcmp(pattern512, mfs_buffer, size) == 0, "wrong record content");
+ }
+ else {
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, id, &size, mfs_buffer);
+ test_assert(err == MFS_ERR_NOT_FOUND, "found unexpected record");
+ }
+ }
+ }
+
+ /* [1.6.5] Erasing one record in the middle, MFS_NO_ERROR is
+ expected.*/
+ test_set_step(5);
+ {
+ mfs_error_t err;
+ size_t size;
+
+ err = mfsEraseRecord(&mfs1, MFS_CFG_MAX_RECORDS / 2);
+ test_assert(err == MFS_NO_ERROR, "error erasing the record");
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, MFS_CFG_MAX_RECORDS / 2, &size, mfs_buffer);
+ test_assert(err == MFS_ERR_NOT_FOUND, "record not erased");
+ }
+
+ /* [1.6.6] Writing one more record triggers garbage collection,
+ MFS_WARN_GC is expected, MFS object state is checked for
+ correctness after the operation.*/
+ test_set_step(6);
+ {
+ mfs_error_t err;
+ size_t size;
+
+ test_assert(mfs1.current_counter == 2, "not second instance");
+ err = mfsWriteRecord(&mfs1, MFS_CFG_MAX_RECORDS / 2, sizeof pattern512, pattern512);
+ test_assert(err == MFS_WARN_GC, "error creating the record");
+ test_assert(mfs1.current_counter == 3, "not third instance");
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, MFS_CFG_MAX_RECORDS / 2, &size, mfs_buffer);
+ test_assert(err == MFS_NO_ERROR, "record not found");
+ test_assert(size == sizeof pattern512, "unexpected record length");
+ test_assert(memcmp(pattern512, mfs_buffer, size) == 0, "wrong record content");
+ test_assert(mfs1.current_bank == MFS_BANK_0, "unexpected bank");
+ test_assert(bank_verify_erased(MFS_BANK_1) == FLASH_NO_ERROR, "bank 1 not erased");
+ }
+
+ /* [1.6.7] Checking for all records in the new bank, MFS_NO_ERROR is
+ expected for each key.*/
+ test_set_step(7);
+ {
+ mfs_id_t id;
+ mfs_id_t id_max = (mfscfg1.bank_size - sizeof (mfs_bank_header_t)) /
+ (sizeof (mfs_data_header_t) + sizeof pattern512);
+
+ for (id = 1; id <= MFS_CFG_MAX_RECORDS; id++) {
+ mfs_error_t err;
+ size_t size;
+
+ if (id < id_max) {
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, id, &size, mfs_buffer);
+ test_assert(err == MFS_NO_ERROR, "record not found");
+ test_assert(size == sizeof pattern512, "unexpected record length");
+ test_assert(memcmp(pattern512, mfs_buffer, size) == 0, "wrong record content");
+ }
+ else {
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, id, &size, mfs_buffer);
+ test_assert(err == MFS_ERR_NOT_FOUND, "found unexpected record");
+ }
+ }
+ }
+}
+
+static const testcase_t mfs_test_001_006 = {
+ "Testing garbage collection by writing",
+ mfs_test_001_006_setup,
+ mfs_test_001_006_teardown,
+ mfs_test_001_006_execute
+};
+
+/**
+ * @page mfs_test_001_007 [1.7] Testing garbage collection by erasing
+ *
+ * <h2>Description</h2>
+ * The garbage collection procedure is triggered by an erase operation
+ * and the state of both banks is checked.
+ *
+ * <h2>Test Steps</h2>
+ * - [1.7.1] Filling up the storage by writing records with increasing
+ * IDs, MFS_NO_ERROR is expected.
+ * - [1.7.2] Erase records until the flash bank is filled entirely.
+ * - [1.7.3] Erasing one more record triggers garbage collection,
+ * MFS_WARN_GC is expected, KS state is checked for correctness after
+ * the operation.
+ * .
+ */
+
+static void mfs_test_001_007_setup(void) {
+ mfsStart(&mfs1, &mfscfg1);
+ mfsErase(&mfs1);
+}
+
+static void mfs_test_001_007_teardown(void) {
+ mfsStop(&mfs1);
+}
+
+static void mfs_test_001_007_execute(void) {
+
+ /* [1.7.1] Filling up the storage by writing records with increasing
+ IDs, MFS_NO_ERROR is expected.*/
+ test_set_step(1);
+ {
+ mfs_id_t id;
+ mfs_id_t id_max = (mfscfg1.bank_size - sizeof (mfs_bank_header_t)) /
+ (sizeof (mfs_data_header_t) + sizeof pattern512);
+
+ for (id = 1; id <= id_max; id++) {
+ mfs_error_t err;
+ size_t size;
+
+ err = mfsWriteRecord(&mfs1, id, sizeof pattern512, pattern512);
+ test_assert(err == MFS_NO_ERROR, "error creating the record");
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, id, &size, mfs_buffer);
+ test_assert(err == MFS_NO_ERROR, "record not found");
+ test_assert(size == sizeof pattern512, "unexpected record length");
+ test_assert(memcmp(pattern512, mfs_buffer, size) == 0, "wrong record content");
+ }
+ }
+
+ /* [1.7.2] Erase records until the flash bank is filled entirely.*/
+ test_set_step(2);
+ {
+ mfs_error_t err;
+ size_t size;
+ mfs_id_t id;
+ mfs_id_t id_max = (mfscfg1.bank_size - sizeof (mfs_bank_header_t)) /
+ (sizeof (mfs_data_header_t) + sizeof pattern512);
+ mfs_id_t n = ((mfscfg1.bank_size - sizeof (mfs_bank_header_t)) -
+ (id_max * (sizeof (mfs_data_header_t) + sizeof pattern512))) /
+ sizeof (mfs_data_header_t);
+
+ for (id = 1; id <= n; id++) {
+ err = mfsEraseRecord(&mfs1, id);
+ test_assert(err == MFS_NO_ERROR, "error erasing the record");
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, id, &size, mfs_buffer);
+ test_assert(err == MFS_ERR_NOT_FOUND, "record not erased");
+ }
+ }
+
+ /* [1.7.3] Erasing one more record triggers garbage collection,
+ MFS_WARN_GC is expected, KS state is checked for correctness after
+ the operation.*/
+ test_set_step(3);
+ {
+ mfs_error_t err;
+ size_t size;
+
+ test_assert(mfs1.current_counter == 1, "not first instance");
+ err = mfsEraseRecord(&mfs1, MFS_CFG_MAX_RECORDS / 2);
+ test_assert(err == MFS_WARN_GC, "error erasing the record");
+ test_assert(mfs1.current_counter == 2, "not second instance");
+ size = sizeof mfs_buffer;
+ err = mfsReadRecord(&mfs1, MFS_CFG_MAX_RECORDS / 2, &size, mfs_buffer);
+ test_assert(err == MFS_ERR_NOT_FOUND, "record not erased");
+ test_assert(mfs1.current_bank == MFS_BANK_1, "unexpected bank");
+ test_assert(bank_verify_erased(MFS_BANK_0) == FLASH_NO_ERROR, "bank 0 not erased");
+ }
+}
+
+static const testcase_t mfs_test_001_007 = {
+ "Testing garbage collection by erasing",
+ mfs_test_001_007_setup,
+ mfs_test_001_007_teardown,
+ mfs_test_001_007_execute
+};
+
+/****************************************************************************
+ * Exported data.
+ ****************************************************************************/
+
+/**
+ * @brief Array of test cases.
+ */
+const testcase_t * const mfs_test_sequence_001_array[] = {
+ &mfs_test_001_001,
+ &mfs_test_001_002,
+ &mfs_test_001_003,
+ &mfs_test_001_004,
+ &mfs_test_001_005,
+ &mfs_test_001_006,
+ &mfs_test_001_007,
+ NULL
+};
+
+/**
+ * @brief Functional tests.
+ */
+const testsequence_t mfs_test_sequence_001 = {
+ "Functional tests",
+ mfs_test_sequence_001_array
+};
diff --git a/test/mfs/source/test/mfs_test_sequence_001.h b/test/mfs/source/test/mfs_test_sequence_001.h
new file mode 100644
index 000000000..6ace5d9c9
--- /dev/null
+++ b/test/mfs/source/test/mfs_test_sequence_001.h
@@ -0,0 +1,27 @@
+/*
+ ChibiOS - Copyright (C) 2006..2017 Giovanni Di Sirio
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+*/
+
+/**
+ * @file mfs_test_sequence_001.h
+ * @brief Test Sequence 001 header.
+ */
+
+#ifndef MFS_TEST_SEQUENCE_001_H
+#define MFS_TEST_SEQUENCE_001_H
+
+extern const testsequence_t mfs_test_sequence_001;
+
+#endif /* MFS_TEST_SEQUENCE_001_H */