mirror of https://github.com/ARMmbed/mbed-os.git
unittests: BlockDevice unittests improvements
Moved the existing BufferedBlockDevice to features/storage unittests and switched it to gmock. Added gmock-based unit tests to all other BlockDevice classes. SlicingBlockDevice test left as a module test.pull/12398/head
parent
10481f2f7e
commit
31ce76487f
|
@ -0,0 +1,318 @@
|
|||
/* Copyright (c) 2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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 "gtest/gtest.h"
|
||||
#include "features/storage/blockdevice/BufferedBlockDevice.h"
|
||||
#include "stubs/BlockDevice_mock.h"
|
||||
|
||||
using ::testing::_;
|
||||
using ::testing::Return;
|
||||
using ::testing::ReturnArg;
|
||||
using ::testing::SaveArg;
|
||||
using ::testing::SaveArgPointee;
|
||||
using ::testing::SetArrayArgument;
|
||||
using ::testing::SetArgPointee;
|
||||
using ::testing::SetArgReferee;
|
||||
using ::testing::DoAll;
|
||||
|
||||
#define BLOCK_SIZE (512)
|
||||
#define DEVICE_SIZE (BLOCK_SIZE*10)
|
||||
|
||||
class BufferedBlockModuleTest : public testing::Test {
|
||||
protected:
|
||||
BlockDeviceMock bd_mock;
|
||||
BufferedBlockDevice bd{&bd_mock};
|
||||
uint8_t *magic;
|
||||
uint8_t *buf;
|
||||
virtual void SetUp()
|
||||
{
|
||||
EXPECT_CALL(bd_mock, init());
|
||||
EXPECT_CALL(bd_mock, get_read_size()).WillOnce(Return(BLOCK_SIZE));
|
||||
EXPECT_CALL(bd_mock, get_program_size()).WillOnce(Return(BLOCK_SIZE));
|
||||
EXPECT_CALL(bd_mock, size()).WillOnce(Return(DEVICE_SIZE));
|
||||
ASSERT_EQ(bd.init(), 0);
|
||||
magic = new uint8_t[2*BLOCK_SIZE];
|
||||
buf = new uint8_t[2*BLOCK_SIZE];
|
||||
// Generate simple pattern to verify against
|
||||
for (int i = 0; i < BLOCK_SIZE*2; i++) {
|
||||
magic[i] = 0xaa + i;
|
||||
buf[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void TearDown()
|
||||
{
|
||||
EXPECT_CALL(bd_mock, deinit());
|
||||
EXPECT_CALL(bd_mock, sync()); // Called on deinit
|
||||
ASSERT_EQ(bd.deinit(), 0);
|
||||
delete[] magic;
|
||||
delete[] buf;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(BufferedBlockModuleTest, init)
|
||||
{
|
||||
BufferedBlockDevice b(&bd_mock);
|
||||
EXPECT_EQ(b.get_erase_size(), 0);
|
||||
EXPECT_EQ(b.get_erase_size(0), 0);
|
||||
EXPECT_EQ(b.get_erase_value(), BD_ERROR_DEVICE_ERROR);
|
||||
EXPECT_EQ(b.size(), 0);
|
||||
EXPECT_EQ(b.program(magic, 0, BLOCK_SIZE), BD_ERROR_DEVICE_ERROR);
|
||||
EXPECT_EQ(b.read(buf, 0, BLOCK_SIZE), BD_ERROR_DEVICE_ERROR);
|
||||
EXPECT_EQ(b.trim(0, BLOCK_SIZE), BD_ERROR_DEVICE_ERROR);
|
||||
EXPECT_EQ(b.deinit(), BD_ERROR_OK);
|
||||
EXPECT_EQ(b.sync(), BD_ERROR_DEVICE_ERROR);
|
||||
EXPECT_EQ(b.erase(0, BLOCK_SIZE), BD_ERROR_DEVICE_ERROR);
|
||||
|
||||
EXPECT_CALL(bd_mock, init());
|
||||
EXPECT_CALL(bd_mock, size()).WillOnce(Return(DEVICE_SIZE));
|
||||
EXPECT_CALL(bd_mock, get_read_size()).WillOnce(Return(DEVICE_SIZE));
|
||||
EXPECT_CALL(bd_mock, get_program_size()).WillOnce(Return(DEVICE_SIZE));
|
||||
|
||||
EXPECT_EQ(b.init(), 0);
|
||||
|
||||
EXPECT_CALL(bd_mock, get_erase_size()).WillOnce(Return(17));
|
||||
EXPECT_CALL(bd_mock, get_erase_size(0)).WillOnce(Return(18));
|
||||
EXPECT_CALL(bd_mock, get_erase_value()).WillOnce(Return(19));
|
||||
EXPECT_CALL(bd_mock, get_type()).WillOnce(Return("mytype"));
|
||||
|
||||
EXPECT_EQ(b.get_erase_size(), 17);
|
||||
EXPECT_EQ(b.get_erase_size(0), 18);
|
||||
EXPECT_EQ(b.get_erase_value(), 19);
|
||||
EXPECT_EQ(b.get_program_size(), 1);
|
||||
EXPECT_EQ(b.get_read_size(), 1);
|
||||
EXPECT_EQ(b.size(), DEVICE_SIZE);
|
||||
EXPECT_EQ(b.get_type(), "mytype");
|
||||
|
||||
EXPECT_CALL(bd_mock, deinit()); // Called in b's destructor
|
||||
EXPECT_CALL(bd_mock, sync()); // Called on b's deinit
|
||||
}
|
||||
|
||||
TEST_F(BufferedBlockModuleTest, read_full_block)
|
||||
{
|
||||
EXPECT_CALL(bd_mock, is_valid_read(0, BLOCK_SIZE))
|
||||
.WillRepeatedly(Return(true));
|
||||
|
||||
EXPECT_CALL(bd_mock, read(_, 0, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(DoAll(SetArg0ToCharPtr(magic, BLOCK_SIZE), Return(BD_ERROR_OK)));
|
||||
|
||||
EXPECT_EQ(0, bd.read(buf, 0, BLOCK_SIZE));
|
||||
EXPECT_EQ(0, memcmp(magic, buf, BLOCK_SIZE));
|
||||
}
|
||||
|
||||
TEST_F(BufferedBlockModuleTest, over_read)
|
||||
{
|
||||
EXPECT_CALL(bd_mock, is_valid_read(DEVICE_SIZE - BLOCK_SIZE, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(Return(true));
|
||||
EXPECT_CALL(bd_mock, read(_, DEVICE_SIZE - BLOCK_SIZE, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(DoAll(SetArg0ToCharPtr(magic, BLOCK_SIZE), Return(BD_ERROR_OK)));
|
||||
|
||||
EXPECT_EQ(bd.read(buf, DEVICE_SIZE - BLOCK_SIZE, BLOCK_SIZE), 0);
|
||||
|
||||
// This will return before mock's is_valid_read()
|
||||
EXPECT_EQ(bd.read(buf, DEVICE_SIZE, BLOCK_SIZE), BD_ERROR_DEVICE_ERROR);
|
||||
}
|
||||
|
||||
TEST_F(BufferedBlockModuleTest, unalign_read)
|
||||
{
|
||||
EXPECT_CALL(bd_mock, is_valid_read(BLOCK_SIZE/2, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(Return(true));
|
||||
|
||||
EXPECT_CALL(bd_mock, read(_, BLOCK_SIZE/2, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(DoAll(SetArg0ToCharPtr(magic, BLOCK_SIZE/2), Return(BD_ERROR_OK)));
|
||||
|
||||
EXPECT_EQ(bd.read(buf, BLOCK_SIZE/2, BLOCK_SIZE), 0);
|
||||
EXPECT_EQ(0, memcmp(buf, magic+(BLOCK_SIZE/2), BLOCK_SIZE/2));
|
||||
}
|
||||
|
||||
TEST_F(BufferedBlockModuleTest, unalign_erase)
|
||||
{
|
||||
EXPECT_CALL(bd_mock, read(_, 0, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(DoAll(SetArg0ToCharPtr(magic, BLOCK_SIZE), Return(BD_ERROR_OK)));
|
||||
|
||||
EXPECT_EQ(bd.program("a", BLOCK_SIZE/2, 1), 0);
|
||||
|
||||
ON_CALL(bd_mock, get_erase_size(_)).WillByDefault(Return(BLOCK_SIZE));
|
||||
|
||||
// Partial erase is not supported
|
||||
EXPECT_EQ(bd.erase(BLOCK_SIZE/2, BLOCK_SIZE), BD_ERROR_DEVICE_ERROR);
|
||||
|
||||
EXPECT_CALL(bd_mock, erase(0, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(Return(BD_ERROR_OK));
|
||||
|
||||
EXPECT_EQ(bd.erase(0, BLOCK_SIZE), BD_ERROR_OK);
|
||||
}
|
||||
|
||||
TEST_F(BufferedBlockModuleTest, align_big_read)
|
||||
{
|
||||
uint8_t *buffer = new uint8_t[BLOCK_SIZE*2];
|
||||
|
||||
EXPECT_CALL(bd_mock, is_valid_read(0, (BLOCK_SIZE*2)-1))
|
||||
.Times(1)
|
||||
.WillOnce(Return(true));
|
||||
|
||||
EXPECT_CALL(bd_mock, read(_, 0, BLOCK_SIZE*2-1))
|
||||
.Times(1)
|
||||
.WillOnce(DoAll(SetArg0ToCharPtr(magic, BLOCK_SIZE*2-1), Return(BD_ERROR_OK)));
|
||||
|
||||
// Should cause 1 full block to be read unaligned from the device
|
||||
// second block would require buffering, because it is not a full (-1)
|
||||
EXPECT_EQ(bd.read(buffer, 0, (BLOCK_SIZE*2)-1), 0);
|
||||
EXPECT_EQ(0, memcmp(magic, buffer, BLOCK_SIZE));
|
||||
EXPECT_EQ(0, memcmp(magic+BLOCK_SIZE, buffer+BLOCK_SIZE, BLOCK_SIZE-1));
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
TEST_F(BufferedBlockModuleTest, program_small_chunks)
|
||||
{
|
||||
EXPECT_CALL(bd_mock, is_valid_read(0, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(Return(true));
|
||||
|
||||
EXPECT_CALL(bd_mock, read(_, 0, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(DoAll(SetArg0ToCharPtr(magic, BLOCK_SIZE), Return(BD_ERROR_OK)));
|
||||
|
||||
for (int i=0; i < BLOCK_SIZE - 1; ++i) {
|
||||
EXPECT_EQ(bd.program(magic+i, i, 1), 0);
|
||||
}
|
||||
EXPECT_EQ(bd.read(buf, 0, BLOCK_SIZE), 0);
|
||||
EXPECT_EQ(0, memcmp(buf, magic, BLOCK_SIZE - 1));
|
||||
|
||||
// write cache will be flushed on deinit.
|
||||
EXPECT_CALL(bd_mock, program(_, 0, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(Return(BD_ERROR_OK));
|
||||
}
|
||||
|
||||
TEST_F(BufferedBlockModuleTest, program_and_read_from_cache)
|
||||
{
|
||||
EXPECT_CALL(bd_mock, program(_, 0, BLOCK_SIZE))
|
||||
.Times(2) // Once on 1st program and once on deinit
|
||||
.WillRepeatedly(Return(BD_ERROR_OK));
|
||||
|
||||
EXPECT_CALL(bd_mock, is_valid_read(0, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(Return(true));
|
||||
|
||||
EXPECT_CALL(bd_mock, read(_, 0, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(DoAll(SetArg0ToCharPtr(magic, BLOCK_SIZE), Return(BD_ERROR_OK)));
|
||||
|
||||
EXPECT_CALL(bd_mock, sync()); // Triggered from program()
|
||||
|
||||
EXPECT_EQ(bd.program(magic, 0, BLOCK_SIZE), 0);
|
||||
EXPECT_EQ(bd.program("a", 0, 1), 0);
|
||||
EXPECT_EQ(bd.read(buf, 0, BLOCK_SIZE), 0);
|
||||
EXPECT_EQ('a', buf[0]);
|
||||
EXPECT_EQ(0, memcmp(buf+1, magic+1, BLOCK_SIZE-1));
|
||||
}
|
||||
|
||||
TEST_F(BufferedBlockModuleTest, program_and_read_from_device)
|
||||
{
|
||||
EXPECT_CALL(bd_mock, program(_, 0, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillRepeatedly(Return(BD_ERROR_OK));
|
||||
|
||||
EXPECT_CALL(bd_mock, program(_, BLOCK_SIZE, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillRepeatedly(Return(BD_ERROR_OK));
|
||||
|
||||
EXPECT_CALL(bd_mock, read(_, BLOCK_SIZE, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(DoAll(SetArg0ToCharPtr(magic, BLOCK_SIZE), Return(BD_ERROR_OK)));
|
||||
|
||||
EXPECT_CALL(bd_mock, is_valid_read(BLOCK_SIZE*3, BLOCK_SIZE-1)).WillOnce(Return(false));
|
||||
|
||||
EXPECT_CALL(bd_mock, read(_, BLOCK_SIZE*3, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(DoAll(SetArg0ToCharPtr(magic, BLOCK_SIZE-1), Return(BD_ERROR_OK)));
|
||||
|
||||
EXPECT_CALL(bd_mock, sync()).Times(1); // Triggered from program()s
|
||||
|
||||
EXPECT_EQ(bd.program(magic, 0, BLOCK_SIZE), 0);
|
||||
EXPECT_EQ(bd.program(magic, BLOCK_SIZE, BLOCK_SIZE-1), 0);
|
||||
EXPECT_EQ(bd.read(buf, BLOCK_SIZE*3, BLOCK_SIZE-1), 0);
|
||||
EXPECT_EQ(0, memcmp(buf, magic, BLOCK_SIZE-1));
|
||||
|
||||
EXPECT_CALL(bd_mock, is_valid_read(BLOCK_SIZE*3, BLOCK_SIZE+1)).WillOnce(Return(false));
|
||||
|
||||
EXPECT_CALL(bd_mock, read(_, BLOCK_SIZE*3, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(DoAll(SetArg0ToCharPtr(magic, BLOCK_SIZE), Return(BD_ERROR_OK)))
|
||||
.RetiresOnSaturation();
|
||||
|
||||
EXPECT_CALL(bd_mock, read(_, BLOCK_SIZE*4, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(DoAll(SetArg0ToCharPtr(magic+BLOCK_SIZE, BLOCK_SIZE), Return(BD_ERROR_OK)));
|
||||
|
||||
EXPECT_EQ(bd.read(buf, BLOCK_SIZE*3, BLOCK_SIZE+1), 0);
|
||||
EXPECT_EQ(0, memcmp(buf, magic, BLOCK_SIZE+1));
|
||||
}
|
||||
|
||||
TEST_F(BufferedBlockModuleTest, program_and_verify_from_storage)
|
||||
{
|
||||
EXPECT_CALL(bd_mock, program(_, 0, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(Return(BD_ERROR_OK));
|
||||
|
||||
EXPECT_CALL(bd_mock, is_valid_read(0, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(Return(true));
|
||||
|
||||
EXPECT_CALL(bd_mock, read(_, 0, BLOCK_SIZE))
|
||||
.Times(2)
|
||||
.WillRepeatedly(DoAll(SetArg0ToCharPtr(magic, BLOCK_SIZE), Return(BD_ERROR_OK)));
|
||||
|
||||
EXPECT_CALL(bd_mock, sync()); // Triggered from program()
|
||||
|
||||
EXPECT_EQ(bd.program(magic, 0, BLOCK_SIZE/2), 0);
|
||||
EXPECT_EQ(bd.program(magic+BLOCK_SIZE/2, BLOCK_SIZE/2, BLOCK_SIZE/2), 0); // This should actually write to device
|
||||
EXPECT_EQ(bd.read(buf, 0, BLOCK_SIZE), 0);
|
||||
EXPECT_EQ(0, memcmp(buf, magic, BLOCK_SIZE));
|
||||
}
|
||||
|
||||
TEST_F(BufferedBlockModuleTest, flush_automatically)
|
||||
{
|
||||
// Validate cache
|
||||
EXPECT_CALL(bd_mock, read(_, 0, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillRepeatedly(DoAll(SetArg0ToCharPtr(magic, BLOCK_SIZE), Return(BD_ERROR_OK)));
|
||||
|
||||
EXPECT_EQ(bd.program(magic, 0, BLOCK_SIZE/2), 0); // Don't write full block
|
||||
|
||||
// Validate cache for the second program
|
||||
EXPECT_CALL(bd_mock, read(_, BLOCK_SIZE, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillRepeatedly(DoAll(SetArg0ToCharPtr(magic, BLOCK_SIZE), Return(BD_ERROR_OK)));
|
||||
|
||||
EXPECT_CALL(bd_mock, program(_, 0, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(Return(BD_ERROR_OK));
|
||||
|
||||
EXPECT_EQ(bd.program(magic, BLOCK_SIZE, BLOCK_SIZE/2), 0); // This should cause flush() for previous data in cache
|
||||
|
||||
EXPECT_CALL(bd_mock, program(_, BLOCK_SIZE, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(Return(BD_ERROR_OK));
|
||||
}
|
|
@ -10,11 +10,11 @@ set(unittest-includes ${unittest-includes}
|
|||
|
||||
set(unittest-sources
|
||||
../features/storage/blockdevice/BufferedBlockDevice.cpp
|
||||
../features/storage/blockdevice/HeapBlockDevice.cpp
|
||||
stubs/mbed_atomic_stub.c
|
||||
stubs/mbed_assert_stub.cpp
|
||||
)
|
||||
|
||||
set(unittest-test-sources
|
||||
moduletests/storage/blockdevice/BufferedBlockDevice/moduletest.cpp
|
||||
features/storage/blockdevice/BufferedBlockDevice/test_BufferedBlockDevice.cpp
|
||||
stubs/BlockDevice_mock.h
|
||||
)
|
|
@ -0,0 +1,163 @@
|
|||
/* Copyright (c) 2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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 "gtest/gtest.h"
|
||||
#include "features/storage/blockdevice/ChainingBlockDevice.cpp"
|
||||
#include "stubs/BlockDevice_mock.h"
|
||||
|
||||
using ::testing::_;
|
||||
using ::testing::Return;
|
||||
using ::testing::ReturnArg;
|
||||
using ::testing::SaveArg;
|
||||
using ::testing::SaveArgPointee;
|
||||
using ::testing::SetArrayArgument;
|
||||
using ::testing::SetArgPointee;
|
||||
using ::testing::SetArgReferee;
|
||||
using ::testing::DoAll;
|
||||
|
||||
#define BLOCK_SIZE (512)
|
||||
#define SECTORS_NUM (8)
|
||||
#define DEVICE_SIZE (BLOCK_SIZE * SECTORS_NUM)
|
||||
|
||||
class ChainingBlockModuleTest : public testing::Test {
|
||||
protected:
|
||||
BlockDeviceMock bd_mock1;
|
||||
BlockDeviceMock bd_mock2;
|
||||
|
||||
BlockDevice *bds[2] = {&bd_mock1, &bd_mock2};
|
||||
ChainingBlockDevice bd{bds, 2};
|
||||
uint8_t *magic;
|
||||
uint8_t *buf;
|
||||
virtual void SetUp()
|
||||
{
|
||||
ON_CALL(bd_mock1, size()).WillByDefault(Return((SECTORS_NUM / 2)*BLOCK_SIZE));
|
||||
ON_CALL(bd_mock2, size()).WillByDefault(Return((SECTORS_NUM )*BLOCK_SIZE));
|
||||
|
||||
ON_CALL(bd_mock1, get_erase_size(_)).WillByDefault(Return(BLOCK_SIZE));
|
||||
ON_CALL(bd_mock2, get_erase_size(_)).WillByDefault(Return(2*BLOCK_SIZE));
|
||||
|
||||
ON_CALL(bd_mock1, get_erase_size()).WillByDefault(Return(BLOCK_SIZE));
|
||||
ON_CALL(bd_mock2, get_erase_size()).WillByDefault(Return(2*BLOCK_SIZE));
|
||||
|
||||
EXPECT_CALL(bd_mock1, init());
|
||||
EXPECT_CALL(bd_mock2, init());
|
||||
// Init performs checks on the parameters of underlying BDs
|
||||
// the BDs used for this test have different parameters:
|
||||
// bd_mock1 has erase/program/read size of BLOCK_SIZE and total (SECTORS_NUM / 2)*BLOCK_SIZE size
|
||||
// bd_mock1 has erase/program/read size of 2*BLOCK_SIZE and total (SECTORS_NUM )*BLOCK_SIZE size
|
||||
EXPECT_CALL(bd_mock1, get_erase_value()).WillOnce(Return(0));
|
||||
EXPECT_CALL(bd_mock1, get_read_size()).WillOnce(Return(BLOCK_SIZE));
|
||||
EXPECT_CALL(bd_mock1, get_program_size()).WillOnce(Return(BLOCK_SIZE));
|
||||
|
||||
EXPECT_CALL(bd_mock2, get_erase_value()).WillOnce(Return(0));
|
||||
EXPECT_CALL(bd_mock2, get_read_size()).WillOnce(Return(BLOCK_SIZE * 2));
|
||||
EXPECT_CALL(bd_mock2, get_program_size()).WillOnce(Return(BLOCK_SIZE * 2));
|
||||
|
||||
ASSERT_EQ(bd.init(), 0);
|
||||
magic = new uint8_t[BLOCK_SIZE * 4];
|
||||
buf = new uint8_t[BLOCK_SIZE * 4];
|
||||
// Generate simple pattern to verify against
|
||||
for (int i = 0; i < BLOCK_SIZE * 4; i++) {
|
||||
magic[i] = 0xaa + i;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void TearDown()
|
||||
{
|
||||
EXPECT_CALL(bd_mock1, deinit());
|
||||
EXPECT_CALL(bd_mock2, deinit());
|
||||
ASSERT_EQ(bd.deinit(), 0);
|
||||
delete[] magic;
|
||||
delete[] buf;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(ChainingBlockModuleTest, init)
|
||||
{
|
||||
ChainingBlockDevice b(this->bds, 2);
|
||||
EXPECT_EQ(b.get_erase_size(), 0);
|
||||
EXPECT_EQ(b.get_erase_size(0), 0);
|
||||
EXPECT_EQ(b.get_erase_value(), -1);
|
||||
EXPECT_EQ(b.size(), 0);
|
||||
EXPECT_EQ(b.program(magic, 0, BLOCK_SIZE), BD_ERROR_DEVICE_ERROR);
|
||||
EXPECT_EQ(b.read(buf, 0, BLOCK_SIZE), BD_ERROR_DEVICE_ERROR);
|
||||
// EXPECT_EQ(b.deinit(), BD_ERROR_OK);
|
||||
EXPECT_EQ(b.sync(), BD_ERROR_DEVICE_ERROR);
|
||||
EXPECT_EQ(b.get_type(), "CHAINING");
|
||||
|
||||
EXPECT_CALL(bd_mock1, init());
|
||||
EXPECT_CALL(bd_mock1, size()).WillOnce(Return((SECTORS_NUM / 2)*BLOCK_SIZE));
|
||||
EXPECT_CALL(bd_mock1, get_erase_size()).WillOnce(Return(BLOCK_SIZE));
|
||||
EXPECT_CALL(bd_mock1, get_read_size()).WillOnce(Return(BLOCK_SIZE));
|
||||
EXPECT_CALL(bd_mock1, get_program_size()).WillOnce(Return(BLOCK_SIZE));
|
||||
EXPECT_CALL(bd_mock1, get_erase_value()).WillOnce(Return(2));
|
||||
EXPECT_CALL(bd_mock2, init());
|
||||
EXPECT_CALL(bd_mock2, size()).WillOnce(Return((SECTORS_NUM )*BLOCK_SIZE));
|
||||
EXPECT_CALL(bd_mock2, get_erase_size()).WillOnce(Return(BLOCK_SIZE * 2));
|
||||
EXPECT_CALL(bd_mock2, get_read_size()).WillOnce(Return(BLOCK_SIZE * 2));
|
||||
EXPECT_CALL(bd_mock2, get_program_size()).WillOnce(Return(BLOCK_SIZE * 2));
|
||||
EXPECT_CALL(bd_mock2, get_erase_value()).WillOnce(Return(3));
|
||||
|
||||
EXPECT_EQ(b.init(), 0);
|
||||
|
||||
EXPECT_EQ(b.get_program_size(), BLOCK_SIZE * 2);
|
||||
EXPECT_EQ(b.get_read_size(), BLOCK_SIZE * 2);
|
||||
EXPECT_EQ(b.get_erase_size(), BLOCK_SIZE * 2);
|
||||
EXPECT_EQ(b.get_erase_value(), -1);
|
||||
}
|
||||
|
||||
TEST_F(ChainingBlockModuleTest, memory_overlap)
|
||||
{
|
||||
// program
|
||||
// Half of the data should go into bd_mock1
|
||||
EXPECT_CALL(bd_mock1, program(ByteBufferMatcher(magic, BLOCK_SIZE*2), (SECTORS_NUM / 2 - 2) * BLOCK_SIZE, 2 * BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(Return(BD_ERROR_OK));
|
||||
|
||||
// Another half should go to bd_mock2
|
||||
EXPECT_CALL(bd_mock2, program(ByteBufferMatcher(magic+BLOCK_SIZE*2, BLOCK_SIZE*2), 0, 2 * BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(Return(BD_ERROR_OK));
|
||||
|
||||
EXPECT_EQ(bd.program(magic, (SECTORS_NUM / 2 - 2) * BLOCK_SIZE, 4 * BLOCK_SIZE), BD_ERROR_OK);
|
||||
|
||||
|
||||
// read
|
||||
// On read half of the data will be read out from bd_mock1
|
||||
EXPECT_CALL(bd_mock1, read(_, (SECTORS_NUM / 2 - 2) * BLOCK_SIZE, 2 * BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(DoAll(SetArg0ToCharPtr(magic, 2*BLOCK_SIZE), Return(BD_ERROR_OK)));
|
||||
|
||||
EXPECT_CALL(bd_mock2, read(_, 0, 2 * BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(DoAll(SetArg0ToCharPtr(magic+2*BLOCK_SIZE, 2*BLOCK_SIZE), Return(BD_ERROR_OK)));
|
||||
|
||||
EXPECT_EQ(bd.read(buf, (SECTORS_NUM / 2 - 2) * BLOCK_SIZE, 4 * BLOCK_SIZE), BD_ERROR_OK);
|
||||
EXPECT_EQ(memcmp(magic, buf, BLOCK_SIZE * 4), 0);
|
||||
|
||||
|
||||
// erase
|
||||
EXPECT_CALL(bd_mock1, erase((SECTORS_NUM / 2 - 2) * BLOCK_SIZE, 2 * BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(Return(BD_ERROR_OK));
|
||||
|
||||
EXPECT_CALL(bd_mock2, erase(0, 2 * BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(Return(BD_ERROR_OK));
|
||||
|
||||
EXPECT_EQ(bd.erase((SECTORS_NUM / 2 - 2) * BLOCK_SIZE, 4 * BLOCK_SIZE), BD_ERROR_OK);
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
|
||||
####################
|
||||
# UNIT TESTS
|
||||
####################
|
||||
|
||||
set(unittest-includes ${unittest-includes}
|
||||
.
|
||||
..
|
||||
)
|
||||
|
||||
set(unittest-sources
|
||||
../features/storage/blockdevice/ChainingBlockDevice.cpp
|
||||
../features/storage/blockdevice/HeapBlockDevice.cpp
|
||||
stubs/mbed_atomic_stub.c
|
||||
stubs/mbed_assert_stub.cpp
|
||||
)
|
||||
|
||||
set(unittest-test-sources
|
||||
features/storage/blockdevice/ChainingBlockDevice/test_ChainingBlockDevice.cpp
|
||||
)
|
|
@ -0,0 +1,152 @@
|
|||
/* Copyright (c) 2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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 "gtest/gtest.h"
|
||||
#include "features/storage/blockdevice/ExhaustibleBlockDevice.h"
|
||||
#include "stubs/BlockDevice_mock.h"
|
||||
|
||||
#define BLOCK_SIZE (512)
|
||||
#define DEVICE_SIZE (BLOCK_SIZE*10)
|
||||
#define ERASE_CYCLES (2)
|
||||
|
||||
using ::testing::_;
|
||||
using ::testing::Return;
|
||||
using ::testing::ReturnArg;
|
||||
using ::testing::SaveArg;
|
||||
using ::testing::SaveArgPointee;
|
||||
using ::testing::SetArrayArgument;
|
||||
using ::testing::SetArgPointee;
|
||||
using ::testing::SetArgReferee;
|
||||
using ::testing::DoAll;
|
||||
|
||||
class ExhaustibleBlockModuleTest : public testing::Test {
|
||||
protected:
|
||||
BlockDeviceMock bd_mock;
|
||||
ExhaustibleBlockDevice bd{&bd_mock, ERASE_CYCLES};
|
||||
uint8_t *magic;
|
||||
uint8_t *magic2;
|
||||
uint8_t *buf;
|
||||
virtual void SetUp()
|
||||
{
|
||||
ON_CALL(bd_mock, size()).WillByDefault(Return(BLOCK_SIZE));
|
||||
ON_CALL(bd_mock, get_erase_size(_)).WillByDefault(Return(BLOCK_SIZE));
|
||||
ON_CALL(bd_mock, get_erase_size()).WillByDefault(Return(BLOCK_SIZE));
|
||||
ON_CALL(bd_mock, get_program_size()).WillByDefault(Return(BLOCK_SIZE));
|
||||
ON_CALL(bd_mock, get_read_size()).WillByDefault(Return(BLOCK_SIZE));
|
||||
|
||||
EXPECT_CALL(bd_mock, init());
|
||||
ASSERT_EQ(bd.init(), 0);
|
||||
magic = new uint8_t[BLOCK_SIZE];
|
||||
magic2 = new uint8_t[BLOCK_SIZE];
|
||||
buf = new uint8_t[BLOCK_SIZE];
|
||||
// Generate simple pattern to verify against
|
||||
for (int i = 0; i < BLOCK_SIZE; i++) {
|
||||
magic[i] = 0xaa + i;
|
||||
magic2[i] = 0xaa + i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void TearDown()
|
||||
{
|
||||
EXPECT_CALL(bd_mock, deinit());
|
||||
ASSERT_EQ(bd.deinit(), 0);
|
||||
delete[] magic;
|
||||
delete[] magic2;
|
||||
delete[] buf;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(ExhaustibleBlockModuleTest, init)
|
||||
{
|
||||
ExhaustibleBlockDevice b(&bd_mock, ERASE_CYCLES);
|
||||
EXPECT_EQ(b.get_erase_size(), 0);
|
||||
EXPECT_EQ(b.get_erase_size(0), 0);
|
||||
EXPECT_EQ(b.get_erase_value(), BD_ERROR_DEVICE_ERROR);
|
||||
EXPECT_EQ(b.get_read_size(), 0);
|
||||
EXPECT_EQ(b.get_program_size(), 0);
|
||||
EXPECT_EQ(b.size(), 0);
|
||||
b.set_erase_cycles(0, 100); // This should not take effect.
|
||||
EXPECT_EQ(b.get_erase_cycles(0), 0);
|
||||
EXPECT_EQ(b.erase(0, BLOCK_SIZE), BD_ERROR_DEVICE_ERROR);
|
||||
EXPECT_EQ(b.program(magic, 0, BLOCK_SIZE), BD_ERROR_DEVICE_ERROR);
|
||||
EXPECT_EQ(b.read(buf, 0, BLOCK_SIZE), BD_ERROR_DEVICE_ERROR);
|
||||
EXPECT_EQ(b.deinit(), BD_ERROR_OK);
|
||||
EXPECT_EQ(b.sync(), BD_ERROR_DEVICE_ERROR);
|
||||
|
||||
EXPECT_CALL(bd_mock, init());
|
||||
EXPECT_EQ(b.init(), 0);
|
||||
|
||||
EXPECT_CALL(bd_mock, get_type()).WillOnce(Return("mytype"));
|
||||
EXPECT_CALL(bd_mock, deinit());
|
||||
|
||||
EXPECT_EQ(b.get_erase_size(), bd_mock.get_erase_size());
|
||||
EXPECT_EQ(b.get_erase_size(0), bd_mock.get_erase_size(0));
|
||||
EXPECT_EQ(b.get_erase_value(), bd_mock.get_erase_value());
|
||||
EXPECT_NE(b.get_erase_cycles(0), 100);
|
||||
EXPECT_EQ(b.get_program_size(), 512);
|
||||
EXPECT_EQ(b.get_read_size(), 512);
|
||||
EXPECT_EQ(b.size(), bd_mock.size());
|
||||
EXPECT_EQ(b.get_type(), "mytype");
|
||||
EXPECT_EQ(b.deinit(), 0);
|
||||
}
|
||||
|
||||
TEST_F(ExhaustibleBlockModuleTest, program_unaligned)
|
||||
{
|
||||
EXPECT_EQ(bd.program(magic, 0, BLOCK_SIZE-1), BD_ERROR_DEVICE_ERROR);
|
||||
}
|
||||
|
||||
TEST_F(ExhaustibleBlockModuleTest, erase_cycle_limit_reached)
|
||||
{
|
||||
EXPECT_NE(bd.get_erase_cycles(0), 0);
|
||||
|
||||
EXPECT_CALL(bd_mock, program(_, 0, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillRepeatedly(Return(BD_ERROR_OK));
|
||||
|
||||
EXPECT_EQ(bd.program(magic, 0, BLOCK_SIZE), 0);
|
||||
|
||||
EXPECT_CALL(bd_mock, erase(0, BLOCK_SIZE))
|
||||
.Times(ERASE_CYCLES)
|
||||
.WillRepeatedly(Return(BD_ERROR_OK));
|
||||
|
||||
for (int i = 0; i < ERASE_CYCLES; i++) {
|
||||
EXPECT_EQ(bd.erase(0, BLOCK_SIZE), 0);
|
||||
}
|
||||
EXPECT_EQ(bd.get_erase_cycles(0), 0);
|
||||
|
||||
// This calls are expect not to happen.
|
||||
EXPECT_EQ(bd.erase(0, BLOCK_SIZE), BD_ERROR_DEVICE_ERROR);
|
||||
EXPECT_EQ(bd.program(magic2, 0, BLOCK_SIZE), BD_ERROR_DEVICE_ERROR);
|
||||
}
|
||||
|
||||
TEST_F(ExhaustibleBlockModuleTest, erase_invalid)
|
||||
{
|
||||
ASSERT_GT(ERASE_CYCLES, 1);
|
||||
|
||||
EXPECT_EQ(bd.get_erase_cycles(0), ERASE_CYCLES);
|
||||
|
||||
// Unaligned erase should fail
|
||||
EXPECT_EQ(bd.erase(0, BLOCK_SIZE-1), BD_ERROR_DEVICE_ERROR);
|
||||
// Number of erase cycles should not change
|
||||
EXPECT_EQ(bd.get_erase_cycles(0), ERASE_CYCLES);
|
||||
}
|
||||
|
||||
TEST_F(ExhaustibleBlockModuleTest, set_erase_cycles)
|
||||
{
|
||||
EXPECT_EQ(bd.get_erase_cycles(0), ERASE_CYCLES);
|
||||
bd.set_erase_cycles(0, ERASE_CYCLES+1);
|
||||
EXPECT_EQ(bd.get_erase_cycles(0), ERASE_CYCLES+1);
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
|
||||
####################
|
||||
# UNIT TESTS
|
||||
####################
|
||||
|
||||
set(unittest-includes ${unittest-includes}
|
||||
.
|
||||
..
|
||||
)
|
||||
|
||||
set(unittest-sources
|
||||
../features/storage/blockdevice/ExhaustibleBlockDevice.cpp
|
||||
stubs/mbed_atomic_stub.c
|
||||
stubs/mbed_assert_stub.cpp
|
||||
)
|
||||
|
||||
set(unittest-test-sources
|
||||
features/storage/blockdevice/ExhaustibleBlockDevice/test_ExhaustibleBlockDevice.cpp
|
||||
)
|
|
@ -0,0 +1,165 @@
|
|||
/* Copyright (c) 2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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 "gtest/gtest.h"
|
||||
#include "features/storage/blockdevice/FlashSimBlockDevice.h"
|
||||
#include "stubs/BlockDevice_mock.h"
|
||||
|
||||
#define BLOCK_SIZE (512)
|
||||
#define DEVICE_SIZE (BLOCK_SIZE*10)
|
||||
#define ERASE_VALUE (2)
|
||||
|
||||
using ::testing::_;
|
||||
using ::testing::Return;
|
||||
using ::testing::ReturnArg;
|
||||
using ::testing::SaveArg;
|
||||
using ::testing::SaveArgPointee;
|
||||
using ::testing::SetArrayArgument;
|
||||
using ::testing::SetArgPointee;
|
||||
using ::testing::SetArgReferee;
|
||||
using ::testing::DoAll;
|
||||
|
||||
class FlashSimBlockModuleTest : public testing::Test {
|
||||
protected:
|
||||
BlockDeviceMock bd_mock;
|
||||
FlashSimBlockDevice bd{&bd_mock, ERASE_VALUE};
|
||||
uint8_t *magic;
|
||||
uint8_t *magic2;
|
||||
uint8_t *erased_mem;
|
||||
uint8_t *buf;
|
||||
virtual void SetUp()
|
||||
{
|
||||
ON_CALL(bd_mock, size()).WillByDefault(Return(BLOCK_SIZE));
|
||||
ON_CALL(bd_mock, get_erase_size(_)).WillByDefault(Return(BLOCK_SIZE));
|
||||
ON_CALL(bd_mock, get_erase_size()).WillByDefault(Return(BLOCK_SIZE));
|
||||
ON_CALL(bd_mock, get_program_size()).WillByDefault(Return(BLOCK_SIZE));
|
||||
ON_CALL(bd_mock, get_read_size()).WillByDefault(Return(BLOCK_SIZE));
|
||||
|
||||
EXPECT_CALL(bd_mock, init());
|
||||
ASSERT_EQ(bd.init(), 0);
|
||||
magic = new uint8_t[BLOCK_SIZE];
|
||||
magic2 = new uint8_t[BLOCK_SIZE];
|
||||
erased_mem = new uint8_t[BLOCK_SIZE];
|
||||
buf = new uint8_t[BLOCK_SIZE];
|
||||
// Generate simple pattern to verify against
|
||||
for (int i = 0; i < BLOCK_SIZE; i++) {
|
||||
magic[i] = 0xaa + i;
|
||||
magic2[i] = 0xaa + i + 1;
|
||||
erased_mem[i] = ERASE_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void TearDown()
|
||||
{
|
||||
EXPECT_CALL(bd_mock, deinit());
|
||||
ASSERT_EQ(bd.deinit(), 0);
|
||||
delete[] magic;
|
||||
delete[] magic2;
|
||||
delete[] buf;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(FlashSimBlockModuleTest, init)
|
||||
{
|
||||
FlashSimBlockDevice b(&bd_mock, ERASE_VALUE);
|
||||
EXPECT_EQ(b.get_erase_size(), 0);
|
||||
EXPECT_EQ(b.get_erase_size(0), 0);
|
||||
EXPECT_EQ(b.get_read_size(), 0);
|
||||
EXPECT_EQ(b.get_program_size(), 0);
|
||||
EXPECT_EQ(b.size(), 0);
|
||||
EXPECT_EQ(b.erase(0, BLOCK_SIZE), BD_ERROR_DEVICE_ERROR);
|
||||
EXPECT_EQ(b.program(magic, 0, BLOCK_SIZE), BD_ERROR_DEVICE_ERROR);
|
||||
EXPECT_EQ(b.read(buf, 0, BLOCK_SIZE), BD_ERROR_DEVICE_ERROR);
|
||||
EXPECT_EQ(b.deinit(), BD_ERROR_OK);
|
||||
EXPECT_EQ(b.sync(), BD_ERROR_DEVICE_ERROR);
|
||||
|
||||
EXPECT_CALL(bd_mock, init());
|
||||
EXPECT_EQ(b.init(), 0);
|
||||
|
||||
EXPECT_CALL(bd_mock, get_type()).WillOnce(Return("mytype"));
|
||||
EXPECT_CALL(bd_mock, deinit());
|
||||
|
||||
EXPECT_EQ(b.get_erase_size(), bd_mock.get_erase_size());
|
||||
EXPECT_EQ(b.get_erase_size(0), bd_mock.get_erase_size(0));
|
||||
EXPECT_EQ(b.get_erase_value(), ERASE_VALUE);
|
||||
EXPECT_EQ(b.get_program_size(), 512);
|
||||
EXPECT_EQ(b.get_read_size(), 512);
|
||||
EXPECT_EQ(b.size(), bd_mock.size());
|
||||
EXPECT_EQ(b.get_type(), "mytype");
|
||||
EXPECT_EQ(b.sync(), 0);
|
||||
EXPECT_EQ(b.deinit(), 0);
|
||||
|
||||
}
|
||||
|
||||
TEST_F(FlashSimBlockModuleTest, program_unaligned)
|
||||
{
|
||||
EXPECT_EQ(bd.program(magic, 0, BLOCK_SIZE-1), BD_ERROR_DEVICE_ERROR);
|
||||
}
|
||||
|
||||
TEST_F(FlashSimBlockModuleTest, program_no_erase)
|
||||
{
|
||||
// Data has not been erased, so this fails
|
||||
EXPECT_EQ(bd.program(magic, 0, BLOCK_SIZE), mbed::BD_ERROR_NOT_ERASED);
|
||||
|
||||
EXPECT_CALL(bd_mock, program(ByteBufferMatcher(erased_mem, BLOCK_SIZE), 0, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(Return(BD_ERROR_OK));
|
||||
|
||||
EXPECT_EQ(bd.erase(0, BLOCK_SIZE), 0);
|
||||
|
||||
EXPECT_CALL(bd_mock, program(ByteBufferMatcher(magic, BLOCK_SIZE), 0, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(Return(BD_ERROR_OK));
|
||||
|
||||
EXPECT_EQ(bd.program(magic, 0, BLOCK_SIZE), 0);
|
||||
|
||||
EXPECT_CALL(bd_mock, read(_, 0, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(DoAll(SetArg0ToCharPtr(magic, BLOCK_SIZE), Return(BD_ERROR_OK)));
|
||||
|
||||
// No program() call should happen for this call.
|
||||
EXPECT_EQ(bd.program(magic2, 0, BLOCK_SIZE), mbed::BD_ERROR_NOT_ERASED);
|
||||
}
|
||||
|
||||
TEST_F(FlashSimBlockModuleTest, reprogram)
|
||||
{
|
||||
EXPECT_CALL(bd_mock, program(ByteBufferMatcher(erased_mem, BLOCK_SIZE), 0, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(Return(BD_ERROR_OK));
|
||||
|
||||
EXPECT_EQ(bd.erase(0, BLOCK_SIZE), 0);
|
||||
|
||||
EXPECT_CALL(bd_mock, program(ByteBufferMatcher(magic, BLOCK_SIZE), 0, BLOCK_SIZE))
|
||||
.Times(2)
|
||||
.WillRepeatedly(Return(BD_ERROR_OK));
|
||||
|
||||
EXPECT_EQ(bd.program(magic, 0, BLOCK_SIZE), 0);
|
||||
|
||||
// Programming the same data.
|
||||
EXPECT_EQ(bd.program(magic, 0, BLOCK_SIZE), 0);
|
||||
|
||||
EXPECT_CALL(bd_mock, program(ByteBufferMatcher(erased_mem, BLOCK_SIZE), 0, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(Return(BD_ERROR_OK));
|
||||
|
||||
EXPECT_EQ(bd.erase(0, BLOCK_SIZE), 0);
|
||||
}
|
||||
|
||||
TEST_F(FlashSimBlockModuleTest, erase_invalid)
|
||||
{
|
||||
// Unaligned erase should fail
|
||||
EXPECT_EQ(bd.erase(0, BLOCK_SIZE-1), BD_ERROR_DEVICE_ERROR);
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
|
||||
####################
|
||||
# UNIT TESTS
|
||||
####################
|
||||
|
||||
set(unittest-includes ${unittest-includes}
|
||||
.
|
||||
..
|
||||
)
|
||||
|
||||
set(unittest-sources
|
||||
../features/storage/blockdevice/FlashSimBlockDevice.cpp
|
||||
stubs/mbed_atomic_stub.c
|
||||
stubs/mbed_assert_stub.cpp
|
||||
)
|
||||
|
||||
set(unittest-test-sources
|
||||
features/storage/blockdevice/FlashSimBlockDevice/test_FlashSimBlockDevice.cpp
|
||||
)
|
|
@ -0,0 +1,309 @@
|
|||
/* Copyright (c) 2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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 "gtest/gtest.h"
|
||||
#include "features/storage/blockdevice/MBRBlockDevice.h"
|
||||
#include "stubs/BlockDevice_mock.h"
|
||||
|
||||
#define BLOCK_SIZE (512)
|
||||
#define PART_DESC_SIZE (16)
|
||||
#define PARTITIONS (4)
|
||||
#define MBR_SIZE (PARTITIONS * PART_DESC_SIZE + 2)
|
||||
#define SECTORS_NUM (20)
|
||||
#define DEVICE_SIZE (BLOCK_SIZE * SECTORS_NUM)
|
||||
|
||||
using ::testing::_;
|
||||
using ::testing::Return;
|
||||
using ::testing::DoAll;
|
||||
|
||||
class MBRBlockModuleTest : public testing::Test {
|
||||
protected:
|
||||
BlockDeviceMock bd_mock;
|
||||
MBRBlockDevice bd{&bd_mock, PARTITIONS};
|
||||
uint8_t *magic;
|
||||
uint8_t *magic2;
|
||||
uint8_t *buf;
|
||||
uint8_t MBR[MBR_SIZE] = {
|
||||
// mba_entry 0
|
||||
0x00, // status
|
||||
0x00, 0x02, 0x00, // chs_start
|
||||
0x0C, // type (FAT32)
|
||||
0x00, 0x05, 0x00, // chs_stop
|
||||
0x01, 0x00, 0x00, 0x00, // lba_offset
|
||||
SECTORS_NUM/4-1, 0x00, 0x00, 0x00, // lba_size
|
||||
// mba_entry 1
|
||||
0x00, // status
|
||||
0x00, 0x06, 0x00, // chs_start
|
||||
0x0C, // type
|
||||
0x00, 0x0A, 0x00, // chs_stop
|
||||
SECTORS_NUM/4, 0x00, 0x00, 0x00, // lba_offset
|
||||
SECTORS_NUM/4, 0x00, 0x00, 0x00, // lba_size
|
||||
// mba_entry 2
|
||||
0x00, // status
|
||||
0x00, 0x0B, 0x00, // chs_start
|
||||
0x83, // type (Linux)
|
||||
0x00, 0x0F, 0x00, // chs_stop
|
||||
2*SECTORS_NUM/4, 0x00, 0x00, 0x00, // lba_offset
|
||||
SECTORS_NUM/4, 0x00, 0x00, 0x00, // lba_size
|
||||
// mba_entry 3
|
||||
0x00, // status
|
||||
0x00, 0x10, 0x00, // chs_start
|
||||
0x82, // type (Linux swap)
|
||||
0x00, 0x14, 0x00, // chs_stop
|
||||
3*SECTORS_NUM/4, 0x00, 0x00, 0x00, // lba_offset
|
||||
SECTORS_NUM/4, 0x00, 0x00, 0x00, // lba_size (in sectors)
|
||||
// signature
|
||||
0x55, // signature 0
|
||||
0xaa // signature 1
|
||||
};
|
||||
uint8_t MBRbuf[BLOCK_SIZE];
|
||||
virtual void SetUp()
|
||||
{
|
||||
memset(MBRbuf, 0, BLOCK_SIZE);
|
||||
memcpy(MBRbuf + (BLOCK_SIZE - MBR_SIZE), MBR, MBR_SIZE);
|
||||
|
||||
ON_CALL(bd_mock, size()).WillByDefault(Return(DEVICE_SIZE));
|
||||
ON_CALL(bd_mock, get_erase_size(_)).WillByDefault(Return(BLOCK_SIZE));
|
||||
ON_CALL(bd_mock, get_erase_size()).WillByDefault(Return(BLOCK_SIZE));
|
||||
ON_CALL(bd_mock, get_program_size()).WillByDefault(Return(BLOCK_SIZE));
|
||||
ON_CALL(bd_mock, get_read_size()).WillByDefault(Return(BLOCK_SIZE));
|
||||
ON_CALL(bd_mock, is_valid_erase(_, _)).WillByDefault(Return(true));
|
||||
ON_CALL(bd_mock, init()).WillByDefault(Return(BD_ERROR_OK));
|
||||
|
||||
EXPECT_CALL(bd_mock, read(_, 0, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(DoAll(SetArg0ToCharPtr(MBRbuf, BLOCK_SIZE), Return(BD_ERROR_OK)));
|
||||
|
||||
magic = new uint8_t[BLOCK_SIZE];
|
||||
magic2 = new uint8_t[BLOCK_SIZE];
|
||||
buf = new uint8_t[BLOCK_SIZE];
|
||||
|
||||
ASSERT_EQ(bd.init(), BD_ERROR_OK);
|
||||
// Generate simple pattern to verify against
|
||||
for (int i = 0; i < BLOCK_SIZE; i++) {
|
||||
magic[i] = 0xaa + i;
|
||||
magic2[i] = 0xaa + i + 1;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void TearDown()
|
||||
{
|
||||
EXPECT_CALL(bd_mock, deinit());
|
||||
ASSERT_EQ(bd.deinit(), 0);
|
||||
delete[] magic;
|
||||
delete[] magic2;
|
||||
delete[] buf;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(MBRBlockModuleTest, init)
|
||||
{
|
||||
MBRBlockDevice b(&bd_mock, PARTITIONS);
|
||||
EXPECT_EQ(b.get_erase_size(), 0);
|
||||
EXPECT_EQ(b.get_erase_size(0), 0);
|
||||
EXPECT_EQ(b.get_erase_value(), BD_ERROR_DEVICE_ERROR);
|
||||
EXPECT_EQ(b.get_read_size(), 0);
|
||||
EXPECT_EQ(b.get_program_size(), 0);
|
||||
EXPECT_EQ(b.size(), 0);
|
||||
EXPECT_EQ(b.erase(0, BLOCK_SIZE), BD_ERROR_DEVICE_ERROR);
|
||||
EXPECT_EQ(b.program(magic, 0, BLOCK_SIZE), BD_ERROR_DEVICE_ERROR);
|
||||
EXPECT_EQ(b.read(buf, 0, BLOCK_SIZE), BD_ERROR_DEVICE_ERROR);
|
||||
EXPECT_EQ(b.deinit(), BD_ERROR_OK);
|
||||
EXPECT_EQ(b.sync(), BD_ERROR_DEVICE_ERROR);
|
||||
|
||||
EXPECT_CALL(bd_mock, read(_, 0, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(DoAll(SetArg0ToCharPtr(MBRbuf, BLOCK_SIZE), Return(BD_ERROR_OK)));
|
||||
|
||||
EXPECT_CALL(bd_mock, init());
|
||||
EXPECT_EQ(b.init(), 0);
|
||||
|
||||
EXPECT_CALL(bd_mock, get_type()).WillOnce(Return("mytype"));
|
||||
EXPECT_CALL(bd_mock, deinit());
|
||||
|
||||
EXPECT_EQ(b.get_erase_size(), bd_mock.get_erase_size());
|
||||
EXPECT_EQ(b.get_erase_size(0), bd_mock.get_erase_size(0));
|
||||
EXPECT_EQ(b.get_erase_value(), bd_mock.get_erase_value());
|
||||
EXPECT_EQ(b.get_program_size(), 512);
|
||||
EXPECT_EQ(b.get_read_size(), 512);
|
||||
EXPECT_EQ(b.get_partition_number(), PARTITIONS);
|
||||
EXPECT_EQ(b.get_partition_start(), 3*DEVICE_SIZE/4);
|
||||
EXPECT_EQ(b.get_partition_stop(), DEVICE_SIZE);
|
||||
EXPECT_EQ(b.get_partition_type(), 0x82);
|
||||
EXPECT_EQ(b.size(), DEVICE_SIZE/4);
|
||||
EXPECT_EQ(b.get_type(), "mytype");
|
||||
EXPECT_EQ(b.deinit(), 0);
|
||||
}
|
||||
|
||||
TEST_F(MBRBlockModuleTest, init_incorrect_signature)
|
||||
{
|
||||
MBRbuf[BLOCK_SIZE - MBR_SIZE + 64] = 0x00;
|
||||
|
||||
EXPECT_CALL(bd_mock, init());
|
||||
EXPECT_CALL(bd_mock, read(_, 0, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(DoAll(SetArg0ToCharPtr(MBRbuf, BLOCK_SIZE), Return(BD_ERROR_OK)));
|
||||
|
||||
MBRBlockDevice b(&bd_mock, PARTITIONS);
|
||||
EXPECT_EQ(b.init(), mbed::BD_ERROR_INVALID_MBR);
|
||||
MBRbuf[BLOCK_SIZE - MBR_SIZE + 64] = 0xaa;
|
||||
}
|
||||
|
||||
TEST_F(MBRBlockModuleTest, init_invalid_type)
|
||||
{
|
||||
MBRbuf[BLOCK_SIZE - MBR_SIZE + 4] = 0x05; // 0x05 is extended partition - not supported
|
||||
|
||||
EXPECT_CALL(bd_mock, init());
|
||||
EXPECT_CALL(bd_mock, read(_, 0, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(DoAll(SetArg0ToCharPtr(MBRbuf, BLOCK_SIZE), Return(BD_ERROR_OK)));
|
||||
|
||||
MBRBlockDevice b(&bd_mock, 1);
|
||||
EXPECT_EQ(b.init(), mbed::BD_ERROR_INVALID_PARTITION);
|
||||
MBRbuf[BLOCK_SIZE - MBR_SIZE + 4] = 0x0C;
|
||||
}
|
||||
|
||||
TEST_F(MBRBlockModuleTest, init_invalid_status)
|
||||
{
|
||||
MBRbuf[BLOCK_SIZE - MBR_SIZE] = 0x01;
|
||||
|
||||
EXPECT_CALL(bd_mock, init());
|
||||
EXPECT_CALL(bd_mock, read(_, 0, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(DoAll(SetArg0ToCharPtr(MBRbuf, BLOCK_SIZE), Return(BD_ERROR_OK)));
|
||||
|
||||
MBRBlockDevice b(&bd_mock, 1);
|
||||
EXPECT_EQ(b.init(), mbed::BD_ERROR_INVALID_PARTITION);
|
||||
MBRbuf[BLOCK_SIZE - MBR_SIZE] = 0x00;
|
||||
}
|
||||
|
||||
TEST_F(MBRBlockModuleTest, program_unaligned)
|
||||
{
|
||||
EXPECT_EQ(bd.program(magic, 0, BLOCK_SIZE-1), BD_ERROR_DEVICE_ERROR);
|
||||
}
|
||||
|
||||
TEST_F(MBRBlockModuleTest, program_read_erase)
|
||||
{
|
||||
constexpr uint32_t partition_offset = BLOCK_SIZE * 3 * SECTORS_NUM / PARTITIONS;
|
||||
//Unalinged addressing is not allowed
|
||||
EXPECT_EQ(bd.program(magic, 0, BLOCK_SIZE-1), BD_ERROR_DEVICE_ERROR);
|
||||
EXPECT_EQ(bd.erase(0, BLOCK_SIZE-1), BD_ERROR_DEVICE_ERROR);
|
||||
EXPECT_EQ(bd.read(magic, 0, BLOCK_SIZE-1), BD_ERROR_DEVICE_ERROR);
|
||||
|
||||
EXPECT_CALL(bd_mock, program(ByteBufferMatcher(magic, BLOCK_SIZE), partition_offset, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(Return(BD_ERROR_OK));
|
||||
|
||||
EXPECT_CALL(bd_mock, read(_, partition_offset, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(DoAll(SetArg0ToCharPtr(magic, BLOCK_SIZE), Return(BD_ERROR_OK)));
|
||||
|
||||
EXPECT_CALL(bd_mock, erase(partition_offset, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(Return(BD_ERROR_OK));
|
||||
|
||||
EXPECT_EQ(bd.program(magic, 0, BLOCK_SIZE), BD_ERROR_OK);
|
||||
EXPECT_EQ(bd.read(buf, 0, BLOCK_SIZE), BD_ERROR_OK);
|
||||
EXPECT_EQ(0, memcmp(buf, magic, BLOCK_SIZE));
|
||||
EXPECT_EQ(bd.erase(0, BLOCK_SIZE), BD_ERROR_OK);
|
||||
}
|
||||
|
||||
TEST_F(MBRBlockModuleTest, partitioning)
|
||||
{
|
||||
uint8_t MBRbuf2[BLOCK_SIZE];
|
||||
memset(MBRbuf2, 0xFF, BLOCK_SIZE);
|
||||
memset(MBRbuf2 + BLOCK_SIZE - MBR_SIZE, 0x0, MBR_SIZE);
|
||||
|
||||
|
||||
// Partition 1
|
||||
memcpy(MBRbuf2 + BLOCK_SIZE - MBR_SIZE, MBRbuf + BLOCK_SIZE - MBR_SIZE, PART_DESC_SIZE);
|
||||
|
||||
EXPECT_CALL(bd_mock, read(_, 0, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(DoAll(SetArg0ToCharPtr(MBRbuf2, BLOCK_SIZE), Return(BD_ERROR_OK)));
|
||||
|
||||
EXPECT_CALL(bd_mock, erase(0, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(Return(BD_ERROR_OK));
|
||||
|
||||
MBRbuf2[BLOCK_SIZE - 2] = MBRbuf[BLOCK_SIZE - 2]; //0x55
|
||||
MBRbuf2[BLOCK_SIZE - 1] = MBRbuf[BLOCK_SIZE - 1]; //0xaa
|
||||
|
||||
EXPECT_CALL(bd_mock, program(ByteBufferMatcher(MBRbuf2, BLOCK_SIZE), 0, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(Return(BD_ERROR_OK));
|
||||
|
||||
EXPECT_EQ(MBRBlockDevice::partition(&bd_mock, 1, 0x0C, 0,
|
||||
(SECTORS_NUM / 4) * BLOCK_SIZE), 0);
|
||||
|
||||
|
||||
// Partition 2
|
||||
memcpy(MBRbuf2 + BLOCK_SIZE - MBR_SIZE + PART_DESC_SIZE,
|
||||
MBRbuf + BLOCK_SIZE - MBR_SIZE + PART_DESC_SIZE, PART_DESC_SIZE);
|
||||
|
||||
EXPECT_CALL(bd_mock, read(_, 0, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(DoAll(SetArg0ToCharPtr(MBRbuf2, BLOCK_SIZE), Return(BD_ERROR_OK)));
|
||||
|
||||
EXPECT_CALL(bd_mock, erase(0, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(Return(BD_ERROR_OK));
|
||||
|
||||
EXPECT_CALL(bd_mock, program(ByteBufferMatcher(MBRbuf2, BLOCK_SIZE), 0, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(Return(BD_ERROR_OK));
|
||||
|
||||
EXPECT_EQ(MBRBlockDevice::partition(&bd_mock, 2, 0x0C, (SECTORS_NUM / 4) * BLOCK_SIZE,
|
||||
(SECTORS_NUM / 4) * BLOCK_SIZE * 2), 0);
|
||||
|
||||
|
||||
// Partition 3
|
||||
memcpy(MBRbuf2 + BLOCK_SIZE - MBR_SIZE + 2 * PART_DESC_SIZE,
|
||||
MBRbuf + BLOCK_SIZE - MBR_SIZE + 2 * PART_DESC_SIZE, PART_DESC_SIZE);
|
||||
|
||||
EXPECT_CALL(bd_mock, read(_, 0, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(DoAll(SetArg0ToCharPtr(MBRbuf2, BLOCK_SIZE), Return(BD_ERROR_OK)));
|
||||
|
||||
EXPECT_CALL(bd_mock, erase(0, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(Return(BD_ERROR_OK));
|
||||
|
||||
EXPECT_CALL(bd_mock, program(ByteBufferMatcher(MBRbuf2, BLOCK_SIZE), 0, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(Return(BD_ERROR_OK));
|
||||
|
||||
EXPECT_EQ(MBRBlockDevice::partition(&bd_mock, 3, 0x83, (SECTORS_NUM / 4) * BLOCK_SIZE * 2,
|
||||
(SECTORS_NUM / 4) * BLOCK_SIZE * 3), 0);
|
||||
|
||||
// Partition 4
|
||||
memcpy(MBRbuf2 + BLOCK_SIZE - MBR_SIZE + 3 * PART_DESC_SIZE,
|
||||
MBRbuf + BLOCK_SIZE - MBR_SIZE + 3 * PART_DESC_SIZE, PART_DESC_SIZE);
|
||||
|
||||
EXPECT_CALL(bd_mock, read(_, 0, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(DoAll(SetArg0ToCharPtr(MBRbuf2, BLOCK_SIZE), Return(BD_ERROR_OK)));
|
||||
|
||||
EXPECT_CALL(bd_mock, erase(0, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(Return(BD_ERROR_OK));
|
||||
|
||||
EXPECT_CALL(bd_mock, program(ByteBufferMatcher(MBRbuf2, BLOCK_SIZE), 0, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(Return(BD_ERROR_OK));
|
||||
|
||||
EXPECT_EQ(MBRBlockDevice::partition(&bd_mock, 4, 0x82, -(SECTORS_NUM / 4) * BLOCK_SIZE), 0);
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
|
||||
####################
|
||||
# UNIT TESTS
|
||||
####################
|
||||
|
||||
set(unittest-includes ${unittest-includes}
|
||||
.
|
||||
..
|
||||
)
|
||||
|
||||
set(unittest-sources
|
||||
../features/storage/blockdevice/MBRBlockDevice.cpp
|
||||
stubs/mbed_atomic_stub.c
|
||||
stubs/mbed_assert_stub.cpp
|
||||
)
|
||||
|
||||
set(unittest-test-sources
|
||||
features/storage/blockdevice/MBRBlockDevice/test_MBRBlockDevice.cpp
|
||||
)
|
|
@ -0,0 +1,93 @@
|
|||
/* Copyright (c) 2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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 "gtest/gtest.h"
|
||||
#include "features/storage/blockdevice/ObservingBlockDevice.h"
|
||||
#include "features/storage/blockdevice/ReadOnlyBlockDevice.h"
|
||||
#include "stubs/BlockDevice_mock.h"
|
||||
|
||||
using ::testing::_;
|
||||
using ::testing::Return;
|
||||
|
||||
#define BLOCK_SIZE (512)
|
||||
#define DEVICE_SIZE (BLOCK_SIZE*10)
|
||||
|
||||
class ObservingBlockModuleTest : public testing::Test {
|
||||
protected:
|
||||
BlockDeviceMock bd_mock;
|
||||
ObservingBlockDevice bd{&bd_mock};
|
||||
uint8_t *magic;
|
||||
static int cnt;
|
||||
virtual void SetUp()
|
||||
{
|
||||
cnt = 0;
|
||||
ASSERT_EQ(bd.init(), 0);
|
||||
magic = new uint8_t[BLOCK_SIZE];
|
||||
// Generate simple pattern to verify against
|
||||
for (int i = 0; i < BLOCK_SIZE; i++) {
|
||||
magic[i] = 0xaa + i;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void TearDown()
|
||||
{
|
||||
ASSERT_EQ(bd.deinit(), 0);
|
||||
delete[] magic;
|
||||
}
|
||||
|
||||
static void bd_change(BlockDevice* bd) {
|
||||
cnt++;
|
||||
}
|
||||
};
|
||||
|
||||
int ObservingBlockModuleTest::cnt = 0;
|
||||
|
||||
TEST_F(ObservingBlockModuleTest, init)
|
||||
{
|
||||
EXPECT_EQ(bd.get_erase_size(), bd_mock.get_erase_size());
|
||||
EXPECT_EQ(bd.get_erase_size(0), bd_mock.get_erase_size(0));
|
||||
EXPECT_EQ(bd.get_erase_value(), bd_mock.get_erase_value());
|
||||
EXPECT_EQ(bd.get_program_size(), bd_mock.get_program_size());
|
||||
EXPECT_EQ(bd.get_read_size(), bd_mock.get_read_size());
|
||||
EXPECT_EQ(bd.size(), bd_mock.size());
|
||||
EXPECT_EQ(bd.get_type(), bd_mock.get_type());
|
||||
}
|
||||
|
||||
TEST_F(ObservingBlockModuleTest, program_erase_cb)
|
||||
{
|
||||
EXPECT_CALL(bd_mock, program(magic, 0, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(Return(BD_ERROR_OK));
|
||||
|
||||
bd.attach(this->bd_change);
|
||||
EXPECT_EQ(bd.program(magic, 0, BLOCK_SIZE), 0);
|
||||
EXPECT_EQ(cnt, 1);
|
||||
|
||||
EXPECT_CALL(bd_mock, erase(0, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(Return(BD_ERROR_OK));
|
||||
|
||||
EXPECT_EQ(bd.erase(0, BLOCK_SIZE), 0);
|
||||
EXPECT_EQ(cnt, 2);
|
||||
|
||||
EXPECT_CALL(bd_mock, read(_, 0, BLOCK_SIZE))
|
||||
.Times(1)
|
||||
.WillOnce(Return(BD_ERROR_OK));
|
||||
|
||||
uint8_t buf[BLOCK_SIZE];
|
||||
EXPECT_EQ(bd.read(buf, 0, BLOCK_SIZE), 0);
|
||||
EXPECT_EQ(cnt, 2); // Counter stays the same
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
|
||||
####################
|
||||
# UNIT TESTS
|
||||
####################
|
||||
|
||||
set(unittest-includes ${unittest-includes}
|
||||
.
|
||||
..
|
||||
)
|
||||
|
||||
set(unittest-sources
|
||||
../features/storage/blockdevice/ObservingBlockDevice.cpp
|
||||
../features/storage/blockdevice/ReadOnlyBlockDevice.cpp
|
||||
stubs/mbed_atomic_stub.c
|
||||
stubs/mbed_assert_stub.cpp
|
||||
stubs/mbed_error.c
|
||||
)
|
||||
|
||||
set(unittest-test-sources
|
||||
features/storage/blockdevice/ObservingBlockDevice/test_ObservingBlockDevice.cpp
|
||||
stubs/BlockDevice_mock.h
|
||||
)
|
|
@ -0,0 +1,94 @@
|
|||
/* Copyright (c) 2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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 "gtest/gtest.h"
|
||||
#include "stubs/BlockDevice_mock.h"
|
||||
#include "features/storage/blockdevice/ProfilingBlockDevice.h"
|
||||
|
||||
#define BLOCK_SIZE (512)
|
||||
#define DEVICE_SIZE (BLOCK_SIZE*10)
|
||||
|
||||
using ::testing::_;
|
||||
using ::testing::Return;
|
||||
using ::testing::DoAll;
|
||||
|
||||
class ProfilingBlockModuleTest : public testing::Test {
|
||||
protected:
|
||||
BlockDeviceMock bd_mock;
|
||||
ProfilingBlockDevice bd{&bd_mock};
|
||||
uint8_t *magic;
|
||||
uint8_t *buf;
|
||||
virtual void SetUp()
|
||||
{
|
||||
ON_CALL(bd_mock, size()).WillByDefault(Return(DEVICE_SIZE));
|
||||
ON_CALL(bd_mock, get_erase_size(_)).WillByDefault(Return(BLOCK_SIZE));
|
||||
ON_CALL(bd_mock, get_erase_size()).WillByDefault(Return(BLOCK_SIZE));
|
||||
ON_CALL(bd_mock, get_program_size()).WillByDefault(Return(BLOCK_SIZE));
|
||||
ON_CALL(bd_mock, get_read_size()).WillByDefault(Return(BLOCK_SIZE));
|
||||
ON_CALL(bd_mock, is_valid_erase(_, _)).WillByDefault(Return(true));
|
||||
ON_CALL(bd_mock, init()).WillByDefault(Return(BD_ERROR_OK));
|
||||
|
||||
ASSERT_EQ(bd.init(), 0);
|
||||
magic = new uint8_t[BLOCK_SIZE];
|
||||
buf = new uint8_t[BLOCK_SIZE];
|
||||
// Generate simple pattern to verify against
|
||||
for (int i = 0; i < BLOCK_SIZE; i++) {
|
||||
magic[i] = 0xaa + i;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void TearDown()
|
||||
{
|
||||
ASSERT_EQ(bd.deinit(), 0);
|
||||
delete[] magic;
|
||||
delete[] buf;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(ProfilingBlockModuleTest, init)
|
||||
{
|
||||
EXPECT_EQ(bd.get_erase_size(), bd_mock.get_erase_size());
|
||||
EXPECT_EQ(bd.get_erase_size(0), bd_mock.get_erase_size(0));
|
||||
EXPECT_EQ(bd.get_erase_value(), bd_mock.get_erase_value());
|
||||
EXPECT_EQ(bd.get_program_size(), bd_mock.get_program_size());
|
||||
EXPECT_EQ(bd.get_read_size(), bd_mock.get_read_size());
|
||||
EXPECT_EQ(bd.size(), bd_mock.size());
|
||||
EXPECT_EQ(bd.get_type(), bd_mock.get_type());
|
||||
}
|
||||
|
||||
TEST_F(ProfilingBlockModuleTest, count) {
|
||||
EXPECT_EQ(bd.get_read_count(), 0);
|
||||
EXPECT_EQ(bd.get_program_count(), 0);
|
||||
EXPECT_EQ(bd.get_erase_count(), 0);
|
||||
|
||||
EXPECT_EQ(bd.program(magic, 0, BLOCK_SIZE), 0);
|
||||
EXPECT_EQ(bd.read(buf, 0, BLOCK_SIZE), 0);
|
||||
EXPECT_EQ(bd.read(buf, 0, BLOCK_SIZE), 0);
|
||||
EXPECT_EQ(bd.erase(0, BLOCK_SIZE), 0);
|
||||
EXPECT_EQ(bd.erase(0, BLOCK_SIZE), 0);
|
||||
EXPECT_EQ(bd.erase(0, BLOCK_SIZE), 0);
|
||||
EXPECT_EQ(bd.sync(), 0); // Should not have any influence
|
||||
|
||||
EXPECT_EQ(bd.get_program_count(), BLOCK_SIZE);
|
||||
EXPECT_EQ(bd.get_read_count(), 2 * BLOCK_SIZE);
|
||||
EXPECT_EQ(bd.get_erase_count(), 3 * BLOCK_SIZE);
|
||||
|
||||
bd.reset();
|
||||
|
||||
EXPECT_EQ(bd.get_read_count(), 0);
|
||||
EXPECT_EQ(bd.get_program_count(), 0);
|
||||
EXPECT_EQ(bd.get_erase_count(), 0);
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
|
||||
####################
|
||||
# UNIT TESTS
|
||||
####################
|
||||
|
||||
set(unittest-includes ${unittest-includes}
|
||||
.
|
||||
..
|
||||
)
|
||||
|
||||
set(unittest-sources
|
||||
../features/storage/blockdevice/ProfilingBlockDevice.cpp
|
||||
../features/storage/blockdevice/HeapBlockDevice.cpp
|
||||
stubs/mbed_atomic_stub.c
|
||||
stubs/mbed_assert_stub.cpp
|
||||
)
|
||||
|
||||
set(unittest-test-sources
|
||||
features/storage/blockdevice/ProfilingBlockDevice/test_ProfilingBlockDevice.cpp
|
||||
stubs/mbed_error.c
|
||||
)
|
|
@ -0,0 +1,78 @@
|
|||
/* Copyright (c) 2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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 "gtest/gtest.h"
|
||||
#include "stubs/BlockDevice_mock.h"
|
||||
#include "features/storage/blockdevice/ReadOnlyBlockDevice.h"
|
||||
#include "platform/mbed_error.h"
|
||||
|
||||
#define BLOCK_SIZE (512)
|
||||
#define DEVICE_SIZE (BLOCK_SIZE*10)
|
||||
|
||||
using ::testing::_;
|
||||
using ::testing::Return;
|
||||
using ::testing::DoAll;
|
||||
|
||||
class ReadOnlyBlockModuleTest : public testing::Test {
|
||||
protected:
|
||||
BlockDeviceMock bd_mock;
|
||||
ReadOnlyBlockDevice bd{&bd_mock};
|
||||
uint8_t *magic;
|
||||
uint8_t *buf;
|
||||
virtual void SetUp()
|
||||
{
|
||||
ON_CALL(bd_mock, size()).WillByDefault(Return(DEVICE_SIZE));
|
||||
ON_CALL(bd_mock, get_erase_size(_)).WillByDefault(Return(BLOCK_SIZE));
|
||||
ON_CALL(bd_mock, get_erase_size()).WillByDefault(Return(BLOCK_SIZE));
|
||||
ON_CALL(bd_mock, get_program_size()).WillByDefault(Return(BLOCK_SIZE));
|
||||
ON_CALL(bd_mock, get_read_size()).WillByDefault(Return(BLOCK_SIZE));
|
||||
ON_CALL(bd_mock, is_valid_erase(_, _)).WillByDefault(Return(true));
|
||||
ON_CALL(bd_mock, init()).WillByDefault(Return(BD_ERROR_OK));
|
||||
|
||||
ASSERT_EQ(bd.init(), 0);
|
||||
magic = new uint8_t[BLOCK_SIZE];
|
||||
buf = new uint8_t[BLOCK_SIZE];
|
||||
// Generate simple pattern to verify against
|
||||
for (int i = 0; i < BLOCK_SIZE; i++) {
|
||||
magic[i] = 0xaa + i;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void TearDown()
|
||||
{
|
||||
ASSERT_EQ(bd.deinit(), 0);
|
||||
delete[] magic;
|
||||
delete[] buf;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(ReadOnlyBlockModuleTest, init)
|
||||
{
|
||||
EXPECT_EQ(bd.get_erase_size(), bd_mock.get_erase_size());
|
||||
EXPECT_EQ(bd.get_erase_size(0), bd_mock.get_erase_size(0));
|
||||
EXPECT_EQ(bd.get_erase_value(), bd_mock.get_erase_value());
|
||||
EXPECT_EQ(bd.get_program_size(), bd_mock.get_program_size());
|
||||
EXPECT_EQ(bd.get_read_size(), bd_mock.get_read_size());
|
||||
EXPECT_EQ(bd.size(), bd_mock.size());
|
||||
EXPECT_EQ(bd.get_type(), bd_mock.get_type());
|
||||
}
|
||||
|
||||
TEST_F(ReadOnlyBlockModuleTest, write_protection) {
|
||||
EXPECT_EQ(bd.program(magic, 0, BLOCK_SIZE), MBED_ERROR_WRITE_PROTECTED);
|
||||
EXPECT_EQ(bd.erase(0, BLOCK_SIZE), MBED_ERROR_WRITE_PROTECTED);
|
||||
EXPECT_EQ(bd.read(buf, 0, BLOCK_SIZE), 0);
|
||||
EXPECT_EQ(bd.sync(), 0); // Should not have any influence
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
|
||||
####################
|
||||
# UNIT TESTS
|
||||
####################
|
||||
|
||||
set(unittest-includes ${unittest-includes}
|
||||
.
|
||||
..
|
||||
)
|
||||
|
||||
set(unittest-sources
|
||||
../features/storage/blockdevice/ReadOnlyBlockDevice.cpp
|
||||
../features/storage/blockdevice/HeapBlockDevice.cpp
|
||||
stubs/mbed_atomic_stub.c
|
||||
stubs/mbed_assert_stub.cpp
|
||||
)
|
||||
|
||||
set(unittest-test-sources
|
||||
features/storage/blockdevice/ReadOnlyBlockDevice/test_ReadOnlyBlockDevice.cpp
|
||||
stubs/mbed_error.c
|
||||
)
|
|
@ -1,150 +0,0 @@
|
|||
/* Copyright (c) 2019 ARM Limited
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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 "gtest/gtest.h"
|
||||
#include "features/storage/blockdevice/HeapBlockDevice.h"
|
||||
#include "features/storage/blockdevice/BufferedBlockDevice.h"
|
||||
|
||||
#define BLOCK_SIZE (512)
|
||||
#define DEVICE_SIZE (BLOCK_SIZE*10)
|
||||
|
||||
class BufferedBlockModuleTest : public testing::Test {
|
||||
protected:
|
||||
HeapBlockDevice bd_heap{DEVICE_SIZE};
|
||||
BufferedBlockDevice bd{&bd_heap};
|
||||
uint8_t *magic;
|
||||
uint8_t *buf;
|
||||
virtual void SetUp()
|
||||
{
|
||||
ASSERT_EQ(bd.init(), 0);
|
||||
magic = new uint8_t[BLOCK_SIZE];
|
||||
buf = new uint8_t[BLOCK_SIZE];
|
||||
// Generate simple pattern to verify against
|
||||
for (int i = 0; i < BLOCK_SIZE; i++) {
|
||||
magic[i] = 0xaa + i;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void TearDown()
|
||||
{
|
||||
ASSERT_EQ(bd.deinit(), 0);
|
||||
delete[] magic;
|
||||
delete[] buf;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(BufferedBlockModuleTest, init)
|
||||
{
|
||||
BufferedBlockDevice b(&bd_heap);
|
||||
EXPECT_EQ(b.get_erase_size(), 0);
|
||||
EXPECT_EQ(b.get_erase_size(0), 0);
|
||||
EXPECT_EQ(b.get_erase_value(), BD_ERROR_DEVICE_ERROR);
|
||||
EXPECT_EQ(b.size(), 0);
|
||||
|
||||
EXPECT_EQ(b.init(), 0);
|
||||
|
||||
EXPECT_EQ(b.get_erase_size(), bd_heap.get_erase_size());
|
||||
EXPECT_EQ(b.get_erase_size(0), bd_heap.get_erase_size(0));
|
||||
EXPECT_EQ(b.get_erase_value(), bd_heap.get_erase_value());
|
||||
EXPECT_EQ(b.get_program_size(), 1);
|
||||
EXPECT_EQ(b.get_read_size(), 1);
|
||||
EXPECT_EQ(b.size(), bd_heap.size());
|
||||
EXPECT_EQ(b.get_type(), bd_heap.get_type());
|
||||
}
|
||||
|
||||
TEST_F(BufferedBlockModuleTest, read_full_block)
|
||||
{
|
||||
bd_heap.program(magic, 0, BLOCK_SIZE);
|
||||
EXPECT_EQ(0, bd.read(buf, 0, BLOCK_SIZE));
|
||||
EXPECT_EQ(0, memcmp(magic, buf, BLOCK_SIZE));
|
||||
}
|
||||
|
||||
TEST_F(BufferedBlockModuleTest, over_read)
|
||||
{
|
||||
bd_heap.program(magic, DEVICE_SIZE - BLOCK_SIZE, BLOCK_SIZE);
|
||||
EXPECT_EQ(bd.read(buf, DEVICE_SIZE - BLOCK_SIZE, BLOCK_SIZE), 0);
|
||||
EXPECT_EQ(bd.read(buf, DEVICE_SIZE, BLOCK_SIZE), BD_ERROR_DEVICE_ERROR);
|
||||
}
|
||||
|
||||
TEST_F(BufferedBlockModuleTest, unalign_read)
|
||||
{
|
||||
bd_heap.program(magic, 0, BLOCK_SIZE);
|
||||
bd_heap.program(magic, BLOCK_SIZE, BLOCK_SIZE);
|
||||
EXPECT_EQ(bd.read(buf, BLOCK_SIZE/2, BLOCK_SIZE), 0);
|
||||
EXPECT_EQ(0, memcmp(buf, magic+(BLOCK_SIZE/2), BLOCK_SIZE/2));
|
||||
EXPECT_EQ(0, memcmp(magic, buf+(BLOCK_SIZE/2), BLOCK_SIZE/2));
|
||||
}
|
||||
|
||||
TEST_F(BufferedBlockModuleTest, align_big_read)
|
||||
{
|
||||
uint8_t *buffer = new uint8_t[BLOCK_SIZE*2];
|
||||
bd_heap.program(magic, 0, BLOCK_SIZE);
|
||||
bd_heap.program(magic, BLOCK_SIZE, BLOCK_SIZE);
|
||||
// Should cause 1 full block to be read unaligned from the device
|
||||
// second block would require buffering, because it is not a full (-1)
|
||||
EXPECT_EQ(bd.read(buffer, 0, (BLOCK_SIZE*2)-1), 0);
|
||||
EXPECT_EQ(0, memcmp(magic, buffer, BLOCK_SIZE));
|
||||
EXPECT_EQ(0, memcmp(magic, buffer+BLOCK_SIZE, BLOCK_SIZE-1));
|
||||
delete[] buffer;
|
||||
}
|
||||
|
||||
TEST_F(BufferedBlockModuleTest, program_small_chunks)
|
||||
{
|
||||
for (int i=0; i < BLOCK_SIZE - 1; ++i) {
|
||||
EXPECT_EQ(bd.program(magic+i, i, 1), 0);
|
||||
}
|
||||
EXPECT_EQ(bd.read(buf, 0, BLOCK_SIZE), 0);
|
||||
EXPECT_EQ(0, memcmp(buf, magic, BLOCK_SIZE - 1));
|
||||
}
|
||||
|
||||
TEST_F(BufferedBlockModuleTest, program_and_read_from_cache)
|
||||
{
|
||||
bd_heap.program(magic, 0, BLOCK_SIZE);
|
||||
EXPECT_EQ(bd.program("a", 0, 1), 0);
|
||||
EXPECT_EQ(bd.read(buf, 0, BLOCK_SIZE), 0);
|
||||
EXPECT_EQ('a', buf[0]);
|
||||
EXPECT_EQ(0, memcmp(buf+1, magic+1, BLOCK_SIZE-1));
|
||||
}
|
||||
|
||||
TEST_F(BufferedBlockModuleTest, program_and_verify_from_storage)
|
||||
{
|
||||
EXPECT_EQ(bd.program(magic, 0, BLOCK_SIZE/2), 0);
|
||||
EXPECT_EQ(bd.program(magic+BLOCK_SIZE/2, BLOCK_SIZE/2, BLOCK_SIZE/2), 0); // This should actually write to device
|
||||
EXPECT_EQ(bd.read(buf, 0, BLOCK_SIZE), 0);
|
||||
EXPECT_EQ(0, memcmp(buf, magic, BLOCK_SIZE));
|
||||
// Verify that data actually is in the underlying block device
|
||||
bd_heap.read(buf, 0, BLOCK_SIZE);
|
||||
EXPECT_EQ(0, memcmp(buf, magic, BLOCK_SIZE));
|
||||
}
|
||||
|
||||
TEST_F(BufferedBlockModuleTest, flush_automatically)
|
||||
{
|
||||
EXPECT_EQ(bd.program(magic, 0, BLOCK_SIZE/2), 0); // Don't write full block
|
||||
EXPECT_EQ(bd.program(magic, BLOCK_SIZE, BLOCK_SIZE/2), 0); // This should cause flush() for previous data in cache
|
||||
// Verify that data actually is in the underlying block device
|
||||
bd_heap.read(buf, 0, BLOCK_SIZE);
|
||||
EXPECT_EQ(0, memcmp(buf, magic, BLOCK_SIZE/2));
|
||||
}
|
||||
|
||||
TEST_F(BufferedBlockModuleTest, flush_at_exit)
|
||||
{
|
||||
bd_heap.init(); // Extra init, to prevent deinit() when BufferedBlockDevice de-inits.
|
||||
EXPECT_EQ(bd.program(magic, 0, BLOCK_SIZE/2), 0); // Don't write full block
|
||||
EXPECT_EQ(bd.deinit(), 0);
|
||||
// Verify that data actually is in the underlying block device
|
||||
EXPECT_EQ(bd_heap.read(buf, 0, BLOCK_SIZE), 0);
|
||||
EXPECT_EQ(0, memcmp(buf, magic, BLOCK_SIZE/2));
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (c) 2019, Arm Limited and affiliates.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef BLOCKDEVICEMOCK_H
|
||||
#define BLOCKDEVICEMOCK_H
|
||||
|
||||
#include "gtest/gtest.h"
|
||||
#include "gmock/gmock.h"
|
||||
#include "features/storage/blockdevice/BlockDevice.h"
|
||||
|
||||
class BlockDeviceMock : public BlockDevice {
|
||||
public:
|
||||
MOCK_METHOD0(init, int());
|
||||
MOCK_METHOD0(deinit, int());
|
||||
MOCK_METHOD0(sync, int());
|
||||
MOCK_METHOD3(read, int(void *, bd_addr_t, bd_size_t));
|
||||
MOCK_METHOD3(program, int(const void *, bd_addr_t, bd_size_t));
|
||||
MOCK_METHOD2(erase, int(bd_addr_t, bd_size_t));
|
||||
MOCK_METHOD2(trim, int(bd_addr_t, bd_size_t));
|
||||
MOCK_CONST_METHOD0(get_read_size, bd_size_t());
|
||||
MOCK_CONST_METHOD0(get_program_size, bd_size_t());
|
||||
MOCK_CONST_METHOD0(get_erase_size, bd_size_t());
|
||||
MOCK_CONST_METHOD1(get_erase_size, bd_size_t(bd_addr_t));
|
||||
MOCK_CONST_METHOD0(get_erase_value, int());
|
||||
MOCK_CONST_METHOD0(size, bd_size_t());
|
||||
MOCK_CONST_METHOD2(is_valid_read, bool(bd_addr_t, bd_size_t));
|
||||
MOCK_CONST_METHOD2(is_valid_program, bool(bd_addr_t, bd_size_t));
|
||||
MOCK_CONST_METHOD2(is_valid_erase, bool(bd_addr_t, bd_size_t));
|
||||
MOCK_CONST_METHOD0(get_type, const char *());
|
||||
};
|
||||
|
||||
// Can be used to compare if the data programmed by mock are correct.
|
||||
MATCHER_P2(ByteBufferMatcher, buffer, length, "") {
|
||||
const uint8_t *argp = static_cast<const uint8_t*>(arg);
|
||||
FILE* fd = fopen("testlog.txt", "w");
|
||||
for (int i = 0; i < length; i++) {
|
||||
fprintf(fd, "%03d %02X %02X\n", i, argp[i], buffer[i]);
|
||||
}
|
||||
fclose(fd);
|
||||
return 0 == memcmp(arg, buffer, length);
|
||||
}
|
||||
|
||||
ACTION_P2(SetArg0ToCharPtr, value, size)
|
||||
{
|
||||
for (int i = 0; i < size; i++) {
|
||||
static_cast<char *>(arg0)[i] = reinterpret_cast<const char *>(value)[i];
|
||||
}
|
||||
}
|
||||
|
||||
#endif // BLOCKDEVICEMOCK_H
|
Loading…
Reference in New Issue