Branch data Line data Source code
1 : : #include "sute.h"
2 : :
3 : : /**
4 : : * Runs precizer with the given arguments and validates output with optional
5 : : * stdout/stderr regex templates.
6 : : */
7 : 10 : static Return assert_compare_output(
8 : : const char *arguments,
9 : : const int expected_return_code,
10 : : const char *stdout_pattern_file,
11 : : const char *stderr_pattern_file)
12 : : {
13 : : /* The status that will be returned before exiting */
14 : : /* By default, assumes the function ran without errors */
15 : 10 : Return status = SUCCESS;
16 : :
17 : 10 : m_create(char,stdout_result,MEMORY_STRING);
18 : 10 : m_create(char,stderr_result,MEMORY_STRING);
19 : 10 : m_create(char,stdout_pattern,MEMORY_STRING);
20 : 10 : m_create(char,stderr_pattern,MEMORY_STRING);
21 : :
22 [ - + ]: 10 : if(arguments == NULL)
23 : : {
24 : 0 : status = FAILURE;
25 : : }
26 : :
27 : 10 : unsigned int capture_policy = ALLOW_BOTH;
28 : :
29 [ + - - + ]: 10 : if(expected_return_code != COMPLETED || stderr_pattern_file != NULL)
30 : : {
31 : 0 : capture_policy = STDERR_ALLOW;
32 : : }
33 : :
34 : 10 : run(runit(arguments,stdout_result,stderr_result,expected_return_code,capture_policy));
35 : :
36 [ + - ]: 10 : if(stdout_pattern_file != NULL)
37 : : {
38 : 10 : run(get_file_content(stdout_pattern_file,stdout_pattern));
39 : 10 : run(match_pattern(stdout_result,stdout_pattern,stdout_pattern_file));
40 : : }
41 : :
42 [ - + ]: 10 : if(stderr_pattern_file != NULL)
43 : : {
44 : 0 : run(get_file_content(stderr_pattern_file,stderr_pattern));
45 : 0 : run(match_pattern(stderr_result,stderr_pattern,stderr_pattern_file));
46 : : }
47 : :
48 : 10 : m_del(stderr_pattern);
49 : 10 : m_del(stdout_pattern);
50 : 10 : m_del(stderr_result);
51 : 10 : m_del(stdout_result);
52 : :
53 : 10 : deliver(status);
54 : : }
55 : :
56 : : /**
57 : : * Prepares two databases with known differences for compare-filter tests.
58 : : */
59 : 6 : static Return prepare_compare_filter_differences_fixture(void)
60 : : {
61 : : /* The status that will be returned before exiting */
62 : : /* By default, assumes the function ran without errors */
63 : 6 : Return status = SUCCESS;
64 : :
65 : 6 : m_create(char,result,MEMORY_STRING);
66 : :
67 : 6 : run(prepare_mutable_fixture("tests/fixtures/diffs/diff1"));
68 : :
69 : 6 : run(set_environment_variable("TESTING","false"));
70 : :
71 : 6 : const char *arguments = "--silent --database=database1.db tests/fixtures/diffs/diff1";
72 : 6 : run(runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
73 : :
74 [ + - - + ]: 6 : if((SUCCESS & status) && result->length != 0)
75 : : {
76 : 0 : status = FAILURE;
77 : : }
78 : :
79 : 6 : run(delete_path("tests/fixtures/diffs/diff1/2/AAA/BBB/CZC/a.txt"));
80 : 6 : run(add_string_to("AFAKDSJ","tests/fixtures/diffs/diff1/1/AAA/ZAW/D/e/f/b_file.txt"));
81 : 6 : run(replase_to_string("WNEURHGO","tests/fixtures/diffs/diff1/2/AAA/BBB/CZC/b.txt"));
82 : :
83 : 6 : arguments = "--silent --database=database2.db tests/fixtures/diffs/diff1";
84 : 6 : run(runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
85 : :
86 [ + - - + ]: 6 : if((SUCCESS & status) && result->length != 0)
87 : : {
88 : 0 : status = FAILURE;
89 : : }
90 : :
91 : 6 : m_del(result);
92 : :
93 : 6 : deliver(status);
94 : : }
95 : :
96 : : /**
97 : : * Prepares two databases where only one existence side differs:
98 : : * database2 contains one extra path compared to database1.
99 : : */
100 : 2 : static Return prepare_compare_filter_one_sided_fixture(void)
101 : : {
102 : : /* The status that will be returned before exiting */
103 : : /* By default, assumes the function ran without errors */
104 : 2 : Return status = SUCCESS;
105 : :
106 : 2 : m_create(char,result,MEMORY_STRING);
107 : :
108 : 2 : run(prepare_mutable_fixture("tests/fixtures/diffs/diff1"));
109 : :
110 : 2 : run(set_environment_variable("TESTING","false"));
111 : :
112 : 2 : const char *arguments = "--silent --database=database1.db tests/fixtures/diffs/diff1";
113 : 2 : run(runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
114 : :
115 [ + - - + ]: 2 : if((SUCCESS & status) && result->length != 0)
116 : : {
117 : 0 : status = FAILURE;
118 : : }
119 : :
120 : 2 : run(replase_to_string("ONLY_DB2_FILE","tests/fixtures/diffs/diff1/2/AAA/BBB/CZC/only_db2.txt"));
121 : :
122 : 2 : arguments = "--silent --database=database2.db tests/fixtures/diffs/diff1";
123 : 2 : run(runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
124 : :
125 [ + - - + ]: 2 : if((SUCCESS & status) && result->length != 0)
126 : : {
127 : 0 : status = FAILURE;
128 : : }
129 : :
130 : 2 : m_del(result);
131 : :
132 : 2 : deliver(status);
133 : : }
134 : :
135 : : /**
136 : : * Cleans temporary files created by the "differences" fixture.
137 : : */
138 : 8 : static Return cleanup_compare_filter_differences_fixture(void)
139 : : {
140 : : /* The status that will be returned before exiting */
141 : : /* By default, assumes the function ran without errors */
142 : 8 : Return status = SUCCESS;
143 : :
144 : 8 : run(delete_path("database1.db"));
145 : 8 : run(delete_path("database2.db"));
146 : 8 : run(restore_mutable_fixture("tests/fixtures/diffs/diff1"));
147 : :
148 : 8 : deliver(status);
149 : : }
150 : :
151 : : /**
152 : : * Prepares two equal databases for compare-filter tests.
153 : : */
154 : 8 : static Return prepare_compare_filter_equal_fixture(void)
155 : : {
156 : : /* The status that will be returned before exiting */
157 : : /* By default, assumes the function ran without errors */
158 : 8 : Return status = SUCCESS;
159 : :
160 : 8 : m_create(char,result,MEMORY_STRING);
161 : :
162 : 8 : run(set_environment_variable("TESTING","false"));
163 : :
164 : 8 : const char *arguments = "--silent --database=database1.db tests/fixtures/diffs/diff1";
165 : 8 : run(runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
166 : :
167 [ + - - + ]: 8 : if((SUCCESS & status) && result->length != 0)
168 : : {
169 : 0 : status = FAILURE;
170 : : }
171 : :
172 : 8 : arguments = "--silent --database=database2.db tests/fixtures/diffs/diff1";
173 : 8 : run(runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
174 : :
175 [ + - - + ]: 8 : if((SUCCESS & status) && result->length != 0)
176 : : {
177 : 0 : status = FAILURE;
178 : : }
179 : :
180 : 8 : m_del(result);
181 : :
182 : 8 : deliver(status);
183 : : }
184 : :
185 : : /**
186 : : * Cleans temporary files created by the "equal" fixture.
187 : : */
188 : 6 : static Return cleanup_compare_filter_equal_fixture(void)
189 : : {
190 : : /* The status that will be returned before exiting */
191 : : /* By default, assumes the function ran without errors */
192 : 6 : Return status = SUCCESS;
193 : :
194 : 6 : run(delete_path("database1.db"));
195 : 6 : run(delete_path("database2.db"));
196 : :
197 : 6 : deliver(status);
198 : : }
199 : :
200 : : /**
201 : : * @brief Compare removed, modified, and added files through CLI and configuration
202 : : *
203 : : * Reuse the prepared databases for normal comparison and dry-run with checksums.
204 : : * The complete output must retain the dry-run mode without traversal or hashing
205 : : *
206 : : * @return Return status for equivalent comparison output from both settings sources
207 : : */
208 : 2 : static Return test0028_1(void)
209 : : {
210 : 2 : INITTEST;
211 : :
212 : : // Create memory for the result
213 : 2 : m_create(char,result,MEMORY_STRING);
214 : :
215 : : // Preparation for tests
216 : 2 : ASSERT(SUCCESS == prepare_mutable_fixture("tests/fixtures/diffs/diff1"));
217 : :
218 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","false"));
219 : :
220 : 2 : const char *arguments = "--silent --database=database1.db tests/fixtures/diffs/diff1";
221 : :
222 : 2 : ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
223 : :
224 : 2 : ASSERT(result->length == 0);
225 : :
226 : 2 : ASSERT(SUCCESS == delete_path("tests/fixtures/diffs/diff1/2/AAA/BBB/CZC/a.txt")); // Remove
227 : 2 : ASSERT(SUCCESS == add_string_to("AFAKDSJ","tests/fixtures/diffs/diff1/1/AAA/ZAW/D/e/f/b_file.txt")); // Modify
228 : 2 : ASSERT(SUCCESS == replase_to_string("WNEURHGO","tests/fixtures/diffs/diff1/2/AAA/BBB/CZC/b.txt")); // New file
229 : :
230 : 2 : arguments = "--silent --database=database2.db tests/fixtures/diffs/diff1";
231 : :
232 : 2 : ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
233 : :
234 : 2 : ASSERT(result->length == 0);
235 : :
236 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
237 : :
238 : 2 : arguments = "--check-level=QUICK --compare database1.db database2.db";
239 : :
240 : 2 : const struct argument_test_case cases[] = {
241 : : {arguments,COMPLETED,"templates/0028_001.txt",STDERR_MUST_BE_EMPTY},
242 : : {0}
243 : : };
244 : :
245 : 2 : ASSERT(SUCCESS == run_and_match_templates(cases,NULL,NULL));
246 : :
247 : : /* Repeat the comparison through the default configuration on the same databases */
248 : 2 : ASSERT(SUCCESS == copy_path("tests/templates/0028_001.conf","precizer.conf"));
249 : 2 : const struct argument_test_case file_cases[] = {
250 : : {"",COMPLETED,"templates/0028_001.txt",STDERR_MUST_BE_EMPTY},
251 : : {0}
252 : : };
253 : 2 : ASSERT(SUCCESS == run_and_match_templates(file_cases,NULL,NULL));
254 : 2 : call(delete_path_if_present("precizer.conf"));
255 : :
256 : : /* Comparison reads saved checksums even when dry-run requests file hashing */
257 : 2 : ASSERT(SUCCESS == copy_path("tests/templates/0028_001_1.conf","0028_001_1.conf"));
258 : 2 : const struct argument_test_case dry_run_cases[] = {
259 : : {"--check-level=QUICK --dry-run=with-checksums --compare database1.db database2.db",
260 : : COMPLETED,"templates/0028_001_1.txt",STDERR_MUST_BE_EMPTY},
261 : : {"--config=0028_001_1.conf",COMPLETED,"templates/0028_001_1.txt",STDERR_MUST_BE_EMPTY},
262 : : {0}
263 : : };
264 : 2 : ASSERT(SUCCESS == run_and_match_templates(dry_run_cases,NULL,NULL));
265 : 2 : call(delete_path_if_present("0028_001_1.conf"));
266 : :
267 : 2 : m_del(result);
268 : :
269 : : // Clean up test results
270 : 2 : ASSERT(SUCCESS == delete_path("database1.db"));
271 : 2 : ASSERT(SUCCESS == delete_path("database2.db"));
272 : 2 : ASSERT(SUCCESS == restore_mutable_fixture("tests/fixtures/diffs/diff1"));
273 : :
274 : 2 : RETURN_STATUS;
275 : : }
276 : :
277 : : /**
278 : : * One file is removed. It should be reflected as a change in one of the databases.
279 : : */
280 : 2 : static Return test0028_2(void)
281 : : {
282 : 2 : INITTEST;
283 : :
284 : : // Create memory for the result
285 : 2 : m_create(char,result,MEMORY_STRING);
286 : :
287 : : // Preparation for tests
288 : 2 : ASSERT(SUCCESS == prepare_mutable_fixture("tests/fixtures/diffs/diff1"));
289 : :
290 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","false"));
291 : :
292 : 2 : const char *arguments = "--silent --database=database1.db tests/fixtures/diffs/diff1";
293 : :
294 : 2 : ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
295 : :
296 : 2 : ASSERT(result->length == 0);
297 : :
298 : 2 : ASSERT(SUCCESS == delete_path("tests/fixtures/diffs/diff1/2/AAA/BBB/CZC/a.txt")); // Remove
299 : :
300 : 2 : arguments = "--silent --database=database2.db tests/fixtures/diffs/diff1";
301 : :
302 : 2 : ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
303 : :
304 : 2 : ASSERT(result->length == 0);
305 : :
306 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
307 : :
308 : 2 : arguments = "--check-level=QUICK --compare database1.db database2.db";
309 : :
310 : 2 : const struct argument_test_case cases[] = {
311 : : {arguments,COMPLETED,"templates/0028_002_1.txt",STDERR_MUST_BE_EMPTY},
312 : : {0}
313 : : };
314 : :
315 : 2 : ASSERT(SUCCESS == run_and_match_templates(cases,NULL,NULL));
316 : 2 : m_del(result);
317 : :
318 : : // Clean up test results
319 : 2 : ASSERT(SUCCESS == delete_path("database1.db"));
320 : 2 : ASSERT(SUCCESS == delete_path("database2.db"));
321 : 2 : ASSERT(SUCCESS == restore_mutable_fixture("tests/fixtures/diffs/diff1"));
322 : :
323 : 2 : RETURN_STATUS;
324 : : }
325 : :
326 : : /**
327 : : * One file is added. It should be reflected as a change in one of the databases.
328 : : */
329 : 2 : static Return test0028_3(void)
330 : : {
331 : 2 : INITTEST;
332 : :
333 : : // Create memory for the result
334 : 2 : m_create(char,result,MEMORY_STRING);
335 : :
336 : : // Preparation for tests
337 : 2 : ASSERT(SUCCESS == prepare_mutable_fixture("tests/fixtures/diffs/diff1"));
338 : :
339 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","false"));
340 : :
341 : 2 : const char *arguments = "--silent --database=database1.db tests/fixtures/diffs/diff1";
342 : :
343 : 2 : ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
344 : :
345 : 2 : ASSERT(result->length == 0);
346 : :
347 : 2 : ASSERT(SUCCESS == replase_to_string("WNEURHGO","tests/fixtures/diffs/diff1/2/AAA/BBB/CZC/b.txt")); // New file
348 : :
349 : 2 : arguments = "--silent --database=database2.db tests/fixtures/diffs/diff1";
350 : :
351 : 2 : ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
352 : :
353 : 2 : ASSERT(result->length == 0);
354 : :
355 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
356 : :
357 : 2 : arguments = "--check-level=QUICK --compare database1.db database2.db";
358 : :
359 : 2 : const struct argument_test_case cases[] = {
360 : : {arguments,COMPLETED,"templates/0028_003_1.txt",STDERR_MUST_BE_EMPTY},
361 : : {0}
362 : : };
363 : :
364 : 2 : ASSERT(SUCCESS == run_and_match_templates(cases,NULL,NULL));
365 : 2 : m_del(result);
366 : :
367 : : // Clean up test results
368 : 2 : ASSERT(SUCCESS == delete_path("database1.db"));
369 : 2 : ASSERT(SUCCESS == delete_path("database2.db"));
370 : 2 : ASSERT(SUCCESS == restore_mutable_fixture("tests/fixtures/diffs/diff1"));
371 : :
372 : 2 : RETURN_STATUS;
373 : : }
374 : :
375 : : /**
376 : : * One file is updated and its checksum should change
377 : : */
378 : 2 : static Return test0028_4(void)
379 : : {
380 : 2 : INITTEST;
381 : :
382 : : // Create memory for the result
383 : 2 : m_create(char,result,MEMORY_STRING);
384 : :
385 : : // Preparation for tests
386 : 2 : ASSERT(SUCCESS == prepare_mutable_fixture("tests/fixtures/diffs/diff1"));
387 : :
388 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","false"));
389 : :
390 : 2 : const char *arguments = "--silent --database=database1.db tests/fixtures/diffs/diff1";
391 : :
392 : 2 : ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
393 : :
394 : 2 : ASSERT(result->length == 0);
395 : :
396 : 2 : ASSERT(SUCCESS == add_string_to("AFAKDSJ","tests/fixtures/diffs/diff1/1/AAA/ZAW/D/e/f/b_file.txt")); // Modify
397 : :
398 : 2 : arguments = "--silent --database=database2.db tests/fixtures/diffs/diff1";
399 : :
400 : 2 : ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
401 : :
402 : 2 : ASSERT(result->length == 0);
403 : :
404 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
405 : :
406 : 2 : arguments = "--check-level=QUICK --compare database1.db database2.db";
407 : :
408 : 2 : const struct argument_test_case cases[] = {
409 : : {arguments,COMPLETED,"templates/0028_004.txt",STDERR_MUST_BE_EMPTY},
410 : : {0}
411 : : };
412 : :
413 : 2 : ASSERT(SUCCESS == run_and_match_templates(cases,NULL,NULL));
414 : 2 : m_del(result);
415 : :
416 : : // Clean up test results
417 : 2 : ASSERT(SUCCESS == delete_path("database1.db"));
418 : 2 : ASSERT(SUCCESS == delete_path("database2.db"));
419 : 2 : ASSERT(SUCCESS == restore_mutable_fixture("tests/fixtures/diffs/diff1"));
420 : :
421 : 2 : RETURN_STATUS;
422 : : }
423 : :
424 : : /**
425 : : * Nothing changes. The databases should be equivalent
426 : : */
427 : 2 : static Return test0028_5(void)
428 : : {
429 : 2 : INITTEST;
430 : :
431 : 2 : const char *arguments = "--database=database1.db tests/fixtures/diffs/diff1";
432 : :
433 : 2 : ASSERT(SUCCESS == runit(arguments,NULL,NULL,COMPLETED,ALLOW_BOTH));
434 : :
435 : 2 : arguments = "--database=database2.db tests/fixtures/diffs/diff1";
436 : :
437 : 2 : ASSERT(SUCCESS == runit(arguments,NULL,NULL,COMPLETED,ALLOW_BOTH));
438 : :
439 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
440 : :
441 : 2 : arguments = "--check-level=QUICK --compare database1.db database2.db";
442 : :
443 : 2 : const struct argument_test_case cases[] = {
444 : : {arguments,COMPLETED,"templates/0028_005.txt",STDERR_MUST_BE_EMPTY},
445 : : {0}
446 : : };
447 : :
448 : 2 : ASSERT(SUCCESS == run_and_match_templates(cases,NULL,NULL));
449 : :
450 : : // Clean up test results
451 : 2 : ASSERT(SUCCESS == delete_path("database1.db"));
452 : 2 : ASSERT(SUCCESS == delete_path("database2.db"));
453 : :
454 : 2 : RETURN_STATUS;
455 : : }
456 : :
457 : : /**
458 : : * @brief Check compare-filter categories, repetitions, and validation through CLI and configuration
459 : : */
460 : 2 : static Return test0028_6(void)
461 : : {
462 : 2 : INITTEST;
463 : :
464 : 2 : SLOWTEST;
465 : :
466 : 2 : ASSERT(SUCCESS == copy_path("tests/templates/0028_006_21.conf","0028_006_21.conf"));
467 : 2 : ASSERT(SUCCESS == copy_path("tests/templates/0028_006_9.conf","0028_006_9.conf"));
468 : 2 : ASSERT(SUCCESS == copy_path("tests/templates/0028_006_10.conf","0028_006_10.conf"));
469 : 2 : ASSERT(SUCCESS == copy_path("tests/templates/0028_006_20.conf","0028_006_20.conf"));
470 : 2 : ASSERT(SUCCESS == copy_path("tests/templates/0028_006_22.conf","0028_006_22.conf"));
471 : 2 : ASSERT(SUCCESS == copy_path("tests/templates/0028_006_14.conf","0028_006_14.conf"));
472 : :
473 : 2 : const struct argument_test_case equal_cases[] = {
474 : : // Valid combinations with --compare for equal databases
475 : : {"--check-level=QUICK --compare database1.db database2.db",COMPLETED,"templates/0028_005.txt",STDERR_MUST_BE_EMPTY},
476 : : {"--check-level=QUICK --compare --compare-filter=checksum-mismatch database1.db database2.db",COMPLETED,"templates/0028_006_1.txt",STDERR_MUST_BE_EMPTY},
477 : : {"--check-level=QUICK --compare database1.db database2.db --compare-filter=checksum-mismatch",COMPLETED,"templates/0028_006_1.txt",STDERR_MUST_BE_EMPTY},
478 : : {"--check-level=QUICK --compare --compare-filter=first-source database1.db database2.db",COMPLETED,"templates/0028_006_2.txt",STDERR_MUST_BE_EMPTY},
479 : : {"--check-level=QUICK --compare --compare-filter=second-source database1.db database2.db",COMPLETED,"templates/0028_006_3.txt",STDERR_MUST_BE_EMPTY},
480 : : {"--check-level=QUICK --compare --compare-filter=first-source --compare-filter=second-source database1.db database2.db",COMPLETED,"templates/0028_006_4.txt",STDERR_MUST_BE_EMPTY},
481 : : {"--check-level=QUICK --compare --compare-filter=checksum-mismatch --compare-filter=first-source database1.db database2.db",COMPLETED,"templates/0028_006_5.txt",STDERR_MUST_BE_EMPTY},
482 : : {"--check-level=QUICK --compare --compare-filter=checksum-mismatch --compare-filter=second-source database1.db database2.db",COMPLETED,"templates/0028_006_6.txt",STDERR_MUST_BE_EMPTY},
483 : : {"--check-level=QUICK --compare --compare-filter=checksum-mismatch --compare-filter=first-source --compare-filter=second-source database1.db database2.db",COMPLETED,"templates/0028_006_19.txt",STDERR_MUST_BE_EMPTY},
484 : : {0}
485 : : };
486 : :
487 : 2 : const struct argument_test_case one_sided_cases[] = {
488 : : // Regression: one-sided filter must not claim full identity if opposite side has differences
489 : : {"--check-level=QUICK --compare --compare-filter=first-source database1.db database2.db",COMPLETED,"templates/0028_006_7.txt",STDERR_MUST_BE_EMPTY},
490 : : {"--check-level=QUICK --compare --compare-filter=second-source database1.db database2.db",COMPLETED,"templates/0028_006_8.txt",STDERR_MUST_BE_EMPTY},
491 : : {"--check-level=QUICK --compare database2.db database1.db --compare-filter=first-source",COMPLETED,"templates/0028_006_17.txt",STDERR_MUST_BE_EMPTY},
492 : : {"--check-level=QUICK --compare database2.db database1.db --compare-filter=second-source",COMPLETED,"templates/0028_006_18.txt",STDERR_MUST_BE_EMPTY},
493 : : {0}
494 : : };
495 : :
496 : 2 : const struct argument_test_case differences_cases[] = {
497 : : // Valid combinations with --compare for databases with all difference categories
498 : : {"--check-level=QUICK --compare database1.db database2.db",COMPLETED,"templates/0028_001.txt",STDERR_MUST_BE_EMPTY},
499 : : {"--check-level=QUICK --compare --compare-filter=checksum-mismatch database1.db database2.db",COMPLETED,"templates/0028_006_21.txt",STDERR_MUST_BE_EMPTY},
500 : : {"--config=0028_006_21.conf",COMPLETED,"templates/0028_006_21.txt",STDERR_MUST_BE_EMPTY},
501 : : {"--check-level=QUICK --compare --compare-filter=first-source database1.db database2.db",COMPLETED,"templates/0028_006_9.txt",STDERR_MUST_BE_EMPTY},
502 : : {"--config=0028_006_9.conf",COMPLETED,"templates/0028_006_9.txt",STDERR_MUST_BE_EMPTY},
503 : : {"--check-level=QUICK --compare --compare-filter=second-source database1.db database2.db",COMPLETED,"templates/0028_006_10.txt",STDERR_MUST_BE_EMPTY},
504 : : {"--config=0028_006_10.conf",COMPLETED,"templates/0028_006_10.txt",STDERR_MUST_BE_EMPTY},
505 : : {"--check-level=QUICK --compare --compare-filter=checksum-mismatch --compare-filter=first-source database1.db database2.db",COMPLETED,"templates/0028_006_11.txt",STDERR_MUST_BE_EMPTY},
506 : : {"--check-level=QUICK --compare --compare-filter=checksum-mismatch --compare-filter=second-source database1.db database2.db",COMPLETED,"templates/0028_006_12.txt",STDERR_MUST_BE_EMPTY},
507 : : {"--check-level=QUICK --compare --compare-filter=first-source --compare-filter=second-source database1.db database2.db",COMPLETED,"templates/0028_006_13.txt",STDERR_MUST_BE_EMPTY},
508 : : {"--check-level=QUICK --compare --compare-filter=checksum-mismatch --compare-filter=first-source --compare-filter=second-source database1.db database2.db",COMPLETED,"templates/0028_006_20.txt",STDERR_MUST_BE_EMPTY},
509 : : {"--config=0028_006_20.conf",COMPLETED,"templates/0028_006_20.txt",STDERR_MUST_BE_EMPTY},
510 : :
511 : : // Repeating a category must not duplicate its report or enable other categories
512 : : {"--check-level=QUICK --compare --compare-filter=checksum-mismatch --compare-filter=checksum-mismatch database1.db database2.db",COMPLETED,"templates/0028_006_21.txt",STDERR_MUST_BE_EMPTY},
513 : : {"--config=0028_006_22.conf",COMPLETED,"templates/0028_006_21.txt",STDERR_MUST_BE_EMPTY},
514 : : {0}
515 : : };
516 : :
517 : 2 : const struct argument_test_case invalid_cases[] = {
518 : : // Invalid combinations: --compare-filter=value without --compare
519 : : {"--compare-filter=checksum-mismatch database1.db database2.db",FAILURE,"templates/0028_006_14.txt","templates/0028_006_15.txt"},
520 : : {"--config=0028_006_14.conf",FAILURE,"templates/0028_006_14.txt","templates/0028_006_15.txt"},
521 : : {"--compare-filter=first-source database1.db database2.db",FAILURE,"templates/0028_006_14.txt","templates/0028_006_15.txt"},
522 : : {"--compare-filter=second-source database1.db database2.db",FAILURE,"templates/0028_006_14.txt","templates/0028_006_15.txt"},
523 : : {"--compare-filter=checksum-mismatch --compare-filter=first-source database1.db database2.db",FAILURE,"templates/0028_006_14.txt","templates/0028_006_15.txt"},
524 : : {"--compare-filter=checksum-mismatch --compare-filter=second-source database1.db database2.db",FAILURE,"templates/0028_006_14.txt","templates/0028_006_15.txt"},
525 : : {"--compare-filter=first-source --compare-filter=second-source database1.db database2.db",FAILURE,"templates/0028_006_14.txt","templates/0028_006_15.txt"},
526 : : {"--compare-filter=checksum-mismatch --compare-filter=first-source --compare-filter=second-source database1.db database2.db",FAILURE,"templates/0028_006_14.txt","templates/0028_006_15.txt"},
527 : :
528 : : // Invalid combinations: --compare-filter without argument
529 : : {"--compare database1.db database2.db --compare-filter",FAILURE,NULL,"templates/0028_006_16.txt"},
530 : : {"--compare-filter",FAILURE,NULL,"templates/0028_006_16.txt"},
531 : : {0}
532 : : };
533 : :
534 : 2 : ASSERT(SUCCESS & prepare_compare_filter_equal_fixture());
535 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
536 : :
537 : 2 : ASSERT(SUCCESS == run_and_match_templates(equal_cases,NULL,NULL));
538 : :
539 : 2 : ASSERT(SUCCESS & cleanup_compare_filter_equal_fixture());
540 : :
541 : 2 : ASSERT(SUCCESS & prepare_compare_filter_one_sided_fixture());
542 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
543 : :
544 : 2 : ASSERT(SUCCESS == run_and_match_templates(one_sided_cases,NULL,NULL));
545 : :
546 : 2 : ASSERT(SUCCESS & cleanup_compare_filter_differences_fixture());
547 : :
548 : 2 : ASSERT(SUCCESS & prepare_compare_filter_differences_fixture());
549 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
550 : :
551 : 2 : ASSERT(SUCCESS == run_and_match_templates(differences_cases,NULL,NULL));
552 : :
553 : 2 : ASSERT(SUCCESS & cleanup_compare_filter_differences_fixture());
554 : :
555 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
556 : :
557 : 2 : ASSERT(SUCCESS == run_and_match_templates(invalid_cases,NULL,NULL));
558 : :
559 : 2 : call(delete_path_if_present("0028_006_21.conf"));
560 : 2 : call(delete_path_if_present("0028_006_9.conf"));
561 : 2 : call(delete_path_if_present("0028_006_10.conf"));
562 : 2 : call(delete_path_if_present("0028_006_20.conf"));
563 : 2 : call(delete_path_if_present("0028_006_22.conf"));
564 : 2 : call(delete_path_if_present("0028_006_14.conf"));
565 : :
566 : 2 : RETURN_STATUS;
567 : : }
568 : :
569 : : /**
570 : : * @brief Reject empty and unsupported compare-filter values with or without comparison
571 : : *
572 : : * Both settings sources stop at the first invalid value. Later valid or invalid
573 : : * entries must neither hide that error nor produce additional diagnostics
574 : : */
575 : 2 : static Return test0028_7(void)
576 : : {
577 : 2 : INITTEST;
578 : :
579 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
580 : :
581 : 2 : ASSERT(SUCCESS == copy_path("tests/templates/0028_007_1.conf","0028_007_1.conf"));
582 : 2 : ASSERT(SUCCESS == copy_path("tests/templates/0028_007_2.conf","0028_007_2.conf"));
583 : 2 : ASSERT(SUCCESS == copy_path("tests/templates/0028_007_3.conf","0028_007_3.conf"));
584 : 2 : ASSERT(SUCCESS == copy_path("tests/templates/0028_007_4.conf","0028_007_4.conf"));
585 : 2 : ASSERT(SUCCESS == copy_path("tests/templates/0028_007_5.conf","0028_007_5.conf"));
586 : :
587 : 2 : const struct argument_test_case cases[] = {
588 : : {"--compare --compare-filter=invalid-value database1.db database2.db",FAILURE,"templates/0028_007_3.txt","templates/0028_007_1.txt"},
589 : : {"--config=0028_007_1.conf",FAILURE,"templates/0028_007_4.txt","templates/0028_007_2.txt"},
590 : : {"--compare --compare-filter= database1.db database2.db",FAILURE,"templates/0028_007_3.txt","templates/0028_007_5.txt"},
591 : : {"--config=0028_007_2.conf",FAILURE,"templates/0028_007_4.txt","templates/0028_007_6.txt"},
592 : :
593 : : // Value errors precede the check requiring comparison mode
594 : : {"--compare-filter=invalid-value database1.db database2.db",FAILURE,"templates/0028_007_3.txt","templates/0028_007_1.txt"},
595 : : {"--config=0028_007_3.conf",FAILURE,"templates/0028_007_4.txt","templates/0028_007_7.txt"},
596 : : {"--compare-filter= database1.db database2.db",FAILURE,"templates/0028_007_3.txt","templates/0028_007_5.txt"},
597 : : {"--config=0028_007_4.conf",FAILURE,"templates/0028_007_4.txt","templates/0028_007_8.txt"},
598 : :
599 : : // Only the first invalid value is reported, regardless of subsequent entries
600 : : {"--compare --compare-filter=invalid-value --compare-filter=first-source --compare-filter=later-invalid-value database1.db database2.db",FAILURE,"templates/0028_007_3.txt","templates/0028_007_1.txt"},
601 : : {"--config=0028_007_5.conf",FAILURE,"templates/0028_007_4.txt","templates/0028_007_2.txt"},
602 : : {0}
603 : : };
604 : :
605 : 2 : ASSERT(SUCCESS == run_and_match_templates(cases,NULL,NULL));
606 : :
607 : 2 : call(delete_path_if_present("0028_007_1.conf"));
608 : 2 : call(delete_path_if_present("0028_007_2.conf"));
609 : 2 : call(delete_path_if_present("0028_007_3.conf"));
610 : 2 : call(delete_path_if_present("0028_007_4.conf"));
611 : 2 : call(delete_path_if_present("0028_007_5.conf"));
612 : :
613 : 2 : RETURN_STATUS;
614 : : }
615 : :
616 : : /**
617 : : * NULL vs non-NULL SHA512 rows must be reported as checksum mismatches
618 : : */
619 : 2 : static Return test0028_8(void)
620 : : {
621 : 2 : INITTEST;
622 : :
623 : 2 : ASSERT(SUCCESS & prepare_compare_filter_equal_fixture());
624 : 2 : ASSERT(SUCCESS == db_set_sha512_to_null("database2.db","1/AAA/ZAW/D/e/f/b_file.txt"));
625 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
626 : :
627 : 2 : const struct argument_test_case cases[] = {
628 : : {"--check-level=QUICK --compare database1.db database2.db",COMPLETED,"templates/0028_000.txt",STDERR_MUST_BE_EMPTY},
629 : : {0}
630 : : };
631 : :
632 : 2 : ASSERT(SUCCESS == run_and_match_templates(cases,NULL,NULL));
633 : :
634 : 2 : ASSERT(SUCCESS & cleanup_compare_filter_equal_fixture());
635 : :
636 : 2 : RETURN_STATUS;
637 : : }
638 : :
639 : : /**
640 : : * NULL SHA512 produced by fixture changes must be reported as a mismatch
641 : : */
642 : 2 : static Return test0028_9(void)
643 : : {
644 : 2 : INITTEST;
645 : :
646 : 2 : m_create(char,result,MEMORY_STRING);
647 : :
648 : 2 : ASSERT(SUCCESS == prepare_mutable_fixture("tests/fixtures/diffs/diff1"));
649 : :
650 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","false"));
651 : :
652 : 2 : const char *arguments = "--silent --database=database1.db tests/fixtures/diffs/diff1";
653 : 2 : ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
654 : :
655 : 2 : ASSERT(result->length == 0);
656 : :
657 : 2 : ASSERT(SUCCESS == truncate_file_to_zero_size("tests/fixtures/diffs/diff1/1/AAA/ZAW/D/e/f/b_file.txt"));
658 : :
659 : 2 : arguments = "--silent --database=database2.db tests/fixtures/diffs/diff1";
660 : 2 : ASSERT(SUCCESS == runit(arguments,result,NULL,COMPLETED,ALLOW_BOTH));
661 : :
662 : 2 : ASSERT(result->length == 0);
663 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
664 : :
665 : 2 : const struct argument_test_case cases[] = {
666 : : {"--check-level=QUICK --compare database1.db database2.db",COMPLETED,"templates/0028_000.txt",STDERR_MUST_BE_EMPTY},
667 : : {0}
668 : : };
669 : :
670 : 2 : ASSERT(SUCCESS == run_and_match_templates(cases,NULL,NULL));
671 : :
672 : 2 : ASSERT(SUCCESS == delete_path("database1.db"));
673 : 2 : ASSERT(SUCCESS == delete_path("database2.db"));
674 : 2 : ASSERT(SUCCESS == restore_mutable_fixture("tests/fixtures/diffs/diff1"));
675 : :
676 : 2 : m_del(result);
677 : :
678 : 2 : RETURN_STATUS;
679 : : }
680 : :
681 : : /**
682 : : * Compare mode must support attached database paths containing apostrophes
683 : : */
684 : 2 : static Return test0028_10(void)
685 : : {
686 : 2 : INITTEST;
687 : :
688 : 2 : ASSERT(SUCCESS & prepare_compare_filter_equal_fixture());
689 : 2 : ASSERT(SUCCESS == move_path("database1.db","database'1.db"));
690 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
691 : :
692 : 2 : const struct argument_test_case cases[] = {
693 : : {"--check-level=QUICK --compare database\\'1.db database2.db",COMPLETED,"templates/0028_010_1.txt",STDERR_MUST_BE_EMPTY},
694 : : {0}
695 : : };
696 : :
697 : 2 : ASSERT(SUCCESS == run_and_match_templates(cases,NULL,NULL));
698 : :
699 : : /* The apostrophe is literal in the configuration value */
700 : 2 : ASSERT(SUCCESS == copy_path("tests/templates/0028_010_1.conf","0028_010_1.conf"));
701 : 2 : const struct argument_test_case file_cases[] = {
702 : : {"--config=0028_010_1.conf",COMPLETED,"templates/0028_010_1.txt",STDERR_MUST_BE_EMPTY},
703 : : {0}
704 : : };
705 : 2 : ASSERT(SUCCESS == run_and_match_templates(file_cases,NULL,NULL));
706 : 2 : call(delete_path_if_present("0028_010_1.conf"));
707 : :
708 : 2 : ASSERT(SUCCESS == delete_path("database'1.db"));
709 : 2 : ASSERT(SUCCESS == delete_path("database2.db"));
710 : :
711 : 2 : RETURN_STATUS;
712 : : }
713 : :
714 : : /**
715 : : * Silent compare mode should print only compare results
716 : : */
717 : 2 : static Return test0028_11(void)
718 : : {
719 : : /* This function was reviewed line by line by a human and is not AI-generated
720 : : Any change to this function requires separate explicit approval */
721 : :
722 : 2 : INITTEST;
723 : :
724 : 2 : m_create(char,result,MEMORY_STRING);
725 : :
726 : 2 : ASSERT(SUCCESS & prepare_compare_filter_differences_fixture());
727 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","false"));
728 : :
729 : 2 : ASSERT(SUCCESS & assert_compare_output("--check-level=QUICK --silent --compare database1.db database2.db",COMPLETED,"templates/0028_011_1.txt",NULL));
730 : :
731 : : /* Repeat the silent comparison without rebuilding either database */
732 : 2 : ASSERT(SUCCESS == copy_path("tests/templates/0028_011_1.conf","0028_011_1.conf"));
733 : 2 : const struct argument_test_case file_cases[] = {
734 : : {"--config=0028_011_1.conf",COMPLETED,"templates/0028_011_1.txt",STDERR_MUST_BE_EMPTY},
735 : : {0}
736 : : };
737 : 2 : ASSERT(SUCCESS == run_and_match_templates(file_cases,NULL,NULL));
738 : 2 : call(delete_path_if_present("0028_011_1.conf"));
739 : :
740 : 2 : ASSERT(SUCCESS & assert_compare_output("--check-level=QUICK --silent --compare --compare-filter=first-source database1.db database2.db",COMPLETED,"templates/0028_011_2.txt",NULL));
741 : 2 : ASSERT(SUCCESS & assert_compare_output("--check-level=QUICK --silent --compare --compare-filter=second-source database1.db database2.db",COMPLETED,"templates/0028_011_5.txt",NULL));
742 : 2 : ASSERT(SUCCESS & assert_compare_output("--check-level=QUICK --silent --compare --compare-filter=checksum-mismatch database1.db database2.db",COMPLETED,"templates/0028_011_3.txt",NULL));
743 : 2 : ASSERT(SUCCESS & assert_compare_output("--check-level=QUICK --silent --compare --compare-filter=first-source --compare-filter=second-source database1.db database2.db",COMPLETED,"templates/0028_011_4.txt",NULL));
744 : :
745 : 2 : ASSERT(SUCCESS & cleanup_compare_filter_differences_fixture());
746 : :
747 : 2 : ASSERT(SUCCESS & prepare_compare_filter_equal_fixture());
748 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","false"));
749 : :
750 : 2 : ASSERT(SUCCESS == runit("--check-level=QUICK --silent --compare database1.db database2.db",result,NULL,COMPLETED,ALLOW_BOTH));
751 : 2 : ASSERT(result->length == 0);
752 : :
753 : 2 : ASSERT(SUCCESS & cleanup_compare_filter_equal_fixture());
754 : :
755 : 2 : m_del(result);
756 : :
757 : 2 : RETURN_STATUS;
758 : : }
759 : :
760 : : /**
761 : : * Compare mode must apply --ignore and --include to the reported compare scope
762 : : *
763 : : * Hidden paths are treated as out of scope for category listings, category
764 : : * summaries, and final equality messages. Paths restored with --include become
765 : : * visible again even when they also match an --ignore pattern
766 : : */
767 : 2 : static Return test0028_12(void)
768 : : {
769 : 2 : INITTEST;
770 : :
771 : 2 : ASSERT(SUCCESS & prepare_compare_filter_differences_fixture());
772 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
773 : :
774 : 2 : ASSERT(SUCCESS == copy_path("tests/templates/0028_012_1.conf","0028_012_1.conf"));
775 : 2 : ASSERT(SUCCESS == copy_path("tests/templates/0028_012_6.conf","0028_012_6.conf"));
776 : :
777 : 2 : const struct argument_test_case cases[] = {
778 : : // All three raw differences are filtered out, so the filtered compare scope is fully identical
779 : : {"--check-level=QUICK --compare --ignore=\"^1/AAA/ZAW/D/e/f/b_file\\.txt$\" --ignore=\"^2/AAA/BBB/CZC/.*$\" database1.db database2.db",COMPLETED,"templates/0028_012_1.txt",STDERR_MUST_BE_EMPTY},
780 : : {"--config=0028_012_1.conf",COMPLETED,"templates/0028_012_1.txt",STDERR_MUST_BE_EMPTY},
781 : :
782 : : // Restore only the first-source path a.txt; the hidden checksum mismatch stays outside the reported scope
783 : : {"--check-level=QUICK --compare --ignore=\"^1/AAA/ZAW/D/e/f/b_file\\.txt$\" --ignore=\"^2/AAA/BBB/CZC/.*$\" --include=\"^2/AAA/BBB/CZC/a\\.txt$\" database1.db database2.db",COMPLETED,"templates/0028_012_2.txt",STDERR_MUST_BE_EMPTY},
784 : :
785 : : // Keep only the first-source path a.txt visible by filtering out the checksum mismatch and the opposite-side path
786 : : {"--check-level=QUICK --compare --ignore=\"^1/AAA/ZAW/D/e/f/b_file\\.txt$\" --ignore=\"^2/AAA/BBB/CZC/b\\.txt$\" database1.db database2.db",COMPLETED,"templates/0028_012_3.txt",STDERR_MUST_BE_EMPTY},
787 : :
788 : : // Hide only a.txt so the remaining reported scope still contains the opposite-side path and the checksum mismatch
789 : : {"--check-level=QUICK --compare --ignore=\"^2/AAA/BBB/CZC/a\\.txt$\" database1.db database2.db",COMPLETED,"templates/0028_012_4.txt",STDERR_MUST_BE_EMPTY},
790 : :
791 : : // Ignore everything, then restore only b.txt; the checksum mismatch remains intentionally out of scope
792 : : {"--check-level=QUICK --compare --ignore=\"^.*$\" --include=\"^2/AAA/BBB/CZC/b\\.txt$\" database1.db database2.db",COMPLETED,"templates/0028_012_5.txt",STDERR_MUST_BE_EMPTY},
793 : :
794 : : // Ignore the whole 2/ subtree, then restore both existence-side differences while the 1/ checksum mismatch remains visible
795 : : {"--check-level=QUICK --compare --ignore=\"^2/.*$\" --include=\"^2/AAA/BBB/CZC/a\\.txt$\" --include=\"^2/AAA/BBB/CZC/b\\.txt$\" database1.db database2.db",COMPLETED,"templates/0028_012_6.txt",STDERR_MUST_BE_EMPTY},
796 : : {"--config=0028_012_6.conf",COMPLETED,"templates/0028_012_6.txt",STDERR_MUST_BE_EMPTY},
797 : : {0}
798 : : };
799 : :
800 : 2 : ASSERT(SUCCESS == run_and_match_templates(cases,NULL,NULL));
801 : :
802 : 2 : call(delete_path_if_present("0028_012_1.conf"));
803 : 2 : call(delete_path_if_present("0028_012_6.conf"));
804 : 2 : ASSERT(SUCCESS & cleanup_compare_filter_differences_fixture());
805 : :
806 : 2 : RETURN_STATUS;
807 : : }
808 : :
809 : : /**
810 : : * @brief Reject comparison with one or three database paths from either settings source
811 : : * @return Return status for matching CLI and configuration diagnostics
812 : : */
813 : 2 : static Return test0028_13(void)
814 : : {
815 : 2 : INITTEST;
816 : :
817 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
818 : 2 : ASSERT(SUCCESS == copy_path("tests/templates/0028_013_1.conf","0028_013_1.conf"));
819 : 2 : ASSERT(SUCCESS == copy_path("tests/templates/0028_013_2.conf","0028_013_2.conf"));
820 : :
821 : 2 : const struct argument_test_case cases[] = {
822 : : {"--compare first.db",FAILURE,"templates/0028_006_14.txt","templates/0003_011.txt"},
823 : : {"--config=0028_013_1.conf",FAILURE,"templates/0028_006_14.txt","templates/0003_011.txt"},
824 : : {"--compare first.db second.db third.db",FAILURE,"templates/0028_006_14.txt","templates/0028_013_1.txt"},
825 : : {"--config=0028_013_2.conf",FAILURE,"templates/0028_006_14.txt","templates/0028_013_1.txt"},
826 : : {0}
827 : : };
828 : 2 : ASSERT(SUCCESS == run_and_match_templates(cases,NULL,NULL));
829 : :
830 : 2 : call(delete_path_if_present("0028_013_1.conf"));
831 : 2 : call(delete_path_if_present("0028_013_2.conf"));
832 : :
833 : 2 : RETURN_STATUS;
834 : : }
835 : :
836 : : /**
837 : : *
838 : : * Testing the --compare mode across different types of responses
839 : : *
840 : : */
841 : 2 : Return test0028(void)
842 : : {
843 : 2 : INITTEST;
844 : :
845 : 2 : TEST(test0028_1,"One file is removed, updated, and added at a time");
846 : 2 : TEST(test0028_2,"One file is removed. It should be reflected as a change in one of the databases");
847 : 2 : TEST(test0028_3,"One file is added. It should be reflected as a change in one of the databases");
848 : 2 : TEST(test0028_4,"One file is updated and its checksum should change");
849 : 2 : TEST(test0028_5,"Nothing changes. The databases should be equivalent");
850 : 2 : TEST(test0028_6,"All supported --compare-filter combinations should behave as expected");
851 : 2 : TEST(test0028_7,"Invalid --compare-filter value should fail with an argument parsing error");
852 : 2 : TEST(test0028_8,"NULL and non-NULL SHA512 values should be reported as mismatches");
853 : 2 : TEST(test0028_9,"NULL SHA512 created from fixture changes should be reported as a mismatch");
854 : 2 : TEST(test0028_10,"Compare mode should work with database names containing apostrophes");
855 : 2 : TEST(test0028_11,"Silent compare mode should print only compare results");
856 : 2 : TEST(test0028_12,"Compare mode should apply --ignore and --include to the reported comparison scope, including summaries and equality messages");
857 : 2 : TEST(test0028_13,"Comparison requires exactly two database paths through CLI and configuration");
858 : :
859 : 2 : RETURN_STATUS;
860 : : }
|