| /* |
| * Copyright (c) 2018 Nordic Semiconductor ASA |
| * Copyright (c) 2015 Runtime Inc |
| * |
| * SPDX-License-Identifier: Apache-2.0 |
| */ |
| #include <stdlib.h> |
| #include <string.h> |
| |
| #include "settings_test.h" |
| #include "settings_priv.h" |
| #include <zephyr/storage/flash_map.h> |
| |
| #define TEST_PARTITION storage_partition |
| #define TEST_PARTITION_ID FIXED_PARTITION_ID(TEST_PARTITION) |
| |
| uint8_t val8; |
| uint8_t val8_un; |
| uint32_t val32; |
| uint64_t val64; |
| |
| int test_get_called; |
| int test_set_called; |
| int test_commit_called; |
| int test_export_block; |
| |
| int c2_var_count = 1; |
| |
| int c1_handle_get(const char *name, char *val, int val_len_max); |
| int c1_handle_set(const char *name, size_t len, settings_read_cb read_cb, |
| void *cb_arg); |
| int c1_handle_commit(void); |
| int c1_handle_export(int (*cb)(const char *name, |
| const void *value, size_t val_len)); |
| |
| int c2_handle_get(const char *name, char *val, int val_len_max); |
| int c2_handle_set(const char *name, size_t len, settings_read_cb read_cb, |
| void *cb_arg); |
| int c2_handle_export(int (*cb)(const char *name, |
| const void *value, size_t val_len)); |
| |
| int c3_handle_get(const char *name, char *val, int val_len_max); |
| int c3_handle_set(const char *name, size_t len, settings_read_cb read_cb, |
| void *cb_arg); |
| int c3_handle_export(int (*cb)(const char *name, |
| const void *value, size_t val_len)); |
| |
| struct settings_handler c_test_handlers[] = { |
| { |
| .name = "myfoo", |
| .h_get = c1_handle_get, |
| .h_set = c1_handle_set, |
| .h_commit = c1_handle_commit, |
| .h_export = c1_handle_export |
| }, |
| { |
| .name = "2nd", |
| .h_get = c2_handle_get, |
| .h_set = c2_handle_set, |
| .h_commit = NULL, |
| .h_export = c2_handle_export |
| }, |
| { |
| .name = "3", |
| .h_get = c3_handle_get, |
| .h_set = c3_handle_set, |
| .h_commit = NULL, |
| .h_export = c3_handle_export |
| } |
| }; |
| |
| char val_string[SETTINGS_TEST_FCB_VAL_STR_CNT][SETTINGS_MAX_VAL_LEN]; |
| char test_ref_value[SETTINGS_TEST_FCB_VAL_STR_CNT][SETTINGS_MAX_VAL_LEN]; |
| |
| int c1_handle_get(const char *name, char *val, int val_len_max) |
| { |
| const char *next; |
| |
| test_get_called = 1; |
| |
| if (settings_name_steq(name, "mybar", &next) && !next) { |
| val_len_max = MIN(val_len_max, sizeof(val8)); |
| memcpy(val, &val8, MIN(val_len_max, sizeof(val8))); |
| return val_len_max; |
| } |
| |
| if (settings_name_steq(name, "mybar64", &next) && !next) { |
| val_len_max = MIN(val_len_max, sizeof(val64)); |
| memcpy(val, &val64, MIN(val_len_max, sizeof(val64))); |
| return val_len_max; |
| } |
| |
| return -ENOENT; |
| } |
| |
| int c1_handle_set(const char *name, size_t len, settings_read_cb read_cb, |
| void *cb_arg) |
| { |
| size_t val_len; |
| int rc; |
| const char *next; |
| |
| test_set_called = 1; |
| if (settings_name_steq(name, "mybar", &next) && !next) { |
| rc = read_cb(cb_arg, &val8, sizeof(val8)); |
| zassert_true(rc >= 0, "SETTINGS_VALUE_SET callback"); |
| return 0; |
| } |
| |
| if (settings_name_steq(name, "mybar64", &next) && !next) { |
| rc = read_cb(cb_arg, &val64, sizeof(val64)); |
| zassert_true(rc >= 0, "SETTINGS_VALUE_SET callback"); |
| return 0; |
| } |
| |
| if (settings_name_steq(name, "unaligned", &next) && !next) { |
| val_len = len; |
| zassert_equal(val_len, sizeof(val8_un), |
| "value length: %d, ought equal 1", val_len); |
| rc = read_cb(cb_arg, &val8_un, sizeof(val8_un)); |
| zassert_true(rc >= 0, "SETTINGS_VALUE_SET callback"); |
| return 0; |
| } |
| |
| return -ENOENT; |
| } |
| |
| int c1_handle_commit(void) |
| { |
| test_commit_called = 1; |
| return 0; |
| } |
| |
| int c1_handle_export(int (*cb)(const char *name, |
| const void *value, size_t val_len)) |
| { |
| if (test_export_block) { |
| return 0; |
| } |
| |
| (void)cb("myfoo/mybar", &val8, sizeof(val8)); |
| |
| (void)cb("myfoo/mybar64", &val64, sizeof(val64)); |
| |
| (void)cb("myfoo/unaligned", &val8_un, sizeof(val8_un)); |
| |
| return 0; |
| } |
| |
| void ctest_clear_call_state(void) |
| { |
| test_get_called = 0; |
| test_set_called = 0; |
| test_commit_called = 0; |
| } |
| |
| int ctest_get_call_state(void) |
| { |
| return test_get_called + test_set_called + test_commit_called; |
| } |
| |
| void config_wipe_srcs(void) |
| { |
| sys_slist_init(&settings_load_srcs); |
| settings_save_dst = NULL; |
| } |
| |
| struct flash_sector fcb_sectors[SETTINGS_TEST_FCB_FLASH_CNT] = { |
| [0] = { |
| .fs_off = 0x00000000, |
| .fs_size = 16 * 1024 |
| }, |
| [1] = { |
| .fs_off = 0x00004000, |
| .fs_size = 16 * 1024 |
| }, |
| [2] = { |
| .fs_off = 0x00008000, |
| .fs_size = 16 * 1024 |
| }, |
| [3] = { |
| .fs_off = 0x0000c000, |
| .fs_size = 16 * 1024 |
| } |
| }; |
| |
| void config_wipe_fcb(struct flash_sector *fs, int cnt) |
| { |
| const struct flash_area *fap; |
| int rc; |
| int i; |
| |
| rc = flash_area_open(TEST_PARTITION_ID, &fap); |
| |
| for (i = 0; i < cnt; i++) { |
| rc = flash_area_erase(fap, fs[i].fs_off, fs[i].fs_size); |
| zassert_true(rc == 0, "Can't get flash area"); |
| } |
| } |
| |
| void |
| test_config_fill_area(char test_value[SETTINGS_TEST_FCB_VAL_STR_CNT] |
| [SETTINGS_MAX_VAL_LEN], |
| int iteration) |
| { |
| int i, j; |
| |
| for (j = 0; j < 64; j++) { |
| for (i = 0; i < SETTINGS_MAX_VAL_LEN; i++) { |
| test_value[j][i] = ((j * 2) + i + iteration) % 10 + '0'; |
| } |
| test_value[j][sizeof(test_value[j]) - 1] = '\0'; |
| } |
| } |
| |
| char *c2_var_find(char *name) |
| { |
| int idx = 0; |
| int len; |
| char *eptr; |
| |
| len = strlen(name); |
| zassert_true(len > 6, "string type expected"); |
| zassert_true(!strncmp(name, "string", 6), "string type expected"); |
| |
| idx = strtoul(&name[6], &eptr, 10); |
| zassert_true(*eptr == '\0', "EOF"); |
| zassert_true(idx < c2_var_count, |
| "var index greater than any exporter"); |
| |
| return val_string[idx]; |
| } |
| |
| int c2_handle_get(const char *name, char *val, int val_len_max) |
| { |
| int len; |
| char *valptr; |
| const char *next; |
| char argv[32]; |
| |
| len = settings_name_next(name, &next); |
| if (len && !next) { |
| strncpy(argv, name, len); |
| argv[len] = '\0'; |
| valptr = c2_var_find(argv); |
| if (!valptr) { |
| return -ENOENT; |
| } |
| |
| len = strlen(val_string[0]); |
| if (len > val_len_max) { |
| len = val_len_max; |
| } |
| |
| len = MIN(strlen(valptr), len); |
| memcpy(val, valptr, len); |
| return len; |
| } |
| |
| return -ENOENT; |
| } |
| |
| int c2_handle_set(const char *name, size_t len, settings_read_cb read_cb, |
| void *cb_arg) |
| { |
| char *valptr; |
| const char *next; |
| char argv[32]; |
| |
| int rc; |
| |
| len = settings_name_next(name, &next); |
| if (len && !next) { |
| strncpy(argv, name, len); |
| argv[len] = '\0'; |
| valptr = c2_var_find(argv); |
| if (!valptr) { |
| return -ENOENT; |
| } |
| |
| rc = read_cb(cb_arg, valptr, sizeof(val_string[0])); |
| zassert_true(rc >= 0, "SETTINGS_VALUE_SET callback"); |
| if (rc == 0) { |
| (void)memset(valptr, 0, sizeof(val_string[0])); |
| } |
| |
| return 0; |
| } |
| |
| return -ENOENT; |
| } |
| |
| int c2_handle_export(int (*cb)(const char *name, |
| const void *value, size_t val_len)) |
| { |
| int i; |
| char name[32]; |
| |
| for (i = 0; i < c2_var_count; i++) { |
| snprintf(name, sizeof(name), "2nd/string%d", i); |
| (void)cb(name, val_string[i], strlen(val_string[i])); |
| } |
| |
| return 0; |
| } |
| |
| int c3_handle_get(const char *name, char *val, int val_len_max) |
| { |
| const char *next; |
| |
| if (settings_name_steq(name, "v", &next) && !next) { |
| val_len_max = MIN(val_len_max, sizeof(val32)); |
| memcpy(val, &val32, MIN(val_len_max, sizeof(val32))); |
| return val_len_max; |
| } |
| return -EINVAL; |
| } |
| |
| int c3_handle_set(const char *name, size_t len, settings_read_cb read_cb, |
| void *cb_arg) |
| { |
| int rc; |
| size_t val_len; |
| const char *next; |
| |
| if (settings_name_steq(name, "v", &next) && !next) { |
| val_len = len; |
| zassert_true(val_len == 4, "bad set-value size"); |
| |
| rc = read_cb(cb_arg, &val32, sizeof(val32)); |
| zassert_true(rc >= 0, "SETTINGS_VALUE_SET callback"); |
| return 0; |
| } |
| |
| return -ENOENT; |
| } |
| |
| int c3_handle_export(int (*cb)(const char *name, |
| const void *value, size_t val_len)) |
| { |
| (void)cb("3/v", &val32, sizeof(val32)); |
| |
| |
| return 0; |
| } |
| |
| void *settings_config_fcb_setup(void) |
| { |
| const struct flash_area *fap; |
| int rc; |
| uint8_t wbs; |
| |
| rc = flash_area_open(TEST_PARTITION_ID, &fap); |
| zassume_true(rc == 0, "Can't open storage flash area"); |
| |
| wbs = flash_area_align(fap); |
| zassume_true(wbs <= 32, |
| "Flash driver is not compatible with the settings fcb-backend"); |
| return NULL; |
| } |
| |
| ZTEST(settings_config_fcb, test_config_insert_handler2) |
| { |
| test_config_insert2(); |
| } |
| |
| ZTEST(settings_config_fcb, test_config_insert_handler3) |
| { |
| test_config_insert3(); |
| } |
| |
| ZTEST_SUITE(settings_config, NULL, settings_config_setup, NULL, NULL, |
| settings_config_teardown); |
| ZTEST_SUITE(settings_config_fcb, NULL, settings_config_fcb_setup, |
| NULL, NULL, NULL); |