Skip to content
Open
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
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ build: cmake

.PHONY: test
test:
@cd $(CURDIR)/build && CTEST_OUTPUT_ON_FAILURE=TRUE make test
@cd $(CURDIR)/build && ctest --verbose

.PHONY: pio-test
pio-test:
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; }
};
8 changes: 5 additions & 3 deletions test/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ using namespace fakeit;
#include "test_client.h"
#include "test_arduino_string.h"
#include "test_include.h"
#include "test_ProxiedArduinoFake_t.h"
#include "test_OverrideableProxiedArduinoFake_t.h"

#ifdef UNIT_TEST

Expand Down Expand Up @@ -45,10 +47,10 @@ int main(int argc, char **argv)
RUN_TEST_GROUP(EEPROMTest);
RUN_TEST_GROUP(ClientTest);
RUN_TEST_GROUP(IncludeTest);
RUN_TEST_GROUP(ProxiedArduinoFakeTTest);
RUN_TEST_GROUP(OverrideableProxiedArduinoFakeTTest);

UNITY_END();

return 0;
return UNITY_END();
}

#endif
Expand Down
44 changes: 44 additions & 0 deletions test/test_OverrideableProxiedArduinoFake_t.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#ifdef UNIT_TEST

namespace OverrideableProxiedArduinoFakeTTest
{
struct IDummy
{
virtual void foo(void) { }
};

struct IArduino
{
virtual void bar(void) {}
};

struct IDummyProxy : public IArduino
{
IDummy *_dummy;
IDummy* getFake(void) { return _dummy; }

virtual void bar(void) override {}
};

void test_getFake(void)
{
FakeOverride_t overrides;
OverrideableProxiedArduinoFake_t<IDummy, IDummyProxy> subject(overrides);

// No override, should get the proxy fake
IDummyProxy proxy;
TEST_ASSERT_EQUAL_PTR(proxy.getFake(), subject.getFake<IArduino>(&proxy));

// Should return the alternate, since it's now overriden
fakeit::Mock<IDummy> alternateFake;
overrides.setOverride(&proxy, &alternateFake);
TEST_ASSERT_EQUAL_PTR(&alternateFake.get(), subject.getFake<IArduino>(&proxy));
}

void run_tests(void)
{
RUN_TEST(test_getFake);
}
}

#endif
Loading