1 /*
2 * Copyright (c) 2022 Nordic Semiconductor
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include "mesh_test.h"
9 #include "mesh/net.h"
10
11 #define LOG_MODULE_NAME test_ivi
12
13 #include <zephyr/logging/log.h>
14 LOG_MODULE_REGISTER(LOG_MODULE_NAME, LOG_LEVEL_INF);
15
16 #define WAIT_TIME 60 /*seconds*/
17 #define TEST_IV_IDX 100
18 #define BCN_IV_IN_PROGRESS true
19 #define BCN_IV_IN_IDLE false
20
21 extern struct bt_mesh_net bt_mesh;
22
23 static const struct bt_mesh_test_cfg ivu_cfg = {
24 .addr = 0x0001,
25 .dev_key = { 0x01 },
26 };
27
async_send_end(int err,void * data)28 static void async_send_end(int err, void *data)
29 {
30 struct k_sem *sem = data;
31
32 if (sem) {
33 k_sem_give(sem);
34 }
35 }
36
37 static const struct bt_mesh_send_cb async_send_cb = {
38 .end = async_send_end,
39 };
40
test_ivu_init(void)41 static void test_ivu_init(void)
42 {
43 bt_mesh_test_cfg_set(&ivu_cfg, WAIT_TIME);
44 }
45
emulate_recovery_timeout(void)46 static void emulate_recovery_timeout(void)
47 {
48 k_work_cancel_delayable(&bt_mesh.ivu_timer);
49 bt_mesh.ivu_duration = 2 * BT_MESH_IVU_MIN_HOURS;
50 }
51
test_ivu_recovery(void)52 static void test_ivu_recovery(void)
53 {
54 bt_mesh_test_setup();
55
56 bt_mesh.iv_index = TEST_IV_IDX;
57
58 atomic_set_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS);
59
60 /* Already in IV Update in Progress state */
61 ASSERT_FALSE(bt_mesh_net_iv_update(TEST_IV_IDX, BCN_IV_IN_PROGRESS));
62
63 /* Out of sync */
64 ASSERT_FALSE(bt_mesh_net_iv_update(TEST_IV_IDX - 1, BCN_IV_IN_IDLE));
65 ASSERT_FALSE(bt_mesh_net_iv_update(TEST_IV_IDX + 43, BCN_IV_IN_IDLE));
66
67 /* Start recovery */
68 ASSERT_TRUE(bt_mesh_net_iv_update(TEST_IV_IDX + 2, BCN_IV_IN_IDLE));
69 ASSERT_EQUAL(TEST_IV_IDX + 2, bt_mesh.iv_index);
70 ASSERT_FALSE(atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS));
71
72 /* Start recovery before minimum delay */
73 ASSERT_FALSE(bt_mesh_net_iv_update(TEST_IV_IDX + 4, BCN_IV_IN_IDLE));
74
75 emulate_recovery_timeout();
76 bt_mesh.iv_index = TEST_IV_IDX;
77
78 atomic_clear_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS);
79
80 /* Already in IV normal mode */
81 ASSERT_FALSE(bt_mesh_net_iv_update(TEST_IV_IDX, BCN_IV_IN_IDLE));
82
83 /* Out of sync */
84 ASSERT_FALSE(bt_mesh_net_iv_update(TEST_IV_IDX - 1, BCN_IV_IN_IDLE));
85 ASSERT_FALSE(bt_mesh_net_iv_update(TEST_IV_IDX + 43, BCN_IV_IN_IDLE));
86
87 /* Start recovery */
88 ASSERT_TRUE(bt_mesh_net_iv_update(TEST_IV_IDX + 1, BCN_IV_IN_IDLE));
89 ASSERT_EQUAL(TEST_IV_IDX + 1, bt_mesh.iv_index);
90 ASSERT_FALSE(atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS));
91
92 /* Start recovery before minimum delay */
93 ASSERT_FALSE(bt_mesh_net_iv_update(TEST_IV_IDX + 4, BCN_IV_IN_IDLE));
94
95 PASS();
96 }
97
test_ivu_normal(void)98 static void test_ivu_normal(void)
99 {
100 bt_mesh_test_setup();
101 bt_mesh.iv_index = TEST_IV_IDX;
102 bt_mesh.seq = 100;
103 atomic_set_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS);
104
105 /* update before minimum duration */
106 ASSERT_FALSE(bt_mesh_net_iv_update(TEST_IV_IDX, BCN_IV_IN_IDLE));
107 /* moving back into the normal mode */
108 bt_mesh.ivu_duration = BT_MESH_IVU_MIN_HOURS;
109 ASSERT_TRUE(bt_mesh_net_iv_update(TEST_IV_IDX, BCN_IV_IN_IDLE));
110 ASSERT_FALSE(atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS));
111 ASSERT_EQUAL(TEST_IV_IDX, bt_mesh.iv_index);
112 ASSERT_EQUAL(0, bt_mesh.seq);
113
114 /* Ignore same iv index but iv in progress */
115 ASSERT_FALSE(bt_mesh_net_iv_update(TEST_IV_IDX, BCN_IV_IN_PROGRESS));
116
117 bt_mesh.seq = 100;
118 /* update before minimum duration */
119 ASSERT_FALSE(bt_mesh_net_iv_update(TEST_IV_IDX + 1, BCN_IV_IN_PROGRESS));
120 /* moving into the IV update mode */
121 bt_mesh.ivu_duration = BT_MESH_IVU_MIN_HOURS;
122 ASSERT_TRUE(bt_mesh_net_iv_update(TEST_IV_IDX + 1, BCN_IV_IN_PROGRESS));
123 ASSERT_TRUE(atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS));
124 ASSERT_EQUAL(TEST_IV_IDX + 1, bt_mesh.iv_index);
125 ASSERT_EQUAL(100, bt_mesh.seq);
126
127 PASS();
128 }
129
test_ivu_deferring(void)130 static void test_ivu_deferring(void)
131 {
132 struct k_sem sem;
133
134 k_sem_init(&sem, 0, 1);
135 bt_mesh_test_setup();
136 bt_mesh.iv_index = TEST_IV_IDX;
137 atomic_set_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS);
138 bt_mesh.ivu_duration = BT_MESH_IVU_MIN_HOURS;
139
140 ASSERT_OK(bt_mesh_test_send_async(0x0002, NULL, 20, FORCE_SEGMENTATION, &async_send_cb,
141 &sem));
142 ASSERT_FALSE(bt_mesh_net_iv_update(TEST_IV_IDX, BCN_IV_IN_IDLE));
143 ASSERT_TRUE(atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS));
144
145 ASSERT_OK(k_sem_take(&sem, K_SECONDS(10)));
146 ASSERT_FALSE(atomic_test_bit(bt_mesh.flags, BT_MESH_IVU_IN_PROGRESS));
147
148 PASS();
149 }
150
151 #define TEST_CASE(role, name, description) \
152 { \
153 .test_id = "ivi_" #role "_" #name, \
154 .test_descr = description, \
155 .test_pre_init_f = test_##role##_init, \
156 .test_tick_f = bt_mesh_test_timeout, \
157 .test_main_f = test_##role##_##name, \
158 }
159
160 static const struct bst_test_instance test_ivi[] = {
161 TEST_CASE(ivu, recovery, "IVI: IV recovery procedure"),
162 TEST_CASE(ivu, normal, "IVI: IV update procedure"),
163 TEST_CASE(ivu, deferring, "IVI: deferring of the IV update procedure"),
164
165 BSTEST_END_MARKER
166 };
167
test_ivi_install(struct bst_test_list * tests)168 struct bst_test_list *test_ivi_install(struct bst_test_list *tests)
169 {
170 tests = bst_add_tests(tests, test_ivi);
171 return tests;
172 }
173