Branch data Line data Source code
1 : : #include "sute.h"
2 : :
3 : : /**
4 : : * @brief Verify updates and DB comparisons after content, deletion, and permission changes
5 : : *
6 : : * Content growth triggers rehashing with or without --watch-timestamps.
7 : : * A permission-only change updates metadata without this option and rehashes
8 : : * unchanged content when it is enabled.
9 : : * Both database comparisons report the deleted file and the content change.
10 : : * Full output is checked with TESTING enabled and disabled
11 : : *
12 : : * @return Return status code
13 : : */
14 : 2 : static Return test0016_1(void)
15 : : {
16 : 2 : INITTEST;
17 : :
18 : 2 : m_create(char,pattern,MEMORY_STRING);
19 : :
20 : : // Create memory for the result
21 : 2 : m_create(char,result,MEMORY_STRING);
22 : 2 : m_create(char,chunk,MEMORY_STRING);
23 : :
24 : 2 : m_create(char,target_path,MEMORY_STRING);
25 : 2 : struct stat stat_before = {0};
26 : 2 : struct stat stat_after = {0};
27 : :
28 : : // Preparation for the test
29 : 2 : const char *diff1_fixture_path = "tests/fixtures/diffs/diff1";
30 : 2 : const char *permission_file_path = "tests/fixtures/diffs/diff1/2/AAA/BBB/CZC/a.txt";
31 : 2 : ASSERT(SUCCESS == prepare_mutable_fixture(diff1_fixture_path));
32 : :
33 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
34 : :
35 : 2 : ASSERT(SUCCESS == runit("--database=database1.db tests/fixtures/diffs/diff1",chunk,NULL,COMPLETED,ALLOW_BOTH));
36 : 2 : ASSERT(SUCCESS == m_copy(result,chunk));
37 : :
38 : 2 : ASSERT(SUCCESS == copy_path("database1.db","database2.db"));
39 : :
40 : 2 : ASSERT(SUCCESS == add_string_to("PWOEUNVSODNLKUHGE","tests/fixtures/diffs/diff1/1/AAA/BCB/CCC/a.txt"));
41 : :
42 : 2 : ASSERT(SUCCESS == delete_path("tests/fixtures/diffs/diff1/path2/AAA/ZAW/D/e/f/b_file.txt"));
43 : :
44 : : // Toggle owner write permission to change ctime while preserving content, mtime, and read access
45 : 2 : ASSERT(SUCCESS == construct_path(permission_file_path,target_path));
46 : 2 : ASSERT(SUCCESS == get_file_stat(m_text(target_path),&stat_before));
47 : 2 : unsigned int changed_mode = ((unsigned int)stat_before.st_mode & 07777U) ^ S_IWUSR;
48 : 2 : ASSERT(SUCCESS == change_mode(permission_file_path,changed_mode));
49 : 2 : ASSERT(SUCCESS == get_file_stat(m_text(target_path),&stat_after));
50 : 2 : ASSERT(stat_after.st_mode == (stat_before.st_mode ^ S_IWUSR));
51 : 2 : ASSERT(stat_before.st_ctim.tv_sec != stat_after.st_ctim.tv_sec
52 : : || stat_before.st_ctim.tv_nsec != stat_after.st_ctim.tv_nsec);
53 : 2 : ASSERT(stat_before.st_mtim.tv_sec == stat_after.st_mtim.tv_sec
54 : : && stat_before.st_mtim.tv_nsec == stat_after.st_mtim.tv_nsec);
55 : 2 : ASSERT(stat_before.st_size == stat_after.st_size);
56 : 2 : ASSERT(stat_before.st_blocks == stat_after.st_blocks);
57 : :
58 : : // Update without --watch-timestamps: rehash changed content, update ctime-only
59 : : // metadata without rehashing, and remove the deleted file's DB record
60 : 2 : ASSERT(SUCCESS == runit("--update --check-level=QUICK --database=database1.db tests/fixtures/diffs/diff1",chunk,NULL,COMPLETED,ALLOW_BOTH));
61 : 2 : ASSERT(SUCCESS == m_concat_strings(result,chunk));
62 : :
63 : : // Compare against the original DB: report the deleted file and the changed checksum
64 : 2 : const char *compare_arguments = "--compare --check-level=QUICK database1.db database2.db";
65 : 2 : ASSERT(SUCCESS == runit(compare_arguments,chunk,NULL,COMPLETED,ALLOW_BOTH));
66 : 2 : ASSERT(SUCCESS == m_concat_strings(result,chunk));
67 : :
68 : : // Restore the original DB so the next update processes the same changes
69 : 2 : ASSERT(SUCCESS == copy_path("database2.db","database1.db"));
70 : :
71 : : // Update with --watch-timestamps: rehash the file whose ctime changed as well
72 : 2 : const char *watch_update_arguments = "--watch-timestamps --update --check-level=QUICK --database=database1.db tests/fixtures/diffs/diff1";
73 : 2 : ASSERT(SUCCESS == runit(watch_update_arguments,chunk,NULL,COMPLETED,ALLOW_BOTH));
74 : 2 : ASSERT(SUCCESS == m_concat_strings(result,chunk));
75 : :
76 : : // Verify that rehashing the permission-only change adds no checksum difference
77 : 2 : ASSERT(SUCCESS == runit(compare_arguments,chunk,NULL,COMPLETED,ALLOW_BOTH));
78 : 2 : ASSERT(SUCCESS == m_concat_strings(result,chunk));
79 : :
80 : : // Check the complete combined output for creation, both updates, and both comparisons
81 : 2 : const char *filename = "templates/0016_001_1.txt";
82 : 2 : ASSERT(SUCCESS == get_file_content(filename,pattern));
83 : 2 : ASSERT(SUCCESS == match_pattern(result,pattern,filename));
84 : :
85 : : // Clean to use it iteratively
86 : 2 : m_del(pattern);
87 : 2 : m_del(result);
88 : 2 : m_del(chunk);
89 : :
90 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","false"));
91 : :
92 : 2 : ASSERT(SUCCESS == copy_path("database2.db","database1.db"));
93 : :
94 : 2 : ASSERT(SUCCESS == runit("--update --check-level=QUICK --database=database1.db tests/fixtures/diffs/diff1",chunk,NULL,COMPLETED,ALLOW_BOTH));
95 : 2 : ASSERT(SUCCESS == m_copy(result,chunk));
96 : :
97 : 2 : ASSERT(SUCCESS == runit(compare_arguments,chunk,NULL,COMPLETED,ALLOW_BOTH));
98 : 2 : ASSERT(SUCCESS == m_concat_strings(result,chunk));
99 : :
100 : 2 : ASSERT(SUCCESS == copy_path("database2.db","database1.db"));
101 : :
102 : 2 : ASSERT(SUCCESS == runit(watch_update_arguments,chunk,NULL,COMPLETED,ALLOW_BOTH));
103 : 2 : ASSERT(SUCCESS == m_concat_strings(result,chunk));
104 : :
105 : 2 : ASSERT(SUCCESS == runit(compare_arguments,chunk,NULL,COMPLETED,ALLOW_BOTH));
106 : 2 : ASSERT(SUCCESS == m_concat_strings(result,chunk));
107 : :
108 : 2 : filename = "templates/0016_001_2.txt";
109 : 2 : ASSERT(SUCCESS == get_file_content(filename,pattern));
110 : 2 : ASSERT(SUCCESS == match_pattern(result,pattern,filename));
111 : :
112 : : // Clean to use it iteratively
113 : 2 : m_del(pattern);
114 : 2 : m_del(result);
115 : 2 : m_del(chunk);
116 : :
117 : : // Clean up test results
118 : 2 : ASSERT(SUCCESS == delete_path("database1.db"));
119 : 2 : ASSERT(SUCCESS == delete_path("database2.db"));
120 : 2 : ASSERT(SUCCESS == restore_mutable_fixture(diff1_fixture_path));
121 : 2 : m_del(target_path);
122 : :
123 : 2 : RETURN_STATUS;
124 : : }
125 : :
126 : : /**
127 : : * @brief Rehash same-size content changes when mtime changes without --watch-timestamps
128 : : *
129 : : * CLI and configuration runs start from the same database and changed file.
130 : : * Both runs must produce the same full output, checksum, and stored timestamps.
131 : : * Only the database is restored before the configuration run
132 : : *
133 : : * @return Return status code
134 : : */
135 : 2 : static Return test0016_2(void)
136 : : {
137 : 2 : INITTEST;
138 : :
139 : 2 : const char *fixture_path = "0016_mtime";
140 : 2 : const char *file_path = "0016_mtime/file.txt";
141 : 2 : const char *db_filename = "0016_mtime.db";
142 : 2 : const char *db_backup_filename = "0016_mtime_before_update.db";
143 : 2 : m_create(char,target_path,MEMORY_STRING);
144 : 2 : struct stat stat_before = {0};
145 : 2 : struct stat stat_after = {0};
146 : 2 : CmpctStat saved_stat = {0};
147 : 2 : sqlite3_int64 offset = -1;
148 : 2 : unsigned char checksum_before[SHA512_DIGEST_LENGTH] = {0};
149 : 2 : unsigned char checksum_after[SHA512_DIGEST_LENGTH] = {0};
150 : :
151 : : // Create a three-byte file containing "aaa" and store its checksum in the DB
152 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","false"));
153 : 2 : ASSERT(SUCCESS == create_directory(fixture_path));
154 : 2 : ASSERT(SUCCESS == replase_to_string("aaa",file_path));
155 : 2 : ASSERT(SUCCESS == construct_path(file_path,target_path));
156 : 2 : ASSERT(SUCCESS == runit("--database=0016_mtime.db 0016_mtime",NULL,NULL,COMPLETED,ALLOW_BOTH));
157 : :
158 : : // Save the completed checksum and verify it independently before changing the file
159 : 2 : ASSERT(SUCCESS == read_final_sha512_from_db(db_filename,"file.txt",&offset,checksum_before));
160 : 2 : ASSERT(offset == 0);
161 : 2 : ASSERT(SUCCESS == db_final_sha512_matches_file(db_filename,"file.txt",m_text(target_path)));
162 : 2 : ASSERT(SUCCESS == get_file_stat(m_text(target_path),&stat_before));
163 : :
164 : : // Use the saved mtime as a deterministic reference and preserve atime
165 : 2 : struct timespec file_times[2] = {{0}};
166 : 2 : file_times[0].tv_nsec = UTIME_OMIT;
167 : 2 : file_times[1] = stat_before.st_mtim;
168 : 2 : file_times[1].tv_sec++;
169 : :
170 : : // Replace "aaa" with "bbb" and force mtime one second past its original value
171 : 2 : ASSERT(SUCCESS == replase_to_string("bbb",file_path));
172 : 2 : ASSERT(utimensat(0,m_text(target_path),file_times,0) == 0);
173 : :
174 : : // Confirm that the file is still three bytes long and its mtime has changed
175 : 2 : ASSERT(SUCCESS == get_file_stat(m_text(target_path),&stat_after));
176 : 2 : ASSERT(stat_before.st_size == 3 && stat_after.st_size == 3);
177 : 2 : ASSERT(stat_before.st_mtim.tv_sec != stat_after.st_mtim.tv_sec
178 : : || stat_before.st_mtim.tv_nsec != stat_after.st_mtim.tv_nsec);
179 : :
180 : : // Preserve the database before either target update
181 : 2 : ASSERT(SUCCESS == copy_path(db_filename,db_backup_filename));
182 : :
183 : : // Update without --watch-timestamps to exercise default mtime detection
184 : 2 : const char *filename = "templates/0016_002_1.txt";
185 : 2 : const struct argument_test_case cases[] = {
186 : : {"--update --check-level=QUICK --database=0016_mtime.db 0016_mtime",
187 : : COMPLETED,filename,STDERR_MUST_BE_EMPTY},
188 : : {0}
189 : : };
190 : :
191 : : // Check the full output for a rehash of file.txt and exactly three hashed bytes
192 : 2 : ASSERT(SUCCESS == run_and_match_templates(cases,NULL,NULL));
193 : :
194 : : // Verify that the new checksum is complete and differs from the checksum of "aaa"
195 : 2 : ASSERT(SUCCESS == read_final_sha512_from_db(db_filename,"file.txt",&offset,checksum_after));
196 : 2 : ASSERT(offset == 0);
197 : 2 : ASSERT(memcmp(checksum_before,checksum_after,sizeof(checksum_before)) != 0);
198 : :
199 : : // Independently hash "bbb" with Monocypher and compare it with the stored checksum
200 : 2 : ASSERT(SUCCESS == db_final_sha512_matches_file(db_filename,"file.txt",m_text(target_path)));
201 : :
202 : : // Verify that the DB contains the file's updated mtime and ctime
203 : 2 : ASSERT(SUCCESS == db_read_cmpctstat_by_relative_path(db_filename,"file.txt",&saved_stat));
204 : 2 : ASSERT(cmpctstat_matches_stat_timestamps(&saved_stat,&stat_after));
205 : :
206 : : /* Restore only the database so the configuration run processes the same
207 : : changed content and timestamps, then repeat all result checks */
208 : 2 : ASSERT(SUCCESS == copy_path(db_backup_filename,db_filename));
209 : 2 : ASSERT(SUCCESS == copy_path("tests/templates/0016_002_1.conf","0016_002_1.conf"));
210 : 2 : const struct argument_test_case file_cases[] = {
211 : : {"--config=0016_002_1.conf",COMPLETED,filename,STDERR_MUST_BE_EMPTY},
212 : : {0}
213 : : };
214 : 2 : ASSERT(SUCCESS == run_and_match_templates(file_cases,NULL,NULL));
215 : 2 : ASSERT(SUCCESS == read_final_sha512_from_db(db_filename,"file.txt",&offset,checksum_after));
216 : 2 : ASSERT(offset == 0);
217 : 2 : ASSERT(memcmp(checksum_before,checksum_after,sizeof(checksum_before)) != 0);
218 : 2 : ASSERT(SUCCESS == db_final_sha512_matches_file(db_filename,"file.txt",m_text(target_path)));
219 : 2 : ASSERT(SUCCESS == db_read_cmpctstat_by_relative_path(db_filename,"file.txt",&saved_stat));
220 : 2 : ASSERT(cmpctstat_matches_stat_timestamps(&saved_stat,&stat_after));
221 : :
222 : : // Remove the temporary DB and files, then release the test buffers
223 : 2 : call(delete_path_if_present("0016_002_1.conf"));
224 : 2 : call(delete_path_if_present(db_backup_filename));
225 : 2 : call(delete_path_if_present(db_filename));
226 : 2 : call(delete_path_if_present(fixture_path));
227 : 2 : m_del(target_path);
228 : :
229 : 2 : RETURN_STATUS;
230 : : }
231 : :
232 : : /**
233 : : * @brief Update metadata without reading file content after a permission change without --watch-timestamps
234 : : *
235 : : * @return Return status code
236 : : */
237 : 2 : static Return test0016_3(void)
238 : : {
239 : 2 : INITTEST;
240 : :
241 : 2 : const char *fixture_path = "0016_chmod";
242 : 2 : const char *file_path = "0016_chmod/file.txt";
243 : 2 : const char *db_filename = "0016_chmod.db";
244 : 2 : m_create(char,target_path,MEMORY_STRING);
245 : 2 : m_create(char,result,MEMORY_STRING);
246 : 2 : m_create(char,pattern,MEMORY_STRING);
247 : 2 : struct stat stat_before = {0};
248 : 2 : struct stat stat_after = {0};
249 : 2 : CmpctStat saved_stat = {0};
250 : 2 : sqlite3_int64 offset = -1;
251 : 2 : unsigned char checksum_before[SHA512_DIGEST_LENGTH] = {0};
252 : 2 : unsigned char checksum_after[SHA512_DIGEST_LENGTH] = {0};
253 : :
254 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","false"));
255 : 2 : ASSERT(SUCCESS == create_directory(fixture_path));
256 : 2 : ASSERT(SUCCESS == replase_to_string("aaa",file_path));
257 : 2 : ASSERT(SUCCESS == change_mode(file_path,0600));
258 : 2 : ASSERT(SUCCESS == construct_path(file_path,target_path));
259 : 2 : ASSERT(SUCCESS == runit("--database=0016_chmod.db 0016_chmod",NULL,NULL,COMPLETED,ALLOW_BOTH));
260 : 2 : ASSERT(SUCCESS == read_final_sha512_from_db(db_filename,"file.txt",&offset,checksum_before));
261 : 2 : ASSERT(offset == 0);
262 : 2 : ASSERT(SUCCESS == get_file_stat(m_text(target_path),&stat_before));
263 : :
264 : : // Keep the file readable while changing ctime without modifying content or mtime
265 : 2 : ASSERT(SUCCESS == change_mode(file_path,0644));
266 : 2 : ASSERT(SUCCESS == get_file_stat(m_text(target_path),&stat_after));
267 : 2 : ASSERT(stat_before.st_mode != stat_after.st_mode);
268 : 2 : ASSERT(stat_before.st_ctim.tv_sec != stat_after.st_ctim.tv_sec
269 : : || stat_before.st_ctim.tv_nsec != stat_after.st_ctim.tv_nsec);
270 : 2 : ASSERT(stat_before.st_mtim.tv_sec == stat_after.st_mtim.tv_sec
271 : : && stat_before.st_mtim.tv_nsec == stat_after.st_mtim.tv_nsec);
272 : 2 : ASSERT(stat_before.st_size == stat_after.st_size);
273 : 2 : ASSERT(stat_before.st_blocks == stat_after.st_blocks);
274 : :
275 : : // Update without --watch-timestamps and check the full output for
276 : : // a metadata-only update with zero bytes hashed by the application
277 : 2 : ASSERT(SUCCESS == runit("--update --check-level=QUICK --database=0016_chmod.db 0016_chmod",result,NULL,COMPLETED,ALLOW_BOTH));
278 : 2 : const char *filename = "templates/0016_002_2.txt";
279 : 2 : ASSERT(SUCCESS == get_file_content(filename,pattern));
280 : 2 : ASSERT(SUCCESS == match_pattern(result,pattern,filename));
281 : :
282 : : // A zero offset denotes a completed checksum, which must retain its original value
283 : 2 : ASSERT(SUCCESS == read_final_sha512_from_db(db_filename,"file.txt",&offset,checksum_after));
284 : 2 : ASSERT(offset == 0);
285 : 2 : ASSERT(memcmp(checksum_before,checksum_after,sizeof(checksum_before)) == 0);
286 : :
287 : : // Independently hash the file in the test to verify the checksum stored in the DB
288 : 2 : ASSERT(SUCCESS == db_final_sha512_matches_file(db_filename,"file.txt",m_text(target_path)));
289 : :
290 : : // Confirm that the DB saved the changed ctime and preserved the file's mtime
291 : 2 : ASSERT(SUCCESS == db_read_cmpctstat_by_relative_path(db_filename,"file.txt",&saved_stat));
292 : 2 : ASSERT(cmpctstat_matches_stat_timestamps(&saved_stat,&stat_after));
293 : :
294 : 2 : call(delete_path_if_present(db_filename));
295 : 2 : call(delete_path_if_present(fixture_path));
296 : 2 : m_del(pattern);
297 : 2 : m_del(result);
298 : 2 : m_del(target_path);
299 : :
300 : 2 : RETURN_STATUS;
301 : : }
302 : :
303 : : /**
304 : : * @brief Rehash unchanged content after a permission change when --watch-timestamps watches ctime
305 : : *
306 : : * CLI and configuration updates start from the same saved database after a
307 : : * single permission change. Both check the full output, checksum, and stored
308 : : * timestamps against the same prepared file
309 : : *
310 : : * @return Return status code
311 : : */
312 : 2 : static Return test0016_4(void)
313 : : {
314 : 2 : INITTEST;
315 : :
316 : 2 : const char *fixture_path = "0016_watch_chmod";
317 : 2 : const char *file_path = "0016_watch_chmod/file.txt";
318 : 2 : const char *db_filename = "0016_watch_chmod.db";
319 : 2 : const char *db_backup_filename = "0016_watch_chmod_before_update.db";
320 : 2 : m_create(char,target_path,MEMORY_STRING);
321 : 2 : struct stat stat_before = {0};
322 : 2 : struct stat stat_after = {0};
323 : 2 : CmpctStat saved_stat = {0};
324 : 2 : sqlite3_int64 offset = -1;
325 : 2 : unsigned char checksum_before[SHA512_DIGEST_LENGTH] = {0};
326 : 2 : unsigned char checksum_after[SHA512_DIGEST_LENGTH] = {0};
327 : :
328 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","false"));
329 : 2 : ASSERT(SUCCESS == create_directory(fixture_path));
330 : 2 : ASSERT(SUCCESS == replase_to_string("aaa",file_path));
331 : 2 : ASSERT(SUCCESS == change_mode(file_path,0644));
332 : 2 : ASSERT(SUCCESS == construct_path(file_path,target_path));
333 : 2 : ASSERT(SUCCESS == runit("--database=0016_watch_chmod.db 0016_watch_chmod",NULL,NULL,COMPLETED,ALLOW_BOTH));
334 : 2 : ASSERT(SUCCESS == read_final_sha512_from_db(db_filename,"file.txt",&offset,checksum_before));
335 : 2 : ASSERT(offset == 0);
336 : 2 : ASSERT(SUCCESS == get_file_stat(m_text(target_path),&stat_before));
337 : :
338 : : // A fresh permission change supplies ctime drift for the watched update
339 : 2 : ASSERT(SUCCESS == change_mode(file_path,0600));
340 : 2 : ASSERT(SUCCESS == get_file_stat(m_text(target_path),&stat_after));
341 : 2 : ASSERT(stat_before.st_mode != stat_after.st_mode);
342 : 2 : ASSERT(stat_before.st_ctim.tv_sec != stat_after.st_ctim.tv_sec
343 : : || stat_before.st_ctim.tv_nsec != stat_after.st_ctim.tv_nsec);
344 : 2 : ASSERT(stat_before.st_mtim.tv_sec == stat_after.st_mtim.tv_sec
345 : : && stat_before.st_mtim.tv_nsec == stat_after.st_mtim.tv_nsec);
346 : 2 : ASSERT(stat_before.st_size == stat_after.st_size);
347 : 2 : ASSERT(stat_before.st_blocks == stat_after.st_blocks);
348 : :
349 : : /* Preserve the database before either update records the changed ctime */
350 : 2 : ASSERT(SUCCESS == copy_path(db_filename,db_backup_filename));
351 : :
352 : 2 : const char *filename = "templates/0016_002_3.txt";
353 : 2 : const struct argument_test_case cases[] = {
354 : : {"--update --check-level=QUICK --watch-timestamps --database=0016_watch_chmod.db 0016_watch_chmod",
355 : : COMPLETED,filename,STDERR_MUST_BE_EMPTY},
356 : : {0}
357 : : };
358 : 2 : ASSERT(SUCCESS == run_and_match_templates(cases,NULL,NULL));
359 : 2 : ASSERT(SUCCESS == read_final_sha512_from_db(db_filename,"file.txt",&offset,checksum_after));
360 : 2 : ASSERT(offset == 0);
361 : 2 : ASSERT(memcmp(checksum_before,checksum_after,sizeof(checksum_before)) == 0);
362 : 2 : ASSERT(SUCCESS == db_final_sha512_matches_file(db_filename,"file.txt",m_text(target_path)));
363 : 2 : ASSERT(SUCCESS == db_read_cmpctstat_by_relative_path(db_filename,"file.txt",&saved_stat));
364 : 2 : ASSERT(cmpctstat_matches_stat_timestamps(&saved_stat,&stat_after));
365 : :
366 : : /* Restore only the database so the configuration run sees the same permission
367 : : change, then repeat the checksum and timestamp checks */
368 : 2 : ASSERT(SUCCESS == copy_path(db_backup_filename,db_filename));
369 : 2 : ASSERT(SUCCESS == copy_path("tests/templates/0016_002_3.conf","0016_002_3.conf"));
370 : 2 : const struct argument_test_case file_cases[] = {
371 : : {"--config=0016_002_3.conf",COMPLETED,filename,STDERR_MUST_BE_EMPTY},
372 : : {0}
373 : : };
374 : 2 : ASSERT(SUCCESS == run_and_match_templates(file_cases,NULL,NULL));
375 : 2 : ASSERT(SUCCESS == read_final_sha512_from_db(db_filename,"file.txt",&offset,checksum_after));
376 : 2 : ASSERT(offset == 0);
377 : 2 : ASSERT(memcmp(checksum_before,checksum_after,sizeof(checksum_before)) == 0);
378 : 2 : ASSERT(SUCCESS == db_final_sha512_matches_file(db_filename,"file.txt",m_text(target_path)));
379 : 2 : ASSERT(SUCCESS == db_read_cmpctstat_by_relative_path(db_filename,"file.txt",&saved_stat));
380 : 2 : ASSERT(cmpctstat_matches_stat_timestamps(&saved_stat,&stat_after));
381 : :
382 : 2 : call(delete_path_if_present("0016_002_3.conf"));
383 : 2 : call(delete_path_if_present(db_backup_filename));
384 : 2 : call(delete_path_if_present(db_filename));
385 : 2 : call(delete_path_if_present(fixture_path));
386 : 2 : m_del(target_path);
387 : :
388 : 2 : RETURN_STATUS;
389 : : }
390 : :
391 : : /**
392 : : * @brief Verify default and optional timestamp-driven checksum updates
393 : : *
394 : : * @return Return status code
395 : : */
396 : 2 : Return test0016(void)
397 : : {
398 : 2 : INITTEST;
399 : :
400 : 2 : TEST(test0016_1,"Content, deletion, and permission updates with and without --watch-timestamps");
401 : 2 : TEST(test0016_2,"A changed mtime rehashes same-size content without --watch-timestamps");
402 : 2 : TEST(test0016_3,"Permission changes update metadata without hashing by default");
403 : 2 : TEST(test0016_4,"Permission changes rehash content when --watch-timestamps watches ctime");
404 : :
405 : 2 : RETURN_STATUS;
406 : : }
|