Branch data Line data Source code
1 : : #include "sute.h"
2 : :
3 : : /**
4 : : * @brief Check the default hostname.db name and ignore scan roots during comparison
5 : : *
6 : : * @return Return status for database creation and both comparison scenarios
7 : : */
8 : 2 : Return test0003_1(void)
9 : : {
10 : 2 : INITTEST;
11 : :
12 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
13 : :
14 : 2 : const char *arguments = "--progress tests/fixtures/diffs/diff1";
15 : :
16 : 2 : ASSERT(SUCCESS == runit(arguments,NULL,NULL,COMPLETED,ALLOW_BOTH));
17 : :
18 : 2 : arguments = "--progress --database=database2.db "
19 : : "tests/fixtures/diffs/diff2";
20 : :
21 : 2 : ASSERT(SUCCESS == runit(arguments,NULL,NULL,COMPLETED,ALLOW_BOTH));
22 : :
23 : : // Get the output of the application
24 : 2 : const struct argument_test_case cases[] = {
25 : : {"--compare $DBNAME database2.db",COMPLETED,"templates/0003_001.txt",STDERR_MUST_BE_EMPTY},
26 : : /* Named roots must be discarded before compare validation and diagnostics */
27 : : {"--path=/definitely/nonexistent/first --compare $DBNAME "
28 : : "--path=/definitely/nonexistent/second database2.db",COMPLETED,"templates/0003_001.txt",STDERR_MUST_BE_EMPTY},
29 : : {0}
30 : : };
31 : 2 : const char *template = "%DB_NAME%";
32 : :
33 : 2 : const char *replacement = getenv("DBNAME"); // Database name
34 : :
35 : 2 : ASSERT(replacement != NULL);
36 : :
37 : 2 : ASSERT(SUCCESS == run_and_match_templates(cases,template,replacement));
38 : :
39 : : // Clean up test results
40 : 2 : ASSERT(SUCCESS == delete_path(replacement));
41 : 2 : ASSERT(SUCCESS == delete_path("database2.db"));
42 : :
43 : 2 : RETURN_STATUS;
44 : : }
45 : :
46 : : /**
47 : : * @brief Check usage output and successful completion without arguments
48 : : *
49 : : * @return Return status for the no-argument invocation
50 : : */
51 : 2 : Return test0003_2(void)
52 : : {
53 : 2 : INITTEST;
54 : :
55 : 2 : const struct argument_test_case cases[] = {
56 : : {"",COMPLETED,"templates/0003_003.txt","templates/0003_002.txt"},
57 : : {0}
58 : : };
59 : :
60 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
61 : :
62 : 2 : ASSERT(SUCCESS == run_and_match_templates(cases,NULL,NULL));
63 : :
64 : 2 : RETURN_STATUS;
65 : :
66 : : }
67 : :
68 : : /**
69 : : * @brief Check that information modes complete successfully without PATH
70 : : *
71 : : * Run each command first without a default configuration file, then with an
72 : : * invalid default file. Both runs must produce the same output and status.
73 : : * Explicit file selections are also ignored for missing and malformed files
74 : : *
75 : : * @return Return status for help, usage, and version output
76 : : */
77 : 2 : Return test0003_3(void)
78 : : {
79 : 2 : INITTEST;
80 : 2 : const struct argument_test_case cases[] = {
81 : : {"--help",COMPLETED,"templates/0003_004.txt",STDERR_MUST_BE_EMPTY},
82 : : {"-h",COMPLETED,"templates/0003_004.txt",STDERR_MUST_BE_EMPTY},
83 : : {"'-?'",COMPLETED,"templates/0003_004.txt",STDERR_MUST_BE_EMPTY},
84 : : {"--usage",COMPLETED,"templates/0003_005.txt",STDERR_MUST_BE_EMPTY},
85 : : {"-z",COMPLETED,"templates/0003_005.txt",STDERR_MUST_BE_EMPTY},
86 : : {"--version",COMPLETED,"templates/0003_006.txt",STDERR_MUST_BE_EMPTY},
87 : : {"-V",COMPLETED,"templates/0003_006.txt",STDERR_MUST_BE_EMPTY},
88 : : {"--version --version",COMPLETED,"templates/0003_006.txt",STDERR_MUST_BE_EMPTY},
89 : : {0}
90 : : };
91 : 2 : const struct argument_test_case config_cases[] = {
92 : : {"--config=0003_003.conf --help",COMPLETED,"templates/0003_004.txt",STDERR_MUST_BE_EMPTY},
93 : : {"--help --config=0003_003.conf",COMPLETED,"templates/0003_004.txt",STDERR_MUST_BE_EMPTY},
94 : : {"-g0003_003.conf -h",COMPLETED,"templates/0003_004.txt",STDERR_MUST_BE_EMPTY},
95 : : {"'-?g0003_003.conf'",COMPLETED,"templates/0003_004.txt",STDERR_MUST_BE_EMPTY},
96 : : {"--config=0003_003.conf --usage",COMPLETED,"templates/0003_005.txt",STDERR_MUST_BE_EMPTY},
97 : : {"-z -g 0003_003.conf",COMPLETED,"templates/0003_005.txt",STDERR_MUST_BE_EMPTY},
98 : : {"--config=0003_003.conf --version",COMPLETED,"templates/0003_006.txt",STDERR_MUST_BE_EMPTY},
99 : : {"-Vg0003_003.conf",COMPLETED,"templates/0003_006.txt",STDERR_MUST_BE_EMPTY},
100 : : {"--config=0003_003.conf --help --version",COMPLETED,"templates/0003_004.txt",STDERR_MUST_BE_EMPTY},
101 : : {"--config=0003_003.conf --compare --help",COMPLETED,"templates/0003_004.txt",STDERR_MUST_BE_EMPTY},
102 : : {"--path=/definitely/nonexistent/path --config=0003_003.conf --version",COMPLETED,"templates/0003_006.txt",STDERR_MUST_BE_EMPTY},
103 : : {0}
104 : : };
105 : :
106 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
107 : :
108 : 2 : ASSERT(SUCCESS == run_and_match_templates(cases,NULL,NULL));
109 : :
110 : : /* Informational CLI requests must not read a malformed default file */
111 : 2 : ASSERT(SUCCESS == copy_from_origin("tests/templates/0003_003.conf",
112 : : "precizer.conf",REQUIRE_SOURCE_EXISTS));
113 : 2 : ASSERT(SUCCESS == run_and_match_templates(cases,NULL,NULL));
114 : :
115 : : /* An explicit selection must not cause a conflict or a file access */
116 : 2 : ASSERT(SUCCESS == run_and_match_templates(config_cases,NULL,NULL));
117 : 2 : ASSERT(SUCCESS == copy_from_origin("tests/templates/0003_003.conf",
118 : : "0003_003.conf",REQUIRE_SOURCE_EXISTS));
119 : 2 : ASSERT(SUCCESS == run_and_match_templates(config_cases,NULL,NULL));
120 : 2 : call(delete_path_if_present("0003_003.conf"));
121 : 2 : call(delete_path_if_present("precizer.conf"));
122 : :
123 : 2 : RETURN_STATUS;
124 : : }
125 : :
126 : : /**
127 : : * @brief Check that information modes ignore PATH and stop before the main workflow
128 : : *
129 : : * Invalid regex values must not be compiled when help, usage, or version is requested
130 : : *
131 : : * @return Return status for information modes combined with paths and comparison
132 : : */
133 : 2 : Return test0003_4(void)
134 : : {
135 : 2 : INITTEST;
136 : 2 : const struct argument_test_case cases[] = {
137 : : {"--help /definitely/nonexistent/path",COMPLETED,"templates/0003_004.txt",STDERR_MUST_BE_EMPTY},
138 : : {"-h /definitely/nonexistent/path",COMPLETED,"templates/0003_004.txt",STDERR_MUST_BE_EMPTY},
139 : : {"--usage /definitely/nonexistent/path",COMPLETED,"templates/0003_005.txt",STDERR_MUST_BE_EMPTY},
140 : : {"-z /definitely/nonexistent/path",COMPLETED,"templates/0003_005.txt",STDERR_MUST_BE_EMPTY},
141 : : {"--version /definitely/nonexistent/path",COMPLETED,"templates/0003_006.txt",STDERR_MUST_BE_EMPTY},
142 : : {"--compare --help",COMPLETED,"templates/0003_004.txt",STDERR_MUST_BE_EMPTY},
143 : : {"--compare --usage",COMPLETED,"templates/0003_005.txt",STDERR_MUST_BE_EMPTY},
144 : : {"--compare -z",COMPLETED,"templates/0003_005.txt",STDERR_MUST_BE_EMPTY},
145 : : {"--compare --version",COMPLETED,"templates/0003_006.txt",STDERR_MUST_BE_EMPTY},
146 : : {"--help --version",COMPLETED,"templates/0003_004.txt",STDERR_MUST_BE_EMPTY},
147 : : {"--path=/definitely/nonexistent/path --help",COMPLETED,"templates/0003_004.txt",STDERR_MUST_BE_EMPTY},
148 : : {"--path=/definitely/nonexistent/path --usage",COMPLETED,"templates/0003_005.txt",STDERR_MUST_BE_EMPTY},
149 : : {"--path=/definitely/nonexistent/path --version",COMPLETED,"templates/0003_006.txt",STDERR_MUST_BE_EMPTY},
150 : : {"--help --ignore='('",COMPLETED,"templates/0003_004_1.txt",STDERR_MUST_BE_EMPTY},
151 : : {"--help --include='('",COMPLETED,"templates/0003_004_1.txt",STDERR_MUST_BE_EMPTY},
152 : : {"--help --lock-checksum='('",COMPLETED,"templates/0003_004_1.txt",STDERR_MUST_BE_EMPTY},
153 : : {"--usage --ignore='('",COMPLETED,"templates/0003_005.txt",STDERR_MUST_BE_EMPTY},
154 : : {"--usage --include='('",COMPLETED,"templates/0003_005.txt",STDERR_MUST_BE_EMPTY},
155 : : {"--usage --lock-checksum='('",COMPLETED,"templates/0003_005.txt",STDERR_MUST_BE_EMPTY},
156 : : {"--version --ignore='('",COMPLETED,"templates/0003_006.txt",STDERR_MUST_BE_EMPTY},
157 : : {"--version --include='('",COMPLETED,"templates/0003_006.txt",STDERR_MUST_BE_EMPTY},
158 : : {"--version --lock-checksum='('",COMPLETED,"templates/0003_006.txt",STDERR_MUST_BE_EMPTY},
159 : : {0}
160 : : };
161 : :
162 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
163 : :
164 : 2 : ASSERT(SUCCESS == run_and_match_templates(cases,NULL,NULL));
165 : :
166 : 2 : RETURN_STATUS;
167 : : }
168 : :
169 : : /**
170 : : * @brief Require named and positional roots to produce the same traversal output
171 : : *
172 : : * Run each command first without a default configuration file, then with an
173 : : * invalid default file, a valid file containing different settings, and a file
174 : : * without read permission.
175 : : * All runs must produce the same output and status
176 : : *
177 : : * @return Return status for long and short named options and positional roots
178 : : */
179 : 2 : static Return test0003_5(void)
180 : : {
181 : 2 : INITTEST;
182 : 2 : const struct argument_test_case cases[] = {
183 : : {"--dry-run --database=dry_run_regular.db tests/fixtures/diffs/diff1",COMPLETED,"templates/0013_001_1.txt",STDERR_MUST_BE_EMPTY},
184 : : {"--dry-run --database=dry_run_regular.db --path=tests/fixtures/diffs/diff1/",COMPLETED,"templates/0013_001_1.txt",STDERR_MUST_BE_EMPTY},
185 : : {"--dry-run --database=dry_run_regular.db --path tests/fixtures/diffs/diff1/",COMPLETED,"templates/0013_001_1.txt",STDERR_MUST_BE_EMPTY},
186 : : {"--dry-run --database=dry_run_regular.db -P tests/fixtures/diffs/diff1/",COMPLETED,"templates/0013_001_1.txt",STDERR_MUST_BE_EMPTY},
187 : : {0}
188 : : };
189 : :
190 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
191 : :
192 : 2 : ASSERT(SUCCESS == run_and_match_templates(cases,NULL,NULL));
193 : :
194 : : /* Ordinary CLI operations must not read a malformed default file */
195 : 2 : ASSERT(SUCCESS == copy_from_origin("tests/templates/0003_003.conf",
196 : : "precizer.conf",REQUIRE_SOURCE_EXISTS));
197 : 2 : ASSERT(SUCCESS == run_and_match_templates(cases,NULL,NULL));
198 : :
199 : : /* Valid default settings must not alter or supplement CLI settings */
200 : 2 : ASSERT(SUCCESS == copy_path("tests/templates/0003_005.conf","precizer.conf"));
201 : 2 : ASSERT(SUCCESS == run_and_match_templates(cases,NULL,NULL));
202 : :
203 : : /* Read permission on an unused default file must not affect CLI operations */
204 : 2 : ASSERT(SUCCESS == change_mode("precizer.conf",0000));
205 : 2 : ASSERT(SUCCESS == run_and_match_templates(cases,NULL,NULL));
206 : 2 : call(change_mode("precizer.conf",0600));
207 : 2 : call(delete_path_if_present("precizer.conf"));
208 : :
209 : 2 : RETURN_STATUS;
210 : : }
211 : :
212 : : /**
213 : : * @brief Preserve repeated roots and combine named roots with positional roots
214 : : *
215 : : * Named options are processed before positional arguments by argp. The full
216 : : * output must match the equivalent positional root array, including duplicates.
217 : : * A file repeat must normalize trailing slashes without removing repeated roots
218 : : *
219 : : * @return Return status for repeated, mixed, and normalized root spellings
220 : : */
221 : 2 : static Return test0003_6(void)
222 : : {
223 : 2 : INITTEST;
224 : 2 : const struct argument_test_case cases[] = {
225 : : {"--dry-run --database=0003_paths.db "
226 : : "--path=tests/fixtures/diffs/diff1/1/ --path=tests/fixtures/diffs/diff1/4 "
227 : : "--path=tests/fixtures/diffs/diff1/1",COMPLETED,"templates/0003_007.txt",STDERR_MUST_BE_EMPTY},
228 : : {"--dry-run --database=0003_paths.db "
229 : : "--path=tests/fixtures/diffs/diff1/1/ --path tests/fixtures/diffs/diff1/4/ "
230 : : "tests/fixtures/diffs/diff1/1/",COMPLETED,"templates/0003_007.txt",STDERR_MUST_BE_EMPTY},
231 : : {"--dry-run --database=0003_paths.db tests/fixtures/diffs/diff1/1/ "
232 : : "--path=tests/fixtures/diffs/diff1/1 --path=tests/fixtures/diffs/diff1/4",COMPLETED,"templates/0003_007.txt",STDERR_MUST_BE_EMPTY},
233 : : {0}
234 : : };
235 : :
236 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
237 : :
238 : 2 : ASSERT(SUCCESS == run_and_match_templates(cases,NULL,NULL));
239 : :
240 : : /* Reuse the dry-run state and full output for the same roots from a file */
241 : 2 : ASSERT(SUCCESS == copy_path("tests/templates/0003_006.conf","0003_006.conf"));
242 : 2 : const struct argument_test_case file_cases[] = {
243 : : {"--config=0003_006.conf",COMPLETED,"templates/0003_007.txt",STDERR_MUST_BE_EMPTY},
244 : : {0}
245 : : };
246 : 2 : ASSERT(SUCCESS == run_and_match_templates(file_cases,NULL,NULL));
247 : 2 : call(delete_path_if_present("0003_006.conf"));
248 : :
249 : 2 : RETURN_STATUS;
250 : : }
251 : :
252 : : /**
253 : : * @brief Reject missing roots, missing path values, and missing compare operands
254 : : *
255 : : * Empty named and positional roots are invalid. Named roots cannot substitute
256 : : * for either positional database operand required by compare mode. Missing
257 : : * scan roots produce a hint for positional paths and --path
258 : : *
259 : : * @return Return status for complete stdout and stderr diagnostics
260 : : */
261 : 2 : static Return test0003_7(void)
262 : : {
263 : 2 : INITTEST;
264 : 2 : const struct argument_test_case cases[] = {
265 : : {"--dry-run",FAILURE,"templates/0028_006_14.txt","templates/0003_007_1.txt"},
266 : : {"--",FAILURE,"templates/0028_006_14.txt","templates/0003_024.txt"},
267 : : {"-- tests/fixtures/diffs/diff1",FAILURE,"templates/0028_006_14.txt","templates/0003_024.txt"},
268 : : {"--path=tests/fixtures/diffs/diff1 --",FAILURE,"templates/0028_006_14.txt","templates/0003_024.txt"},
269 : : {"--compare --",FAILURE,"templates/0028_006_14.txt","templates/0003_024.txt"},
270 : : {"--version --",FAILURE,"templates/0028_006_14.txt","templates/0003_024.txt"},
271 : : {"--path",FAILURE,"templates/0040_003.txt","templates/0003_008.txt"},
272 : : {"--path=",FAILURE,"templates/0040_003.txt","templates/0003_010.txt"},
273 : : {"--dry-run ''",FAILURE,"templates/0040_003.txt","templates/0003_010.txt"},
274 : : {"--compare --path='' first.db second.db",FAILURE,"templates/0040_003.txt","templates/0003_010.txt"},
275 : : {"--compare --path=first.db --path=second.db",FAILURE,"templates/0028_006_14.txt","templates/0003_002.txt"},
276 : : {"--compare --path=second.db first.db",FAILURE,"templates/0028_006_14.txt","templates/0003_011.txt"},
277 : : {0}
278 : : };
279 : :
280 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
281 : :
282 : 2 : ASSERT(SUCCESS == run_and_match_templates(cases,NULL,NULL));
283 : :
284 : 2 : RETURN_STATUS;
285 : : }
286 : :
287 : : /**
288 : : * @brief Select the default file only for an argument-free invocation
289 : : *
290 : : * Missing scan roots produce a hint to add the path key to the configuration
291 : : * file, whether it was selected automatically or explicitly
292 : : *
293 : : * @return Return status for empty, documented, incomplete, and populated files
294 : : */
295 : 2 : static Return test0003_8(void)
296 : : {
297 : 2 : INITTEST;
298 : 2 : const struct argument_test_case empty_file[] = {
299 : : {"",COMPLETED,"templates/0003_003.txt","templates/0003_002.txt"},
300 : : {"--config=precizer.conf",FAILURE,"templates/0028_006_14.txt","templates/0003_008_1.txt"},
301 : : {0}
302 : : };
303 : 2 : const struct argument_test_case missing_root[] = {
304 : : {"",FAILURE,"templates/0028_006_14.txt","templates/0003_008_1.txt"},
305 : : {"--config=precizer.conf",FAILURE,"templates/0028_006_14.txt","templates/0003_008_1.txt"},
306 : : {0}
307 : : };
308 : 2 : const struct argument_test_case configured_root[] = {
309 : : {"",FAILURE,"templates/0003_012.txt",STDERR_MUST_BE_EMPTY},
310 : : {0}
311 : : };
312 : :
313 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
314 : 2 : ASSERT(SUCCESS == copy_from_origin("tests/templates/0003_008_1.conf",
315 : : "precizer.conf",REQUIRE_SOURCE_EXISTS));
316 : 2 : ASSERT(SUCCESS == run_and_match_templates(empty_file,NULL,NULL));
317 : : /* The documented default must remain safe until a setting is uncommented */
318 : 2 : ASSERT(SUCCESS == copy_from_origin("precizer.conf","precizer.conf",REQUIRE_SOURCE_EXISTS));
319 : 2 : ASSERT(SUCCESS == run_and_match_templates(empty_file,NULL,NULL));
320 : : /* A false flag is still a supplied setting, so a scan root is required */
321 : 2 : ASSERT(SUCCESS == copy_from_origin("tests/templates/0003_008_2.conf",
322 : : "precizer.conf",REQUIRE_SOURCE_EXISTS));
323 : 2 : ASSERT(SUCCESS == run_and_match_templates(missing_root,NULL,NULL));
324 : 2 : ASSERT(SUCCESS == copy_from_origin("tests/templates/0003_012.conf","precizer.conf",REQUIRE_SOURCE_EXISTS));
325 : 2 : ASSERT(SUCCESS == run_and_match_templates(configured_root,"%CONFIG_PATH%","precizer[.]conf"));
326 : :
327 : 2 : call(delete_path_if_present("precizer.conf"));
328 : 2 : RETURN_STATUS;
329 : : }
330 : :
331 : : /**
332 : : * @brief Read only the last explicit file and resolve its relative roots from the working directory
333 : : * @return Return status for long, short, attached, separate, and repeated selectors
334 : : */
335 : 2 : static Return test0003_9(void)
336 : : {
337 : 2 : INITTEST;
338 : 2 : const struct argument_test_case cases[] = {
339 : : {"--config=tests/templates/0003_012.conf",FAILURE,"templates/0003_012.txt",STDERR_MUST_BE_EMPTY},
340 : : {"--config tests/templates/0003_012.conf",FAILURE,"templates/0003_012.txt",STDERR_MUST_BE_EMPTY},
341 : : {"-g tests/templates/0003_012.conf",FAILURE,"templates/0003_012.txt",STDERR_MUST_BE_EMPTY},
342 : : {"-gtests/templates/0003_012.conf",FAILURE,"templates/0003_012.txt",STDERR_MUST_BE_EMPTY},
343 : : {"--config=0003_absent.conf -gtests/templates/0003_012.conf",FAILURE,"templates/0003_012.txt",STDERR_MUST_BE_EMPTY},
344 : : {"-gprecizer.conf --config=tests/templates/0003_012.conf",FAILURE,"templates/0003_012.txt",STDERR_MUST_BE_EMPTY},
345 : : {"--config -- -g tests/templates/0003_012.conf",FAILURE,"templates/0003_012.txt",STDERR_MUST_BE_EMPTY},
346 : : {0}
347 : : };
348 : :
349 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
350 : 2 : ASSERT(SUCCESS == copy_from_origin("tests/templates/0003_003.conf",
351 : : "precizer.conf",REQUIRE_SOURCE_EXISTS));
352 : 2 : ASSERT(SUCCESS == copy_from_origin("tests/templates/0003_012.conf","tests/templates/0003_012.conf",REQUIRE_SOURCE_EXISTS));
353 : : /* A root relative to the config directory would incorrectly find this directory */
354 : 2 : ASSERT(SUCCESS == create_directory("tests/templates/0003_missing_root"));
355 : 2 : ASSERT(SUCCESS == run_and_match_templates(cases,"%CONFIG_PATH%","tests/templates/0003_012[.]conf"));
356 : :
357 : 2 : call(delete_path_if_present("tests/templates/0003_missing_root"));
358 : 2 : call(delete_path_if_present("tests/templates/0003_012.conf"));
359 : 2 : call(delete_path_if_present("precizer.conf"));
360 : 2 : RETURN_STATUS;
361 : : }
362 : :
363 : : /**
364 : : * @brief Accept option-like values and configuration filenames containing spaces
365 : : *
366 : : * Config selector names passed as --path or -P values remain scan roots.
367 : : * Missing directories must produce path diagnostics, not source-selection errors
368 : : *
369 : : * @return Return status for literal option-like values and quoted paths
370 : : */
371 : 2 : static Return test0003_10(void)
372 : : {
373 : 2 : INITTEST;
374 : 2 : const struct argument_test_case delimiter_name[] = {
375 : : {"--config=--",FAILURE,"templates/0003_012.txt",STDERR_MUST_BE_EMPTY},
376 : : {"-g--",FAILURE,"templates/0003_012.txt",STDERR_MUST_BE_EMPTY},
377 : : {0}
378 : : };
379 : 2 : const struct argument_test_case relative_name[] = {
380 : : {"--config ./--",FAILURE,"templates/0003_012.txt",STDERR_MUST_BE_EMPTY},
381 : : {0}
382 : : };
383 : 2 : const struct argument_test_case option_name[] = {
384 : : {"--config --help",FAILURE,"templates/0003_012.txt",STDERR_MUST_BE_EMPTY},
385 : : {0}
386 : : };
387 : 2 : const struct argument_test_case spaced_name[] = {
388 : : {"-g '0003 config.conf'",FAILURE,"templates/0003_012.txt",STDERR_MUST_BE_EMPTY},
389 : : {0}
390 : : };
391 : 2 : const struct argument_test_case root_values[] = {
392 : : {"--path --config --path -g",FAILURE,"templates/0003_010_1.txt",STDERR_MUST_BE_EMPTY},
393 : : {"-P --config -P -g",FAILURE,"templates/0003_010_1.txt",STDERR_MUST_BE_EMPTY},
394 : : {0}
395 : : };
396 : :
397 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
398 : 2 : ASSERT(SUCCESS == copy_from_origin("tests/templates/0003_012.conf","--",REQUIRE_SOURCE_EXISTS));
399 : 2 : ASSERT(SUCCESS == run_and_match_templates(delimiter_name,"%CONFIG_PATH%","--"));
400 : 2 : ASSERT(SUCCESS == run_and_match_templates(relative_name,"%CONFIG_PATH%","[.]/--"));
401 : 2 : ASSERT(SUCCESS == copy_from_origin("tests/templates/0003_012.conf","--help",REQUIRE_SOURCE_EXISTS));
402 : 2 : ASSERT(SUCCESS == run_and_match_templates(option_name,"%CONFIG_PATH%","--help"));
403 : 2 : ASSERT(SUCCESS == copy_from_origin("tests/templates/0003_012.conf","0003 config.conf",REQUIRE_SOURCE_EXISTS));
404 : 2 : ASSERT(SUCCESS == run_and_match_templates(spaced_name,"%CONFIG_PATH%","0003 config[.]conf"));
405 : 2 : ASSERT(SUCCESS == run_and_match_templates(root_values,NULL,NULL));
406 : :
407 : 2 : call(delete_path_if_present("0003 config.conf"));
408 : 2 : call(delete_path_if_present("--help"));
409 : 2 : call(delete_path_if_present("--"));
410 : 2 : RETURN_STATUS;
411 : : }
412 : :
413 : : /**
414 : : * @brief Reject explicit file selection combined with other CLI arguments before opening the file
415 : : *
416 : : * Check all selector forms, both argument orders, repeated selections, and a
417 : : * short-option group. Missing, malformed, and unreadable files must produce
418 : : * the same source-conflict diagnostic without attempting to read settings
419 : : *
420 : : * @return Return status for operational and positional conflicts
421 : : */
422 : 2 : static Return test0003_11(void)
423 : : {
424 : 2 : INITTEST;
425 : 2 : const struct argument_test_case cases[] = {
426 : : {"--config=0003_011.conf --path=0003_missing_root",FAILURE,"templates/0003_013.txt","templates/0003_014.txt"},
427 : : {"--path=0003_missing_root --config=0003_011.conf",FAILURE,"templates/0003_013.txt","templates/0003_014.txt"},
428 : : {"--config=0003_011.conf 0003_missing_root",FAILURE,"templates/0003_013.txt","templates/0003_014.txt"},
429 : : {"0003_missing_root --config=0003_011.conf",FAILURE,"templates/0003_013.txt","templates/0003_014.txt"},
430 : : {"--config 0003_011.conf --path=0003_missing_root",FAILURE,"templates/0003_013.txt","templates/0003_014.txt"},
431 : : {"--path=0003_missing_root --config 0003_011.conf",FAILURE,"templates/0003_013.txt","templates/0003_014.txt"},
432 : : {"--config 0003_011.conf 0003_missing_root",FAILURE,"templates/0003_013.txt","templates/0003_014.txt"},
433 : : {"0003_missing_root --config 0003_011.conf",FAILURE,"templates/0003_013.txt","templates/0003_014.txt"},
434 : : {"-g 0003_011.conf --path=0003_missing_root",FAILURE,"templates/0003_013.txt","templates/0003_014.txt"},
435 : : {"--path=0003_missing_root -g 0003_011.conf",FAILURE,"templates/0003_013.txt","templates/0003_014.txt"},
436 : : {"-g 0003_011.conf 0003_missing_root",FAILURE,"templates/0003_013.txt","templates/0003_014.txt"},
437 : : {"0003_missing_root -g 0003_011.conf",FAILURE,"templates/0003_013.txt","templates/0003_014.txt"},
438 : : {"-g0003_011.conf --path=0003_missing_root",FAILURE,"templates/0003_013.txt","templates/0003_014.txt"},
439 : : {"--path=0003_missing_root -g0003_011.conf",FAILURE,"templates/0003_013.txt","templates/0003_014.txt"},
440 : : {"-g0003_011.conf 0003_missing_root",FAILURE,"templates/0003_013.txt","templates/0003_014.txt"},
441 : : {"0003_missing_root -g0003_011.conf",FAILURE,"templates/0003_013.txt","templates/0003_014.txt"},
442 : : {"-vg0003_011.conf",FAILURE,"templates/0003_013.txt","templates/0003_014.txt"},
443 : : {"--config=0003_absent.conf --path=0003_missing_root -g0003_011.conf",FAILURE,"templates/0003_013.txt","templates/0003_014.txt"},
444 : : {"0003_missing_root -g0003_absent.conf --config=0003_011.conf",FAILURE,"templates/0003_013.txt","templates/0003_014.txt"},
445 : : {0}
446 : : };
447 : :
448 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
449 : 2 : ASSERT(SUCCESS == run_and_match_templates(cases,NULL,NULL));
450 : :
451 : : /* Invalid settings must not replace the conflict with a configuration error */
452 : 2 : ASSERT(SUCCESS == copy_path("tests/templates/0003_011.conf","0003_011.conf"));
453 : 2 : ASSERT(SUCCESS == run_and_match_templates(cases,NULL,NULL));
454 : : /* File permissions must not replace the source conflict with an open error */
455 : 2 : ASSERT(SUCCESS == change_mode("0003_011.conf",0000));
456 : 2 : ASSERT(SUCCESS == run_and_match_templates(cases,NULL,NULL));
457 : 2 : call(change_mode("0003_011.conf",0600));
458 : 2 : call(delete_path_if_present("0003_011.conf"));
459 : :
460 : 2 : RETURN_STATUS;
461 : : }
462 : :
463 : : /**
464 : : * @brief Defer invalid CLI diagnostics to the main parser without reading a file
465 : : *
466 : : * Preserve the first main-pass error and any help or silent behavior preceding it
467 : : *
468 : : * @return Return status for missing values, unknown options, forbidden option values, and argp-marked --
469 : : */
470 : 2 : static Return test0003_12(void)
471 : : {
472 : 2 : INITTEST;
473 : 2 : const struct argument_test_case cases[] = {
474 : : {"--config",FAILURE,"templates/0040_003.txt","templates/0003_015.txt"},
475 : : {"-g",FAILURE,"templates/0040_003.txt","templates/0003_016.txt"},
476 : : {"--config=0003_absent.conf --path",FAILURE,"templates/0040_003.txt","templates/0003_008.txt"},
477 : : {"--config=0003_absent.conf --unknown",FAILURE,"templates/0040_003.txt","templates/0003_017.txt"},
478 : : {"--unknown --config=0003_absent.conf",FAILURE,"templates/0040_003.txt","templates/0003_017.txt"},
479 : : {"--maxdepth=bad --unknown",FAILURE,"templates/0040_003.txt","templates/0018_005_2.txt"},
480 : : {"--help --unknown",FAILURE,"templates/0003_012_1.txt","templates/0003_017.txt"},
481 : : {"--silent --unknown",FAILURE,"templates/0045_033.txt","templates/0003_017.txt"},
482 : : {"--version --config=0003_absent.conf --unknown",FAILURE,"templates/0040_003.txt","templates/0003_017.txt"},
483 : : {"--config=0003_absent.conf --version --color=invalid-value",FAILURE,"templates/0040_003.txt","templates/0040_004.txt"},
484 : : {"--config=0003_absent.conf --progress=no",FAILURE,"templates/0040_003.txt","templates/0003_018.txt"},
485 : : {"--",FAILURE,"templates/0028_006_14.txt","templates/0003_024.txt"},
486 : : {"-- tests/fixtures/diffs/diff1",FAILURE,"templates/0028_006_14.txt","templates/0003_024.txt"},
487 : : {"--path=tests/fixtures/diffs/diff1 --",FAILURE,"templates/0028_006_14.txt","templates/0003_024.txt"},
488 : : {"--compare --",FAILURE,"templates/0028_006_14.txt","templates/0003_024.txt"},
489 : : {"--version --",FAILURE,"templates/0028_006_14.txt","templates/0003_024.txt"},
490 : : {"--config --",FAILURE,"templates/0028_006_14.txt","templates/0003_024.txt"},
491 : : {"-g --",FAILURE,"templates/0028_006_14.txt","templates/0003_024.txt"},
492 : : {"--config=0003_absent.conf --",FAILURE,"templates/0028_006_14.txt","templates/0003_024.txt"},
493 : : {"--config -- --",FAILURE,"templates/0028_006_14.txt","templates/0003_024.txt"},
494 : : {"-g -- --",FAILURE,"templates/0028_006_14.txt","templates/0003_024.txt"},
495 : : {"--config=-- --",FAILURE,"templates/0028_006_14.txt","templates/0003_024.txt"},
496 : : {"-g-- --",FAILURE,"templates/0028_006_14.txt","templates/0003_024.txt"},
497 : : {0}
498 : : };
499 : :
500 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
501 : 2 : ASSERT(SUCCESS == copy_from_origin("tests/templates/0003_003.conf",
502 : : "precizer.conf",REQUIRE_SOURCE_EXISTS));
503 : 2 : ASSERT(SUCCESS == run_and_match_templates(cases,NULL,NULL));
504 : 2 : call(delete_path_if_present("precizer.conf"));
505 : 2 : RETURN_STATUS;
506 : : }
507 : :
508 : : /**
509 : : * @brief Stop startup on configuration open, read, and parsing errors without fallback
510 : : *
511 : : * A file without read permission must fail for default and explicit selection.
512 : : * Information requests must ignore the same inaccessible file
513 : : *
514 : : * @return Return status for default and explicitly selected file errors
515 : : */
516 : 2 : static Return test0003_13(void)
517 : : {
518 : 2 : INITTEST;
519 : 2 : const struct argument_test_case missing_file[] = {
520 : : {"--config=0003_absent.conf",FAILURE,"templates/0003_013.txt","templates/0003_019.txt"},
521 : : {"--config=",FAILURE,"templates/0003_013.txt","templates/0003_020.txt"},
522 : : {0}
523 : : };
524 : 2 : const struct argument_test_case invalid_file[] = {
525 : : {"",FAILURE,"templates/0003_013.txt","templates/0003_021.txt"},
526 : : {"--config=precizer.conf",FAILURE,"templates/0003_013.txt","templates/0003_021.txt"},
527 : : {0}
528 : : };
529 : :
530 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
531 : 2 : ASSERT(SUCCESS == copy_from_origin("tests/templates/0003_012.conf","precizer.conf",REQUIRE_SOURCE_EXISTS));
532 : 2 : ASSERT(SUCCESS == run_and_match_templates(missing_file,NULL,NULL));
533 : 2 : ASSERT(SUCCESS == copy_from_origin("tests/templates/0003_003.conf",
534 : : "precizer.conf",REQUIRE_SOURCE_EXISTS));
535 : 2 : ASSERT(SUCCESS == run_and_match_templates(invalid_file,NULL,NULL));
536 : 2 : call(delete_path_if_present("precizer.conf"));
537 : :
538 : : /* A directory opens successfully but causes a read error when inih reads it */
539 : 2 : const struct argument_test_case unreadable_file[] = {
540 : : {"",FAILURE,"templates/0003_013.txt","templates/0003_022.txt"},
541 : : {"--config=precizer.conf",FAILURE,"templates/0003_013.txt","templates/0003_022.txt"},
542 : : {"--version",COMPLETED,"templates/0003_006.txt",STDERR_MUST_BE_EMPTY},
543 : : {0}
544 : : };
545 : 2 : ASSERT(SUCCESS == create_directory("precizer.conf"));
546 : 2 : ASSERT(SUCCESS == run_and_match_templates(unreadable_file,NULL,NULL));
547 : 2 : call(delete_path_if_present("precizer.conf"));
548 : :
549 : : /* Permission denial is an open error, unlike a directory's read error */
550 : 2 : const struct argument_test_case denied_file[] = {
551 : : {"",FAILURE,"templates/0003_013.txt","templates/0003_013_1.txt"},
552 : : {"--config=precizer.conf",FAILURE,"templates/0003_013.txt","templates/0003_013_1.txt"},
553 : : {"--version",COMPLETED,"templates/0003_006.txt",STDERR_MUST_BE_EMPTY},
554 : : {"--config=precizer.conf --version",COMPLETED,"templates/0003_006.txt",STDERR_MUST_BE_EMPTY},
555 : : {0}
556 : : };
557 : 2 : ASSERT(SUCCESS == copy_path("tests/templates/0003_005.conf","precizer.conf"));
558 : 2 : ASSERT(SUCCESS == change_mode("precizer.conf",0000));
559 : 2 : ASSERT(SUCCESS == run_and_match_templates(denied_file,NULL,NULL));
560 : 2 : call(change_mode("precizer.conf",0600));
561 : 2 : call(delete_path_if_present("precizer.conf"));
562 : :
563 : 2 : RETURN_STATUS;
564 : : }
565 : :
566 : : /**
567 : : * @brief Include the selected file path in verbose configuration diagnostics
568 : : * @return Return status for the complete verbose startup output
569 : : */
570 : 2 : static Return test0003_14(void)
571 : : {
572 : 2 : INITTEST;
573 : 2 : const struct argument_test_case cases[] = {
574 : : {"--config=tests/templates/0003_014.conf",FAILURE,"templates/0003_023.txt",STDERR_MUST_BE_EMPTY},
575 : : {0}
576 : : };
577 : :
578 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
579 : 2 : ASSERT(SUCCESS == copy_from_origin("tests/templates/0003_014.conf","tests/templates/0003_014.conf",REQUIRE_SOURCE_EXISTS));
580 : 2 : ASSERT(SUCCESS == run_and_match_templates(cases,NULL,NULL));
581 : 2 : call(delete_path_if_present("tests/templates/0003_014.conf"));
582 : 2 : RETURN_STATUS;
583 : : }
584 : :
585 : : /**
586 : : * @brief Reject invalid regex values identically through CLI and configuration
587 : : *
588 : : * Each pattern is compiled during normal startup after argument parsing.
589 : : * Full output matching verifies the PCRE2 error and that no traversal starts
590 : : *
591 : : * @return Return status for ignore, include, and lock-checksum compilation errors
592 : : */
593 : 2 : static Return test0003_15(void)
594 : : {
595 : 2 : INITTEST;
596 : 2 : const struct argument_test_case cases[] = {
597 : : {"--ignore='(' tests/fixtures/diffs/diff1",FAILURE,"templates/0003_015_1.txt",STDERR_MUST_BE_EMPTY},
598 : : {"--config=0003_015_1.conf",FAILURE,"templates/0003_015_1.txt",STDERR_MUST_BE_EMPTY},
599 : : {"--include='(' tests/fixtures/diffs/diff1",FAILURE,"templates/0003_015_2.txt",STDERR_MUST_BE_EMPTY},
600 : : {"--config=0003_015_2.conf",FAILURE,"templates/0003_015_2.txt",STDERR_MUST_BE_EMPTY},
601 : : {"--lock-checksum='(' tests/fixtures/diffs/diff1",FAILURE,"templates/0003_015_3.txt",STDERR_MUST_BE_EMPTY},
602 : : {"--config=0003_015_3.conf",FAILURE,"templates/0003_015_3.txt",STDERR_MUST_BE_EMPTY},
603 : : {0}
604 : : };
605 : :
606 : 2 : ASSERT(SUCCESS == set_environment_variable("TESTING","true"));
607 : 2 : ASSERT(SUCCESS == copy_path("tests/templates/0003_015_1.conf","0003_015_1.conf"));
608 : 2 : ASSERT(SUCCESS == copy_path("tests/templates/0003_015_2.conf","0003_015_2.conf"));
609 : 2 : ASSERT(SUCCESS == copy_path("tests/templates/0003_015_3.conf","0003_015_3.conf"));
610 : 2 : ASSERT(SUCCESS == run_and_match_templates(cases,NULL,NULL));
611 : 2 : call(delete_path_if_present("0003_015_1.conf"));
612 : 2 : call(delete_path_if_present("0003_015_2.conf"));
613 : 2 : call(delete_path_if_present("0003_015_3.conf"));
614 : :
615 : 2 : RETURN_STATUS;
616 : : }
617 : :
618 : 2 : Return test0003(void)
619 : : {
620 : 2 : INITTEST;
621 : :
622 : 2 : TEST(test0003_1,"Comply default DB name to \"hostname.db\" template");
623 : 2 : TEST(test0003_2,"Running the application with no arguments at all");
624 : 2 : TEST(test0003_3,"Information modes without PATH return success");
625 : 2 : TEST(test0003_4,"Information modes ignore PATH and stop early");
626 : 2 : TEST(test0003_5,"Named roots match positional traversal");
627 : 2 : TEST(test0003_6,"Repeated and positional roots are combined without removing duplicates");
628 : 2 : TEST(test0003_7,"Missing or empty roots and missing compare operands are rejected");
629 : 2 : TEST(test0003_8,"Default configuration distinguishes empty files from incomplete settings");
630 : 2 : TEST(test0003_9,"Explicit configuration forms select only the last file");
631 : 2 : TEST(test0003_10,"Option-like values and config filenames with spaces are accepted");
632 : 2 : TEST(test0003_11,"Explicit configuration conflicts with other CLI arguments before reading");
633 : 2 : TEST(test0003_12,"Invalid CLI arguments and argp-marked -- are reported without reading configuration");
634 : 2 : TEST(test0003_13,"Configuration errors stop startup without fallback");
635 : 2 : TEST(test0003_14,"Verbose diagnostics identify the selected configuration file");
636 : 2 : TEST(test0003_15,"Invalid regex values produce the same CLI and configuration errors");
637 : :
638 : 2 : RETURN_STATUS;
639 : : }
|