xref: /nrf52832-nimble/packages/NimBLE-latest/nimble/host/test/src/ble_os_test.c (revision 042d53a763ad75cb1465103098bb88c245d95138)
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements.  See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership.  The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License.  You may obtain a copy of the License at
9  *
10  *  http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied.  See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 #include <string.h>
21 #include "os/os.h"
22 #include "testutil/testutil.h"
23 #include "nimble/hci_common.h"
24 #include "nimble/ble_hci_trans.h"
25 #include "host/ble_hs_test.h"
26 #include "host/ble_gap.h"
27 #include "ble_hs_test_util.h"
28 
29 #define BLE_OS_TEST_STACK_SIZE      256
30 #define BLE_OS_TEST_APP_STACK_SIZE  256
31 
32 #define BLE_OS_TEST_APP_PRIO         9
33 #define BLE_OS_TEST_TASK_PRIO        10
34 
35 static struct os_task ble_os_test_task;
36 static struct os_task ble_os_test_app_task;
37 static os_stack_t ble_os_test_stack[OS_STACK_ALIGN(BLE_OS_TEST_STACK_SIZE)];
38 
39 static os_stack_t
40 ble_os_test_app_stack[OS_STACK_ALIGN(BLE_OS_TEST_APP_STACK_SIZE)];
41 
42 static uint8_t ble_os_test_peer_addr[6] = { 1, 2, 3, 4, 5, 6 };
43 
44 static void ble_os_test_app_task_handler(void *arg);
45 
46 static int ble_os_test_gap_event_type;
47 
48 static void
ble_os_test_init_app_task(void)49 ble_os_test_init_app_task(void)
50 {
51     int rc;
52 
53     rc = os_task_init(&ble_os_test_app_task,
54                       "ble_gap_terminate_test_task",
55                       ble_os_test_app_task_handler, NULL,
56                       BLE_OS_TEST_APP_PRIO, OS_WAIT_FOREVER,
57                       ble_os_test_app_stack,
58                       OS_STACK_ALIGN(BLE_OS_TEST_APP_STACK_SIZE));
59     TEST_ASSERT_FATAL(rc == 0);
60 }
61 
62 static void
ble_os_test_misc_init(void)63 ble_os_test_misc_init(void)
64 {
65     extern os_time_t g_os_time;
66 
67     ble_hs_test_util_init_no_start();
68 
69     /* Allow the OS to approach tick rollover.  This will help ensure host
70      * timers don't break when the tick counter resets.
71      */
72     g_os_time = UINT32_MAX - 10 * OS_TICKS_PER_SEC;
73 
74     /* Receive acknowledgements for the startup sequence.  We sent the
75      * corresponding requests when the host task was started.
76      */
77     ble_hs_test_util_hci_ack_set_startup();
78 
79     ble_os_test_init_app_task();
80 }
81 
82 static int
ble_os_test_misc_conn_exists(uint16_t conn_handle)83 ble_os_test_misc_conn_exists(uint16_t conn_handle)
84 {
85     struct ble_hs_conn *conn;
86 
87     ble_hs_lock();
88 
89     if (conn_handle == BLE_HS_CONN_HANDLE_NONE) {
90         conn = ble_hs_conn_first();
91     } else {
92         conn = ble_hs_conn_find(conn_handle);
93     }
94 
95     ble_hs_unlock();
96 
97     return conn != NULL;
98 }
99 
100 static int
ble_gap_direct_connect_test_connect_cb(struct ble_gap_event * event,void * arg)101 ble_gap_direct_connect_test_connect_cb(struct ble_gap_event *event, void *arg)
102 {
103     struct ble_gap_conn_desc desc;
104     int *cb_called;
105     int rc;
106 
107     cb_called = arg;
108     *cb_called = 1;
109 
110     TEST_ASSERT(event->type == BLE_GAP_EVENT_CONNECT);
111     TEST_ASSERT(event->connect.status == 0);
112     TEST_ASSERT(event->connect.conn_handle == 2);
113 
114     rc = ble_gap_conn_find(event->connect.conn_handle, &desc);
115     TEST_ASSERT_FATAL(rc == 0);
116     TEST_ASSERT(desc.peer_id_addr.type == BLE_ADDR_PUBLIC);
117     TEST_ASSERT(memcmp(desc.peer_id_addr.val, ble_os_test_peer_addr, 6) == 0);
118 
119     return 0;
120 }
121 
122 static void
ble_gap_direct_connect_test_task_handler(void * arg)123 ble_gap_direct_connect_test_task_handler(void *arg)
124 {
125     struct hci_le_conn_complete evt;
126     ble_addr_t addr = { BLE_ADDR_PUBLIC, { 1, 2, 3, 4, 5, 6 }};
127     int cb_called;
128     int rc;
129 
130     /* Set the connect callback so we can verify that it gets called with the
131      * proper arguments.
132      */
133     cb_called = 0;
134 
135     /* Make sure there are no created connections and no connections in
136      * progress.
137      */
138     TEST_ASSERT(!ble_os_test_misc_conn_exists(BLE_HS_CONN_HANDLE_NONE));
139 
140     /* Initiate a direct connection. */
141     ble_hs_test_util_connect(BLE_OWN_ADDR_PUBLIC, &addr, 0, NULL,
142                              ble_gap_direct_connect_test_connect_cb,
143                              &cb_called, 0);
144     TEST_ASSERT(!ble_os_test_misc_conn_exists(BLE_HS_CONN_HANDLE_NONE));
145     TEST_ASSERT(!cb_called);
146 
147     /* ble_gap_rx_conn_complete() will send extra HCI command, need phony ack */
148     ble_hs_test_util_hci_ack_set(ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
149                              BLE_HCI_OCF_LE_RD_REM_FEAT), 0);
150 
151     /* Receive an HCI connection-complete event. */
152     memset(&evt, 0, sizeof evt);
153     evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
154     evt.status = BLE_ERR_SUCCESS;
155     evt.connection_handle = 2;
156     memcpy(evt.peer_addr, addr.val, 6);
157     rc = ble_gap_rx_conn_complete(&evt, 0);
158     TEST_ASSERT(rc == 0);
159 
160     /* The connection should now be created. */
161     TEST_ASSERT(ble_os_test_misc_conn_exists(2));
162     TEST_ASSERT(cb_called);
163 
164     tu_restart();
165 }
166 
TEST_CASE(ble_gap_direct_connect_test_case)167 TEST_CASE(ble_gap_direct_connect_test_case)
168 {
169     ble_os_test_misc_init();
170 
171     os_task_init(&ble_os_test_task,
172                  "ble_gap_direct_connect_test_task",
173                  ble_gap_direct_connect_test_task_handler, NULL,
174                  BLE_OS_TEST_TASK_PRIO, OS_WAIT_FOREVER, ble_os_test_stack,
175                  OS_STACK_ALIGN(BLE_OS_TEST_STACK_SIZE));
176 
177     os_start();
178 }
179 
180 static int
ble_os_disc_test_cb(struct ble_gap_event * event,void * arg)181 ble_os_disc_test_cb(struct ble_gap_event *event, void *arg)
182 {
183     int *cb_called;
184 
185     cb_called = arg;
186     *cb_called = 1;
187 
188     TEST_ASSERT(event->type == BLE_GAP_EVENT_DISC_COMPLETE);
189 
190     return 0;
191 }
192 
193 static void
ble_os_disc_test_task_handler(void * arg)194 ble_os_disc_test_task_handler(void *arg)
195 {
196     struct ble_gap_disc_params disc_params;
197     int cb_called;
198     int rc;
199 
200     /* Receive acknowledgements for the startup sequence.  We sent the
201      * corresponding requests when the host task was started.
202      */
203     ble_hs_test_util_hci_ack_set_startup();
204 
205     /* Set the connect callback so we can verify that it gets called with the
206      * proper arguments.
207      */
208     cb_called = 0;
209 
210     os_time_delay(10);
211 
212     /* Make sure there are no created connections and no connections in
213      * progress.
214      */
215     TEST_ASSERT(!ble_os_test_misc_conn_exists(BLE_HS_CONN_HANDLE_NONE));
216     TEST_ASSERT(!ble_gap_master_in_progress());
217 
218     /* Initiate the general discovery procedure with a 300 ms timeout. */
219     memset(&disc_params, 0, sizeof disc_params);
220     rc = ble_hs_test_util_disc(BLE_OWN_ADDR_PUBLIC, 300, &disc_params,
221                                ble_os_disc_test_cb,
222                                &cb_called, 0, 0);
223     TEST_ASSERT(rc == 0);
224     TEST_ASSERT(!ble_os_test_misc_conn_exists(BLE_HS_CONN_HANDLE_NONE));
225     TEST_ASSERT(ble_gap_master_in_progress());
226     TEST_ASSERT(!cb_called);
227 
228     /* Receive acks from the controller. */
229     TEST_ASSERT(!ble_os_test_misc_conn_exists(BLE_HS_CONN_HANDLE_NONE));
230     TEST_ASSERT(ble_gap_master_in_progress());
231     TEST_ASSERT(!cb_called);
232 
233     /* Wait 100 ms; verify scan still in progress. */
234     os_time_delay(100 * OS_TICKS_PER_SEC / 1000);
235     TEST_ASSERT(!ble_os_test_misc_conn_exists(BLE_HS_CONN_HANDLE_NONE));
236     TEST_ASSERT(ble_gap_master_in_progress());
237     TEST_ASSERT(!cb_called);
238 
239     ble_hs_test_util_hci_ack_set(
240         ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
241                                     BLE_HCI_OCF_LE_SET_SCAN_ENABLE),
242         0);
243 
244     /* Wait 250 more ms; verify scan completed. */
245     os_time_delay(250 * OS_TICKS_PER_SEC / 1000);
246     TEST_ASSERT(!ble_os_test_misc_conn_exists(BLE_HS_CONN_HANDLE_NONE));
247     TEST_ASSERT(!ble_gap_master_in_progress());
248     TEST_ASSERT(cb_called);
249 
250     tu_restart();
251 }
252 
TEST_CASE(ble_os_disc_test_case)253 TEST_CASE(ble_os_disc_test_case)
254 {
255     ble_os_test_misc_init();
256 
257     os_task_init(&ble_os_test_task,
258                  "ble_os_disc_test_task",
259                  ble_os_disc_test_task_handler, NULL,
260                  BLE_OS_TEST_TASK_PRIO, OS_WAIT_FOREVER, ble_os_test_stack,
261                  OS_STACK_ALIGN(BLE_OS_TEST_STACK_SIZE));
262 
263     os_start();
264 }
265 
266 static int
ble_gap_terminate_cb(struct ble_gap_event * event,void * arg)267 ble_gap_terminate_cb(struct ble_gap_event *event, void *arg)
268 {
269     int *disconn_handle;
270 
271     ble_os_test_gap_event_type = event->type;
272 
273     if (event->type == BLE_GAP_EVENT_DISCONNECT) {
274         disconn_handle = arg;
275         *disconn_handle = event->disconnect.conn.conn_handle;
276     }
277 
278     return 0;
279 }
280 
281 static void
ble_gap_terminate_test_task_handler(void * arg)282 ble_gap_terminate_test_task_handler(void *arg)
283 {
284     struct hci_disconn_complete disconn_evt;
285     struct hci_le_conn_complete conn_evt;
286     ble_addr_t addr1 = { BLE_ADDR_PUBLIC, { 1, 2, 3, 4, 5, 6 }};
287     ble_addr_t addr2 = { BLE_ADDR_PUBLIC, { 2, 3, 4, 5, 6, 7 }};
288     int disconn_handle;
289     int rc;
290 
291     /* Receive acknowledgements for the startup sequence.  We sent the
292      * corresponding requests when the host task was started.
293      */
294     ble_hs_test_util_hci_ack_set_startup();
295 
296     /* Set the connect callback so we can verify that it gets called with the
297      * proper arguments.
298      */
299     disconn_handle = 0;
300 
301     /* Make sure there are no created connections and no connections in
302      * progress.
303      */
304     TEST_ASSERT(!ble_os_test_misc_conn_exists(BLE_HS_CONN_HANDLE_NONE));
305     TEST_ASSERT(!ble_gap_master_in_progress());
306 
307     /* Create two direct connections. */
308     ble_hs_test_util_connect(BLE_OWN_ADDR_PUBLIC,
309                              &addr1, 0, NULL, ble_gap_terminate_cb,
310                              &disconn_handle, 0);
311     /* ble_gap_rx_conn_complete() will send extra HCI command, need phony ack */
312     ble_hs_test_util_hci_ack_set(ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
313                              BLE_HCI_OCF_LE_RD_REM_FEAT), 0);
314     memset(&conn_evt, 0, sizeof conn_evt);
315     conn_evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
316     conn_evt.status = BLE_ERR_SUCCESS;
317     conn_evt.connection_handle = 1;
318     memcpy(conn_evt.peer_addr, addr1.val, 6);
319     rc = ble_gap_rx_conn_complete(&conn_evt, 0);
320     TEST_ASSERT(rc == 0);
321 
322     ble_hs_test_util_connect(BLE_OWN_ADDR_PUBLIC,
323                              &addr2, 0, NULL, ble_gap_terminate_cb,
324                              &disconn_handle, 0);
325     /* ble_gap_rx_conn_complete() will send extra HCI command, need phony ack */
326     ble_hs_test_util_hci_ack_set(ble_hs_hci_util_opcode_join(BLE_HCI_OGF_LE,
327                              BLE_HCI_OCF_LE_RD_REM_FEAT), 0);
328     memset(&conn_evt, 0, sizeof conn_evt);
329     conn_evt.subevent_code = BLE_HCI_LE_SUBEV_CONN_COMPLETE;
330     conn_evt.status = BLE_ERR_SUCCESS;
331     conn_evt.connection_handle = 2;
332     memcpy(conn_evt.peer_addr, addr2.val, 6);
333     rc = ble_gap_rx_conn_complete(&conn_evt, 0);
334     TEST_ASSERT(rc == 0);
335 
336     TEST_ASSERT_FATAL(ble_os_test_misc_conn_exists(1));
337     TEST_ASSERT_FATAL(ble_os_test_misc_conn_exists(2));
338 
339     /* Terminate the first one. */
340     rc = ble_hs_test_util_conn_terminate(1, 0);
341     TEST_ASSERT(rc == 0);
342     disconn_evt.connection_handle = 1;
343     disconn_evt.status = 0;
344     disconn_evt.reason = BLE_ERR_REM_USER_CONN_TERM;
345     ble_hs_test_util_hci_rx_disconn_complete_event(&disconn_evt);
346     TEST_ASSERT(ble_os_test_gap_event_type == BLE_GAP_EVENT_DISCONNECT);
347     TEST_ASSERT(disconn_handle == 1);
348     TEST_ASSERT_FATAL(!ble_os_test_misc_conn_exists(1));
349     TEST_ASSERT_FATAL(ble_os_test_misc_conn_exists(2));
350 
351     /* Terminate the second one. */
352     rc = ble_hs_test_util_conn_terminate(2, 0);
353     TEST_ASSERT(rc == 0);
354     disconn_evt.connection_handle = 2;
355     disconn_evt.status = 0;
356     disconn_evt.reason = BLE_ERR_REM_USER_CONN_TERM;
357     ble_hs_test_util_hci_rx_disconn_complete_event(&disconn_evt);
358     TEST_ASSERT(ble_os_test_gap_event_type == BLE_GAP_EVENT_DISCONNECT);
359     TEST_ASSERT(disconn_handle == 2);
360     TEST_ASSERT_FATAL(!ble_os_test_misc_conn_exists(1));
361     TEST_ASSERT_FATAL(!ble_os_test_misc_conn_exists(2));
362 
363     tu_restart();
364 }
365 
366 static void
ble_os_test_app_task_handler(void * arg)367 ble_os_test_app_task_handler(void *arg)
368 {
369     while (1) {
370         os_eventq_run(os_eventq_dflt_get());
371     }
372 }
373 
TEST_CASE(ble_gap_terminate_test_case)374 TEST_CASE(ble_gap_terminate_test_case)
375 {
376     ble_os_test_misc_init();
377 
378     os_task_init(&ble_os_test_task,
379                  "ble_gap_terminate_test_task",
380                  ble_gap_terminate_test_task_handler, NULL,
381                  BLE_OS_TEST_TASK_PRIO, OS_WAIT_FOREVER, ble_os_test_stack,
382                  OS_STACK_ALIGN(BLE_OS_TEST_STACK_SIZE));
383 
384     os_start();
385 }
386 
TEST_SUITE(ble_os_test_suite)387 TEST_SUITE(ble_os_test_suite)
388 {
389     tu_suite_set_post_test_cb(ble_hs_test_util_post_test, NULL);
390 
391     ble_os_disc_test_case();
392     ble_gap_direct_connect_test_case();
393     ble_gap_terminate_test_case();
394 }
395 
396 int
ble_os_test_all(void)397 ble_os_test_all(void)
398 {
399     ble_os_test_suite();
400     return tu_any_failed;
401 }
402