/* * Copyright (c) 2022 Nordic Semiconductor * * SPDX-License-Identifier: Apache-2.0 */ #include #include "mesh_test.h" #include "mesh/net.h" #define LOG_MODULE_NAME test_ivi #include LOG_MODULE_REGISTER(LOG_MODULE_NAME, LOG_LEVEL_INF); #define WAIT_TIME 60 /*seconds*/ #define TEST_IV_IDX 100 #define BCN_IV_IN_PROGRESS true #define BCN_IV_IN_IDLE false extern struct bt_mesh_net bt_mesh; static const struct bt_mesh_test_cfg ivu_cfg = { .addr = 0x0001, .dev_key = { 0x01 }, }; static void async_send_end(int err, void *data) { struct k_sem *sem = data; if (sem) { k_sem_give(sem); } } static const struct bt_mesh_send_cb async_send_cb = { .end = async_send_end, }; static void test_ivu_init(void) { bt_mesh_test_cfg_set(&ivu_cfg, WAIT_TIME); } static void emulate_recovery_timeout(void) { k_work_cancel_delayable(&bt_mesh.ivu_timer); bt_mesh.ivu_duration = 2 * BT_MESH_IVU_MIN_HOURS; } static void test_ivu_recovery(void) { bt_mesh_test_setup(); bt_mesh.iv_index = TEST_IV_IDX; atomic_set_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS); /* Already in IV Update in Progress state */ ASSERT_FALSE(bt_mesh_net_iv_update(TEST_IV_IDX, BCN_IV_IN_PROGRESS)); /* Out of sync */ ASSERT_FALSE(bt_mesh_net_iv_update(TEST_IV_IDX - 1, BCN_IV_IN_IDLE)); ASSERT_FALSE(bt_mesh_net_iv_update(TEST_IV_IDX + 43, BCN_IV_IN_IDLE)); /* Start recovery */ ASSERT_TRUE(bt_mesh_net_iv_update(TEST_IV_IDX + 2, BCN_IV_IN_IDLE)); ASSERT_EQUAL(TEST_IV_IDX + 2, bt_mesh.iv_index); ASSERT_FALSE(atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS)); /* Start recovery before minimum delay */ ASSERT_FALSE(bt_mesh_net_iv_update(TEST_IV_IDX + 4, BCN_IV_IN_IDLE)); emulate_recovery_timeout(); bt_mesh.iv_index = TEST_IV_IDX; atomic_clear_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS); /* Already in IV normal mode */ ASSERT_FALSE(bt_mesh_net_iv_update(TEST_IV_IDX, BCN_IV_IN_IDLE)); /* Out of sync */ ASSERT_FALSE(bt_mesh_net_iv_update(TEST_IV_IDX - 1, BCN_IV_IN_IDLE)); ASSERT_FALSE(bt_mesh_net_iv_update(TEST_IV_IDX + 43, BCN_IV_IN_IDLE)); /* Start recovery */ ASSERT_TRUE(bt_mesh_net_iv_update(TEST_IV_IDX + 1, BCN_IV_IN_IDLE)); ASSERT_EQUAL(TEST_IV_IDX + 1, bt_mesh.iv_index); ASSERT_FALSE(atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS)); /* Start recovery before minimum delay */ ASSERT_FALSE(bt_mesh_net_iv_update(TEST_IV_IDX + 4, BCN_IV_IN_IDLE)); PASS(); } static void test_ivu_normal(void) { bt_mesh_test_setup(); bt_mesh.iv_index = TEST_IV_IDX; bt_mesh.seq = 100; atomic_set_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS); /* update before minimum duration */ ASSERT_FALSE(bt_mesh_net_iv_update(TEST_IV_IDX, BCN_IV_IN_IDLE)); /* moving back into the normal mode */ bt_mesh.ivu_duration = BT_MESH_IVU_MIN_HOURS; ASSERT_TRUE(bt_mesh_net_iv_update(TEST_IV_IDX, BCN_IV_IN_IDLE)); ASSERT_FALSE(atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS)); ASSERT_EQUAL(TEST_IV_IDX, bt_mesh.iv_index); ASSERT_EQUAL(0, bt_mesh.seq); /* Ignore same iv index but iv in progress */ ASSERT_FALSE(bt_mesh_net_iv_update(TEST_IV_IDX, BCN_IV_IN_PROGRESS)); bt_mesh.seq = 100; /* update before minimum duration */ ASSERT_FALSE(bt_mesh_net_iv_update(TEST_IV_IDX + 1, BCN_IV_IN_PROGRESS)); /* moving into the IV update mode */ bt_mesh.ivu_duration = BT_MESH_IVU_MIN_HOURS; ASSERT_TRUE(bt_mesh_net_iv_update(TEST_IV_IDX + 1, BCN_IV_IN_PROGRESS)); ASSERT_TRUE(atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS)); ASSERT_EQUAL(TEST_IV_IDX + 1, bt_mesh.iv_index); ASSERT_EQUAL(100, bt_mesh.seq); PASS(); } static void test_ivu_deferring(void) { struct k_sem sem; k_sem_init(&sem, 0, 1); bt_mesh_test_setup(); bt_mesh.iv_index = TEST_IV_IDX; atomic_set_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS); bt_mesh.ivu_duration = BT_MESH_IVU_MIN_HOURS; ASSERT_OK(bt_mesh_test_send_async(0x0002, NULL, 20, FORCE_SEGMENTATION, &async_send_cb, &sem)); ASSERT_FALSE(bt_mesh_net_iv_update(TEST_IV_IDX, BCN_IV_IN_IDLE)); ASSERT_TRUE(atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS)); ASSERT_OK(k_sem_take(&sem, K_SECONDS(10))); ASSERT_FALSE(atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS)); PASS(); } #define TEST_CASE(role, name, description) \ { \ .test_id = "ivi_" #role "_" #name, \ .test_descr = description, \ .test_pre_init_f = test_##role##_init, \ .test_tick_f = bt_mesh_test_timeout, \ .test_main_f = test_##role##_##name, \ } static const struct bst_test_instance test_ivi[] = { TEST_CASE(ivu, recovery, "IVI: IV recovery procedure"), TEST_CASE(ivu, normal, "IVI: IV update procedure"), TEST_CASE(ivu, deferring, "IVI: deferring of the IV update procedure"), BSTEST_END_MARKER }; struct bst_test_list *test_ivi_install(struct bst_test_list *tests) { tests = bst_add_tests(tests, test_ivi); return tests; }