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