Files
IoTManager/lib/ArduinoStreamUtils/extras/test/HammingPrintTest.cpp
Dmitry Borisenko b8a8290928 compiling
2021-12-13 00:58:42 +01:00

203 lines
4.8 KiB
C++

// StreamUtils - github.com/bblanchon/ArduinoStreamUtils
// Copyright Benoit Blanchon 2019-2021
// MIT License
#include "SpyingAllocator.hpp"
#include "StreamUtils/Prints/HammingPrint.hpp"
#include "StreamUtils/Prints/SpyingPrint.hpp"
#include "StreamUtils/Prints/StringPrint.hpp"
#include "StreamUtils/Streams/MemoryStream.hpp"
#include "doctest.h"
using namespace StreamUtils;
TEST_CASE("HammingPrint") {
MemoryStream upstream(4);
StringPrint log;
SpyingPrint spy{upstream, log};
SpyingAllocator allocator{log};
BasicHammingPrint<7, 4, SpyingAllocator&> print{spy, allocator};
SUBCASE("write(char*, size_t)") {
SUBCASE("stops if even byte fails") {
CHECK(print.print("ABA") == 2);
print.write('A'); // try to flush remainder
CHECK(log.str() ==
"write('TqTbTq', 6) -> 4"
"write('T') -> 0" // no remainder
);
}
SUBCASE("saves remainder if odd byte fails") {
upstream.print("?");
CHECK(print.print("ABA") == 2);
print.write('A'); // try to flush remainder
CHECK(log.str() ==
"write('TqTbTq', 6) -> 3"
"write('b') -> 0" // remainder!!
);
}
SUBCASE("writes remainder first") {
upstream.print("???");
print.write('A'); // add remainder
log.clear();
upstream.readString();
CHECK(print.print("ABA") == 2);
CHECK(log.str() ==
"write('q') -> 1"
"write('TqTbTq', 6) -> 3");
}
SUBCASE("stops if remainder fails") {
upstream.print("???");
print.write('A'); // add remainder
log.clear();
CHECK(print.print("ABA") == 0);
CHECK(log.str() == "write('q') -> 0");
}
SUBCASE("allocates in stack when buffer is small") {
print.write("ABABABABABABABAB", 16);
CHECK(log.str() == "write('TqTbTqTbTqTbTqTbTqTbTqTbTqTbTqTb', 32) -> 4");
}
SUBCASE("allocates in heap when buffer is large") {
print.write("ABABABABABABABABA", 17);
CHECK(log.str() ==
"allocate(34) -> ptr"
"write('TqTbTqTbTqTbTqTbTqTbTqTbTqTbTqTbTq', 34) -> 4"
"deallocate(ptr)");
}
SUBCASE("falls back to stack if heap fails") {
allocator.forceFail = true;
print.write("ABABABABABABABABA", 17);
CHECK(log.str() ==
"allocate(34) -> null"
"write('TqTbTqTbTqTbTqTbTqTbTqTbTqTbTqTb', 32) -> 4");
}
}
SUBCASE("write(char)") {
SUBCASE("writes both bytes") {
CHECK(print.write('A') == 1);
CHECK(upstream.readString() == "Tq");
CHECK(log.str() ==
"write('T') -> 1"
"write('q') -> 1");
}
SUBCASE("stops if first by fails") {
upstream.print("????");
CHECK(print.write('A') == 0);
print.write('A'); // try to flush remainder
CHECK(log.str() ==
"write('T') -> 0"
"write('T') -> 0" // no remainder
);
}
SUBCASE("saves remainder if second by fails") {
upstream.print("???");
CHECK(print.write('A') == 1);
print.write('A'); // try to flush remainder
CHECK(log.str() ==
"write('T') -> 1"
"write('q') -> 0"
"write('q') -> 0" // remainder!!
);
}
SUBCASE("writes remainder first") {
upstream.print("???");
print.write('A'); // add remainder
log.clear();
upstream.readString();
CHECK(print.write('A') == 1);
CHECK(log.str() ==
"write('q') -> 1"
"write('T') -> 1"
"write('q') -> 1");
}
SUBCASE("stops if remainder fails") {
upstream.print("???");
print.write('A'); // add remainder
log.clear();
CHECK(print.write('A') == 0);
print.write('A'); // try to flush remainder
CHECK(log.str() ==
"write('q') -> 0"
"write('q') -> 0" // remainder!!
);
}
SUBCASE("resets remainder") {
upstream.print("???");
print.write('A'); // add remainder
log.clear();
upstream.read();
CHECK(print.write('A') == 0);
print.write('A'); // try to flush remainder
CHECK(log.str() ==
"write('q') -> 1"
"write('T') -> 0"
"write('T') -> 0" // no remainder
);
}
}
#if STREAMUTILS_PRINT_FLUSH_EXISTS
SUBCASE("flush() writes remainder") {
upstream.print("???");
print.write('A'); // add remainder
log.clear();
upstream.read();
print.flush();
CHECK(log.str() ==
"write('q') -> 1"
"flush()" // no remainder
);
}
#endif
SUBCASE("destructor flushes remainder") {
{
BasicHammingPrint<7, 4, SpyingAllocator&> print{spy, allocator};
upstream.print("???");
print.write('A'); // add remainder
log.clear();
}
CHECK(log.str() == "write('q') -> 0");
}
}