Branch data Line data Source code
1 : : #include "sute.h"
2 : :
3 : : /**
4 : : * @brief Verify reporting and preservation of inaccessible paths
5 : : *
6 : : * Makes one file and one directory inaccessible, runs an update without
7 : : * `--db-drop-inaccessible`, and verifies that the expected inaccessible-path
8 : : * messages are produced while their database records are retained
9 : : */
10 : 2 : static Return test0029_1(void)
11 : : {
12 : 2 : INITTEST;
13 : :
14 : : // Create memory for the result
15 : 2 : m_create(char,result,MEMORY_STRING);
16 : 2 : m_create(char,pattern,MEMORY_STRING);
17 : :
18 : : // Preparation for tests
19 : 2 : ASSERT(SUCCESS == prepare_mutable_fixture("tests/fixtures/diffs/diff1"));
20 : :
21 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","false"));
22 : :
23 : 2 : const char *arguments = "--silent --database=database1.db tests/fixtures/diffs/diff1";
24 : :
25 : 2 : ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
26 : :
27 : 2 : ASSERT(result->length == 0);
28 : :
29 : 2 : ASSERT(SUCCESS == change_mode("tests/fixtures/diffs/diff1/1/AAA/ZAW/D/e/f/b_file.txt",0000));
30 : 2 : ASSERT(SUCCESS == change_mode("tests/fixtures/diffs/diff1/2/AAA/BBB/CZC",0000));
31 : :
32 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
33 : :
34 : 2 : arguments = "--update --database=database1.db tests/fixtures/diffs/diff1";
35 : :
36 : 2 : ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
37 : :
38 : 2 : const char *filename = "templates/0029_001.txt";
39 : :
40 : 2 : ASSERT(SUCCESS == get_file_content(filename,pattern));
41 : 2 : ASSERT(SUCCESS == match_pattern(result,pattern,filename));
42 : :
43 : 2 : m_del(pattern);
44 : 2 : m_del(result);
45 : :
46 : : // Clean up test results
47 : 2 : ASSERT(SUCCESS == delete_path("database1.db"));
48 : 2 : ASSERT(SUCCESS == change_mode("tests/fixtures/diffs/diff1/1/AAA/ZAW/D/e/f/b_file.txt",0666));
49 : 2 : ASSERT(SUCCESS == change_mode("tests/fixtures/diffs/diff1/2/AAA/BBB/CZC",0777));
50 : 2 : ASSERT(SUCCESS == restore_mutable_fixture("tests/fixtures/diffs/diff1"));
51 : :
52 : 2 : RETURN_STATUS;
53 : : }
54 : :
55 : : /**
56 : : * @brief Verify removal of inaccessible records with --db-drop-inaccessible
57 : : *
58 : : * Makes one file and one directory inaccessible, enables
59 : : * `--db-drop-inaccessible`, and verifies that their database records are
60 : : * removed during the update
61 : : */
62 : 2 : static Return test0029_2(void)
63 : : {
64 : 2 : INITTEST;
65 : :
66 : : // Create memory for the result
67 : 2 : m_create(char,result,MEMORY_STRING);
68 : 2 : m_create(char,pattern,MEMORY_STRING);
69 : :
70 : : // Preparation for tests
71 : 2 : ASSERT(SUCCESS == prepare_mutable_fixture("tests/fixtures/diffs/diff1"));
72 : :
73 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","false"));
74 : :
75 : 2 : const char *arguments = "--silent --database=database2.db tests/fixtures/diffs/diff1";
76 : :
77 : 2 : ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
78 : :
79 : 2 : ASSERT(result->length == 0);
80 : :
81 : 2 : ASSERT(SUCCESS == change_mode("tests/fixtures/diffs/diff1/1/AAA/ZAW/D/e/f/b_file.txt",0000));
82 : 2 : ASSERT(SUCCESS == change_mode("tests/fixtures/diffs/diff1/2/AAA/BBB/CZC",0000));
83 : :
84 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
85 : :
86 : 2 : arguments = "--update --db-drop-inaccessible --database=database2.db "
87 : : "tests/fixtures/diffs/diff1";
88 : :
89 : 2 : ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
90 : :
91 : 2 : const char *filename = "templates/0029_002.txt";
92 : :
93 : 2 : ASSERT(SUCCESS == get_file_content(filename,pattern));
94 : 2 : ASSERT(SUCCESS == match_pattern(result,pattern,filename));
95 : :
96 : 2 : m_del(pattern);
97 : 2 : m_del(result);
98 : :
99 : : // Clean up test results
100 : 2 : ASSERT(SUCCESS == delete_path("database2.db"));
101 : 2 : ASSERT(SUCCESS == change_mode("tests/fixtures/diffs/diff1/1/AAA/ZAW/D/e/f/b_file.txt",0666));
102 : 2 : ASSERT(SUCCESS == change_mode("tests/fixtures/diffs/diff1/2/AAA/BBB/CZC",0777));
103 : 2 : ASSERT(SUCCESS == restore_mutable_fixture("tests/fixtures/diffs/diff1"));
104 : :
105 : 2 : RETURN_STATUS;
106 : : }
107 : :
108 : : /**
109 : : * @brief Verify that an access-check failure for one regular file does not stop traversal
110 : : *
111 : : * Forces one early file to report FILE_ACCESS_ERROR during an update run, then
112 : : * changes a later file. The update for the later file proves that traversal
113 : : * continued after the access-check failure
114 : : */
115 : 2 : static Return test0029_3(void)
116 : : {
117 : 2 : INITTEST;
118 : :
119 : 2 : m_create(char,result,MEMORY_STRING);
120 : 2 : m_create(char,pattern,MEMORY_STRING);
121 : :
122 : 2 : const char *db_filename = "database3.db";
123 : 2 : const char *access_error_root_path = "tests/fixtures/diffs/diff1";
124 : 2 : const char *access_error_relative_path = "1/AAA/ZAW/D/e/f/b_file.txt";
125 : 2 : const char *changed_later_file_path = "tests/fixtures/diffs/diff1/4/AAA/BBB/CCC/a.txt";
126 : :
127 : 2 : ASSERT(SUCCESS == prepare_mutable_fixture("tests/fixtures/diffs/diff1"));
128 : :
129 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","false"));
130 : :
131 : 2 : const char *arguments = "--silent --database=database3.db tests/fixtures/diffs/diff1";
132 : :
133 : 2 : ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
134 : :
135 : 2 : ASSERT(result->length == 0);
136 : :
137 : 2 : ASSERT(SUCCESS == replase_to_string("access check failure must not stop traversal",changed_later_file_path));
138 : :
139 : 2 : ASSERT(SUCCESS == expect_file_access_from_root(
140 : : access_error_root_path,
141 : : access_error_relative_path,
142 : : R_OK,
143 : : FILE_ACCESS_ALLOWED));
144 : :
145 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTITALL_TEST_ENV_FILE_ACCESS_SUFFIX",access_error_relative_path));
146 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTITALL_TEST_ENV_FILE_ACCESS_STATUS","FILE_ACCESS_ERROR"));
147 : 2 : ASSERT(SUCCESS == expect_file_access_from_root(
148 : : access_error_root_path,
149 : : access_error_relative_path,
150 : : R_OK,
151 : : FILE_ACCESS_ERROR));
152 : :
153 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
154 : :
155 : 2 : arguments = "--update --database=database3.db tests/fixtures/diffs/diff1";
156 : :
157 : 2 : ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
158 : :
159 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTITALL_TEST_ENV_FILE_ACCESS_SUFFIX",""));
160 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTITALL_TEST_ENV_FILE_ACCESS_STATUS",""));
161 : :
162 : 2 : const char *filename = "templates/0029_003.txt";
163 : :
164 : 2 : ASSERT(SUCCESS == get_file_content(filename,pattern));
165 : 2 : ASSERT(SUCCESS == match_pattern(result,pattern,filename));
166 : :
167 : 2 : m_del(pattern);
168 : 2 : m_del(result);
169 : :
170 : 2 : ASSERT(SUCCESS == delete_path(db_filename));
171 : 2 : ASSERT(SUCCESS == restore_mutable_fixture("tests/fixtures/diffs/diff1"));
172 : :
173 : 2 : RETURN_STATUS;
174 : : }
175 : :
176 : : /**
177 : : * @brief Verify that every root opening failure safely skips metadata cleanup
178 : : *
179 : : * Creates a baseline database, skips file traversal, and forces root opening
180 : : * to report access denied, not found, and an unexpected access error. Every
181 : : * update uses `--db-drop-inaccessible` and must still finish successfully
182 : : * without deleting file records. The complete output from every update is
183 : : * matched against the same PCRE2 template
184 : : */
185 : 2 : static Return test0029_4(void)
186 : : {
187 : 2 : INITTEST;
188 : :
189 : 2 : m_create(char,result,MEMORY_STRING);
190 : 2 : m_create(char,pattern,MEMORY_STRING);
191 : :
192 : 2 : const char *db_filename = "database4.db";
193 : 2 : const char *filename = "templates/0029_004.txt";
194 : 2 : const char *root_access_statuses[] = {
195 : : "FILE_ACCESS_DENIED",
196 : : "FILE_NOT_FOUND",
197 : : "FILE_ACCESS_ERROR"
198 : : };
199 : 2 : const size_t root_access_status_count =
200 : : sizeof(root_access_statuses) / sizeof(root_access_statuses[0]);
201 : 2 : int files_count_before = 0;
202 : :
203 : 2 : ASSERT(SUCCESS == prepare_mutable_fixture("tests/fixtures/diffs/diff1"));
204 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","false"));
205 : :
206 : 2 : const char *arguments = "--silent --database=database4.db tests/fixtures/diffs/diff1";
207 : :
208 : 2 : ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
209 : 2 : ASSERT(result->length == 0);
210 : 2 : ASSERT(SUCCESS == db_read_files_count(db_filename,&files_count_before));
211 : 2 : ASSERT(files_count_before > 0);
212 : :
213 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
214 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTITALL_TEST_ENV_SKIP_FILE_LIST","1"));
215 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTITALL_TEST_ENV_FILE_ACCESS_SUFFIX","diff1"));
216 : 2 : ASSERT(SUCCESS == get_file_content(filename,pattern));
217 : :
218 : 2 : arguments = "--update --db-drop-inaccessible --database=database4.db "
219 : : "tests/fixtures/diffs/diff1";
220 : :
221 [ + + ]: 8 : for(size_t index = 0; index < root_access_status_count; index++)
222 : : {
223 : 6 : int files_count_after = 0;
224 : :
225 : 6 : ASSERT(SUCCESS == set_environment_variable(
226 : : "TESTITALL_TEST_ENV_FILE_ACCESS_STATUS",
227 : : root_access_statuses[index]));
228 : :
229 : 6 : ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
230 : 6 : ASSERT(SUCCESS == match_pattern(result,pattern,filename));
231 : :
232 : 6 : ASSERT(SUCCESS == db_read_files_count(db_filename,&files_count_after));
233 : 6 : ASSERT(files_count_after == files_count_before);
234 : : }
235 : :
236 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTITALL_TEST_ENV_SKIP_FILE_LIST",""));
237 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTITALL_TEST_ENV_FILE_ACCESS_SUFFIX",""));
238 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTITALL_TEST_ENV_FILE_ACCESS_STATUS",""));
239 : :
240 : 2 : m_del(pattern);
241 : 2 : m_del(result);
242 : :
243 : 2 : ASSERT(SUCCESS == delete_path(db_filename));
244 : 2 : ASSERT(SUCCESS == restore_mutable_fixture("tests/fixtures/diffs/diff1"));
245 : :
246 : 2 : RETURN_STATUS;
247 : : }
248 : :
249 : : /**
250 : : * @brief Verify that an unavailable PATH root does not stop later roots
251 : : *
252 : : * Forces the first of two traversal roots to fail during root opening. The
253 : : * unavailable root must be reported immediately and shown again in the final
254 : : * warning summary, while a file from the second root must still be written to
255 : : * the database
256 : : */
257 : 2 : static Return test0029_5(void)
258 : : {
259 : 2 : INITTEST;
260 : :
261 : 2 : m_create(char,result,MEMORY_STRING);
262 : 2 : m_create(char,pattern,MEMORY_STRING);
263 : :
264 : 2 : const char *db_filename = "database5.db";
265 : 2 : const char *filename = "templates/0029_005.txt";
266 : 2 : const char *available_relative_path = "AAA/BBB/CCC/a.txt";
267 : 2 : bool available_path_exists = false;
268 : :
269 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","false"));
270 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTITALL_TEST_ENV_FILE_ACCESS_SUFFIX","diff1/1"));
271 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTITALL_TEST_ENV_FILE_ACCESS_STATUS","FILE_ACCESS_DENIED"));
272 : :
273 : 2 : const char *arguments = "--database=database5.db "
274 : : "tests/fixtures/diffs/diff1/1 tests/fixtures/diffs/diff1/4";
275 : :
276 : 2 : ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
277 : :
278 : 2 : ASSERT(SUCCESS == get_file_content(filename,pattern));
279 : 2 : ASSERT(SUCCESS == match_pattern(result,pattern,filename));
280 : 2 : ASSERT(SUCCESS == db_relative_path_exists(db_filename,available_relative_path,&available_path_exists));
281 : 2 : ASSERT(available_path_exists == true);
282 : :
283 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTITALL_TEST_ENV_FILE_ACCESS_SUFFIX",""));
284 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTITALL_TEST_ENV_FILE_ACCESS_STATUS",""));
285 : :
286 : 2 : m_del(pattern);
287 : 2 : m_del(result);
288 : :
289 : 2 : ASSERT(SUCCESS == delete_path(db_filename));
290 : :
291 : 2 : RETURN_STATUS;
292 : : }
293 : :
294 : : /**
295 : : * @brief Verify --db-drop-inaccessible does not override ignore scope
296 : : *
297 : : * Makes one file inaccessible and ignores the same relative path during update.
298 : : * Even with --db-drop-inaccessible, the ignored non-locked row must stay in the
299 : : * DB and must not be reported through inaccessible cleanup
300 : : */
301 : 2 : static Return test0029_6(void)
302 : : {
303 : 2 : INITTEST;
304 : :
305 : 2 : m_create(char,result,MEMORY_STRING);
306 : 2 : m_create(char,pattern,MEMORY_STRING);
307 : :
308 : 2 : const char *db_filename = "database6.db";
309 : 2 : const char *ignored_relative_path = "1/AAA/ZAW/D/e/f/b_file.txt";
310 : 2 : bool ignored_path_exists = false;
311 : :
312 : 2 : ASSERT(SUCCESS == prepare_mutable_fixture("tests/fixtures/diffs/diff1"));
313 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","false"));
314 : :
315 : 2 : const char *arguments = "--silent --database=database6.db tests/fixtures/diffs/diff1";
316 : :
317 : 2 : ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
318 : 2 : ASSERT(result->length == 0);
319 : :
320 : 2 : ASSERT(SUCCESS == change_mode("tests/fixtures/diffs/diff1/1/AAA/ZAW/D/e/f/b_file.txt",0000));
321 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
322 : :
323 : 2 : arguments = "--update --db-drop-inaccessible "
324 : : "--ignore=\"^1/AAA/ZAW/D/e/f/b_file\\.txt$\" "
325 : : "--database=database6.db tests/fixtures/diffs/diff1";
326 : :
327 : 2 : ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
328 : :
329 : 2 : const char *filename = "templates/0029_006.txt";
330 : 2 : ASSERT(SUCCESS == get_file_content(filename,pattern));
331 : 2 : ASSERT(SUCCESS == match_pattern(result,pattern,filename));
332 : :
333 : 2 : ASSERT(SUCCESS == db_relative_path_exists(db_filename,ignored_relative_path,&ignored_path_exists));
334 : 2 : ASSERT(ignored_path_exists == true);
335 : :
336 : 2 : m_del(pattern);
337 : 2 : m_del(result);
338 : :
339 : 2 : ASSERT(SUCCESS == change_mode("tests/fixtures/diffs/diff1/1/AAA/ZAW/D/e/f/b_file.txt",0666));
340 : 2 : ASSERT(SUCCESS == delete_path(db_filename));
341 : 2 : ASSERT(SUCCESS == restore_mutable_fixture("tests/fixtures/diffs/diff1"));
342 : :
343 : 2 : RETURN_STATUS;
344 : : }
345 : :
346 : : /**
347 : : * @brief Run inaccessible-path behavior tests
348 : : *
349 : : * Covers preservation, explicit removal, unexpected file access-check failure,
350 : : * safe cleanup skipping, and continued traversal after a PATH root cannot be
351 : : * opened
352 : : */
353 : 2 : Return test0029(void)
354 : : {
355 : 2 : INITTEST;
356 : :
357 : 2 : TEST(test0029_1,"Inaccessible paths are reported and kept by default");
358 : 2 : TEST(test0029_2,"--db-drop-inaccessible drops inaccessible DB records");
359 : 2 : TEST(test0029_3,"Access-check failure for a regular file does not stop traversal");
360 : 2 : TEST(test0029_4,"Root opening failures skip metadata cleanup without deleting records");
361 : 2 : TEST(test0029_5,"Unavailable PATH root is remembered while later roots continue");
362 : 2 : TEST(test0029_6,"--db-drop-inaccessible does not override ignore scope");
363 : :
364 : 2 : RETURN_STATUS;
365 : : }
|