/* * Copyright (c) 2018 Nordic Semiconductor ASA * Copyright (c) 2015 Runtime Inc * * SPDX-License-Identifier: Apache-2.0 */ #include #include #include "settings_test.h" #include "settings_priv.h" #include #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_flatten(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);