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