1 /*
2 * Copyright (c) 2024 Nordic Semiconductor
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Subnet bridge test
7 */
8
9 #include "mesh_test.h"
10 #include <zephyr/bluetooth/mesh.h>
11 #include "mesh/net.h"
12 #include "mesh/keys.h"
13 #include "mesh/va.h"
14 #include "bsim_args_runner.h"
15 #include "common/bt_str.h"
16
17 #include <zephyr/logging/log.h>
18 LOG_MODULE_REGISTER(test_brg, LOG_LEVEL_INF);
19
20 #define WAIT_TIME 32 /*seconds*/
21 #define WAIT_TIME_IVU_TEST 240 /* seconds */
22 #define BEACON_INTERVAL 10 /*seconds */
23
24 #define PROV_ADDR 0x0001
25 /* Bridge address must be less than DEVICE_ADDR_START */
26 #define BRIDGE_ADDR 0x0002
27 #define DEVICE_ADDR_START 0x0003
28 #define GROUP_ADDR 0xc000
29
30 #define REMOTE_NODES_MULTICAST 3
31
32 static const uint8_t prov_dev_key[16] = {0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,
33 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef};
34
35 static const uint8_t subnet_keys[][16] = {
36 {0xaa, 0xbb, 0xcc},
37 {0xdd, 0xee, 0xff},
38 {0x11, 0x22, 0x33},
39 {0x12, 0x34, 0x56},
40 };
41
42 static uint8_t prov_uuid[16] = {0x6c, 0x69, 0x6e, 0x67, 0x61, 0xaa};
43 static uint8_t bridge_uuid[16] = {0x6c, 0x69, 0x6e, 0x67, 0x61, 0xbb};
44 static uint8_t dev_uuid[16] = {0x6c, 0x69, 0x6e, 0x67, 0x61, 0xcc};
45
46 static int test_ividx = 0x123456;
47
48 extern const struct bt_mesh_comp comp;
49 static bool tester_ready;
50
51 enum {
52 MSG_TYPE_DATA = 0,
53 MSG_TYPE_GET = 1,
54 MSG_TYPE_STATUS = 2,
55 };
56
57 static uint8_t recvd_msgs[10];
58 static uint8_t recvd_msgs_cnt;
59
60 const struct bt_mesh_va *va_entry;
61
62 /*
63 * The number of remote nodes participating in the test. Initialized to 2 because most tests use 2
64 * remote nodes.
65 */
66 static int remote_nodes = 2;
67
68 BUILD_ASSERT((2 /* opcode */ + 1 /* type */ + 1 /* msgs cnt */ + sizeof(recvd_msgs) +
69 BT_MESH_MIC_SHORT) <= BT_MESH_RX_SDU_MAX,
70 "Status message does not fit into the maximum incoming SDU size.");
71 BUILD_ASSERT((2 /* opcode */ + 1 /* type */ + 1 /* msgs cnt */ + sizeof(recvd_msgs) +
72 BT_MESH_MIC_SHORT) <= BT_MESH_TX_SDU_MAX,
73 "Status message does not fit into the maximum outgoing SDU size.");
74
75 static K_SEM_DEFINE(status_msg_recvd_sem, 0, 1);
76 static K_SEM_DEFINE(prov_sem, 0, 1);
77
test_tester_init(void)78 static void test_tester_init(void)
79 {
80 /* Stub */
81 }
82
test_bridge_init(void)83 static void test_bridge_init(void)
84 {
85 /* Bridge device must always be the second device. */
86 ASSERT_EQUAL(1, get_device_nbr());
87 }
88
test_device_init(void)89 static void test_device_init(void)
90 {
91 ASSERT_TRUE_MSG(get_device_nbr() >= 2, "Regular devices must be initialized after "
92 "tester and Bridge devices.");
93
94 /* Regular devices addresses starts from address 0x0003.*/
95 dev_uuid[6] = get_device_nbr() + 1;
96
97 /* Regular devices are provisioned into subnets starting with idx 1. */
98 dev_uuid[8] = get_device_nbr() - 1;
99 }
100
unprovisioned_beacon(uint8_t uuid[16],bt_mesh_prov_oob_info_t oob_info,uint32_t * uri_hash)101 static void unprovisioned_beacon(uint8_t uuid[16], bt_mesh_prov_oob_info_t oob_info,
102 uint32_t *uri_hash)
103 {
104 int err;
105
106 /* Subnet may not be ready yet when tester receives a beacon. */
107 if (!tester_ready) {
108 LOG_INF("tester is not ready yet");
109 return;
110 }
111
112 LOG_INF("Received unprovisioned beacon, uuid %s", bt_hex(uuid, 16));
113
114 if (!memcmp(uuid, bridge_uuid, 16)) {
115 err = bt_mesh_provision_adv(uuid, 0, BRIDGE_ADDR, 0);
116 if (!err) {
117 LOG_INF("Provisioning bridge at address 0x%04x", BRIDGE_ADDR);
118 }
119
120 return;
121 }
122
123 /* UUID[6] - address to be used for provisioning.
124 * UUID[8] - subnet to be used for provisioning.
125 */
126 uint16_t addr = uuid[6];
127 int subnet_idx = uuid[8];
128
129 err = bt_mesh_provision_adv(uuid, subnet_idx, addr, 0);
130 if (!err) {
131 LOG_INF("Provisioning device at address 0x%04x with NetKeyIdx 0x%04x", addr,
132 subnet_idx);
133 }
134 }
135
prov_node_added(uint16_t net_idx,uint8_t uuid[16],uint16_t addr,uint8_t num_elem)136 static void prov_node_added(uint16_t net_idx, uint8_t uuid[16], uint16_t addr, uint8_t num_elem)
137 {
138 LOG_INF("Device 0x%04x provisioned, NetKeyIdx 0x%04x", addr, net_idx);
139 k_sem_give(&prov_sem);
140 }
141
142 static struct bt_mesh_prov tester_prov = {.uuid = prov_uuid,
143 .unprovisioned_beacon = unprovisioned_beacon,
144 .node_added = prov_node_added};
145
prov_complete(uint16_t net_idx,uint16_t addr)146 static void prov_complete(uint16_t net_idx, uint16_t addr)
147 {
148 LOG_INF("Device 0x%04x provisioning is complete, NetKeyIdx 0x%04x", addr, net_idx);
149 k_sem_give(&prov_sem);
150 }
151
152 static struct bt_mesh_prov device_prov = {
153 .uuid = dev_uuid,
154 .complete = prov_complete,
155 };
156
157 static struct bt_mesh_prov bridge_prov = {
158 .uuid = bridge_uuid,
159 .complete = prov_complete,
160 };
161
tester_setup(void)162 static void tester_setup(void)
163 {
164 uint8_t status;
165 int err;
166
167 ASSERT_OK(bt_mesh_cdb_create(test_net_key));
168 ASSERT_OK(bt_mesh_provision(test_net_key, 0, 0, test_ividx, PROV_ADDR, prov_dev_key));
169
170 err = bt_mesh_cfg_cli_app_key_add(0, PROV_ADDR, 0, 0, test_app_key, &status);
171 if (err || status) {
172 FAIL("AppKey add failed (err %d, status %u)", err, status);
173 return;
174 }
175
176 err = bt_mesh_cfg_cli_mod_app_bind(0, PROV_ADDR, PROV_ADDR, 0, TEST_MOD_ID, &status);
177 if (err || status) {
178 FAIL("Mod app bind failed (err %d, status %u)", err, status);
179 return;
180 }
181
182 for (int i = 0; i < remote_nodes; i++) {
183 LOG_INF("Creating subnet idx %d", i);
184
185 ASSERT_OK(
186 bt_mesh_cfg_cli_net_key_add(0, PROV_ADDR, i + 1, subnet_keys[i], &status));
187 if (status) {
188 FAIL("NetKey add failed (status %u)", status);
189 return;
190 }
191
192 struct bt_mesh_cdb_subnet *subnet = bt_mesh_cdb_subnet_alloc(i + 1);
193
194 ASSERT_TRUE(subnet != NULL);
195
196 ASSERT_OK(bt_mesh_cdb_subnet_key_import(subnet, 0, subnet_keys[i]));
197
198 bt_mesh_cdb_subnet_store(subnet);
199 }
200
201 uint8_t transmit;
202
203 ASSERT_OK(bt_mesh_cfg_cli_relay_set(0, PROV_ADDR, BT_MESH_RELAY_DISABLED,
204 BT_MESH_TRANSMIT(2, 20), &status, &transmit));
205 if (status) {
206 FAIL("Relay set failed (status %u)", status);
207 return;
208 }
209
210 tester_ready = true;
211 }
212
bridge_entry_add(uint16_t src,uint16_t dst,uint16_t net_idx1,uint16_t net_idx2,uint8_t dir)213 static void bridge_entry_add(uint16_t src, uint16_t dst, uint16_t net_idx1, uint16_t net_idx2,
214 uint8_t dir)
215 {
216 struct bt_mesh_brg_cfg_table_entry entry;
217 struct bt_mesh_brg_cfg_table_status rsp;
218 int err;
219
220 entry.directions = dir;
221 entry.net_idx1 = net_idx1;
222 entry.net_idx2 = net_idx2;
223 entry.addr1 = src;
224 entry.addr2 = dst;
225
226 err = bt_mesh_brg_cfg_cli_table_add(0, BRIDGE_ADDR, &entry, &rsp);
227 if (err || rsp.status || rsp.entry.directions != dir || rsp.entry.net_idx1 != net_idx1 ||
228 rsp.entry.net_idx2 != net_idx2 || rsp.entry.addr1 != src || rsp.entry.addr2 != dst) {
229 FAIL("Bridging table add failed (err %d) (status %u)", err, rsp.status);
230 return;
231 }
232 }
233
bridge_entry_remove(uint16_t src,uint16_t dst,uint16_t net_idx1,uint16_t net_idx2)234 static void bridge_entry_remove(uint16_t src, uint16_t dst, uint16_t net_idx1, uint16_t net_idx2)
235 {
236 struct bt_mesh_brg_cfg_table_status rsp;
237
238 ASSERT_OK(bt_mesh_brg_cfg_cli_table_remove(0, BRIDGE_ADDR, net_idx1, net_idx2, src, dst,
239 &rsp));
240 if (rsp.status) {
241 FAIL("Bridging table remove failed (status %u)", rsp.status);
242 return;
243 }
244 }
245
tester_bridge_configure(void)246 static void tester_bridge_configure(void)
247 {
248 uint8_t status;
249
250 LOG_INF("Configuring bridge...");
251
252 ASSERT_OK(
253 bt_mesh_cfg_cli_net_transmit_set(0, BRIDGE_ADDR, BT_MESH_TRANSMIT(2, 20), &status));
254 if (status != BT_MESH_TRANSMIT(2, 20)) {
255 FAIL("Net transmit set failed (status %u)", status);
256 }
257
258 for (int i = 0; i < remote_nodes; i++) {
259 ASSERT_OK(bt_mesh_cfg_cli_net_key_add(0, BRIDGE_ADDR, i + 1, subnet_keys[i],
260 &status));
261 if (status) {
262 FAIL("NetKey add failed (status %u)", status);
263 }
264 }
265
266 ASSERT_OK(bt_mesh_brg_cfg_cli_set(0, BRIDGE_ADDR, BT_MESH_BRG_CFG_ENABLED, &status));
267 if (status != BT_MESH_BRG_CFG_ENABLED) {
268 FAIL("Subnet bridge set failed (status %u)", status);
269 }
270
271 /* Disable Relay feature to avoid interference in the test. */
272 uint8_t transmit;
273
274 ASSERT_OK(bt_mesh_cfg_cli_relay_set(0, BRIDGE_ADDR, BT_MESH_RELAY_DISABLED,
275 BT_MESH_TRANSMIT(2, 20), &status, &transmit));
276 if (status) {
277 FAIL("Relay set failed (status %u)", status);
278 }
279
280 LOG_INF("Bridge configured");
281 }
282
tester_device_configure(uint16_t net_key_idx,uint16_t addr)283 static void tester_device_configure(uint16_t net_key_idx, uint16_t addr)
284 {
285 int err;
286 uint8_t status;
287
288 err = bt_mesh_cfg_cli_app_key_add(net_key_idx, addr, net_key_idx, 0, test_app_key, &status);
289 if (err || status) {
290 FAIL("AppKey add failed (err %d, status %u)", err, status);
291 return;
292 }
293
294 err = bt_mesh_cfg_cli_mod_app_bind(net_key_idx, addr, addr, 0, TEST_MOD_ID, &status);
295 if (err || status) {
296 FAIL("Mod app bind failed (err %d, status %u)", err, status);
297 return;
298 }
299
300 /* Disable SNB on devices to let Subnet Bridge propagate new IV index value. */
301 err = bt_mesh_cfg_cli_beacon_set(net_key_idx, addr, BT_MESH_BEACON_DISABLED, &status);
302 if (err || status) {
303 FAIL("Beacon set failed (err %d, status %u)", err, status);
304 return;
305 }
306
307 LOG_INF("Device 0x%04x configured", addr);
308 }
309
tester_data_cb(uint8_t * data,size_t length)310 static void tester_data_cb(uint8_t *data, size_t length)
311 {
312 uint8_t type = data[0];
313
314 LOG_HEXDUMP_DBG(data, length, "tester received message");
315
316 ASSERT_TRUE_MSG(length > 1, "Too short message");
317 ASSERT_EQUAL(type, MSG_TYPE_STATUS);
318
319 recvd_msgs_cnt = data[1];
320 ASSERT_EQUAL(recvd_msgs_cnt * sizeof(recvd_msgs[0]), length - 2);
321 memcpy(recvd_msgs, &data[2], recvd_msgs_cnt * sizeof(recvd_msgs[0]));
322
323 k_sem_give(&status_msg_recvd_sem);
324 }
325
send_data(uint16_t dst,uint8_t payload,const uint8_t * uuid)326 static int send_data(uint16_t dst, uint8_t payload, const uint8_t *uuid)
327 {
328 uint8_t data[2] = {MSG_TYPE_DATA, payload};
329
330 return bt_mesh_test_send_data(dst, uuid, data, sizeof(data), NULL, NULL);
331 }
332
send_get(uint16_t dst,const uint8_t * uuid)333 static int send_get(uint16_t dst, const uint8_t *uuid)
334 {
335 uint8_t data[1] = {MSG_TYPE_GET};
336
337 return bt_mesh_test_send_data(dst, uuid, data, sizeof(data), NULL, NULL);
338 }
339
340 struct bridged_addresses_entry {
341 uint16_t addr1;
342 uint16_t addr2;
343 uint8_t dir;
344 };
345
bridge_table_verify(uint16_t net_idx1,uint16_t net_idx2,uint16_t start_idx,struct bridged_addresses_entry * list,size_t list_len)346 static void bridge_table_verify(uint16_t net_idx1, uint16_t net_idx2, uint16_t start_idx,
347 struct bridged_addresses_entry *list, size_t list_len)
348 {
349 struct bt_mesh_brg_cfg_table_list rsp = {
350 .list = NET_BUF_SIMPLE(BT_MESH_RX_SDU_MAX),
351 };
352
353 net_buf_simple_init(rsp.list, 0);
354
355 ASSERT_OK(
356 bt_mesh_brg_cfg_cli_table_get(0, BRIDGE_ADDR, net_idx1, net_idx2, start_idx, &rsp));
357 ASSERT_EQUAL(rsp.status, 0);
358 ASSERT_EQUAL(rsp.net_idx1, net_idx1);
359 ASSERT_EQUAL(rsp.net_idx2, net_idx2);
360 ASSERT_EQUAL(rsp.start_idx, start_idx);
361
362 LOG_HEXDUMP_DBG(rsp.list->data, rsp.list->len, "Received table");
363
364 ASSERT_EQUAL(rsp.list->len / 5, list_len);
365 ASSERT_EQUAL(rsp.list->len % 5, 0);
366
367 for (int i = 0; i < list_len; i++) {
368 struct bridged_addresses_entry entry;
369
370 entry.addr1 = net_buf_simple_pull_le16(rsp.list);
371 entry.addr2 = net_buf_simple_pull_le16(rsp.list);
372 entry.dir = net_buf_simple_pull_u8(rsp.list);
373
374 ASSERT_EQUAL(entry.addr1, list[i].addr1);
375 ASSERT_EQUAL(entry.addr2, list[i].addr2);
376 ASSERT_EQUAL(entry.dir, list[i].dir);
377 }
378 }
379
device_data_cb(uint8_t * data,size_t length)380 static void device_data_cb(uint8_t *data, size_t length)
381 {
382 uint8_t type = data[0];
383
384 /* For group/va tests: There is no bridge entry for the subnet that the final device
385 * belongs to. If it receives a message from the tester, fail.
386 */
387 ASSERT_TRUE_MSG(get_device_nbr() != REMOTE_NODES_MULTICAST + 1,
388 "Unbridged device received message");
389
390 LOG_HEXDUMP_DBG(data, length, "Device received message");
391
392 switch (type) {
393 case MSG_TYPE_DATA:
394 ASSERT_EQUAL(2, length);
395 ASSERT_TRUE_MSG(recvd_msgs_cnt < ARRAY_SIZE(recvd_msgs), "Too many messages");
396
397 recvd_msgs[recvd_msgs_cnt] = data[1];
398 recvd_msgs_cnt++;
399
400 break;
401
402 case MSG_TYPE_GET: {
403 uint8_t test_data[1 /*type */ + 1 /* msgs cnt */ + sizeof(recvd_msgs)] = {
404 MSG_TYPE_STATUS, recvd_msgs_cnt};
405
406 memcpy(&test_data[2], recvd_msgs, recvd_msgs_cnt * sizeof(recvd_msgs[0]));
407
408 ASSERT_OK(bt_mesh_test_send_data(PROV_ADDR, NULL, test_data,
409 2 + recvd_msgs_cnt * sizeof(recvd_msgs[0]), NULL,
410 NULL));
411
412 memset(recvd_msgs, 0, sizeof(recvd_msgs));
413 recvd_msgs_cnt = 0;
414
415 break;
416 }
417
418 case MSG_TYPE_STATUS:
419 ASSERT_TRUE_MSG(false, "Unexpected message");
420 break;
421 }
422 }
423
424 /**
425 * This is a workaround that removes secondary subnets from the tester to avoid message cache
426 * hit when the devices send STATUS message encrypted with the subnet key known by the tester,
427 * but with different app key pair (app key is the same, but net key <-> app key pair is different).
428 */
tester_workaround(void)429 static void tester_workaround(void)
430 {
431 uint8_t status;
432 int err;
433
434 LOG_INF("Applying subnet's workaround for tester...");
435
436 for (int i = 0; i < remote_nodes; i++) {
437 err = bt_mesh_cfg_cli_net_key_del(0, PROV_ADDR, i + 1, &status);
438 if (err || status) {
439 FAIL("NetKey del failed (err %d, status %u)", err, status);
440 return;
441 }
442 }
443 }
444
tester_init_common(void)445 static void tester_init_common(void)
446 {
447 bt_mesh_device_setup(&tester_prov, &comp);
448 tester_setup();
449
450 for (int i = 0; i < 1 /* bridge */ + remote_nodes; i++) {
451 LOG_INF("Waiting for a device to provision...");
452 ASSERT_OK(k_sem_take(&prov_sem, K_SECONDS(40)));
453 }
454
455 tester_bridge_configure();
456
457 for (int i = 0; i < remote_nodes; i++) {
458 tester_device_configure(i + 1, DEVICE_ADDR_START + i);
459 }
460
461 bt_mesh_test_data_cb_setup(tester_data_cb);
462 }
463
setup_basic_bridge(void)464 static void setup_basic_bridge(void)
465 {
466 /* Adding devices to bridge table */
467 for (int i = 0; i < remote_nodes; i++) {
468 bridge_entry_add(PROV_ADDR, DEVICE_ADDR_START + i, 0, i + 1,
469 BT_MESH_BRG_CFG_DIR_TWOWAY);
470 }
471 }
472
send_and_receive(void)473 static void send_and_receive(void)
474 {
475 const int msgs_cnt = 3;
476
477 LOG_INF("Sending data...");
478
479 for (int i = 0; i < remote_nodes; i++) {
480 uint8_t payload = i | i << 4;
481
482 for (int j = 0; j < msgs_cnt; j++) {
483 ASSERT_OK(send_data(DEVICE_ADDR_START + i, payload + j, NULL));
484 }
485 }
486
487 LOG_INF("Checking data...");
488
489 for (int i = 0; i < remote_nodes; i++) {
490 uint8_t payload = i | i << 4;
491
492 ASSERT_OK(send_get(DEVICE_ADDR_START + i, NULL));
493 ASSERT_OK(k_sem_take(&status_msg_recvd_sem, K_SECONDS(5)));
494
495 ASSERT_EQUAL(recvd_msgs_cnt, msgs_cnt);
496 for (int j = 0; j < recvd_msgs_cnt; j++) {
497 ASSERT_EQUAL(recvd_msgs[j], payload + j);
498 }
499 }
500 }
501
test_tester_simple(void)502 static void test_tester_simple(void)
503 {
504 uint8_t status;
505 int err;
506
507 bt_mesh_test_cfg_set(NULL, WAIT_TIME);
508 tester_init_common();
509 setup_basic_bridge();
510 tester_workaround();
511
512 LOG_INF("Step 1: Checking bridging table...");
513
514 send_and_receive();
515
516 LOG_INF("Step 2: Disabling bridging...");
517
518 err = bt_mesh_brg_cfg_cli_set(0, BRIDGE_ADDR, BT_MESH_BRG_CFG_DISABLED, &status);
519 if (err || status != BT_MESH_BRG_CFG_DISABLED) {
520 FAIL("Subnet bridge set failed (err %d) (status %u)", err, status);
521 return;
522 }
523
524 LOG_INF("Sending data...");
525 for (int i = 0; i < remote_nodes; i++) {
526 uint8_t payload = i | i << 4;
527
528 for (int j = 0; j < 3; j++) {
529 ASSERT_OK(send_data(DEVICE_ADDR_START + i, payload + j, NULL));
530 }
531 }
532
533 LOG_INF("Step3: Enabling bridging...");
534 err = bt_mesh_brg_cfg_cli_set(0, BRIDGE_ADDR, BT_MESH_BRG_CFG_ENABLED, &status);
535 if (err || status != BT_MESH_BRG_CFG_ENABLED) {
536 FAIL("Subnet bridge set failed (err %d) (status %u)", err, status);
537 return;
538 }
539
540 LOG_INF("Checking data...");
541 for (int i = 0; i < remote_nodes; i++) {
542 ASSERT_OK(send_get(DEVICE_ADDR_START + i, NULL));
543 ASSERT_OK(k_sem_take(&status_msg_recvd_sem, K_SECONDS(5)));
544
545 ASSERT_EQUAL(recvd_msgs_cnt, 0);
546 }
547
548 PASS();
549 }
550
tester_simple_multicast(uint16_t addr,const uint8_t * uuid)551 static void tester_simple_multicast(uint16_t addr, const uint8_t *uuid)
552 {
553 uint8_t status;
554 int err;
555 const int msgs_cnt = 3;
556
557 /* Adding devices to bridge table */
558 for (int i = 0; i < remote_nodes; i++) {
559 /* Bridge messages from tester to multicast addr, for each subnet expect the last */
560 if (i != remote_nodes - 1) {
561 bridge_entry_add(PROV_ADDR, addr, 0, i + 1, BT_MESH_BRG_CFG_DIR_ONEWAY);
562 }
563
564 /* Bridge messages from remote nodes to tester */
565 bridge_entry_add(DEVICE_ADDR_START + i, PROV_ADDR, i + 1, 0,
566 BT_MESH_BRG_CFG_DIR_ONEWAY);
567 }
568
569 tester_workaround();
570
571 bt_mesh_test_data_cb_setup(tester_data_cb);
572
573 LOG_INF("Step 1: Checking bridging table...");
574
575 LOG_INF("Sending data...");
576
577 for (int i = 0; i < msgs_cnt; i++) {
578 ASSERT_OK(send_data(addr, i, uuid));
579 }
580
581 LOG_INF("Checking data...");
582
583 ASSERT_OK(send_get(addr, uuid));
584 for (int i = 0; i < remote_nodes - 1; i++) {
585 ASSERT_OK(k_sem_take(&status_msg_recvd_sem, K_SECONDS(5)));
586
587 ASSERT_EQUAL(recvd_msgs_cnt, msgs_cnt);
588 for (int j = 0; j < recvd_msgs_cnt; j++) {
589 ASSERT_EQUAL(recvd_msgs[j], j);
590 }
591 }
592
593 LOG_INF("Step 2: Disabling bridging...");
594
595 err = bt_mesh_brg_cfg_cli_set(0, BRIDGE_ADDR, BT_MESH_BRG_CFG_DISABLED, &status);
596 if (err || status != BT_MESH_BRG_CFG_DISABLED) {
597 FAIL("Subnet bridge set failed (err %d) (status %u)", err, status);
598 return;
599 }
600
601 LOG_INF("Sending data...");
602 for (int i = 0; i < msgs_cnt; i++) {
603 ASSERT_OK(send_data(addr, i, uuid));
604 }
605
606 LOG_INF("Step 3: Enabling bridging...");
607 err = bt_mesh_brg_cfg_cli_set(0, BRIDGE_ADDR, BT_MESH_BRG_CFG_ENABLED, &status);
608 if (err || status != BT_MESH_BRG_CFG_ENABLED) {
609 FAIL("Subnet bridge set failed (err %d) (status %u)", err, status);
610 return;
611 }
612
613 LOG_INF("Checking data...");
614 ASSERT_OK(send_get(addr, uuid));
615 for (int i = 0; i < remote_nodes - 1; i++) {
616 ASSERT_OK(k_sem_take(&status_msg_recvd_sem, K_SECONDS(5)));
617 ASSERT_EQUAL(recvd_msgs_cnt, 0);
618 }
619 }
620
test_tester_simple_group(void)621 static void test_tester_simple_group(void)
622 {
623 int err;
624 uint8_t status;
625
626 remote_nodes = REMOTE_NODES_MULTICAST;
627 bt_mesh_test_cfg_set(NULL, WAIT_TIME);
628 tester_init_common();
629
630 for (int i = 0; i < remote_nodes; i++) {
631 err = bt_mesh_cfg_cli_mod_sub_add(i + 1, DEVICE_ADDR_START + i,
632 DEVICE_ADDR_START + i, GROUP_ADDR, TEST_MOD_ID,
633 &status);
634 if (err || status) {
635 FAIL("Mod sub add failed (err %d, status %u)", err, status);
636 return;
637 }
638 }
639
640 tester_simple_multicast(GROUP_ADDR, NULL);
641 PASS();
642 }
643
test_tester_simple_va(void)644 static void test_tester_simple_va(void)
645 {
646 int err;
647 uint8_t status;
648 uint16_t vaddr;
649
650 remote_nodes = REMOTE_NODES_MULTICAST;
651 bt_mesh_test_cfg_set(NULL, WAIT_TIME);
652
653 ASSERT_OK(bt_mesh_va_add(test_va_uuid, &va_entry));
654 ASSERT_TRUE(va_entry != NULL);
655
656 tester_init_common();
657
658 for (int i = 0; i < remote_nodes; i++) {
659 err = bt_mesh_cfg_cli_mod_sub_va_add(i + 1, DEVICE_ADDR_START + i,
660 DEVICE_ADDR_START + i, test_va_uuid,
661 TEST_MOD_ID, &vaddr, &status);
662 if (err || status) {
663 FAIL("Mod sub VA add failed (err %d, status %u)", err, status);
664 return;
665 }
666 ASSERT_EQUAL(vaddr, va_entry->addr);
667 }
668
669 tester_simple_multicast(va_entry->addr, va_entry->uuid);
670 PASS();
671 }
672
test_tester_table_state_change(void)673 static void test_tester_table_state_change(void)
674 {
675 int err;
676
677 bt_mesh_test_cfg_set(NULL, WAIT_TIME);
678 tester_init_common();
679 tester_workaround();
680
681 /* Bridge Table is empty, will not get any message back. */
682 ASSERT_OK(send_get(DEVICE_ADDR_START, NULL));
683 err = k_sem_take(&status_msg_recvd_sem, K_SECONDS(5));
684 ASSERT_EQUAL(err, -EAGAIN);
685
686 /* DATA and GET messages should reach Device 1, but STATUS message won't be received. */
687 bridge_entry_add(PROV_ADDR, DEVICE_ADDR_START, 0, 1, BT_MESH_BRG_CFG_DIR_ONEWAY);
688
689 ASSERT_OK(send_data(DEVICE_ADDR_START, 0xAA, NULL));
690
691 ASSERT_OK(send_get(DEVICE_ADDR_START, NULL));
692 err = k_sem_take(&status_msg_recvd_sem, K_SECONDS(5));
693 ASSERT_EQUAL(err, -EAGAIN);
694
695 /* Sending DATA message again before adding a new entry as the previous GET message resets
696 * received messages counter on Devices
697 */
698 ASSERT_OK(send_data(DEVICE_ADDR_START, 0xAA, NULL));
699 /* Adding a reverse entry. This should be added to the bridge table as a separate entry as
700 * the addresses and net keys indexs are provided in the opposite order.
701 */
702 bridge_entry_add(DEVICE_ADDR_START, PROV_ADDR, 1, 0, BT_MESH_BRG_CFG_DIR_ONEWAY);
703 bridge_table_verify(0, 1, 0,
704 (struct bridged_addresses_entry[]){
705 {PROV_ADDR, DEVICE_ADDR_START, BT_MESH_BRG_CFG_DIR_ONEWAY},
706 },
707 1);
708 bridge_table_verify(1, 0, 0,
709 (struct bridged_addresses_entry[]){
710 {DEVICE_ADDR_START, PROV_ADDR, BT_MESH_BRG_CFG_DIR_ONEWAY},
711 },
712 1);
713
714 k_sleep(K_SECONDS(1));
715
716 /* Now we should receive STATUS message. */
717 ASSERT_OK(send_get(DEVICE_ADDR_START, NULL));
718 ASSERT_OK(k_sem_take(&status_msg_recvd_sem, K_SECONDS(5)));
719
720 ASSERT_EQUAL(recvd_msgs_cnt, 1);
721 ASSERT_EQUAL(recvd_msgs[0], 0xAA);
722
723 /* Removing the reverse entry and changing direction on the first entry.
724 * tester should still receive STATUS message.
725 */
726 bridge_entry_remove(DEVICE_ADDR_START, PROV_ADDR, 1, 0);
727 bridge_entry_add(PROV_ADDR, DEVICE_ADDR_START, 0, 1, BT_MESH_BRG_CFG_DIR_TWOWAY);
728 bridge_table_verify(0, 1, 0,
729 (struct bridged_addresses_entry[]){
730 {PROV_ADDR, DEVICE_ADDR_START, BT_MESH_BRG_CFG_DIR_TWOWAY},
731 },
732 1);
733 bridge_table_verify(1, 0, 0, NULL, 0);
734
735 ASSERT_OK(send_get(DEVICE_ADDR_START, NULL));
736 ASSERT_OK(k_sem_take(&status_msg_recvd_sem, K_SECONDS(5)));
737 ASSERT_EQUAL(recvd_msgs_cnt, 0);
738
739 PASS();
740 }
741
net_key_remove(uint16_t dst,uint16_t net_idx,uint16_t net_idx_to_remove)742 static void net_key_remove(uint16_t dst, uint16_t net_idx, uint16_t net_idx_to_remove)
743 {
744 uint8_t status;
745 int err;
746
747 err = bt_mesh_cfg_cli_net_key_del(net_idx, dst, net_idx_to_remove, &status);
748 if (err || status) {
749 FAIL("NetKey del failed (err %d, status %u)", err, status);
750 return;
751 }
752 }
753
test_tester_net_key_remove(void)754 static void test_tester_net_key_remove(void)
755 {
756 int err;
757
758 bt_mesh_test_cfg_set(NULL, WAIT_TIME);
759 tester_init_common();
760 setup_basic_bridge();
761 tester_workaround();
762
763 ASSERT_OK(send_data(DEVICE_ADDR_START, 0xAA, NULL));
764 ASSERT_OK(send_get(DEVICE_ADDR_START, NULL));
765 ASSERT_OK(k_sem_take(&status_msg_recvd_sem, K_SECONDS(5)));
766 ASSERT_EQUAL(recvd_msgs_cnt, 1);
767 ASSERT_EQUAL(recvd_msgs[0], 0xAA);
768
769 /* Removing subnet 1 from Subnet Bridge. */
770 net_key_remove(BRIDGE_ADDR, 0, 1);
771
772 ASSERT_OK(send_get(DEVICE_ADDR_START, NULL));
773 err = k_sem_take(&status_msg_recvd_sem, K_SECONDS(5));
774 ASSERT_EQUAL(err, -EAGAIN);
775
776 bridge_table_verify(0, 2, 0,
777 (struct bridged_addresses_entry[]){
778 {PROV_ADDR, DEVICE_ADDR_START + 1, BT_MESH_BRG_CFG_DIR_TWOWAY},
779 },
780 1);
781
782 /* Bridging Table Get message will return Invalid NetKey Index error because Subnet 1 is
783 * removed.
784 */
785 struct bt_mesh_brg_cfg_table_list rsp = {
786 .list = NULL,
787 };
788
789 ASSERT_OK(bt_mesh_brg_cfg_cli_table_get(0, BRIDGE_ADDR, 0, 1, 0, &rsp));
790 ASSERT_EQUAL(rsp.status, 4);
791
792 PASS();
793 }
794
795 #if CONFIG_BT_SETTINGS
test_tester_persistence(void)796 static void test_tester_persistence(void)
797 {
798 bt_mesh_test_cfg_set(NULL, WAIT_TIME);
799
800 bt_mesh_device_setup(&tester_prov, &comp);
801
802 if (bt_mesh_is_provisioned()) {
803 uint8_t status;
804
805 LOG_INF("Already provisioned, skipping provisioning");
806
807 ASSERT_OK(bt_mesh_brg_cfg_cli_get(0, BRIDGE_ADDR, &status));
808 if (status != BT_MESH_BRG_CFG_ENABLED) {
809 FAIL("Subnet bridge set failed (status %u)", status);
810 return;
811 }
812
813 bridge_table_verify(
814 0, 1, 0,
815 (struct bridged_addresses_entry[]){
816 {PROV_ADDR, DEVICE_ADDR_START, BT_MESH_BRG_CFG_DIR_TWOWAY},
817 },
818 1);
819
820 bridge_table_verify(
821 0, 2, 0,
822 (struct bridged_addresses_entry[]){
823 {PROV_ADDR, DEVICE_ADDR_START + 1, BT_MESH_BRG_CFG_DIR_TWOWAY},
824 },
825 1);
826
827 bridge_table_verify(
828 1, 0, 0,
829 (struct bridged_addresses_entry[]){
830 {DEVICE_ADDR_START, PROV_ADDR, BT_MESH_BRG_CFG_DIR_ONEWAY},
831 },
832 1);
833
834 bridge_table_verify(
835 2, 0, 0,
836 (struct bridged_addresses_entry[]){
837 {DEVICE_ADDR_START + 1, PROV_ADDR, BT_MESH_BRG_CFG_DIR_ONEWAY},
838 },
839 1);
840 } else {
841 tester_setup();
842
843 LOG_INF("Waiting for a bridge to provision...");
844 ASSERT_OK(k_sem_take(&prov_sem, K_SECONDS(40)));
845
846 LOG_INF("Configuring bridge...");
847 tester_bridge_configure();
848
849 /* Adding devices to bridge table */
850 for (int i = 0; i < remote_nodes; i++) {
851 bridge_entry_add(PROV_ADDR, DEVICE_ADDR_START + i, 0, i + 1,
852 BT_MESH_BRG_CFG_DIR_TWOWAY);
853 bridge_entry_add(DEVICE_ADDR_START + i, PROV_ADDR, i + 1, 0,
854 BT_MESH_BRG_CFG_DIR_ONEWAY);
855 }
856
857 k_sleep(K_SECONDS(CONFIG_BT_MESH_STORE_TIMEOUT));
858 }
859
860 PASS();
861 }
862 #endif
863
864 /* When testing IV Index update, after the IV Index incremented devices starts sending messages
865 * with SEQ number 0 that is lower than the SEQ number of the last message received before IV Index.
866 * The Network Message Cache is not cleared and thus will drop these messages.
867 *
868 * The workaround is to send GET message to each device to bump SEQ number and overflow the cache so
869 * that after IV Index update there is no message with SEQ 0 in the cache.
870 */
msg_cache_workaround(void)871 static void msg_cache_workaround(void)
872 {
873 LOG_INF("Applying Msg Cache workaround...");
874
875 for (int i = 0; i < remote_nodes; i++) {
876 for (int j = 0; j < CONFIG_BT_MESH_MSG_CACHE_SIZE; j++) {
877 ASSERT_OK(send_get(DEVICE_ADDR_START + i, NULL));
878 /* k_sem_take is needed to not overflow network buffer pool. The result
879 * of the semaphor is not important as we just need to bump sequence number
880 * enough to bypass message cache.
881 */
882 (void)k_sem_take(&status_msg_recvd_sem, K_SECONDS(1));
883 }
884 }
885
886 LOG_INF("Msg Cache workaround applied");
887 k_sleep(K_SECONDS(10));
888 }
889
beacon_set(uint16_t dst,uint8_t val)890 static int beacon_set(uint16_t dst, uint8_t val)
891 {
892 uint8_t status;
893 int err;
894
895 err = bt_mesh_cfg_cli_beacon_set(0, dst, val, &status);
896 if (err || status != val) {
897 FAIL("Beacon set failed (err %d, status %u)", err, status);
898 return -EINVAL;
899 }
900
901 return 0;
902 }
903
904 /* This function guarantees that IV Update procedure state is propagated to all nodes by togging off
905 * Beacon features on Subnet Bridge and Tester nodes. When Beacon feature is disabled on Subnet
906 * Bridge, Tester will be able to send beacon with new IVI flag and vice versa.
907 *
908 * Beacon feature is disabled on other nodes at the setup.
909 */
propagate_ivi_update_state(void)910 static void propagate_ivi_update_state(void)
911 {
912 /* Disable Beacon feature on subnet bridge to let tester send beacon first. */
913 ASSERT_OK(beacon_set(BRIDGE_ADDR, BT_MESH_BEACON_DISABLED));
914
915 LOG_INF("Waiting for IV Update state to propagate to Subnet Bridge");
916 k_sleep(K_SECONDS(BEACON_INTERVAL * 2));
917
918 /* Disable Beacon feature on tester and enable it on subnet bridge to let it send beacon. */
919 ASSERT_OK(beacon_set(PROV_ADDR, BT_MESH_BEACON_DISABLED));
920 ASSERT_OK(beacon_set(BRIDGE_ADDR, BT_MESH_BEACON_ENABLED));
921
922 LOG_INF("Waiting for IV Update state to propagate to other nodes");
923 k_sleep(K_SECONDS(BEACON_INTERVAL * 2));
924
925 /* Restore Beacon feature on tester. */
926 ASSERT_OK(beacon_set(PROV_ADDR, BT_MESH_BEACON_ENABLED));
927 }
928
test_tester_ivu(void)929 static void test_tester_ivu(void)
930 {
931 bt_mesh_test_cfg_set(NULL, WAIT_TIME_IVU_TEST);
932 bt_mesh_iv_update_test(true);
933 tester_init_common();
934 setup_basic_bridge();
935 tester_workaround();
936
937 ASSERT_TRUE(!atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS));
938 ASSERT_TRUE(bt_mesh.iv_index == test_ividx);
939
940 LOG_INF("IV Update procedure state: Normal");
941
942 k_sleep(K_SECONDS(BEACON_INTERVAL));
943
944 send_and_receive();
945
946 for (int i = 0; i < 2; i++) {
947 uint32_t iv_index = bt_mesh.iv_index;
948
949 LOG_INF("Round: %d", i);
950
951 msg_cache_workaround();
952
953 LOG_INF("Starting IV Update procedure, IVI %d -> %d", bt_mesh.iv_index,
954 bt_mesh.iv_index + 1);
955
956 iv_index = bt_mesh.iv_index;
957
958 ASSERT_TRUE(bt_mesh_iv_update());
959 ASSERT_TRUE(atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS));
960 ASSERT_TRUE(bt_mesh.iv_index == iv_index + 1);
961
962 send_and_receive();
963
964 propagate_ivi_update_state();
965
966 LOG_INF("Finishing IV Update procedure");
967
968 ASSERT_TRUE(!bt_mesh_iv_update());
969 ASSERT_TRUE(!atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS));
970 ASSERT_TRUE(bt_mesh.iv_index == iv_index + 1);
971
972 propagate_ivi_update_state();
973
974 /* Sleep here to avoid packet collision. */
975 k_sleep(K_MSEC(300));
976
977 send_and_receive();
978 }
979
980 PASS();
981 }
982
start_krp(uint16_t addr,const uint8_t * key)983 static void start_krp(uint16_t addr, const uint8_t *key)
984 {
985 uint8_t status;
986 uint16_t net_idx = (addr == PROV_ADDR) ? 0 : (addr - DEVICE_ADDR_START + 1);
987
988 ASSERT_OK(bt_mesh_cfg_cli_net_key_update(0, BRIDGE_ADDR, net_idx, key, &status));
989 if (status) {
990 FAIL("Could not update net key (status %u)", status);
991 return;
992 }
993
994 ASSERT_OK(bt_mesh_cfg_cli_net_key_update(0, addr, net_idx, key, &status));
995 if (status) {
996 FAIL("Could not update net key (status %u)", status);
997 return;
998 }
999 }
1000
set_krp_phase(uint16_t addr,uint8_t transition)1001 static void set_krp_phase(uint16_t addr, uint8_t transition)
1002 {
1003 uint8_t status;
1004 uint8_t phase;
1005 uint16_t net_idx = (addr == PROV_ADDR) ? 0 : (addr - DEVICE_ADDR_START + 1);
1006
1007 ASSERT_OK(bt_mesh_cfg_cli_krp_set(0, BRIDGE_ADDR, net_idx, transition, &status, &phase));
1008 if (status || (phase != (transition == 0x02 ? 0x02 : 0x00))) {
1009 FAIL("Could not update KRP (status %u, transition %u, phase %u)", status,
1010 transition, phase);
1011 return;
1012 }
1013
1014 ASSERT_OK(bt_mesh_cfg_cli_krp_set(0, addr, net_idx, transition, &status, &phase));
1015 if (status || (phase != (transition == 0x02 ? 0x02 : 0x00))) {
1016 FAIL("Could not update KRP (status %u, transition %u, phase %u)", status,
1017 transition, phase);
1018 return;
1019 }
1020 }
1021
test_tester_key_refresh(void)1022 static void test_tester_key_refresh(void)
1023 {
1024 const uint8_t new_net_keys[][16] = {
1025 {0x12, 0x34, 0x56},
1026 {0x78, 0x9a, 0xbc},
1027 {0xde, 0xf0, 0x12},
1028 {0x34, 0x56, 0x78}
1029 };
1030
1031 remote_nodes = 1;
1032 bt_mesh_test_cfg_set(NULL, WAIT_TIME);
1033
1034 tester_init_common();
1035 setup_basic_bridge();
1036 tester_workaround();
1037
1038 LOG_INF("Step 1: Run KRP for tester net and check messaging");
1039 start_krp(PROV_ADDR, new_net_keys[0]);
1040 send_and_receive();
1041 set_krp_phase(PROV_ADDR, 0x02);
1042 send_and_receive();
1043 set_krp_phase(PROV_ADDR, 0x03);
1044 send_and_receive();
1045
1046 LOG_INF("Step 2: Run KRP for device net and check messaging");
1047 start_krp(DEVICE_ADDR_START, new_net_keys[1]);
1048 send_and_receive();
1049 set_krp_phase(DEVICE_ADDR_START, 0x02);
1050 send_and_receive();
1051 set_krp_phase(DEVICE_ADDR_START, 0x03);
1052 send_and_receive();
1053
1054 LOG_INF("Step 3: Run KRP in parallell for both device and tester");
1055 start_krp(PROV_ADDR, new_net_keys[2]);
1056 send_and_receive();
1057 start_krp(DEVICE_ADDR_START, new_net_keys[3]);
1058 send_and_receive();
1059 set_krp_phase(PROV_ADDR, 0x02);
1060 send_and_receive();
1061 set_krp_phase(DEVICE_ADDR_START, 0x02);
1062 send_and_receive();
1063 set_krp_phase(PROV_ADDR, 0x03);
1064 send_and_receive();
1065 set_krp_phase(DEVICE_ADDR_START, 0x03);
1066 send_and_receive();
1067
1068 PASS();
1069 }
1070
bridge_setup(void)1071 static void bridge_setup(void)
1072 {
1073 bt_mesh_device_setup(&bridge_prov, &comp);
1074
1075 if (IS_ENABLED(CONFIG_BT_SETTINGS) && bt_mesh_is_provisioned()) {
1076 LOG_INF("Already provisioned, skipping provisioning");
1077 } else {
1078 ASSERT_OK(bt_mesh_prov_enable(BT_MESH_PROV_ADV));
1079 LOG_INF("Waiting for being provisioned...");
1080 ASSERT_OK(k_sem_take(&prov_sem, K_SECONDS(40)));
1081 LOG_INF("Bridge is provisioned");
1082 }
1083 }
1084
test_bridge_simple(void)1085 static void test_bridge_simple(void)
1086 {
1087 bt_mesh_test_cfg_set(NULL, WAIT_TIME);
1088
1089 bridge_setup();
1090
1091 PASS();
1092 }
1093
test_bridge_simple_iv_test_mode(void)1094 static void test_bridge_simple_iv_test_mode(void)
1095 {
1096 bt_mesh_test_cfg_set(NULL, WAIT_TIME_IVU_TEST);
1097 bt_mesh_iv_update_test(true);
1098
1099 bridge_setup();
1100
1101 PASS();
1102 }
1103
device_setup(void)1104 static void device_setup(void)
1105 {
1106 bt_mesh_device_setup(&device_prov, &comp);
1107
1108 ASSERT_OK(bt_mesh_prov_enable(BT_MESH_PROV_ADV));
1109
1110 LOG_INF("Waiting for being provisioned...");
1111 ASSERT_OK(k_sem_take(&prov_sem, K_SECONDS(40)));
1112 LOG_INF("Node is provisioned");
1113
1114 bt_mesh_test_data_cb_setup(device_data_cb);
1115 }
1116
test_device_simple(void)1117 static void test_device_simple(void)
1118 {
1119 bt_mesh_test_cfg_set(NULL, WAIT_TIME);
1120
1121 device_setup();
1122
1123 PASS();
1124 }
1125
test_device_simple_iv_test_mode(void)1126 static void test_device_simple_iv_test_mode(void)
1127 {
1128 bt_mesh_test_cfg_set(NULL, WAIT_TIME_IVU_TEST);
1129 bt_mesh_iv_update_test(true);
1130
1131 device_setup();
1132
1133 PASS();
1134 }
1135
1136 #define TEST_CASE(role, name, description) \
1137 { \
1138 .test_id = "brg_" #role "_" #name, \
1139 .test_post_init_f = test_##role##_init, \
1140 .test_descr = description, \
1141 .test_tick_f = bt_mesh_test_timeout, \
1142 .test_main_f = test_##role##_##name, \
1143 }
1144
1145 static const struct bst_test_instance test_brg[] = {
1146 TEST_CASE(tester, simple,
1147 "Tester node: provisions network, exchanges messages with "
1148 "mesh nodes"),
1149 TEST_CASE(tester, simple_group,
1150 "Tester node: provisions network, configures group subscription and exchanges "
1151 "messages with mesh nodes"),
1152 TEST_CASE(tester, simple_va,
1153 "Tester node: provisions network, configures virtual address subscription "
1154 "and exchanges messages with mesh nodes"),
1155 TEST_CASE(tester, table_state_change,
1156 "Tester node: tests changing bridging table "
1157 "state"),
1158 TEST_CASE(tester, net_key_remove,
1159 "Tester node: tests removing net key from Subnet "
1160 "Bridge"),
1161 #if CONFIG_BT_SETTINGS
1162 TEST_CASE(tester, persistence, "Tester node: test persistence of subnet bridge states"),
1163 #endif
1164 TEST_CASE(tester, ivu, "Tester node: tests subnet bridge with IV Update procedure"),
1165 TEST_CASE(tester, key_refresh,
1166 "Tester node: tests bridge behavior during key refresh procedures"),
1167 TEST_CASE(bridge, simple, "Subnet Bridge node"),
1168 TEST_CASE(device, simple, "A mesh node"),
1169
1170 TEST_CASE(bridge, simple_iv_test_mode, "Subnet Bridge node with IV test mode enabled"),
1171 TEST_CASE(device, simple_iv_test_mode, "A mesh node with IV test mode enabled"),
1172
1173 BSTEST_END_MARKER};
1174
test_brg_install(struct bst_test_list * tests)1175 struct bst_test_list *test_brg_install(struct bst_test_list *tests)
1176 {
1177 tests = bst_add_tests(tests, test_brg);
1178 return tests;
1179 }
1180