1 /*
2  * Copyright (c) 2022 Nordic Semiconductor ASA
3  * SPDX-License-Identifier: Apache-2.0
4  */
5 
6 #include <zephyr/ztest.h>
7 #include <zephyr/sys/linear_range.h>
8 
9 /*
10  * +-----+-----+
11  * | Val | Idx |
12  * +-----+-----+
13  * | -10 | 0   |
14  * | -5  | 1   |
15  * +-----+-----+
16  * | 0   | 2   |
17  * | 1   | 3   |
18  * +-----+-----+
19  * | 100 | 4   |
20  * | 130 | 5   |
21  * | 160 | 6   |
22  * | 190 | 7   |
23  * | 220 | 8   |
24  * | 250 | 9   |
25  * | 290 | 10  |
26  * +-----+-----+
27  * | 400 | 11  |
28  * | 400 | 12  |
29  * +-----+-----+
30  */
31 static const struct linear_range r[] = {
32 	LINEAR_RANGE_INIT(-10, 5U,  0U,  1U),
33 	LINEAR_RANGE_INIT(0,   1U,  2U,  3U),
34 	LINEAR_RANGE_INIT(100, 30U, 4U,  10U),
35 	LINEAR_RANGE_INIT(400, 0U,  11U, 12U),
36 };
37 
38 static const size_t r_cnt = ARRAY_SIZE(r);
39 
ZTEST(linear_range,test_linear_range_init)40 ZTEST(linear_range, test_linear_range_init)
41 {
42 	zassert_equal(r[0].min, -10);
43 	zassert_equal(r[0].step, 5U);
44 	zassert_equal(r[0].min_idx, 0U);
45 	zassert_equal(r[0].max_idx, 1U);
46 }
47 
ZTEST(linear_range,test_linear_range_values_count)48 ZTEST(linear_range, test_linear_range_values_count)
49 {
50 	zassert_equal(linear_range_values_count(&r[0]), 2U);
51 	zassert_equal(linear_range_values_count(&r[1]), 2U);
52 	zassert_equal(linear_range_values_count(&r[2]), 7U);
53 	zassert_equal(linear_range_values_count(&r[3]), 2U);
54 
55 	zassert_equal(linear_range_group_values_count(r, r_cnt), 13U);
56 }
57 
ZTEST(linear_range,test_linear_range_get_max_value)58 ZTEST(linear_range, test_linear_range_get_max_value)
59 {
60 	zassert_equal(linear_range_get_max_value(&r[0]), -5);
61 	zassert_equal(linear_range_get_max_value(&r[1]), 1);
62 	zassert_equal(linear_range_get_max_value(&r[2]), 280);
63 	zassert_equal(linear_range_get_max_value(&r[3]), 400);
64 }
65 
ZTEST(linear_range,test_linear_range_get_value)66 ZTEST(linear_range, test_linear_range_get_value)
67 {
68 	int ret;
69 	int32_t val;
70 
71 	ret = linear_range_get_value(&r[0], 0U, &val);
72 	zassert_equal(ret, 0);
73 	zassert_equal(val, -10);
74 
75 	ret = linear_range_get_value(&r[0], 1U, &val);
76 	zassert_equal(ret, 0);
77 	zassert_equal(val, -5);
78 
79 	ret = linear_range_get_value(&r[1], 2U, &val);
80 	zassert_equal(ret, 0);
81 	zassert_equal(val, 0);
82 
83 	ret = linear_range_get_value(&r[1], 3U, &val);
84 	zassert_equal(ret, 0);
85 	zassert_equal(val, 1);
86 
87 	ret = linear_range_get_value(&r[2], 4U, &val);
88 	zassert_equal(ret, 0);
89 	zassert_equal(val, 100);
90 
91 	ret = linear_range_get_value(&r[2], 5U, &val);
92 	zassert_equal(ret, 0);
93 	zassert_equal(val, 130);
94 
95 	ret = linear_range_get_value(&r[2], 6U, &val);
96 	zassert_equal(ret, 0);
97 	zassert_equal(val, 160);
98 
99 	ret = linear_range_get_value(&r[2], 7U, &val);
100 	zassert_equal(ret, 0);
101 	zassert_equal(val, 190);
102 
103 	ret = linear_range_get_value(&r[2], 8U, &val);
104 	zassert_equal(ret, 0);
105 	zassert_equal(val, 220);
106 
107 	ret = linear_range_get_value(&r[2], 9U, &val);
108 	zassert_equal(ret, 0);
109 	zassert_equal(val, 250);
110 
111 	ret = linear_range_get_value(&r[2], 10U, &val);
112 	zassert_equal(ret, 0);
113 	zassert_equal(val, 280);
114 
115 	ret = linear_range_get_value(&r[3], 11U, &val);
116 	zassert_equal(ret, 0);
117 	zassert_equal(val, 400);
118 
119 	ret = linear_range_get_value(&r[3], 12U, &val);
120 	zassert_equal(ret, 0);
121 	zassert_equal(val, 400);
122 
123 	ret = linear_range_get_value(&r[1], 13U, &val);
124 	zassert_equal(ret, -EINVAL);
125 
126 	ret = linear_range_group_get_value(r, r_cnt, 0U, &val);
127 	zassert_equal(ret, 0);
128 	zassert_equal(val, -10);
129 
130 	ret = linear_range_group_get_value(r, r_cnt, 1U, &val);
131 	zassert_equal(ret, 0);
132 	zassert_equal(val, -5);
133 
134 	ret = linear_range_group_get_value(r, r_cnt, 2U, &val);
135 	zassert_equal(ret, 0);
136 	zassert_equal(val, 0);
137 
138 	ret = linear_range_group_get_value(r, r_cnt, 3U, &val);
139 	zassert_equal(ret, 0);
140 	zassert_equal(val, 1);
141 
142 	ret = linear_range_group_get_value(r, r_cnt, 4U, &val);
143 	zassert_equal(ret, 0);
144 	zassert_equal(val, 100);
145 
146 	ret = linear_range_group_get_value(r, r_cnt, 5U, &val);
147 	zassert_equal(ret, 0);
148 	zassert_equal(val, 130);
149 
150 	ret = linear_range_group_get_value(r, r_cnt, 6U, &val);
151 	zassert_equal(ret, 0);
152 	zassert_equal(val, 160);
153 
154 	ret = linear_range_group_get_value(r, r_cnt, 7U, &val);
155 	zassert_equal(ret, 0);
156 	zassert_equal(val, 190);
157 
158 	ret = linear_range_group_get_value(r, r_cnt, 8U, &val);
159 	zassert_equal(ret, 0);
160 	zassert_equal(val, 220);
161 
162 	ret = linear_range_group_get_value(r, r_cnt, 9U, &val);
163 	zassert_equal(ret, 0);
164 	zassert_equal(val, 250);
165 
166 	ret = linear_range_group_get_value(r, r_cnt, 10U, &val);
167 	zassert_equal(ret, 0);
168 	zassert_equal(val, 280);
169 
170 	ret = linear_range_group_get_value(r, r_cnt, 11U, &val);
171 	zassert_equal(ret, 0);
172 	zassert_equal(val, 400);
173 
174 	ret = linear_range_group_get_value(r, r_cnt, 12U, &val);
175 	zassert_equal(ret, 0);
176 	zassert_equal(val, 400);
177 }
178 
ZTEST(linear_range,test_linear_range_get_index)179 ZTEST(linear_range, test_linear_range_get_index)
180 {
181 	int ret;
182 	uint16_t idx;
183 
184 	/* negative */
185 	ret = linear_range_get_index(&r[0], -10, &idx);
186 	zassert_equal(ret, 0);
187 	zassert_equal(idx, 0U);
188 
189 	ret = linear_range_get_index(&r[0], -7, &idx);
190 	zassert_equal(ret, 0);
191 	zassert_equal(idx, 1U);
192 
193 	/* out of range (< min, > max) */
194 	ret = linear_range_get_index(&r[1], -1, &idx);
195 	zassert_equal(ret, -ERANGE);
196 	zassert_equal(idx, 2U);
197 
198 	ret = linear_range_get_index(&r[1], 2, &idx);
199 	zassert_equal(ret, -ERANGE);
200 	zassert_equal(idx, 3U);
201 
202 	/* range limits */
203 	ret = linear_range_get_index(&r[2], 100, &idx);
204 	zassert_equal(ret, 0);
205 	zassert_equal(idx, 4U);
206 
207 	ret = linear_range_get_index(&r[2], 280, &idx);
208 	zassert_equal(ret, 0);
209 	zassert_equal(idx, 10U);
210 
211 	/* rounding: 120->130 (5) */
212 	ret = linear_range_get_index(&r[2], 120, &idx);
213 	zassert_equal(ret, 0);
214 	zassert_equal(idx, 5U);
215 
216 	/* always minimum index in constant ranges */
217 	ret = linear_range_get_index(&r[3], 400, &idx);
218 	zassert_equal(ret, 0);
219 	zassert_equal(idx, 11U);
220 
221 	/* group */
222 	ret = linear_range_group_get_index(r, r_cnt, -20, &idx);
223 	zassert_equal(ret, -ERANGE);
224 	zassert_equal(idx, 0U);
225 
226 	ret = linear_range_group_get_index(r, r_cnt, -6, &idx);
227 	zassert_equal(ret, 0);
228 	zassert_equal(idx, 1U);
229 
230 	ret = linear_range_group_get_index(r, r_cnt, 0, &idx);
231 	zassert_equal(ret, 0);
232 	zassert_equal(idx, 2U);
233 
234 	ret = linear_range_group_get_index(r, r_cnt, 50, &idx);
235 	zassert_equal(ret, -ERANGE);
236 	zassert_equal(idx, 4U);
237 
238 	ret = linear_range_group_get_index(r, r_cnt, 200, &idx);
239 	zassert_equal(ret, 0);
240 	zassert_equal(idx, 8U);
241 
242 	ret = linear_range_group_get_index(r, r_cnt, 400, &idx);
243 	zassert_equal(ret, 0);
244 	zassert_equal(idx, 11U);
245 }
246 
ZTEST(linear_range,test_linear_range_get_win_index)247 ZTEST(linear_range, test_linear_range_get_win_index)
248 {
249 	int ret;
250 	uint16_t idx;
251 
252 	/* negative */
253 	ret = linear_range_get_win_index(&r[0], -10, -6, &idx);
254 	zassert_equal(ret, 0);
255 	zassert_equal(idx, 0U);
256 
257 	ret = linear_range_get_win_index(&r[0], -7, -5, &idx);
258 	zassert_equal(ret, 0);
259 	zassert_equal(idx, 1U);
260 
261 	/* no intersection */
262 	ret = linear_range_get_win_index(&r[0], -20, -15, &idx);
263 	zassert_equal(ret, -EINVAL);
264 
265 	ret = linear_range_get_win_index(&r[0], -4, -3, &idx);
266 	zassert_equal(ret, -EINVAL);
267 
268 	/* out of range, partial intersection (< min, > max) */
269 	ret = linear_range_get_win_index(&r[1], -1, 0, &idx);
270 	zassert_equal(ret, -ERANGE);
271 	zassert_equal(idx, 2U);
272 
273 	ret = linear_range_get_win_index(&r[1], 1, 2, &idx);
274 	zassert_equal(ret, -ERANGE);
275 	zassert_equal(idx, 3U);
276 
277 	/* min/max equal */
278 	ret = linear_range_get_win_index(&r[2], 100, 100, &idx);
279 	zassert_equal(ret, 0);
280 	zassert_equal(idx, 4U);
281 
282 	/* always minimum index that satisfies >= min */
283 	ret = linear_range_get_win_index(&r[2], 100, 180, &idx);
284 	zassert_equal(ret, 0);
285 	zassert_equal(idx, 4U);
286 
287 	/* rounding: 120->130, maximum < 130 */
288 	ret = linear_range_get_win_index(&r[2], 120, 140, &idx);
289 	zassert_equal(ret, 0);
290 	zassert_equal(idx, 5U);
291 
292 	/* rounding: 120->130, maximum > 125 (range too narrow) */
293 	ret = linear_range_get_win_index(&r[2], 120, 125, &idx);
294 	zassert_equal(ret, -EINVAL);
295 
296 	ret = linear_range_group_get_win_index(r, r_cnt, 120, 125, &idx);
297 	zassert_equal(ret, -EINVAL);
298 
299 	/* always minimum index in constant ranges */
300 	ret = linear_range_get_win_index(&r[3], 400, 400, &idx);
301 	zassert_equal(ret, 0);
302 	zassert_equal(idx, 11U);
303 
304 	/* group */
305 	ret = linear_range_group_get_win_index(r, r_cnt, -10, -8, &idx);
306 	zassert_equal(ret, 0);
307 	zassert_equal(idx, 0U);
308 
309 	ret = linear_range_group_get_win_index(r, r_cnt, 0, 1, &idx);
310 	zassert_equal(ret, 0);
311 	zassert_equal(idx, 2U);
312 
313 	ret = linear_range_group_get_win_index(r, r_cnt, 1, 120, &idx);
314 	zassert_equal(ret, -ERANGE);
315 	zassert_equal(idx, 3U);
316 
317 	ret = linear_range_group_get_win_index(r, r_cnt, 120, 140, &idx);
318 	zassert_equal(ret, 0);
319 	zassert_equal(idx, 5U);
320 
321 	ret = linear_range_group_get_win_index(r, r_cnt, 140, 400, &idx);
322 	zassert_equal(ret, -ERANGE);
323 	zassert_equal(idx, 10U);
324 
325 	ret = linear_range_group_get_win_index(r, r_cnt, 400, 400, &idx);
326 	zassert_equal(ret, 0);
327 	zassert_equal(idx, 11U);
328 
329 	ret = linear_range_group_get_win_index(r, r_cnt, 300, 310, &idx);
330 	zassert_equal(ret, -EINVAL);
331 }
332 
333 ZTEST_SUITE(linear_range, NULL, NULL, NULL, NULL, NULL);
334