From d5143f5c9d803a811f4e8f662a3508685db5f01e Mon Sep 17 00:00:00 2001 From: Stefan de Bruijn Date: Thu, 22 Oct 2020 20:16:27 +0200 Subject: [PATCH] Added some unit tests; fixed pin option parser. --- Grbl_Esp32.sln | 2 +- Grbl_Esp32/src/Pins/PinAttributes.cpp | 2 +- Grbl_Esp32/src/Pins/PinOptionsParser.cpp | 9 +- Grbl_Esp32/src/Pins/PinOptionsParser.h | 2 +- Grbl_Esp32/test/Pins/GPIO.cpp | 30 +++++ Grbl_Esp32/test/Pins/PinOptionParsing.cpp | 128 ++++++++++++++++++++++ UnitTests.vcxproj | 1 + UnitTests.vcxproj.filters | 3 + 8 files changed, 170 insertions(+), 7 deletions(-) create mode 100644 Grbl_Esp32/test/Pins/PinOptionParsing.cpp diff --git a/Grbl_Esp32.sln b/Grbl_Esp32.sln index 2aa43d42..5479c1cb 100644 --- a/Grbl_Esp32.sln +++ b/Grbl_Esp32.sln @@ -16,7 +16,6 @@ Global EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {11C8A44F-A303-4885-B5AD-5B65F7FE41C0}.Debug|x64.ActiveCfg = Debug|x64 - {11C8A44F-A303-4885-B5AD-5B65F7FE41C0}.Debug|x64.Build.0 = Debug|x64 {11C8A44F-A303-4885-B5AD-5B65F7FE41C0}.Debug|x86.ActiveCfg = Debug|Win32 {11C8A44F-A303-4885-B5AD-5B65F7FE41C0}.Debug|x86.Build.0 = Debug|Win32 {11C8A44F-A303-4885-B5AD-5B65F7FE41C0}.Release|x64.ActiveCfg = Release|x64 @@ -24,6 +23,7 @@ Global {11C8A44F-A303-4885-B5AD-5B65F7FE41C0}.Release|x86.ActiveCfg = Release|Win32 {11C8A44F-A303-4885-B5AD-5B65F7FE41C0}.Release|x86.Build.0 = Release|Win32 {33ECE513-60D1-4949-A4A9-C95D353C2CF0}.Debug|x64.ActiveCfg = Debug|x64 + {33ECE513-60D1-4949-A4A9-C95D353C2CF0}.Debug|x64.Build.0 = Debug|x64 {33ECE513-60D1-4949-A4A9-C95D353C2CF0}.Debug|x86.ActiveCfg = Debug|Win32 {33ECE513-60D1-4949-A4A9-C95D353C2CF0}.Debug|x86.Build.0 = Debug|Win32 {33ECE513-60D1-4949-A4A9-C95D353C2CF0}.Release|x64.ActiveCfg = Release|x64 diff --git a/Grbl_Esp32/src/Pins/PinAttributes.cpp b/Grbl_Esp32/src/Pins/PinAttributes.cpp index f67e6295..91d0c675 100644 --- a/Grbl_Esp32/src/Pins/PinAttributes.cpp +++ b/Grbl_Esp32/src/Pins/PinAttributes.cpp @@ -21,7 +21,7 @@ namespace Pins { bool PinAttributes::validateWith(PinCapabilities caps) { auto capMask = (caps._value & capabilityMask); - auto attrMask = _value; + auto attrMask = (_value & capabilityMask); // We're good if: return (capMask & attrMask) == attrMask && // the capabilities overlap with the required attributes AND diff --git a/Grbl_Esp32/src/Pins/PinOptionsParser.cpp b/Grbl_Esp32/src/Pins/PinOptionsParser.cpp index 8578e927..17c787a8 100644 --- a/Grbl_Esp32/src/Pins/PinOptionsParser.cpp +++ b/Grbl_Esp32/src/Pins/PinOptionsParser.cpp @@ -3,11 +3,11 @@ #include namespace Pins { - PinOption::PinOption(char* start, const char* end) : _start(start) {} + PinOption::PinOption(char* start, const char* end) : _start(start), _end(end) {} bool PinOption::is(const char* option) const { return !::strcmp(option, _start); } - PinOption PinOption ::operator++() const { + PinOption& PinOption::operator++() { if (_start == _end) { return *this; } @@ -16,13 +16,14 @@ namespace Pins { if (newStart != _end) { // and 1 past it if we're not at the end ++newStart; } - return PinOption(newStart, _end); + _start = newStart; + return *this; } PinOptionsParser::PinOptionsParser(char* buffer, char* bufferEnd) : _buffer(buffer), _bufferEnd(bufferEnd) { // Do the actual parsing: for (auto i = buffer; i != bufferEnd; ++i) { - if (*i == ':') { + if (*i == ':' || *i == ';') { *i = '\0'; } else if (*i >= 'A' && *i <= 'Z') { // where did cstring->tolower go? Anyways, here goes: *i = char(*i + 32); diff --git a/Grbl_Esp32/src/Pins/PinOptionsParser.h b/Grbl_Esp32/src/Pins/PinOptionsParser.h index 6b68a43a..8403d037 100644 --- a/Grbl_Esp32/src/Pins/PinOptionsParser.h +++ b/Grbl_Esp32/src/Pins/PinOptionsParser.h @@ -35,7 +35,7 @@ namespace Pins { // Iterator support: inline PinOption const* operator->() const { return this; } inline PinOption operator*() const { return *this; } - PinOption operator++() const; + PinOption& operator++(); bool operator==(const PinOption& o) const { return _start == o._start; } bool operator!=(const PinOption& o) const { return _start != o._start; } diff --git a/Grbl_Esp32/test/Pins/GPIO.cpp b/Grbl_Esp32/test/Pins/GPIO.cpp index 15f79355..c058c93a 100644 --- a/Grbl_Esp32/test/Pins/GPIO.cpp +++ b/Grbl_Esp32/test/Pins/GPIO.cpp @@ -247,4 +247,34 @@ namespace Pins { Pin gpio16 = Pin::create("gpio.16"); Assert(gpio16.name().equals("GPIO.16"), "Name is %s", gpio16.name().c_str()); } + + Test(GPIO, ActiveLow) { + GPIONative::initialize(); + PinLookup::ResetAllPins(); + + Pin gpio16 = Pin::create("gpio.16:low"); + Pin gpio17 = Pin::create("gpio.17"); + + gpio16.setAttr(Pin::Attr::Output | Pin::Attr::InitialHigh); + gpio17.setAttr(Pin::Attr::Input); + + Assert(false == gpio16.read()); + Assert(true == gpio17.read()); + Assert(false == GPIONative::read(16)); + Assert(true == GPIONative::read(17)); + + gpio16.on(); + + Assert(true == gpio16.read()); + Assert(false == gpio17.read()); + Assert(true == GPIONative::read(16)); + Assert(false == GPIONative::read(17)); + + gpio16.off(); + + Assert(false == gpio16.read()); + Assert(true == gpio17.read()); + Assert(false == GPIONative::read(16)); + Assert(true == GPIONative::read(17)); + } } diff --git a/Grbl_Esp32/test/Pins/PinOptionParsing.cpp b/Grbl_Esp32/test/Pins/PinOptionParsing.cpp new file mode 100644 index 00000000..2c96c095 --- /dev/null +++ b/Grbl_Esp32/test/Pins/PinOptionParsing.cpp @@ -0,0 +1,128 @@ +#include "../TestFramework.h" + +#include "src/Pins/PinOptionsParser.h" +#include +#include + +namespace Pins { + Test(PinOptionParsing, NoArgs) { + char nullDescr[1] = { '\0' }; + Pins::PinOptionsParser parser(nullDescr, nullDescr); + + { + auto opt = parser.begin(); + auto endopt = parser.end(); + Assert(opt == endopt, "Expected empty enumerator"); + } + + // Typical use is a for loop. Let's test the two ways to use it: + for (auto it : parser) { + Assert(false, "Didn't expect to get here"); + } + + for (auto it = parser.begin(); it != parser.end(); ++it) { + Assert(false, "Didn't expect to get here"); + } + } + + Test(PinOptionParsing, SingleArg) { + const char* input = "first"; + char tmp[20]; + int n = snprintf(tmp, 20, "%s", input); + + Pins::PinOptionsParser parser(tmp, tmp + n); + + { + auto opt = parser.begin(); + auto endopt = parser.end(); + Assert(opt != endopt, "Expected an argument"); + Assert(opt->is("first"), "Expected 'first'"); + + ++opt; + Assert(opt == endopt, "Expected one argument"); + } + + // Typical use is a for loop. Let's test the two ways to use it: + int ctr = 0; + for (auto it : parser) { + if (ctr == 0) { + Assert(it.is("first"), "Expected 'first'"); + } else { + Assert(false, "Didn't expect to get here"); + } + ++ctr; + } + } + + Test(PinOptionParsing, TwoArg1) { + const char* input = "first;second"; + char tmp[20]; + int n = snprintf(tmp, 20, "%s", input); + + Pins::PinOptionsParser parser(tmp, tmp + n); + + { + auto opt = parser.begin(); + auto endopt = parser.end(); + Assert(opt != endopt, "Expected an argument"); + Assert(opt->is("first"), "Expected 'first'"); + + ++opt; + Assert(opt != endopt, "Expected second argument"); + Assert(opt->is("second"), "Expected 'second'"); + + ++opt; + Assert(opt == endopt, "Expected one argument"); + } + + // Typical use is a for loop. Let's test the two ways to use it: + int ctr = 0; + for (auto it : parser) { + if (ctr == 0) { + Assert(it.is("first"), "Expected 'first'"); + } else if (ctr == 1) { + Assert(it.is("second"), "Expected 'second'"); + } else { + Assert(false, "Didn't expect to get here"); + } + ++ctr; + } + } + + Test(PinOptionParsing, TwoArg2) { + const char* input = "first:second"; + char tmp[20]; + int n = snprintf(tmp, 20, "%s", input); + + Pins::PinOptionsParser parser(tmp, tmp + n); + + { + auto opt = parser.begin(); + auto endopt = parser.end(); + Assert(opt != endopt, "Expected an argument"); + Assert(opt->is("first"), "Expected 'first'"); + + ++opt; + Assert(opt != endopt, "Expected second argument"); + Assert(opt->is("second"), "Expected 'second'"); + + ++opt; + Assert(opt == endopt, "Expected one argument"); + } + + // Typical use is a for loop. Let's test the two ways to use it: + int ctr = 0; + for (auto it : parser) { + if (ctr == 0) { + Assert(it.is("first"), "Expected 'first'"); + } + else if (ctr == 1) { + Assert(it.is("second"), "Expected 'second'"); + } + else { + Assert(false, "Didn't expect to get here"); + } + ++ctr; + } + } +} diff --git a/UnitTests.vcxproj b/UnitTests.vcxproj index b59b9993..05ff4c1d 100644 --- a/UnitTests.vcxproj +++ b/UnitTests.vcxproj @@ -73,6 +73,7 @@ + diff --git a/UnitTests.vcxproj.filters b/UnitTests.vcxproj.filters index 0d9c89de..878e967a 100644 --- a/UnitTests.vcxproj.filters +++ b/UnitTests.vcxproj.filters @@ -143,6 +143,9 @@ X86TestSupport + + test\Pins +