Skip to content

Commit c520449

Browse files
authored
Merge pull request #12206 from SeppoTakalo/kvstore_tests
Kvstore tests
2 parents 685e0be + b8361e4 commit c520449

File tree

5 files changed

+400
-0
lines changed

5 files changed

+400
-0
lines changed
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
/* Copyright (c) 2020 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/FlashSimBlockDevice.h"
20+
#include "features/storage/kvstore/tdbstore/TDBStore.h"
21+
#include <stdlib.h>
22+
23+
#define BLOCK_SIZE (512)
24+
#define DEVICE_SIZE (BLOCK_SIZE*200)
25+
26+
using namespace mbed;
27+
28+
class TDBStoreModuleTest : public testing::Test {
29+
protected:
30+
HeapBlockDevice heap{DEVICE_SIZE};
31+
FlashSimBlockDevice flash{&heap};
32+
TDBStore tdb{&flash};
33+
34+
virtual void SetUp()
35+
{
36+
EXPECT_EQ(tdb.init(), MBED_SUCCESS);
37+
EXPECT_EQ(tdb.reset(), MBED_SUCCESS);
38+
}
39+
40+
virtual void TearDown()
41+
{
42+
EXPECT_EQ(tdb.deinit(), MBED_SUCCESS);
43+
}
44+
};
45+
46+
TEST_F(TDBStoreModuleTest, init)
47+
{
48+
EXPECT_EQ(tdb.deinit(), MBED_SUCCESS);
49+
EXPECT_EQ(tdb.init(), MBED_SUCCESS);
50+
EXPECT_EQ(tdb.init(), MBED_SUCCESS);
51+
}
52+
53+
TEST_F(TDBStoreModuleTest, set_get)
54+
{
55+
char buf[100];
56+
size_t size;
57+
EXPECT_EQ(tdb.set("key", "data", 5, 0), MBED_SUCCESS);
58+
EXPECT_EQ(tdb.get("key", buf, 100, &size), MBED_SUCCESS);
59+
EXPECT_EQ(size, 5);
60+
EXPECT_STREQ("data", buf);
61+
}
62+
63+
TEST_F(TDBStoreModuleTest, erased_get_set)
64+
{
65+
EXPECT_EQ(tdb.deinit(), MBED_SUCCESS);
66+
EXPECT_EQ(flash.init(), MBED_SUCCESS);
67+
EXPECT_EQ(flash.erase(0, flash.size()), MBED_SUCCESS);
68+
EXPECT_EQ(flash.deinit(), MBED_SUCCESS);
69+
EXPECT_EQ(tdb.init(), MBED_SUCCESS);
70+
char buf[100];
71+
size_t size;
72+
EXPECT_EQ(tdb.set("key", "data", 5, 0), MBED_SUCCESS);
73+
EXPECT_EQ(tdb.get("key", buf, 100, &size), MBED_SUCCESS);
74+
EXPECT_EQ(size, 5);
75+
EXPECT_STREQ("data", buf);
76+
}
77+
78+
TEST_F(TDBStoreModuleTest, set_deinit_init_get)
79+
{
80+
char buf[100];
81+
size_t size;
82+
for (int i = 0; i < 100; ++i) {
83+
EXPECT_EQ(tdb.set("key", "data", 5, 0), MBED_SUCCESS);
84+
EXPECT_EQ(tdb.deinit(), MBED_SUCCESS);
85+
EXPECT_EQ(tdb.init(), MBED_SUCCESS);
86+
EXPECT_EQ(tdb.get("key", buf, 100, &size), MBED_SUCCESS);
87+
EXPECT_EQ(size, 5);
88+
EXPECT_STREQ("data", buf);
89+
EXPECT_EQ(tdb.remove("key"), MBED_SUCCESS);
90+
}
91+
}
92+
93+
TEST_F(TDBStoreModuleTest, corrupted_set_deinit_init_get)
94+
{
95+
char buf[100];
96+
char *block = new char[BLOCK_SIZE];
97+
size_t size;
98+
EXPECT_EQ(heap.init(), MBED_SUCCESS); // Extra init, so the heap will not be deinitialized
99+
100+
srand(0); // Prefer to have always the same pattern
101+
102+
for (int i = 0; i < 100; ++i) {
103+
EXPECT_EQ(tdb.deinit(), MBED_SUCCESS);
104+
// Corrupt the first part of the storage
105+
for (int i = 0; i < heap.size()/BLOCK_SIZE/2; i++) {
106+
for (int j = 0; j < BLOCK_SIZE; j++) {
107+
block[j] = rand();
108+
}
109+
EXPECT_EQ(heap.program(block, BLOCK_SIZE * i, BLOCK_SIZE), MBED_SUCCESS);
110+
}
111+
EXPECT_EQ(tdb.init(), MBED_SUCCESS);
112+
for (int j = 0; j < 100; ++j) {
113+
// Use random data, so the data has to be updated
114+
EXPECT_EQ(tdb.set("key", block+j, 50, 0), MBED_SUCCESS);
115+
EXPECT_EQ(tdb.deinit(), MBED_SUCCESS);
116+
EXPECT_EQ(tdb.init(), MBED_SUCCESS);
117+
EXPECT_EQ(tdb.get("key", buf, 100, &size), MBED_SUCCESS);
118+
EXPECT_EQ(size, 50);
119+
EXPECT_EQ(0, memcmp(buf, block+j, size));
120+
}
121+
EXPECT_EQ(tdb.remove("key"), MBED_SUCCESS);
122+
}
123+
124+
EXPECT_EQ(heap.deinit(), MBED_SUCCESS);
125+
delete[] block;
126+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
2+
####################
3+
# UNIT TESTS
4+
####################
5+
6+
set(unittest-includes ${unittest-includes}
7+
.
8+
..
9+
../features/frameworks/mbed-trace/mbed-trace
10+
)
11+
12+
set(unittest-sources
13+
../features/storage/blockdevice/FlashSimBlockDevice.cpp
14+
../features/storage/blockdevice/HeapBlockDevice.cpp
15+
../features/storage/blockdevice/BufferedBlockDevice.cpp
16+
../features/storage/kvstore/tdbstore/TDBStore.cpp
17+
../features/frameworks/mbed-trace/source/mbed_trace.c
18+
stubs/mbed_atomic_stub.c
19+
stubs/mbed_assert_stub.cpp
20+
stubs/mbed_error.c
21+
)
22+
23+
set(unittest-test-sources
24+
moduletests/storage/kvstore/TDBStore/moduletest.cpp
25+
)
26+
27+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")

UNITTESTS/stubs/EmulatedSD.cpp

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
/* Copyright (c) 2020 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 "EmulatedSD.h"
18+
#include <stdio.h>
19+
20+
class EmulatedSD_Private {
21+
public:
22+
~EmulatedSD_Private() {
23+
if (fs) {
24+
fclose(fs);
25+
}
26+
}
27+
const char *path;
28+
FILE *fs;
29+
bd_size_t size;
30+
};
31+
32+
EmulatedSD::EmulatedSD(const char *path)
33+
{
34+
_p = new EmulatedSD_Private;
35+
_p->path = path;
36+
}
37+
38+
EmulatedSD::~EmulatedSD()
39+
{
40+
delete _p;
41+
}
42+
43+
int EmulatedSD::init()
44+
{
45+
_p->fs = fopen(_p->path, "r+");
46+
if (!_p->fs) {
47+
perror("fdopen():");
48+
return -1;
49+
}
50+
if (fseek(_p->fs, 0, SEEK_END)) {
51+
perror("fseek()");
52+
fclose(_p->fs);
53+
_p->fs = nullptr;
54+
return -1;
55+
}
56+
_p->size = ftell(_p->fs);
57+
rewind(_p->fs);
58+
return 0;
59+
}
60+
61+
int EmulatedSD::deinit()
62+
{
63+
fclose(_p->fs);
64+
_p->fs = nullptr;
65+
}
66+
67+
int EmulatedSD::read(void *buffer, bd_addr_t addr, bd_size_t size)
68+
{
69+
if (!_p->fs) {
70+
return -1;
71+
}
72+
if (fseek(_p->fs, addr, SEEK_SET)) {
73+
perror("fseek()");
74+
return -1;
75+
}
76+
size_t r = fread(buffer, size, 1, _p->fs);
77+
if (r < 1) {
78+
perror("fread()");
79+
return -1;
80+
}
81+
return 0;
82+
}
83+
84+
int EmulatedSD::program(const void *buffer, bd_addr_t addr, bd_size_t size)
85+
{
86+
if (!_p->fs) {
87+
return -1;
88+
}
89+
if (fseek(_p->fs, addr, SEEK_SET)) {
90+
perror("fseek()");
91+
return -1;
92+
}
93+
size_t r = fwrite(buffer, size, 1, _p->fs);
94+
if (r < 1) {
95+
perror("fread()");
96+
return -1;
97+
}
98+
return 0;
99+
}
100+
101+
bd_size_t EmulatedSD::get_read_size() const
102+
{
103+
return 512;
104+
}
105+
bd_size_t EmulatedSD::get_program_size() const
106+
{
107+
return 512;
108+
}
109+
bd_size_t EmulatedSD::size() const
110+
{
111+
if (!_p->fs) {
112+
return -1;
113+
}
114+
return _p->size;
115+
}
116+
const char *EmulatedSD::get_type() const
117+
{
118+
return "SD";
119+
}

UNITTESTS/stubs/EmulatedSD.h

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/* Copyright (c) 2020 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+
#ifndef EMULATEDSD_H
18+
#define EMULATEDSD_H
19+
20+
#include "features/storage/blockdevice/BlockDevice.h"
21+
22+
class EmulatedSD_Private;
23+
24+
class EmulatedSD : public mbed::BlockDevice {
25+
public:
26+
EmulatedSD(const char *path);
27+
~EmulatedSD();
28+
29+
/** Initialize a block device
30+
*
31+
* @return 0 on success or a negative error code on failure
32+
*/
33+
virtual int init();
34+
35+
/** Deinitialize a block device
36+
*
37+
* @return 0 on success or a negative error code on failure
38+
*/
39+
virtual int deinit();
40+
41+
/** Read blocks from a block device
42+
*
43+
* If a failure occurs, it is not possible to determine how many bytes succeeded
44+
*
45+
* @param buffer Buffer to write blocks to
46+
* @param addr Address of block to begin reading from
47+
* @param size Size to read in bytes, must be a multiple of the read block size
48+
* @return 0 on success or a negative error code on failure
49+
*/
50+
virtual int read(void *buffer, bd_addr_t addr, bd_size_t size);
51+
52+
/** Program blocks to a block device
53+
*
54+
* The blocks must have been erased prior to being programmed
55+
*
56+
* If a failure occurs, it is not possible to determine how many bytes succeeded
57+
*
58+
* @param buffer Buffer of data to write to blocks
59+
* @param addr Address of block to begin writing to
60+
* @param size Size to write in bytes, must be a multiple of the program block size
61+
* @return 0 on success or a negative error code on failure
62+
*/
63+
virtual int program(const void *buffer, bd_addr_t addr, bd_size_t size);
64+
65+
/** Get the size of a readable block
66+
*
67+
* @return Size of a readable block in bytes
68+
*/
69+
virtual bd_size_t get_read_size() const;
70+
71+
/** Get the size of a programmable block
72+
*
73+
* @return Size of a programmable block in bytes
74+
* @note Must be a multiple of the read size
75+
*/
76+
virtual bd_size_t get_program_size() const;
77+
78+
/** Get the total size of the underlying device
79+
*
80+
* @return Size of the underlying device in bytes
81+
*/
82+
virtual bd_size_t size() const;
83+
84+
/** Get the BlockDevice class type.
85+
*
86+
* @return A string represent the BlockDevice class type.
87+
*/
88+
virtual const char *get_type() const;
89+
private:
90+
EmulatedSD_Private *_p;
91+
};
92+
93+
#endif // EMULATEDSD_H

0 commit comments

Comments
 (0)