From 1441ad312c7bca9f301f51494df8641a597cfe47 Mon Sep 17 00:00:00 2001 From: Tristan Honscheid Date: Mon, 4 Oct 2021 15:34:59 -0600 Subject: zephyr: Add test for `st_write_data_with_mask()` Add a unit test for `st_write_data_with_mask()`. Also adds a new mock i2c write function and adds the ability to return fake i2c read values from the read mock. BUG=b:200589041 BRANCH=None TEST=zmake configure --test zephyr/test/drivers Signed-off-by: Tristan Honscheid Cq-Depend: chromium:3203150 Change-Id: I9d7a5673417f3e62d28536bf2a871d57d7ff5cfb Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/3203591 Reviewed-by: Yuval Peress Reviewed-by: Jack Rosenthal --- zephyr/test/drivers/src/stm_mems_common.c | 104 +++++++++++++++++++++++++++++- 1 file changed, 103 insertions(+), 1 deletion(-) diff --git a/zephyr/test/drivers/src/stm_mems_common.c b/zephyr/test/drivers/src/stm_mems_common.c index 464fdb9b38..701a573f79 100644 --- a/zephyr/test/drivers/src/stm_mems_common.c +++ b/zephyr/test/drivers/src/stm_mems_common.c @@ -16,6 +16,11 @@ #define MOCK_EMUL emul_get_binding(DT_LABEL(DT_NODELABEL(i2c_mock))) +struct mock_properties { + /* Incremented by the mock function every time it is called */ + int call_count; +}; + static void setup(void) { i2c_mock_reset(MOCK_EMUL); @@ -26,6 +31,24 @@ static int mock_read_fn(struct i2c_emul *emul, int reg, uint8_t *val, int bytes, { ztest_check_expected_value(reg); ztest_check_expected_value(bytes); + if (val != NULL) { + /* Allow passing a mocked read byte through the output param */ + ztest_copy_return_data(val, sizeof(*val)); + } + return ztest_get_return_value(); +} + +static int mock_write_fn(struct i2c_emul *emul, int reg, uint8_t val, int bytes, + void *data) +{ + struct mock_properties *props = (struct mock_properties *)data; + + if (props) + props->call_count++; + + ztest_check_expected_value(reg); + ztest_check_expected_value(val); + ztest_check_expected_value(bytes); return ztest_get_return_value(); } @@ -72,6 +95,83 @@ static void test_st_raw_read_n_noinc(void) EC_ERROR_INVAL); } +static void test_st_write_data_with_mask(void) +{ + const struct emul *emul = MOCK_EMUL; + struct i2c_emul *i2c_emul = i2c_mock_to_i2c_emul(emul); + int rv; + + const struct motion_sensor_t sensor = { + .port = I2C_PORT_POWER, + .i2c_spi_addr_flags = i2c_mock_get_addr(emul), + }; + + /* Arbitrary named test parameters */ + uint8_t test_addr = 0xAA; + uint8_t initial_value = 0x55; + uint8_t test_mask = 0xF0; + uint8_t test_data = 0xFF; + uint8_t expected_new_value = (initial_value & ~test_mask) | + (test_data & test_mask); + + /* Part 1: error occurs when reading initial value from sensor */ + i2c_common_emul_set_read_func(i2c_emul, mock_read_fn, NULL); + ztest_expect_value(mock_read_fn, reg, test_addr); + ztest_expect_value(mock_read_fn, bytes, 0); + /* Value is immaterial but ztest has no way to explicitly ignore it */ + ztest_return_data(mock_read_fn, val, &initial_value); + ztest_returns_value(mock_read_fn, -EIO); + + rv = st_write_data_with_mask(&sensor, test_addr, test_mask, test_data); + /* The shim layer translates -EIO to EC_ERROR_INVAL. */ + zassert_equal(rv, EC_ERROR_INVAL, "rv was %d but expected %d", rv, + EC_ERROR_INVAL); + + /* + * Part 2: initial read succeeds, but the initial value already + * matches the new value, so no write happens. + */ + ztest_expect_value(mock_read_fn, reg, test_addr); + ztest_expect_value(mock_read_fn, bytes, 0); + ztest_return_data(mock_read_fn, val, &expected_new_value); + ztest_returns_value(mock_read_fn, 0); + + struct mock_properties write_fn_props = { + .call_count = 0, + }; + + i2c_common_emul_set_write_func(i2c_emul, mock_write_fn, + &write_fn_props); + + rv = st_write_data_with_mask(&sensor, test_addr, test_mask, test_data); + zassert_equal(rv, EC_SUCCESS, "rv was %d but expected %d", rv, + EC_SUCCESS); + zassert_equal(write_fn_props.call_count, 0, + "mock_write_fn was called."); + + /* + * Part 3: this time a write is required, but it fails. This also + * tests the masking logic. + */ + ztest_expect_value(mock_read_fn, reg, test_addr); + ztest_expect_value(mock_read_fn, bytes, 0); + ztest_return_data(mock_read_fn, val, &initial_value); + ztest_returns_value(mock_read_fn, 0); + + write_fn_props.call_count = 0; /* Reset call count */ + ztest_expect_value(mock_write_fn, reg, test_addr); + ztest_expect_value(mock_write_fn, bytes, 1); + ztest_expect_value(mock_write_fn, val, expected_new_value); + ztest_returns_value(mock_write_fn, -EIO); + + rv = st_write_data_with_mask(&sensor, test_addr, test_mask, test_data); + /* The shim layer translates -EIO to EC_ERROR_INVAL. */ + zassert_equal(rv, EC_ERROR_INVAL, "rv was %d but expected %d", rv, + EC_ERROR_INVAL); + zassert_equal(write_fn_props.call_count, 1, + "mock_write_fn was not called."); +} + void test_suite_stm_mems_common(void) { ztest_test_suite( @@ -79,6 +179,8 @@ void test_suite_stm_mems_common(void) ztest_unit_test_setup_teardown(test_st_raw_read_n, setup, unit_test_noop), ztest_unit_test_setup_teardown(test_st_raw_read_n_noinc, setup, - unit_test_noop)); + unit_test_noop), + ztest_unit_test_setup_teardown(test_st_write_data_with_mask, + setup, unit_test_noop)); ztest_run_test_suite(stm_mems_common); } -- cgit v1.2.1