| /* |
| * Copyright (c) 2021 Nordic Semiconductor |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| #include <kernel.h> |
| #include "mesh_test.h" |
| #include "mesh/net.h" |
| #include "mesh/beacon.h" |
| #include "mesh/mesh.h" |
| #include "mesh/foundation.h" |
| |
| #define LOG_MODULE_NAME test_beacon |
| |
| #include <logging/log.h> |
| LOG_MODULE_REGISTER(LOG_MODULE_NAME, LOG_LEVEL_INF); |
| |
| #define GROUP_ADDR 0xc000 |
| #define WAIT_TIME 60 /*seconds*/ |
| #define BEACON_INTERVAL K_SECONDS(10) |
| |
| extern enum bst_result_t bst_result; |
| |
| static const struct bt_mesh_test_cfg tx_cfg = { |
| .addr = 0x0001, |
| .dev_key = { 0x01 }, |
| }; |
| static const struct bt_mesh_test_cfg rx_cfg = { |
| .addr = 0x0002, |
| .dev_key = { 0x02 }, |
| }; |
| |
| static void test_tx_init(void) |
| { |
| bt_mesh_test_cfg_set(&tx_cfg, WAIT_TIME); |
| } |
| |
| static void test_rx_init(void) |
| { |
| bt_mesh_test_cfg_set(&rx_cfg, WAIT_TIME); |
| } |
| |
| static void ivu_log(void) |
| { |
| LOG_DBG("ivi: %i", bt_mesh.iv_index); |
| LOG_DBG("flags:"); |
| |
| if (atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_INITIATOR)) { |
| LOG_DBG("IVU initiator"); |
| } |
| |
| if (atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS)) { |
| LOG_DBG("IVU in progress"); |
| } |
| |
| if (atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_PENDING)) { |
| LOG_DBG("IVU pending"); |
| } |
| |
| if (atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_TEST)) { |
| LOG_DBG("IVU in test mode"); |
| } |
| } |
| |
| static void test_tx_on_iv_update(void) |
| { |
| bt_mesh_test_setup(); |
| ASSERT_TRUE(!atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_INITIATOR)); |
| ASSERT_TRUE(!atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS)); |
| ASSERT_TRUE(!atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_PENDING)); |
| ASSERT_TRUE(!atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_TEST)); |
| ASSERT_TRUE(bt_mesh.iv_index == 0); |
| |
| /* shift beaconing time line to avoid boundary cases. */ |
| k_sleep(K_SECONDS(1)); |
| |
| bt_mesh_iv_update_test(true); |
| ASSERT_TRUE(atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_TEST)); |
| |
| ASSERT_TRUE(bt_mesh_iv_update()); |
| ASSERT_TRUE(atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS)); |
| ASSERT_TRUE(bt_mesh.iv_index == 1); |
| |
| k_sleep(BEACON_INTERVAL); |
| |
| ASSERT_TRUE(!bt_mesh_iv_update()); |
| ASSERT_TRUE(!atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS)); |
| ASSERT_TRUE(bt_mesh.iv_index == 1); |
| |
| k_sleep(BEACON_INTERVAL); |
| |
| ASSERT_TRUE(bt_mesh_iv_update()); |
| ASSERT_TRUE(atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS)); |
| ASSERT_TRUE(bt_mesh.iv_index == 2); |
| |
| k_sleep(BEACON_INTERVAL); |
| |
| PASS(); |
| } |
| |
| static void test_rx_on_iv_update(void) |
| { |
| bt_mesh_test_setup(); |
| /* disable beaconing from Rx device to prevent |
| * the time line adaptation due to observation algorithm. |
| */ |
| bt_mesh_beacon_disable(); |
| ASSERT_TRUE(!atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_INITIATOR)); |
| ASSERT_TRUE(!atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS)); |
| ASSERT_TRUE(!atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_PENDING)); |
| ASSERT_TRUE(!atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_TEST)); |
| ASSERT_TRUE(bt_mesh.iv_index == 0); |
| |
| /* shift beaconing time line to avoid boundary cases. */ |
| k_sleep(K_SECONDS(1)); |
| |
| bt_mesh_iv_update_test(true); |
| ASSERT_TRUE(atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_TEST)); |
| ivu_log(); |
| |
| k_sleep(BEACON_INTERVAL); |
| |
| ASSERT_TRUE(atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS)); |
| ASSERT_TRUE(bt_mesh.iv_index == 1); |
| ivu_log(); |
| |
| k_sleep(BEACON_INTERVAL); |
| |
| ASSERT_TRUE(!atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS)); |
| ASSERT_TRUE(bt_mesh.iv_index == 1); |
| ivu_log(); |
| |
| k_sleep(BEACON_INTERVAL); |
| |
| ASSERT_TRUE(atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS)); |
| ASSERT_TRUE(bt_mesh.iv_index == 2); |
| ivu_log(); |
| |
| PASS(); |
| } |
| |
| static void test_tx_on_key_refresh(void) |
| { |
| const uint8_t new_key[16] = {0x01}; |
| uint8_t phase; |
| uint8_t status; |
| |
| bt_mesh_test_setup(); |
| |
| status = bt_mesh_subnet_kr_phase_get(BT_MESH_KEY_PRIMARY, &phase); |
| ASSERT_TRUE(status == STATUS_SUCCESS); |
| ASSERT_TRUE(phase == BT_MESH_KR_NORMAL); |
| |
| /* shift beaconing time line to avoid boundary cases. */ |
| k_sleep(K_SECONDS(1)); |
| |
| status = bt_mesh_subnet_update(BT_MESH_KEY_PRIMARY, new_key); |
| ASSERT_TRUE(status == STATUS_SUCCESS); |
| status = bt_mesh_subnet_kr_phase_get(BT_MESH_KEY_PRIMARY, &phase); |
| ASSERT_TRUE(status == STATUS_SUCCESS); |
| ASSERT_TRUE(phase == BT_MESH_KR_PHASE_1); |
| |
| k_sleep(BEACON_INTERVAL); |
| |
| phase = BT_MESH_KR_PHASE_2; |
| status = bt_mesh_subnet_kr_phase_set(BT_MESH_KEY_PRIMARY, &phase); |
| ASSERT_TRUE(status == STATUS_SUCCESS); |
| status = bt_mesh_subnet_kr_phase_get(BT_MESH_KEY_PRIMARY, &phase); |
| ASSERT_TRUE(status == STATUS_SUCCESS); |
| ASSERT_TRUE(phase == BT_MESH_KR_PHASE_2); |
| |
| k_sleep(BEACON_INTERVAL); |
| |
| phase = BT_MESH_KR_PHASE_3; |
| status = bt_mesh_subnet_kr_phase_set(BT_MESH_KEY_PRIMARY, &phase); |
| ASSERT_TRUE(status == STATUS_SUCCESS); |
| status = bt_mesh_subnet_kr_phase_get(BT_MESH_KEY_PRIMARY, &phase); |
| ASSERT_TRUE(status == STATUS_SUCCESS); |
| ASSERT_TRUE(phase == BT_MESH_KR_NORMAL); |
| |
| k_sleep(BEACON_INTERVAL); |
| |
| PASS(); |
| } |
| |
| static void test_rx_on_key_refresh(void) |
| { |
| const uint8_t new_key[16] = {0x01}; |
| uint8_t phase; |
| uint8_t status; |
| |
| bt_mesh_test_setup(); |
| /* disable beaconing from Rx device to prevent |
| * the time line adaptation due to observation algorithm. |
| */ |
| bt_mesh_beacon_disable(); |
| |
| status = bt_mesh_subnet_kr_phase_get(BT_MESH_KEY_PRIMARY, &phase); |
| ASSERT_TRUE(status == STATUS_SUCCESS); |
| ASSERT_TRUE(phase == BT_MESH_KR_NORMAL); |
| |
| /* shift beaconing time line to avoid boundary cases. */ |
| k_sleep(K_SECONDS(1)); |
| |
| status = bt_mesh_subnet_update(BT_MESH_KEY_PRIMARY, new_key); |
| ASSERT_TRUE(status == STATUS_SUCCESS); |
| status = bt_mesh_subnet_kr_phase_get(BT_MESH_KEY_PRIMARY, &phase); |
| ASSERT_TRUE(status == STATUS_SUCCESS); |
| ASSERT_TRUE(phase == BT_MESH_KR_PHASE_1); |
| |
| k_sleep(BEACON_INTERVAL); |
| |
| status = bt_mesh_subnet_kr_phase_get(BT_MESH_KEY_PRIMARY, &phase); |
| ASSERT_TRUE(status == STATUS_SUCCESS); |
| ASSERT_TRUE(phase == BT_MESH_KR_PHASE_1); |
| |
| k_sleep(BEACON_INTERVAL); |
| |
| status = bt_mesh_subnet_kr_phase_get(BT_MESH_KEY_PRIMARY, &phase); |
| ASSERT_TRUE(status == STATUS_SUCCESS); |
| ASSERT_TRUE(phase == BT_MESH_KR_PHASE_2); |
| |
| k_sleep(BEACON_INTERVAL); |
| |
| status = bt_mesh_subnet_kr_phase_get(BT_MESH_KEY_PRIMARY, &phase); |
| ASSERT_TRUE(status == STATUS_SUCCESS); |
| ASSERT_TRUE(phase == BT_MESH_KR_NORMAL); |
| |
| PASS(); |
| } |
| |
| #define TEST_CASE(role, name, description) \ |
| { \ |
| .test_id = "beacon_" #role "_" #name, \ |
| .test_descr = description, \ |
| .test_post_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_beacon[] = { |
| TEST_CASE(tx, on_iv_update, "Beacon: send on IV update"), |
| TEST_CASE(tx, on_key_refresh, "Beacon: send on key refresh"), |
| |
| TEST_CASE(rx, on_iv_update, "Beacon: receive with IV update flag"), |
| TEST_CASE(rx, on_key_refresh, "Beacon: receive with key refresh flag"), |
| BSTEST_END_MARKER |
| }; |
| |
| struct bst_test_list *test_beacon_install(struct bst_test_list *tests) |
| { |
| tests = bst_add_tests(tests, test_beacon); |
| return tests; |
| } |