| /* |
| * Copyright (c) 2022 Vestas Wind Systems A/S |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| |
| #include <zephyr/drivers/eeprom.h> |
| #include <zephyr/drivers/eeprom/eeprom_fake.h> |
| #include <zephyr/fff.h> |
| #include <zephyr/shell/shell.h> |
| #include <zephyr/shell/shell_dummy.h> |
| #include <zephyr/sys/util.h> |
| #include <zephyr/ztest.h> |
| |
| #define FAKE_EEPROM_NAME DEVICE_DT_NAME(DT_NODELABEL(fake_eeprom)) |
| |
| /* Global variables */ |
| static const struct device *const fake_eeprom_dev = DEVICE_DT_GET(DT_NODELABEL(fake_eeprom)); |
| static uint8_t data_capture[CONFIG_EEPROM_SHELL_BUFFER_SIZE]; |
| DEFINE_FFF_GLOBALS; |
| |
| static int eeprom_shell_test_write_capture_data(const struct device *dev, off_t offset, |
| const void *data, size_t len) |
| { |
| ARG_UNUSED(dev); |
| ARG_UNUSED(offset); |
| |
| zassert_true(len <= sizeof(data_capture)); |
| memcpy(&data_capture, data, MIN(sizeof(data_capture), len)); |
| |
| return 0; |
| } |
| |
| static int eeprom_shell_test_read_captured_data(const struct device *dev, off_t offset, |
| void *data, size_t len) |
| { |
| ARG_UNUSED(dev); |
| ARG_UNUSED(offset); |
| |
| zassert_true(len <= sizeof(data_capture)); |
| memcpy(data, &data_capture, MIN(sizeof(data_capture), len)); |
| |
| return 0; |
| } |
| |
| ZTEST(eeprom_shell, test_eeprom_write) |
| { |
| const struct shell *sh = shell_backend_dummy_get_ptr(); |
| const uint8_t expected[] = { 0x11, 0x22, 0x33, 0x44, 0xaa, 0xbb, 0xcc, 0xdd }; |
| int err; |
| |
| /* This test relies on the EEPROM shell using a buffer size of at least 8 bytes */ |
| BUILD_ASSERT(CONFIG_EEPROM_SHELL_BUFFER_SIZE >= 8); |
| |
| /* Setup data capture to satisfy EEPROM shell verification read-back */ |
| fake_eeprom_write_fake.custom_fake = eeprom_shell_test_write_capture_data; |
| fake_eeprom_read_fake.custom_fake = eeprom_shell_test_read_captured_data; |
| |
| err = shell_execute_cmd(sh, "eeprom write " FAKE_EEPROM_NAME |
| " 8 0x11 0x22 0x33 0x44 0xaa 0xbb 0xcc 0xdd"); |
| zassert_ok(err, "failed to execute shell command (err %d)", err); |
| |
| /* The EEPROM shell will write the bytes ... */ |
| zassert_equal(fake_eeprom_write_fake.call_count, 1); |
| zassert_equal(fake_eeprom_write_fake.arg0_val, fake_eeprom_dev); |
| zassert_equal(fake_eeprom_write_fake.arg1_val, 8); |
| zassert_not_null(fake_eeprom_write_fake.arg2_val); |
| zassert_equal(fake_eeprom_write_fake.arg3_val, 8); |
| |
| /* ... and verify the written bytes by reading them back */ |
| zassert_equal(fake_eeprom_read_fake.call_count, 1); |
| zassert_equal(fake_eeprom_read_fake.arg0_val, fake_eeprom_dev); |
| zassert_equal(fake_eeprom_read_fake.arg1_val, 8); |
| zassert_not_null(fake_eeprom_read_fake.arg2_val); |
| zassert_equal(fake_eeprom_write_fake.arg3_val, 8); |
| |
| /* Verify data values parsed and written correctly */ |
| zassert_mem_equal(&data_capture, &expected, sizeof(expected)); |
| } |
| |
| ZTEST(eeprom_shell, test_eeprom_write_failed_verification) |
| { |
| const struct shell *sh = shell_backend_dummy_get_ptr(); |
| int err; |
| |
| err = shell_execute_cmd(sh, "eeprom write " FAKE_EEPROM_NAME " 0 0xaa 0x55"); |
| zassert_true(err < 0, "shell command should have failed (err %d)", err); |
| |
| /* The EEPROM shell will write the bytes ... */ |
| zassert_equal(fake_eeprom_write_fake.call_count, 1); |
| zassert_equal(fake_eeprom_write_fake.arg0_val, fake_eeprom_dev); |
| zassert_equal(fake_eeprom_write_fake.arg1_val, 0); |
| zassert_not_null(fake_eeprom_write_fake.arg2_val); |
| zassert_equal(fake_eeprom_write_fake.arg3_val, 2); |
| |
| /* ... and attempt to verify the written bytes by reading them back */ |
| zassert_equal(fake_eeprom_read_fake.call_count, 1); |
| zassert_equal(fake_eeprom_read_fake.arg0_val, fake_eeprom_dev); |
| zassert_equal(fake_eeprom_read_fake.arg1_val, 0); |
| zassert_not_null(fake_eeprom_read_fake.arg2_val); |
| zassert_equal(fake_eeprom_write_fake.arg3_val, 2); |
| } |
| |
| ZTEST(eeprom_shell, test_eeprom_read) |
| { |
| const struct shell *sh = shell_backend_dummy_get_ptr(); |
| int err; |
| |
| /* This test relies on the shell hexdumping 16 bytes per line */ |
| BUILD_ASSERT(SHELL_HEXDUMP_BYTES_IN_LINE == 16); |
| |
| /* The EEPROM shell will split this read into two calls to eeprom_read() */ |
| err = shell_execute_cmd(sh, "eeprom read " FAKE_EEPROM_NAME " 8 32"); |
| zassert_ok(err, "failed to execute shell command (err %d)", err); |
| zassert_equal(fake_eeprom_read_fake.call_count, 2); |
| |
| /* 1st read */ |
| zassert_equal(fake_eeprom_read_fake.arg0_history[0], fake_eeprom_dev); |
| zassert_equal(fake_eeprom_read_fake.arg1_history[0], 8); |
| zassert_not_null(fake_eeprom_read_fake.arg2_history[0]); |
| zassert_equal(fake_eeprom_read_fake.arg3_history[0], SHELL_HEXDUMP_BYTES_IN_LINE); |
| |
| /* 2nd read */ |
| zassert_equal(fake_eeprom_read_fake.arg0_history[1], fake_eeprom_dev); |
| zassert_equal(fake_eeprom_read_fake.arg1_history[1], 8 + SHELL_HEXDUMP_BYTES_IN_LINE); |
| zassert_not_null(fake_eeprom_read_fake.arg2_history[1]); |
| zassert_equal(fake_eeprom_read_fake.arg3_history[1], SHELL_HEXDUMP_BYTES_IN_LINE); |
| } |
| |
| ZTEST(eeprom_shell, test_eeprom_size) |
| { |
| const struct shell *sh = shell_backend_dummy_get_ptr(); |
| int err; |
| |
| err = shell_execute_cmd(sh, "eeprom size " FAKE_EEPROM_NAME); |
| zassert_ok(err, "failed to execute shell command (err %d)", err); |
| zassert_equal(fake_eeprom_size_fake.call_count, 1); |
| zassert_equal(fake_eeprom_size_fake.arg0_val, fake_eeprom_dev); |
| } |
| |
| ZTEST(eeprom_shell, test_eeprom_fill) |
| { |
| const struct shell *sh = shell_backend_dummy_get_ptr(); |
| const uint8_t expected[] = { 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa }; |
| int err; |
| |
| /* This test relies on the EEPROM shell using a buffer size of at least 8 bytes */ |
| BUILD_ASSERT(CONFIG_EEPROM_SHELL_BUFFER_SIZE >= 8); |
| |
| /* Setup data capture to satisfy EEPROM shell verification read-back */ |
| fake_eeprom_write_fake.custom_fake = eeprom_shell_test_write_capture_data; |
| fake_eeprom_read_fake.custom_fake = eeprom_shell_test_read_captured_data; |
| |
| err = shell_execute_cmd(sh, "eeprom fill " FAKE_EEPROM_NAME |
| " 16 8 0xaa"); |
| zassert_ok(err, "failed to execute shell command (err %d)", err); |
| |
| /* The EEPROM shell will write the bytes ... */ |
| zassert_equal(fake_eeprom_write_fake.call_count, 1); |
| zassert_equal(fake_eeprom_write_fake.arg0_val, fake_eeprom_dev); |
| zassert_equal(fake_eeprom_write_fake.arg1_val, 16); |
| zassert_not_null(fake_eeprom_write_fake.arg2_val); |
| zassert_equal(fake_eeprom_write_fake.arg3_val, 8); |
| |
| /* ... and verify the written bytes by reading them back */ |
| zassert_equal(fake_eeprom_read_fake.call_count, 1); |
| zassert_equal(fake_eeprom_read_fake.arg0_val, fake_eeprom_dev); |
| zassert_equal(fake_eeprom_read_fake.arg1_val, 16); |
| zassert_not_null(fake_eeprom_read_fake.arg2_val); |
| zassert_equal(fake_eeprom_write_fake.arg3_val, 8); |
| |
| /* Verify data values parsed and written correctly */ |
| zassert_mem_equal(&data_capture, &expected, sizeof(expected)); |
| } |
| |
| static void eeprom_shell_before(void *fixture) |
| { |
| ARG_UNUSED(fixture); |
| |
| memset(&data_capture, 0, sizeof(data_capture)); |
| } |
| |
| static void *eeprom_shell_setup(void) |
| { |
| const struct shell *sh = shell_backend_dummy_get_ptr(); |
| |
| zassert_true(device_is_ready(fake_eeprom_dev)); |
| |
| /* Verify that the EEPROM size is as expected by the tests */ |
| zassert_equal(KB(8), eeprom_get_size(fake_eeprom_dev)); |
| |
| /* Wait for the initialization of the shell dummy backend. */ |
| WAIT_FOR(shell_ready(sh), 20000, k_msleep(1)); |
| zassert_true(shell_ready(sh), "timed out waiting for dummy shell backend"); |
| |
| return NULL; |
| } |
| |
| ZTEST_SUITE(eeprom_shell, NULL, eeprom_shell_setup, eeprom_shell_before, NULL, NULL); |