| /* |
| * Copyright (c) 2020 Intel Corporation. |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| /** |
| * @defgroup driver_sensor_subsys_tests sensor_subsys |
| * @ingroup all_tests |
| * @{ |
| * @} |
| */ |
| |
| #include <ztest.h> |
| #include "dummy_sensor.h" |
| |
| K_SEM_DEFINE(sem, 0, 1); |
| #define RETURN_SUCCESS (0) |
| |
| struct channel_sequence { |
| enum sensor_channel chan; |
| struct sensor_value data; |
| }; |
| |
| struct trigger_sequence { |
| struct sensor_trigger trig; |
| struct sensor_value data; |
| enum sensor_attribute attr; |
| }; |
| |
| static struct channel_sequence chan_elements[] = { |
| { SENSOR_CHAN_LIGHT, { 0, 0 } }, |
| { SENSOR_CHAN_RED, { 1, 1 } }, |
| { SENSOR_CHAN_GREEN, { 2, 4 } }, |
| { SENSOR_CHAN_BLUE, { 3, 9 } }, |
| { SENSOR_CHAN_PROX, { 4, 16 } } |
| }; |
| |
| static struct trigger_sequence trigger_elements[] = { |
| /* trigger for SENSOR_TRIG_THRESHOLD */ |
| { {SENSOR_TRIG_THRESHOLD, SENSOR_CHAN_PROX}, |
| { 127, 0 }, SENSOR_ATTR_UPPER_THRESH }, |
| |
| /* trigger for SENSOR_TRIG_TIMER */ |
| { {SENSOR_TRIG_TIMER, SENSOR_CHAN_PROX}, |
| { 130, 127 }, SENSOR_ATTR_UPPER_THRESH }, |
| |
| /* trigger for SENSOR_TRIG_DATA_READY */ |
| { {SENSOR_TRIG_DATA_READY, SENSOR_CHAN_PROX}, |
| { 150, 130 }, SENSOR_ATTR_UPPER_THRESH }, |
| |
| /* trigger for SENSOR_TRIG_DELTA */ |
| { {SENSOR_TRIG_DELTA, SENSOR_CHAN_PROX}, |
| { 180, 150 }, SENSOR_ATTR_UPPER_THRESH }, |
| |
| /* trigger for SENSOR_TRIG_NEAR_FAR */ |
| { {SENSOR_TRIG_NEAR_FAR, SENSOR_CHAN_PROX}, |
| { 155, 180 }, SENSOR_ATTR_UPPER_THRESH } |
| }; |
| |
| #define TOTAL_CHAN_ELEMENTS (sizeof(chan_elements) / \ |
| sizeof(struct channel_sequence)) |
| #define TOTAL_TRIG_ELEMENTS (sizeof(trigger_elements) / \ |
| sizeof(struct trigger_sequence)) |
| |
| /** |
| * @brief Test get multiple channels values. |
| * |
| * @ingroup driver_sensor_subsys_tests |
| * |
| * @details |
| * Test Objective: |
| * - get multiple channels values consistently in two operations: |
| * fetch sample and get the values of each channel individually. |
| * - check the results with sensor_value type avoids use of |
| * floating point values |
| * |
| * Testing techniques: |
| * - function and block box testing,Interface testing, |
| * Dynamic analysis and testing, Equivalence classes. |
| * |
| * Prerequisite Conditions: |
| * - N/A |
| * |
| * Input Specifications: |
| * - N/A |
| * |
| * Test Procedure: |
| * -# Define a device and bind to dummy sensor. |
| * -# Fetch the sample of dummy senor and check the result. |
| * -# Get SENSOR_CHAN_LIGHT/SENSOR_CHAN_RED/SENSOR_CHAN_GREEN/ |
| * SENSOR_CHAN_BLUE/SENSOR_CHAN_BLUE channels from the sensor, |
| * and check the result. |
| * |
| * Expected Test Result: |
| * - Application can get multiple channels for dummy sensor. |
| * |
| * Pass/Fail Criteria: |
| * - Successful if check points in test procedure are all passed, otherwise failure. |
| * |
| * Assumptions and Constraints: |
| * - N/A |
| * |
| * @see sensor_sample_fetch(), sensor_channel_get() |
| */ |
| void test_sensor_get_channels(void) |
| { |
| const struct device *dev; |
| struct sensor_value data; |
| |
| dev = device_get_binding(DUMMY_SENSOR_NAME); |
| zassert_not_null(dev, "failed: dev is null."); |
| |
| /* test fetch single channel */ |
| zassert_equal(sensor_sample_fetch_chan(dev, chan_elements[0].chan), |
| RETURN_SUCCESS, "fail to fetch sample."); |
| /* Get and check channel 0 value. */ |
| zassert_equal(sensor_channel_get(dev, chan_elements[0].chan, |
| &data), RETURN_SUCCESS, "fail to get channel."); |
| zassert_equal(data.val1, chan_elements[0].data.val1, |
| "the data is not match."); |
| zassert_equal(data.val2, chan_elements[0].data.val2, |
| "the data is not match."); |
| |
| /* test fetch all channel */ |
| zassert_equal(sensor_sample_fetch(dev), RETURN_SUCCESS, |
| "fail to fetch sample."); |
| /* Get and check channels value except for chanel 0. */ |
| for (int i = 1; i < TOTAL_CHAN_ELEMENTS; i++) { |
| zassert_equal(sensor_channel_get(dev, chan_elements[i].chan, |
| &data), RETURN_SUCCESS, "fail to get channel."); |
| zassert_equal(data.val1, chan_elements[i].data.val1, |
| "the data is not match."); |
| zassert_equal(data.val2, chan_elements[i].data.val2, |
| "the data is not match."); |
| } |
| |
| /* Get data with invalid channel. */ |
| zassert_not_equal(sensor_channel_get(dev, SENSOR_CHAN_DISTANCE, |
| &data), RETURN_SUCCESS, "should fail for invalid channel."); |
| } |
| |
| static void trigger_handler(const struct device *dev, |
| const struct sensor_trigger *trigger) |
| { |
| ARG_UNUSED(dev); |
| ARG_UNUSED(trigger); |
| |
| k_sem_give(&sem); |
| } |
| |
| /** |
| * @brief Test sensor multiple triggers. |
| * |
| * @ingroup driver_sensor_subsys_tests |
| * |
| * @details |
| * Test Objective: |
| * Check if sensor subsys can set multiple triggers and |
| * can set/get sensor attribute. |
| * |
| * Testing techniques: |
| * - function and block box testing,Interface testing, |
| * Dynamic analysis and testing. |
| * |
| * Prerequisite Conditions: |
| * - N/A |
| * |
| * Input Specifications: |
| * - N/A |
| * |
| * Test Procedure: |
| * -# Define a device and bind to dummy sensor and |
| * check the result. |
| * -# set multiple triggers for the dummy sensor and no trig sensor. |
| * then check the result. |
| * -# Handle different types of triggers, based on time, data,threshold, |
| * based on a delta value, near/far events and single/double tap and |
| * check the result. |
| * |
| * Expected Test Result: |
| * - Application can get multiple channels for dummy sensor. |
| * |
| * Pass/Fail Criteria: |
| * - Successful if check points in test procedure are all passed, otherwise failure. |
| * |
| * Assumptions and Constraints: |
| * - N/A |
| * |
| * @see sensor_attr_set(), sensor_trigger_set() |
| */ |
| void test_sensor_handle_triggers(void) |
| { |
| const struct device *dev; |
| const struct device *dev_no_trig; |
| struct sensor_value data; |
| |
| dev = device_get_binding(DUMMY_SENSOR_NAME); |
| dev_no_trig = device_get_binding(DUMMY_SENSOR_NAME_NO_TRIG); |
| zassert_not_null(dev, "failed: dev is null."); |
| |
| zassert_equal(sensor_sample_fetch(dev), RETURN_SUCCESS, |
| "fail to fetch sample."); |
| |
| /* setup multiple triggers */ |
| for (int i = 0; i < TOTAL_TRIG_ELEMENTS; i++) { |
| /* set attributes for trigger */ |
| zassert_equal(sensor_attr_set(dev, |
| trigger_elements[i].trig.chan, |
| trigger_elements[i].attr, |
| &trigger_elements[i].data), |
| RETURN_SUCCESS, "fail to set attributes"); |
| |
| /* read-back attributes for trigger */ |
| zassert_equal(sensor_attr_get(dev, |
| trigger_elements[i].trig.chan, |
| trigger_elements[i].attr, |
| &data), |
| RETURN_SUCCESS, "fail to get attributes"); |
| zassert_equal(trigger_elements[i].data.val1, |
| data.val1, "read-back returned wrong val1"); |
| zassert_equal(trigger_elements[i].data.val2, |
| data.val2, "read-back returned wrong val2"); |
| |
| /* setting a sensor's trigger and handler */ |
| zassert_equal(sensor_trigger_set(dev, |
| &trigger_elements[i].trig, |
| trigger_handler), |
| RETURN_SUCCESS, "fail to set trigger"); |
| |
| /* get channels value after trigger fired */ |
| k_sem_take(&sem, K_FOREVER); |
| zassert_equal(sensor_channel_get(dev, |
| trigger_elements[i].trig.chan, |
| &data), RETURN_SUCCESS, "fail to get channel."); |
| |
| /* check the result of the trigger channel */ |
| zassert_equal(data.val1, trigger_elements[i].data.val1, |
| "retrieved data is not match."); |
| zassert_equal(data.val2, trigger_elements[i].data.val2, |
| "retrieved data is not match."); |
| |
| /* set attributes for no trig dev */ |
| zassert_equal(sensor_attr_set(dev_no_trig, |
| trigger_elements[i].trig.chan, |
| trigger_elements[i].attr, |
| &trigger_elements[i].data), |
| -ENOSYS, "fail to set attributes"); |
| |
| /* read-back attributes for no trig dev*/ |
| zassert_equal(sensor_attr_get(dev_no_trig, |
| trigger_elements[i].trig.chan, |
| trigger_elements[i].attr, |
| &data), |
| -ENOSYS, "fail to get attributes"); |
| |
| /* setting a sensor's trigger and handler for no trig dev */ |
| zassert_equal(sensor_trigger_set(dev_no_trig, |
| &trigger_elements[i].trig, |
| trigger_handler), |
| -ENOSYS, "fail to set trigger"); |
| } |
| } |
| |
| /** |
| * @brief Test unit conversion of sensor module |
| * @details Verify helper function to convert acceleration from |
| * Gs to m/s^2 and from m/s^2 to Gs. Verify helper function |
| * to convert radians to degrees and degrees to radians. Verify |
| * helper function for converting struct sensor_value to double. |
| */ |
| void test_sensor_unit_conversion(void) |
| { |
| struct sensor_value data; |
| |
| /* Test acceleration unit conversion */ |
| sensor_g_to_ms2(1, &data); |
| zassert_equal(data.val1, SENSOR_G/1000000LL, |
| "the data is not match."); |
| zassert_equal(data.val2, SENSOR_G%(data.val1 * 1000000LL), |
| "the data is not match."); |
| zassert_equal(sensor_ms2_to_g(&data), 1, |
| "the data is not match."); |
| /* set test data to negative value */ |
| data.val1 = -data.val1; |
| data.val2 = -data.val2; |
| zassert_equal(sensor_ms2_to_g(&data), -1, |
| "the data is not match."); |
| |
| /* Test the conversion between angle and radian */ |
| sensor_degrees_to_rad(180, &data); |
| zassert_equal(data.val1, SENSOR_PI/1000000LL, |
| "the data is not match."); |
| zassert_equal(data.val2, SENSOR_PI%(data.val1 * 1000000LL), |
| "the data is not match."); |
| zassert_equal(sensor_rad_to_degrees(&data), 180, |
| "the data is not match."); |
| /* set test data to negative value */ |
| data.val1 = -data.val1; |
| data.val2 = -data.val2; |
| zassert_equal(sensor_rad_to_degrees(&data), -180, |
| "the data is not match."); |
| |
| /* reset test data to positive value */ |
| data.val1 = -data.val1; |
| data.val2 = -data.val2; |
| /* Test struct sensor_value to double */ |
| #if defined(CONFIG_FPU) |
| zassert_equal((long long)(sensor_value_to_double(&data) * 1000000LL), |
| SENSOR_PI, "the data is not match."); |
| #endif |
| } |
| |
| /*test case main entry*/ |
| void test_main(void) |
| { |
| ztest_test_suite(test_sensor_api, |
| ztest_1cpu_unit_test(test_sensor_get_channels), |
| ztest_1cpu_unit_test(test_sensor_handle_triggers), |
| ztest_1cpu_unit_test(test_sensor_unit_conversion)); |
| |
| ztest_run_test_suite(test_sensor_api); |
| } |