1 /*
2 * Copyright (c) 2022 Nordic Semiconductor
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include "mesh_test.h"
7 #include "dfu_blob_common.h"
8 #include "friendship_common.h"
9 #include "mesh/blob.h"
10 #include "argparse.h"
11 #include "mesh/adv.h"
12
13 #define LOG_MODULE_NAME test_blob
14
15 #include <zephyr/logging/log.h>
16 LOG_MODULE_REGISTER(LOG_MODULE_NAME, LOG_LEVEL_INF);
17
18 #define BLOB_GROUP_ADDR 0xc000
19 #define BLOB_CLI_ADDR 0x0001
20 #define SYNC_CHAN 0
21 #define CLI_DEV 0
22 #define SRV1_DEV 1
23 #define IMPOSTER_MODEL_ID 0xe000
24
25 static bool is_pull_mode;
26 static enum {
27 BLOCK_GET_FAIL = 0,
28 XFER_GET_FAIL = 1
29 } msg_fail_type;
30 static enum bt_mesh_blob_xfer_phase expected_stop_phase;
31
test_args_parse(int argc,char * argv[])32 static void test_args_parse(int argc, char *argv[])
33 {
34 bs_args_struct_t args_struct[] = {
35 {
36 .dest = &is_pull_mode,
37 .type = 'b',
38 .name = "{0, 1}",
39 .option = "use-pull-mode",
40 .descript = "Set transfer type to pull mode"
41 },
42 {
43 .dest = &msg_fail_type,
44 .type = 'i',
45 .name = "{0, 1}",
46 .option = "msg-fail-type",
47 .descript = "Message type to fail on"
48 },
49 {
50 .dest = &expected_stop_phase,
51 .type = 'i',
52 .name = "{inactive, start, wait-block, wait-chunk, complete, suspended}",
53 .option = "expected-phase",
54 .descript = "Expected DFU Server phase value restored from flash"
55 }
56 };
57
58 bs_args_parse_all_cmd_line(argc, argv, args_struct);
59 }
60
blob_io_open(const struct bt_mesh_blob_io * io,const struct bt_mesh_blob_xfer * xfer,enum bt_mesh_blob_io_mode mode)61 static int blob_io_open(const struct bt_mesh_blob_io *io,
62 const struct bt_mesh_blob_xfer *xfer,
63 enum bt_mesh_blob_io_mode mode)
64 {
65 return 0;
66 }
67
68 static struct k_sem first_block_wr_sem;
69 static uint16_t partial_block;
70 ATOMIC_DEFINE(block_bitfield, 8);
71
72 static struct k_sem blob_srv_end_sem;
73
blob_chunk_wr(const struct bt_mesh_blob_io * io,const struct bt_mesh_blob_xfer * xfer,const struct bt_mesh_blob_block * block,const struct bt_mesh_blob_chunk * chunk)74 static int blob_chunk_wr(const struct bt_mesh_blob_io *io,
75 const struct bt_mesh_blob_xfer *xfer,
76 const struct bt_mesh_blob_block *block,
77 const struct bt_mesh_blob_chunk *chunk)
78 {
79 partial_block += chunk->size;
80 ASSERT_TRUE_MSG(partial_block <= block->size, "Received block is too large\n");
81
82
83 if (partial_block == block->size) {
84 partial_block = 0;
85 ASSERT_FALSE_MSG(atomic_test_and_set_bit(block_bitfield, block->number),
86 "Received duplicate block\n");
87 }
88
89 if (atomic_test_bit(block_bitfield, 0)) {
90 k_sem_give(&first_block_wr_sem);
91 }
92
93 if (expected_stop_phase == BT_MESH_BLOB_XFER_PHASE_WAITING_FOR_CHUNK) {
94 bt_mesh_scan_disable();
95 k_sem_give(&blob_srv_end_sem);
96 }
97 return 0;
98 }
99
blob_chunk_rd(const struct bt_mesh_blob_io * io,const struct bt_mesh_blob_xfer * xfer,const struct bt_mesh_blob_block * block,const struct bt_mesh_blob_chunk * chunk)100 static int blob_chunk_rd(const struct bt_mesh_blob_io *io,
101 const struct bt_mesh_blob_xfer *xfer,
102 const struct bt_mesh_blob_block *block,
103 const struct bt_mesh_blob_chunk *chunk)
104 {
105 memset(chunk->data, 0, chunk->size);
106
107 return 0;
108 }
109
blob_block_end(const struct bt_mesh_blob_io * io,const struct bt_mesh_blob_xfer * xfer,const struct bt_mesh_blob_block * block)110 static void blob_block_end(const struct bt_mesh_blob_io *io,
111 const struct bt_mesh_blob_xfer *xfer,
112 const struct bt_mesh_blob_block *block)
113 {
114 if (expected_stop_phase == BT_MESH_BLOB_XFER_PHASE_WAITING_FOR_BLOCK ||
115 expected_stop_phase == BT_MESH_BLOB_XFER_PHASE_SUSPENDED) {
116 bt_mesh_scan_disable();
117 k_sem_give(&blob_srv_end_sem);
118 }
119 }
120
121 static const struct bt_mesh_blob_io blob_io = {
122 .open = blob_io_open,
123 .rd = blob_chunk_rd,
124 .wr = blob_chunk_wr,
125 .block_end = blob_block_end,
126 };
127
128 static uint8_t dev_key[16] = { 0xdd };
129 static uint8_t app_key[16] = { 0xaa };
130 static uint8_t net_key[16] = { 0xcc };
131 static struct bt_mesh_prov prov;
132
133 static struct {
134 struct bt_mesh_blob_cli_inputs inputs;
135 struct bt_mesh_blob_target targets[5];
136 struct bt_mesh_blob_target_pull pull[5];
137 uint8_t target_count;
138 struct bt_mesh_blob_xfer xfer;
139 } blob_cli_xfer;
140
141 static struct k_sem blob_caps_sem;
142
blob_cli_caps(struct bt_mesh_blob_cli * b,const struct bt_mesh_blob_cli_caps * caps)143 static void blob_cli_caps(struct bt_mesh_blob_cli *b, const struct bt_mesh_blob_cli_caps *caps)
144 {
145 k_sem_give(&blob_caps_sem);
146 if (caps) {
147 ASSERT_EQUAL(caps->mtu_size, BT_MESH_RX_SDU_MAX - BT_MESH_MIC_SHORT);
148 ASSERT_EQUAL(caps->modes, BT_MESH_BLOB_XFER_MODE_ALL);
149 ASSERT_EQUAL(caps->max_size, CONFIG_BT_MESH_BLOB_SIZE_MAX);
150 ASSERT_EQUAL(caps->min_block_size_log, BLOB_BLOCK_SIZE_LOG_MIN);
151 ASSERT_EQUAL(caps->max_block_size_log, BLOB_BLOCK_SIZE_LOG_MAX);
152 ASSERT_EQUAL(caps->max_chunk_size, BLOB_CHUNK_SIZE_MAX(BT_MESH_RX_SDU_MAX));
153 ASSERT_EQUAL(caps->max_chunks, CONFIG_BT_MESH_BLOB_CHUNK_COUNT_MAX);
154 }
155 }
156
157 static struct k_sem lost_target_sem;
158
blob_cli_lost_target(struct bt_mesh_blob_cli * b,struct bt_mesh_blob_target * blobt,enum bt_mesh_blob_status reason)159 static void blob_cli_lost_target(struct bt_mesh_blob_cli *b, struct bt_mesh_blob_target *blobt,
160 enum bt_mesh_blob_status reason)
161 {
162 ASSERT_FALSE(reason == BT_MESH_BLOB_SUCCESS);
163 ASSERT_TRUE(lost_target_find_and_remove(blobt->addr));
164
165 if (!lost_targets_rem()) {
166 k_sem_give(&lost_target_sem);
167 }
168 }
169
170 static struct k_sem blob_cli_suspend_sem;
171
blob_cli_suspended(struct bt_mesh_blob_cli * b)172 static void blob_cli_suspended(struct bt_mesh_blob_cli *b)
173 {
174 k_sem_give(&blob_cli_suspend_sem);
175 }
176
177 static struct k_sem blob_cli_end_sem;
178 static bool cli_end_success;
179
blob_cli_end(struct bt_mesh_blob_cli * b,const struct bt_mesh_blob_xfer * xfer,bool success)180 static void blob_cli_end(struct bt_mesh_blob_cli *b, const struct bt_mesh_blob_xfer *xfer,
181 bool success)
182 {
183 cli_end_success = success;
184 k_sem_give(&blob_cli_end_sem);
185 }
186
187 static struct k_sem blob_srv_suspend_sem;
188
blob_srv_suspended(struct bt_mesh_blob_srv * b)189 static void blob_srv_suspended(struct bt_mesh_blob_srv *b)
190 {
191 k_sem_give(&blob_srv_suspend_sem);
192 }
193
blob_srv_end(struct bt_mesh_blob_srv * b,uint64_t id,bool success)194 static void blob_srv_end(struct bt_mesh_blob_srv *b, uint64_t id, bool success)
195 {
196 k_sem_give(&blob_srv_end_sem);
197 }
198
blob_srv_recover(struct bt_mesh_blob_srv * b,struct bt_mesh_blob_xfer * xfer,const struct bt_mesh_blob_io ** io)199 static int blob_srv_recover(struct bt_mesh_blob_srv *b, struct bt_mesh_blob_xfer *xfer,
200 const struct bt_mesh_blob_io **io)
201 {
202 *io = &blob_io;
203 return 0;
204 }
205
blob_srv_start(struct bt_mesh_blob_srv * srv,struct bt_mesh_msg_ctx * ctx,struct bt_mesh_blob_xfer * xfer)206 static int blob_srv_start(struct bt_mesh_blob_srv *srv, struct bt_mesh_msg_ctx *ctx,
207 struct bt_mesh_blob_xfer *xfer)
208 {
209 return 0;
210 }
211
blob_srv_resume(struct bt_mesh_blob_srv * srv)212 static void blob_srv_resume(struct bt_mesh_blob_srv *srv)
213 {
214 }
215
216 static const struct bt_mesh_blob_srv_cb blob_srv_cb = {
217 .suspended = blob_srv_suspended,
218 .end = blob_srv_end,
219 .recover = blob_srv_recover,
220 .start = blob_srv_start,
221 .resume = blob_srv_resume,
222 };
223 static const struct bt_mesh_blob_cli_cb blob_cli_handlers = {
224 .caps = blob_cli_caps,
225 .lost_target = blob_cli_lost_target,
226 .suspended = blob_cli_suspended,
227 .end = blob_cli_end,
228 };
229 static struct bt_mesh_blob_srv blob_srv = { .cb = &blob_srv_cb };
230 static struct bt_mesh_blob_cli blob_cli = { .cb = &blob_cli_handlers };
231 static struct bt_mesh_cfg_cli cfg_cli;
232 static struct bt_mesh_sar_cfg_cli sar_cfg_cli;
233
234 static const struct bt_mesh_comp srv_comp = {
235 .elem =
236 (struct bt_mesh_elem[]){
237 BT_MESH_ELEM(1,
238 MODEL_LIST(BT_MESH_MODEL_CFG_SRV,
239 BT_MESH_MODEL_CFG_CLI(&cfg_cli),
240 BT_MESH_MODEL_SAR_CFG_SRV,
241 BT_MESH_MODEL_SAR_CFG_CLI(&sar_cfg_cli),
242 BT_MESH_MODEL_BLOB_SRV(&blob_srv)),
243 BT_MESH_MODEL_NONE),
244 },
245 .elem_count = 1,
246 };
247
248 static const struct bt_mesh_comp cli_comp = {
249 .elem =
250 (struct bt_mesh_elem[]){
251 BT_MESH_ELEM(1,
252 MODEL_LIST(BT_MESH_MODEL_CFG_SRV,
253 BT_MESH_MODEL_CFG_CLI(&cfg_cli),
254 BT_MESH_MODEL_SAR_CFG_SRV,
255 BT_MESH_MODEL_SAR_CFG_CLI(&sar_cfg_cli),
256 BT_MESH_MODEL_BLOB_CLI(&blob_cli)),
257 BT_MESH_MODEL_NONE),
258 },
259 .elem_count = 1,
260 };
261
262 static struct k_sem info_get_sem;
263
mock_handle_info_get(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)264 static int mock_handle_info_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
265 struct net_buf_simple *buf)
266 {
267 k_sem_give(&info_get_sem);
268 return 0;
269 }
270
271 static const struct bt_mesh_model_op model_op1[] = {
272 { BT_MESH_BLOB_OP_INFO_GET, 0, mock_handle_info_get },
273 BT_MESH_MODEL_OP_END
274 };
275
276 static const struct bt_mesh_comp none_rsp_srv_comp = {
277 .elem =
278 (struct bt_mesh_elem[]){
279 BT_MESH_ELEM(1,
280 MODEL_LIST(BT_MESH_MODEL_CFG_SRV,
281 BT_MESH_MODEL_CFG_CLI(&cfg_cli),
282 BT_MESH_MODEL_SAR_CFG_SRV,
283 BT_MESH_MODEL_SAR_CFG_CLI(&sar_cfg_cli),
284 BT_MESH_MODEL_CB(BT_MESH_MODEL_ID_BLOB_SRV,
285 model_op1, NULL, NULL, NULL)),
286 BT_MESH_MODEL_NONE),
287 },
288 .elem_count = 1,
289 };
290
provision(uint16_t addr)291 static void provision(uint16_t addr)
292 {
293 int err;
294
295 err = bt_mesh_provision(net_key, 0, 0, 0, addr, dev_key);
296 if (err) {
297 FAIL("Provisioning failed (err %d)", err);
298 return;
299 }
300 }
301
common_configure(uint16_t addr)302 static void common_configure(uint16_t addr)
303 {
304 uint8_t status;
305 int err;
306
307 err = bt_mesh_cfg_cli_app_key_add(0, addr, 0, 0, app_key, &status);
308 if (err || status) {
309 FAIL("AppKey add failed (err %d, status %u)", err, status);
310 return;
311 }
312 }
313
blob_srv_prov_and_conf(uint16_t addr)314 static void blob_srv_prov_and_conf(uint16_t addr)
315 {
316 uint8_t status;
317 int err;
318
319 provision(addr);
320 common_configure(addr);
321
322 err = bt_mesh_cfg_cli_mod_app_bind(0, addr, addr, 0, BT_MESH_MODEL_ID_BLOB_SRV, &status);
323 if (err || status) {
324 FAIL("Model %#4x bind failed (err %d, status %u)", BT_MESH_MODEL_ID_BLOB_SRV, err,
325 status);
326 return;
327 }
328
329 err = bt_mesh_cfg_cli_mod_sub_add(0, addr, addr, BLOB_GROUP_ADDR, BT_MESH_MODEL_ID_BLOB_SRV,
330 &status);
331 if (err || status) {
332 FAIL("Model %#4x sub add failed (err %d, status %u)", BT_MESH_MODEL_ID_BLOB_SRV,
333 err, status);
334 return;
335 }
336
337 common_sar_conf(addr);
338 }
339
blob_cli_prov_and_conf(uint16_t addr)340 static void blob_cli_prov_and_conf(uint16_t addr)
341 {
342 uint8_t status;
343 int err;
344
345 provision(addr);
346 common_configure(addr);
347
348 err = bt_mesh_cfg_cli_mod_app_bind(0, addr, addr, 0, BT_MESH_MODEL_ID_BLOB_CLI, &status);
349 if (err || status) {
350 FAIL("Model %#4x bind failed (err %d, status %u)", BT_MESH_MODEL_ID_BLOB_CLI, err,
351 status);
352 return;
353 }
354
355 common_sar_conf(addr);
356 }
357
blob_cli_inputs_prepare(uint16_t group)358 static void blob_cli_inputs_prepare(uint16_t group)
359 {
360 blob_cli_xfer.inputs.ttl = BT_MESH_TTL_DEFAULT;
361 blob_cli_xfer.inputs.group = group;
362 blob_cli_xfer.inputs.app_idx = 0;
363 sys_slist_init(&blob_cli_xfer.inputs.targets);
364
365 for (int i = 0; i < blob_cli_xfer.target_count; ++i) {
366 /* Reset target context. */
367 uint16_t addr = blob_cli_xfer.targets[i].addr;
368
369 memset(&blob_cli_xfer.targets[i], 0, sizeof(struct bt_mesh_blob_target));
370 blob_cli_xfer.targets[i].addr = addr;
371 blob_cli_xfer.targets[i].pull = &blob_cli_xfer.pull[i];
372
373 sys_slist_append(&blob_cli_xfer.inputs.targets, &blob_cli_xfer.targets[i].n);
374 }
375 }
376
target_srv_add(uint16_t addr,bool expect_lost)377 static struct bt_mesh_blob_target *target_srv_add(uint16_t addr, bool expect_lost)
378 {
379 if (expect_lost) {
380 lost_target_add(addr);
381 }
382
383 ASSERT_TRUE(blob_cli_xfer.target_count < ARRAY_SIZE(blob_cli_xfer.targets));
384 struct bt_mesh_blob_target *t = &blob_cli_xfer.targets[blob_cli_xfer.target_count];
385
386 t->addr = addr;
387 blob_cli_xfer.target_count++;
388 return t;
389 }
390
cli_caps_common_procedure(bool lost_targets)391 static void cli_caps_common_procedure(bool lost_targets)
392 {
393 int err;
394
395 bt_mesh_test_cfg_set(NULL, 60);
396 bt_mesh_device_setup(&prov, &cli_comp);
397 blob_cli_prov_and_conf(BLOB_CLI_ADDR);
398
399 blob_cli_inputs_prepare(BLOB_GROUP_ADDR);
400 k_sem_init(&blob_caps_sem, 0, 1);
401 k_sem_init(&lost_target_sem, 0, 1);
402
403 err = bt_mesh_blob_cli_caps_get(&blob_cli, &blob_cli_xfer.inputs);
404 if (err) {
405 FAIL("Boundary check start failed (err: %d)", err);
406 }
407
408 if (lost_targets) {
409 if (k_sem_take(&lost_target_sem, K_SECONDS(60))) {
410 FAIL("Lost targets CB did not trigger for all expected lost targets");
411 }
412 }
413
414 if (k_sem_take(&blob_caps_sem, K_SECONDS(60))) {
415 FAIL("Caps CB did not trigger at the end of caps procedure");
416 }
417 }
418
test_cli_caps_all_rsp(void)419 static void test_cli_caps_all_rsp(void)
420 {
421 struct bt_mesh_blob_target *srv1 = target_srv_add(BLOB_CLI_ADDR + 1, false);
422 struct bt_mesh_blob_target *srv2 = target_srv_add(BLOB_CLI_ADDR + 2, false);
423
424 cli_caps_common_procedure(false);
425
426 ASSERT_TRUE(srv1->acked);
427 ASSERT_FALSE(srv1->timedout);
428 ASSERT_TRUE(srv2->acked);
429 ASSERT_FALSE(srv2->timedout);
430
431 PASS();
432 }
433
test_cli_caps_partial_rsp(void)434 static void test_cli_caps_partial_rsp(void)
435 {
436 struct bt_mesh_blob_target *srv1 = target_srv_add(BLOB_CLI_ADDR + 1, false);
437 struct bt_mesh_blob_target *srv2 = target_srv_add(BLOB_CLI_ADDR + 2, true);
438
439 cli_caps_common_procedure(true);
440
441 ASSERT_TRUE(srv1->acked);
442 ASSERT_FALSE(srv1->timedout);
443 ASSERT_FALSE(srv2->acked);
444 ASSERT_TRUE(srv2->timedout);
445
446 PASS();
447 }
448
test_cli_caps_no_rsp(void)449 static void test_cli_caps_no_rsp(void)
450 {
451 struct bt_mesh_blob_target *srv1 = target_srv_add(BLOB_CLI_ADDR + 1, true);
452 struct bt_mesh_blob_target *srv2 = target_srv_add(BLOB_CLI_ADDR + 2, true);
453
454 cli_caps_common_procedure(true);
455
456 ASSERT_FALSE(srv1->acked);
457 ASSERT_TRUE(srv1->timedout);
458 ASSERT_FALSE(srv2->acked);
459 ASSERT_TRUE(srv2->timedout);
460
461 PASS();
462 }
463
test_cli_caps_cancelled(void)464 static void test_cli_caps_cancelled(void)
465 {
466 int err;
467
468 bt_mesh_test_cfg_set(NULL, 300);
469 bt_mesh_device_setup(&prov, &cli_comp);
470 blob_cli_prov_and_conf(BLOB_CLI_ADDR);
471
472 struct bt_mesh_blob_target *srv1 = target_srv_add(BLOB_CLI_ADDR + 1, false);
473 struct bt_mesh_blob_target *srv2 = target_srv_add(BLOB_CLI_ADDR + 2, true);
474
475 blob_cli_inputs_prepare(BLOB_GROUP_ADDR);
476
477 k_sem_init(&blob_caps_sem, 0, 1);
478 k_sem_init(&lost_target_sem, 0, 1);
479
480 /* Start first caps procedure */
481 err = bt_mesh_blob_cli_caps_get(&blob_cli, &blob_cli_xfer.inputs);
482 if (err) {
483 FAIL("Boundary check start failed (err: %d)", err);
484 }
485
486 /* Let first caps procedure run for a little while */
487 k_sleep(K_SECONDS(15));
488
489 /* Cancel first caps procedure */
490 bt_mesh_blob_cli_cancel(&blob_cli);
491 ASSERT_EQUAL(blob_cli.state, BT_MESH_BLOB_CLI_STATE_NONE);
492
493 /* Wait and assure that caps procedure is canceled */
494 if (!k_sem_take(&blob_caps_sem, K_SECONDS(60))) {
495 FAIL("Caps CB triggered unexpectedly");
496 }
497
498 /* Expect that the responsive srv responded, while the */
499 /* unresponsive srv has not yet timed out due to cancel call */
500 ASSERT_TRUE(srv1->acked);
501 ASSERT_FALSE(srv1->timedout);
502 ASSERT_FALSE(srv2->acked);
503 ASSERT_FALSE(srv2->timedout);
504
505 /* Start second caps procedure and verify that it completes as expected*/
506 blob_cli_inputs_prepare(BLOB_GROUP_ADDR);
507 err = bt_mesh_blob_cli_caps_get(&blob_cli, &blob_cli_xfer.inputs);
508 if (err) {
509 FAIL("Boundary check start failed (err: %d)", err);
510 }
511
512 if (k_sem_take(&blob_caps_sem, K_SECONDS(60))) {
513 FAIL("Caps CB did not trigger at the end of second caps procedure");
514 }
515
516 if (k_sem_take(&lost_target_sem, K_NO_WAIT)) {
517 FAIL("Lost targets CB did not trigger for all expeted lost targets");
518 }
519
520 ASSERT_TRUE(srv1->acked);
521 ASSERT_FALSE(srv1->timedout);
522 ASSERT_FALSE(srv2->acked);
523 ASSERT_TRUE(srv2->timedout);
524
525 PASS();
526 }
527
test_srv_caps_standard(void)528 static void test_srv_caps_standard(void)
529 {
530 bt_mesh_test_cfg_set(NULL, 140);
531 bt_mesh_device_setup(&prov, &srv_comp);
532 blob_srv_prov_and_conf(bt_mesh_test_own_addr_get(BLOB_CLI_ADDR));
533
534 PASS();
535 }
536
test_srv_caps_no_rsp(void)537 static void test_srv_caps_no_rsp(void)
538 {
539 bt_mesh_test_cfg_set(NULL, 60);
540 bt_mesh_device_setup(&prov, &none_rsp_srv_comp);
541 blob_srv_prov_and_conf(bt_mesh_test_own_addr_get(BLOB_CLI_ADDR));
542
543 k_sem_init(&info_get_sem, 0, 1);
544
545 /* Checks that the client performs correct amount of retransmit attempts */
546 for (size_t j = 0; j < CONFIG_BT_MESH_BLOB_CLI_BLOCK_RETRIES; j++) {
547 int err = k_sem_take(&info_get_sem, K_SECONDS(15));
548
549 if (err) {
550 FAIL("Failed to receive expected number of info get messages from cli"
551 "(expected: %d, got %d)", CONFIG_BT_MESH_BLOB_CLI_BLOCK_RETRIES, j);
552 }
553 }
554
555 PASS();
556 }
557
558 static struct k_sem blob_broad_send_sem;
559 static bool broadcast_tx_complete_auto;
560
broadcast_send(struct bt_mesh_blob_cli * b,uint16_t dst)561 static void broadcast_send(struct bt_mesh_blob_cli *b, uint16_t dst)
562 {
563 ASSERT_EQUAL(BLOB_GROUP_ADDR, dst);
564 k_sem_give(&blob_broad_send_sem);
565 if (broadcast_tx_complete_auto) {
566 /* Mocks completion of transmission to trigger retransmit timer */
567 blob_cli_broadcast_tx_complete(&blob_cli);
568 }
569 }
570
571 static struct k_sem blob_broad_next_sem;
572
broadcast_next(struct bt_mesh_blob_cli * b)573 static void broadcast_next(struct bt_mesh_blob_cli *b)
574 {
575 k_sem_give(&blob_broad_next_sem);
576 }
577
test_cli_broadcast_basic(void)578 static void test_cli_broadcast_basic(void)
579 {
580 bt_mesh_test_cfg_set(NULL, 300);
581 bt_mesh_device_setup(&prov, &cli_comp);
582 blob_cli_prov_and_conf(BLOB_CLI_ADDR);
583
584 struct bt_mesh_blob_target *srv1 = target_srv_add(BLOB_CLI_ADDR + 1, false);
585 struct bt_mesh_blob_target *srv2 = target_srv_add(BLOB_CLI_ADDR + 2, false);
586
587 struct blob_cli_broadcast_ctx tx = {
588 .send = broadcast_send,
589 .next = broadcast_next,
590 .acked = true,
591 .optional = false,
592 };
593
594 broadcast_tx_complete_auto = false;
595 k_sem_init(&blob_broad_send_sem, 0, 1);
596 k_sem_init(&blob_broad_next_sem, 0, 1);
597
598 blob_cli.inputs = &blob_cli_xfer.inputs;
599 blob_cli_inputs_prepare(BLOB_GROUP_ADDR);
600
601 /* Call broadcast and expect send CB to trigger */
602 blob_cli_broadcast(&blob_cli, &tx);
603 if (k_sem_take(&blob_broad_send_sem, K_SECONDS(15))) {
604 FAIL("Broadcast did not trigger send CB");
605 }
606
607 ASSERT_FALSE(srv1->acked);
608 ASSERT_FALSE(srv2->acked);
609
610 /* Run tx complete with two missing responses */
611 blob_cli_broadcast_tx_complete(&blob_cli);
612 if (k_sem_take(&blob_broad_send_sem, K_SECONDS(15))) {
613 FAIL("Tx_complete did not trigger send CB after timeout");
614 }
615
616 ASSERT_FALSE(srv1->acked);
617 ASSERT_FALSE(srv2->acked);
618
619 /* Mock rsp from first target server */
620 /* Run tx complete with one missing response */
621 blob_cli_broadcast_rsp(&blob_cli, srv1);
622 blob_cli_broadcast_tx_complete(&blob_cli);
623 if (k_sem_take(&blob_broad_send_sem, K_SECONDS(15))) {
624 FAIL("Tx_complete did not trigger send CB after timeout");
625 }
626
627 ASSERT_TRUE(srv1->acked);
628 ASSERT_FALSE(srv2->acked);
629
630 /* Mock rsp from second target server */
631 /* Run tx complete with response from all targets */
632 blob_cli_broadcast_tx_complete(&blob_cli);
633 blob_cli_broadcast_rsp(&blob_cli, srv2);
634 if (k_sem_take(&blob_broad_next_sem, K_SECONDS(15))) {
635 FAIL("Tx_complete did not trigger next CB after timeout");
636 }
637
638 ASSERT_TRUE(srv1->acked);
639 ASSERT_TRUE(srv2->acked);
640
641 /* Verify that a single broadcast call triggers a single send CB */
642 k_sem_init(&blob_broad_send_sem, 0, 2);
643 (void)target_srv_add(BLOB_CLI_ADDR + 3, false);
644
645 blob_cli_inputs_prepare(BLOB_GROUP_ADDR);
646
647 blob_cli_broadcast(&blob_cli, &tx);
648 k_sleep(K_SECONDS(80));
649
650 ASSERT_EQUAL(k_sem_count_get(&blob_broad_send_sem), 1);
651
652 PASS();
653 }
654
test_cli_broadcast_trans(void)655 static void test_cli_broadcast_trans(void)
656 {
657 bt_mesh_test_cfg_set(NULL, 150);
658 bt_mesh_device_setup(&prov, &cli_comp);
659 blob_cli_prov_and_conf(BLOB_CLI_ADDR);
660
661 struct bt_mesh_blob_target *srv1 = target_srv_add(BLOB_CLI_ADDR + 1, true);
662
663 struct blob_cli_broadcast_ctx tx = {
664 .send = broadcast_send,
665 .next = broadcast_next,
666 .acked = true,
667 .optional = false
668 };
669
670 broadcast_tx_complete_auto = true;
671 k_sem_init(&blob_broad_send_sem, 0, 1);
672 k_sem_init(&blob_broad_next_sem, 0, 1);
673 k_sem_init(&lost_target_sem, 0, 1);
674
675 blob_cli.inputs = &blob_cli_xfer.inputs;
676
677 /* Run acked broadcast */
678 blob_cli_inputs_prepare(BLOB_GROUP_ADDR);
679
680 blob_cli_broadcast(&blob_cli, &tx);
681
682 /* Checks that the client performs correct amount of retransmit attempts */
683 for (size_t j = 0; j < CONFIG_BT_MESH_BLOB_CLI_BLOCK_RETRIES; j++) {
684 if (k_sem_take(&blob_broad_send_sem, K_SECONDS(15))) {
685 FAIL("Wrong number of attempted transmissions from blob cli"
686 "(expected: %d, got %d)",
687 CONFIG_BT_MESH_BLOB_CLI_BLOCK_RETRIES, j);
688 }
689 }
690
691 if (k_sem_take(&blob_broad_next_sem, K_SECONDS(15))) {
692 FAIL("Broadcast did not trigger next CB after retransmisson ran out of attempts");
693 }
694
695 if (k_sem_take(&lost_target_sem, K_NO_WAIT)) {
696 FAIL("Lost targets CB did not trigger for all expected lost targets");
697 }
698
699 ASSERT_TRUE(srv1->timedout);
700
701 /* Re-run with unacked broadcast */
702 tx.acked = false;
703 blob_cli_inputs_prepare(BLOB_GROUP_ADDR);
704
705 /* Call broadcast and expect send CB to trigger once*/
706 blob_cli_broadcast(&blob_cli, &tx);
707 if (k_sem_take(&blob_broad_send_sem, K_NO_WAIT)) {
708 FAIL("Broadcast did not trigger send CB");
709 }
710
711 if (k_sem_take(&blob_broad_next_sem, K_SECONDS(1))) {
712 FAIL("Broadcast did not trigger next CB");
713 }
714
715 /* Lost target CB should not trigger for unacked broadcast */
716 if (!k_sem_take(&lost_target_sem, K_NO_WAIT)) {
717 FAIL("Lost targets CB triggered unexpectedly");
718 }
719
720 ASSERT_FALSE(srv1->timedout);
721
722 /* Re-run with optional flag */
723 tx.acked = true;
724 tx.optional = true;
725 blob_cli_inputs_prepare(BLOB_GROUP_ADDR);
726
727 blob_cli_broadcast(&blob_cli, &tx);
728
729 for (size_t j = 0; j < CONFIG_BT_MESH_BLOB_CLI_BLOCK_RETRIES; j++) {
730 if (k_sem_take(&blob_broad_send_sem, K_SECONDS(15))) {
731 FAIL("Wrong number of attempted transmissions from blob cli"
732 "(expected: %d, got %d)",
733 CONFIG_BT_MESH_BLOB_CLI_BLOCK_RETRIES, j);
734 }
735 }
736
737 if (k_sem_take(&blob_broad_next_sem, K_SECONDS(15))) {
738 FAIL("Broadcast did not trigger next CB");
739 }
740
741 /* Lost target CB should not trigger for optional broadcast */
742 if (!k_sem_take(&lost_target_sem, K_NO_WAIT)) {
743 FAIL("Lost targets CB triggered unexpectedly");
744 }
745
746 ASSERT_FALSE(srv1->timedout);
747
748 PASS();
749 }
750
751 static uint16_t dst_addr_last;
752 static struct k_sem blob_broad_send_uni_sem;
753
broadcast_uni_send(struct bt_mesh_blob_cli * b,uint16_t dst)754 static void broadcast_uni_send(struct bt_mesh_blob_cli *b, uint16_t dst)
755 {
756 dst_addr_last = dst;
757 k_sem_give(&blob_broad_send_uni_sem);
758 if (broadcast_tx_complete_auto) {
759 /* Mocks completion of transmission to trigger retransmit timer */
760 blob_cli_broadcast_tx_complete(&blob_cli);
761 }
762 }
763
test_cli_broadcast_unicast_seq(void)764 static void test_cli_broadcast_unicast_seq(void)
765 {
766 bt_mesh_test_cfg_set(NULL, 60);
767 bt_mesh_device_setup(&prov, &cli_comp);
768 blob_cli_prov_and_conf(BLOB_CLI_ADDR);
769
770 struct bt_mesh_blob_target *srv1 = target_srv_add(BLOB_CLI_ADDR + 1, false);
771 struct bt_mesh_blob_target *srv2 = target_srv_add(BLOB_CLI_ADDR + 2, false);
772
773 struct blob_cli_broadcast_ctx tx = {
774 .send = broadcast_uni_send,
775 .next = broadcast_next,
776 .acked = true,
777 .optional = false,
778 };
779
780 k_sem_init(&blob_broad_send_uni_sem, 0, 1);
781 k_sem_init(&blob_broad_next_sem, 0, 1);
782
783 blob_cli.inputs = &blob_cli_xfer.inputs;
784 broadcast_tx_complete_auto = false;
785
786 /** Two responsive targets. Checks that:
787 * - Send CB alternates between targets
788 * - Don't retransmit to responded targets
789 * - Next CB is called as soon as all have responded
790 * (Test assumes at least 5 transmission attempts)
791 */
792 BUILD_ASSERT(CONFIG_BT_MESH_BLOB_CLI_BLOCK_RETRIES >= 5);
793
794 blob_cli_inputs_prepare(BT_MESH_ADDR_UNASSIGNED);
795 blob_cli_broadcast(&blob_cli, &tx);
796
797 for (size_t i = 0; i < 2; i++) {
798 if (k_sem_take(&blob_broad_send_uni_sem, K_SECONDS(10))) {
799 FAIL("Broadcast did not trigger send CB");
800 }
801
802 ASSERT_EQUAL(BLOB_CLI_ADDR + 1, dst_addr_last);
803 blob_cli_broadcast_tx_complete(&blob_cli);
804 if (k_sem_take(&blob_broad_send_uni_sem, K_SECONDS(10))) {
805 FAIL("Tx complete did not trigger send CB");
806 }
807
808 ASSERT_EQUAL(BLOB_CLI_ADDR + 2, dst_addr_last);
809 blob_cli_broadcast_tx_complete(&blob_cli);
810 }
811
812 blob_cli_broadcast_rsp(&blob_cli, srv1);
813 for (size_t i = 0; i < 2; i++) {
814 if (k_sem_take(&blob_broad_send_uni_sem, K_SECONDS(10))) {
815 FAIL("Tx complete did not trigger send CB");
816 }
817
818 ASSERT_EQUAL(BLOB_CLI_ADDR + 2, dst_addr_last);
819 blob_cli_broadcast_tx_complete(&blob_cli);
820 }
821
822 blob_cli_broadcast_rsp(&blob_cli, srv2);
823 if (!k_sem_take(&blob_broad_send_uni_sem, K_SECONDS(10))) {
824 FAIL("Unexpected send CB");
825 }
826
827 if (k_sem_take(&blob_broad_next_sem, K_NO_WAIT)) {
828 FAIL("Broadcast did not trigger next CB");
829 }
830
831 PASS();
832 }
833
test_cli_broadcast_unicast(void)834 static void test_cli_broadcast_unicast(void)
835 {
836 bt_mesh_test_cfg_set(NULL, 120);
837 bt_mesh_device_setup(&prov, &cli_comp);
838 blob_cli_prov_and_conf(BLOB_CLI_ADDR);
839
840 (void)target_srv_add(BLOB_CLI_ADDR + 1, true);
841 (void)target_srv_add(BLOB_CLI_ADDR + 2, true);
842
843 struct blob_cli_broadcast_ctx tx = {
844 .send = broadcast_uni_send,
845 .next = broadcast_next,
846 .acked = true,
847 .optional = false,
848 };
849
850 k_sem_init(&blob_broad_send_uni_sem, 0, 1);
851 k_sem_init(&blob_broad_next_sem, 0, 1);
852 k_sem_init(&lost_target_sem, 0, 1);
853
854 blob_cli.inputs = &blob_cli_xfer.inputs;
855 broadcast_tx_complete_auto = true;
856
857 /** 1. Two non-responsive targets. Checks that:
858 * - Next CB is called after all retransmit attempts expires
859 * - All lost targets is registered
860 */
861 blob_cli_inputs_prepare(BT_MESH_ADDR_UNASSIGNED);
862 blob_cli_broadcast(&blob_cli, &tx);
863
864 if (k_sem_take(&blob_broad_next_sem, K_SECONDS(60))) {
865 FAIL("Broadcast did not trigger next CB");
866 }
867
868 if (k_sem_take(&lost_target_sem, K_NO_WAIT)) {
869 FAIL("Lost targets CB did not trigger for all expected lost targets");
870 }
871
872 /** 2. Two non-responsive targets re-run. Checks that:
873 * - Already lost targets does not attempt new transmission
874 * (Next CB called immediately)
875 */
876 blob_cli_broadcast(&blob_cli, &tx);
877 if (k_sem_take(&blob_broad_next_sem, K_NO_WAIT)) {
878 FAIL("Broadcast did not trigger immediate next CB");
879 }
880
881 /** 3. Two non-responsive targets (Abort after first attempt). Checks that:
882 * - First transmission calls send CB
883 * - After abort is called, neither send or next CB is called
884 */
885 k_sem_init(&blob_broad_send_uni_sem, 0, 1);
886 blob_cli_inputs_prepare(BT_MESH_ADDR_UNASSIGNED);
887 blob_cli_broadcast(&blob_cli, &tx);
888 if (k_sem_take(&blob_broad_send_uni_sem, K_NO_WAIT)) {
889 FAIL("Broadcast did not trigger send CB");
890 }
891
892 blob_cli_broadcast_abort(&blob_cli);
893 if (!k_sem_take(&blob_broad_send_uni_sem, K_SECONDS(60))) {
894 FAIL("Unexpected send CB");
895 }
896
897 if (!k_sem_take(&blob_broad_next_sem, K_NO_WAIT)) {
898 FAIL("Unexpected next CB");
899 }
900
901 PASS();
902 }
903
test_cli_trans_complete(void)904 static void test_cli_trans_complete(void)
905 {
906 int err;
907
908 bt_mesh_test_cfg_set(NULL, 400);
909 bt_mesh_device_setup(&prov, &cli_comp);
910 blob_cli_prov_and_conf(BLOB_CLI_ADDR);
911
912 (void)target_srv_add(BLOB_CLI_ADDR + 1, false);
913 (void)target_srv_add(BLOB_CLI_ADDR + 2, false);
914 (void)target_srv_add(BLOB_CLI_ADDR + 3, false);
915 (void)target_srv_add(BLOB_CLI_ADDR + 4, false);
916
917 k_sem_init(&blob_caps_sem, 0, 1);
918 k_sem_init(&lost_target_sem, 0, 1);
919 k_sem_init(&blob_cli_end_sem, 0, 1);
920 k_sem_init(&blob_cli_suspend_sem, 0, 1);
921
922 LOG_INF("Running transfer in %s", is_pull_mode ? "Pull mode" : "Push mode");
923
924 blob_cli_inputs_prepare(BLOB_GROUP_ADDR);
925 blob_cli_xfer.xfer.mode =
926 is_pull_mode ? BT_MESH_BLOB_XFER_MODE_PULL : BT_MESH_BLOB_XFER_MODE_PUSH;
927 blob_cli_xfer.xfer.size = CONFIG_BT_MESH_BLOB_BLOCK_SIZE_MAX * 2;
928 blob_cli_xfer.xfer.id = 1;
929 blob_cli_xfer.xfer.block_size_log = 12;
930 blob_cli_xfer.xfer.chunk_size = 377;
931 blob_cli_xfer.inputs.timeout_base = 10;
932
933 err = bt_mesh_blob_cli_send(&blob_cli, &blob_cli_xfer.inputs,
934 &blob_cli_xfer.xfer, &blob_io);
935 if (err) {
936 FAIL("BLOB send failed (err: %d)", err);
937 }
938
939 if (k_sem_take(&blob_cli_end_sem, K_SECONDS(380))) {
940 FAIL("End CB did not trigger as expected for the cli");
941 }
942
943 ASSERT_TRUE(blob_cli.state == BT_MESH_BLOB_CLI_STATE_NONE);
944
945 PASS();
946 }
947
test_srv_trans_complete(void)948 static void test_srv_trans_complete(void)
949 {
950 bt_mesh_test_cfg_set(NULL, 400);
951 bt_mesh_device_setup(&prov, &srv_comp);
952 blob_srv_prov_and_conf(bt_mesh_test_own_addr_get(BLOB_CLI_ADDR));
953
954 k_sem_init(&first_block_wr_sem, 0, 1);
955 k_sem_init(&blob_srv_end_sem, 0, 1);
956 k_sem_init(&blob_srv_suspend_sem, 0, 1);
957
958 bt_mesh_blob_srv_recv(&blob_srv, 1, &blob_io, 0, 10);
959
960 if (k_sem_take(&blob_srv_end_sem, K_SECONDS(380))) {
961 FAIL("End CB did not trigger as expected for the srv");
962 }
963
964 ASSERT_TRUE(blob_srv.phase == BT_MESH_BLOB_XFER_PHASE_COMPLETE);
965
966 /* Check that all blocks is received */
967 ASSERT_TRUE(atomic_test_bit(block_bitfield, 0));
968 ASSERT_TRUE(atomic_test_bit(block_bitfield, 1));
969
970 /* Check that a third block was not received */
971 ASSERT_FALSE(atomic_test_bit(block_bitfield, 2));
972
973 PASS();
974 }
975
test_cli_trans_resume(void)976 static void test_cli_trans_resume(void)
977 {
978 int err;
979
980 bt_mesh_test_cfg_set(NULL, 800);
981 bt_mesh_device_setup(&prov, &cli_comp);
982 blob_cli_prov_and_conf(BLOB_CLI_ADDR);
983
984 (void)target_srv_add(BLOB_CLI_ADDR + 1, true);
985
986 k_sem_init(&blob_caps_sem, 0, 1);
987 k_sem_init(&lost_target_sem, 0, 1);
988 k_sem_init(&blob_cli_end_sem, 0, 1);
989 k_sem_init(&blob_cli_suspend_sem, 0, 1);
990
991 LOG_INF("Running transfer in %s", is_pull_mode ? "Pull mode" : "Push mode");
992
993 /** Test resumption of suspended BLOB transfer (Push).
994 * Client initiates transfer with two blocks. After
995 * first block completes the server will be suspended.
996 * At this point the client will attempt to resume the
997 * transfer.
998 */
999 blob_cli_inputs_prepare(BLOB_GROUP_ADDR);
1000 blob_cli_xfer.xfer.mode =
1001 is_pull_mode ? BT_MESH_BLOB_XFER_MODE_PULL : BT_MESH_BLOB_XFER_MODE_PUSH;
1002 blob_cli_xfer.xfer.size = CONFIG_BT_MESH_BLOB_BLOCK_SIZE_MAX * 2;
1003 blob_cli_xfer.xfer.id = 1;
1004 blob_cli_xfer.xfer.block_size_log = 12;
1005 blob_cli_xfer.xfer.chunk_size = 377;
1006 blob_cli_xfer.inputs.timeout_base = 10;
1007
1008 err = bt_mesh_blob_cli_send(&blob_cli, &blob_cli_xfer.inputs,
1009 &blob_cli_xfer.xfer, &blob_io);
1010 if (err) {
1011 FAIL("BLOB send failed (err: %d)", err);
1012 }
1013
1014 if (k_sem_take(&blob_cli_suspend_sem, K_SECONDS(500))) {
1015 FAIL("Suspend CB did not trigger as expected for the cli");
1016 }
1017
1018 if (k_sem_take(&lost_target_sem, K_NO_WAIT)) {
1019 FAIL("Lost targets CB did not trigger for the target srv");
1020 }
1021
1022 ASSERT_TRUE(blob_cli.state == BT_MESH_BLOB_CLI_STATE_SUSPENDED);
1023
1024 /* Initiate resumption of BLOB transfer */
1025 err = bt_mesh_blob_cli_resume(&blob_cli);
1026 if (err) {
1027 FAIL("BLOB resume failed (err: %d)", err);
1028 }
1029
1030 if (k_sem_take(&blob_cli_end_sem, K_SECONDS(780))) {
1031 FAIL("End CB did not trigger as expected for the cli");
1032 }
1033
1034 ASSERT_TRUE(blob_cli.state == BT_MESH_BLOB_CLI_STATE_NONE);
1035
1036 PASS();
1037 }
1038
test_srv_trans_resume(void)1039 static void test_srv_trans_resume(void)
1040 {
1041 bt_mesh_test_cfg_set(NULL, 800);
1042 bt_mesh_device_setup(&prov, &srv_comp);
1043 blob_srv_prov_and_conf(bt_mesh_test_own_addr_get(BLOB_CLI_ADDR));
1044
1045 k_sem_init(&first_block_wr_sem, 0, 1);
1046 k_sem_init(&blob_srv_end_sem, 0, 1);
1047 k_sem_init(&blob_srv_suspend_sem, 0, 1);
1048
1049 /** Wait for a first blob block to be received, then simulate radio
1050 * disruption to cause suspension of the blob srv. Re-enable the radio
1051 * as soon as the server is suspended and wait to receive the second
1052 * block.
1053 */
1054 bt_mesh_blob_srv_recv(&blob_srv, 1, &blob_io, 0, 10);
1055
1056 /* Let server receive a couple of chunks from second block before disruption */
1057 for (int i = 0; i < 3; i++) {
1058 if (k_sem_take(&first_block_wr_sem, K_SECONDS(180))) {
1059 FAIL("Server did not receive the first BLOB block");
1060 }
1061 }
1062
1063 bt_mesh_scan_disable();
1064 partial_block = 0;
1065 if (k_sem_take(&blob_srv_suspend_sem, K_SECONDS(140))) {
1066 FAIL("Suspend CB did not trigger as expected for the srv");
1067 }
1068
1069 ASSERT_TRUE(blob_srv.phase == BT_MESH_BLOB_XFER_PHASE_SUSPENDED);
1070
1071 /* Wait for BLOB client to suspend. Measured experimentally. */
1072 k_sleep(K_SECONDS(140));
1073
1074 bt_mesh_scan_enable();
1075
1076 if (k_sem_take(&blob_srv_end_sem, K_SECONDS(780))) {
1077 FAIL("End CB did not trigger as expected for the srv");
1078 }
1079
1080 ASSERT_TRUE(blob_srv.phase == BT_MESH_BLOB_XFER_PHASE_COMPLETE);
1081
1082 /* Check that all blocks is received */
1083 ASSERT_TRUE(atomic_test_bit(block_bitfield, 0));
1084 ASSERT_TRUE(atomic_test_bit(block_bitfield, 1));
1085
1086 /* Check that a third block was not received */
1087 ASSERT_FALSE(atomic_test_bit(block_bitfield, 2));
1088
1089 PASS();
1090 }
1091
cli_pull_mode_setup(void)1092 static void cli_pull_mode_setup(void)
1093 {
1094 bt_mesh_device_setup(&prov, &cli_comp);
1095 blob_cli_prov_and_conf(BLOB_CLI_ADDR);
1096
1097 k_sem_init(&blob_caps_sem, 0, 1);
1098 k_sem_init(&lost_target_sem, 0, 1);
1099 k_sem_init(&blob_cli_end_sem, 0, 1);
1100 k_sem_init(&blob_cli_suspend_sem, 0, 1);
1101
1102 blob_cli_xfer.xfer.mode = BT_MESH_BLOB_XFER_MODE_PULL;
1103 blob_cli_xfer.xfer.size = CONFIG_BT_MESH_BLOB_BLOCK_SIZE_MIN * 3;
1104 blob_cli_xfer.xfer.id = 1;
1105 blob_cli_xfer.xfer.block_size_log = 8;
1106 blob_cli_xfer.xfer.chunk_size = 36;
1107 blob_cli_xfer.inputs.timeout_base = 10;
1108 }
1109
test_cli_trans_persistency_pull(void)1110 static void test_cli_trans_persistency_pull(void)
1111 {
1112 int err;
1113
1114 bt_mesh_test_cfg_set(NULL, 240);
1115
1116 (void)target_srv_add(BLOB_CLI_ADDR + 1, true);
1117 (void)target_srv_add(BLOB_CLI_ADDR + 2, false);
1118
1119 cli_pull_mode_setup();
1120
1121 blob_cli_inputs_prepare(0);
1122
1123 err = bt_mesh_blob_cli_send(&blob_cli, &blob_cli_xfer.inputs,
1124 &blob_cli_xfer.xfer, &blob_io);
1125 if (err) {
1126 FAIL("BLOB send failed (err: %d)", err);
1127 }
1128
1129 if (k_sem_take(&blob_cli_end_sem, K_SECONDS(230))) {
1130 FAIL("End CB did not trigger as expected for the cli");
1131 }
1132
1133 ASSERT_TRUE(blob_cli.state == BT_MESH_BLOB_CLI_STATE_NONE);
1134
1135 PASS();
1136 }
1137
srv_pull_mode_setup(void)1138 static void srv_pull_mode_setup(void)
1139 {
1140 bt_mesh_device_setup(&prov, &srv_comp);
1141 blob_srv_prov_and_conf(bt_mesh_test_own_addr_get(BLOB_CLI_ADDR));
1142
1143 k_sem_init(&first_block_wr_sem, 0, 1);
1144 k_sem_init(&blob_srv_end_sem, 0, 1);
1145 k_sem_init(&blob_srv_suspend_sem, 0, 1);
1146 }
1147
test_srv_trans_persistency_pull(void)1148 static void test_srv_trans_persistency_pull(void)
1149 {
1150 bt_mesh_test_cfg_set(NULL, 240);
1151
1152 srv_pull_mode_setup();
1153
1154 bt_mesh_blob_srv_recv(&blob_srv, 1, &blob_io, 0, 10);
1155
1156 /* Target with address 0x0002 (the first one) will disappear after receiving the first
1157 * block. Target with address 0x0003 (the second one) will stay alive.
1158 */
1159 if (bt_mesh_test_own_addr_get(BLOB_CLI_ADDR) == 0x0002) {
1160 /* Let the first target receive a couple of chunks from second block before
1161 * disruption.
1162 */
1163 for (int i = 0; i < 3; i++) {
1164 if (k_sem_take(&first_block_wr_sem, K_SECONDS(100))) {
1165 FAIL("Server did not receive the first BLOB block");
1166 }
1167 }
1168
1169 bt_mesh_scan_disable();
1170 bt_mesh_blob_srv_cancel(&blob_srv);
1171 PASS();
1172 return;
1173 }
1174
1175 if (k_sem_take(&blob_srv_end_sem, K_SECONDS(230))) {
1176 FAIL("End CB did not trigger as expected for the srv");
1177 }
1178
1179 ASSERT_TRUE(blob_srv.phase == BT_MESH_BLOB_XFER_PHASE_COMPLETE);
1180
1181 /* Check that all blocks is received */
1182 ASSERT_TRUE(atomic_test_bit(block_bitfield, 0));
1183 ASSERT_TRUE(atomic_test_bit(block_bitfield, 1));
1184 ASSERT_TRUE(atomic_test_bit(block_bitfield, 2));
1185
1186 /* Check that a third block was not received */
1187 ASSERT_FALSE(atomic_test_bit(block_bitfield, 3));
1188
1189 PASS();
1190 }
1191
1192 /* Makes device unresponsive after I/O is opened */
fail_on_io_open(const struct bt_mesh_blob_io * io,const struct bt_mesh_blob_xfer * xfer,enum bt_mesh_blob_io_mode mode)1193 static int fail_on_io_open(const struct bt_mesh_blob_io *io,
1194 const struct bt_mesh_blob_xfer *xfer,
1195 enum bt_mesh_blob_io_mode mode)
1196 {
1197 bt_mesh_scan_disable();
1198 return 0;
1199 }
1200
1201 /* Makes device unresponsive after receiving block start msg */
fail_on_block_start(const struct bt_mesh_blob_io * io,const struct bt_mesh_blob_xfer * xfer,const struct bt_mesh_blob_block * block)1202 static int fail_on_block_start(const struct bt_mesh_blob_io *io,
1203 const struct bt_mesh_blob_xfer *xfer,
1204 const struct bt_mesh_blob_block *block)
1205 {
1206 bt_mesh_scan_disable();
1207 return 0;
1208 }
1209
cli_common_fail_on_init(void)1210 static void cli_common_fail_on_init(void)
1211 {
1212 bt_mesh_test_cfg_set(NULL, 800);
1213 bt_mesh_device_setup(&prov, &cli_comp);
1214 blob_cli_prov_and_conf(BLOB_CLI_ADDR);
1215
1216 k_sem_init(&blob_caps_sem, 0, 1);
1217 k_sem_init(&lost_target_sem, 0, 1);
1218 k_sem_init(&blob_cli_end_sem, 0, 1);
1219 k_sem_init(&blob_cli_suspend_sem, 0, 1);
1220
1221 blob_cli_inputs_prepare(BLOB_GROUP_ADDR);
1222 blob_cli_xfer.xfer.mode = BT_MESH_BLOB_XFER_MODE_PUSH;
1223 blob_cli_xfer.xfer.size = CONFIG_BT_MESH_BLOB_BLOCK_SIZE_MAX * 1;
1224 blob_cli_xfer.xfer.id = 1;
1225 blob_cli_xfer.xfer.block_size_log = 12;
1226 blob_cli_xfer.xfer.chunk_size = 377;
1227 blob_cli_xfer.inputs.timeout_base = 10;
1228 }
1229
test_cli_fail_on_persistency(void)1230 static void test_cli_fail_on_persistency(void)
1231 {
1232 int err;
1233
1234 /** Test that Push mode BLOB transfer persists as long as at
1235 * least one target is still active. During the test multiple
1236 * servers will become unresponsive at different phases of the
1237 * transfer:
1238 * - Srv 0x0002 will not respond to Block start msg.
1239 * - Srv 0x0003 will not respond to Block get msg.
1240 * - Srv 0x0004 will not respond to Xfer get msg.
1241 * - Srv 0x0005 is responsive all the way
1242 * - Srv 0x0006 is a non-existing unresponsive node
1243 */
1244 (void)target_srv_add(BLOB_CLI_ADDR + 1, true);
1245 (void)target_srv_add(BLOB_CLI_ADDR + 2, true);
1246 (void)target_srv_add(BLOB_CLI_ADDR + 3, true);
1247 (void)target_srv_add(BLOB_CLI_ADDR + 4, false);
1248 (void)target_srv_add(BLOB_CLI_ADDR + 5, true);
1249
1250 cli_common_fail_on_init();
1251
1252 err = bt_mesh_blob_cli_send(&blob_cli, &blob_cli_xfer.inputs,
1253 &blob_cli_xfer.xfer, &blob_io);
1254 if (err) {
1255 FAIL("BLOB send failed (err: %d)", err);
1256 }
1257
1258 if (k_sem_take(&blob_cli_end_sem, K_SECONDS(750))) {
1259 FAIL("End CB did not trigger as expected for the cli");
1260 }
1261
1262 ASSERT_TRUE(cli_end_success);
1263
1264 if (k_sem_take(&lost_target_sem, K_NO_WAIT)) {
1265 FAIL("Lost targets CB did not trigger for all expected lost targets");
1266 }
1267
1268 PASS();
1269 }
1270
common_fail_on_srv_init(const struct bt_mesh_comp * comp)1271 static void common_fail_on_srv_init(const struct bt_mesh_comp *comp)
1272 {
1273 bt_mesh_test_cfg_set(NULL, 800);
1274 bt_mesh_device_setup(&prov, comp);
1275 blob_srv_prov_and_conf(bt_mesh_test_own_addr_get(BLOB_CLI_ADDR));
1276
1277 k_sem_init(&first_block_wr_sem, 0, 1);
1278 k_sem_init(&blob_srv_end_sem, 0, 1);
1279 k_sem_init(&blob_srv_suspend_sem, 0, 1);
1280 }
1281
test_srv_fail_on_block_start(void)1282 static void test_srv_fail_on_block_start(void)
1283 {
1284 common_fail_on_srv_init(&srv_comp);
1285
1286 static const struct bt_mesh_blob_io io = {
1287 .open = fail_on_io_open,
1288 .rd = blob_chunk_rd,
1289 .wr = blob_chunk_wr,
1290 };
1291
1292 bt_mesh_blob_srv_recv(&blob_srv, 1, &io, 0, 1);
1293
1294 PASS();
1295 }
1296
test_srv_fail_on_block_get(void)1297 static void test_srv_fail_on_block_get(void)
1298 {
1299 common_fail_on_srv_init(&srv_comp);
1300
1301 static const struct bt_mesh_blob_io io = {
1302 .open = blob_io_open,
1303 .rd = blob_chunk_rd,
1304 .wr = blob_chunk_wr,
1305 .block_start = fail_on_block_start,
1306 };
1307
1308 bt_mesh_blob_srv_recv(&blob_srv, 1, &io, 0, 1);
1309
1310 PASS();
1311 }
1312
dummy_xfer_get(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1313 static int dummy_xfer_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
1314 struct net_buf_simple *buf)
1315 {
1316 return 0;
1317 }
1318
1319 static const struct bt_mesh_model_op model_op2[] = {
1320 { BT_MESH_BLOB_OP_XFER_GET, 0, dummy_xfer_get },
1321 BT_MESH_MODEL_OP_END
1322 };
1323
1324 /** Composition data for BLOB server where we intercept the
1325 * BT_MESH_BLOB_OP_XFER_GET message handler through an imposter
1326 * model. This is done to emulate a BLOB server that becomes
1327 * unresponsive at the later stage of a BLOB transfer.
1328 */
1329 static const struct bt_mesh_comp srv_broken_comp = {
1330 .elem =
1331 (struct bt_mesh_elem[]){
1332 BT_MESH_ELEM(1,
1333 MODEL_LIST(BT_MESH_MODEL_CFG_SRV,
1334 BT_MESH_MODEL_CFG_CLI(&cfg_cli),
1335 BT_MESH_MODEL_SAR_CFG_SRV,
1336 BT_MESH_MODEL_SAR_CFG_CLI(&sar_cfg_cli),
1337 BT_MESH_MODEL_CB(IMPOSTER_MODEL_ID,
1338 model_op2, NULL, NULL, NULL),
1339 BT_MESH_MODEL_BLOB_SRV(&blob_srv)),
1340 BT_MESH_MODEL_NONE),
1341 },
1342 .elem_count = 1,
1343 };
1344
test_srv_fail_on_xfer_get(void)1345 static void test_srv_fail_on_xfer_get(void)
1346 {
1347 common_fail_on_srv_init(&srv_broken_comp);
1348
1349 bt_mesh_blob_srv_recv(&blob_srv, 1, &blob_io, 0, 5);
1350
1351 PASS();
1352 }
1353
test_srv_fail_on_nothing(void)1354 static void test_srv_fail_on_nothing(void)
1355 {
1356 common_fail_on_srv_init(&srv_comp);
1357
1358 bt_mesh_blob_srv_recv(&blob_srv, 1, &blob_io, 0, 5);
1359
1360 PASS();
1361 }
1362
test_cli_fail_on_no_rsp(void)1363 static void test_cli_fail_on_no_rsp(void)
1364 {
1365 int err;
1366
1367 /** Test fail conditions upon non-responsive servers
1368 * during push transfer. Depending on the set
1369 * test message type it tests the following:
1370 *
1371 * msg_fail_type = BLOCK_GET_FAIL - BLOB transfer suspends
1372 * when targets does not respond to Block get.
1373 * msg_fail_type = XFER_GET_FAIL - BLOB transfer stops
1374 * when targets does not respond to Xfer get message.
1375 */
1376
1377 (void)target_srv_add(BLOB_CLI_ADDR + 1, true);
1378 (void)target_srv_add(BLOB_CLI_ADDR + 2, true);
1379
1380 cli_common_fail_on_init();
1381
1382 err = bt_mesh_blob_cli_send(&blob_cli, &blob_cli_xfer.inputs,
1383 &blob_cli_xfer.xfer, &blob_io);
1384 if (err) {
1385 FAIL("BLOB send failed (err: %d)", err);
1386 }
1387
1388 switch (msg_fail_type) {
1389 case BLOCK_GET_FAIL:
1390 if (k_sem_take(&blob_cli_suspend_sem, K_SECONDS(750))) {
1391 FAIL("Suspend CB did not trigger as expected for the cli");
1392 }
1393
1394 break;
1395
1396 case XFER_GET_FAIL:
1397 if (k_sem_take(&blob_cli_end_sem, K_SECONDS(750))) {
1398 FAIL("End CB did not trigger as expected for the cli");
1399 }
1400
1401 ASSERT_FALSE(cli_end_success);
1402 break;
1403
1404 default:
1405 FAIL("Did not recognize the message type of the test");
1406 }
1407
1408 if (k_sem_take(&lost_target_sem, K_NO_WAIT)) {
1409 FAIL("Lost targets CB did not trigger for all expected lost targets");
1410 }
1411
1412 PASS();
1413 }
1414
1415 #if CONFIG_BT_SETTINGS
cli_stop_setup(void)1416 static void cli_stop_setup(void)
1417 {
1418 bt_mesh_device_setup(&prov, &cli_comp);
1419
1420 (void)target_srv_add(BLOB_CLI_ADDR + 1, true);
1421
1422 blob_cli_inputs_prepare(BLOB_GROUP_ADDR);
1423 blob_cli_xfer.xfer.mode =
1424 is_pull_mode ? BT_MESH_BLOB_XFER_MODE_PULL : BT_MESH_BLOB_XFER_MODE_PUSH;
1425 blob_cli_xfer.xfer.size = CONFIG_BT_MESH_BLOB_BLOCK_SIZE_MAX * 2;
1426 blob_cli_xfer.xfer.id = 1;
1427 blob_cli_xfer.xfer.block_size_log = 12;
1428 blob_cli_xfer.xfer.chunk_size = 377;
1429 blob_cli_xfer.inputs.timeout_base = 10;
1430 }
1431
cli_restore_suspended(void)1432 static void cli_restore_suspended(void)
1433 {
1434 blob_cli.state = BT_MESH_BLOB_CLI_STATE_SUSPENDED;
1435 blob_cli.inputs = &blob_cli_xfer.inputs;
1436 blob_cli.xfer = &blob_cli_xfer.xfer;
1437 blob_cli_xfer.xfer.id = 1;
1438 blob_cli.io = &blob_io;
1439
1440 bt_mesh_blob_cli_resume(&blob_cli);
1441 }
1442
test_cli_stop(void)1443 static void test_cli_stop(void)
1444 {
1445 int err;
1446
1447 bt_mesh_test_cfg_set(NULL, 1000);
1448 k_sem_init(&blob_caps_sem, 0, 1);
1449 k_sem_init(&lost_target_sem, 0, 1);
1450 k_sem_init(&blob_cli_end_sem, 0, 1);
1451 k_sem_init(&blob_cli_suspend_sem, 0, 1);
1452
1453 switch (expected_stop_phase) {
1454 case BT_MESH_BLOB_XFER_PHASE_WAITING_FOR_START:
1455 /* Nothing to do on client side in this step,
1456 * just self-provision for future steps
1457 */
1458 bt_mesh_device_setup(&prov, &cli_comp);
1459 blob_cli_prov_and_conf(BLOB_CLI_ADDR);
1460 break;
1461 case BT_MESH_BLOB_XFER_PHASE_WAITING_FOR_BLOCK:
1462 /* Target will be unresponsive once first block completes */
1463 cli_stop_setup();
1464
1465 err = bt_mesh_blob_cli_send(&blob_cli, &blob_cli_xfer.inputs,
1466 &blob_cli_xfer.xfer, &blob_io);
1467 if (err) {
1468 FAIL("BLOB send failed (err: %d)", err);
1469 }
1470
1471 if (k_sem_take(&blob_cli_suspend_sem, K_SECONDS(750))) {
1472 FAIL("Suspend targets CB did not trigger for all expected lost targets");
1473 }
1474
1475 break;
1476 case BT_MESH_BLOB_XFER_PHASE_WAITING_FOR_CHUNK:
1477 cli_stop_setup();
1478
1479 cli_restore_suspended();
1480
1481 /* This will time out but gives time for server to process all messages */
1482 k_sem_take(&blob_cli_end_sem, K_SECONDS(380));
1483
1484 break;
1485 case BT_MESH_BLOB_XFER_PHASE_COMPLETE:
1486 cli_stop_setup();
1487
1488 cli_restore_suspended();
1489
1490 if (k_sem_take(&blob_cli_end_sem, K_SECONDS(380))) {
1491 FAIL("End CB did not trigger as expected for the cli");
1492 }
1493
1494 ASSERT_TRUE(blob_cli.state == BT_MESH_BLOB_CLI_STATE_NONE);
1495
1496 break;
1497 case BT_MESH_BLOB_XFER_PHASE_SUSPENDED:
1498 /* Server will become unresponsive after receiving first chunk */
1499 cli_stop_setup();
1500
1501 blob_cli_prov_and_conf(BLOB_CLI_ADDR);
1502
1503 err = bt_mesh_blob_cli_send(&blob_cli, &blob_cli_xfer.inputs,
1504 &blob_cli_xfer.xfer, &blob_io);
1505 if (err) {
1506 FAIL("BLOB send failed (err: %d)", err);
1507 }
1508
1509 if (k_sem_take(&blob_cli_suspend_sem, K_SECONDS(750))) {
1510 FAIL("Lost targets CB did not trigger for all expected lost targets");
1511 }
1512
1513 break;
1514 default:
1515 /* There is no use case to stop in Inactive phase */
1516 FAIL();
1517 }
1518
1519 PASS();
1520 }
1521
srv_check_reboot_and_continue(void)1522 static void srv_check_reboot_and_continue(void)
1523 {
1524 ASSERT_EQUAL(BT_MESH_BLOB_XFER_PHASE_SUSPENDED, blob_srv.phase);
1525 ASSERT_EQUAL(0, blob_srv.state.ttl);
1526 ASSERT_EQUAL(BLOB_CLI_ADDR, blob_srv.state.cli);
1527 ASSERT_EQUAL(1, blob_srv.state.timeout_base);
1528 ASSERT_EQUAL(BT_MESH_RX_SDU_MAX - BT_MESH_MIC_SHORT, blob_srv.state.mtu_size);
1529 ASSERT_EQUAL(CONFIG_BT_MESH_BLOB_BLOCK_SIZE_MAX * 2, blob_srv.state.xfer.size);
1530 ASSERT_EQUAL(12, blob_srv.state.xfer.block_size_log);
1531 ASSERT_EQUAL(1, blob_srv.state.xfer.id);
1532 ASSERT_TRUE(blob_srv.state.xfer.mode != BT_MESH_BLOB_XFER_MODE_NONE);
1533 /* First block should be already received, second one pending */
1534 ASSERT_FALSE(atomic_test_bit(blob_srv.state.blocks, 0));
1535 ASSERT_TRUE(atomic_test_bit(blob_srv.state.blocks, 1));
1536
1537 k_sem_take(&blob_srv_end_sem, K_SECONDS(500));
1538 }
1539
test_srv_stop(void)1540 static void test_srv_stop(void)
1541 {
1542 bt_mesh_test_cfg_set(NULL, 1000);
1543 k_sem_init(&blob_srv_end_sem, 0, 1);
1544 k_sem_init(&first_block_wr_sem, 0, 1);
1545 k_sem_init(&blob_srv_suspend_sem, 0, 1);
1546
1547 bt_mesh_device_setup(&prov, &srv_comp);
1548
1549 switch (expected_stop_phase) {
1550 case BT_MESH_BLOB_XFER_PHASE_WAITING_FOR_START:
1551 blob_srv_prov_and_conf(bt_mesh_test_own_addr_get(BLOB_CLI_ADDR));
1552 bt_mesh_blob_srv_recv(&blob_srv, 1, &blob_io, 0, 1);
1553
1554 ASSERT_EQUAL(BT_MESH_BLOB_XFER_PHASE_WAITING_FOR_START, blob_srv.phase);
1555 break;
1556 case BT_MESH_BLOB_XFER_PHASE_WAITING_FOR_BLOCK:
1557 ASSERT_EQUAL(BT_MESH_BLOB_XFER_PHASE_WAITING_FOR_START, blob_srv.phase);
1558 ASSERT_OK(blob_srv.state.xfer.mode != BT_MESH_BLOB_XFER_MODE_NONE);
1559 ASSERT_EQUAL(0, blob_srv.state.ttl);
1560
1561 k_sem_take(&blob_srv_end_sem, K_SECONDS(500));
1562
1563 ASSERT_EQUAL(BT_MESH_BLOB_XFER_PHASE_WAITING_FOR_BLOCK, blob_srv.phase);
1564 break;
1565 case BT_MESH_BLOB_XFER_PHASE_WAITING_FOR_CHUNK:
1566 __fallthrough;
1567 case BT_MESH_BLOB_XFER_PHASE_COMPLETE:
1568 srv_check_reboot_and_continue();
1569
1570 ASSERT_EQUAL(expected_stop_phase, blob_srv.phase);
1571 break;
1572 case BT_MESH_BLOB_XFER_PHASE_SUSPENDED:
1573 /* This state is expected to be reached from freshly started procedure */
1574 ASSERT_EQUAL(BT_MESH_BLOB_XFER_PHASE_INACTIVE, blob_srv.phase);
1575 ASSERT_EQUAL(BT_MESH_BLOB_XFER_MODE_NONE, blob_srv.state.xfer.mode);
1576 ASSERT_EQUAL(BT_MESH_TTL_DEFAULT, blob_srv.state.ttl);
1577
1578 blob_srv_prov_and_conf(bt_mesh_test_own_addr_get(BLOB_CLI_ADDR));
1579 bt_mesh_blob_srv_recv(&blob_srv, 1, &blob_io, 0, 1);
1580 k_sem_take(&blob_srv_suspend_sem, K_SECONDS(140));
1581
1582 ASSERT_EQUAL(BT_MESH_BLOB_XFER_PHASE_SUSPENDED, blob_srv.phase);
1583 break;
1584 default:
1585 /* There is no use case to stop in Inactive phase */
1586 FAIL();
1587 }
1588
1589 PASS();
1590 }
1591 #endif /* CONFIG_BT_SETTINGS */
1592
test_cli_friend_pull(void)1593 static void test_cli_friend_pull(void)
1594 {
1595 int err;
1596
1597 bt_mesh_test_cfg_set(NULL, 1000);
1598
1599 bt_mesh_test_friendship_init(1);
1600
1601 cli_pull_mode_setup();
1602
1603 bt_mesh_friend_set(BT_MESH_FEATURE_ENABLED);
1604
1605 for (int i = 1; i <= CONFIG_BT_MESH_FRIEND_LPN_COUNT; i++) {
1606
1607 ASSERT_OK_MSG(bt_mesh_test_friendship_evt_wait(BT_MESH_TEST_FRIEND_ESTABLISHED,
1608 K_SECONDS(5)),
1609 "Friendship not established");
1610 (void)target_srv_add(BLOB_CLI_ADDR + i, false);
1611 }
1612
1613 blob_cli_inputs_prepare(0);
1614
1615 err = bt_mesh_blob_cli_send(&blob_cli, &blob_cli_xfer.inputs,
1616 &blob_cli_xfer.xfer, &blob_io);
1617 if (err) {
1618 FAIL("BLOB send failed (err: %d)", err);
1619 }
1620
1621 if (k_sem_take(&blob_cli_end_sem, K_SECONDS(750))) {
1622 FAIL("End CB did not trigger as expected for the cli");
1623 }
1624
1625 ASSERT_TRUE(blob_cli.state == BT_MESH_BLOB_CLI_STATE_NONE);
1626
1627 PASS();
1628 }
1629
test_srv_lpn_pull(void)1630 static void test_srv_lpn_pull(void)
1631 {
1632 bt_mesh_test_cfg_set(NULL, 1000);
1633
1634 bt_mesh_test_friendship_init(1);
1635
1636 srv_pull_mode_setup();
1637
1638 /* This test is used to establish friendship with single lpn as well as
1639 * with many lpn devices. If legacy advertiser is used friendship with
1640 * many lpn devices is established normally due to bad precision of advertiser.
1641 * If extended advertiser is used simultaneous lpn running causes the situation
1642 * when Friend Request from several devices collide in emulated radio channel.
1643 * This shift of start moment helps to avoid Friend Request collisions.
1644 */
1645 k_sleep(K_MSEC(10 * get_device_nbr()));
1646
1647 bt_mesh_lpn_set(true);
1648
1649 ASSERT_OK_MSG(bt_mesh_test_friendship_evt_wait(BT_MESH_TEST_LPN_ESTABLISHED, K_SECONDS(5)),
1650 "LPN not established");
1651
1652 bt_mesh_blob_srv_recv(&blob_srv, 1, &blob_io, 0, 10);
1653
1654 if (k_sem_take(&blob_srv_end_sem, K_SECONDS(750))) {
1655 FAIL("End CB did not trigger as expected for the srv");
1656 }
1657
1658 ASSERT_TRUE(blob_srv.phase == BT_MESH_BLOB_XFER_PHASE_COMPLETE);
1659
1660 /* Check that all blocks is received */
1661 ASSERT_TRUE(atomic_test_bit(block_bitfield, 0));
1662 ASSERT_TRUE(atomic_test_bit(block_bitfield, 1));
1663 ASSERT_TRUE(atomic_test_bit(block_bitfield, 2));
1664
1665 PASS();
1666 }
1667
1668 #define TEST_CASE(role, name, description) \
1669 { \
1670 .test_id = "blob_" #role "_" #name, \
1671 .test_descr = description, \
1672 .test_args_f = test_args_parse, \
1673 .test_tick_f = bt_mesh_test_timeout, \
1674 .test_main_f = test_##role##_##name, \
1675 }
1676
1677 static const struct bst_test_instance test_blob[] = {
1678 TEST_CASE(cli, caps_all_rsp, "Caps procedure: All responsive targets"),
1679 TEST_CASE(cli, caps_partial_rsp, "Caps procedure: Mixed response from targets"),
1680 TEST_CASE(cli, caps_no_rsp, "Caps procedure: No response from targets"),
1681 TEST_CASE(cli, caps_cancelled, "Caps procedure: Cancel caps"),
1682 TEST_CASE(cli, broadcast_basic, "Test basic broadcast API and CBs "),
1683 TEST_CASE(cli, broadcast_trans, "Test all broadcast transmission types"),
1684 TEST_CASE(cli, broadcast_unicast_seq, "Test broadcast with unicast addr (Sequential)"),
1685 TEST_CASE(cli, broadcast_unicast, "Test broadcast with unicast addr"),
1686 TEST_CASE(cli, trans_complete, "Transfer completes successfully on client (Default: Push)"),
1687 TEST_CASE(cli, trans_resume, "Resume BLOB transfer after srv suspension (Default: Push)"),
1688 TEST_CASE(cli, fail_on_persistency, "BLOB Client doesn't give up BLOB Transfer"),
1689 TEST_CASE(cli, trans_persistency_pull, "Test transfer persistency in Pull mode"),
1690 TEST_CASE(cli, fail_on_no_rsp, "BLOB Client end transfer if no targets rsp to Xfer Get"),
1691 TEST_CASE(cli, friend_pull, "BLOB Client on friend node completes transfer in pull mode"),
1692
1693 TEST_CASE(srv, caps_standard, "Standard responsive blob server"),
1694 TEST_CASE(srv, caps_no_rsp, "Non-responsive blob server"),
1695 TEST_CASE(srv, trans_complete, "Transfer completes successfully on server"),
1696 TEST_CASE(srv, trans_resume, "Self suspending server after first received block"),
1697 TEST_CASE(srv, trans_persistency_pull, "Test transfer persistency in Pull mode"),
1698 TEST_CASE(srv, fail_on_block_start, "Server failing right before first block start msg"),
1699 TEST_CASE(srv, fail_on_block_get, "Server failing right before first block get msg"),
1700 TEST_CASE(srv, fail_on_xfer_get, "Server failing right before first xfer get msg"),
1701 TEST_CASE(srv, fail_on_nothing, "Non-failing server"),
1702 TEST_CASE(srv, lpn_pull, "BLOB Server on LPN completes transfer in pull mode"),
1703
1704 BSTEST_END_MARKER
1705 };
1706
test_blob_install(struct bst_test_list * tests)1707 struct bst_test_list *test_blob_install(struct bst_test_list *tests)
1708 {
1709 tests = bst_add_tests(tests, test_blob);
1710 return tests;
1711 }
1712
1713 #if CONFIG_BT_SETTINGS
1714 static const struct bst_test_instance test_blob_pst[] = {
1715 TEST_CASE(cli, stop,
1716 "Client expecting server to stop after reaching configured phase and continuing"),
1717 TEST_CASE(srv, stop, "Server stopping after reaching configured xfer phase"),
1718 };
1719
test_blob_pst_install(struct bst_test_list * tests)1720 struct bst_test_list *test_blob_pst_install(struct bst_test_list *tests)
1721 {
1722 tests = bst_add_tests(tests, test_blob_pst);
1723 return tests;
1724 }
1725 #endif
1726