Skip to content

Commit 6bd2895

Browse files
Add callback tests
1 parent ef16aa8 commit 6bd2895

File tree

2 files changed

+379
-0
lines changed

2 files changed

+379
-0
lines changed

test/callback_tests.cpp

+378
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,378 @@
1+
#include "wpc_test.hpp"
2+
3+
#include <cstring>
4+
#include <mutex>
5+
#include <chrono>
6+
#include <thread>
7+
8+
class WpcCallbackTest : public WpcTest
9+
{
10+
public:
11+
static void SetUpTestSuite()
12+
{
13+
ASSERT_NO_FATAL_FAILURE(WpcTest::SetUpTestSuite());
14+
15+
// Following parameters should be set in order to be able to start the
16+
// stack, and stack should be stopped in order to be able to set them.
17+
ASSERT_NO_FATAL_FAILURE(WpcTest::StopStack());
18+
ASSERT_EQ(APP_RES_OK, WPC_set_role(APP_ROLE_SINK));
19+
ASSERT_EQ(APP_RES_OK, WPC_set_node_address(2345));
20+
ASSERT_EQ(APP_RES_OK, WPC_set_network_address(0x65432));
21+
ASSERT_EQ(APP_RES_OK, WPC_set_network_channel(38));
22+
23+
// Set diagnostics interval to zero, so that data callbacks are not called.
24+
const uint8_t TEST_CONFIG[] = { 0 };
25+
ASSERT_EQ(APP_RES_OK, WPC_set_app_config_data(1, 0, TEST_CONFIG, sizeof(TEST_CONFIG)));
26+
27+
ASSERT_EQ(APP_RES_OK, WPC_start_stack());
28+
29+
// Wait a bit for possible earlier status messages to be ignored
30+
std::this_thread::sleep_for(std::chrono::milliseconds(500));
31+
}
32+
33+
protected:
34+
struct BaseCallbackHandler
35+
{
36+
void WaitForCallback(size_t max_seconds = 5)
37+
{
38+
for (size_t i = 0; i < 20 * max_seconds; i++) {
39+
std::this_thread::sleep_for(std::chrono::milliseconds(50));
40+
std::lock_guard<std::mutex> lock(mutex);
41+
if (callback_called) {
42+
return;
43+
}
44+
}
45+
46+
ADD_FAILURE() << "Callback was not called";
47+
}
48+
49+
std::mutex mutex;
50+
bool callback_called;
51+
};
52+
53+
struct StackStatusCb : public BaseCallbackHandler
54+
{
55+
void reset()
56+
{
57+
std::lock_guard<std::mutex> lock(mutex);
58+
callback_called = false;
59+
status = 0;
60+
}
61+
62+
uint8_t status;
63+
};
64+
65+
struct ScanNeighborsCb : public BaseCallbackHandler
66+
{
67+
void reset()
68+
{
69+
std::lock_guard<std::mutex> lock(mutex);
70+
callback_called = false;
71+
status = 0;
72+
}
73+
74+
uint8_t status;
75+
};
76+
77+
struct AppConfigCb : public BaseCallbackHandler
78+
{
79+
void reset()
80+
{
81+
std::lock_guard<std::mutex> lock(mutex);
82+
callback_called = false;
83+
interval = 0;
84+
std::memset(config, 0, sizeof(config));
85+
app_config_size = 0;
86+
}
87+
88+
uint16_t interval;
89+
uint8_t config[UINT8_MAX];
90+
91+
uint8_t app_config_size;
92+
};
93+
94+
struct DataSentCb : public BaseCallbackHandler
95+
{
96+
void reset()
97+
{
98+
std::lock_guard<std::mutex> lock(mutex);
99+
callback_called = false;
100+
pduid = 0;
101+
result = 0;
102+
}
103+
104+
uint16_t pduid;
105+
uint8_t result;
106+
};
107+
108+
struct DataReceivedCb : public BaseCallbackHandler
109+
{
110+
void reset()
111+
{
112+
std::lock_guard<std::mutex> lock(mutex);
113+
callback_called = false;
114+
bytes.clear();
115+
qos = APP_QOS_NORMAL;
116+
src_addr = 0;
117+
dst_addr = 0;
118+
expected_src_ep = 0;
119+
expected_dst_ep = 0;
120+
}
121+
122+
std::vector<uint8_t> bytes;
123+
app_qos_e qos;
124+
app_addr_t src_addr;
125+
app_addr_t dst_addr;
126+
127+
uint8_t expected_src_ep;
128+
uint8_t expected_dst_ep;
129+
};
130+
131+
inline static StackStatusCb stack_status_cb;
132+
inline static ScanNeighborsCb scan_neighbors_cb;
133+
inline static AppConfigCb app_config_cb;
134+
inline static DataSentCb data_sent_cb;
135+
inline static DataReceivedCb data_received_cb;
136+
137+
static void onStackStatusReceived(uint8_t status)
138+
{
139+
std::lock_guard<std::mutex> lock(stack_status_cb.mutex);
140+
stack_status_cb.callback_called = true;
141+
142+
stack_status_cb.status = status;
143+
}
144+
145+
static void onScanNeighborsDone(uint8_t status)
146+
{
147+
std::lock_guard<std::mutex> lock(scan_neighbors_cb.mutex);
148+
scan_neighbors_cb.callback_called = true;
149+
150+
scan_neighbors_cb.status = status;
151+
}
152+
153+
static void onAppConfigDataReceived(uint8_t seq, uint16_t interval, uint8_t* config)
154+
{
155+
std::lock_guard<std::mutex> lock(app_config_cb.mutex);
156+
app_config_cb.callback_called = true;
157+
158+
app_config_cb.interval = interval;
159+
std::memcpy(app_config_cb.config, config, app_config_cb.app_config_size);
160+
}
161+
162+
static void onDataSent(uint16_t pduid, uint32_t buffering_delay, uint8_t result)
163+
{
164+
std::lock_guard<std::mutex> lock(data_sent_cb.mutex);
165+
data_sent_cb.callback_called = true;
166+
167+
data_sent_cb.pduid = pduid;
168+
data_sent_cb.result = result;
169+
}
170+
171+
static bool onDataReceived(const uint8_t* bytes,
172+
size_t num_bytes,
173+
app_addr_t src_addr,
174+
app_addr_t dst_addr,
175+
app_qos_e qos,
176+
uint8_t src_ep,
177+
uint8_t dst_ep,
178+
uint32_t travel_time,
179+
uint8_t hop_count,
180+
unsigned long long timestamp_ms_epoch)
181+
{
182+
if (src_ep != data_received_cb.expected_src_ep || dst_ep != data_received_cb.expected_dst_ep) {
183+
return false;
184+
}
185+
186+
std::lock_guard<std::mutex> lock(data_received_cb.mutex);
187+
data_received_cb.callback_called = true;
188+
189+
data_received_cb.bytes.resize(num_bytes);
190+
std::memcpy(data_received_cb.bytes.data(), bytes, num_bytes);
191+
data_received_cb.qos = qos;
192+
data_received_cb.src_addr = src_addr;
193+
data_received_cb.dst_addr = dst_addr;
194+
195+
return true;
196+
}
197+
198+
void SetUp() override
199+
{
200+
stack_status_cb.reset();
201+
scan_neighbors_cb.reset();
202+
app_config_cb.reset();
203+
data_sent_cb.reset();
204+
data_received_cb.reset();
205+
}
206+
207+
void TearDown() override
208+
{
209+
WPC_unregister_from_stack_status();
210+
WPC_unregister_from_scan_neighbors_done();
211+
WPC_unregister_from_app_config_data();
212+
WPC_unregister_for_data();
213+
}
214+
};
215+
216+
TEST_F(WpcCallbackTest, testStackStatus)
217+
{
218+
// Only testing stack stopping, because in some DualMCU versions indication
219+
// for stack starting is not sent.
220+
221+
ASSERT_EQ(APP_RES_OK, WPC_register_for_stack_status(onStackStatusReceived));
222+
223+
ASSERT_EQ(APP_RES_OK, WPC_stop_stack());
224+
225+
ASSERT_NO_FATAL_FAILURE(stack_status_cb.WaitForCallback());
226+
227+
{
228+
std::lock_guard<std::mutex> lock(stack_status_cb.mutex);
229+
// bit 0: 0 = running, 1 = sopped
230+
ASSERT_EQ(1, (stack_status_cb.status & 1));
231+
}
232+
233+
ASSERT_EQ(APP_RES_OK, WPC_start_stack());
234+
}
235+
236+
TEST_F(WpcCallbackTest, testScanNeighbors)
237+
{
238+
ASSERT_EQ(APP_RES_OK, WPC_register_for_scan_neighbors_done(onScanNeighborsDone));
239+
240+
ASSERT_EQ(APP_RES_OK, WPC_start_scan_neighbors());
241+
242+
ASSERT_NO_FATAL_FAILURE(scan_neighbors_cb.WaitForCallback());
243+
244+
{
245+
std::lock_guard<std::mutex> lock(scan_neighbors_cb.mutex);
246+
// 1 = scan done
247+
ASSERT_EQ(1, scan_neighbors_cb.status);
248+
}
249+
250+
app_nbors_t neighbors_list;
251+
ASSERT_EQ(APP_RES_OK, WPC_get_neighbors(&neighbors_list));
252+
}
253+
254+
TEST_F(WpcCallbackTest, testAppConfigData)
255+
{
256+
{
257+
std::lock_guard<std::mutex> lock(app_config_cb.mutex);
258+
ASSERT_EQ(APP_RES_OK, WPC_get_app_config_data_size(&app_config_cb.app_config_size));
259+
}
260+
261+
ASSERT_EQ(APP_RES_OK, WPC_register_for_app_config_data(onAppConfigDataReceived));
262+
263+
const uint8_t TEST_CONFIG[] = { 0xAA, 0xBB, 0xCC, 0xDD };
264+
ASSERT_EQ(APP_RES_OK, WPC_set_app_config_data(1, 600, TEST_CONFIG, sizeof(TEST_CONFIG)));
265+
266+
ASSERT_NO_FATAL_FAILURE(app_config_cb.WaitForCallback());
267+
268+
{
269+
std::lock_guard<std::mutex> lock(app_config_cb.mutex);
270+
ASSERT_EQ(600, app_config_cb.interval);
271+
ASSERT_EQ_ARRAY(TEST_CONFIG, app_config_cb.config, sizeof(TEST_CONFIG));
272+
}
273+
}
274+
275+
TEST_F(WpcCallbackTest, testSendDataWithSendCallback)
276+
{
277+
const uint8_t TEST_DATA[] = { 0x10, 0x12, 0x14, 0x16, 0x18 };
278+
279+
// Send data to the sink itself
280+
ASSERT_EQ(APP_RES_OK,
281+
WPC_send_data(TEST_DATA, sizeof(TEST_DATA), 106, APP_ADDR_ANYSINK, APP_QOS_HIGH, 50, 50, onDataSent, 0));
282+
283+
ASSERT_NO_FATAL_FAILURE(data_sent_cb.WaitForCallback());
284+
285+
{
286+
std::lock_guard<std::mutex> lock(data_sent_cb.mutex);
287+
// 0 = success, 1 = failure
288+
ASSERT_EQ(0, data_sent_cb.result);
289+
ASSERT_EQ(106, data_sent_cb.pduid);
290+
}
291+
}
292+
293+
TEST_F(WpcCallbackTest, testSendDataWithReceiveCallback)
294+
{
295+
const uint8_t TEST_SRC_EP = 51;
296+
const uint8_t TEST_DST_EP = 52;
297+
const uint8_t TEST_DATA[] = { 0x10, 0x12, 0x14, 0x16, 0x18 };
298+
const app_qos_e TEST_QOS = APP_QOS_HIGH;
299+
300+
net_addr_t address;
301+
ASSERT_EQ(APP_RES_OK, WPC_get_node_address(&address));
302+
303+
{
304+
std::lock_guard<std::mutex> lock(data_received_cb.mutex);
305+
data_received_cb.expected_src_ep = TEST_SRC_EP;
306+
data_received_cb.expected_dst_ep = TEST_DST_EP;
307+
}
308+
309+
ASSERT_EQ(APP_RES_OK, WPC_register_for_data(onDataReceived));
310+
311+
312+
// Send data to the sink itself
313+
ASSERT_EQ(APP_RES_OK,
314+
WPC_send_data(TEST_DATA,
315+
sizeof(TEST_DATA),
316+
10,
317+
APP_ADDR_ANYSINK,
318+
TEST_QOS,
319+
TEST_SRC_EP,
320+
TEST_DST_EP,
321+
NULL,
322+
0));
323+
324+
ASSERT_NO_FATAL_FAILURE(data_received_cb.WaitForCallback());
325+
326+
{
327+
std::lock_guard<std::mutex> lock(data_received_cb.mutex);
328+
ASSERT_EQ(sizeof(TEST_DATA), data_received_cb.bytes.size());
329+
ASSERT_EQ_ARRAY(TEST_DATA, (uint8_t*)data_received_cb.bytes.data(), sizeof(TEST_DATA));
330+
ASSERT_EQ(TEST_QOS, data_received_cb.qos);
331+
ASSERT_EQ(address, data_received_cb.src_addr);
332+
ASSERT_EQ(address, data_received_cb.dst_addr);
333+
}
334+
}
335+
336+
TEST_F(WpcCallbackTest, testSendFragmentedDataWithReceiveCallback)
337+
{
338+
const uint8_t TEST_SRC_EP = 73;
339+
const uint8_t TEST_DST_EP = 81;
340+
uint8_t TEST_DATA[500] = { 0 };
341+
std::memset(TEST_DATA, 0xF1, sizeof(TEST_DATA));
342+
const app_qos_e TEST_QOS = APP_QOS_HIGH;
343+
344+
net_addr_t address;
345+
ASSERT_EQ(APP_RES_OK, WPC_get_node_address(&address));
346+
347+
{
348+
std::lock_guard<std::mutex> lock(data_received_cb.mutex);
349+
data_received_cb.expected_src_ep = TEST_SRC_EP;
350+
data_received_cb.expected_dst_ep = TEST_DST_EP;
351+
}
352+
353+
ASSERT_EQ(APP_RES_OK, WPC_register_for_data(onDataReceived));
354+
355+
// Send data to the sink itself
356+
ASSERT_EQ(APP_RES_OK,
357+
WPC_send_data(TEST_DATA,
358+
sizeof(TEST_DATA),
359+
20,
360+
APP_ADDR_ANYSINK,
361+
TEST_QOS,
362+
TEST_SRC_EP,
363+
TEST_DST_EP,
364+
NULL,
365+
0));
366+
367+
ASSERT_NO_FATAL_FAILURE(data_received_cb.WaitForCallback());
368+
369+
{
370+
std::lock_guard<std::mutex> lock(data_received_cb.mutex);
371+
ASSERT_EQ(sizeof(TEST_DATA), data_received_cb.bytes.size());
372+
ASSERT_EQ_ARRAY(TEST_DATA, (uint8_t*)data_received_cb.bytes.data(), sizeof(TEST_DATA));
373+
ASSERT_EQ(TEST_QOS, data_received_cb.qos);
374+
ASSERT_EQ(address, data_received_cb.src_addr);
375+
ASSERT_EQ(address, data_received_cb.dst_addr);
376+
}
377+
}
378+

test/makefile_gtest

+1
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ CFLAGS += -I$(SOURCEPREFIX)
4141
SOURCES += $(SOURCEPREFIX)wpc_test.cpp \
4242
$(SOURCEPREFIX)general_tests.cpp \
4343
$(SOURCEPREFIX)scratchpad_tests.cpp \
44+
$(SOURCEPREFIX)callback_tests.cpp \
4445
$(SOURCEPREFIX)cdd_tests.cpp
4546

4647
OBJECTS := $(patsubst $(SOURCEPREFIX)%, \

0 commit comments

Comments
 (0)