Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 28 additions & 9 deletions .github/workflows/check.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,38 @@ name: Check
on: [push, pull_request]

jobs:
build:
unit-tests:
runs-on: ${{ matrix.os }}

strategy:
fail-fast: false
matrix:
os: [ubuntu-22.04]
os:
- ubuntu-22.04
#- windows-latest
pio_env:
- native
#- Win32
# exclude:
# - os: ubuntu-22.04
# pio_env: Win32
# - os: windows-latest
# pio_env: native

steps:
-
name: Checkout
uses: actions/checkout@v3
-
name: Tests
run: make
- uses: actions/checkout@v4

- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.11'

- name: Install PlatformIO
run: |
python -m pip install --upgrade pip
pip install --upgrade platformio

- name: Run unit tests
run: platformio test -v -e ${{ matrix.pio_env }}

examples:
runs-on: ${{ matrix.os }}
Expand Down
9 changes: 2 additions & 7 deletions src/ArduinoFake.cpp
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
#include "ArduinoFake.h"

ArduinoFakeContext* arduinoFakeContext;

ArduinoFakeContext* getArduinoFakeContext()
{
if (!arduinoFakeContext) {
arduinoFakeContext = new ArduinoFakeContext();
}

return arduinoFakeContext;
static ArduinoFakeContext arduinoFakeContext;
return &arduinoFakeContext;
}
215 changes: 128 additions & 87 deletions src/ArduinoFake.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,8 @@
#include "SPI.h"
#include "EEPROM.h"

#define ArduinoFake(mock) _ArduinoFakeGet##mock()

#define ArduinoFakeReset() \
getArduinoFakeContext()->reset()
getArduinoFakeContext()->Reset()

#define ArduinoFakeInstance(mock, ...) \
getArduinoFakeContext()->mock(__VA_ARGS__)
Expand All @@ -34,7 +32,7 @@
new mock##FakeProxy(ArduinoFakeInstance(mock))

#define _ArduinoFakeGetMock(mock) \
getArduinoFakeContext()->Mocks->mock
getArduinoFakeContext()->_##mock

#define _ArduinoFakeGetFunction() _ArduinoFakeGetMock(Function)
#define _ArduinoFakeGetSerial() _ArduinoFakeGetMock(Serial)
Expand All @@ -46,101 +44,144 @@
#define _ArduinoFakeGetPrint() _ArduinoFakeGetMock(Print)
#define _ArduinoFakeGet() _ArduinoFakeGetMock(Function)

#define _ArduinoFakeInstanceGetter1(mock) \
mock##Fake* mock() \
{ \
if (!this->Instances->mock){ \
this->Instances->mock = &this->Mocks->mock.get(); \
} \
return this->Instances->mock; \
}
#define ArduinoFake(mock) _ArduinoFakeGet##mock()

#define _ArduinoFakeInstanceGetter2(name, clazz) \
name##Fake* name(class clazz* instance) \
{ \
if (Mapping[instance]) { \
return (name##Fake*) Mapping[instance]; \
} \
if (dynamic_cast<name##FakeProxy*>(instance)) { \
return dynamic_cast<name##FakeProxy*>(instance)->get##name##Fake(); \
} \
throw std::runtime_error("Unknown instance"); \
template <class FakeT, class ProxyT, typename BaseT = fakeit::Mock<FakeT>>
struct ProxiedArduinoFake_t : public BaseT
{
template <class ArduinoT>
FakeT* getFake(ArduinoT *instance)
{
if (dynamic_cast<ProxyT*>(instance)) {
return dynamic_cast<ProxyT*>(instance)->getFake();
}
throw std::runtime_error("Unknown instance");
}
};

struct ArduinoFakeMocks
class FakeOverride_t
{
fakeit::Mock<FunctionFake> Function;
fakeit::Mock<SerialFake> Serial;
fakeit::Mock<WireFake> Wire;
fakeit::Mock<StreamFake> Stream;
fakeit::Mock<ClientFake> Client;
fakeit::Mock<PrintFake> Print;
fakeit::Mock<SPIFake> SPI;
fakeit::Mock<EEPROMFake> EEPROM;
public:
void Reset(void)
{
_mapping.clear();
}

void *getOverride(void *instance)
{
auto iter = _mapping.find(instance);
return iter==_mapping.end() ? nullptr : iter->second;
}

void setOverride(void *instance, void *override)
{
_mapping[instance] = override;
}

private:
std::unordered_map<void*, void*> _mapping;
};

struct ArduinoFakeInstances
template <class FakeT, class ProxyT, typename BaseT = ProxiedArduinoFake_t<FakeT, ProxyT>>
struct OverrideableProxiedArduinoFake_t : public BaseT
{
FunctionFake* Function;
SerialFake* Serial;
WireFake* Wire;
StreamFake* Stream;
ClientFake* Client;
PrintFake* Print;
SPIFake* SPI;
EEPROMFake* EEPROM;
FakeOverride_t &_overrides;

OverrideableProxiedArduinoFake_t(FakeOverride_t &overrides)
: BaseT()
, _overrides(overrides)
{
}

template <class ArduinoT>
FakeT* getFake(ArduinoT *instance)
{
fakeit::Mock<FakeT> *pOverride = static_cast<fakeit::Mock<FakeT> *>(_overrides.getOverride(instance));
if (pOverride!=nullptr) {
return &pOverride->get();
}
return BaseT::getFake(instance);
}
};

class ArduinoFakeContext
{
public:
ArduinoFakeInstances* Instances = new ArduinoFakeInstances();
ArduinoFakeMocks* Mocks = new ArduinoFakeMocks();
std::unordered_map<void*, void*> Mapping;

_ArduinoFakeInstanceGetter1(Print)
_ArduinoFakeInstanceGetter1(Stream)
_ArduinoFakeInstanceGetter1(Serial)
_ArduinoFakeInstanceGetter1(Wire)
_ArduinoFakeInstanceGetter1(Client)
_ArduinoFakeInstanceGetter1(Function)
_ArduinoFakeInstanceGetter1(SPI)
_ArduinoFakeInstanceGetter1(EEPROM)

_ArduinoFakeInstanceGetter2(Print, Print)
_ArduinoFakeInstanceGetter2(Client, Client)
_ArduinoFakeInstanceGetter2(Stream, Stream)
_ArduinoFakeInstanceGetter2(Serial, Serial_)
_ArduinoFakeInstanceGetter2(Wire, TwoWire)
_ArduinoFakeInstanceGetter2(SPI, SPIClass)
_ArduinoFakeInstanceGetter2(EEPROM, EEPROMClass)

ArduinoFakeContext()
{
this->reset();
}
public:
FakeOverride_t _fakeOverrides;
fakeit::Mock<FunctionFake> _Function;
OverrideableProxiedArduinoFake_t<SerialFake, SerialFakeProxy> _Serial;
OverrideableProxiedArduinoFake_t<WireFake, WireFakeProxy> _Wire;
OverrideableProxiedArduinoFake_t<StreamFake, StreamFakeProxy> _Stream;
OverrideableProxiedArduinoFake_t<ClientFake, ClientFakeProxy> _Client;
OverrideableProxiedArduinoFake_t<PrintFake, PrintFakeProxy> _Print;
OverrideableProxiedArduinoFake_t<SPIFake, SPIFakeProxy> _SPI;
OverrideableProxiedArduinoFake_t<EEPROMFake, EEPROMFakeProxy> _EEPROM;

#define _ArduinoFakeInstanceGetter1(mock) \
mock##Fake* mock() \
{ \
return &this->_##mock.get(); \
}

_ArduinoFakeInstanceGetter1(Print)
_ArduinoFakeInstanceGetter1(Stream)
_ArduinoFakeInstanceGetter1(Serial)
_ArduinoFakeInstanceGetter1(Wire)
_ArduinoFakeInstanceGetter1(Client)
_ArduinoFakeInstanceGetter1(Function)
_ArduinoFakeInstanceGetter1(SPI)
_ArduinoFakeInstanceGetter1(EEPROM)

#undef _ArduinoFakeInstanceGetter1

#define _ArduinoFakeInstanceGetter2(name, clazz) \
name##Fake* name(class clazz* instance) \
{ \
return this->_##name.getFake(instance); \
}

_ArduinoFakeInstanceGetter2(Print, Print)
_ArduinoFakeInstanceGetter2(Client, Client)
_ArduinoFakeInstanceGetter2(Stream, Stream)
_ArduinoFakeInstanceGetter2(Serial, Serial_)
_ArduinoFakeInstanceGetter2(Wire, TwoWire)
_ArduinoFakeInstanceGetter2(SPI, SPIClass)
_ArduinoFakeInstanceGetter2(EEPROM, EEPROMClass)

#undef _ArduinoFakeInstanceGetter2

ArduinoFakeContext()
: _fakeOverrides()
, _Function()
, _Serial(_fakeOverrides)
, _Wire(_fakeOverrides)
, _Stream(_fakeOverrides)
, _Client(_fakeOverrides)
, _Print(_fakeOverrides)
, _SPI(_fakeOverrides)
, _EEPROM(_fakeOverrides)
{
this->Reset();
}

void Reset(void)
{
_Function.Reset();
_Serial.Reset();
_Wire.Reset();
_Stream.Reset();
_Client.Reset();
_Print.Reset();
_SPI.Reset();
_EEPROM.Reset();

_fakeOverrides.Reset();
_fakeOverrides.setOverride(&::Serial, &_Serial);
_fakeOverrides.setOverride(&::Wire, &_Wire);
_fakeOverrides.setOverride(&::SPI, &_SPI);
_fakeOverrides.setOverride(&::EEPROM, &_EEPROM);
}

void reset(void)
{
if (this->Instances) {
delete this->Instances;
}
this->Instances = new ArduinoFakeInstances();

this->Mocks->Function.Reset();
this->Mocks->Stream.Reset();
this->Mocks->Serial.Reset();
this->Mocks->Wire.Reset();
this->Mocks->Client.Reset();
this->Mocks->Print.Reset();
this->Mocks->SPI.Reset();
this->Mocks->EEPROM.Reset();

Mapping[&::Serial] = this->Serial();
Mapping[&::Wire] = this->Wire();
Mapping[&::SPI] = this->SPI();
Mapping[&::EEPROM] = this->EEPROM();
}
};

ArduinoFakeContext* getArduinoFakeContext();
Expand Down
2 changes: 1 addition & 1 deletion src/ClientFake.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ class ClientFakeProxy : public StreamFakeProxy, public Client

virtual operator bool();

ClientFake* getClientFake()
ClientFake* getFake()
{
return clientFake;
}
Expand Down
2 changes: 1 addition & 1 deletion src/EEPROMFake.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,5 @@ class EEPROMFakeProxy : public EEPROMClass {
public:
EEPROMFakeProxy(EEPROMFake *fake) { eepromFake = fake; }

EEPROMFake *getEEPROMFake() { return eepromFake; }
EEPROMFake *getFake() { return eepromFake; }
};
2 changes: 1 addition & 1 deletion src/PrintFake.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class PrintFakeProxy : public Print
return printFake->write(value);
}

PrintFake* getPrintFake()
PrintFake* getFake()
{
return printFake;
}
Expand Down
2 changes: 1 addition & 1 deletion src/SPIFake.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,5 @@ class SPIFakeProxy : public SPIClass {
public:
SPIFakeProxy(SPIFake *fake) { spiFake = fake; }

SPIFake *getSPIFake() { return spiFake; }
SPIFake *getFake() { return spiFake; }
};
2 changes: 1 addition & 1 deletion src/SerialFake.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ class SerialFakeProxy : public StreamFakeProxy, public Serial_
serialFake = fake;
}

SerialFake* getSerialFake()
SerialFake* getFake()
{
return serialFake;
}
Expand Down
2 changes: 1 addition & 1 deletion src/StreamFake.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ class StreamFakeProxy : public Stream, public PrintFakeProxy
streamFake->flush();
}

StreamFake* getStreamFake()
StreamFake* getFake()
{
return streamFake;
}
Expand Down
2 changes: 1 addition & 1 deletion src/WireFake.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,5 +37,5 @@ class WireFakeProxy : public StreamFakeProxy, public TwoWire {
public:
WireFakeProxy(WireFake *fake) : StreamFakeProxy(fake) { wireFake = fake; }

WireFake *getWireFake() { return wireFake; }
WireFake *getFake() { return wireFake; }
};
Loading
Loading