STAR
Cal STAR — firmware, DAQ server, and engine design
Loading...
Searching...
No Matches
test_main.cpp
Go to the documentation of this file.
1// End-to-end host test: fake radio -> Link::poll -> decode_frame -> ArmGate.
2#include <string.h>
3
5#include "unity.h"
6
7// Build the code under test, plus the fake radio from the radio.h tests.
12
13using namespace radio_link;
14
15static const uint8_t kMe = 7;
16
17static Link lk(kMe);
18
19void setUp(void) {
20 fake::reset(true);
21 lk = Link(kMe);
22}
23void tearDown(void) {
24}
25
26static void inject_arm(uint16_t seq, bool corrupt) {
27 uint8_t payload[9];
28 uint8_t out[kFrameMaxLen];
29 size_t n = 0;
31 put_u32(payload + 4, ~kArmKey);
32 payload[8] = kMe;
33 TEST_ASSERT_EQUAL(
35 encode_frame(FrameType::Arm, seq, payload, 9, out, sizeof out, n));
36 if (corrupt) {
37 out[6] ^= 0x01; // flip one bit in the key
38 }
39 TEST_ASSERT_TRUE(fake::inject(out, static_cast<uint8_t>(n)));
40}
41
43 fake::reset(true);
44 TEST_ASSERT_EQUAL(RadioStatus::Ok, radio_probe());
45 fake::reset(false);
46 TEST_ASSERT_EQUAL(RadioStatus::ErrNotFound, radio_probe());
47}
48
50 TEST_ASSERT_EQUAL(ArmAction::None, lk.poll(0));
51 TEST_ASSERT_EQUAL_UINT32(0, lk.frames_ok());
52 TEST_ASSERT_EQUAL_UINT32(0, lk.frames_dropped());
53}
54
56 inject_arm(1, false);
57 inject_arm(2, false);
58 TEST_ASSERT_EQUAL(ArmAction::Pending, lk.poll(0));
59 TEST_ASSERT_EQUAL(ArmAction::Arm, lk.poll(100));
60 TEST_ASSERT_EQUAL_UINT32(2, lk.frames_ok());
61 TEST_ASSERT_EQUAL_UINT32(0, lk.frames_dropped());
62}
63
65 inject_arm(1, true); // bit flip: CRC fails
66 TEST_ASSERT_EQUAL(ArmAction::None, lk.poll(0));
67 TEST_ASSERT_EQUAL_UINT32(0, lk.frames_ok());
68 TEST_ASSERT_EQUAL_UINT32(1, lk.frames_dropped());
69}
70
72 uint8_t noise[12] = {0xDE, 0xAD, 0xBE, 0xEF, 1, 2, 3, 4, 5, 6, 7, 8};
73 inject_arm(1, false);
74 TEST_ASSERT_TRUE(fake::inject(noise, sizeof noise));
75 inject_arm(2, false);
76 TEST_ASSERT_EQUAL(ArmAction::Pending, lk.poll(0));
77 TEST_ASSERT_EQUAL(ArmAction::None, lk.poll(10)); // noise dropped
78 TEST_ASSERT_EQUAL(ArmAction::Arm, lk.poll(20));
79 TEST_ASSERT_EQUAL_UINT32(1, lk.frames_dropped());
80}
81
82static void test_pure_noise_never_arms(void) {
83 // 200 deterministic pseudo-random packets of varying length.
84 uint32_t x = 12345u;
85 for (int i = 0; i < 200; i++) {
86 uint8_t buf[kLoraMaxPacket];
87 x = x * 1664525u + 1013904223u;
88 const uint8_t len = static_cast<uint8_t>(1 + (x >> 24) % 200);
89 for (unsigned k = 0; k < len; k++) {
90 x = x * 1664525u + 1013904223u;
91 buf[k] = static_cast<uint8_t>(x >> 24);
92 }
93 TEST_ASSERT_TRUE(fake::inject(buf, len));
94 const ArmAction a = lk.poll(static_cast<uint32_t>(i));
95 TEST_ASSERT_TRUE(a == ArmAction::None);
96 }
97}
98
100 uint8_t payload[7] = {1, 0x10, 0x1C, 0, 0, 0, 0};
101 uint8_t out[kFrameMaxLen];
102 size_t n = 0;
103 TEST_ASSERT_EQUAL(
105 encode_frame(FrameType::Heartbeat, 9, payload, 7, out, sizeof out, n));
106 TEST_ASSERT_TRUE(fake::inject(out, static_cast<uint8_t>(n)));
107 TEST_ASSERT_EQUAL(ArmAction::None, lk.poll(0));
108 TEST_ASSERT_EQUAL_UINT32(1, lk.frames_ok());
109 // The decoded frame stays readable for telemetry / link tests.
110 TEST_ASSERT_EQUAL(FrameType::Heartbeat, lk.last_frame().type);
111 TEST_ASSERT_EQUAL_UINT16(9, lk.last_frame().seq);
112 TEST_ASSERT_EQUAL_UINT8(7, lk.last_frame().payload_len);
113 TEST_ASSERT_EQUAL_HEX8_ARRAY(payload, lk.last_frame().payload, 7);
114}
115
117 uint8_t payload[7] = {1, 0x10, 0x1C, 0, 0, 0, 0};
118 uint8_t out[kFrameMaxLen];
119 size_t n = 0;
120 TEST_ASSERT_EQUAL(
122 encode_frame(FrameType::Heartbeat, 41, payload, 7, out, sizeof out, n));
123 TEST_ASSERT_TRUE(fake::inject(out, static_cast<uint8_t>(n)));
124 (void)lk.poll(0);
125 TEST_ASSERT_EQUAL(
127 encode_frame(FrameType::Heartbeat, 42, payload, 7, out, sizeof out, n));
128 out[n - 1] ^= 0xFF; /* a different frame, CRC broken */
129 TEST_ASSERT_TRUE(fake::inject(out, static_cast<uint8_t>(n)));
130 (void)lk.poll(0);
131 TEST_ASSERT_EQUAL_UINT32(1, lk.frames_ok());
132 TEST_ASSERT_EQUAL_UINT16(41, lk.last_frame().seq);
133}
134
136 uint8_t payload[4] = {0xFF, 0x01, 0xE8, 0x1C};
137 uint8_t out[kFrameMaxLen], back[kFrameMaxLen];
138 size_t n = 0;
139 Frame f;
140 TEST_ASSERT_EQUAL(
142 encode_frame(FrameType::SelfTest, 3, payload, 4, out, sizeof out, n));
143 TEST_ASSERT_EQUAL(RadioStatus::Ok,
144 radio_send(out, static_cast<uint8_t>(n)));
145 const uint8_t got = fake::last_sent(back, sizeof back);
146 TEST_ASSERT_EQUAL_UINT8(static_cast<uint8_t>(n), got);
147 TEST_ASSERT_EQUAL(FrameStatus::Ok, decode_frame(back, got, f));
148 TEST_ASSERT_EQUAL(FrameType::SelfTest, f.type);
149}
150
151// A radio that stops answering is not counted as a bad frame: the heartbeat
152// must be able to say "radio dead" rather than "noisy channel".
155 TEST_ASSERT_EQUAL(ArmAction::None, lk.poll(0));
157 TEST_ASSERT_EQUAL(ArmAction::None, lk.poll(1));
158 TEST_ASSERT_EQUAL_UINT32(2, lk.radio_errors());
159 TEST_ASSERT_EQUAL_UINT32(0, lk.frames_dropped());
160 TEST_ASSERT_EQUAL_UINT32(0, lk.frames_ok());
161}
162
*brief create JSON pointer *sa reference_tokens const string_t & a
Definition json.hpp:13877
return reference_tokens back()
*brief user defined string literal for JSON values *sa std::size_t n
Definition json.hpp:24474
int main()
static const uint8_t kMe
Definition test_main.cpp:13