mirror of
https://github.com/bdring/Grbl_Esp32.git
synced 2025-09-01 02:21:46 +02:00
Added yaml tree builder tests. Fixed nasty bug in parser handler.
This commit is contained in:
@@ -110,6 +110,7 @@ namespace Configuration {
|
||||
if (last == token_.indent_) {
|
||||
// Yes, the token continues where we left off:
|
||||
current_ = token_;
|
||||
// Tokenize();
|
||||
} else {
|
||||
current_ = TokenData();
|
||||
current_.indent_ = last;
|
||||
|
@@ -28,66 +28,86 @@
|
||||
namespace Configuration {
|
||||
class ParserHandler : public Configuration::HandlerBase {
|
||||
private:
|
||||
Configuration::Parser& parser_;
|
||||
Configuration::Parser& _parser;
|
||||
bool _previousIsLeave = false;
|
||||
|
||||
void checkPreviousLeave() {
|
||||
// When a section does a 'leave', the token becomes invalid, and we need to do a
|
||||
// moveNext. See the tests for the yaml parser for what the parser expects.
|
||||
// So, let's introduce that here:
|
||||
if (_previousIsLeave) {
|
||||
_parser.moveNext();
|
||||
}
|
||||
_previousIsLeave = false;
|
||||
}
|
||||
|
||||
protected:
|
||||
void handleDetail(const char* name, Configuration::Configurable* value) override {
|
||||
if (value != nullptr && parser_.is(name)) {
|
||||
if (value != nullptr && _parser.is(name)) {
|
||||
log_debug("Parsing configurable " << name);
|
||||
checkPreviousLeave();
|
||||
|
||||
parser_.enter();
|
||||
for (; !parser_.isEndSection(); parser_.moveNext()) {
|
||||
_parser.enter();
|
||||
for (; !_parser.isEndSection(); _parser.moveNext()) {
|
||||
value->handle(*this);
|
||||
}
|
||||
parser_.leave();
|
||||
_parser.leave();
|
||||
_previousIsLeave = true;
|
||||
}
|
||||
}
|
||||
|
||||
bool matchesUninitialized(const char* name) override { return parser_.is(name); }
|
||||
bool matchesUninitialized(const char* name) override { return _parser.is(name); }
|
||||
|
||||
public:
|
||||
ParserHandler(Configuration::Parser& parser) : parser_(parser) {}
|
||||
ParserHandler(Configuration::Parser& parser) : _parser(parser) {}
|
||||
|
||||
void handle(const char* name, int32_t& value, int32_t minValue, int32_t maxValue) override {
|
||||
if (parser_.is(name)) {
|
||||
value = parser_.intValue();
|
||||
if (_parser.is(name)) {
|
||||
checkPreviousLeave();
|
||||
value = _parser.intValue();
|
||||
}
|
||||
}
|
||||
|
||||
void handle(const char* name, int& value, EnumItem* e) override {
|
||||
if (parser_.is(name)) {
|
||||
value = parser_.enumValue(e);
|
||||
if (_parser.is(name)) {
|
||||
checkPreviousLeave();
|
||||
value = _parser.enumValue(e);
|
||||
}
|
||||
}
|
||||
|
||||
void handle(const char* name, bool& value) override {
|
||||
if (parser_.is(name)) {
|
||||
value = parser_.boolValue();
|
||||
if (_parser.is(name)) {
|
||||
checkPreviousLeave();
|
||||
value = _parser.boolValue();
|
||||
}
|
||||
}
|
||||
|
||||
void handle(const char* name, float& value, float minValue, float maxValue) override {
|
||||
if (parser_.is(name)) {
|
||||
value = parser_.floatValue();
|
||||
if (_parser.is(name)) {
|
||||
checkPreviousLeave();
|
||||
value = _parser.floatValue();
|
||||
}
|
||||
}
|
||||
|
||||
void handle(const char* name, StringRange& value, int minLength, int maxLength) override {
|
||||
if (parser_.is(name)) {
|
||||
value = parser_.stringValue();
|
||||
if (_parser.is(name)) {
|
||||
checkPreviousLeave();
|
||||
value = _parser.stringValue();
|
||||
}
|
||||
}
|
||||
|
||||
void handle(const char* name, Pin& value) override {
|
||||
if (parser_.is(name)) {
|
||||
auto parsed = parser_.pinValue();
|
||||
if (_parser.is(name)) {
|
||||
checkPreviousLeave();
|
||||
auto parsed = _parser.pinValue();
|
||||
value.swap(parsed);
|
||||
}
|
||||
}
|
||||
|
||||
void handle(const char* name, IPAddress& value) override {
|
||||
if (parser_.is(name)) {
|
||||
value = parser_.ipValue();
|
||||
if (_parser.is(name)) {
|
||||
checkPreviousLeave();
|
||||
value = _parser.ipValue();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -23,7 +23,7 @@
|
||||
# include <iostream>
|
||||
|
||||
DebugStream::DebugStream(const char* name) {
|
||||
std::cout << '[MSG:' << name << ": ";
|
||||
std::cout << "[MSG:" << name << ": ";
|
||||
}
|
||||
void DebugStream::add(char c) {
|
||||
std::cout << c;
|
||||
|
199
Grbl_Esp32/test/Configuration/YamlTreeBuilder.cpp
Normal file
199
Grbl_Esp32/test/Configuration/YamlTreeBuilder.cpp
Normal file
@@ -0,0 +1,199 @@
|
||||
#include "../TestFramework.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <src/Configuration/Tokenizer.h>
|
||||
#include <src/Configuration/Parser.h>
|
||||
#include <src/Configuration/ParserHandler.h>
|
||||
#include <src/Configuration/Configurable.h>
|
||||
|
||||
namespace Configuration {
|
||||
class TestBasic : public Configurable {
|
||||
public:
|
||||
String a;
|
||||
String b;
|
||||
String c;
|
||||
|
||||
void validate() const {}
|
||||
void handle(HandlerBase& handler) {
|
||||
handler.handle("a", a);
|
||||
handler.handle("b", b);
|
||||
handler.handle("c", c);
|
||||
}
|
||||
};
|
||||
|
||||
class TestBasic2 : public Configurable {
|
||||
public:
|
||||
String aap;
|
||||
int banaan;
|
||||
|
||||
void validate() const {}
|
||||
void handle(HandlerBase& handler) {
|
||||
handler.handle("aap", aap);
|
||||
handler.handle("banaan", banaan);
|
||||
}
|
||||
};
|
||||
|
||||
class TestHierarchical : public Configurable {
|
||||
public:
|
||||
TestBasic* n1 = nullptr;
|
||||
TestBasic2* n2 = nullptr;
|
||||
int foo = 0;
|
||||
|
||||
void validate() const {}
|
||||
void handle(HandlerBase& handler) {
|
||||
handler.handle("n1", n1);
|
||||
handler.handle("n2", n2);
|
||||
handler.handle("foo", foo);
|
||||
}
|
||||
};
|
||||
|
||||
struct Helper {
|
||||
template <typename T>
|
||||
static inline void Parse(const char* config, T& test) {
|
||||
Parser p(config, config + strlen(config));
|
||||
ParserHandler handler(p);
|
||||
|
||||
test.handle(handler);
|
||||
for (; !p.isEndSection(); p.moveNext()) {
|
||||
test.handle(handler);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
Test(YamlTreeBuilder, BasicProperties) {
|
||||
const char* config = "a: aap\n"
|
||||
"b: banaan\n"
|
||||
"\n"
|
||||
"c: chocolade";
|
||||
|
||||
TestBasic test;
|
||||
Helper::Parse(config, test);
|
||||
|
||||
Assert(test.a == "aap");
|
||||
Assert(test.b == "banaan");
|
||||
Assert(test.c == "chocolade");
|
||||
}
|
||||
|
||||
Test(YamlTreeBuilder, BasicPropertiesInvert) {
|
||||
const char* config = "c: chocolade\n"
|
||||
"b: banaan\n"
|
||||
"a: aap\n";
|
||||
|
||||
TestBasic test;
|
||||
Helper::Parse(config, test);
|
||||
|
||||
Assert(test.a == "aap");
|
||||
Assert(test.b == "banaan");
|
||||
Assert(test.c == "chocolade");
|
||||
}
|
||||
|
||||
Test(YamlTreeBuilder, BasicProperties2) {
|
||||
const char* config = "aap: aap\n"
|
||||
"banaan: 2\n";
|
||||
|
||||
TestBasic2 test;
|
||||
Helper::Parse(config, test);
|
||||
|
||||
Assert(test.aap == "aap");
|
||||
Assert(test.banaan == 2);
|
||||
}
|
||||
|
||||
Test(YamlTreeBuilder, BasicPropertiesInvert2) {
|
||||
const char* config = "banaan: 2\n"
|
||||
"aap: aap\n";
|
||||
|
||||
TestBasic2 test;
|
||||
Helper::Parse(config, test);
|
||||
|
||||
Assert(test.aap == "aap");
|
||||
Assert(test.banaan == 2);
|
||||
}
|
||||
|
||||
Test(YamlTreeBuilder, Hierarchical1) {
|
||||
const char* config = "n1:\n"
|
||||
" a: aap\n"
|
||||
" b: banaan\n"
|
||||
" \n"
|
||||
" c: chocolade\n"
|
||||
"n2:\n"
|
||||
" banaan: 2\n"
|
||||
" aap: aap\n"
|
||||
"foo: 2\n";
|
||||
|
||||
TestHierarchical test;
|
||||
Helper::Parse(config, test);
|
||||
|
||||
{
|
||||
Assert(test.n1 != nullptr);
|
||||
Assert(test.n1->a == "aap");
|
||||
Assert(test.n1->b == "banaan");
|
||||
Assert(test.n1->c == "chocolade");
|
||||
}
|
||||
|
||||
{
|
||||
Assert(test.n2 != nullptr);
|
||||
Assert(test.n2->banaan == 2);
|
||||
Assert(test.n2->aap == "aap");
|
||||
}
|
||||
Assert(test.foo == 2);
|
||||
}
|
||||
|
||||
Test(YamlTreeBuilder, Hierarchical2) {
|
||||
const char* config = "n2:\n"
|
||||
" banaan: 2\n"
|
||||
" aap: aap\n"
|
||||
"n1:\n"
|
||||
" a: aap\n"
|
||||
" b: banaan\n"
|
||||
" \n"
|
||||
" c: chocolade\n"
|
||||
"foo: 2\n";
|
||||
|
||||
TestHierarchical test;
|
||||
Helper::Parse(config, test);
|
||||
|
||||
{
|
||||
Assert(test.n1 != nullptr);
|
||||
Assert(test.n1->a == "aap");
|
||||
Assert(test.n1->b == "banaan");
|
||||
Assert(test.n1->c == "chocolade");
|
||||
}
|
||||
|
||||
{
|
||||
Assert(test.n2 != nullptr);
|
||||
Assert(test.n2->banaan == 2);
|
||||
Assert(test.n2->aap == "aap");
|
||||
}
|
||||
Assert(test.foo == 2);
|
||||
}
|
||||
|
||||
Test(YamlTreeBuilder, Hierarchical3) {
|
||||
const char* config = "foo: 2\n"
|
||||
"n2:\n"
|
||||
" banaan: 2\n"
|
||||
" aap: aap\n"
|
||||
"n1:\n"
|
||||
" a: aap\n"
|
||||
" b: banaan\n"
|
||||
" \n"
|
||||
" c: chocolade\n";
|
||||
|
||||
TestHierarchical test;
|
||||
Helper::Parse(config, test);
|
||||
|
||||
{
|
||||
Assert(test.n1 != nullptr);
|
||||
Assert(test.n1->a == "aap");
|
||||
Assert(test.n1->b == "banaan");
|
||||
Assert(test.n1->c == "chocolade");
|
||||
}
|
||||
|
||||
{
|
||||
Assert(test.n2 != nullptr);
|
||||
Assert(test.n2->banaan == 2);
|
||||
Assert(test.n2->aap == "aap");
|
||||
}
|
||||
Assert(test.foo == 2);
|
||||
}
|
||||
}
|
@@ -44,6 +44,7 @@
|
||||
<ClInclude Include="Grbl_Esp32\src\Configuration\ParserHandler.h" />
|
||||
<ClInclude Include="Grbl_Esp32\src\Configuration\Tokenizer.h" />
|
||||
<ClInclude Include="Grbl_Esp32\src\Configuration\TokenKind.h" />
|
||||
<ClInclude Include="Grbl_Esp32\src\Logging.h" />
|
||||
<ClInclude Include="Grbl_Esp32\src\Pin.h" />
|
||||
<ClInclude Include="Grbl_Esp32\src\Pins\ErrorPinDetail.h" />
|
||||
<ClInclude Include="Grbl_Esp32\src\Pins\GPIOPinDetail.h" />
|
||||
@@ -53,6 +54,7 @@
|
||||
<ClInclude Include="Grbl_Esp32\src\Pins\PinDetail.h" />
|
||||
<ClInclude Include="Grbl_Esp32\src\Pins\PinOptionsParser.h" />
|
||||
<ClInclude Include="Grbl_Esp32\src\Pins\VoidPinDetail.h" />
|
||||
<ClInclude Include="Grbl_Esp32\src\SimpleOutputStream.h" />
|
||||
<ClInclude Include="Grbl_Esp32\src\StackTrace\AssertionFailed.h" />
|
||||
<ClInclude Include="Grbl_Esp32\src\StackTrace\debug_helpers.h" />
|
||||
<ClInclude Include="Grbl_Esp32\test\TestFactory.h" />
|
||||
@@ -65,6 +67,7 @@
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Grbl_Esp32\src\Configuration\Parser.cpp" />
|
||||
<ClCompile Include="Grbl_Esp32\src\Configuration\Tokenizer.cpp" />
|
||||
<ClCompile Include="Grbl_Esp32\src\Logging.cpp" />
|
||||
<ClCompile Include="Grbl_Esp32\src\Pin.cpp" />
|
||||
<ClCompile Include="Grbl_Esp32\src\Pins\ErrorPinDetail.cpp" />
|
||||
<ClCompile Include="Grbl_Esp32\src\Pins\GPIOPinDetail.cpp" />
|
||||
@@ -74,10 +77,12 @@
|
||||
<ClCompile Include="Grbl_Esp32\src\Pins\PinDetail.cpp" />
|
||||
<ClCompile Include="Grbl_Esp32\src\Pins\PinOptionsParser.cpp" />
|
||||
<ClCompile Include="Grbl_Esp32\src\Pins\VoidPinDetail.cpp" />
|
||||
<ClCompile Include="Grbl_Esp32\src\SimpleOutputStream.cpp" />
|
||||
<ClCompile Include="Grbl_Esp32\src\StackTrace\AssertionFailed.cpp" />
|
||||
<ClCompile Include="Grbl_Esp32\src\StackTrace\debug_helpers.cpp" />
|
||||
<ClCompile Include="Grbl_Esp32\test\Configuration\YamlComplete.cpp" />
|
||||
<ClCompile Include="Grbl_Esp32\test\Configuration\YamlParser.cpp" />
|
||||
<ClCompile Include="Grbl_Esp32\test\Configuration\YamlTreeBuilder.cpp" />
|
||||
<ClCompile Include="Grbl_Esp32\test\Pins\BasicGPIO.cpp" />
|
||||
<ClCompile Include="Grbl_Esp32\test\Pins\Error.cpp" />
|
||||
<ClCompile Include="Grbl_Esp32\test\Pins\GPIO.cpp" />
|
||||
|
@@ -93,6 +93,12 @@
|
||||
<ClInclude Include="X86TestSupport\IPAddress.h">
|
||||
<Filter>X86TestSupport</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Grbl_Esp32\src\SimpleOutputStream.h">
|
||||
<Filter>src</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Grbl_Esp32\src\Logging.h">
|
||||
<Filter>src</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Grbl_Esp32\test\TestFrameworkTest.cpp">
|
||||
@@ -170,7 +176,18 @@
|
||||
<ClCompile Include="Grbl_Esp32\src\Configuration\Parser.cpp">
|
||||
<Filter>src\Configuration</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Grbl_Esp32\test\Configuration\YamlComplete.cpp" />
|
||||
<ClCompile Include="Grbl_Esp32\test\Configuration\YamlComplete.cpp">
|
||||
<Filter>test\Configuration</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Grbl_Esp32\test\Configuration\YamlTreeBuilder.cpp">
|
||||
<Filter>test\Configuration</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Grbl_Esp32\src\SimpleOutputStream.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Grbl_Esp32\src\Logging.cpp">
|
||||
<Filter>src</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Grbl_Esp32\test\UnitTests.md">
|
||||
|
Reference in New Issue
Block a user