Skip to content

Commit 6f18801

Browse files
authored
Merge pull request #11986 from ARMmbed/feature_storage_test_improvements
Storage related test improvements and small fixes
2 parents 4ae8984 + 0fe159f commit 6f18801

File tree

11 files changed

+286
-191
lines changed

11 files changed

+286
-191
lines changed
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
/* Copyright (c) 2019 ARM Limited
2+
* SPDX-License-Identifier: Apache-2.0
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "gtest/gtest.h"
18+
#include "features/storage/blockdevice/HeapBlockDevice.h"
19+
#include "features/storage/blockdevice/BufferedBlockDevice.h"
20+
21+
#define BLOCK_SIZE (512)
22+
#define DEVICE_SIZE (BLOCK_SIZE*10)
23+
24+
class BufferedBlockModuleTest : public testing::Test {
25+
protected:
26+
HeapBlockDevice bd_heap{DEVICE_SIZE};
27+
BufferedBlockDevice bd{&bd_heap};
28+
uint8_t *magic;
29+
uint8_t *buf;
30+
virtual void SetUp()
31+
{
32+
ASSERT_EQ(bd.init(), 0);
33+
magic = new uint8_t[BLOCK_SIZE];
34+
buf = new uint8_t[BLOCK_SIZE];
35+
// Generate simple pattern to verify against
36+
for (int i = 0; i < BLOCK_SIZE; i++) {
37+
magic[i] = 0xaa + i;
38+
}
39+
}
40+
41+
virtual void TearDown()
42+
{
43+
ASSERT_EQ(bd.deinit(), 0);
44+
delete[] magic;
45+
delete[] buf;
46+
}
47+
};
48+
49+
TEST_F(BufferedBlockModuleTest, init)
50+
{
51+
BufferedBlockDevice b(&bd_heap);
52+
EXPECT_EQ(b.get_erase_size(), 0);
53+
EXPECT_EQ(b.get_erase_size(0), 0);
54+
EXPECT_EQ(b.get_erase_value(), BD_ERROR_DEVICE_ERROR);
55+
EXPECT_EQ(b.size(), 0);
56+
57+
EXPECT_EQ(b.init(), 0);
58+
59+
EXPECT_EQ(b.get_erase_size(), bd_heap.get_erase_size());
60+
EXPECT_EQ(b.get_erase_size(0), bd_heap.get_erase_size(0));
61+
EXPECT_EQ(b.get_erase_value(), bd_heap.get_erase_value());
62+
EXPECT_EQ(b.get_program_size(), 1);
63+
EXPECT_EQ(b.get_read_size(), 1);
64+
EXPECT_EQ(b.size(), bd_heap.size());
65+
EXPECT_EQ(b.get_type(), bd_heap.get_type());
66+
}
67+
68+
TEST_F(BufferedBlockModuleTest, read_full_block)
69+
{
70+
bd_heap.program(magic, 0, BLOCK_SIZE);
71+
EXPECT_EQ(0, bd.read(buf, 0, BLOCK_SIZE));
72+
EXPECT_EQ(0, memcmp(magic, buf, BLOCK_SIZE));
73+
}
74+
75+
TEST_F(BufferedBlockModuleTest, over_read)
76+
{
77+
bd_heap.program(magic, DEVICE_SIZE - BLOCK_SIZE, BLOCK_SIZE);
78+
EXPECT_EQ(bd.read(buf, DEVICE_SIZE - BLOCK_SIZE, BLOCK_SIZE), 0);
79+
EXPECT_EQ(bd.read(buf, DEVICE_SIZE, BLOCK_SIZE), BD_ERROR_DEVICE_ERROR);
80+
}
81+
82+
TEST_F(BufferedBlockModuleTest, unalign_read)
83+
{
84+
bd_heap.program(magic, 0, BLOCK_SIZE);
85+
bd_heap.program(magic, BLOCK_SIZE, BLOCK_SIZE);
86+
EXPECT_EQ(bd.read(buf, BLOCK_SIZE/2, BLOCK_SIZE), 0);
87+
EXPECT_EQ(0, memcmp(buf, magic+(BLOCK_SIZE/2), BLOCK_SIZE/2));
88+
EXPECT_EQ(0, memcmp(magic, buf+(BLOCK_SIZE/2), BLOCK_SIZE/2));
89+
}
90+
91+
TEST_F(BufferedBlockModuleTest, align_big_read)
92+
{
93+
uint8_t *buffer = new uint8_t[BLOCK_SIZE*2];
94+
bd_heap.program(magic, 0, BLOCK_SIZE);
95+
bd_heap.program(magic, BLOCK_SIZE, BLOCK_SIZE);
96+
// Should cause 1 full block to be read unaligned from the device
97+
// second block would require buffering, because it is not a full (-1)
98+
EXPECT_EQ(bd.read(buffer, 0, (BLOCK_SIZE*2)-1), 0);
99+
EXPECT_EQ(0, memcmp(magic, buffer, BLOCK_SIZE));
100+
EXPECT_EQ(0, memcmp(magic, buffer+BLOCK_SIZE, BLOCK_SIZE-1));
101+
delete[] buffer;
102+
}
103+
104+
TEST_F(BufferedBlockModuleTest, program_small_chunks)
105+
{
106+
for (int i=0; i < BLOCK_SIZE - 1; ++i) {
107+
EXPECT_EQ(bd.program(magic+i, i, 1), 0);
108+
}
109+
EXPECT_EQ(bd.read(buf, 0, BLOCK_SIZE), 0);
110+
EXPECT_EQ(0, memcmp(buf, magic, BLOCK_SIZE - 1));
111+
}
112+
113+
TEST_F(BufferedBlockModuleTest, program_and_read_from_cache)
114+
{
115+
bd_heap.program(magic, 0, BLOCK_SIZE);
116+
EXPECT_EQ(bd.program("a", 0, 1), 0);
117+
EXPECT_EQ(bd.read(buf, 0, BLOCK_SIZE), 0);
118+
EXPECT_EQ('a', buf[0]);
119+
EXPECT_EQ(0, memcmp(buf+1, magic+1, BLOCK_SIZE-1));
120+
}
121+
122+
TEST_F(BufferedBlockModuleTest, program_and_verify_from_storage)
123+
{
124+
EXPECT_EQ(bd.program(magic, 0, BLOCK_SIZE/2), 0);
125+
EXPECT_EQ(bd.program(magic+BLOCK_SIZE/2, BLOCK_SIZE/2, BLOCK_SIZE/2), 0); // This should actually write to device
126+
EXPECT_EQ(bd.read(buf, 0, BLOCK_SIZE), 0);
127+
EXPECT_EQ(0, memcmp(buf, magic, BLOCK_SIZE));
128+
// Verify that data actually is in the underlying block device
129+
bd_heap.read(buf, 0, BLOCK_SIZE);
130+
EXPECT_EQ(0, memcmp(buf, magic, BLOCK_SIZE));
131+
}
132+
133+
TEST_F(BufferedBlockModuleTest, flush_automatically)
134+
{
135+
EXPECT_EQ(bd.program(magic, 0, BLOCK_SIZE/2), 0); // Don't write full block
136+
EXPECT_EQ(bd.program(magic, BLOCK_SIZE, BLOCK_SIZE/2), 0); // This should cause flush() for previous data in cache
137+
// Verify that data actually is in the underlying block device
138+
bd_heap.read(buf, 0, BLOCK_SIZE);
139+
EXPECT_EQ(0, memcmp(buf, magic, BLOCK_SIZE/2));
140+
}
141+
142+
TEST_F(BufferedBlockModuleTest, flush_at_exit)
143+
{
144+
bd_heap.init(); // Extra init, to prevent deinit() when BufferedBlockDevice de-inits.
145+
EXPECT_EQ(bd.program(magic, 0, BLOCK_SIZE/2), 0); // Don't write full block
146+
EXPECT_EQ(bd.deinit(), 0);
147+
// Verify that data actually is in the underlying block device
148+
EXPECT_EQ(bd_heap.read(buf, 0, BLOCK_SIZE), 0);
149+
EXPECT_EQ(0, memcmp(buf, magic, BLOCK_SIZE/2));
150+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
2+
####################
3+
# UNIT TESTS
4+
####################
5+
6+
set(unittest-includes ${unittest-includes}
7+
.
8+
..
9+
)
10+
11+
set(unittest-sources
12+
../features/storage/blockdevice/BufferedBlockDevice.cpp
13+
../features/storage/blockdevice/HeapBlockDevice.cpp
14+
stubs/mbed_atomic_stub.c
15+
stubs/mbed_assert_stub.cpp
16+
)
17+
18+
set(unittest-test-sources
19+
moduletests/storage/blockdevice/BufferedBlockDevice/moduletest.cpp
20+
)

UNITTESTS/moduletests/storage/blockdevice/SlicingBlockDevice/moduletest.cpp

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,14 +148,67 @@ TEST_F(SlicingBlockModuleTest, slice_at_the_end)
148148
TEST_F(SlicingBlockModuleTest, over_write)
149149
{
150150
uint8_t *program = new uint8_t[BLOCK_SIZE] {0xbb,0xbb,0xbb};
151+
uint8_t *buf = new uint8_t[BLOCK_SIZE];
151152

152153
//Screate sclicing device, with size of 2 blocks
153154
mbed::SlicingBlockDevice slice(&bd, BLOCK_SIZE, BLOCK_SIZE * 3);
154155
EXPECT_EQ(slice.init(), BD_ERROR_OK);
155156

156157
EXPECT_EQ(slice.program(program, 0, BLOCK_SIZE), BD_ERROR_OK);
157158
EXPECT_EQ(slice.program(program, BLOCK_SIZE, BLOCK_SIZE), BD_ERROR_OK);
159+
160+
// Verify written value
161+
EXPECT_EQ(slice.read(buf, BLOCK_SIZE, BLOCK_SIZE), BD_ERROR_OK);
162+
EXPECT_EQ(0, memcmp(buf, program, BLOCK_SIZE));
163+
158164
//Program a test value to address that is one pass the device size
159165
EXPECT_EQ(slice.program(program, 2 * BLOCK_SIZE, BLOCK_SIZE), BD_ERROR_DEVICE_ERROR);
160166
delete[] program;
161167
}
168+
169+
TEST_F(SlicingBlockModuleTest, over_read)
170+
{
171+
uint8_t *buf = new uint8_t[BLOCK_SIZE];
172+
173+
//Screate sclicing device, with size of 2 blocks
174+
mbed::SlicingBlockDevice slice(&bd, BLOCK_SIZE, BLOCK_SIZE * 3);
175+
EXPECT_EQ(slice.init(), BD_ERROR_OK);
176+
177+
//Try to read a block after the slice
178+
EXPECT_EQ(slice.read(buf, 2 * BLOCK_SIZE, BLOCK_SIZE), BD_ERROR_DEVICE_ERROR);
179+
delete[] buf;
180+
}
181+
182+
TEST_F(SlicingBlockModuleTest, get_type)
183+
{
184+
mbed::SlicingBlockDevice slice(&bd, BLOCK_SIZE, BLOCK_SIZE * 3);
185+
EXPECT_EQ(bd.get_type(), slice.get_type());
186+
}
187+
188+
TEST_F(SlicingBlockModuleTest, get_erase_value)
189+
{
190+
mbed::SlicingBlockDevice slice(&bd, BLOCK_SIZE, BLOCK_SIZE * 3);
191+
EXPECT_EQ(bd.get_erase_value(), slice.get_erase_value());
192+
}
193+
194+
TEST_F(SlicingBlockModuleTest, erase)
195+
{
196+
mbed::SlicingBlockDevice slice(&bd, BLOCK_SIZE, BLOCK_SIZE * 3);
197+
EXPECT_EQ(slice.erase(0, BLOCK_SIZE), BD_ERROR_OK);
198+
// Erase one block after the slice
199+
EXPECT_EQ(slice.erase(2*BLOCK_SIZE, BLOCK_SIZE), BD_ERROR_DEVICE_ERROR);
200+
}
201+
202+
TEST_F(SlicingBlockModuleTest, sync)
203+
{
204+
mbed::SlicingBlockDevice slice(&bd, BLOCK_SIZE, BLOCK_SIZE * 3);
205+
// Just a pass through
206+
EXPECT_EQ(slice.sync(), 0);
207+
}
208+
209+
TEST_F(SlicingBlockModuleTest, too_big_to_init)
210+
{
211+
mbed::SlicingBlockDevice slice(&bd, 0, DEVICE_SIZE + BLOCK_SIZE);
212+
// Just a pass through
213+
EXPECT_EQ(slice.init(), BD_ERROR_DEVICE_ERROR);
214+
}

features/storage/TESTS/blockdevice/general_block_device/main.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -809,7 +809,7 @@ int main()
809809

810810

811811
Specification specification(greentea_test_setup, cases, total_num_cases,
812-
greentea_test_teardown_handler, (test_failure_handler_t)greentea_failure_handler);
812+
greentea_test_teardown_handler, default_handler);
813813

814814
return !Harness::run(specification);
815815
}

features/storage/TESTS/kvstore/general_tests_phase_1/main.cpp

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -289,29 +289,46 @@ static void set_several_keys_multithreaded()
289289
//set key "write once" and try to set it again
290290
static void set_write_once_flag_try_set_twice()
291291
{
292+
char buf[10];
293+
size_t len;
292294
TEST_SKIP_UNLESS(kvstore != NULL);
293295

294-
int res = kvstore->set(key, data, data_size, KVStore::WRITE_ONCE_FLAG);
296+
int res = kvstore->set(key, "ONCE", 5, KVStore::WRITE_ONCE_FLAG);
295297
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
296298

297-
res = kvstore->set(key, data, data_size, KVStore::WRITE_ONCE_FLAG);
299+
res = kvstore->set(key, "TWICE", 6, KVStore::WRITE_ONCE_FLAG);
298300
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_WRITE_PROTECTED, res);
299301

302+
res = kvstore->get(key, buf, 10, &len);
303+
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
304+
TEST_ASSERT_EQUAL(len, 5);
305+
TEST_ASSERT_EQUAL_STRING_LEN(buf, "ONCE", 5);
306+
300307
res = kvstore->reset();
301308
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
302309
}
303310

304311
//set key "write once" and try to remove it
305312
static void set_write_once_flag_try_remove()
306313
{
314+
char buf[20];
315+
size_t len;
307316
TEST_SKIP_UNLESS(kvstore != NULL);
308317

309-
int res = kvstore->set(key, data, data_size, KVStore::WRITE_ONCE_FLAG);
318+
int res = kvstore->set(key, "TO_BE_REMOVED", 14, KVStore::WRITE_ONCE_FLAG);
319+
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
320+
321+
res = kvstore->get(key, buf, 20, &len);
310322
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
323+
TEST_ASSERT_EQUAL(len, 14);
324+
TEST_ASSERT_EQUAL_STRING_LEN(buf, "TO_BE_REMOVED", 14);
311325

312326
res = kvstore->remove(key);
313327
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_ERROR_WRITE_PROTECTED, res);
314328

329+
res = kvstore->get(key, buf, 20, &len);
330+
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
331+
315332
res = kvstore->reset();
316333
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
317334
}
@@ -873,7 +890,7 @@ int main()
873890
}
874891

875892
Specification specification(greentea_test_setup, cases, total_num_cases,
876-
greentea_test_teardown_handler, (test_failure_handler_t)greentea_failure_handler);
893+
greentea_test_teardown_handler, default_handler);
877894

878895
return !Harness::run(specification);
879896
}

features/storage/TESTS/kvstore/general_tests_phase_2/main.cpp

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,13 +68,18 @@ static int kv_setup = TDBStoreSet;
6868

6969
static const int heap_alloc_threshold_size = 4096;
7070

71+
static inline uint32_t align_up(uint32_t val, uint32_t size)
72+
{
73+
return (((val - 1) / size) + 1) * size;
74+
}
75+
7176
/*----------------initialization------------------*/
7277

7378
//init the blockdevice
7479
static void kvstore_init()
7580
{
7681
int res;
77-
size_t erase_size, ul_bd_size, rbp_bd_size;
82+
size_t program_size, erase_size, ul_bd_size, rbp_bd_size;
7883
BlockDevice *sec_bd;
7984

8085
res = bd->init();
@@ -109,10 +114,17 @@ static void kvstore_init()
109114
flash_bd = new FlashSimBlockDevice(bd);
110115
sec_bd = flash_bd;
111116
}
117+
res = sec_bd->init();
118+
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
119+
120+
program_size = sec_bd->get_program_size();
121+
erase_size = sec_bd->get_erase_size();
122+
// We must be able to hold at least 10 small keys (20 program sectors) and master record + internal data
123+
ul_bd_size = align_up(program_size * 40, erase_size);
124+
rbp_bd_size = align_up(program_size * 40, erase_size);
112125

113-
erase_size = sec_bd->get_erase_size();
114-
ul_bd_size = erase_size * 4;
115-
rbp_bd_size = erase_size * 2;
126+
res = sec_bd->deinit();
127+
TEST_ASSERT_EQUAL_ERROR_CODE(MBED_SUCCESS, res);
116128

117129
ul_bd = new SlicingBlockDevice(sec_bd, 0, ul_bd_size);
118130
rbp_bd = new SlicingBlockDevice(sec_bd, ul_bd_size, ul_bd_size + rbp_bd_size);
@@ -861,7 +873,7 @@ int main()
861873
}
862874

863875
Specification specification(greentea_test_setup, cases, total_num_cases,
864-
greentea_test_teardown_handler, (test_failure_handler_t)greentea_failure_handler);
876+
greentea_test_teardown_handler, default_handler);
865877

866878
return !Harness::run(specification);
867879
}

0 commit comments

Comments
 (0)