Skip to content

Commit 6a16d27

Browse files
committed
Harden and document Wire mocks
1 parent 47e294a commit 6a16d27

File tree

4 files changed

+101
-17
lines changed

4 files changed

+101
-17
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1414
- `assertInfinity()` and `assertNotInfinity()` for comparing floats to infinity
1515
- `assertNAN()` and `assertNotNAN()` for comparing floats to `NaN`
1616
- `assertion()`, `ReporterTAP.onAssert()`, and `testBehaviorExp` macro to handle simple expression evaluation (is true, is false, etc)
17+
- `Wire.resetMocks()` and documentation
1718

1819
### Changed
1920
- Rubocop expected syntax downgraded from ruby 2.6 to 2.5

REFERENCE.md

+44
Original file line numberDiff line numberDiff line change
@@ -656,3 +656,47 @@ unittest(eeprom)
656656
assertEqual(10, a);
657657
}
658658
```
659+
660+
661+
### Wire
662+
663+
This library allows communication with I2C / TWI devices.
664+
665+
The interface the library has been fully mocked, with the addition of several functions for debugging
666+
667+
* `Wire.resetMocks()`: Initializes all mocks, and for test repeatability should be called at the top of any unit tests that use Wire.
668+
* `Wire.didBegin()`: returns whether `Wire.begin()` was called at any point
669+
* `Wire.getMosi(address)`: returns a pointer to a `deque` that represents the history of data sent to `address`
670+
* `Wire.getMiso(address)`: returns a pointer to a `deque` that defines what the master will read from `address` (i.e. for you to supply)
671+
672+
```c++
673+
unittest(wire_basics) {
674+
// ensure known starting state
675+
Wire.resetMocks();
676+
677+
// in case you need to check that your library is properly calling .begin()
678+
assertFalse(Wire.didBegin());
679+
Wire.begin();
680+
assertTrue(Wire.didBegin());
681+
682+
// pick a random device. master write buffer should be empty
683+
const uint8_t randomSlaveAddr = 14;
684+
deque<uint8_t>* mosi = Wire.getMosi(randomSlaveAddr);
685+
assertEqual(0, mosi->size());
686+
687+
// write some random data to random device
688+
const uint8_t randomData[] = { 0x07, 0x0E };
689+
Wire.beginTransmission(randomSlaveAddr);
690+
Wire.write(randomData[0]);
691+
Wire.write(randomData[1]);
692+
Wire.endTransmission();
693+
694+
// check master write buffer values
695+
assertEqual(2, mosi->size());
696+
assertEqual(randomData[0], mosi->front());
697+
mosi->pop_front();
698+
assertEqual(randomData[1], mosi->front());
699+
mosi->pop_front();
700+
assertEqual(0, mosi->size());
701+
}
702+
```

SampleProjects/TestSomething/test/wire.cpp

+19-4
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,27 @@
33
#include <Wire.h>
44
using std::deque;
55

6+
unittest(wire_init) {
7+
Wire.resetMocks();
8+
assertFalse(Wire.didBegin());
9+
Wire.begin();
10+
assertTrue(Wire.didBegin());
11+
Wire.resetMocks();
12+
assertFalse(Wire.didBegin());
13+
}
14+
615
unittest(begin_write_end) {
16+
Wire.resetMocks();
17+
18+
const uint8_t randomSlaveAddr = 14;
19+
const uint8_t randomData[] = { 0x07, 0x0E };
20+
721
// master write buffer should be empty
8-
deque<uint8_t>* mosi = Wire.getMosi(14);
22+
deque<uint8_t>* mosi = Wire.getMosi(randomSlaveAddr);
923
assertEqual(0, mosi->size());
10-
24+
1125
// write some random data to random slave
12-
const uint8_t randomSlaveAddr = 14;
13-
const uint8_t randomData[] = { 0x07, 0x0E };
26+
1427
Wire.begin();
1528
Wire.beginTransmission(randomSlaveAddr);
1629
Wire.write(randomData[0]);
@@ -27,6 +40,8 @@ unittest(begin_write_end) {
2740
}
2841

2942
unittest(readTwo_writeOne) {
43+
Wire.resetMocks();
44+
3045
Wire.begin();
3146
deque<uint8_t>* miso;
3247
// place some values on random slaves' read buffers

cpp/arduino/Wire.h

+37-13
Original file line numberDiff line numberDiff line change
@@ -54,19 +54,52 @@ struct wireData_t {
5454
class TwoWire : public ObservableDataStream {
5555
private:
5656
bool _didBegin = false;
57-
wireData_t *in = nullptr; // pointer to current slave for writing
58-
wireData_t *out = nullptr; // pointer to current slave for reading
57+
wireData_t* in = nullptr; // pointer to current slave for writing
58+
wireData_t* out = nullptr; // pointer to current slave for reading
5959
wireData_t slaves[SLAVE_COUNT];
6060

6161
public:
62-
// constructor initializes internal data
63-
TwoWire() {
62+
63+
//////////////////////////////////////////////////////////////////////////////////////////////
64+
// testing methods
65+
//////////////////////////////////////////////////////////////////////////////////////////////
66+
67+
// initialize all the mocks
68+
void resetMocks() {
69+
_didBegin = false;
70+
in = nullptr; // pointer to current slave for writing
71+
out = nullptr; // pointer to current slave for reading
6472
for (int i = 0; i < SLAVE_COUNT; ++i) {
6573
slaves[i].misoSize = 0;
6674
slaves[i].mosiSize = 0;
75+
slaves[i].misoBuffer.clear();
76+
slaves[i].mosiBuffer.clear();
6777
}
6878
}
6979

80+
// to verify that Wire.begin() was called at some point
81+
bool didBegin() { return _didBegin; }
82+
83+
// to access the MISO buffer, which allows you to mock what the master will read in a request
84+
deque<uint8_t>* getMiso(uint8_t address) {
85+
return &slaves[address].misoBuffer;
86+
}
87+
88+
// to access the MOSI buffer, which records what the master sends during a write
89+
deque<uint8_t>* getMosi(uint8_t address) {
90+
return &slaves[address].mosiBuffer;
91+
}
92+
93+
94+
//////////////////////////////////////////////////////////////////////////////////////////////
95+
// mock implementation
96+
//////////////////////////////////////////////////////////////////////////////////////////////
97+
98+
// constructor initializes internal data
99+
TwoWire() {
100+
resetMocks();
101+
}
102+
70103
// https://www.arduino.cc/en/Reference/WireBegin
71104
// Initiate the Wire library and join the I2C bus as a master or slave. This
72105
// should normally be called only once.
@@ -220,15 +253,6 @@ class TwoWire : public ObservableDataStream {
220253
// We don't (yet) support the slave role in the mock
221254
void onRequest(void (*callback)(void)) { assert(false); }
222255

223-
// testing methods
224-
bool didBegin() { return _didBegin; }
225-
226-
deque<uint8_t> *getMiso(uint8_t address) {
227-
return &slaves[address].misoBuffer;
228-
}
229-
deque<uint8_t> *getMosi(uint8_t address) {
230-
return &slaves[address].mosiBuffer;
231-
}
232256
};
233257

234258
extern TwoWire Wire;

0 commit comments

Comments
 (0)