1 /*
2 * Copyright (c) 2018 Nordic Semiconductor ASA
3 * Copyright (c) 2015 Runtime Inc
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7 #include <stdlib.h>
8 #include <string.h>
9
10 #include "settings_test.h"
11 #include "settings_priv.h"
12 #include <zephyr/storage/flash_map.h>
13
14 #define TEST_PARTITION storage_partition
15 #define TEST_PARTITION_ID FIXED_PARTITION_ID(TEST_PARTITION)
16
17 uint8_t val8;
18 uint8_t val8_un;
19 uint32_t val32;
20 uint64_t val64;
21
22 int test_get_called;
23 int test_set_called;
24 int test_commit_called;
25 int test_export_block;
26
27 int c2_var_count = 1;
28
29 int c1_handle_get(const char *name, char *val, int val_len_max);
30 int c1_handle_set(const char *name, size_t len, settings_read_cb read_cb,
31 void *cb_arg);
32 int c1_handle_commit(void);
33 int c1_handle_export(int (*cb)(const char *name,
34 const void *value, size_t val_len));
35
36 int c2_handle_get(const char *name, char *val, int val_len_max);
37 int c2_handle_set(const char *name, size_t len, settings_read_cb read_cb,
38 void *cb_arg);
39 int c2_handle_export(int (*cb)(const char *name,
40 const void *value, size_t val_len));
41
42 int c3_handle_get(const char *name, char *val, int val_len_max);
43 int c3_handle_set(const char *name, size_t len, settings_read_cb read_cb,
44 void *cb_arg);
45 int c3_handle_export(int (*cb)(const char *name,
46 const void *value, size_t val_len));
47
48 struct settings_handler c_test_handlers[] = {
49 {
50 .name = "myfoo",
51 .h_get = c1_handle_get,
52 .h_set = c1_handle_set,
53 .h_commit = c1_handle_commit,
54 .h_export = c1_handle_export
55 },
56 {
57 .name = "2nd",
58 .h_get = c2_handle_get,
59 .h_set = c2_handle_set,
60 .h_commit = NULL,
61 .h_export = c2_handle_export
62 },
63 {
64 .name = "3",
65 .h_get = c3_handle_get,
66 .h_set = c3_handle_set,
67 .h_commit = NULL,
68 .h_export = c3_handle_export
69 }
70 };
71
72 char val_string[SETTINGS_TEST_FCB_VAL_STR_CNT][SETTINGS_MAX_VAL_LEN];
73 char test_ref_value[SETTINGS_TEST_FCB_VAL_STR_CNT][SETTINGS_MAX_VAL_LEN];
74
c1_handle_get(const char * name,char * val,int val_len_max)75 int c1_handle_get(const char *name, char *val, int val_len_max)
76 {
77 const char *next;
78
79 test_get_called = 1;
80
81 if (settings_name_steq(name, "mybar", &next) && !next) {
82 val_len_max = MIN(val_len_max, sizeof(val8));
83 memcpy(val, &val8, MIN(val_len_max, sizeof(val8)));
84 return val_len_max;
85 }
86
87 if (settings_name_steq(name, "mybar64", &next) && !next) {
88 val_len_max = MIN(val_len_max, sizeof(val64));
89 memcpy(val, &val64, MIN(val_len_max, sizeof(val64)));
90 return val_len_max;
91 }
92
93 return -ENOENT;
94 }
95
c1_handle_set(const char * name,size_t len,settings_read_cb read_cb,void * cb_arg)96 int c1_handle_set(const char *name, size_t len, settings_read_cb read_cb,
97 void *cb_arg)
98 {
99 size_t val_len;
100 int rc;
101 const char *next;
102
103 test_set_called = 1;
104 if (settings_name_steq(name, "mybar", &next) && !next) {
105 rc = read_cb(cb_arg, &val8, sizeof(val8));
106 zassert_true(rc >= 0, "SETTINGS_VALUE_SET callback");
107 return 0;
108 }
109
110 if (settings_name_steq(name, "mybar64", &next) && !next) {
111 rc = read_cb(cb_arg, &val64, sizeof(val64));
112 zassert_true(rc >= 0, "SETTINGS_VALUE_SET callback");
113 return 0;
114 }
115
116 if (settings_name_steq(name, "unaligned", &next) && !next) {
117 val_len = len;
118 zassert_equal(val_len, sizeof(val8_un),
119 "value length: %d, ought equal 1", val_len);
120 rc = read_cb(cb_arg, &val8_un, sizeof(val8_un));
121 zassert_true(rc >= 0, "SETTINGS_VALUE_SET callback");
122 return 0;
123 }
124
125 return -ENOENT;
126 }
127
c1_handle_commit(void)128 int c1_handle_commit(void)
129 {
130 test_commit_called = 1;
131 return 0;
132 }
133
c1_handle_export(int (* cb)(const char * name,const void * value,size_t val_len))134 int c1_handle_export(int (*cb)(const char *name,
135 const void *value, size_t val_len))
136 {
137 if (test_export_block) {
138 return 0;
139 }
140
141 (void)cb("myfoo/mybar", &val8, sizeof(val8));
142
143 (void)cb("myfoo/mybar64", &val64, sizeof(val64));
144
145 (void)cb("myfoo/unaligned", &val8_un, sizeof(val8_un));
146
147 return 0;
148 }
149
ctest_clear_call_state(void)150 void ctest_clear_call_state(void)
151 {
152 test_get_called = 0;
153 test_set_called = 0;
154 test_commit_called = 0;
155 }
156
ctest_get_call_state(void)157 int ctest_get_call_state(void)
158 {
159 return test_get_called + test_set_called + test_commit_called;
160 }
161
config_wipe_srcs(void)162 void config_wipe_srcs(void)
163 {
164 sys_slist_init(&settings_load_srcs);
165 settings_save_dst = NULL;
166 }
167
168 struct flash_sector fcb_sectors[SETTINGS_TEST_FCB_FLASH_CNT] = {
169 [0] = {
170 .fs_off = 0x00000000,
171 .fs_size = 16 * 1024
172 },
173 [1] = {
174 .fs_off = 0x00004000,
175 .fs_size = 16 * 1024
176 },
177 [2] = {
178 .fs_off = 0x00008000,
179 .fs_size = 16 * 1024
180 },
181 [3] = {
182 .fs_off = 0x0000c000,
183 .fs_size = 16 * 1024
184 }
185 };
186
config_wipe_fcb(struct flash_sector * fs,int cnt)187 void config_wipe_fcb(struct flash_sector *fs, int cnt)
188 {
189 const struct flash_area *fap;
190 int rc;
191 int i;
192
193 rc = flash_area_open(TEST_PARTITION_ID, &fap);
194
195 for (i = 0; i < cnt; i++) {
196 rc = flash_area_erase(fap, fs[i].fs_off, fs[i].fs_size);
197 zassert_true(rc == 0, "Can't get flash area");
198 }
199 }
200
201 void
test_config_fill_area(char test_value[SETTINGS_TEST_FCB_VAL_STR_CNT][SETTINGS_MAX_VAL_LEN],int iteration)202 test_config_fill_area(char test_value[SETTINGS_TEST_FCB_VAL_STR_CNT]
203 [SETTINGS_MAX_VAL_LEN],
204 int iteration)
205 {
206 int i, j;
207
208 for (j = 0; j < 64; j++) {
209 for (i = 0; i < SETTINGS_MAX_VAL_LEN; i++) {
210 test_value[j][i] = ((j * 2) + i + iteration) % 10 + '0';
211 }
212 test_value[j][sizeof(test_value[j]) - 1] = '\0';
213 }
214 }
215
c2_var_find(char * name)216 char *c2_var_find(char *name)
217 {
218 int idx = 0;
219 int len;
220 char *eptr;
221
222 len = strlen(name);
223 zassert_true(len > 6, "string type expected");
224 zassert_true(!strncmp(name, "string", 6), "string type expected");
225
226 idx = strtoul(&name[6], &eptr, 10);
227 zassert_true(*eptr == '\0', "EOF");
228 zassert_true(idx < c2_var_count,
229 "var index greater than any exporter");
230
231 return val_string[idx];
232 }
233
c2_handle_get(const char * name,char * val,int val_len_max)234 int c2_handle_get(const char *name, char *val, int val_len_max)
235 {
236 int len;
237 char *valptr;
238 const char *next;
239 char argv[32];
240
241 len = settings_name_next(name, &next);
242 if (len && !next) {
243 strncpy(argv, name, len);
244 argv[len] = '\0';
245 valptr = c2_var_find(argv);
246 if (!valptr) {
247 return -ENOENT;
248 }
249
250 len = strlen(val_string[0]);
251 if (len > val_len_max) {
252 len = val_len_max;
253 }
254
255 len = MIN(strlen(valptr), len);
256 memcpy(val, valptr, len);
257 return len;
258 }
259
260 return -ENOENT;
261 }
262
c2_handle_set(const char * name,size_t len,settings_read_cb read_cb,void * cb_arg)263 int c2_handle_set(const char *name, size_t len, settings_read_cb read_cb,
264 void *cb_arg)
265 {
266 char *valptr;
267 const char *next;
268 char argv[32];
269
270 int rc;
271
272 len = settings_name_next(name, &next);
273 if (len && !next) {
274 strncpy(argv, name, len);
275 argv[len] = '\0';
276 valptr = c2_var_find(argv);
277 if (!valptr) {
278 return -ENOENT;
279 }
280
281 rc = read_cb(cb_arg, valptr, sizeof(val_string[0]));
282 zassert_true(rc >= 0, "SETTINGS_VALUE_SET callback");
283 if (rc == 0) {
284 (void)memset(valptr, 0, sizeof(val_string[0]));
285 }
286
287 return 0;
288 }
289
290 return -ENOENT;
291 }
292
c2_handle_export(int (* cb)(const char * name,const void * value,size_t val_len))293 int c2_handle_export(int (*cb)(const char *name,
294 const void *value, size_t val_len))
295 {
296 int i;
297 char name[32];
298
299 for (i = 0; i < c2_var_count; i++) {
300 snprintf(name, sizeof(name), "2nd/string%d", i);
301 (void)cb(name, val_string[i], strlen(val_string[i]));
302 }
303
304 return 0;
305 }
306
c3_handle_get(const char * name,char * val,int val_len_max)307 int c3_handle_get(const char *name, char *val, int val_len_max)
308 {
309 const char *next;
310
311 if (settings_name_steq(name, "v", &next) && !next) {
312 val_len_max = MIN(val_len_max, sizeof(val32));
313 memcpy(val, &val32, MIN(val_len_max, sizeof(val32)));
314 return val_len_max;
315 }
316 return -EINVAL;
317 }
318
c3_handle_set(const char * name,size_t len,settings_read_cb read_cb,void * cb_arg)319 int c3_handle_set(const char *name, size_t len, settings_read_cb read_cb,
320 void *cb_arg)
321 {
322 int rc;
323 size_t val_len;
324 const char *next;
325
326 if (settings_name_steq(name, "v", &next) && !next) {
327 val_len = len;
328 zassert_true(val_len == 4, "bad set-value size");
329
330 rc = read_cb(cb_arg, &val32, sizeof(val32));
331 zassert_true(rc >= 0, "SETTINGS_VALUE_SET callback");
332 return 0;
333 }
334
335 return -ENOENT;
336 }
337
c3_handle_export(int (* cb)(const char * name,const void * value,size_t val_len))338 int c3_handle_export(int (*cb)(const char *name,
339 const void *value, size_t val_len))
340 {
341 (void)cb("3/v", &val32, sizeof(val32));
342
343
344 return 0;
345 }
346
settings_config_fcb_setup(void)347 void *settings_config_fcb_setup(void)
348 {
349 const struct flash_area *fap;
350 int rc;
351 uint8_t wbs;
352
353 rc = flash_area_open(TEST_PARTITION_ID, &fap);
354 zassume_true(rc == 0, "Can't open storage flash area");
355
356 wbs = flash_area_align(fap);
357 zassume_true(wbs <= 32,
358 "Flash driver is not compatible with the settings fcb-backend");
359 return NULL;
360 }
361
ZTEST(settings_config_fcb,test_config_insert_handler2)362 ZTEST(settings_config_fcb, test_config_insert_handler2)
363 {
364 test_config_insert2();
365 }
366
ZTEST(settings_config_fcb,test_config_insert_handler3)367 ZTEST(settings_config_fcb, test_config_insert_handler3)
368 {
369 test_config_insert3();
370 }
371
372 ZTEST_SUITE(settings_config, NULL, settings_config_setup, NULL, NULL,
373 settings_config_teardown);
374 ZTEST_SUITE(settings_config_fcb, NULL, settings_config_fcb_setup,
375 NULL, NULL, NULL);
376