1 /*
2  * Copyright (c) 2022 Nordic Semiconductor
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #include "mesh_test.h"
7 #include "mesh/dfd_srv_internal.h"
8 #include "mesh/dfu_slot.h"
9 #include "mesh/adv.h"
10 #include "mesh/dfu.h"
11 #include "mesh/blob.h"
12 #include "argparse.h"
13 #include "dfu_blob_common.h"
14 
15 #define LOG_MODULE_NAME test_dfu
16 
17 #include <zephyr/logging/log.h>
18 LOG_MODULE_REGISTER(LOG_MODULE_NAME, LOG_LEVEL_INF);
19 
20 #define WAIT_TIME 420 /* seconds */
21 #define DFU_TIMEOUT 400 /* seconds */
22 #define DIST_ADDR 0x0001
23 #define TARGET_ADDR 0x0100
24 #define IMPOSTER_MODEL_ID 0xe000
25 #define TEST_BLOB_ID 0xaabbccdd
26 
27 struct bind_params {
28 	uint16_t model_id;
29 	uint16_t addr;
30 };
31 
32 static uint8_t dev_key[16] = { 0xdd };
33 
34 static struct k_sem dfu_dist_ended;
35 static struct k_sem dfu_started;
36 static struct k_sem dfu_verifying;
37 static struct k_sem dfu_verify_failed;
38 static struct k_sem dfu_applying;
39 static struct k_sem dfu_ended;
40 
41 static struct bt_mesh_prov prov;
42 
43 static enum bt_mesh_dfu_effect dfu_target_effect;
44 static uint32_t target_fw_ver_curr = 0xDEADBEEF;
45 static uint32_t target_fw_ver_new;
46 static struct bt_mesh_dfu_img dfu_imgs[] = { {
47 	.fwid = &target_fw_ver_curr,
48 	.fwid_len = sizeof(target_fw_ver_curr),
49 } };
50 
51 static struct bt_mesh_cfg_cli cfg_cli;
52 static struct bt_mesh_sar_cfg_cli sar_cfg_cli;
53 
54 static int dfu_targets_cnt;
55 static bool dfu_fail_confirm;
56 static bool recover;
57 static bool expect_fail;
58 static enum bt_mesh_dfu_phase expected_stop_phase;
59 
test_args_parse(int argc,char * argv[])60 static void test_args_parse(int argc, char *argv[])
61 {
62 	bs_args_struct_t args_struct[] = {
63 		{
64 			.dest = &dfu_targets_cnt,
65 			.type = 'i',
66 			.name = "{targets}",
67 			.option = "targets",
68 			.descript = "Number of targets to upgrade"
69 		},
70 		{
71 			.dest = &dfu_fail_confirm,
72 			.type = 'b',
73 			.name = "{0, 1}",
74 			.option = "fail-confirm",
75 			.descript = "Request target to fail confirm step"
76 		},
77 		{
78 			.dest = &expected_stop_phase,
79 			.type = 'i',
80 			.name = "{none, start, verify, verify-ok, verify-fail, apply}",
81 			.option = "expected-phase",
82 			.descript = "Expected DFU Server phase value restored from flash"
83 		},
84 		{
85 			.dest = &recover,
86 			.type = 'b',
87 			.name = "{0, 1}",
88 			.option = "recover",
89 			.descript = "Recover DFU server phase"
90 		},
91 	};
92 
93 	bs_args_parse_all_cmd_line(argc, argv, args_struct);
94 }
95 
dummy_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)96 static int dummy_blob_chunk_wr(const struct bt_mesh_blob_io *io,
97 			 const struct bt_mesh_blob_xfer *xfer,
98 			 const struct bt_mesh_blob_block *block,
99 			 const struct bt_mesh_blob_chunk *chunk)
100 {
101 	return 0;
102 }
103 
dummy_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)104 static int dummy_blob_chunk_rd(const struct bt_mesh_blob_io *io,
105 			 const struct bt_mesh_blob_xfer *xfer,
106 			 const struct bt_mesh_blob_block *block,
107 			 const struct bt_mesh_blob_chunk *chunk)
108 {
109 	memset(chunk->data, 0, chunk->size);
110 
111 	return 0;
112 }
113 
114 static const struct bt_mesh_blob_io dummy_blob_io = {
115 	.rd = dummy_blob_chunk_rd,
116 	.wr = dummy_blob_chunk_wr,
117 };
118 
dist_fw_recv(struct bt_mesh_dfd_srv * srv,const struct bt_mesh_dfu_slot * slot,const struct bt_mesh_blob_io ** io)119 static int dist_fw_recv(struct bt_mesh_dfd_srv *srv,
120 			const struct bt_mesh_dfu_slot *slot,
121 			const struct bt_mesh_blob_io **io)
122 {
123 	*io = &dummy_blob_io;
124 
125 	return 0;
126 }
127 
dist_fw_del(struct bt_mesh_dfd_srv * srv,const struct bt_mesh_dfu_slot * slot)128 static void dist_fw_del(struct bt_mesh_dfd_srv *srv,
129 			const struct bt_mesh_dfu_slot *slot)
130 {
131 }
132 
dist_fw_send(struct bt_mesh_dfd_srv * srv,const struct bt_mesh_dfu_slot * slot,const struct bt_mesh_blob_io ** io)133 static int dist_fw_send(struct bt_mesh_dfd_srv *srv,
134 			const struct bt_mesh_dfu_slot *slot,
135 			const struct bt_mesh_blob_io **io)
136 {
137 	*io = &dummy_blob_io;
138 
139 	return 0;
140 }
141 
dist_phase_changed(struct bt_mesh_dfd_srv * srv,enum bt_mesh_dfd_phase phase)142 static void dist_phase_changed(struct bt_mesh_dfd_srv *srv, enum bt_mesh_dfd_phase phase)
143 {
144 	static enum bt_mesh_dfd_phase prev_phase;
145 
146 	if (phase == BT_MESH_DFD_PHASE_COMPLETED ||
147 	    phase == BT_MESH_DFD_PHASE_FAILED) {
148 		if (phase == BT_MESH_DFD_PHASE_FAILED) {
149 			ASSERT_EQUAL(BT_MESH_DFD_PHASE_APPLYING_UPDATE, prev_phase);
150 		}
151 
152 		k_sem_give(&dfu_dist_ended);
153 	}
154 
155 	prev_phase = phase;
156 }
157 
158 static struct bt_mesh_dfd_srv_cb dfd_srv_cb = {
159 	.recv = dist_fw_recv,
160 	.del = dist_fw_del,
161 	.send = dist_fw_send,
162 	.phase = dist_phase_changed,
163 };
164 
165 struct bt_mesh_dfd_srv dfd_srv = BT_MESH_DFD_SRV_INIT(&dfd_srv_cb);
166 
167 static struct k_sem dfu_metadata_check_sem;
168 static bool dfu_metadata_fail = true;
169 
target_metadata_check(struct bt_mesh_dfu_srv * srv,const struct bt_mesh_dfu_img * img,struct net_buf_simple * metadata_raw,enum bt_mesh_dfu_effect * effect)170 static int target_metadata_check(struct bt_mesh_dfu_srv *srv,
171 			  const struct bt_mesh_dfu_img *img,
172 			  struct net_buf_simple *metadata_raw,
173 			  enum bt_mesh_dfu_effect *effect)
174 {
175 	*effect = dfu_target_effect;
176 
177 	memcpy(&target_fw_ver_new, net_buf_simple_pull_mem(metadata_raw, sizeof(target_fw_ver_new)),
178 	       sizeof(target_fw_ver_new));
179 
180 	k_sem_give(&dfu_metadata_check_sem);
181 
182 	return dfu_metadata_fail ? 0 : -1;
183 }
184 
185 static bool expect_dfu_start = true;
186 
target_dfu_start(struct bt_mesh_dfu_srv * srv,const struct bt_mesh_dfu_img * img,struct net_buf_simple * metadata,const struct bt_mesh_blob_io ** io)187 static int target_dfu_start(struct bt_mesh_dfu_srv *srv,
188 		     const struct bt_mesh_dfu_img *img,
189 		     struct net_buf_simple *metadata,
190 		     const struct bt_mesh_blob_io **io)
191 {
192 	ASSERT_TRUE(expect_dfu_start);
193 
194 	*io = &dummy_blob_io;
195 
196 	if (expected_stop_phase == BT_MESH_DFU_PHASE_APPLYING) {
197 		return -EALREADY;
198 	}
199 
200 	return 0;
201 }
202 
203 static struct k_sem dfu_verify_sem;
204 static bool dfu_verify_fail;
205 static bool expect_dfu_xfer_end = true;
206 
target_dfu_transfer_end(struct bt_mesh_dfu_srv * srv,const struct bt_mesh_dfu_img * img,bool success)207 static void target_dfu_transfer_end(struct bt_mesh_dfu_srv *srv, const struct bt_mesh_dfu_img *img,
208 				    bool success)
209 {
210 	ASSERT_TRUE(expect_dfu_xfer_end);
211 	ASSERT_TRUE(success);
212 
213 	if (expected_stop_phase == BT_MESH_DFU_PHASE_VERIFY) {
214 		k_sem_give(&dfu_verifying);
215 		return;
216 	}
217 
218 	if (dfu_verify_fail) {
219 		bt_mesh_dfu_srv_rejected(srv);
220 		if (expected_stop_phase == BT_MESH_DFU_PHASE_VERIFY_FAIL) {
221 			k_sem_give(&dfu_verify_failed);
222 			return;
223 		}
224 	} else {
225 		bt_mesh_dfu_srv_verified(srv);
226 	}
227 
228 	k_sem_give(&dfu_verify_sem);
229 }
230 
target_dfu_recover(struct bt_mesh_dfu_srv * srv,const struct bt_mesh_dfu_img * img,const struct bt_mesh_blob_io ** io)231 static int target_dfu_recover(struct bt_mesh_dfu_srv *srv,
232 		       const struct bt_mesh_dfu_img *img,
233 		       const struct bt_mesh_blob_io **io)
234 {
235 	if (!recover) {
236 		FAIL("Not supported");
237 	}
238 
239 	*io = &dummy_blob_io;
240 
241 	return 0;
242 }
243 
244 static bool expect_dfu_apply = true;
245 
target_dfu_apply(struct bt_mesh_dfu_srv * srv,const struct bt_mesh_dfu_img * img)246 static int target_dfu_apply(struct bt_mesh_dfu_srv *srv, const struct bt_mesh_dfu_img *img)
247 {
248 	if (expected_stop_phase == BT_MESH_DFU_PHASE_VERIFY_OK) {
249 		k_sem_give(&dfu_verifying);
250 	} else if (expected_stop_phase == BT_MESH_DFU_PHASE_APPLYING) {
251 		k_sem_give(&dfu_applying);
252 		return 0;
253 	}
254 
255 	ASSERT_TRUE(expect_dfu_apply);
256 
257 	bt_mesh_dfu_srv_applied(srv);
258 
259 	k_sem_give(&dfu_ended);
260 
261 	if (dfu_fail_confirm) {
262 		/* To fail the confirm step, don't change fw version for devices that should boot
263 		 * up provisioned. Change fw version for devices that should boot up unprovisioned.
264 		 */
265 		if (dfu_target_effect == BT_MESH_DFU_EFFECT_UNPROV) {
266 			target_fw_ver_curr = target_fw_ver_new;
267 		}
268 	} else {
269 		if (dfu_target_effect == BT_MESH_DFU_EFFECT_UNPROV) {
270 			bt_mesh_reset();
271 		}
272 
273 		target_fw_ver_curr = target_fw_ver_new;
274 	}
275 
276 	return 0;
277 }
278 
279 static const struct bt_mesh_dfu_srv_cb dfu_handlers = {
280 	.check = target_metadata_check,
281 	.start = target_dfu_start,
282 	.end = target_dfu_transfer_end,
283 	.apply = target_dfu_apply,
284 	.recover = target_dfu_recover,
285 };
286 
287 static struct bt_mesh_dfu_srv dfu_srv = BT_MESH_DFU_SRV_INIT(&dfu_handlers, dfu_imgs,
288 							     ARRAY_SIZE(dfu_imgs));
289 
290 static const struct bt_mesh_comp dist_comp = {
291 	.elem =
292 		(struct bt_mesh_elem[]){
293 			BT_MESH_ELEM(1,
294 				     MODEL_LIST(BT_MESH_MODEL_CFG_SRV,
295 						BT_MESH_MODEL_CFG_CLI(&cfg_cli),
296 						BT_MESH_MODEL_SAR_CFG_SRV,
297 						BT_MESH_MODEL_SAR_CFG_CLI(&sar_cfg_cli),
298 						BT_MESH_MODEL_DFD_SRV(&dfd_srv)),
299 				     BT_MESH_MODEL_NONE),
300 		},
301 	.elem_count = 1,
302 };
303 
304 static const struct bt_mesh_comp dist_comp_self_update = {
305 	.elem =
306 		(struct bt_mesh_elem[]){
307 			BT_MESH_ELEM(1,
308 				     MODEL_LIST(BT_MESH_MODEL_CFG_SRV,
309 						BT_MESH_MODEL_CFG_CLI(&cfg_cli),
310 						BT_MESH_MODEL_SAR_CFG_SRV,
311 						BT_MESH_MODEL_SAR_CFG_CLI(&sar_cfg_cli),
312 						BT_MESH_MODEL_DFD_SRV(&dfd_srv)),
313 				     BT_MESH_MODEL_NONE),
314 			BT_MESH_ELEM(2,
315 				     MODEL_LIST(BT_MESH_MODEL_DFU_SRV(&dfu_srv)),
316 				     BT_MESH_MODEL_NONE),
317 		},
318 	.elem_count = 2,
319 };
320 
321 static const struct bt_mesh_model_op model_dummy_op[] = {
322 	BT_MESH_MODEL_OP_END
323 };
324 
325 static const struct bt_mesh_comp target_comp = {
326 	.elem =
327 		(struct bt_mesh_elem[]){
328 			BT_MESH_ELEM(1,
329 				     MODEL_LIST(BT_MESH_MODEL_CFG_SRV,
330 						BT_MESH_MODEL_CFG_CLI(&cfg_cli),
331 						BT_MESH_MODEL_SAR_CFG_SRV,
332 						BT_MESH_MODEL_SAR_CFG_CLI(&sar_cfg_cli),
333 						/* Imposter model without custom handlers is used
334 						 * so device testing persistent storage can be
335 						 * configured using both `target_comp` and
336 						 * `srv_caps_broken_comp`. If these compositions
337 						 * have different model count and order
338 						 * loading settings will fail.
339 						 */
340 						BT_MESH_MODEL_CB(IMPOSTER_MODEL_ID,
341 								 model_dummy_op, NULL, NULL, NULL),
342 						BT_MESH_MODEL_DFU_SRV(&dfu_srv)),
343 				     BT_MESH_MODEL_NONE),
344 		},
345 	.elem_count = 1,
346 };
347 
provision(uint16_t addr)348 static void provision(uint16_t addr)
349 {
350 	int err;
351 
352 	err = bt_mesh_provision(test_net_key, 0, 0, 0, addr, dev_key);
353 	if (err) {
354 		FAIL("Provisioning failed (err %d)", err);
355 		return;
356 	}
357 }
358 
common_configure(uint16_t addr)359 static void common_configure(uint16_t addr)
360 {
361 	uint8_t status;
362 	int err;
363 
364 	err = bt_mesh_cfg_cli_app_key_add(0, addr, 0, 0, test_app_key, &status);
365 	if (err || status) {
366 		FAIL("AppKey add failed (err %d, status %u)", err, status);
367 		return;
368 	}
369 }
370 
common_app_bind(uint16_t addr,struct bind_params * params,size_t num)371 static void common_app_bind(uint16_t addr, struct bind_params *params, size_t num)
372 {
373 	uint8_t status;
374 	int err;
375 
376 	for (size_t i = 0; i < num; i++) {
377 		err = bt_mesh_cfg_cli_mod_app_bind(0, addr, params[i].addr, 0, params[i].model_id,
378 						   &status);
379 		if (err || status) {
380 			FAIL("Model %#4x bind failed (err %d, status %u)", params[i].model_id,
381 			     err, status);
382 			return;
383 		}
384 	}
385 }
386 
dist_prov_and_conf(uint16_t addr)387 static void dist_prov_and_conf(uint16_t addr)
388 {
389 	provision(addr);
390 	common_configure(addr);
391 
392 	struct bind_params bind_params[] = {
393 		{ BT_MESH_MODEL_ID_BLOB_CLI, addr },
394 		{ BT_MESH_MODEL_ID_DFU_CLI, addr },
395 	};
396 
397 	common_app_bind(addr, &bind_params[0], ARRAY_SIZE(bind_params));
398 	common_sar_conf(addr);
399 }
400 
dist_self_update_prov_and_conf(uint16_t addr)401 static void dist_self_update_prov_and_conf(uint16_t addr)
402 {
403 	provision(addr);
404 	common_configure(addr);
405 
406 	struct bind_params bind_params[] = {
407 		{ BT_MESH_MODEL_ID_BLOB_CLI, addr },
408 		{ BT_MESH_MODEL_ID_DFU_CLI, addr },
409 		{ BT_MESH_MODEL_ID_BLOB_SRV, addr + 1 },
410 		{ BT_MESH_MODEL_ID_DFU_SRV, addr + 1 },
411 	};
412 
413 	common_app_bind(addr, &bind_params[0], ARRAY_SIZE(bind_params));
414 	common_sar_conf(addr);
415 }
416 
target_prov_and_conf(uint16_t addr,struct bind_params * params,size_t len)417 static void target_prov_and_conf(uint16_t addr, struct bind_params *params, size_t len)
418 {
419 	provision(addr);
420 	common_configure(addr);
421 
422 	common_app_bind(addr, params, len);
423 	common_sar_conf(addr);
424 }
425 
target_prov_and_conf_default(void)426 static void target_prov_and_conf_default(void)
427 {
428 	uint16_t addr = bt_mesh_test_own_addr_get(TARGET_ADDR);
429 	struct bind_params bind_params[] = {
430 		{ BT_MESH_MODEL_ID_BLOB_SRV, addr },
431 		{ BT_MESH_MODEL_ID_DFU_SRV, addr },
432 	};
433 
434 	target_prov_and_conf(addr, bind_params, ARRAY_SIZE(bind_params));
435 }
436 
slot_reserve_and_set(size_t size,uint8_t * fwid,size_t fwid_len,uint8_t * metadata,size_t metadata_len)437 static struct bt_mesh_dfu_slot *slot_reserve_and_set(size_t size, uint8_t *fwid, size_t fwid_len,
438 						     uint8_t *metadata, size_t metadata_len)
439 {
440 	struct bt_mesh_dfu_slot *new_slot = bt_mesh_dfu_slot_reserve();
441 
442 	if (!new_slot) {
443 		LOG_WRN("Reserving slot failed");
444 		return NULL;
445 	}
446 
447 	int err = bt_mesh_dfu_slot_fwid_set(new_slot, fwid, fwid_len);
448 
449 	if (err) {
450 		return NULL;
451 	}
452 
453 	err = bt_mesh_dfu_slot_info_set(new_slot, size, metadata, metadata_len);
454 
455 	if (err) {
456 		return NULL;
457 	}
458 
459 	return new_slot;
460 }
461 
slot_add(const struct bt_mesh_dfu_slot ** slot)462 static bool slot_add(const struct bt_mesh_dfu_slot **slot)
463 {
464 	struct bt_mesh_dfu_slot *new_slot;
465 	size_t size = 100;
466 	uint8_t fwid[CONFIG_BT_MESH_DFU_FWID_MAXLEN] = { 0xAA, 0xBB, 0xCC, 0xDD };
467 	size_t fwid_len = 4;
468 	uint8_t metadata[CONFIG_BT_MESH_DFU_METADATA_MAXLEN] = { 0xAA, 0xBB, 0xCC, 0xDD };
469 	size_t metadata_len = 4;
470 
471 	ASSERT_EQUAL(sizeof(target_fw_ver_new), fwid_len);
472 
473 	new_slot = slot_reserve_and_set(size, fwid, fwid_len, metadata, metadata_len);
474 	if (!new_slot) {
475 		return false;
476 	}
477 
478 	if (bt_mesh_dfu_slot_commit(new_slot) != 0) {
479 		return false;
480 	}
481 
482 	if (slot) {
483 		*slot = new_slot;
484 	}
485 
486 	return true;
487 }
488 
dist_dfu_start_and_confirm(void)489 static void dist_dfu_start_and_confirm(void)
490 {
491 	enum bt_mesh_dfd_status status;
492 	struct bt_mesh_dfd_start_params start_params = {
493 		.app_idx = 0,
494 		.timeout_base = 10,
495 		.slot_idx = 0,
496 		.group = 0,
497 		.xfer_mode = BT_MESH_BLOB_XFER_MODE_PUSH,
498 		.ttl = 2,
499 		.apply = true,
500 	};
501 
502 	status = bt_mesh_dfd_srv_start(&dfd_srv, &start_params);
503 	ASSERT_EQUAL(BT_MESH_DFD_SUCCESS, status);
504 
505 	if (k_sem_take(&dfu_dist_ended, K_SECONDS(DFU_TIMEOUT))) {
506 		FAIL("DFU timed out");
507 	}
508 
509 	enum bt_mesh_dfu_status expected_status;
510 	enum bt_mesh_dfu_phase expected_phase;
511 
512 	if (dfu_fail_confirm) {
513 		ASSERT_EQUAL(BT_MESH_DFD_PHASE_FAILED, dfd_srv.phase);
514 		expected_status = BT_MESH_DFU_ERR_INTERNAL;
515 		expected_phase = BT_MESH_DFU_PHASE_APPLY_FAIL;
516 	} else {
517 		ASSERT_EQUAL(BT_MESH_DFD_PHASE_COMPLETED, dfd_srv.phase);
518 		expected_status = BT_MESH_DFU_SUCCESS;
519 		expected_phase = BT_MESH_DFU_PHASE_APPLY_SUCCESS;
520 	}
521 
522 	for (int i = 0; i < dfu_targets_cnt; i++) {
523 		ASSERT_EQUAL(expected_status, dfd_srv.targets[i].status);
524 
525 		if (dfd_srv.targets[i].effect == BT_MESH_DFU_EFFECT_UNPROV) {
526 			/* If device should unprovision itself after the update, the phase won't
527 			 * change. If phase changes, DFU failed.
528 			 */
529 			if  (dfu_fail_confirm) {
530 				ASSERT_EQUAL(BT_MESH_DFU_PHASE_APPLY_FAIL,
531 					     dfd_srv.targets[i].phase);
532 			} else {
533 				ASSERT_EQUAL(BT_MESH_DFU_PHASE_APPLYING, dfd_srv.targets[i].phase);
534 			}
535 		} else {
536 			ASSERT_EQUAL(expected_phase, dfd_srv.targets[i].phase);
537 		}
538 	}
539 }
540 
test_dist_dfu(void)541 static void test_dist_dfu(void)
542 {
543 	enum bt_mesh_dfd_status status;
544 
545 	bt_mesh_test_cfg_set(NULL, WAIT_TIME);
546 	bt_mesh_device_setup(&prov, &dist_comp);
547 	dist_prov_and_conf(DIST_ADDR);
548 
549 	ASSERT_TRUE(slot_add(NULL));
550 
551 	ASSERT_TRUE(dfu_targets_cnt > 0);
552 
553 	for (int i = 0; i < dfu_targets_cnt; i++) {
554 		status = bt_mesh_dfd_srv_receiver_add(&dfd_srv, TARGET_ADDR + 1 + i, 0);
555 		ASSERT_EQUAL(BT_MESH_DFD_SUCCESS, status);
556 	}
557 
558 	dist_dfu_start_and_confirm();
559 
560 	PASS();
561 }
562 
test_dist_dfu_self_update(void)563 static void test_dist_dfu_self_update(void)
564 {
565 	enum bt_mesh_dfd_status status;
566 
567 	ASSERT_TRUE(dfu_targets_cnt > 0);
568 
569 	bt_mesh_test_cfg_set(NULL, WAIT_TIME);
570 	bt_mesh_device_setup(&prov, &dist_comp_self_update);
571 	dist_self_update_prov_and_conf(DIST_ADDR);
572 
573 	ASSERT_TRUE(slot_add(NULL));
574 
575 	status = bt_mesh_dfd_srv_receiver_add(&dfd_srv, DIST_ADDR + 1, 0);
576 	ASSERT_EQUAL(BT_MESH_DFD_SUCCESS, status);
577 	dfu_target_effect = BT_MESH_DFU_EFFECT_NONE;
578 
579 	for (int i = 1; i < dfu_targets_cnt; i++) {
580 		status = bt_mesh_dfd_srv_receiver_add(&dfd_srv, TARGET_ADDR + i, 0);
581 		ASSERT_EQUAL(BT_MESH_DFD_SUCCESS, status);
582 	}
583 
584 	dist_dfu_start_and_confirm();
585 
586 	/* Check that DFU finished on distributor. */
587 	if (k_sem_take(&dfu_ended, K_SECONDS(DFU_TIMEOUT))) {
588 		FAIL("firmware was not applied");
589 	}
590 
591 	PASS();
592 }
593 
test_dist_dfu_slot_create(void)594 static void test_dist_dfu_slot_create(void)
595 {
596 	struct bt_mesh_dfu_slot *slot[CONFIG_BT_MESH_DFU_SLOT_CNT];
597 	size_t size = 100;
598 	uint8_t fwid[CONFIG_BT_MESH_DFU_FWID_MAXLEN] = { 0 };
599 	size_t fwid_len = 4;
600 	uint8_t metadata[CONFIG_BT_MESH_DFU_METADATA_MAXLEN] = { 0 };
601 	size_t metadata_len = 4;
602 	int err, i;
603 
604 	ASSERT_TRUE_MSG(CONFIG_BT_MESH_DFU_SLOT_CNT >= 3,
605 			"CONFIG_BT_MESH_DFU_SLOT_CNT must be at least 3\n");
606 
607 	bt_mesh_test_cfg_set(NULL, WAIT_TIME);
608 	bt_mesh_device_setup(&prov, &dist_comp);
609 	dist_prov_and_conf(DIST_ADDR);
610 
611 	for (i = 0; i < CONFIG_BT_MESH_DFU_SLOT_CNT; i++) {
612 		fwid[0] = i;
613 		metadata[0] = i;
614 		slot[i] = slot_reserve_and_set(size, fwid, fwid_len, metadata, metadata_len);
615 
616 		ASSERT_FALSE_MSG(slot[i] == NULL, "Failed to add slot\n");
617 
618 		if (i > 0) {
619 			/* All but first slot are committed */
620 			err = bt_mesh_dfu_slot_commit(slot[i]);
621 			if (err) {
622 				FAIL("Committing slot failed (err %d)", err);
623 			}
624 		}
625 	}
626 
627 	/* Second slot is deleted */
628 	err = bt_mesh_dfu_slot_del(slot[1]);
629 	if (err) {
630 		FAIL("Slot delete failed (err %d)", err);
631 	}
632 
633 	PASS();
634 }
635 
check_slot(const struct bt_mesh_dfu_slot * slot,void * data)636 enum bt_mesh_dfu_iter check_slot(const struct bt_mesh_dfu_slot *slot, void *data)
637 {
638 	size_t size = 100;
639 	uint8_t fwid[CONFIG_BT_MESH_DFU_FWID_MAXLEN] = { 0 };
640 	size_t fwid_len = 4;
641 	uint8_t metadata[CONFIG_BT_MESH_DFU_METADATA_MAXLEN] = { 0 };
642 	size_t metadata_len = 4;
643 	int idx = bt_mesh_dfu_slot_img_idx_get(slot);
644 	int *i = data;
645 
646 	ASSERT_EQUAL(idx, (*i)++);
647 	ASSERT_EQUAL(size, slot->size);
648 
649 	fwid[0] = idx + 2;
650 	ASSERT_EQUAL(fwid_len, slot->fwid_len);
651 	ASSERT_TRUE(memcmp(fwid, slot->fwid, fwid_len) == 0);
652 
653 	metadata[0] = idx + 2;
654 	ASSERT_EQUAL(metadata_len, slot->metadata_len);
655 	ASSERT_TRUE(memcmp(metadata, slot->metadata, metadata_len) == 0);
656 
657 	return BT_MESH_DFU_ITER_CONTINUE;
658 }
659 
test_dist_dfu_slot_create_recover(void)660 static void test_dist_dfu_slot_create_recover(void)
661 {
662 	size_t slot_count;
663 	struct bt_mesh_dfu_slot *slot;
664 	size_t size = 100;
665 	uint8_t fwid[CONFIG_BT_MESH_DFU_FWID_MAXLEN] = { 0 };
666 	size_t fwid_len = 4;
667 	uint8_t metadata[CONFIG_BT_MESH_DFU_METADATA_MAXLEN] = { 0 };
668 	size_t metadata_len = 4;
669 	int i, idx;
670 
671 	ASSERT_TRUE_MSG(CONFIG_BT_MESH_DFU_SLOT_CNT >= 3,
672 			"CONFIG_BT_MESH_DFU_SLOT_CNT must be at least 3\n");
673 
674 	bt_mesh_test_cfg_set(NULL, WAIT_TIME);
675 	bt_mesh_device_setup(&prov, &dist_comp);
676 
677 	i = 0;
678 	slot_count = bt_mesh_dfu_slot_foreach(check_slot, &i);
679 	ASSERT_EQUAL(CONFIG_BT_MESH_DFU_SLOT_CNT - 2, slot_count);
680 
681 	for (i = 2; i < CONFIG_BT_MESH_DFU_SLOT_CNT; i++) {
682 		fwid[0] = i;
683 		idx = bt_mesh_dfu_slot_get(fwid, fwid_len, &slot);
684 		ASSERT_EQUAL(idx, i - 2);
685 		ASSERT_EQUAL(size, slot->size);
686 
687 		metadata[0] = i;
688 		ASSERT_EQUAL(metadata_len, slot->metadata_len);
689 		ASSERT_TRUE(memcmp(metadata, slot->metadata, metadata_len) == 0);
690 	}
691 
692 	PASS();
693 }
694 
check_delete_all(void)695 static void check_delete_all(void)
696 {
697 	int i;
698 	const struct bt_mesh_dfu_slot *slot;
699 	size_t slot_count;
700 
701 	ASSERT_TRUE_MSG(CONFIG_BT_MESH_DFU_SLOT_CNT >= 3,
702 			"CONFIG_BT_MESH_DFU_SLOT_CNT must be at least 3\n");
703 
704 	slot_count = bt_mesh_dfu_slot_foreach(NULL, NULL);
705 	ASSERT_EQUAL(0, slot_count);
706 
707 	for (i = 0; i < CONFIG_BT_MESH_DFU_SLOT_CNT - 1; i++) {
708 		slot = bt_mesh_dfu_slot_at(i);
709 		ASSERT_TRUE(slot == NULL);
710 	}
711 }
712 
test_dist_dfu_slot_delete_all(void)713 static void test_dist_dfu_slot_delete_all(void)
714 {
715 	ASSERT_TRUE_MSG(CONFIG_BT_MESH_DFU_SLOT_CNT >= 3,
716 			"CONFIG_BT_MESH_DFU_SLOT_CNT must be at least 3\n");
717 
718 	bt_mesh_test_cfg_set(NULL, WAIT_TIME);
719 	bt_mesh_device_setup(&prov, &dist_comp);
720 
721 	bt_mesh_dfu_slot_del_all();
722 	check_delete_all();
723 
724 	PASS();
725 }
726 
test_dist_dfu_slot_check_delete_all(void)727 static void test_dist_dfu_slot_check_delete_all(void)
728 {
729 	bt_mesh_test_cfg_set(NULL, WAIT_TIME);
730 	bt_mesh_device_setup(&prov, &dist_comp);
731 
732 	check_delete_all();
733 
734 	PASS();
735 }
736 
test_dist_dfu_slot_reservation(void)737 static void test_dist_dfu_slot_reservation(void)
738 {
739 	int i;
740 	struct bt_mesh_dfu_slot *slots[CONFIG_BT_MESH_DFU_SLOT_CNT];
741 
742 	bt_mesh_test_cfg_set(NULL, WAIT_TIME);
743 	bt_mesh_device_setup(&prov, &dist_comp);
744 
745 	for (i = 0; i < CONFIG_BT_MESH_DFU_SLOT_CNT; i++) {
746 		slots[i] = bt_mesh_dfu_slot_reserve();
747 		ASSERT_TRUE(slots[i] != NULL);
748 	}
749 
750 	ASSERT_EQUAL(NULL, bt_mesh_dfu_slot_reserve());
751 	bt_mesh_dfu_slot_release(slots[0]);
752 	/* Release twice to check idempotency with empty pool */
753 	bt_mesh_dfu_slot_release(slots[0]);
754 	ASSERT_TRUE(bt_mesh_dfu_slot_reserve() != NULL);
755 	ASSERT_EQUAL(NULL, bt_mesh_dfu_slot_reserve());
756 
757 	PASS();
758 }
759 
test_dist_dfu_slot_idempotency(void)760 static void test_dist_dfu_slot_idempotency(void)
761 {
762 	uint8_t fwid[CONFIG_BT_MESH_DFU_FWID_MAXLEN] = { 0 };
763 	size_t fwid_len = 4;
764 	struct bt_mesh_dfu_slot *slot;
765 
766 	ASSERT_TRUE_MSG(CONFIG_BT_MESH_DFU_SLOT_CNT >= 1,
767 			"CONFIG_BT_MESH_DFU_SLOT_CNT must be at least 1\n");
768 
769 	bt_mesh_test_cfg_set(NULL, WAIT_TIME);
770 	bt_mesh_device_setup(&prov, &dist_comp);
771 	dist_prov_and_conf(DIST_ADDR);
772 
773 	slot = bt_mesh_dfu_slot_reserve();
774 	ASSERT_TRUE(slot != NULL);
775 
776 	bt_mesh_dfu_slot_release(slot);
777 	bt_mesh_dfu_slot_release(slot);
778 
779 	slot = bt_mesh_dfu_slot_reserve();
780 	ASSERT_TRUE(slot != NULL);
781 
782 	ASSERT_EQUAL(0, bt_mesh_dfu_slot_fwid_set(slot, fwid, fwid_len));
783 	ASSERT_EQUAL(0, bt_mesh_dfu_slot_info_set(slot, 100, NULL, 0));
784 
785 	ASSERT_EQUAL(0, bt_mesh_dfu_slot_commit(slot));
786 	ASSERT_EQUAL(-EINVAL, bt_mesh_dfu_slot_commit(slot));
787 
788 	ASSERT_EQUAL(0, bt_mesh_dfu_slot_del(slot));
789 	ASSERT_EQUAL(-EINVAL, bt_mesh_dfu_slot_del(slot));
790 
791 	PASS();
792 }
793 
target_test_effect(enum bt_mesh_dfu_effect effect)794 static void target_test_effect(enum bt_mesh_dfu_effect effect)
795 {
796 	dfu_target_effect = effect;
797 
798 	bt_mesh_test_cfg_set(NULL, WAIT_TIME);
799 	bt_mesh_device_setup(&prov, &target_comp);
800 	target_prov_and_conf_default();
801 
802 	if (k_sem_take(&dfu_ended, K_SECONDS(DFU_TIMEOUT))) {
803 		FAIL("Firmware was not applied");
804 	}
805 }
806 
test_target_dfu_no_change(void)807 static void test_target_dfu_no_change(void)
808 {
809 	target_test_effect(BT_MESH_DFU_EFFECT_NONE);
810 
811 	PASS();
812 }
813 
test_target_dfu_new_comp_no_rpr(void)814 static void test_target_dfu_new_comp_no_rpr(void)
815 {
816 	target_test_effect(BT_MESH_DFU_EFFECT_COMP_CHANGE_NO_RPR);
817 
818 	PASS();
819 }
820 
test_target_dfu_new_comp_rpr(void)821 static void test_target_dfu_new_comp_rpr(void)
822 {
823 	target_test_effect(BT_MESH_DFU_EFFECT_COMP_CHANGE);
824 
825 	PASS();
826 }
827 
test_target_dfu_unprov(void)828 static void test_target_dfu_unprov(void)
829 {
830 	target_test_effect(BT_MESH_DFU_EFFECT_UNPROV);
831 
832 	PASS();
833 }
834 
835 static struct {
836 	struct bt_mesh_blob_cli_inputs inputs;
837 	struct bt_mesh_blob_target_pull pull[7];
838 	struct bt_mesh_dfu_target targets[7];
839 	uint8_t target_count;
840 	struct bt_mesh_dfu_cli_xfer xfer;
841 } dfu_cli_xfer;
842 
dfu_cli_inputs_prepare(uint16_t group)843 static void dfu_cli_inputs_prepare(uint16_t group)
844 {
845 	dfu_cli_xfer.inputs.ttl = BT_MESH_TTL_DEFAULT;
846 	dfu_cli_xfer.inputs.group = group;
847 	dfu_cli_xfer.inputs.app_idx = 0;
848 	dfu_cli_xfer.inputs.timeout_base = 1;
849 	sys_slist_init(&dfu_cli_xfer.inputs.targets);
850 
851 	for (int i = 0; i < dfu_cli_xfer.target_count; ++i) {
852 		/* Reset target context. */
853 		uint16_t addr = dfu_cli_xfer.targets[i].blob.addr;
854 
855 		memset(&dfu_cli_xfer.targets[i], 0, sizeof(struct bt_mesh_dfu_target));
856 		dfu_cli_xfer.targets[i].blob.addr = addr;
857 		if (recover) {
858 			memset(&dfu_cli_xfer.pull[i].missing, 1,
859 			       DIV_ROUND_UP(CONFIG_BT_MESH_BLOB_CHUNK_COUNT_MAX, 8));
860 			dfu_cli_xfer.targets[i].blob.pull = &dfu_cli_xfer.pull[i];
861 		}
862 
863 		sys_slist_append(&dfu_cli_xfer.inputs.targets, &dfu_cli_xfer.targets[i].blob.n);
864 	}
865 }
866 
target_srv_add(uint16_t addr,bool expect_lost)867 static struct bt_mesh_blob_target *target_srv_add(uint16_t addr, bool expect_lost)
868 {
869 	if (expect_lost) {
870 		lost_target_add(addr);
871 	}
872 
873 	ASSERT_TRUE(dfu_cli_xfer.target_count < ARRAY_SIZE(dfu_cli_xfer.targets));
874 	struct bt_mesh_blob_target *t = &dfu_cli_xfer.targets[dfu_cli_xfer.target_count].blob;
875 
876 	t->addr = addr;
877 	dfu_cli_xfer.target_count++;
878 	return t;
879 }
880 
dfu_cli_suspended(struct bt_mesh_dfu_cli * cli)881 static void dfu_cli_suspended(struct bt_mesh_dfu_cli *cli)
882 {
883 	FAIL("Unexpected call");
884 }
885 
dfu_cli_ended(struct bt_mesh_dfu_cli * cli,enum bt_mesh_dfu_status reason)886 static void dfu_cli_ended(struct bt_mesh_dfu_cli *cli, enum bt_mesh_dfu_status reason)
887 {
888 	if ((expected_stop_phase == BT_MESH_DFU_PHASE_IDLE ||
889 	     expected_stop_phase == BT_MESH_DFU_PHASE_VERIFY_OK) &&
890 	    !expect_fail) {
891 		ASSERT_EQUAL(BT_MESH_DFU_SUCCESS, reason);
892 	}
893 
894 	if (expected_stop_phase == BT_MESH_DFU_PHASE_TRANSFER_ACTIVE) {
895 		k_sem_give(&dfu_started);
896 	} else if (expected_stop_phase == BT_MESH_DFU_PHASE_VERIFY) {
897 		k_sem_give(&dfu_verifying);
898 	} else if (expected_stop_phase == BT_MESH_DFU_PHASE_VERIFY_FAIL) {
899 		k_sem_give(&dfu_verify_failed);
900 	}
901 
902 	k_sem_give(&dfu_ended);
903 }
904 
905 static struct k_sem dfu_cli_applied_sem;
906 
dfu_cli_applied(struct bt_mesh_dfu_cli * cli)907 static void dfu_cli_applied(struct bt_mesh_dfu_cli *cli)
908 {
909 	k_sem_give(&dfu_cli_applied_sem);
910 }
911 
912 static struct k_sem dfu_cli_confirmed_sem;
913 
dfu_cli_confirmed(struct bt_mesh_dfu_cli * cli)914 static void dfu_cli_confirmed(struct bt_mesh_dfu_cli *cli)
915 {
916 	k_sem_give(&dfu_cli_confirmed_sem);
917 }
918 
919 static struct k_sem lost_target_sem;
920 
dfu_cli_lost_target(struct bt_mesh_dfu_cli * cli,struct bt_mesh_dfu_target * target)921 static void dfu_cli_lost_target(struct bt_mesh_dfu_cli *cli, struct bt_mesh_dfu_target *target)
922 {
923 	ASSERT_FALSE(target->status == BT_MESH_DFU_SUCCESS);
924 	ASSERT_TRUE(lost_target_find_and_remove(target->blob.addr));
925 
926 	if (!lost_targets_rem()) {
927 		k_sem_give(&lost_target_sem);
928 	}
929 }
930 
931 static struct bt_mesh_dfu_cli_cb dfu_cli_cb = {
932 	.suspended = dfu_cli_suspended,
933 	.ended = dfu_cli_ended,
934 	.applied = dfu_cli_applied,
935 	.confirmed = dfu_cli_confirmed,
936 	.lost_target = dfu_cli_lost_target,
937 };
938 
939 static struct bt_mesh_dfu_cli dfu_cli = BT_MESH_DFU_CLI_INIT(&dfu_cli_cb);
940 
941 static const struct bt_mesh_comp cli_comp = {
942 	.elem =
943 		(struct bt_mesh_elem[]){
944 			BT_MESH_ELEM(1,
945 				     MODEL_LIST(BT_MESH_MODEL_CFG_SRV,
946 						BT_MESH_MODEL_CFG_CLI(&cfg_cli),
947 						BT_MESH_MODEL_SAR_CFG_SRV,
948 						BT_MESH_MODEL_SAR_CFG_CLI(&sar_cfg_cli),
949 						BT_MESH_MODEL_DFU_CLI(&dfu_cli)),
950 				     BT_MESH_MODEL_NONE),
951 		},
952 	.elem_count = 1,
953 };
954 
cli_common_fail_on_init(void)955 static void cli_common_fail_on_init(void)
956 {
957 	const struct bt_mesh_dfu_slot *slot;
958 
959 	bt_mesh_test_cfg_set(NULL, 300);
960 	bt_mesh_device_setup(&prov, &cli_comp);
961 	dist_prov_and_conf(DIST_ADDR);
962 
963 	ASSERT_TRUE(slot_add(&slot));
964 
965 	dfu_cli_inputs_prepare(0);
966 	dfu_cli_xfer.xfer.mode = BT_MESH_BLOB_XFER_MODE_PUSH;
967 	dfu_cli_xfer.xfer.slot = slot;
968 	dfu_cli_xfer.xfer.blob_id = TEST_BLOB_ID;
969 }
970 
cli_common_init_recover(void)971 static void cli_common_init_recover(void)
972 {
973 	struct bt_mesh_dfu_slot *slot;
974 	uint8_t fwid[CONFIG_BT_MESH_DFU_FWID_MAXLEN] = { 0xAA, 0xBB, 0xCC, 0xDD };
975 	size_t fwid_len = 4;
976 
977 	bt_mesh_test_cfg_set(NULL, 300);
978 	bt_mesh_device_setup(&prov, &cli_comp);
979 
980 	ASSERT_TRUE(bt_mesh_dfu_slot_get(fwid, fwid_len, &slot) >= 0);
981 
982 	dfu_cli_inputs_prepare(0);
983 	dfu_cli_xfer.xfer.mode = BT_MESH_BLOB_XFER_MODE_PUSH;
984 	dfu_cli_xfer.xfer.slot = slot;
985 	dfu_cli_xfer.xfer.blob_id = TEST_BLOB_ID;
986 }
987 
test_cli_fail_on_persistency(void)988 static void test_cli_fail_on_persistency(void)
989 {
990 	int err;
991 
992 	/** Test that DFU transfer persists as long as at least one target is still active. During
993 	 * the test multiple servers will become unresponsive at different phases of the transfer:
994 	 * - Srv 0x0002 will reject firmware by metadata.
995 	 * - Srv 0x0003 will not respond to BLOB Information Get msg (Retrieve Caps proc).
996 	 * - Srv 0x0004 will not respond to Firmware Update Get msg after BLOB Transfer.
997 	 * - Srv 0x0005 will fail firmware verification.
998 	 * - Srv 0x0006 will not respond to Firmware Update Apply msg.
999 	 * - Srv 0x0007 is responsive all the way.
1000 	 * - Srv 0x0008 is a non-existing unresponsive node that will not respond to Firmware
1001 	 *   Update Start msg, which is the first message sent by DFU Client.
1002 	 */
1003 	(void)target_srv_add(TARGET_ADDR + 1, true);
1004 	(void)target_srv_add(TARGET_ADDR + 2, true);
1005 	(void)target_srv_add(TARGET_ADDR + 3, true);
1006 	(void)target_srv_add(TARGET_ADDR + 4, true);
1007 	(void)target_srv_add(TARGET_ADDR + 5, true);
1008 	(void)target_srv_add(TARGET_ADDR + 6, false);
1009 	(void)target_srv_add(TARGET_ADDR + 7, true);
1010 
1011 	cli_common_fail_on_init();
1012 
1013 	err = bt_mesh_dfu_cli_send(&dfu_cli, &dfu_cli_xfer.inputs, &dummy_blob_io,
1014 				   &dfu_cli_xfer.xfer);
1015 	if (err) {
1016 		FAIL("DFU Client send failed (err: %d)", err);
1017 	}
1018 
1019 	if (k_sem_take(&dfu_ended, K_SECONDS(200))) {
1020 		FAIL("Firmware transfer failed");
1021 	}
1022 
1023 	/* This is non-existing unresponsive target that didn't reply on Firmware Update Start
1024 	 * message.
1025 	 */
1026 	ASSERT_EQUAL(BT_MESH_DFU_ERR_INTERNAL, dfu_cli_xfer.targets[6].status);
1027 	ASSERT_EQUAL(BT_MESH_DFU_PHASE_UNKNOWN, dfu_cli_xfer.targets[6].phase);
1028 	/* This target rejected metadata. */
1029 	ASSERT_EQUAL(BT_MESH_DFU_ERR_METADATA, dfu_cli_xfer.targets[0].status);
1030 	ASSERT_EQUAL(BT_MESH_DFU_PHASE_IDLE, dfu_cli_xfer.targets[0].phase);
1031 	/* This target shouldn't respond on BLOB Information Get message from Retrieve Caps
1032 	 * procedure.
1033 	 */
1034 	ASSERT_EQUAL(BT_MESH_DFU_ERR_INTERNAL, dfu_cli_xfer.targets[1].status);
1035 	ASSERT_EQUAL(BT_MESH_DFU_PHASE_TRANSFER_ACTIVE, dfu_cli_xfer.targets[1].phase);
1036 	/* This target shouldn't respond on Firmware Update Get msg. */
1037 	ASSERT_EQUAL(BT_MESH_DFU_ERR_INTERNAL, dfu_cli_xfer.targets[2].status);
1038 	ASSERT_EQUAL(BT_MESH_DFU_PHASE_TRANSFER_ACTIVE, dfu_cli_xfer.targets[2].phase);
1039 	/* This target failed firmware verification. */
1040 	ASSERT_EQUAL(BT_MESH_DFU_ERR_WRONG_PHASE, dfu_cli_xfer.targets[3].status);
1041 	ASSERT_EQUAL(BT_MESH_DFU_PHASE_VERIFY_FAIL, dfu_cli_xfer.targets[3].phase);
1042 	/* The next two targets should be OK. */
1043 	ASSERT_EQUAL(BT_MESH_DFU_SUCCESS, dfu_cli_xfer.targets[4].status);
1044 	ASSERT_EQUAL(BT_MESH_DFU_PHASE_VERIFY_OK, dfu_cli_xfer.targets[4].phase);
1045 	ASSERT_EQUAL(BT_MESH_DFU_SUCCESS, dfu_cli_xfer.targets[5].status);
1046 	ASSERT_EQUAL(BT_MESH_DFU_PHASE_VERIFY_OK, dfu_cli_xfer.targets[5].phase);
1047 
1048 	err = bt_mesh_dfu_cli_apply(&dfu_cli);
1049 	if (err) {
1050 		FAIL("DFU Client apply failed (err: %d)", err);
1051 	}
1052 
1053 	if (k_sem_take(&dfu_cli_applied_sem, K_SECONDS(200))) {
1054 		FAIL("Failed to apply firmware");
1055 	}
1056 
1057 	/* This target shouldn't respond on Firmware Update Apply message. */
1058 	ASSERT_EQUAL(BT_MESH_DFU_ERR_INTERNAL, dfu_cli_xfer.targets[4].status);
1059 	ASSERT_EQUAL(BT_MESH_DFU_PHASE_VERIFY_OK, dfu_cli_xfer.targets[4].phase);
1060 
1061 	err = bt_mesh_dfu_cli_confirm(&dfu_cli);
1062 	if (err) {
1063 		FAIL("DFU Client confirm failed (err: %d)", err);
1064 	}
1065 
1066 	if (k_sem_take(&dfu_cli_confirmed_sem, K_SECONDS(200))) {
1067 		FAIL("Failed to confirm firmware");
1068 	}
1069 
1070 	/* This target should complete DFU successfully. */
1071 	ASSERT_EQUAL(BT_MESH_DFU_SUCCESS, dfu_cli_xfer.targets[5].status);
1072 	ASSERT_EQUAL(BT_MESH_DFU_PHASE_APPLY_SUCCESS, dfu_cli_xfer.targets[5].phase);
1073 
1074 	if (k_sem_take(&lost_target_sem, K_NO_WAIT)) {
1075 		FAIL("Lost targets CB did not trigger for all expected lost targets");
1076 	}
1077 
1078 	PASS();
1079 }
1080 
test_cli_all_targets_lost_common(void)1081 static void test_cli_all_targets_lost_common(void)
1082 {
1083 	int err, i;
1084 
1085 	expect_fail = true;
1086 
1087 	for (i = 1; i <= dfu_targets_cnt; i++) {
1088 		(void)target_srv_add(TARGET_ADDR + i, true);
1089 	}
1090 
1091 	cli_common_fail_on_init();
1092 
1093 	err = bt_mesh_dfu_cli_send(&dfu_cli, &dfu_cli_xfer.inputs, &dummy_blob_io,
1094 				   &dfu_cli_xfer.xfer);
1095 	if (err) {
1096 		FAIL("DFU Client send failed (err: %d)", err);
1097 	}
1098 
1099 	if (k_sem_take(&dfu_ended, K_SECONDS(200))) {
1100 		FAIL("Firmware transfer failed");
1101 	}
1102 }
1103 
test_cli_all_targets_lost_on_metadata(void)1104 static void test_cli_all_targets_lost_on_metadata(void)
1105 {
1106 	int i;
1107 
1108 	test_cli_all_targets_lost_common();
1109 
1110 	for (i = 0; i < dfu_targets_cnt; i++) {
1111 		ASSERT_EQUAL(BT_MESH_DFU_ERR_METADATA, dfu_cli_xfer.targets[i].status);
1112 		ASSERT_EQUAL(BT_MESH_DFU_PHASE_IDLE, dfu_cli_xfer.targets[i].phase);
1113 	}
1114 
1115 	/* `lost_target` cb must be called on all targets */
1116 	ASSERT_EQUAL(0, lost_targets_rem());
1117 
1118 	PASS();
1119 }
1120 
test_cli_all_targets_lost_on_caps_get(void)1121 static void test_cli_all_targets_lost_on_caps_get(void)
1122 {
1123 	int i;
1124 
1125 	test_cli_all_targets_lost_common();
1126 
1127 	for (i = 0; i < dfu_targets_cnt; i++) {
1128 		ASSERT_EQUAL(BT_MESH_DFU_ERR_INTERNAL, dfu_cli_xfer.targets[i].status);
1129 		ASSERT_EQUAL(BT_MESH_DFU_PHASE_TRANSFER_ACTIVE,
1130 			     dfu_cli_xfer.targets[i].phase);
1131 	}
1132 
1133 	/* `lost_target` cb must be called on all targets */
1134 	ASSERT_EQUAL(0, lost_targets_rem());
1135 
1136 	PASS();
1137 }
1138 
test_cli_all_targets_lost_on_update_get(void)1139 static void test_cli_all_targets_lost_on_update_get(void)
1140 {
1141 	int i;
1142 
1143 	test_cli_all_targets_lost_common();
1144 
1145 	for (i = 0; i < dfu_targets_cnt; i++) {
1146 		ASSERT_EQUAL(BT_MESH_DFU_ERR_INTERNAL, dfu_cli_xfer.targets[i].status);
1147 		ASSERT_EQUAL(BT_MESH_DFU_PHASE_TRANSFER_ACTIVE,
1148 			     dfu_cli_xfer.targets[i].phase);
1149 	}
1150 
1151 	/* `lost_target` cb must be called on all targets */
1152 	ASSERT_EQUAL(0, lost_targets_rem());
1153 
1154 	PASS();
1155 }
1156 
test_cli_all_targets_lost_on_verify(void)1157 static void test_cli_all_targets_lost_on_verify(void)
1158 {
1159 	int i;
1160 
1161 	test_cli_all_targets_lost_common();
1162 
1163 	for (i = 0; i < dfu_targets_cnt; i++) {
1164 		ASSERT_EQUAL(BT_MESH_DFU_ERR_WRONG_PHASE, dfu_cli_xfer.targets[i].status);
1165 		ASSERT_EQUAL(BT_MESH_DFU_PHASE_VERIFY_FAIL, dfu_cli_xfer.targets[i].phase);
1166 	}
1167 
1168 	/* `lost_target` cb must be called on all targets */
1169 	ASSERT_EQUAL(0, lost_targets_rem());
1170 
1171 	PASS();
1172 }
1173 
test_cli_all_targets_lost_on_apply(void)1174 static void test_cli_all_targets_lost_on_apply(void)
1175 {
1176 	int err, i;
1177 
1178 	test_cli_all_targets_lost_common();
1179 
1180 	for (i = 0; i < dfu_targets_cnt; i++) {
1181 		ASSERT_EQUAL(BT_MESH_DFU_SUCCESS, dfu_cli_xfer.targets[i].status);
1182 		ASSERT_EQUAL(BT_MESH_DFU_PHASE_VERIFY_OK, dfu_cli_xfer.targets[i].phase);
1183 	}
1184 
1185 	err = bt_mesh_dfu_cli_apply(&dfu_cli);
1186 	if (err) {
1187 		FAIL("DFU Client apply failed (err: %d)", err);
1188 	}
1189 
1190 	if (!k_sem_take(&dfu_cli_applied_sem, K_SECONDS(200))) {
1191 		FAIL("Apply should not be successful on any target");
1192 	}
1193 
1194 	for (i = 0; i < dfu_targets_cnt; i++) {
1195 		ASSERT_EQUAL(BT_MESH_DFU_ERR_INTERNAL, dfu_cli_xfer.targets[i].status);
1196 		ASSERT_EQUAL(BT_MESH_DFU_PHASE_VERIFY_OK, dfu_cli_xfer.targets[i].phase);
1197 	}
1198 
1199 	/* `lost_target` cb must be called on all targets */
1200 	ASSERT_EQUAL(0, lost_targets_rem());
1201 
1202 	PASS();
1203 }
1204 
test_cli_stop(void)1205 static void test_cli_stop(void)
1206 {
1207 	int err;
1208 
1209 	(void)target_srv_add(TARGET_ADDR + 1, true);
1210 
1211 	switch (expected_stop_phase) {
1212 	case BT_MESH_DFU_PHASE_TRANSFER_ACTIVE:
1213 		cli_common_fail_on_init();
1214 
1215 		err = bt_mesh_dfu_cli_send(&dfu_cli, &dfu_cli_xfer.inputs, &dummy_blob_io,
1216 					   &dfu_cli_xfer.xfer);
1217 		if (err) {
1218 			FAIL("DFU Client send failed (err: %d)", err);
1219 		}
1220 
1221 		if (k_sem_take(&dfu_started, K_SECONDS(200))) {
1222 			FAIL("Firmware transfer failed");
1223 		}
1224 
1225 		ASSERT_EQUAL(BT_MESH_DFU_ERR_INTERNAL, dfu_cli_xfer.targets[0].status);
1226 		ASSERT_EQUAL(BT_MESH_DFU_PHASE_TRANSFER_ACTIVE, dfu_cli_xfer.targets[0].phase);
1227 		break;
1228 	case BT_MESH_DFU_PHASE_VERIFY:
1229 		cli_common_init_recover();
1230 
1231 		err = bt_mesh_dfu_cli_send(&dfu_cli, &dfu_cli_xfer.inputs, &dummy_blob_io,
1232 					   &dfu_cli_xfer.xfer);
1233 		if (err) {
1234 			FAIL("DFU Client resume failed (err: %d)", err);
1235 		}
1236 
1237 		if (k_sem_take(&dfu_verifying, K_SECONDS(200))) {
1238 			FAIL("Firmware transfer failed");
1239 		}
1240 		ASSERT_EQUAL(BT_MESH_DFU_ERR_INTERNAL, dfu_cli_xfer.targets[0].status);
1241 		ASSERT_EQUAL(BT_MESH_DFU_PHASE_VERIFY, dfu_cli_xfer.targets[0].phase);
1242 
1243 		break;
1244 	case BT_MESH_DFU_PHASE_VERIFY_OK:
1245 		/* Nothing to do here on distributor side, target must verify image */
1246 		break;
1247 	case BT_MESH_DFU_PHASE_VERIFY_FAIL:
1248 		cli_common_fail_on_init();
1249 
1250 		err = bt_mesh_dfu_cli_send(&dfu_cli, &dfu_cli_xfer.inputs, &dummy_blob_io,
1251 					   &dfu_cli_xfer.xfer);
1252 		if (err) {
1253 			FAIL("DFU Client send failed (err: %d)", err);
1254 		}
1255 
1256 		if (k_sem_take(&dfu_verify_failed, K_SECONDS(200))) {
1257 			FAIL("Firmware transfer failed");
1258 		}
1259 
1260 		ASSERT_EQUAL(BT_MESH_DFU_ERR_WRONG_PHASE, dfu_cli_xfer.targets[0].status);
1261 		ASSERT_EQUAL(BT_MESH_DFU_PHASE_VERIFY_FAIL, dfu_cli_xfer.targets[0].phase);
1262 		break;
1263 	case BT_MESH_DFU_PHASE_APPLYING:
1264 		cli_common_init_recover();
1265 
1266 		err = bt_mesh_dfu_cli_send(&dfu_cli, &dfu_cli_xfer.inputs, &dummy_blob_io,
1267 					   &dfu_cli_xfer.xfer);
1268 
1269 		if (err) {
1270 			FAIL("DFU Client send failed (err: %d)", err);
1271 		}
1272 		if (k_sem_take(&dfu_ended, K_SECONDS(200))) {
1273 			FAIL("Firmware transfer failed");
1274 		}
1275 
1276 		bt_mesh_dfu_cli_apply(&dfu_cli);
1277 		if (k_sem_take(&dfu_cli_applied_sem, K_SECONDS(200))) {
1278 			/* This will time out as target will reboot before applying */
1279 		}
1280 		ASSERT_EQUAL(BT_MESH_DFU_ERR_INTERNAL, dfu_cli_xfer.targets[0].status);
1281 		ASSERT_EQUAL(BT_MESH_DFU_PHASE_APPLYING, dfu_cli_xfer.targets[0].phase);
1282 		break;
1283 	case BT_MESH_DFU_PHASE_APPLY_SUCCESS:
1284 		cli_common_init_recover();
1285 
1286 		dfu_cli.xfer.state = 5;
1287 		dfu_cli.xfer.slot = dfu_cli_xfer.xfer.slot;
1288 		dfu_cli.xfer.blob.id = TEST_BLOB_ID;
1289 		dfu_cli_xfer.xfer.mode = BT_MESH_BLOB_XFER_MODE_PUSH;
1290 
1291 		dfu_cli.blob.inputs = &dfu_cli_xfer.inputs;
1292 
1293 		err = bt_mesh_dfu_cli_confirm(&dfu_cli);
1294 		if (err) {
1295 			FAIL("DFU Client confirm failed (err: %d)", err);
1296 		}
1297 
1298 		ASSERT_EQUAL(BT_MESH_DFU_SUCCESS, dfu_cli_xfer.targets[0].status);
1299 		ASSERT_EQUAL(BT_MESH_DFU_PHASE_IDLE, dfu_cli_xfer.targets[0].phase);
1300 
1301 		PASS();
1302 		break;
1303 	default:
1304 		break;
1305 	}
1306 	PASS();
1307 }
1308 
1309 static struct k_sem caps_get_sem;
1310 
mock_handle_caps_get(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1311 static int mock_handle_caps_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
1312 				struct net_buf_simple *buf)
1313 {
1314 	LOG_WRN("Rejecting BLOB Information Get message");
1315 
1316 	k_sem_give(&caps_get_sem);
1317 
1318 	return 0;
1319 }
1320 
1321 static const struct bt_mesh_model_op model_caps_op1[] = {
1322 	{ BT_MESH_BLOB_OP_INFO_GET, 0, mock_handle_caps_get },
1323 	BT_MESH_MODEL_OP_END
1324 };
1325 
1326 static const struct bt_mesh_comp srv_caps_broken_comp = {
1327 	.elem =
1328 		(struct bt_mesh_elem[]){
1329 			BT_MESH_ELEM(1,
1330 				     MODEL_LIST(BT_MESH_MODEL_CFG_SRV,
1331 						BT_MESH_MODEL_CFG_CLI(&cfg_cli),
1332 						BT_MESH_MODEL_SAR_CFG_SRV,
1333 						BT_MESH_MODEL_SAR_CFG_CLI(&sar_cfg_cli),
1334 						BT_MESH_MODEL_CB(IMPOSTER_MODEL_ID,
1335 								 model_caps_op1, NULL, NULL, NULL),
1336 						BT_MESH_MODEL_DFU_SRV(&dfu_srv)),
1337 				     BT_MESH_MODEL_NONE),
1338 		},
1339 	.elem_count = 1,
1340 };
1341 
mock_handle_chunks(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1342 static int mock_handle_chunks(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
1343 				struct net_buf_simple *buf)
1344 {
1345 	LOG_WRN("Skipping receiving block");
1346 
1347 	k_sem_give(&dfu_started);
1348 
1349 	return 0;
1350 }
1351 
1352 static const struct bt_mesh_model_op model_caps_op2[] = {
1353 	{ BT_MESH_BLOB_OP_CHUNK, 0, mock_handle_chunks },
1354 	BT_MESH_MODEL_OP_END
1355 };
1356 
1357 static const struct bt_mesh_comp broken_target_comp = {
1358 	.elem =
1359 		(struct bt_mesh_elem[]){
1360 			BT_MESH_ELEM(1,
1361 				     MODEL_LIST(BT_MESH_MODEL_CFG_SRV,
1362 						BT_MESH_MODEL_CFG_CLI(&cfg_cli),
1363 						BT_MESH_MODEL_SAR_CFG_SRV,
1364 						BT_MESH_MODEL_SAR_CFG_CLI(&sar_cfg_cli),
1365 						BT_MESH_MODEL_CB(IMPOSTER_MODEL_ID,
1366 								 model_caps_op2, NULL, NULL, NULL),
1367 						BT_MESH_MODEL_DFU_SRV(&dfu_srv)),
1368 				     BT_MESH_MODEL_NONE),
1369 		},
1370 	.elem_count = 1,
1371 };
1372 
1373 static struct k_sem update_get_sem;
1374 
mock_handle_update_get(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1375 static int mock_handle_update_get(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
1376 				  struct net_buf_simple *buf)
1377 {
1378 	LOG_WRN("Rejecting Firmware Update Get message");
1379 	k_sem_give(&update_get_sem);
1380 
1381 	return 0;
1382 }
1383 
1384 static const struct bt_mesh_model_op model_update_get_op1[] = {
1385 	{ BT_MESH_DFU_OP_UPDATE_GET, 0, mock_handle_update_get },
1386 	BT_MESH_MODEL_OP_END
1387 };
1388 
1389 static const struct bt_mesh_comp srv_update_get_broken_comp = {
1390 	.elem =
1391 		(struct bt_mesh_elem[]){
1392 			BT_MESH_ELEM(1,
1393 				     MODEL_LIST(BT_MESH_MODEL_CFG_SRV,
1394 						BT_MESH_MODEL_CFG_CLI(&cfg_cli),
1395 						BT_MESH_MODEL_SAR_CFG_SRV,
1396 						BT_MESH_MODEL_SAR_CFG_CLI(&sar_cfg_cli),
1397 						BT_MESH_MODEL_CB(IMPOSTER_MODEL_ID,
1398 								 model_update_get_op1, NULL, NULL,
1399 								 NULL),
1400 						BT_MESH_MODEL_DFU_SRV(&dfu_srv)),
1401 				     BT_MESH_MODEL_NONE),
1402 		},
1403 	.elem_count = 1,
1404 };
1405 
1406 static struct k_sem update_apply_sem;
1407 
mock_handle_update_apply(struct bt_mesh_model * model,struct bt_mesh_msg_ctx * ctx,struct net_buf_simple * buf)1408 static int mock_handle_update_apply(struct bt_mesh_model *model, struct bt_mesh_msg_ctx *ctx,
1409 				    struct net_buf_simple *buf)
1410 {
1411 	LOG_WRN("Rejecting Firmware Update Apply message");
1412 	k_sem_give(&update_apply_sem);
1413 
1414 	return 0;
1415 }
1416 
1417 static const struct bt_mesh_model_op model_update_apply_op1[] = {
1418 	{ BT_MESH_DFU_OP_UPDATE_APPLY, 0, mock_handle_update_apply },
1419 	BT_MESH_MODEL_OP_END
1420 };
1421 
1422 static const struct bt_mesh_comp srv_update_apply_broken_comp = {
1423 	.elem =
1424 		(struct bt_mesh_elem[]){
1425 			BT_MESH_ELEM(1,
1426 				     MODEL_LIST(BT_MESH_MODEL_CFG_SRV,
1427 						BT_MESH_MODEL_CFG_CLI(&cfg_cli),
1428 						BT_MESH_MODEL_SAR_CFG_SRV,
1429 						BT_MESH_MODEL_SAR_CFG_CLI(&sar_cfg_cli),
1430 						BT_MESH_MODEL_CB(IMPOSTER_MODEL_ID,
1431 								 model_update_apply_op1, NULL,
1432 								 NULL, NULL),
1433 						BT_MESH_MODEL_DFU_SRV(&dfu_srv)),
1434 				     BT_MESH_MODEL_NONE),
1435 		},
1436 	.elem_count = 1,
1437 };
1438 
target_prov_and_conf_with_imposer(void)1439 static void target_prov_and_conf_with_imposer(void)
1440 {
1441 	uint16_t addr = bt_mesh_test_own_addr_get(TARGET_ADDR);
1442 	struct bind_params bind_params[] = {
1443 		{ BT_MESH_MODEL_ID_BLOB_SRV, addr },
1444 		{ BT_MESH_MODEL_ID_DFU_SRV, addr },
1445 		{ IMPOSTER_MODEL_ID, addr },
1446 	};
1447 
1448 	target_prov_and_conf(addr, bind_params, ARRAY_SIZE(bind_params));
1449 }
1450 
common_fail_on_target_init(const struct bt_mesh_comp * comp)1451 static void common_fail_on_target_init(const struct bt_mesh_comp *comp)
1452 {
1453 	bt_mesh_test_cfg_set(NULL, 300);
1454 	bt_mesh_device_setup(&prov, comp);
1455 
1456 	dfu_target_effect = BT_MESH_DFU_EFFECT_NONE;
1457 }
1458 
test_target_fail_on_metadata(void)1459 static void test_target_fail_on_metadata(void)
1460 {
1461 	dfu_metadata_fail = false;
1462 	expect_dfu_start = false;
1463 
1464 	common_fail_on_target_init(&target_comp);
1465 	target_prov_and_conf_default();
1466 
1467 	if (k_sem_take(&dfu_metadata_check_sem, K_SECONDS(200))) {
1468 		FAIL("Metadata check CB wasn't called");
1469 	}
1470 
1471 	PASS();
1472 }
1473 
test_target_fail_on_caps_get(void)1474 static void test_target_fail_on_caps_get(void)
1475 {
1476 	expect_dfu_xfer_end = false;
1477 
1478 	common_fail_on_target_init(&srv_caps_broken_comp);
1479 	target_prov_and_conf_with_imposer();
1480 
1481 	if (k_sem_take(&caps_get_sem, K_SECONDS(200))) {
1482 		FAIL("BLOB Info Get msg handler wasn't called");
1483 	}
1484 
1485 	PASS();
1486 }
1487 
test_target_fail_on_update_get(void)1488 static void test_target_fail_on_update_get(void)
1489 {
1490 	expect_dfu_apply = false;
1491 
1492 	common_fail_on_target_init(&srv_update_get_broken_comp);
1493 	target_prov_and_conf_with_imposer();
1494 
1495 	if (k_sem_take(&dfu_verify_sem, K_SECONDS(200))) {
1496 		FAIL("Transfer end CB wasn't triggered");
1497 	}
1498 
1499 	if (k_sem_take(&update_get_sem, K_SECONDS(200))) {
1500 		FAIL("Firmware Update Get msg handler wasn't called");
1501 	}
1502 
1503 	PASS();
1504 }
1505 
test_target_fail_on_verify(void)1506 static void test_target_fail_on_verify(void)
1507 {
1508 	dfu_verify_fail = true;
1509 	expect_dfu_apply = false;
1510 
1511 	common_fail_on_target_init(&target_comp);
1512 	target_prov_and_conf_default();
1513 
1514 	if (k_sem_take(&dfu_verify_sem, K_SECONDS(200))) {
1515 		FAIL("Transfer end CB wasn't triggered");
1516 	}
1517 
1518 	PASS();
1519 }
1520 
test_target_fail_on_apply(void)1521 static void test_target_fail_on_apply(void)
1522 {
1523 	expect_dfu_apply = false;
1524 
1525 	common_fail_on_target_init(&srv_update_apply_broken_comp);
1526 	target_prov_and_conf_with_imposer();
1527 
1528 	if (k_sem_take(&update_apply_sem, K_SECONDS(200))) {
1529 		FAIL("Firmware Update Apply msg handler wasn't called");
1530 	}
1531 
1532 	PASS();
1533 }
1534 
test_target_fail_on_nothing(void)1535 static void test_target_fail_on_nothing(void)
1536 {
1537 	common_fail_on_target_init(&target_comp);
1538 	target_prov_and_conf_default();
1539 
1540 	if (k_sem_take(&dfu_ended, K_SECONDS(200))) {
1541 		FAIL("DFU failed");
1542 	}
1543 
1544 	PASS();
1545 }
1546 
test_target_dfu_stop(void)1547 static void test_target_dfu_stop(void)
1548 {
1549 	dfu_target_effect = BT_MESH_DFU_EFFECT_NONE;
1550 
1551 	if (!recover) {
1552 		bt_mesh_test_cfg_set(NULL, WAIT_TIME);
1553 
1554 		common_fail_on_target_init(expected_stop_phase == BT_MESH_DFU_PHASE_VERIFY_FAIL ?
1555 					   &target_comp : &broken_target_comp);
1556 		target_prov_and_conf_with_imposer();
1557 
1558 		if (expected_stop_phase == BT_MESH_DFU_PHASE_VERIFY_FAIL) {
1559 			dfu_verify_fail = true;
1560 			if (k_sem_take(&dfu_verify_failed, K_SECONDS(DFU_TIMEOUT))) {
1561 				FAIL("Phase not reached");
1562 			}
1563 		} else {
1564 			/* Stop at BT_MESH_DFU_PHASE_TRANSFER_ACTIVE */
1565 			if (k_sem_take(&dfu_started, K_SECONDS(DFU_TIMEOUT))) {
1566 				FAIL("Phase not reached");
1567 			}
1568 		}
1569 
1570 		ASSERT_EQUAL(expected_stop_phase, dfu_srv.update.phase);
1571 		PASS();
1572 		return;
1573 	}
1574 
1575 	bt_mesh_device_setup(&prov, &target_comp);
1576 	bt_mesh_test_cfg_set(NULL, WAIT_TIME);
1577 
1578 	switch (expected_stop_phase) {
1579 	case BT_MESH_DFU_PHASE_VERIFY:
1580 		ASSERT_EQUAL(BT_MESH_DFU_PHASE_TRANSFER_ERR, dfu_srv.update.phase);
1581 		if (k_sem_take(&dfu_verifying, K_SECONDS(DFU_TIMEOUT))) {
1582 			FAIL("Phase not reached");
1583 		}
1584 		ASSERT_EQUAL(BT_MESH_DFU_PHASE_VERIFY, dfu_srv.update.phase);
1585 		break;
1586 	case BT_MESH_DFU_PHASE_VERIFY_OK:
1587 		ASSERT_EQUAL(BT_MESH_DFU_PHASE_VERIFY, dfu_srv.update.phase);
1588 		bt_mesh_dfu_srv_verified(&dfu_srv);
1589 		ASSERT_EQUAL(BT_MESH_DFU_PHASE_VERIFY_OK, dfu_srv.update.phase);
1590 		break;
1591 	case BT_MESH_DFU_PHASE_APPLYING:
1592 		ASSERT_EQUAL(BT_MESH_DFU_PHASE_VERIFY_FAIL, dfu_srv.update.phase);
1593 		if (k_sem_take(&dfu_applying, K_SECONDS(DFU_TIMEOUT))) {
1594 			FAIL("Phase not reached");
1595 		}
1596 		ASSERT_EQUAL(BT_MESH_DFU_PHASE_APPLYING, dfu_srv.update.phase);
1597 		break;
1598 	case BT_MESH_DFU_PHASE_APPLY_SUCCESS:
1599 		ASSERT_EQUAL(BT_MESH_DFU_PHASE_APPLYING, dfu_srv.update.phase);
1600 		bt_mesh_dfu_srv_applied(&dfu_srv);
1601 		ASSERT_EQUAL(BT_MESH_DFU_PHASE_IDLE, dfu_srv.update.phase);
1602 		break;
1603 	default:
1604 		FAIL("Wrong expected phase");
1605 		break;
1606 	}
1607 
1608 	ASSERT_EQUAL(0, dfu_srv.update.idx);
1609 	PASS();
1610 }
1611 
test_pre_init(void)1612 static void test_pre_init(void)
1613 {
1614 	k_sem_init(&dfu_dist_ended, 0, 1);
1615 	k_sem_init(&dfu_ended, 0, 1);
1616 	k_sem_init(&caps_get_sem, 0, 1);
1617 	k_sem_init(&update_get_sem, 0, 1);
1618 	k_sem_init(&update_apply_sem, 0, 1);
1619 	k_sem_init(&dfu_metadata_check_sem, 0, 1);
1620 	k_sem_init(&dfu_verify_sem, 0, 1);
1621 	k_sem_init(&dfu_cli_applied_sem, 0, 1);
1622 	k_sem_init(&dfu_cli_confirmed_sem, 0, 1);
1623 	k_sem_init(&lost_target_sem, 0, 1);
1624 	k_sem_init(&dfu_started, 0, 1);
1625 	k_sem_init(&dfu_verifying, 0, 1);
1626 	k_sem_init(&dfu_verify_failed, 0, 1);
1627 	k_sem_init(&dfu_applying, 0, 1);
1628 }
1629 
1630 #define TEST_CASE(role, name, description)                     \
1631 	{                                                      \
1632 		.test_id = "dfu_" #role "_" #name,             \
1633 		.test_descr = description,                     \
1634 		.test_pre_init_f = test_pre_init,              \
1635 		.test_args_f = test_args_parse,                \
1636 		.test_tick_f = bt_mesh_test_timeout,           \
1637 		.test_main_f = test_##role##_##name,           \
1638 	}
1639 
1640 static const struct bst_test_instance test_dfu[] = {
1641 	TEST_CASE(dist, dfu, "Distributor performs DFU"),
1642 	TEST_CASE(dist, dfu_self_update, "Distributor performs DFU with self update"),
1643 	TEST_CASE(dist, dfu_slot_create, "Distributor creates image slots"),
1644 	TEST_CASE(dist, dfu_slot_create_recover,
1645 		      "Distributor recovers created image slots from persitent storage"),
1646 	TEST_CASE(dist, dfu_slot_delete_all, "Distributor deletes all image slots"),
1647 	TEST_CASE(dist, dfu_slot_check_delete_all,
1648 		      "Distributor checks if all slots are removed from persistent storage"),
1649 	TEST_CASE(dist, dfu_slot_reservation,
1650 		      "Distributor checks that the correct number of slots can be reserved"),
1651 	TEST_CASE(dist, dfu_slot_idempotency,
1652 		      "Distributor checks that the the DFU slot APIs are idempotent"),
1653 	TEST_CASE(cli, stop, "DFU Client stops at configured point of Firmware Distribution"),
1654 	TEST_CASE(cli, fail_on_persistency, "DFU Client doesn't give up DFU Transfer"),
1655 	TEST_CASE(cli, all_targets_lost_on_metadata,
1656 		  "All targets fail to check metadata and Client ends DFU Transfer"),
1657 	TEST_CASE(cli, all_targets_lost_on_caps_get,
1658 		  "All targets fail to respond to caps get and Client ends DFU Transfer"),
1659 	TEST_CASE(cli, all_targets_lost_on_update_get,
1660 		  "All targets fail to respond to update get and Client ends DFU Transfer"),
1661 	TEST_CASE(cli, all_targets_lost_on_verify,
1662 		  "All targets fail on verify step and Client ends DFU Transfer"),
1663 	TEST_CASE(cli, all_targets_lost_on_apply,
1664 		  "All targets fail on apply step and Client ends DFU Transfer"),
1665 
1666 	TEST_CASE(target, dfu_no_change, "Target node, Comp Data stays unchanged"),
1667 	TEST_CASE(target, dfu_new_comp_no_rpr, "Target node, Comp Data changes, no RPR"),
1668 	TEST_CASE(target, dfu_new_comp_rpr, "Target node, Comp Data changes, has RPR"),
1669 	TEST_CASE(target, dfu_unprov, "Target node, Comp Data changes, unprovisioned"),
1670 	TEST_CASE(target, fail_on_metadata, "Server rejects metadata"),
1671 	TEST_CASE(target, fail_on_caps_get, "Server failing on Retrieve Capabilities procedure"),
1672 	TEST_CASE(target, fail_on_update_get, "Server failing on Fw Update Get msg"),
1673 	TEST_CASE(target, fail_on_verify, "Server rejects fw at Refresh step"),
1674 	TEST_CASE(target, fail_on_apply, "Server failing on Fw Update Apply msg"),
1675 	TEST_CASE(target, fail_on_nothing, "Non-failing server"),
1676 	TEST_CASE(target, dfu_stop, "Server stops FD procedure at configured step"),
1677 
1678 	BSTEST_END_MARKER
1679 };
1680 
test_dfu_install(struct bst_test_list * tests)1681 struct bst_test_list *test_dfu_install(struct bst_test_list *tests)
1682 {
1683 	tests = bst_add_tests(tests, test_dfu);
1684 	return tests;
1685 }
1686