mirror of
https://github.com/bdring/Grbl_Esp32.git
synced 2025-09-02 19:02:35 +02:00
Added some unit tests; fixed pin option parser.
This commit is contained in:
@@ -16,7 +16,6 @@ Global
|
|||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||||
{11C8A44F-A303-4885-B5AD-5B65F7FE41C0}.Debug|x64.ActiveCfg = Debug|x64
|
{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.ActiveCfg = Debug|Win32
|
||||||
{11C8A44F-A303-4885-B5AD-5B65F7FE41C0}.Debug|x86.Build.0 = Debug|Win32
|
{11C8A44F-A303-4885-B5AD-5B65F7FE41C0}.Debug|x86.Build.0 = Debug|Win32
|
||||||
{11C8A44F-A303-4885-B5AD-5B65F7FE41C0}.Release|x64.ActiveCfg = Release|x64
|
{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.ActiveCfg = Release|Win32
|
||||||
{11C8A44F-A303-4885-B5AD-5B65F7FE41C0}.Release|x86.Build.0 = 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.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.ActiveCfg = Debug|Win32
|
||||||
{33ECE513-60D1-4949-A4A9-C95D353C2CF0}.Debug|x86.Build.0 = Debug|Win32
|
{33ECE513-60D1-4949-A4A9-C95D353C2CF0}.Debug|x86.Build.0 = Debug|Win32
|
||||||
{33ECE513-60D1-4949-A4A9-C95D353C2CF0}.Release|x64.ActiveCfg = Release|x64
|
{33ECE513-60D1-4949-A4A9-C95D353C2CF0}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
@@ -21,7 +21,7 @@ namespace Pins {
|
|||||||
|
|
||||||
bool PinAttributes::validateWith(PinCapabilities caps) {
|
bool PinAttributes::validateWith(PinCapabilities caps) {
|
||||||
auto capMask = (caps._value & capabilityMask);
|
auto capMask = (caps._value & capabilityMask);
|
||||||
auto attrMask = _value;
|
auto attrMask = (_value & capabilityMask);
|
||||||
|
|
||||||
// We're good if:
|
// We're good if:
|
||||||
return (capMask & attrMask) == attrMask && // the capabilities overlap with the required attributes AND
|
return (capMask & attrMask) == attrMask && // the capabilities overlap with the required attributes AND
|
||||||
|
@@ -3,11 +3,11 @@
|
|||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
namespace Pins {
|
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); }
|
bool PinOption::is(const char* option) const { return !::strcmp(option, _start); }
|
||||||
|
|
||||||
PinOption PinOption ::operator++() const {
|
PinOption& PinOption::operator++() {
|
||||||
if (_start == _end) {
|
if (_start == _end) {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
@@ -16,13 +16,14 @@ namespace Pins {
|
|||||||
if (newStart != _end) { // and 1 past it if we're not at the end
|
if (newStart != _end) { // and 1 past it if we're not at the end
|
||||||
++newStart;
|
++newStart;
|
||||||
}
|
}
|
||||||
return PinOption(newStart, _end);
|
_start = newStart;
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
PinOptionsParser::PinOptionsParser(char* buffer, char* bufferEnd) : _buffer(buffer), _bufferEnd(bufferEnd) {
|
PinOptionsParser::PinOptionsParser(char* buffer, char* bufferEnd) : _buffer(buffer), _bufferEnd(bufferEnd) {
|
||||||
// Do the actual parsing:
|
// Do the actual parsing:
|
||||||
for (auto i = buffer; i != bufferEnd; ++i) {
|
for (auto i = buffer; i != bufferEnd; ++i) {
|
||||||
if (*i == ':') {
|
if (*i == ':' || *i == ';') {
|
||||||
*i = '\0';
|
*i = '\0';
|
||||||
} else if (*i >= 'A' && *i <= 'Z') { // where did cstring->tolower go? Anyways, here goes:
|
} else if (*i >= 'A' && *i <= 'Z') { // where did cstring->tolower go? Anyways, here goes:
|
||||||
*i = char(*i + 32);
|
*i = char(*i + 32);
|
||||||
|
@@ -35,7 +35,7 @@ namespace Pins {
|
|||||||
// Iterator support:
|
// Iterator support:
|
||||||
inline PinOption const* operator->() const { return this; }
|
inline PinOption const* operator->() const { return this; }
|
||||||
inline PinOption 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; }
|
||||||
bool operator!=(const PinOption& o) const { return _start != o._start; }
|
bool operator!=(const PinOption& o) const { return _start != o._start; }
|
||||||
|
@@ -247,4 +247,34 @@ namespace Pins {
|
|||||||
Pin gpio16 = Pin::create("gpio.16");
|
Pin gpio16 = Pin::create("gpio.16");
|
||||||
Assert(gpio16.name().equals("GPIO.16"), "Name is %s", gpio16.name().c_str());
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
128
Grbl_Esp32/test/Pins/PinOptionParsing.cpp
Normal file
128
Grbl_Esp32/test/Pins/PinOptionParsing.cpp
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
#include "../TestFramework.h"
|
||||||
|
|
||||||
|
#include "src/Pins/PinOptionsParser.h"
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@@ -73,6 +73,7 @@
|
|||||||
<ClCompile Include="Grbl_Esp32\test\Pins\BasicGPIO.cpp" />
|
<ClCompile Include="Grbl_Esp32\test\Pins\BasicGPIO.cpp" />
|
||||||
<ClCompile Include="Grbl_Esp32\test\Pins\Error.cpp" />
|
<ClCompile Include="Grbl_Esp32\test\Pins\Error.cpp" />
|
||||||
<ClCompile Include="Grbl_Esp32\test\Pins\GPIO.cpp" />
|
<ClCompile Include="Grbl_Esp32\test\Pins\GPIO.cpp" />
|
||||||
|
<ClCompile Include="Grbl_Esp32\test\Pins\PinOptionParsing.cpp" />
|
||||||
<ClCompile Include="Grbl_Esp32\test\Pins\Undefined.cpp" />
|
<ClCompile Include="Grbl_Esp32\test\Pins\Undefined.cpp" />
|
||||||
<ClCompile Include="Grbl_Esp32\test\TestFactory.cpp" />
|
<ClCompile Include="Grbl_Esp32\test\TestFactory.cpp" />
|
||||||
<ClCompile Include="Grbl_Esp32\test\TestFrameworkTest.cpp" />
|
<ClCompile Include="Grbl_Esp32\test\TestFrameworkTest.cpp" />
|
||||||
|
@@ -143,6 +143,9 @@
|
|||||||
<ClCompile Include="X86TestSupport\Arduino.cpp">
|
<ClCompile Include="X86TestSupport\Arduino.cpp">
|
||||||
<Filter>X86TestSupport</Filter>
|
<Filter>X86TestSupport</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="Grbl_Esp32\test\Pins\PinOptionParsing.cpp">
|
||||||
|
<Filter>test\Pins</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="Grbl_Esp32\test\UnitTests.md">
|
<None Include="Grbl_Esp32\test\UnitTests.md">
|
||||||
|
Reference in New Issue
Block a user