1 /*
2 * Copyright (c) 2020 Intel Corporation.
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /**
8 * @defgroup driver_sensor_subsys_tests sensor_subsys
9 * @ingroup all_tests
10 * @{
11 * @}
12 */
13
14 #include <zephyr/ztest.h>
15 #include "dummy_sensor.h"
16
17 K_SEM_DEFINE(sem, 0, 1);
18 #define RETURN_SUCCESS (0)
19
20 struct channel_sequence {
21 enum sensor_channel chan;
22 struct sensor_value data;
23 };
24
25 struct trigger_sequence {
26 struct sensor_trigger trig;
27 struct sensor_value data;
28 enum sensor_attribute attr;
29 };
30
31 static struct channel_sequence chan_elements[] = {
32 { SENSOR_CHAN_LIGHT, { 0, 0 } },
33 { SENSOR_CHAN_RED, { 1, 1 } },
34 { SENSOR_CHAN_GREEN, { 2, 4 } },
35 { SENSOR_CHAN_BLUE, { 3, 9 } },
36 { SENSOR_CHAN_PROX, { 4, 16 } }
37 };
38
39 static struct trigger_sequence trigger_elements[] = {
40 /* trigger for SENSOR_TRIG_THRESHOLD */
41 { {SENSOR_TRIG_THRESHOLD, SENSOR_CHAN_PROX},
42 { 127, 0 }, SENSOR_ATTR_UPPER_THRESH },
43
44 /* trigger for SENSOR_TRIG_TIMER */
45 { {SENSOR_TRIG_TIMER, SENSOR_CHAN_PROX},
46 { 130, 127 }, SENSOR_ATTR_UPPER_THRESH },
47
48 /* trigger for SENSOR_TRIG_DATA_READY */
49 { {SENSOR_TRIG_DATA_READY, SENSOR_CHAN_PROX},
50 { 150, 130 }, SENSOR_ATTR_UPPER_THRESH },
51
52 /* trigger for SENSOR_TRIG_DELTA */
53 { {SENSOR_TRIG_DELTA, SENSOR_CHAN_PROX},
54 { 180, 150 }, SENSOR_ATTR_UPPER_THRESH },
55
56 /* trigger for SENSOR_TRIG_NEAR_FAR */
57 { {SENSOR_TRIG_NEAR_FAR, SENSOR_CHAN_PROX},
58 { 155, 180 }, SENSOR_ATTR_UPPER_THRESH }
59 };
60
61 #define TOTAL_CHAN_ELEMENTS (sizeof(chan_elements) / \
62 sizeof(struct channel_sequence))
63 #define TOTAL_TRIG_ELEMENTS (sizeof(trigger_elements) / \
64 sizeof(struct trigger_sequence))
65
66 /**
67 * @brief Test get multiple channels values.
68 *
69 * @ingroup driver_sensor_subsys_tests
70 *
71 * @details
72 * Test Objective:
73 * - get multiple channels values consistently in two operations:
74 * fetch sample and get the values of each channel individually.
75 * - check the results with sensor_value type avoids use of
76 * floating point values
77 *
78 * Testing techniques:
79 * - function and block box testing,Interface testing,
80 * Dynamic analysis and testing, Equivalence classes.
81 *
82 * Prerequisite Conditions:
83 * - N/A
84 *
85 * Input Specifications:
86 * - N/A
87 *
88 * Test Procedure:
89 * -# Define a device and bind to dummy sensor.
90 * -# Fetch the sample of dummy senor and check the result.
91 * -# Get SENSOR_CHAN_LIGHT/SENSOR_CHAN_RED/SENSOR_CHAN_GREEN/
92 * SENSOR_CHAN_BLUE/SENSOR_CHAN_BLUE channels from the sensor,
93 * and check the result.
94 *
95 * Expected Test Result:
96 * - Application can get multiple channels for dummy sensor.
97 *
98 * Pass/Fail Criteria:
99 * - Successful if check points in test procedure are all passed, otherwise failure.
100 *
101 * Assumptions and Constraints:
102 * - N/A
103 *
104 * @see sensor_sample_fetch(), sensor_channel_get()
105 */
ZTEST(sensor_api,test_sensor_get_channels)106 ZTEST(sensor_api, test_sensor_get_channels)
107 {
108 const struct device *dev;
109 struct sensor_value data;
110
111 dev = device_get_binding(DUMMY_SENSOR_NAME);
112 zassert_not_null(dev, "failed: dev is null");
113
114 /* test fetch single channel */
115 zassert_equal(sensor_sample_fetch_chan(dev, chan_elements[0].chan),
116 RETURN_SUCCESS, "fail to fetch sample");
117 /* Get and check channel 0 value. */
118 zassert_equal(sensor_channel_get(dev, chan_elements[0].chan,
119 &data), RETURN_SUCCESS, "fail to get channel");
120 zassert_equal(data.val1, chan_elements[0].data.val1,
121 "the data does not match");
122 zassert_equal(data.val2, chan_elements[0].data.val2,
123 "the data does not match");
124
125 /* test fetch all channel */
126 zassert_equal(sensor_sample_fetch(dev), RETURN_SUCCESS,
127 "fail to fetch sample");
128 /* Get and check channels value except for chanel 0. */
129 for (int i = 1; i < TOTAL_CHAN_ELEMENTS; i++) {
130 zassert_equal(sensor_channel_get(dev, chan_elements[i].chan,
131 &data), RETURN_SUCCESS, "fail to get channel");
132 zassert_equal(data.val1, chan_elements[i].data.val1,
133 "the data does not match");
134 zassert_equal(data.val2, chan_elements[i].data.val2,
135 "the data does not match");
136 }
137
138 /* Get data with invalid channel. */
139 zassert_not_equal(sensor_channel_get(dev, SENSOR_CHAN_DISTANCE,
140 &data), RETURN_SUCCESS, "should fail for invalid channel");
141 }
142
trigger_handler(const struct device * dev,const struct sensor_trigger * trigger)143 static void trigger_handler(const struct device *dev,
144 const struct sensor_trigger *trigger)
145 {
146 ARG_UNUSED(dev);
147 ARG_UNUSED(trigger);
148
149 k_sem_give(&sem);
150 }
151
152 /**
153 * @brief Test sensor multiple triggers.
154 *
155 * @ingroup driver_sensor_subsys_tests
156 *
157 * @details
158 * Test Objective:
159 * Check if sensor subsys can set multiple triggers and
160 * can set/get sensor attribute.
161 *
162 * Testing techniques:
163 * - function and block box testing,Interface testing,
164 * Dynamic analysis and testing.
165 *
166 * Prerequisite Conditions:
167 * - N/A
168 *
169 * Input Specifications:
170 * - N/A
171 *
172 * Test Procedure:
173 * -# Define a device and bind to dummy sensor and
174 * check the result.
175 * -# set multiple triggers for the dummy sensor and no trig sensor.
176 * then check the result.
177 * -# Handle different types of triggers, based on time, data,threshold,
178 * based on a delta value, near/far events and single/double tap and
179 * check the result.
180 *
181 * Expected Test Result:
182 * - Application can get multiple channels for dummy sensor.
183 *
184 * Pass/Fail Criteria:
185 * - Successful if check points in test procedure are all passed, otherwise failure.
186 *
187 * Assumptions and Constraints:
188 * - N/A
189 *
190 * @see sensor_attr_set(), sensor_trigger_set()
191 */
ZTEST(sensor_api,test_sensor_handle_triggers)192 ZTEST(sensor_api, test_sensor_handle_triggers)
193 {
194 const struct device *dev;
195 const struct device *dev_no_trig;
196 struct sensor_value data;
197
198 dev = device_get_binding(DUMMY_SENSOR_NAME);
199 dev_no_trig = device_get_binding(DUMMY_SENSOR_NAME_NO_TRIG);
200 zassert_not_null(dev, "failed: dev is null");
201
202 zassert_equal(sensor_sample_fetch(dev), RETURN_SUCCESS,
203 "fail to fetch sample");
204
205 /* setup multiple triggers */
206 for (int i = 0; i < TOTAL_TRIG_ELEMENTS; i++) {
207 /* set attributes for trigger */
208 zassert_equal(sensor_attr_set(dev,
209 trigger_elements[i].trig.chan,
210 trigger_elements[i].attr,
211 &trigger_elements[i].data),
212 RETURN_SUCCESS, "fail to set attributes");
213
214 /* read-back attributes for trigger */
215 zassert_equal(sensor_attr_get(dev,
216 trigger_elements[i].trig.chan,
217 trigger_elements[i].attr,
218 &data),
219 RETURN_SUCCESS, "fail to get attributes");
220 zassert_equal(trigger_elements[i].data.val1,
221 data.val1, "read-back returned wrong val1");
222 zassert_equal(trigger_elements[i].data.val2,
223 data.val2, "read-back returned wrong val2");
224
225 /* setting a sensor's trigger and handler */
226 zassert_equal(sensor_trigger_set(dev,
227 &trigger_elements[i].trig,
228 trigger_handler),
229 RETURN_SUCCESS, "fail to set trigger");
230
231 /* get channels value after trigger fired */
232 k_sem_take(&sem, K_FOREVER);
233 zassert_equal(sensor_channel_get(dev,
234 trigger_elements[i].trig.chan,
235 &data), RETURN_SUCCESS, "fail to get channel");
236
237 /* check the result of the trigger channel */
238 zassert_equal(data.val1, trigger_elements[i].data.val1,
239 "retrieved data does not match");
240 zassert_equal(data.val2, trigger_elements[i].data.val2,
241 "retrieved data does not match");
242
243 /* set attributes for no trig dev */
244 zassert_equal(sensor_attr_set(dev_no_trig,
245 trigger_elements[i].trig.chan,
246 trigger_elements[i].attr,
247 &trigger_elements[i].data),
248 -ENOSYS, "fail to set attributes");
249
250 /* read-back attributes for no trig dev*/
251 zassert_equal(sensor_attr_get(dev_no_trig,
252 trigger_elements[i].trig.chan,
253 trigger_elements[i].attr,
254 &data),
255 -ENOSYS, "fail to get attributes");
256
257 /* setting a sensor's trigger and handler for no trig dev */
258 zassert_equal(sensor_trigger_set(dev_no_trig,
259 &trigger_elements[i].trig,
260 trigger_handler),
261 -ENOSYS, "fail to set trigger");
262 }
263 }
264
265 /**
266 * @brief Test unit conversion of sensor module
267 * @details Verify helper function to convert acceleration from
268 * Gs to m/s^2 and from m/s^2 to Gs. Verify helper function
269 * to convert radians to degrees and degrees to radians. Verify
270 * helper function for converting struct sensor_value to double.
271 * Verify helper functions for converting to milli and micro prefix
272 * units.
273 */
ZTEST(sensor_api,test_sensor_unit_conversion)274 ZTEST(sensor_api, test_sensor_unit_conversion)
275 {
276 struct sensor_value data;
277
278 /* Test acceleration unit conversion */
279 sensor_g_to_ms2(1, &data);
280 zassert_equal(data.val1, SENSOR_G/1000000LL,
281 "the data does not match");
282 zassert_equal(data.val2, SENSOR_G%(data.val1 * 1000000LL),
283 "the data does not match");
284 zassert_equal(sensor_ms2_to_g(&data), 1,
285 "the data does not match");
286 /* set test data to negative value */
287 data.val1 = -data.val1;
288 data.val2 = -data.val2;
289 zassert_equal(sensor_ms2_to_g(&data), -1,
290 "the data does not match");
291
292 /* Test the conversion between angle and radian */
293 sensor_degrees_to_rad(180, &data);
294 zassert_equal(data.val1, SENSOR_PI/1000000LL,
295 "the data does not match");
296 zassert_equal(data.val2, SENSOR_PI%(data.val1 * 1000000LL),
297 "the data does not match");
298 zassert_equal(sensor_rad_to_degrees(&data), 180,
299 "the data does not match");
300 /* set test data to negative value */
301 data.val1 = -data.val1;
302 data.val2 = -data.val2;
303 zassert_equal(sensor_rad_to_degrees(&data), -180,
304 "the data does not match");
305
306 /* reset test data to positive value */
307 data.val1 = -data.val1;
308 data.val2 = -data.val2;
309 #if defined(CONFIG_FPU)
310 /* Test struct sensor_value to double and float */
311 zassert_equal((long long)(sensor_value_to_double(&data) * 1000000LL),
312 SENSOR_PI, "the data does not match");
313 zassert_equal((long long)(sensor_value_to_float(&data) * 1000000LL),
314 SENSOR_PI, "the data does not match");
315
316 /* Test struct sensor_value from double and float */
317 sensor_value_from_double(&data, (double)(SENSOR_PI) / 1000000.0);
318 zassert_equal(data.val1, SENSOR_PI/1000000LL,
319 "the data does not match");
320 zassert_equal(data.val2, SENSOR_PI%(data.val1 * 1000000LL),
321 "the data does not match");
322
323 sensor_value_from_float(&data, (float)(SENSOR_PI) / 1000000.0f);
324 zassert_equal(data.val1, SENSOR_PI/1000000LL,
325 "the data does not match");
326 zassert_equal(data.val2, SENSOR_PI%(data.val1 * 1000000LL),
327 "the data does not match");
328 #endif
329 /* reset test data to positive value */
330 data.val1 = 3;
331 data.val2 = 300000;
332 zassert_equal(sensor_value_to_milli(&data), 3300LL,
333 "the result does not match");
334 zassert_equal(sensor_value_to_micro(&data), 3300000LL,
335 "the result does not match");
336 /* reset test data to negative value */
337 data.val1 = -data.val1;
338 data.val2 = -data.val2;
339 zassert_equal(sensor_value_to_milli(&data), -3300LL,
340 "the result does not match");
341 zassert_equal(sensor_value_to_micro(&data), -3300000LL,
342 "the result does not match");
343 /* Test when result is greater than 32-bit wide */
344 data.val1 = 5432109;
345 data.val2 = 876543;
346 zassert_equal(sensor_value_to_milli(&data), 5432109876LL,
347 "the result does not match");
348 zassert_equal(sensor_value_to_micro(&data), 5432109876543LL,
349 "the result does not match");
350 }
351
352 ZTEST_SUITE(sensor_api, NULL, NULL, ztest_simple_1cpu_before, ztest_simple_1cpu_after, NULL);
353