Skip to content

Commit e200d2c

Browse files
authored
Merge pull request #16 from ifreecarve/2018-01-26_mocks
Support for more builtins via mocks
2 parents 2e74ebc + edf63d2 commit e200d2c

File tree

303 files changed

+480674
-47
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

303 files changed

+480674
-47
lines changed

CHANGELOG.md

+13
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,21 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
66

77
## [Unreleased]
88
### Added
9+
- Support for all builtin Math functions https://www.arduino.cc/reference/en/
10+
- Support for all builtin Bits and Bytes functions https://www.arduino.cc/reference/en/
11+
- Support for GODMODE and time functions
12+
- Support for Character functions https://www.arduino.cc/reference/en/
13+
- Mocks for `random` functions with seed control
14+
- Many original Arduino `#define`s
15+
- Mocks for pinMode, analog/digital read/write
16+
- Support for WString
17+
- Support for Print
18+
- Support for Stream (backed by a String implementation)
19+
- All the IO stuff (pins, serial port support flags, etc) from the Arduino library
20+
- Support for Serial (backed by GODMODE)
921

1022
### Changed
23+
- Made `wget` have quieter output
1124

1225
### Deprecated
1326

README.md

+76
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,82 @@ unittest_main()
4949
This test defines one `unittest` (a macro provided by `ArduionUnitTests.h`), called `your_test_name`, which makes some assertions on the target library. The `unittest_main()` is a macro for the `int main()` boilerplate required for unit testing.
5050

5151

52+
### Using `GODMODE`
53+
54+
Complete control of the Arduino environment is available in your unit tests through a construct called `GODMODE()`.
55+
56+
```C++
57+
unittest(example_godmode_stuff)
58+
{
59+
GodmodeState* state = GODMODE(); // get access to the state
60+
state->reset(); // does a full reset of the state.
61+
state->resetClock(); // - you can reset just the clock (to zero)
62+
state->resetPins(); // - or just the pins
63+
state->micros = 1; // manually set the clock such that micros() returns 1
64+
state->digitalPin[4]; // stores the commanded state of digital pin 4
65+
state->digitalPin[4] = HIGH; // digitalRead(4) will now return HIGH
66+
state->analogPin[3]; // stores the commanded state of analog pin 3
67+
state->analogPin[3] = 99; // analogRead(3) will now return 99
68+
}
69+
```
70+
71+
A more complicated example: working with serial port IO. Let's say I have the following function:
72+
73+
```C++
74+
void smartLightswitchSerialHandler(int pin) {
75+
if (Serial.available() > 0) {
76+
int incomingByte = Serial.read();
77+
int val = incomingByte == '0' ? LOW : HIGH;
78+
Serial.print("Ack ");
79+
digitalWrite(pin, val);
80+
Serial.print(String(pin));
81+
Serial.print(" ");
82+
Serial.print((char)incomingByte);
83+
}
84+
}
85+
```
86+
87+
This function has 3 side effects: it drains the serial port's receive buffer, affects a pin, and puts data in the serial port's send buffer. Or, if the receive buffer is empty, it does nothing at all.
88+
89+
```C++
90+
unittest(does_nothing_if_no_data)
91+
{
92+
// configure initial state
93+
GodmodeState* state = GODMODE();
94+
int myPin = 3;
95+
state->serialPort[0].dataIn = "";
96+
state->serialPort[0].dataOut = "";
97+
state->digitalPin[myPin] = LOW;
98+
99+
// execute action
100+
smartLightswitchSerialHandler(myPin);
101+
102+
// assess final state
103+
assertEqual(LOW, state->digitalPin[myPin]);
104+
assertEqual("", state->serialPort[0].dataIn);
105+
assertEqual("", state->serialPort[0].dataOut);
106+
}
107+
108+
unittest(two_flips)
109+
{
110+
GodmodeState* state = GODMODE();
111+
int myPin = 3;
112+
state->serialPort[0].dataIn = "10junk";
113+
state->serialPort[0].dataOut = "";
114+
state->digitalPin[myPin] = LOW;
115+
smartLightswitchSerialHandler(myPin);
116+
assertEqual(HIGH, state->digitalPin[myPin]);
117+
assertEqual("0junk", state->serialPort[0].dataIn);
118+
assertEqual("Ack 3 1", state->serialPort[0].dataOut);
119+
120+
state->serialPort[0].dataOut = "";
121+
smartLightswitchSerialHandler(myPin);
122+
assertEqual(LOW, state->digitalPin[myPin]);
123+
assertEqual("junk", state->serialPort[0].dataIn);
124+
assertEqual("Ack 3 0", state->serialPort[0].dataOut);
125+
}
126+
```
127+
52128
## More Documentation
53129

54130
This software is in alpha. But [SampleProjects/DoSomething](SampleProjects/DoSomething) has a decent writeup and is a good bare-bones example of all the features.
+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
# TestSomething
22

33
This is a "beater" example that is referenced by tests of the Arduino CI module itself.
4+
5+
All the tests of our mocked `Arduino.h` implementation live here.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#include <ArduinoUnitTests.h>
2+
#include <Arduino.h>
3+
4+
unittest(binary)
5+
{
6+
assertEqual(1, B1);
7+
assertEqual(10, B1010);
8+
assertEqual(100, B1100100);
9+
}
10+
11+
unittest_main()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
#include <ArduinoUnitTests.h>
2+
#include <Arduino.h>
3+
4+
unittest(millis_micros_and_delay)
5+
{
6+
GodmodeState* state = GODMODE();
7+
state->reset();
8+
assertEqual(0, millis());
9+
assertEqual(0, micros());
10+
delay(3);
11+
assertEqual(3, millis());
12+
assertEqual(3000, micros());
13+
delayMicroseconds(11000);
14+
assertEqual(14, millis());
15+
assertEqual(14000, micros());
16+
}
17+
18+
unittest(random)
19+
{
20+
randomSeed(1);
21+
unsigned long x;
22+
x = random(4294967293);
23+
assertEqual(4294967292, x);
24+
x = random(50, 100);
25+
assertEqual(83, x);
26+
x = random(100);
27+
assertEqual(74, x);
28+
}
29+
30+
void myInterruptHandler() {
31+
}
32+
33+
unittest(interrupts)
34+
{
35+
// these are meaningless for testing; just call the routine directly.
36+
// make sure our mocks work though
37+
attachInterrupt(2, myInterruptHandler, CHANGE);
38+
detachInterrupt(2);
39+
}
40+
41+
unittest(pins)
42+
{
43+
GodmodeState* state = GODMODE();
44+
state->reset();
45+
pinMode(1, OUTPUT); // this is a no-op in unit tests. it's just here to prove compilation
46+
digitalWrite(1, HIGH);
47+
assertEqual(HIGH, state->digitalPin[1]);
48+
digitalWrite(1, LOW);
49+
assertEqual(LOW, state->digitalPin[1]);
50+
51+
pinMode(1, INPUT);
52+
state->digitalPin[1] = HIGH;
53+
assertEqual(HIGH, digitalRead(1));
54+
state->digitalPin[1] = LOW;
55+
assertEqual(LOW, digitalRead(1));
56+
57+
analogWrite(1, 37);
58+
assertEqual(37, state->analogPin[1]);
59+
analogWrite(1, 22);
60+
assertEqual(22, state->analogPin[1]);
61+
62+
state->analogPin[1] = 99;
63+
assertEqual(99, analogRead(1));
64+
state->analogPin[1] = 56;
65+
assertEqual(56, analogRead(1));
66+
}
67+
68+
unittest_main()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#include <ArduinoUnitTests.h>
2+
#include <Arduino.h>
3+
4+
unittest(abs)
5+
{
6+
assertEqual(1, abs(1));
7+
assertEqual(1, abs(-1));
8+
assertEqual(1.0, abs(1.0));
9+
assertEqual(1.0, abs(-1.0));
10+
}
11+
12+
unittest(constrain)
13+
{
14+
assertEqual(3, constrain(1, 3, 5));
15+
assertEqual(5, constrain(9, 3, 5));
16+
assertEqual(2.0, constrain(1, 2.0, 5));
17+
assertEqual(6.0, constrain(1.3, 6.0, 9));
18+
}
19+
20+
unittest(map)
21+
{
22+
assertEqual(30, map(3, 0, 10, 0, 100));
23+
assertEqual(30, map(20, 0, 50, 50, 0));
24+
assertEqual(-4, map(26, 0, 50, 100, -100));
25+
}
26+
27+
unittest(max)
28+
{
29+
assertEqual(4, max(3, 4));
30+
assertEqual(5, max(3.0, 5));
31+
assertEqual(6.0, max(-4, 6.0));
32+
assertEqual(7.0, max(5.0, 7.0));
33+
}
34+
35+
unittest(min)
36+
{
37+
assertEqual(3, min(3, 4));
38+
assertEqual(3.0, min(3.0, 5));
39+
assertEqual(-4, min(-4, 6.0));
40+
assertEqual(5.0, min(5.0, 7.0));
41+
}
42+
43+
unittest(pow)
44+
{
45+
assertEqual(4.0, pow(2, 2));
46+
assertEqual(4.0, pow(2.0, 2.0));
47+
assertEqual(0.125, pow(2, -3));
48+
assertLess(1.41420, pow(2, 0.5));
49+
assertMore(1.41422, pow(2, 0.5));
50+
}
51+
52+
unittest(sq)
53+
{
54+
assertEqual(9, sq(3));
55+
assertEqual(9.0, sq(3.0));
56+
assertEqual(9, sq(-3));
57+
assertEqual(9.0, sq(-3.0));
58+
assertEqual(0.25, sq(0.5));
59+
assertEqual(0.25, sq(-0.5));
60+
}
61+
62+
unittest(sqrt)
63+
{
64+
assertEqual(3, sqrt(9));
65+
assertEqual(3.0, sqrt(9.0));
66+
}
67+
68+
69+
unittest_main()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
#include <ArduinoUnitTests.h>
2+
#include <Arduino.h>
3+
4+
#if defined(HAVE_HWSERIAL0)
5+
#define HAVE_SERIAL true
6+
#else
7+
#define HAVE_SERIAL false
8+
#endif
9+
10+
bool have_serial_ports = HAVE_SERIAL;
11+
12+
unittest(serial_ports)
13+
{
14+
assertTrue(have_serial_ports);
15+
}
16+
17+
#ifdef HAVE_HWSERIAL0
18+
19+
unittest(reading_writing_serial)
20+
{
21+
GodmodeState* state = GODMODE();
22+
state->serialPort[0].dataIn = "";
23+
state->serialPort[0].dataOut = "";
24+
assertEqual(-1, Serial.peek());
25+
assertEqual("", state->serialPort[0].dataIn);
26+
assertEqual("", state->serialPort[0].dataOut);
27+
state->serialPort[0].dataIn = "a";
28+
assertEqual('a', Serial.peek());
29+
assertEqual("a", state->serialPort[0].dataIn);
30+
assertEqual("", state->serialPort[0].dataOut);
31+
assertEqual('a', Serial.read());
32+
assertEqual("", state->serialPort[0].dataIn);
33+
assertEqual("", state->serialPort[0].dataOut);
34+
Serial.write('b');
35+
assertEqual("", state->serialPort[0].dataIn);
36+
assertEqual("b", state->serialPort[0].dataOut);
37+
Serial.print("cdefg");
38+
assertEqual("", state->serialPort[0].dataIn);
39+
assertEqual("bcdefg", state->serialPort[0].dataOut);
40+
}
41+
42+
#endif
43+
44+
unittest_main()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#include <ArduinoUnitTests.h>
2+
#include <Arduino.h>
3+
4+
unittest(stream_construction)
5+
{
6+
String data = "";
7+
unsigned long micros = 100;
8+
9+
Stream s;
10+
s.mGodmodeDataIn = &data;
11+
s.mGodmodeMicrosDelay = &micros;
12+
13+
assertEqual(0, s.available());
14+
data = "abcd";
15+
assertEqual(4, s.available());
16+
assertEqual('a', s.peek());
17+
assertEqual('a', s.read());
18+
assertEqual("bcd", s.readString());
19+
assertEqual("", s.readString());
20+
21+
}
22+
23+
24+
unittest(stream_find)
25+
{
26+
String data = "";
27+
unsigned long micros = 100;
28+
29+
Stream s;
30+
s.mGodmodeDataIn = &data;
31+
s.mGodmodeMicrosDelay = &micros;
32+
33+
data = "abcdefghijkl";
34+
assertEqual('a', s.peek());
35+
assertEqual(true, s.find('f'));
36+
assertEqual('f', s.peek());
37+
assertEqual("fghijkl", s.readString());
38+
data = "fghijkl";
39+
assertEqual(false, s.findUntil("k", "j"));
40+
assertEqual('j', s.peek());
41+
}
42+
43+
unittest(stream_parse)
44+
{
45+
String data = "";
46+
unsigned long micros = 100;
47+
48+
Stream s;
49+
s.mGodmodeDataIn = &data;
50+
s.mGodmodeMicrosDelay = &micros;
51+
52+
long l;
53+
float f;
54+
data = "abcdefghijkl-123-456abcd";
55+
l = s.parseInt();
56+
assertEqual(-123, l);
57+
assertEqual('-', data[0]);
58+
l = s.parseInt();
59+
assertEqual(-456, l);
60+
l = s.parseInt();
61+
assertEqual(0, l);
62+
63+
data = "abc123.456-345.322";
64+
f = s.parseFloat();
65+
assertLess(123.456 - f, 0.0001);
66+
assertEqual('-', data[0]);
67+
f = s.parseFloat();
68+
assertLess(-345.322 - f, 0.0001);
69+
70+
}
71+
72+
unittest_main()

0 commit comments

Comments
 (0)