Branch data Line data Source code
1 : : #include "sute.h"
2 : :
3 : : /**
4 : : * @brief Corrupt stored SHA512 bytes for one locked file row in DB
5 : : *
6 : : * @param[in] db_filename Database filename relative to TMPDIR
7 : : * @param[in] relative_path Relative path key in files table
8 : : *
9 : : * @return Return status code:
10 : : * - SUCCESS: SHA512 value was updated for at least one row
11 : : * - FAILURE: Validation, DB access, bind, step, or change check failed
12 : : */
13 : 2 : static Return db_tamper_locked_checksum(
14 : : const char *db_filename,
15 : : const char *relative_path)
16 : : {
17 : : /* Status returned by this function through provide()
18 : : Default value assumes successful completion */
19 : 2 : Return status = SUCCESS;
20 : 2 : sqlite3 *db = NULL;
21 : 2 : sqlite3_stmt *stmt = NULL;
22 : 2 : const char *sql = "UPDATE files SET sha512 = (substr(sha512,1,2) || X'BEEF' || substr(sha512,5)) " "WHERE relative_path = ?1;";
23 : :
24 : 2 : create(char,db_path);
25 : :
26 [ + - + - : 2 : if(SUCCESS == status && (db_filename == NULL || relative_path == NULL))
- + ]
27 : : {
28 : 0 : status = FAILURE;
29 : : }
30 : :
31 [ + - ]: 2 : if(SUCCESS == status)
32 : : {
33 : 2 : status = construct_path(db_filename,db_path);
34 : : }
35 : :
36 [ + - - + ]: 2 : if(SUCCESS == status && SQLITE_OK != sqlite3_open_v2(getcstring(db_path),&db,SQLITE_OPEN_READWRITE,NULL))
37 : : {
38 : 0 : status = FAILURE;
39 : : }
40 : :
41 [ + - - + ]: 2 : if(SUCCESS == status && SQLITE_OK != sqlite3_prepare_v2(db,sql,-1,&stmt,NULL))
42 : : {
43 : 0 : status = FAILURE;
44 : : }
45 : :
46 [ + - - + ]: 2 : if(SUCCESS == status && SQLITE_OK != sqlite3_bind_text(stmt,1,relative_path,(int)strlen(relative_path),SQLITE_TRANSIENT))
47 : : {
48 : 0 : status = FAILURE;
49 : : }
50 : :
51 [ + - - + ]: 2 : if(SUCCESS == status && SQLITE_DONE != sqlite3_step(stmt))
52 : : {
53 : 0 : status = FAILURE;
54 : : }
55 : :
56 [ + - - + ]: 2 : if(SUCCESS == status && sqlite3_changes(db) < 1)
57 : : {
58 : 0 : status = FAILURE;
59 : : }
60 : :
61 [ + - ]: 2 : if(stmt != NULL)
62 : : {
63 : 2 : (void)sqlite3_finalize(stmt);
64 : : }
65 : :
66 [ + - ]: 2 : if(db != NULL)
67 : : {
68 : 2 : (void)sqlite3_close(db);
69 : : }
70 : :
71 : 2 : del(db_path);
72 : :
73 : 2 : return(status);
74 : : }
75 : :
76 : : /**
77 : : * @brief Read CmpctStat blob for one file by relative path
78 : : *
79 : : * @param[in] db_filename Database filename relative to TMPDIR
80 : : * @param[in] relative_path Relative path key in files table
81 : : * @param[out] stat_out Output compact stat structure
82 : : *
83 : : * @return Return status code:
84 : : * - SUCCESS: CmpctStat value was read
85 : : * - FAILURE: Validation, DB access, blob size check, or row parsing failed
86 : : */
87 : 8 : static Return read_cmpctstat_from_db(
88 : : const char *db_filename,
89 : : const char *relative_path,
90 : : CmpctStat *stat_out)
91 : : {
92 : : /* Status returned by this function through provide()
93 : : Default value assumes successful completion */
94 : 8 : Return status = SUCCESS;
95 : 8 : sqlite3 *db = NULL;
96 : 8 : sqlite3_stmt *stmt = NULL;
97 : 8 : const char *sql = "SELECT stat FROM files WHERE relative_path = ?1;";
98 : 8 : create(char,db_path);
99 : :
100 [ + - + - : 8 : if(SUCCESS == status && (db_filename == NULL || relative_path == NULL || stat_out == NULL))
+ - - + ]
101 : : {
102 : 0 : status = FAILURE;
103 : : }
104 : :
105 [ + - ]: 8 : if(SUCCESS == status)
106 : : {
107 : 8 : status = construct_path(db_filename,db_path);
108 : : }
109 : :
110 [ + - - + ]: 8 : if(SUCCESS == status && SQLITE_OK != sqlite3_open_v2(getcstring(db_path),&db,SQLITE_OPEN_READONLY,NULL))
111 : : {
112 : 0 : status = FAILURE;
113 : : }
114 : :
115 [ + - - + ]: 8 : if(SUCCESS == status && SQLITE_OK != sqlite3_prepare_v2(db,sql,-1,&stmt,NULL))
116 : : {
117 : 0 : status = FAILURE;
118 : : }
119 : :
120 [ + - - + ]: 8 : if(SUCCESS == status && SQLITE_OK != sqlite3_bind_text(stmt,1,relative_path,(int)strlen(relative_path),SQLITE_TRANSIENT))
121 : : {
122 : 0 : status = FAILURE;
123 : : }
124 : :
125 [ + - ]: 8 : if(SUCCESS == status)
126 : : {
127 : 8 : int rc = sqlite3_step(stmt);
128 : :
129 [ + - ]: 8 : if(rc == SQLITE_ROW)
130 : : {
131 : 8 : const void *blob = sqlite3_column_blob(stmt,0);
132 : 8 : int bytes = sqlite3_column_bytes(stmt,0);
133 : :
134 [ + - - + ]: 8 : if(blob == NULL || bytes != (int)sizeof(CmpctStat))
135 : : {
136 : 0 : status = FAILURE;
137 : : } else {
138 : 8 : memcpy(stat_out,blob,sizeof(CmpctStat));
139 : : }
140 : :
141 : 8 : rc = sqlite3_step(stmt);
142 : :
143 [ + - - + ]: 8 : if(SUCCESS == status && rc != SQLITE_DONE)
144 : : {
145 : 0 : status = FAILURE;
146 : : }
147 : : } else {
148 : 0 : status = FAILURE;
149 : : }
150 : : }
151 : :
152 [ + - ]: 8 : if(stmt != NULL)
153 : : {
154 : 8 : (void)sqlite3_finalize(stmt);
155 : : }
156 : :
157 [ + - ]: 8 : if(db != NULL)
158 : : {
159 : 8 : (void)sqlite3_close(db);
160 : : }
161 : :
162 : 8 : del(db_path);
163 : :
164 : 8 : return(status);
165 : : }
166 : :
167 : : /**
168 : : * @brief Check whether DB compact-stat timestamps match the current file stat timestamps
169 : : *
170 : : * @param[in] db_stat Compact stat loaded from the database
171 : : * @param[in] file_stat Current filesystem stat structure
172 : : * @return `true` when both ctime and mtime fields match exactly, otherwise `false`
173 : : */
174 : 8 : static bool cmpctstat_matches_stat_timestamps(
175 : : const CmpctStat *db_stat,
176 : : const struct stat *file_stat)
177 : : {
178 [ + - - + ]: 8 : if(db_stat == NULL || file_stat == NULL)
179 : : {
180 : 0 : return(false);
181 : : }
182 : :
183 : 16 : return(db_stat->mtim_tv_sec == file_stat->st_mtim.tv_sec &&
184 [ + - ]: 8 : db_stat->mtim_tv_nsec == file_stat->st_mtim.tv_nsec &&
185 [ + - + - ]: 24 : db_stat->ctim_tv_sec == file_stat->st_ctim.tv_sec &&
186 [ + - ]: 8 : db_stat->ctim_tv_nsec == file_stat->st_ctim.tv_nsec);
187 : : }
188 : :
189 : : /**
190 : : * @brief README --lock-checksum example: on-disk size change of a locked file
191 : : * with --rehash-locked triggers WARNING
192 : : */
193 : 2 : static Return test0030_1(void)
194 : : {
195 : 2 : INITTEST;
196 : :
197 : 2 : create(char,result);
198 : 2 : create(char,pattern);
199 : :
200 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
201 : :
202 : 2 : ASSERT(SUCCESS == move_path("tests/fixtures/diffs/diff1","tests/fixtures/diff1_backup"));
203 : 2 : ASSERT(SUCCESS == copy_path("tests/fixtures/diff1_backup","tests/fixtures/diffs/diff1"));
204 : :
205 : 2 : const char *arguments = "--database=lock_s1.db --progress "
206 : : "--lock-checksum=\"^path1/.*\" tests/fixtures/diffs/diff1";
207 : :
208 : 2 : ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
209 : :
210 : 2 : const char *filename = "templates/0030_001_1.txt";
211 : :
212 : 2 : ASSERT(SUCCESS == get_file_content(filename,pattern));
213 : :
214 : 2 : ASSERT(SUCCESS == match_pattern(result,pattern,filename));
215 : :
216 : 2 : ASSERT(SUCCESS == write_string_to_file("pad",
217 : : "tests/fixtures/diffs/diff1/path1/AAA/BCB/CCC/a.txt",
218 : : FILE_WRITE_APPEND));
219 : :
220 : 2 : arguments = "--update --rehash-locked --lock-checksum=\"^path1/.*\" "
221 : : "--database=lock_s1.db tests/fixtures/diffs/diff1";
222 : :
223 : 2 : ASSERT(SUCCESS == runit(arguments,result,NULL,WARNING,ALLOW_BOTH));
224 : :
225 : 2 : filename = "templates/0030_001_2.txt";
226 : :
227 : 2 : ASSERT(SUCCESS == get_file_content(filename,pattern));
228 : :
229 : 2 : ASSERT(SUCCESS == match_pattern(result,pattern,filename));
230 : :
231 : 2 : ASSERT(SUCCESS == delete_path("lock_s1.db"));
232 : 2 : ASSERT(SUCCESS == delete_path("tests/fixtures/diffs/diff1"));
233 : 2 : ASSERT(SUCCESS == move_path("tests/fixtures/diff1_backup","tests/fixtures/diffs/diff1"));
234 : :
235 : 2 : del(pattern);
236 : 2 : del(result);
237 : :
238 : 2 : RETURN_STATUS;
239 : : }
240 : :
241 : : /**
242 : : * @brief README --lock-checksum example: timestamp-only drift with
243 : : * --watch-timestamps and without --rehash-locked triggers WARNING
244 : : */
245 : 2 : static Return test0030_2(void)
246 : : {
247 : 2 : INITTEST;
248 : :
249 : 2 : create(char,result);
250 : 2 : create(char,pattern);
251 : :
252 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
253 : :
254 : 2 : ASSERT(SUCCESS == move_path("tests/fixtures/diffs/diff1","tests/fixtures/diff1_backup"));
255 : 2 : ASSERT(SUCCESS == copy_path("tests/fixtures/diff1_backup","tests/fixtures/diffs/diff1"));
256 : :
257 : 2 : const char *arguments = "--database=lock_s2.db --progress "
258 : : "--lock-checksum=\"^path1/.*\" tests/fixtures/diffs/diff1";
259 : :
260 : 2 : ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
261 : :
262 : 2 : const char *filename = "templates/0030_002_1.txt";
263 : :
264 : 2 : ASSERT(SUCCESS == get_file_content(filename,pattern));
265 : :
266 : 2 : ASSERT(SUCCESS == match_pattern(result,pattern,filename));
267 : :
268 : : // Bump file mtime by a nanosecond delta without changing file content
269 : 2 : ASSERT(SUCCESS == touch_file_mtime_with_reference_delta_ns(NULL,"tests/fixtures/diffs/diff1/path1/AAA/BCB/CCC/a.txt",999));
270 : :
271 : 2 : arguments = "--update --watch-timestamps --lock-checksum=\"^path1/.*\" "
272 : : "--database=lock_s2.db tests/fixtures/diffs/diff1";
273 : :
274 : 2 : ASSERT(SUCCESS == runit(arguments,result,NULL,WARNING,ALLOW_BOTH));
275 : :
276 : 2 : filename = "templates/0030_002_2.txt";
277 : :
278 : 2 : ASSERT(SUCCESS == get_file_content(filename,pattern));
279 : :
280 : 2 : ASSERT(SUCCESS == match_pattern(result,pattern,filename));
281 : :
282 : 2 : ASSERT(SUCCESS == delete_path("lock_s2.db"));
283 : 2 : ASSERT(SUCCESS == delete_path("tests/fixtures/diffs/diff1"));
284 : 2 : ASSERT(SUCCESS == move_path("tests/fixtures/diff1_backup","tests/fixtures/diffs/diff1"));
285 : :
286 : 2 : del(pattern);
287 : 2 : del(result);
288 : :
289 : 2 : RETURN_STATUS;
290 : : }
291 : :
292 : : /**
293 : : * @brief README --lock-checksum example: timestamp-only drift without
294 : : * --watch-timestamps and without --rehash-locked completes successfully
295 : : */
296 : 2 : static Return test0030_3(void)
297 : : {
298 : 2 : INITTEST;
299 : :
300 : 2 : create(char,result);
301 : 2 : create(char,pattern);
302 : :
303 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
304 : :
305 : 2 : ASSERT(SUCCESS == move_path("tests/fixtures/diffs/diff1","tests/fixtures/diff1_backup"));
306 : 2 : ASSERT(SUCCESS == copy_path("tests/fixtures/diff1_backup","tests/fixtures/diffs/diff1"));
307 : :
308 : 2 : const char *arguments = "--database=lock_s3.db --progress "
309 : : "--lock-checksum=\"^path1/.*\" tests/fixtures/diffs/diff1";
310 : :
311 : 2 : ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
312 : :
313 : 2 : const char *filename = "templates/0030_003_1.txt";
314 : :
315 : 2 : ASSERT(SUCCESS == get_file_content(filename,pattern));
316 : :
317 : 2 : ASSERT(SUCCESS == match_pattern(result,pattern,filename));
318 : :
319 : : // Bump file mtime by a nanosecond delta without changing file content
320 : 2 : ASSERT(SUCCESS == touch_file_mtime_with_reference_delta_ns(NULL,"tests/fixtures/diffs/diff1/path1/AAA/BCB/CCC/a.txt",999));
321 : :
322 : 2 : arguments = "--update --lock-checksum=\"^path1/.*\" "
323 : : "--database=lock_s3.db tests/fixtures/diffs/diff1";
324 : :
325 : 2 : ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
326 : :
327 : 2 : filename = "templates/0030_003_2.txt";
328 : :
329 : 2 : ASSERT(SUCCESS == get_file_content(filename,pattern));
330 : :
331 : 2 : ASSERT(SUCCESS == match_pattern(result,pattern,filename));
332 : :
333 : 2 : ASSERT(SUCCESS == delete_path("lock_s3.db"));
334 : 2 : ASSERT(SUCCESS == delete_path("tests/fixtures/diffs/diff1"));
335 : 2 : ASSERT(SUCCESS == move_path("tests/fixtures/diff1_backup","tests/fixtures/diffs/diff1"));
336 : :
337 : 2 : del(pattern);
338 : 2 : del(result);
339 : :
340 : 2 : RETURN_STATUS;
341 : : }
342 : :
343 : : /**
344 : : * @brief README --lock-checksum example: timestamp-only drift with
345 : : * --watch-timestamps and with --rehash-locked completes successfully and
346 : : * synchronizes DB timestamps
347 : : */
348 : 2 : static Return test0030_4(void)
349 : : {
350 : 2 : INITTEST;
351 : :
352 : 2 : create(char,result);
353 : 2 : create(char,pattern);
354 : 2 : create(char,target_path);
355 : 2 : struct stat file_stat_before = {0};
356 : 2 : struct stat file_stat_after = {0};
357 : 2 : CmpctStat db_stat_before = {0};
358 : 2 : CmpctStat db_stat_after = {0};
359 : :
360 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
361 : :
362 : 2 : ASSERT(SUCCESS == move_path("tests/fixtures/diffs/diff1","tests/fixtures/diff1_backup"));
363 : 2 : ASSERT(SUCCESS == copy_path("tests/fixtures/diff1_backup","tests/fixtures/diffs/diff1"));
364 : :
365 : 2 : const char *arguments = "--database=lock_s4.db --progress "
366 : : "--lock-checksum=\"^path1/.*\" tests/fixtures/diffs/diff1";
367 : :
368 : 2 : ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
369 : :
370 : 2 : const char *filename = "templates/0030_004_1.txt";
371 : :
372 : 2 : ASSERT(SUCCESS == get_file_content(filename,pattern));
373 : :
374 : 2 : ASSERT(SUCCESS == match_pattern(result,pattern,filename));
375 : :
376 : 2 : ASSERT(SUCCESS == construct_path("tests/fixtures/diffs/diff1/path1/AAA/BCB/CCC/a.txt",target_path));
377 : :
378 : 2 : ASSERT(SUCCESS == read_cmpctstat_from_db("lock_s4.db","path1/AAA/BCB/CCC/a.txt",&db_stat_before));
379 : :
380 : 2 : ASSERT(SUCCESS == get_file_stat(getcstring(target_path),&file_stat_before));
381 : :
382 : 2 : ASSERT(cmpctstat_matches_stat_timestamps(&db_stat_before,&file_stat_before));
383 : :
384 : : // Bump file mtime by a nanosecond delta without changing file content
385 : 2 : ASSERT(SUCCESS == touch_file_mtime_with_reference_delta_ns(NULL,"tests/fixtures/diffs/diff1/path1/AAA/BCB/CCC/a.txt",999));
386 : :
387 : 2 : arguments = "--update --watch-timestamps --rehash-locked "
388 : : "--lock-checksum=\"^path1/.*\" --database=lock_s4.db "
389 : : "tests/fixtures/diffs/diff1";
390 : :
391 : 2 : ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
392 : :
393 : 2 : filename = "templates/0030_004_2.txt";
394 : :
395 : 2 : ASSERT(SUCCESS == get_file_content(filename,pattern));
396 : :
397 : 2 : ASSERT(SUCCESS == match_pattern(result,pattern,filename));
398 : :
399 : 2 : ASSERT(SUCCESS == read_cmpctstat_from_db("lock_s4.db","path1/AAA/BCB/CCC/a.txt",&db_stat_after));
400 : :
401 : 2 : ASSERT(SUCCESS == get_file_stat(getcstring(target_path),&file_stat_after));
402 : :
403 : 2 : ASSERT(cmpctstat_matches_stat_timestamps(&db_stat_after,&file_stat_after));
404 : :
405 : 2 : ASSERT(SUCCESS == delete_path("lock_s4.db"));
406 : 2 : ASSERT(SUCCESS == delete_path("tests/fixtures/diffs/diff1"));
407 : 2 : ASSERT(SUCCESS == move_path("tests/fixtures/diff1_backup","tests/fixtures/diffs/diff1"));
408 : :
409 : 2 : del(target_path);
410 : 2 : del(pattern);
411 : 2 : del(result);
412 : :
413 : 2 : RETURN_STATUS;
414 : : }
415 : :
416 : : /**
417 : : * @brief README --lock-checksum example: timestamp-only drift without
418 : : * --watch-timestamps and with --rehash-locked completes successfully and
419 : : * synchronizes DB timestamps
420 : : */
421 : 2 : static Return test0030_5(void)
422 : : {
423 : 2 : INITTEST;
424 : :
425 : 2 : create(char,result);
426 : 2 : create(char,pattern);
427 : 2 : create(char,target_path);
428 : 2 : struct stat file_stat_before = {0};
429 : 2 : struct stat file_stat_after = {0};
430 : 2 : CmpctStat db_stat_before = {0};
431 : 2 : CmpctStat db_stat_after = {0};
432 : :
433 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
434 : :
435 : 2 : ASSERT(SUCCESS == move_path("tests/fixtures/diffs/diff1","tests/fixtures/diff1_backup"));
436 : 2 : ASSERT(SUCCESS == copy_path("tests/fixtures/diff1_backup","tests/fixtures/diffs/diff1"));
437 : :
438 : 2 : const char *arguments = "--database=lock_s5.db --progress "
439 : : "--lock-checksum=\"^path1/.*\" tests/fixtures/diffs/diff1";
440 : :
441 : 2 : ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
442 : :
443 : 2 : const char *filename = "templates/0030_005_1.txt";
444 : :
445 : 2 : ASSERT(SUCCESS == get_file_content(filename,pattern));
446 : :
447 : 2 : ASSERT(SUCCESS == match_pattern(result,pattern,filename));
448 : :
449 : 2 : ASSERT(SUCCESS == construct_path("tests/fixtures/diffs/diff1/path1/AAA/BCB/CCC/a.txt",target_path));
450 : :
451 : 2 : ASSERT(SUCCESS == read_cmpctstat_from_db("lock_s5.db","path1/AAA/BCB/CCC/a.txt",&db_stat_before));
452 : :
453 : 2 : ASSERT(SUCCESS == get_file_stat(getcstring(target_path),&file_stat_before));
454 : :
455 : 2 : ASSERT(cmpctstat_matches_stat_timestamps(&db_stat_before,&file_stat_before));
456 : :
457 : : // Bump file mtime by a nanosecond delta without changing file content
458 : 2 : ASSERT(SUCCESS == touch_file_mtime_with_reference_delta_ns(NULL,"tests/fixtures/diffs/diff1/path1/AAA/BCB/CCC/a.txt",999));
459 : :
460 : 2 : arguments = "--update --rehash-locked --lock-checksum=\"^path1/.*\" "
461 : : "--database=lock_s5.db tests/fixtures/diffs/diff1";
462 : :
463 : 2 : ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
464 : :
465 : 2 : filename = "templates/0030_005_2.txt";
466 : :
467 : 2 : ASSERT(SUCCESS == get_file_content(filename,pattern));
468 : :
469 : 2 : ASSERT(SUCCESS == match_pattern(result,pattern,filename));
470 : :
471 : 2 : ASSERT(SUCCESS == read_cmpctstat_from_db("lock_s5.db","path1/AAA/BCB/CCC/a.txt",&db_stat_after));
472 : :
473 : 2 : ASSERT(SUCCESS == get_file_stat(getcstring(target_path),&file_stat_after));
474 : :
475 : 2 : ASSERT(cmpctstat_matches_stat_timestamps(&db_stat_after,&file_stat_after));
476 : :
477 : 2 : ASSERT(SUCCESS == delete_path("lock_s5.db"));
478 : 2 : ASSERT(SUCCESS == delete_path("tests/fixtures/diffs/diff1"));
479 : 2 : ASSERT(SUCCESS == move_path("tests/fixtures/diff1_backup","tests/fixtures/diffs/diff1"));
480 : :
481 : 2 : del(target_path);
482 : 2 : del(pattern);
483 : 2 : del(result);
484 : :
485 : 2 : RETURN_STATUS;
486 : : }
487 : :
488 : : /**
489 : : * @brief README --lock-checksum example extension: timestamp-only drift on one
490 : : * locked file plus a stored checksum mismatch on another locked file triggers
491 : : * WARNING under --watch-timestamps and --rehash-locked
492 : : */
493 : 2 : static Return test0030_6(void)
494 : : {
495 : 2 : INITTEST;
496 : :
497 : 2 : create(char,result);
498 : 2 : create(char,pattern);
499 : :
500 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
501 : :
502 : 2 : ASSERT(SUCCESS == move_path("tests/fixtures/diffs/diff1","tests/fixtures/diff1_backup"));
503 : 2 : ASSERT(SUCCESS == copy_path("tests/fixtures/diff1_backup","tests/fixtures/diffs/diff1"));
504 : :
505 : 2 : const char *arguments = "--database=lock_s6.db --progress "
506 : : "--lock-checksum=\"^path1/.*\" tests/fixtures/diffs/diff1";
507 : :
508 : 2 : ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
509 : :
510 : 2 : const char *filename = "templates/0030_006_1.txt";
511 : :
512 : 2 : ASSERT(SUCCESS == get_file_content(filename,pattern));
513 : :
514 : 2 : ASSERT(SUCCESS == match_pattern(result,pattern,filename));
515 : :
516 : : // Bump file mtime by a nanosecond delta without changing file content
517 : 2 : ASSERT(SUCCESS == touch_file_mtime_with_reference_delta_ns(NULL,"tests/fixtures/diffs/diff1/path1/AAA/BCB/CCC/a.txt",999));
518 : :
519 : : // Corrupt the stored checksum for a locked file without touching it on disk
520 : 2 : ASSERT(SUCCESS == db_tamper_locked_checksum("lock_s6.db","path1/AAA/ZAW/A/b/c/a_file.txt"));
521 : :
522 : 2 : arguments = "--update --watch-timestamps --rehash-locked "
523 : : "--lock-checksum=\"^path1/.*\" --database=lock_s6.db "
524 : : "tests/fixtures/diffs/diff1";
525 : :
526 : 2 : ASSERT(SUCCESS == runit(arguments,result,NULL,WARNING,ALLOW_BOTH));
527 : :
528 : 2 : filename = "templates/0030_006_2.txt";
529 : :
530 : 2 : ASSERT(SUCCESS == get_file_content(filename,pattern));
531 : :
532 : 2 : ASSERT(SUCCESS == match_pattern(result,pattern,filename));
533 : :
534 : 2 : ASSERT(SUCCESS == delete_path("lock_s6.db"));
535 : 2 : ASSERT(SUCCESS == delete_path("tests/fixtures/diffs/diff1"));
536 : 2 : ASSERT(SUCCESS == move_path("tests/fixtures/diff1_backup","tests/fixtures/diffs/diff1"));
537 : :
538 : 2 : del(pattern);
539 : 2 : del(result);
540 : :
541 : 2 : RETURN_STATUS;
542 : : }
543 : :
544 : : /**
545 : : * README --lock-checksum example extension: on-disk content change with
546 : : * --rehash-locked should trigger WARNING
547 : : */
548 : 2 : static Return test0030_7(void)
549 : : {
550 : 2 : INITTEST;
551 : :
552 : 2 : create(char,result);
553 : 2 : create(char,pattern);
554 : :
555 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
556 : :
557 : 2 : ASSERT(SUCCESS == move_path("tests/fixtures/diffs/diff1","tests/fixtures/diff1_backup"));
558 : 2 : ASSERT(SUCCESS == copy_path("tests/fixtures/diff1_backup","tests/fixtures/diffs/diff1"));
559 : :
560 : 2 : const char *arguments = "--database=lock_s7.db --progress "
561 : : "--lock-checksum=\"^path1/.*\" tests/fixtures/diffs/diff1";
562 : :
563 : 2 : ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
564 : :
565 : 2 : const char *filename = "templates/0030_007_1.txt";
566 : :
567 : 2 : ASSERT(SUCCESS == get_file_content(filename,pattern));
568 : :
569 : 2 : ASSERT(SUCCESS == match_pattern(result,pattern,filename));
570 : :
571 : 2 : ASSERT(SUCCESS == tamper_locked_file_bytes("tests/fixtures/diffs/diff1/path1/AAA/ZAW/A/b/c/a_file.txt"));
572 : :
573 : 2 : arguments = "--update --rehash-locked --lock-checksum=\"^path1/.*\" "
574 : : "--database=lock_s7.db tests/fixtures/diffs/diff1";
575 : :
576 : 2 : ASSERT(SUCCESS == runit(arguments,result,NULL,WARNING,ALLOW_BOTH));
577 : :
578 : 2 : filename = "templates/0030_007_2.txt";
579 : :
580 : 2 : ASSERT(SUCCESS == get_file_content(filename,pattern));
581 : :
582 : 2 : ASSERT(SUCCESS == match_pattern(result,pattern,filename));
583 : :
584 : 2 : ASSERT(SUCCESS == delete_path("lock_s7.db"));
585 : 2 : ASSERT(SUCCESS == delete_path("tests/fixtures/diffs/diff1"));
586 : 2 : ASSERT(SUCCESS == move_path("tests/fixtures/diff1_backup","tests/fixtures/diffs/diff1"));
587 : :
588 : 2 : del(pattern);
589 : 2 : del(result);
590 : :
591 : 2 : RETURN_STATUS;
592 : : }
593 : :
594 : : /**
595 : : * Same as test0030_7 but with --watch-timestamps; per README example, this option
596 : : * does not change the --rehash-locked outcome
597 : : */
598 : 2 : static Return test0030_8(void)
599 : : {
600 : 2 : INITTEST;
601 : :
602 : 2 : create(char,result);
603 : 2 : create(char,pattern);
604 : :
605 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
606 : :
607 : 2 : ASSERT(SUCCESS == move_path("tests/fixtures/diffs/diff1","tests/fixtures/diff1_backup"));
608 : 2 : ASSERT(SUCCESS == copy_path("tests/fixtures/diff1_backup","tests/fixtures/diffs/diff1"));
609 : :
610 : 2 : const char *arguments = "--database=lock_s8.db --progress "
611 : : "--lock-checksum=\"^path1/.*\" tests/fixtures/diffs/diff1";
612 : :
613 : 2 : ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
614 : :
615 : 2 : const char *filename = "templates/0030_008_1.txt";
616 : :
617 : 2 : ASSERT(SUCCESS == get_file_content(filename,pattern));
618 : :
619 : 2 : ASSERT(SUCCESS == match_pattern(result,pattern,filename));
620 : :
621 : 2 : ASSERT(SUCCESS == tamper_locked_file_bytes("tests/fixtures/diffs/diff1/path1/AAA/ZAW/A/b/c/a_file.txt"));
622 : :
623 : 2 : arguments = "--update --watch-timestamps --rehash-locked "
624 : : "--lock-checksum=\"^path1/.*\" --database=lock_s8.db "
625 : : "tests/fixtures/diffs/diff1";
626 : :
627 : 2 : ASSERT(SUCCESS == runit(arguments,result,NULL,WARNING,ALLOW_BOTH));
628 : :
629 : 2 : filename = "templates/0030_008_2.txt";
630 : :
631 : 2 : ASSERT(SUCCESS == get_file_content(filename,pattern));
632 : :
633 : 2 : ASSERT(SUCCESS == match_pattern(result,pattern,filename));
634 : :
635 : 2 : ASSERT(SUCCESS == delete_path("lock_s8.db"));
636 : 2 : ASSERT(SUCCESS == delete_path("tests/fixtures/diffs/diff1"));
637 : 2 : ASSERT(SUCCESS == move_path("tests/fixtures/diff1_backup","tests/fixtures/diffs/diff1"));
638 : :
639 : 2 : del(pattern);
640 : 2 : del(result);
641 : :
642 : 2 : RETURN_STATUS;
643 : : }
644 : :
645 : : /**
646 : : * README --lock-checksum example: size and timestamps match,
647 : : * --watch-timestamps enabled, --rehash-locked disabled -> SUCCESS
648 : : */
649 : 2 : static Return test0030_9(void)
650 : : {
651 : 2 : INITTEST;
652 : :
653 : 2 : create(char,result);
654 : 2 : create(char,pattern);
655 : :
656 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
657 : :
658 : 2 : ASSERT(SUCCESS == move_path("tests/fixtures/diffs/diff1","tests/fixtures/diff1_backup"));
659 : 2 : ASSERT(SUCCESS == copy_path("tests/fixtures/diff1_backup","tests/fixtures/diffs/diff1"));
660 : :
661 : 2 : const char *arguments = "--database=lock_s9.db --progress "
662 : : "--lock-checksum=\"^path1/.*\" tests/fixtures/diffs/diff1";
663 : :
664 : 2 : ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
665 : :
666 : 2 : const char *filename = "templates/0030_009_1.txt";
667 : :
668 : 2 : ASSERT(SUCCESS == get_file_content(filename,pattern));
669 : :
670 : 2 : ASSERT(SUCCESS == match_pattern(result,pattern,filename));
671 : :
672 : 2 : arguments = "--update --watch-timestamps --lock-checksum=\"^path1/.*\" "
673 : : "--database=lock_s9.db tests/fixtures/diffs/diff1";
674 : :
675 : 2 : ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
676 : :
677 : 2 : filename = "templates/0030_009_2.txt";
678 : :
679 : 2 : ASSERT(SUCCESS == get_file_content(filename,pattern));
680 : :
681 : 2 : ASSERT(SUCCESS == match_pattern(result,pattern,filename));
682 : :
683 : 2 : ASSERT(SUCCESS == delete_path("lock_s9.db"));
684 : 2 : ASSERT(SUCCESS == delete_path("tests/fixtures/diffs/diff1"));
685 : 2 : ASSERT(SUCCESS == move_path("tests/fixtures/diff1_backup","tests/fixtures/diffs/diff1"));
686 : :
687 : 2 : del(pattern);
688 : 2 : del(result);
689 : :
690 : 2 : RETURN_STATUS;
691 : : }
692 : :
693 : : /**
694 : : *
695 : : * README --lock-checksum examples.
696 : : * Scenarios with --lock-checksum, --rehash-locked, and --watch-timestamps
697 : : *
698 : : */
699 : 2 : Return test0030(void)
700 : : {
701 : 2 : INITTEST;
702 : :
703 : 2 : TEST(test0030_1,"Size change with locked checksum triggers a warning…");
704 : 2 : TEST(test0030_2,"Timestamp drift with --watch-timestamps triggers a warning…");
705 : 2 : TEST(test0030_3,"Timestamp drift without --watch-timestamps completes successfully…");
706 : 2 : TEST(test0030_4,"Timestamp drift with --watch-timestamps and --rehash-locked completes successfully…");
707 : 2 : TEST(test0030_5,"Timestamp drift without --watch-timestamps and with --rehash-locked completes successfully…");
708 : 2 : TEST(test0030_6,"Locked checksum mismatch in DB triggers a warning…");
709 : 2 : TEST(test0030_7,"Locked file content change triggers a warning…");
710 : 2 : TEST(test0030_8,"Locked file content change with --watch-timestamps triggers a warning…");
711 : 2 : TEST(test0030_9,"No changes with --watch-timestamps completes successfully…");
712 : :
713 : 2 : RETURN_STATUS;
714 : : }
|