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