1 /*
2  * Copyright (c) 2018 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include "settings_test.h"
8 #include "settings/settings_fcb.h"
9 
10 #define NAME_DELETABLE "4/deletable"
11 
12 struct flash_sector fcb_small_sectors[2] = {
13 	[0] = {
14 		.fs_off = 0x00000000,
15 		.fs_size = 4 * 1024
16 	},
17 	[1] = {
18 		.fs_off = 0x00001000,
19 		.fs_size = 4 * 1024
20 	}
21 };
22 
23 struct deletable_s {
24 	bool valid;
25 	uint32_t val32;
26 } deletable_val;
27 
28 uint32_t val4v2;
29 
30 int c4_handle_export(int (*cb)(const char *name, const void *value, size_t val_len));
31 int c4_handle_set(const char *name, size_t len, settings_read_cb read_cb,
32 		  void *cb_arg);
33 
34 struct settings_handler c4_test_handler = {
35 	.name = "4",
36 	.h_get = NULL,
37 	.h_set = c4_handle_set,
38 	.h_commit = NULL,
39 	.h_export = c4_handle_export
40 };
41 
c4_handle_set(const char * name,size_t len,settings_read_cb read_cb,void * cb_arg)42 int c4_handle_set(const char *name, size_t len, settings_read_cb read_cb,
43 		  void *cb_arg)
44 {
45 	return 0;
46 }
47 
c4_handle_export(int (* cb)(const char * name,const void * value,size_t val_len))48 int c4_handle_export(int (*cb)(const char *name, const void *value, size_t val_len))
49 {
50 	if (deletable_val.valid) {
51 		(void)cb(NAME_DELETABLE, &deletable_val.val32,
52 			 sizeof(deletable_val.val32));
53 	} else {
54 		(void)cb(NAME_DELETABLE, NULL, 0);
55 	}
56 
57 	(void)cb("4/dummy", &val4v2, sizeof(val4v2));
58 
59 	return 0;
60 }
61 
check_compressed_cb(struct fcb_entry_ctx * entry_ctx,void * arg)62 static int check_compressed_cb(struct fcb_entry_ctx *entry_ctx, void *arg)
63 {
64 	char buf[SETTINGS_MAX_NAME_LEN + SETTINGS_MAX_VAL_LEN +
65 		 SETTINGS_EXTRA_LEN];
66 	int rc;
67 	int len;
68 
69 	len = entry_ctx->loc.fe_data_len;
70 	if (len >= sizeof(buf)) {
71 		len = sizeof(buf) - 1;
72 	}
73 
74 	rc = flash_area_read(entry_ctx->fap,
75 			     FCB_ENTRY_FA_DATA_OFF(entry_ctx->loc), buf, len);
76 
77 	if (rc) {
78 		return 0;
79 	}
80 	buf[len] = '\0';
81 
82 	rc = strncmp(buf, NAME_DELETABLE, sizeof(NAME_DELETABLE)-1);
83 	zassert_true(rc != 0, "The deleted settings shouldn be compressed.");
84 
85 	return 0;
86 }
87 
ZTEST(settings_config_fcb,test_config_compress_deleted)88 ZTEST(settings_config_fcb, test_config_compress_deleted)
89 {
90 	int rc;
91 	struct settings_fcb cf;
92 	int i;
93 
94 	config_wipe_srcs();
95 	config_wipe_fcb(fcb_small_sectors, ARRAY_SIZE(fcb_small_sectors));
96 
97 	cf.cf_fcb.f_magic = CONFIG_SETTINGS_FCB_MAGIC;
98 	cf.cf_fcb.f_sectors = fcb_small_sectors;
99 	cf.cf_fcb.f_sector_cnt = ARRAY_SIZE(fcb_small_sectors);
100 
101 	rc = settings_fcb_src(&cf);
102 	zassert_true(rc == 0, "can't register FCB as configuration source");
103 	settings_mount_fcb_backend(&cf);
104 
105 	rc = settings_fcb_dst(&cf);
106 	zassert_true(rc == 0,
107 		     "can't register FCB as configuration destination");
108 
109 	rc = settings_register(&c4_test_handler);
110 	zassert_true(rc == 0, "settings_register fail");
111 
112 	deletable_val.valid = true;
113 	deletable_val.val32 = 2018U;
114 	val4v2 = 0U;
115 
116 	rc = settings_save();
117 	zassert_true(rc == 0, "fcb write error");
118 
119 	deletable_val.valid = false;
120 
121 	for (i = 0; ; i++) {
122 		val4v2++;
123 
124 		rc = settings_save();
125 		zassert_true(rc == 0, "fcb write error");
126 
127 		if (cf.cf_fcb.f_active.fe_sector == &fcb_small_sectors[1]) {
128 			/*
129 			 * The compression should happened while the active
130 			 * sector was changing.
131 			 */
132 			break;
133 		}
134 	}
135 
136 	rc = fcb_walk(&cf.cf_fcb, &fcb_small_sectors[1], check_compressed_cb,
137 		      NULL);
138 	settings_unregister(&c4_test_handler);
139 }
140