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