aboutsummaryrefslogtreecommitdiffstats
path: root/test/mfs/source
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/mfs/source
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/mfs/source')
-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
4 files changed, 1015 insertions, 0 deletions
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 */