Skip to content

Commit 3bdb80f

Browse files
authored
Merge pull request #9 from c1728p9/resilience_and_wear_leveling
Add filesystem recovery tests
2 parents 7eaf61c + 2d374ce commit 3bdb80f

File tree

12 files changed

+1802
-0
lines changed

12 files changed

+1802
-0
lines changed
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2017-2017 ARM Limited
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy
5+
* of this software and associated documentation files (the "Software"), to deal
6+
* in the Software without restriction, including without limitation the rights
7+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
* copies of the Software, and to permit persons to whom the Software is
9+
* furnished to do so, subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in
12+
* all copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
* SOFTWARE.
21+
*/
22+
23+
#include "mbed.h"
24+
#include "unity.h"
25+
#include "utest.h"
26+
#include "test_env.h"
27+
28+
#include "atomic_usage.h"
29+
#include "ObservingBlockDevice.h"
30+
#include "LittleFileSystem.h"
31+
32+
33+
using namespace utest::v1;
34+
35+
#define TEST_CYCLES 10
36+
#define TEST_BD_SIZE (16 * 1024)
37+
38+
/**
39+
* Check that the filesystem is valid after every change
40+
*
41+
* This test is to ensure that littlefs contains a valid filesystem at
42+
* all times. This property is required for handling unexpected power
43+
* loss.
44+
*/
45+
void test_resilience()
46+
{
47+
HeapBlockDevice bd(TEST_BD_SIZE);
48+
49+
// Setup the test
50+
setup_atomic_operations(&bd, true);
51+
52+
// Run check on every write operation
53+
ObservingBlockDevice observer(&bd);
54+
observer.attach(check_atomic_operations);
55+
56+
// Perform operations
57+
printf("Performing %i operations on flash\n", TEST_CYCLES);
58+
for (int i = 1; i <= TEST_CYCLES; i++) {
59+
int64_t ret = perform_atomic_operations(&observer);
60+
TEST_ASSERT_EQUAL(i, ret);
61+
}
62+
printf("No errors detected\n");
63+
}
64+
65+
Case cases[] = {
66+
Case("test resilience", test_resilience),
67+
};
68+
69+
utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
70+
{
71+
GREENTEA_SETUP(20, "default_auto");
72+
return greentea_test_setup_handler(number_of_cases);
73+
}
74+
75+
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
76+
77+
int main()
78+
{
79+
Harness::run(specification);
80+
}
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2017-2017 ARM Limited
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy
5+
* of this software and associated documentation files (the "Software"), to deal
6+
* in the Software without restriction, including without limitation the rights
7+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
* copies of the Software, and to permit persons to whom the Software is
9+
* furnished to do so, subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in
12+
* all copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
* SOFTWARE.
21+
*/
22+
23+
#include "mbed.h"
24+
#include "unity.h"
25+
#include "utest.h"
26+
#include "test_env.h"
27+
28+
#include "atomic_usage.h"
29+
#include "ObservingBlockDevice.h"
30+
#include "LittleFileSystem.h"
31+
32+
#include <string.h>
33+
34+
35+
using namespace utest::v1;
36+
37+
#ifndef MBED_TEST_BLOCKDEVICE
38+
#define MBED_TEST_BLOCKDEVICE SPIFBlockDevice
39+
#define MBED_TEST_BLOCKDEVICE_DECL SPIFBlockDevice bd(PTE2, PTE4, PTE1, PTE5)
40+
#endif
41+
42+
#ifndef MBED_TEST_BLOCKDEVICE_DECL
43+
#define MBED_TEST_BLOCKDEVICE_DECL MBED_TEST_BLOCKDEVICE bd
44+
#endif
45+
46+
// declarations
47+
#define STRINGIZE(x) STRINGIZE2(x)
48+
#define STRINGIZE2(x) #x
49+
#define INCLUDE(x) STRINGIZE(x.h)
50+
51+
#include INCLUDE(MBED_TEST_BLOCKDEVICE)
52+
53+
MBED_TEST_BLOCKDEVICE_DECL;
54+
55+
typedef enum {
56+
CMD_STATUS_PASS,
57+
CMD_STATUS_FAIL,
58+
CMD_STATUS_CONTINUE,
59+
CMD_STATUS_ERROR
60+
} cmd_status_t;
61+
62+
void use_filesystem()
63+
{
64+
// Perform operations
65+
while (true) {
66+
int64_t ret = perform_atomic_operations(&bd);
67+
TEST_ASSERT(ret > 0);
68+
}
69+
}
70+
71+
static cmd_status_t handle_command(const char *key, const char *value)
72+
{
73+
if (strcmp(key, "format") == 0) {
74+
setup_atomic_operations(&bd, true);
75+
greentea_send_kv("format_done", 1);
76+
return CMD_STATUS_CONTINUE;
77+
78+
} else if (strcmp(key, "run") == 0) {
79+
use_filesystem();
80+
return CMD_STATUS_CONTINUE;
81+
82+
} else if (strcmp(key, "exit") == 0) {
83+
if (strcmp(value, "pass") != 0) {
84+
return CMD_STATUS_FAIL;
85+
}
86+
check_atomic_operations(&bd);
87+
return CMD_STATUS_PASS;
88+
89+
} else {
90+
return CMD_STATUS_ERROR;
91+
92+
}
93+
}
94+
95+
int main()
96+
{
97+
GREENTEA_SETUP(60, "unexpected_reset");
98+
99+
static char _key[10 + 1] = {};
100+
static char _value[128 + 1] = {};
101+
102+
greentea_send_kv("start", 1);
103+
104+
// Handshake with host
105+
cmd_status_t cmd_status = CMD_STATUS_CONTINUE;
106+
while (CMD_STATUS_CONTINUE == cmd_status) {
107+
memset(_key, 0, sizeof(_key));
108+
memset(_value, 0, sizeof(_value));
109+
greentea_parse_kv(_key, _value, sizeof(_key) - 1, sizeof(_value) - 1);
110+
cmd_status = handle_command(_key, _value);
111+
}
112+
113+
GREENTEA_TESTSUITE_RESULT(CMD_STATUS_PASS == cmd_status);
114+
}
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/* mbed Microcontroller Library
2+
* Copyright (c) 2017-2017 ARM Limited
3+
*
4+
* Permission is hereby granted, free of charge, to any person obtaining a copy
5+
* of this software and associated documentation files (the "Software"), to deal
6+
* in the Software without restriction, including without limitation the rights
7+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8+
* copies of the Software, and to permit persons to whom the Software is
9+
* furnished to do so, subject to the following conditions:
10+
*
11+
* The above copyright notice and this permission notice shall be included in
12+
* all copies or substantial portions of the Software.
13+
*
14+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20+
* SOFTWARE.
21+
*/
22+
23+
#include "mbed.h"
24+
#include "unity.h"
25+
#include "utest.h"
26+
#include "test_env.h"
27+
28+
#include "atomic_usage.h"
29+
#include "ExhaustibleBlockDevice.h"
30+
#include "LittleFileSystem.h"
31+
32+
using namespace utest::v1;
33+
34+
#define ERASE_CYCLES 20
35+
#define TEST_BD_SIZE (8 * 1024)
36+
37+
static uint32_t test_wear_leveling_size(uint32_t bd_size)
38+
{
39+
HeapBlockDevice hbd(bd_size, 1, 1, 512);
40+
ExhaustibleBlockDevice ebd(&hbd, ERASE_CYCLES);
41+
42+
printf("Testing size %lu\n", bd_size);
43+
setup_atomic_operations(&ebd, true);
44+
45+
int64_t cycles = 0;
46+
while (true) {
47+
int64_t ret = perform_atomic_operations(&ebd);
48+
check_atomic_operations(&ebd);
49+
if (-1 == ret) {
50+
break;
51+
}
52+
cycles++;
53+
TEST_ASSERT_EQUAL(cycles, ret);
54+
55+
}
56+
57+
printf(" Simulated flash lasted %lli cylces\n", cycles);
58+
return cycles;
59+
}
60+
61+
/**
62+
* Check that storage life is proportional to storage size
63+
*
64+
* This test is to ensure that littlefs is properly handling wear
65+
* leveling. It does this by creating a simulated flash block device
66+
* which can be worn out and then using it until it is exhausted.
67+
* It then doubles the size of the block device and runs the same
68+
* test. If the block device with twice the size lasts at least
69+
* twice as long then the test passes.
70+
*/
71+
void test_wear_leveling()
72+
{
73+
uint32_t cycles_1 = test_wear_leveling_size(TEST_BD_SIZE * 1);
74+
uint32_t cycles_2 = test_wear_leveling_size(TEST_BD_SIZE * 2);
75+
TEST_ASSERT(cycles_2 > cycles_1 * 2);
76+
}
77+
78+
Case cases[] = {
79+
Case("test wear leveling", test_wear_leveling),
80+
};
81+
82+
utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
83+
{
84+
GREENTEA_SETUP(60, "default_auto");
85+
return greentea_test_setup_handler(number_of_cases);
86+
}
87+
88+
Specification specification(greentea_test_setup, cases, greentea_test_teardown_handler);
89+
90+
int main()
91+
{
92+
Harness::run(specification);
93+
}

TESTS/host_tests/unexpected_reset.py

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
"""
2+
mbed SDK
3+
Copyright (c) 2017-2017 ARM Limited
4+
5+
Licensed under the Apache License, Version 2.0 (the "License");
6+
you may not use this file except in compliance with the License.
7+
You may obtain a copy of the License at
8+
9+
http://www.apache.org/licenses/LICENSE-2.0
10+
11+
Unless required by applicable law or agreed to in writing, software
12+
distributed under the License is distributed on an "AS IS" BASIS,
13+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
See the License for the specific language governing permissions and
15+
limitations under the License.
16+
"""
17+
from __future__ import print_function
18+
19+
from mbed_host_tests import BaseHostTest
20+
from time import sleep
21+
22+
23+
class UnexpectedResetTest(BaseHostTest):
24+
"""This test checks that a device's RTC keeps count through a reset
25+
26+
It does this by setting the RTC's time, triggering a reset,
27+
delaying and then reading the RTC's time again to ensure
28+
that the RTC is still counting.
29+
"""
30+
31+
"""Number of times to reset the device in this test"""
32+
RESET_COUNT = 20
33+
RESET_DELAY_BASE = 1.0
34+
RESET_DELAY_INC = 0.02
35+
VALUE_PLACEHOLDER = "0"
36+
37+
def setup(self):
38+
"""Register callbacks required for the test"""
39+
self._error = False
40+
generator = self.unexpected_reset_test()
41+
generator.next()
42+
43+
def run_gen(key, value, time):
44+
"""Run the generator, and fail testing if the iterator stops"""
45+
if self._error:
46+
return
47+
try:
48+
generator.send((key, value, time))
49+
except StopIteration:
50+
self._error = True
51+
52+
for resp in ("start", "read", "format_done", "soft_reset_dut_complete"):
53+
self.register_callback(resp, run_gen)
54+
55+
def teardown(self):
56+
"""No work to do here"""
57+
pass
58+
59+
def unexpected_reset_test(self):
60+
"""Generator for running the reset test
61+
62+
This function calls yield to wait for the next event from
63+
the device. If the device gives the wrong response, then the
64+
generator terminates by returing which raises a StopIteration
65+
exception and fails the test.
66+
"""
67+
68+
# Wait for start token
69+
key, value, time = yield
70+
if key != "start":
71+
return
72+
73+
# Format the device before starting the test
74+
self.send_kv("format", self.VALUE_PLACEHOLDER)
75+
key, value, time = yield
76+
if key != "format_done":
77+
return
78+
79+
for i in range(self.RESET_COUNT):
80+
81+
self.send_kv("run", self.VALUE_PLACEHOLDER)
82+
sleep(self.RESET_DELAY_BASE + self.RESET_DELAY_INC * i)
83+
84+
self.reset()
85+
86+
# Wait for start token
87+
key, value, time = yield
88+
self.log("Key from yield: %s" % key)
89+
if key != "soft_reset_dut_complete":
90+
return
91+
92+
93+
self.send_kv("__sync", "00000000-0000-000000000-000000000000")
94+
95+
# Wait for start token
96+
key, value, time = yield
97+
if key != "start":
98+
return
99+
100+
self.send_kv("exit", "pass")
101+
102+
yield # No more events expected
103+

0 commit comments

Comments
 (0)