Skip to content

Commit 2133475

Browse files
fix: add tests for FlashAligner and fix it (#88)
* fix: add tests for FlashAligner and fix it * Configure tests * Only build postmaster.programmer.test when the tests are enabled
1 parent 0e34eeb commit 2133475

File tree

9 files changed

+145
-15
lines changed

9 files changed

+145
-15
lines changed

CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ set(CMAKE_CXX_STANDARD 20)
66
set(CMAKE_CXX_STANDARD_REQUIRED true)
77

88
option(CMAKE_COMPILE_WARNING_AS_ERROR "Enable warnings-as-error" On)
9+
option(HALST_BUILD_TESTS "Enable building the tests" Off)
910

1011
include(CheckIPOSupported)
1112
check_ipo_supported(RESULT supported OUTPUT error)
@@ -17,9 +18,18 @@ add_definitions(-DMEMP_NUM_UDP_PCB=10)
1718

1819
set(HALST_INCLUDE_DEFAULT_LINKER_SCRIPTS Off CACHE INTERNAL "")
1920

21+
if (POSTMASTER_BUILD_TESTS)
22+
include(CTest)
23+
endif()
24+
2025
add_subdirectory(amp-embedded-infra-lib)
2126
add_subdirectory(amp-hal-st)
2227
add_subdirectory(amp-preview)
28+
29+
if (POSTMASTER_BUILD_TESTS)
30+
emil_enable_testing()
31+
endif()
32+
2333
add_subdirectory(postmaster)
2434

2535
emil_folderize_all_targets()

CMakePresets.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"generator": "Ninja Multi-Config",
1515
"cacheVariables": {
1616
"CMAKE_CONFIGURATION_TYPES": "Debug;RelWithDebInfo",
17+
"POSTMASTER_BUILD_TESTS": true,
1718
"EMIL_BUILD_TESTS": true
1819
}
1920
},

amp-embedded-infra-lib

postmaster/instantiations/EchoServer.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ namespace main_
1818
infra::ProxyCreator<hal::SerialCommunication, void(const UartConfig& config)> serial;
1919
services::MethodSerializerFactory::ForServices<>::AndProxies<> serializerFactory;
2020
hal::BufferedSerialCommunicationOnUnbuffered::WithStorage<256> bufferedSerial{ *serial };
21-
main_::EchoOnSesame<256> echoUart{ bufferedSerial, serializerFactory };
21+
main_::EchoOnSesame::WithMessageSize<256> echoUart{ bufferedSerial, serializerFactory };
2222
services::EchoOnConnection echoConnection{ serializerFactory };
2323

24-
services::ServiceForwarderAll forwardLeft{ echoUart, echoConnection };
25-
services::ServiceForwarderAll forwardRight{ echoConnection, echoUart };
24+
services::ServiceForwarderAll forwardLeft{ echoUart.echo, echoConnection };
25+
services::ServiceForwarderAll forwardRight{ echoConnection, echoUart.echo };
2626

2727
operator services::ConnectionObserver&();
2828
operator const services::ConnectionObserver&() const;

postmaster/instantiations/TargetUartEcho.hpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,12 @@ namespace main_
4242
infra::ProxyCreator<hal::SerialCommunication, void(const UartConfig& config)> serial;
4343
services::MethodSerializerFactory::ForServices<>::AndProxies<> serializerFactory;
4444
hal::BufferedSerialCommunicationOnUnbuffered::WithStorage<256> bufferedSerial{ *serial };
45-
main_::EchoOnSesame<256> echoUart{ bufferedSerial, serializerFactory };
45+
main_::EchoOnSesame::WithMessageSize<256> echoUart{ bufferedSerial, serializerFactory };
4646
services::EchoOnConnection echoConnection{ serializerFactory };
4747
WebSocketServerConnectionObserver webSocket{ *this };
4848

49-
services::ServiceForwarderAll forwardLeft{ echoUart, echoConnection };
50-
services::ServiceForwarderAll forwardRight{ echoConnection, echoUart };
49+
services::ServiceForwarderAll forwardLeft{ echoUart.echo, echoConnection };
50+
services::ServiceForwarderAll forwardRight{ echoConnection, echoUart.echo };
5151

5252
operator services::ConnectionObserver&();
5353
operator const services::ConnectionObserver&() const;

postmaster/programmer/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,5 @@ target_link_libraries(postmaster.programmer PUBLIC
3333
services.st_util
3434
protobuf.echo
3535
)
36+
37+
add_subdirectory(test)

postmaster/programmer/FlashAligner.cpp

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,14 @@ namespace services
99

1010
void FlashAligner::Flush(const infra::Function<void()>& onDone)
1111
{
12-
alignedBuffer.resize(alignedBuffer.max_size());
13-
FlashDelegate::WriteBuffer(infra::MakeRange(alignedBuffer), address, onDone);
12+
if (alignedBuffer.empty())
13+
onDone();
14+
else
15+
{
16+
auto size = alignedBuffer.size();
17+
alignedBuffer.resize(alignedBuffer.max_size());
18+
FlashDelegate::WriteBuffer(infra::MakeRange(alignedBuffer), address - size, onDone);
19+
}
1420
}
1521

1622
void FlashAligner::WriteBuffer(infra::ConstByteRange buffer, uint32_t address, infra::Function<void()> onDone)
@@ -20,6 +26,7 @@ namespace services
2026
auto range = infra::Head(buffer, alignedBuffer.max_size() - alignedBuffer.size());
2127
alignedBuffer.insert(alignedBuffer.end(), range.begin(), range.end());
2228
buffer.pop_front(range.size());
29+
address += range.size();
2330
}
2431

2532
if (alignedBuffer.full())
@@ -28,21 +35,27 @@ namespace services
2835
this->address = address;
2936
this->onDone = onDone;
3037

31-
FlashDelegate::WriteBuffer(infra::MakeRange(alignedBuffer), address, [this]()
38+
FlashDelegate::WriteBuffer(infra::MakeRange(alignedBuffer), address - alignedBuffer.size(), [this]()
3239
{
3340
alignedBuffer.clear();
3441
auto onDoneCopy = this->onDone.Clone();
3542
this->onDone = nullptr;
36-
WriteBuffer(this->buffer, this->address + alignedBuffer.max_size(), onDoneCopy);
43+
WriteBuffer(this->buffer, this->address, onDoneCopy);
3744
});
3845
}
3946
else
4047
{
41-
auto range = infra::Head(buffer, buffer.size() - buffer.size() % alignedBuffer.max_size());
42-
alignedBuffer.insert(alignedBuffer.end(), range.end(), buffer.end());
48+
auto sendNowSize = buffer.size() - buffer.size() % alignedBuffer.max_size();
49+
auto sendNow = infra::Head(buffer, sendNowSize);
50+
auto sendLater = infra::DiscardHead(buffer, sendNowSize);
51+
alignedBuffer.insert(alignedBuffer.end(), sendLater.begin(), sendLater.end());
52+
53+
this->address = address + buffer.size();
4354

44-
FlashDelegate::WriteBuffer(range, address, onDone);
45-
this->address = address + range.size();
55+
if (sendNow.empty())
56+
onDone();
57+
else
58+
FlashDelegate::WriteBuffer(sendNow, address, onDone);
4659
}
4760
}
4861
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
add_executable(postmaster.programmer.test)
2+
emil_build_for(postmaster.programmer.test BOOL EMIL_BUILD_TESTS)
3+
emil_add_test(postmaster.programmer.test)
4+
5+
target_link_libraries(postmaster.programmer.test PUBLIC
6+
gmock_main
7+
postmaster.programmer
8+
hal.interfaces_test_doubles
9+
)
10+
11+
target_sources(postmaster.programmer.test PRIVATE
12+
TestFlashAligner.cpp
13+
)
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
#include "hal/interfaces/test_doubles/FlashMock.hpp"
2+
#include "infra/util/test_helper/MemoryRangeMatcher.hpp"
3+
#include "infra/util/test_helper/MockCallback.hpp"
4+
#include "postmaster/programmer/FlashAligner.hpp"
5+
#include "gtest/gtest.h"
6+
7+
class FlashAlignerTest
8+
: public testing::Test
9+
{
10+
public:
11+
testing::StrictMock<hal::CleanFlashMock> flash;
12+
services::FlashAligner::WithAlignment<4> aligner{ flash };
13+
14+
std::array<uint8_t, 1> size1{ 99 };
15+
std::array<uint8_t, 4> size4{ 1, 2, 3, 4 };
16+
std::array<uint8_t, 6> size6{ 5, 6, 7, 8, 9, 10 };
17+
std::array<uint8_t, 8> size8{ 11, 12, 13, 14, 15, 16, 17, 18 };
18+
};
19+
20+
TEST_F(FlashAlignerTest, write_one_block)
21+
{
22+
EXPECT_CALL(flash, WriteBuffer(infra::MakeConstRange(size4), 0, testing::_)).WillOnce(testing::InvokeArgument<2>());
23+
aligner.WriteBuffer(size4, 0, infra::MockFunction<void()>());
24+
25+
aligner.Flush(infra::MockFunction<void()>());
26+
}
27+
28+
TEST_F(FlashAlignerTest, write_small_block)
29+
{
30+
aligner.WriteBuffer(size1, 0, infra::MockFunction<void()>());
31+
32+
EXPECT_CALL(flash, WriteBuffer(infra::ContentsEqual(std::vector<uint8_t>{ 99, 0, 0, 0 }), 0, testing::_)).WillOnce(testing::InvokeArgument<2>());
33+
aligner.Flush(infra::MockFunction<void()>());
34+
}
35+
36+
TEST_F(FlashAlignerTest, write_large_block)
37+
{
38+
EXPECT_CALL(flash, WriteBuffer(infra::Head(infra::MakeConstRange(size6), 4), 0, testing::_)).WillOnce(testing::InvokeArgument<2>());
39+
aligner.WriteBuffer(size6, 0, infra::MockFunction<void()>());
40+
41+
EXPECT_CALL(flash, WriteBuffer(infra::ContentsEqual(std::vector<uint8_t>{ 9, 10, 0, 0}), 4, testing::_)).WillOnce(testing::InvokeArgument<2>());
42+
aligner.Flush(infra::MockFunction<void()>());
43+
}
44+
45+
TEST_F(FlashAlignerTest, write_double_block)
46+
{
47+
EXPECT_CALL(flash, WriteBuffer(infra::MakeConstRange(size8), 0, testing::_)).WillOnce(testing::InvokeArgument<2>());
48+
aligner.WriteBuffer(size8, 0, infra::MockFunction<void()>());
49+
50+
aligner.Flush(infra::MockFunction<void()>());
51+
}
52+
53+
TEST_F(FlashAlignerTest, write_one_block_at_offset)
54+
{
55+
aligner.WriteBuffer(size1, 0, infra::MockFunction<void()>());
56+
57+
EXPECT_CALL(flash, WriteBuffer(infra::ContentsEqual(std::vector<uint8_t>{ 99, 1, 2, 3 }), 0, testing::_)).WillOnce(testing::InvokeArgument<2>());
58+
aligner.WriteBuffer(size4, 1, infra::MockFunction<void()>());
59+
}
60+
61+
TEST_F(FlashAlignerTest, write_small_block_at_offset)
62+
{
63+
aligner.WriteBuffer(size1, 0, infra::MockFunction<void()>());
64+
aligner.WriteBuffer(size1, 1, infra::MockFunction<void()>());
65+
66+
EXPECT_CALL(flash, WriteBuffer(infra::ContentsEqual(std::vector<uint8_t>{ 99, 99, 0, 0 }), 0, testing::_)).WillOnce(testing::InvokeArgument<2>());
67+
aligner.Flush(infra::MockFunction<void()>());
68+
}
69+
70+
TEST_F(FlashAlignerTest, write_large_block_at_offset)
71+
{
72+
aligner.WriteBuffer(size1, 0, infra::MockFunction<void()>());
73+
74+
EXPECT_CALL(flash, WriteBuffer(infra::ContentsEqual(std::vector<uint8_t>{ 99, 5, 6, 7 }), 0, testing::_)).WillOnce(testing::InvokeArgument<2>());
75+
aligner.WriteBuffer(size6, 1, infra::MockFunction<void()>());
76+
77+
EXPECT_CALL(flash, WriteBuffer(infra::ContentsEqual(std::vector<uint8_t>{ 8, 9, 10, 0 }), 4, testing::_)).WillOnce(testing::InvokeArgument<2>());
78+
aligner.Flush(infra::MockFunction<void()>());
79+
}
80+
81+
TEST_F(FlashAlignerTest, write_double_block_at_offset)
82+
{
83+
aligner.WriteBuffer(size1, 0, infra::MockFunction<void()>());
84+
85+
EXPECT_CALL(flash, WriteBuffer(infra::ContentsEqual(std::vector<uint8_t>{ 99, 11, 12, 13 }), 0, testing::_)).WillOnce(testing::InvokeArgument<2>());
86+
EXPECT_CALL(flash, WriteBuffer(infra::ContentsEqual(std::vector<uint8_t>{ 14, 15, 16, 17 }), 4, testing::_)).WillOnce(testing::InvokeArgument<2>());
87+
aligner.WriteBuffer(size8, 1, infra::MockFunction<void()>());
88+
89+
EXPECT_CALL(flash, WriteBuffer(infra::ContentsEqual(std::vector<uint8_t>{ 18, 0, 0, 0 }), 8, testing::_)).WillOnce(testing::InvokeArgument<2>());
90+
aligner.Flush(infra::MockFunction<void()>());
91+
}

0 commit comments

Comments
 (0)