1 /*
2 * Copyright (c) 2020 Nordic Semiconductor
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 /**
8 * @file
9 * @brief Test logging to file system
10 *
11 */
12
13 #include <stdbool.h>
14 #include <stdlib.h>
15 #include <zephyr/kernel.h>
16 #include <zephyr/ztest.h>
17 #include <zephyr/fs/fs.h>
18
19 #define DT_DRV_COMPAT zephyr_fstab_littlefs
20 #define TEST_AUTOMOUNT DT_PROP(DT_DRV_INST(0), automount)
21 #if !TEST_AUTOMOUNT
22 #include <zephyr/fs/littlefs.h>
23 #define PARTITION_NODE DT_NODELABEL(lfs1)
24 FS_FSTAB_DECLARE_ENTRY(PARTITION_NODE);
25 #endif
26
27 #define MAX_PATH_LEN (256 + 7)
28
29 static const char *log_prefix = CONFIG_LOG_BACKEND_FS_FILE_PREFIX;
30
31 int write_log_to_file(uint8_t *data, size_t length, void *ctx);
32
33
ZTEST(test_log_backend_fs,test_fs_nonexist)34 ZTEST(test_log_backend_fs, test_fs_nonexist)
35 {
36 #if TEST_AUTOMOUNT
37 ztest_test_skip();
38 #else
39 uint8_t to_log[] = "Log to left behind";
40 int rc;
41
42 rc = write_log_to_file(to_log, sizeof(to_log), NULL);
43 zassert_equal(rc, sizeof(to_log), "Unexpected rteval.");
44 struct fs_mount_t *mp = &FS_FSTAB_ENTRY(PARTITION_NODE);
45
46 rc = fs_mount(mp);
47 zassert_equal(rc, 0, "Can not mount FS.");
48 #endif
49 }
50
ZTEST(test_log_backend_fs,test_wipe_fs_logs)51 ZTEST(test_log_backend_fs, test_wipe_fs_logs)
52 {
53 int rc;
54 struct fs_dir_t dir;
55 struct fs_file_t file;
56 char fname[MAX_PATH_LEN];
57
58 fs_dir_t_init(&dir);
59 fs_file_t_init(&file);
60
61 rc = fs_opendir(&dir, CONFIG_LOG_BACKEND_FS_DIR);
62 if (rc) {
63 /* log directory might not exist jet */
64 return;
65 }
66
67 /* Iterate over logging directory. */
68 while (1) {
69 struct fs_dirent ent = { 0 };
70
71 rc = fs_readdir(&dir, &ent);
72 zassert_equal(rc, 0, "Can not read directory.");
73 if ((rc < 0) || (ent.name[0] == 0)) {
74 break;
75 }
76 if (ent.type == FS_DIR_ENTRY_FILE &&
77 strncmp(ent.name, log_prefix, strlen(log_prefix)) == 0) {
78 sprintf(fname, "%s/%s", CONFIG_LOG_BACKEND_FS_DIR,
79 ent.name);
80 rc = fs_unlink(fname);
81 zassert_equal(rc, 0, "Can not remove file %s.", fname);
82 TC_PRINT("removed: %s\n", fname);
83 }
84 }
85
86 (void)fs_closedir(&dir);
87 }
88
ZTEST(test_log_backend_fs,test_log_fs_file_content)89 ZTEST(test_log_backend_fs, test_log_fs_file_content)
90 {
91 int rc;
92 struct fs_file_t file;
93 char log_read[MAX_PATH_LEN];
94 uint8_t to_log[] = "Correct Log 1";
95 static char fname[MAX_PATH_LEN];
96
97 fs_file_t_init(&file);
98
99 rc = write_log_to_file(to_log, sizeof(to_log), NULL);
100
101 sprintf(fname, "%s/%s0000", CONFIG_LOG_BACKEND_FS_DIR, log_prefix);
102
103 zassert_equal(fs_open(&file, fname, FS_O_READ), 0,
104 "Can not open log file.");
105
106 zassert_true(fs_read(&file, log_read, MAX_PATH_LEN) >= 0,
107 "Can not read log file.");
108
109 rc = strncmp(log_read, to_log, sizeof(log_read));
110 zassert_equal(rc, 0, "Text inside log file is not correct.");
111
112 zassert_equal(fs_close(&file), 0, "Can not close log file.");
113
114 to_log[sizeof(to_log)-2] = '2';
115 rc = write_log_to_file(to_log, sizeof(to_log), NULL);
116
117 zassert_equal(fs_open(&file, fname, FS_O_READ), 0,
118 "Can not open log file.");
119
120 zassert_equal(fs_seek(&file, sizeof(to_log), FS_SEEK_SET), 0,
121 "Bad file size");
122
123 zassert_true(fs_read(&file, log_read, MAX_PATH_LEN) >= 0,
124 "Can not read log file.");
125
126 rc = strncmp(log_read, to_log, sizeof(log_read));
127 zassert_equal(rc, 0, "Text inside log file is not correct.");
128
129 zassert_equal(fs_close(&file), 0, "Can not close log file.");
130 }
131
ZTEST(test_log_backend_fs,test_log_fs_file_size)132 ZTEST(test_log_backend_fs, test_log_fs_file_size)
133 {
134 int rc;
135 int i;
136 struct fs_dir_t dir;
137 int file_ctr = 0;
138 static char fname[MAX_PATH_LEN];
139 uint8_t to_log[] = "Text Log";
140 struct fs_dirent entry;
141
142 fs_dir_t_init(&dir);
143
144 sprintf(fname, "%s/%s0000", CONFIG_LOG_BACKEND_FS_DIR, log_prefix);
145 zassert_equal(fs_stat(fname, &entry), 0, "Can not get file info.");
146
147 /* Fill in log file over size limit. */
148 for (i = 0;
149 i <= (CONFIG_LOG_BACKEND_FS_FILE_SIZE - entry.size) /
150 sizeof(to_log);
151 i++) {
152 rc = write_log_to_file(to_log, sizeof(to_log), NULL);
153 /* Written length not tracked here. */
154 ARG_UNUSED(rc);
155 }
156
157 zassert_equal(fs_stat(fname, &entry), 0, "Can not get file info.");
158 size_t exp_size = CONFIG_LOG_BACKEND_FS_FILE_SIZE -
159 (CONFIG_LOG_BACKEND_FS_FILE_SIZE - entry.size) %
160 sizeof(to_log);
161 zassert_equal(entry.size, exp_size, "Unexpected %s file size (%d B)",
162 fname, entry.size);
163
164 sprintf(fname, "%s/%s0001", CONFIG_LOG_BACKEND_FS_DIR, log_prefix);
165 zassert_equal(fs_stat(fname, &entry), 0, "Can not get file info.");
166
167 zassert_equal(entry.size, sizeof(to_log),
168 "Unexpected %s file size (%d B)",
169 fname, entry.size);
170
171 rc = fs_opendir(&dir, CONFIG_LOG_BACKEND_FS_DIR);
172 zassert_equal(rc, 0, "Can not open directory.");
173 /* Count number of log files. */
174 while (rc >= 0) {
175 struct fs_dirent ent = { 0 };
176
177 rc = fs_readdir(&dir, &ent);
178 if ((rc < 0) || (ent.name[0] == 0)) {
179 break;
180 }
181 if (strstr(ent.name, log_prefix) != NULL) {
182 ++file_ctr;
183 }
184 }
185 (void)fs_closedir(&dir);
186 zassert_equal(file_ctr, 2, "File changing failed");
187 }
188
ZTEST(test_log_backend_fs,test_log_fs_files_max)189 ZTEST(test_log_backend_fs, test_log_fs_files_max)
190 {
191 int rc;
192 int i;
193 struct fs_dir_t dir;
194 int file_ctr = 0;
195 uint8_t to_log[] = "Text Log";
196 struct fs_dirent ent;
197 uint32_t test_mask = 0;
198
199 fs_dir_t_init(&dir);
200
201 /* Fill in log files over files count limit. */
202 for (i = 0;
203 i <= CONFIG_LOG_BACKEND_FS_FILE_SIZE /
204 sizeof(to_log) * (CONFIG_LOG_BACKEND_FS_FILES_LIMIT - 1);
205 i++) {
206 rc = write_log_to_file(to_log, sizeof(to_log), NULL);
207 /* Written length not tracked here. */
208 ARG_UNUSED(rc);
209 }
210
211 rc = fs_opendir(&dir, CONFIG_LOG_BACKEND_FS_DIR);
212 zassert_equal(rc, 0, "Can not open directory.");
213 /* Count log files. */
214 while (rc >= 0) {
215
216 rc = fs_readdir(&dir, &ent);
217 if ((rc < 0) || (ent.name[0] == 0)) {
218 break;
219 }
220 if (strstr(ent.name, log_prefix) != NULL) {
221 ++file_ctr;
222 test_mask |= 1 << atoi(&ent.name[strlen(log_prefix)]);
223 }
224 }
225 (void)fs_closedir(&dir);
226 zassert_equal(file_ctr, CONFIG_LOG_BACKEND_FS_FILES_LIMIT,
227 "Bad files count: expected %d, got %d ",
228 CONFIG_LOG_BACKEND_FS_FILES_LIMIT, file_ctr);
229 /*expected files: log.0001, log.0002, log.0003, log.0004 */
230 zassert_equal(test_mask, 0b11110, "Unexpected file numeration");
231 }
232
233 ZTEST_SUITE(test_log_backend_fs, NULL, NULL, NULL, NULL, NULL);
234