1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.rat.test;
20
21 import java.io.FileWriter;
22 import java.nio.charset.StandardCharsets;
23 import java.nio.file.FileSystems;
24 import java.nio.file.Path;
25 import org.apache.commons.cli.Option;
26 import org.apache.commons.io.FileUtils;
27 import org.apache.commons.io.IOUtils;
28 import org.apache.commons.lang3.tuple.ImmutablePair;
29 import org.apache.commons.lang3.tuple.Pair;
30 import org.apache.commons.text.WordUtils;
31 import org.apache.rat.OptionCollectionTest;
32 import org.apache.rat.ReportConfiguration;
33 import org.apache.rat.ReporterTest;
34 import org.apache.rat.commandline.Arg;
35 import org.apache.rat.commandline.StyleSheets;
36 import org.apache.rat.config.exclusion.StandardCollection;
37 import org.apache.rat.document.DocumentNameMatcher;
38 import org.apache.rat.document.DocumentName;
39 import org.apache.rat.license.ILicense;
40 import org.apache.rat.license.ILicenseFamily;
41 import org.apache.rat.license.LicenseSetFactory;
42 import org.apache.rat.report.claim.ClaimStatistic;
43 import org.apache.rat.report.xml.writer.XmlWriter;
44 import org.apache.rat.test.utils.Resources;
45 import org.apache.rat.utils.DefaultLog;
46 import org.apache.rat.utils.Log.Level;
47
48 import java.io.BufferedReader;
49 import java.io.ByteArrayOutputStream;
50 import java.io.File;
51 import java.io.IOException;
52 import java.io.InputStream;
53 import java.io.InputStreamReader;
54 import java.io.OutputStream;
55 import java.io.PrintStream;
56 import java.nio.file.Files;
57 import java.util.Arrays;
58 import java.util.Collection;
59 import java.util.Collections;
60 import java.util.Locale;
61 import java.util.SortedSet;
62
63 import static org.apache.rat.commandline.Arg.HELP_LICENSES;
64 import static org.assertj.core.api.Assertions.assertThat;
65 import static org.assertj.core.api.Fail.fail;
66 import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
67
68
69
70
71
72
73
74 public abstract class AbstractConfigurationOptionsProvider extends AbstractOptionsProvider {
75
76
77
78
79
80
81 public static void preserveData(File baseDir, String targetDir) {
82 final Path recordPath = FileSystems.getDefault().getPath("target", targetDir);
83 org.apache.rat.utils.FileUtils.mkDir(recordPath.toFile());
84 try {
85 FileUtils.copyDirectory(baseDir, recordPath.toFile());
86 } catch (IOException e) {
87 System.err.format("Unable to copy data from %s to %s%n", baseDir, recordPath);
88 }
89 }
90
91
92
93
94
95
96 public static File setup(final File baseDir) {
97 try {
98 final File sourceDir = Resources.getResourceDirectory("OptionTools");
99 FileUtils.copyDirectory(sourceDir, new File(baseDir,"/src/test/resources/OptionTools"));
100 } catch (IOException e) {
101 DefaultLog.getInstance().error("Can not copy 'OptionTools' to " + baseDir, e);
102 }
103 return baseDir;
104 }
105
106
107
108
109
110
111
112 protected AbstractConfigurationOptionsProvider(final String providerName, final Collection<String> unsupportedArgs, final File baseDir) {
113 super(providerName, setup(baseDir));
114 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "addLicense", this::addLicenseTest));
115 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "config", this::configTest));
116 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "configuration-no-defaults", this::configurationNoDefaultsTest));
117 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "copyright", this::copyrightTest));
118 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "counter-min", this::counterMinTest));
119 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "counter-max", this::counterMaxTest));
120 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "dir", () -> DefaultLog.getInstance().info("--dir has no valid test")));
121 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "dry-run", this::dryRunTest));
122 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "edit-copyright", this::editCopyrightTest));
123 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "edit-license", this::editLicenseTest));
124 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "edit-overwrite", this::editOverwriteTest));
125 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "exclude", this::excludeTest));
126 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "exclude-file", this::excludeFileTest));
127 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "force", this::forceTest));
128 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "help-licenses", this::helpLicenses));
129 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "include", this::includeTest));
130 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "includes-file", this::includesFileTest));
131 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "input-exclude", this::inputExcludeTest));
132 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "input-exclude-file", this::inputExcludeFileTest));
133 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "input-exclude-parsed-scm", this::inputExcludeParsedScmTest));
134 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "input-exclude-std", this::inputExcludeStdTest));
135 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "input-exclude-size", this::inputExcludeSizeTest));
136 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "input-include", this::inputIncludeTest));
137 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "input-include-file", this::inputIncludeFileTest));
138 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "input-include-std", this::inputIncludeStdTest));
139 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "input-source", this::inputSourceTest));
140 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "license-families-approved", this::licenseFamiliesApprovedTest));
141 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "license-families-approved-file", this::licenseFamiliesApprovedFileTest));
142 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "license-families-denied", this::licenseFamiliesDeniedTest));
143 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "license-families-denied-file", this::licenseFamiliesDeniedFileTest));
144 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "licenses", this::licensesTest));
145 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "licenses-approved", this::licensesApprovedTest));
146 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "licenses-approved-file", this::licensesApprovedFileTest));
147 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "licenses-denied", this::licensesDeniedTest));
148 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "licenses-denied-file", this::licensesDeniedFileTest));
149 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "list-families", this::listFamiliesTest));
150 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "list-licenses", this::listLicensesTest));
151 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "log-level", this::logLevelTest));
152 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "no-default-licenses", this::noDefaultsTest));
153 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "out", this::outTest));
154 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "output-archive", this::outputArchiveTest));
155 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "output-families", this::outputFamiliesTest));
156 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "output-file", this::outputFileTest));
157 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "output-licenses", this::outputLicensesTest));
158 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "output-standard", this::outputStandardTest));
159 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "output-style", this::outputStyleTest));
160 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "scan-hidden-directories", this::scanHiddenDirectoriesTest));
161 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "stylesheet", this::styleSheetTest));
162 addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "xml", this::xmlTest));
163 super.validate(unsupportedArgs);
164 }
165
166
167 private void execExcludeTest(final Option option, final String[] args) {
168 String[] notExcluded = {"notbaz", "well._afile"};
169 String[] excluded = {"some.foo", "B.bar", "justbaz"};
170
171 assertDoesNotThrow(() -> {
172 ReportConfiguration config = generateConfig(ImmutablePair.of(option, args));
173 DocumentNameMatcher excluder = config.getDocumentExcluder(baseName());
174 for (String fname : notExcluded) {
175 DocumentName docName = mkDocName(fname);
176 assertThat(excluder.matches(docName)).as(() -> dump(option, fname, excluder, docName)).isTrue();
177 }
178 for (String fname : excluded) {
179 DocumentName docName = mkDocName(fname);
180 assertThat(excluder.matches(docName)).as(() -> dump(option, fname, excluder, docName)).isFalse();
181 }
182 });
183 }
184
185 private void excludeFileTest(final Option option) {
186 File outputFile = writeFile("exclude.txt", Arrays.asList(EXCLUDE_ARGS));
187 execExcludeTest(option, new String[]{outputFile.getAbsolutePath()});
188 }
189
190 protected void excludeFileTest() {
191 excludeFileTest(Arg.EXCLUDE_FILE.find("exclude-file"));
192 }
193
194 protected void inputExcludeFileTest() {
195 excludeFileTest(Arg.EXCLUDE_FILE.find("input-exclude-file"));
196 }
197
198 protected void excludeTest() {
199 execExcludeTest(Arg.EXCLUDE.find("exclude"), EXCLUDE_ARGS);
200 }
201
202 protected void inputExcludeTest() {
203 execExcludeTest(Arg.EXCLUDE.find("input-exclude"), EXCLUDE_ARGS);
204 }
205
206 protected void inputExcludeStdTest() {
207 Option option = Arg.EXCLUDE_STD.find("input-exclude-std");
208 String[] args = {StandardCollection.MISC.name()};
209 String[] excluded = {"afile~", ".#afile", "%afile%", "._afile"};
210 String[] notExcluded = {"afile~more", "what.#afile", "%afile%withMore", "well._afile"};
211
212 assertDoesNotThrow(() -> {
213 ReportConfiguration config = generateConfig(ImmutablePair.of(option, args));
214 DocumentNameMatcher excluder = config.getDocumentExcluder(baseName());
215 for (String fname : excluded) {
216 DocumentName docName = mkDocName(fname);
217 assertThat(excluder.matches(docName)).as(() -> dump(option, fname, excluder, docName)).isFalse();
218 }
219 for (String fname : notExcluded) {
220 DocumentName docName = mkDocName(fname);
221 assertThat(excluder.matches(docName)).as(() -> dump(option, fname, excluder, docName)).isTrue();
222 }
223 });
224 }
225
226 protected void inputExcludeParsedScmTest() {
227 Option option = Arg.EXCLUDE_PARSE_SCM.find("input-exclude-parsed-scm");
228 String[] args = {"GIT"};
229 String[] lines = {
230 "# somethings",
231 "!thingone", "thing*", System.lineSeparator(),
232 "# some fish",
233 "**/fish", "*_fish",
234 "# some colorful directories",
235 "red/", "blue/*/"};
236 String[] notExcluded = {"thingone", "dir/fish_two", "some/thingone", "blue/fish/dory" };
237 String[] excluded = {"thingtwo", "some/things", "dir/fish", "red/fish", "blue/fish", "some/fish", "another/red_fish"};
238
239 writeFile(".gitignore", Arrays.asList(lines));
240 File dir = new File(baseDir, "red");
241 org.apache.rat.utils.FileUtils.mkDir(dir);
242 dir = new File(baseDir, "blue");
243 dir = new File(dir, "fish");
244 org.apache.rat.utils.FileUtils.mkDir(dir);
245
246 assertDoesNotThrow(() -> {
247 ReportConfiguration config = generateConfig(ImmutablePair.of(option, args));
248 DocumentNameMatcher excluder = config.getDocumentExcluder(baseName());
249 for (String fname : excluded) {
250 DocumentName docName = mkDocName(fname);
251 assertThat(excluder.matches(docName)).as(() -> dump(option, fname, excluder, docName)).isFalse();
252 }
253 for (String fname : notExcluded) {
254 DocumentName docName = mkDocName(fname);
255 assertThat(excluder.matches(docName)).as(() -> dump(option, fname, excluder, docName)).isTrue();
256 }
257 });
258 }
259
260 private void inputExcludeSizeTest() {
261 Option option = Arg.EXCLUDE_SIZE.option();
262 String[] args = {"5"};
263 writeFile("Hi.txt", Collections.singletonList("Hi"));
264 writeFile("Hello.txt", Collections.singletonList("Hello"));
265 writeFile("HelloWorld.txt", Collections.singletonList("HelloWorld"));
266
267 String[] notExcluded = {"Hello.txt", "HelloWorld.txt"};
268 String[] excluded = {"Hi.txt"};
269
270 assertDoesNotThrow(() -> {
271 ReportConfiguration config = generateConfig(ImmutablePair.of(option, args));
272 DocumentNameMatcher excluder = config.getDocumentExcluder(baseName());
273 for (String fname : excluded) {
274 DocumentName docName = mkDocName(fname);
275 assertThat(excluder.matches(docName)).as(() -> dump(option, fname, excluder, docName)).isFalse();
276 }
277 for (String fname : notExcluded) {
278 DocumentName docName = mkDocName(fname);
279 assertThat(excluder.matches(docName)).as(() -> dump(option, fname, excluder, docName)).isTrue();
280 }
281 });
282 }
283
284
285 private void execIncludeTest(final Option option, final String[] args) {
286 Option excludeOption = Arg.EXCLUDE.option();
287 String[] notExcluded = {"B.bar", "justbaz", "notbaz"};
288 String[] excluded = {"some.foo"};
289
290 assertDoesNotThrow(() -> {
291 ReportConfiguration config = generateConfig(ImmutablePair.of(option, args),
292 ImmutablePair.of(excludeOption, EXCLUDE_ARGS));
293 DocumentNameMatcher excluder = config.getDocumentExcluder(baseName());
294 for (String fname : excluded) {
295 DocumentName docName = mkDocName(fname);
296 assertThat(excluder.matches(docName)).as(() -> dump(option, fname, excluder, docName)).isFalse();
297 }
298 for (String fname : notExcluded) {
299 DocumentName docName = mkDocName(fname);
300 assertThat(excluder.matches(docName)).as(() -> dump(option, fname, excluder, docName)).isTrue();
301 }
302 });
303 }
304
305 private void includeFileTest(final Option option) {
306 File outputFile = writeFile("include.txt", Arrays.asList(INCLUDE_ARGS));
307 execIncludeTest(option, new String[]{outputFile.getAbsolutePath()});
308 }
309
310 protected void inputIncludeFileTest() {
311 includeFileTest(Arg.INCLUDE_FILE.find("input-include-file"));
312 }
313
314 protected void includesFileTest() {
315 includeFileTest(Arg.INCLUDE_FILE.find("includes-file"));
316 }
317
318 protected void includeTest() {
319 execIncludeTest(Arg.INCLUDE.find("include"), INCLUDE_ARGS);
320 }
321
322 protected void inputIncludeTest() {
323 execIncludeTest(Arg.INCLUDE.find("input-include"), INCLUDE_ARGS);
324 }
325
326 protected void inputIncludeStdTest() {
327 ImmutablePair<Option, String[]> excludes = ImmutablePair.of(Arg.EXCLUDE.find("input-exclude"),
328 new String[]{"*~more", "*~"});
329 Option option = Arg.INCLUDE_STD.find("input-include-std");
330 String[] args = {StandardCollection.MISC.name()};
331 String[] excluded = {"afile~more"};
332 String[] notExcluded = {"afile~", ".#afile", "%afile%", "._afile", "what.#afile", "%afile%withMore", "well._afile"};
333
334 assertDoesNotThrow(() -> {
335 ReportConfiguration config = generateConfig(excludes, ImmutablePair.of(option, args));
336 DocumentNameMatcher excluder = config.getDocumentExcluder(baseName());
337 for (String fname : excluded) {
338 DocumentName docName = mkDocName(fname);
339 assertThat(excluder.matches(docName)).as(() -> dump(option, fname, excluder, docName)).isFalse();
340 }
341 for (String fname : notExcluded) {
342 DocumentName docName = mkDocName(fname);
343 assertThat(excluder.matches(docName)).as(() -> dump(option, fname, excluder, docName)).isTrue();
344 }
345 });
346 }
347
348 protected void inputSourceTest() {
349 Option option = Arg.SOURCE.find("input-source");
350 assertDoesNotThrow(() -> {
351 ReportConfiguration config = generateConfig(ImmutablePair.of(option, new String[]{baseDir.getAbsolutePath()}));
352 assertThat(config.hasSource()).isTrue();
353 });
354 }
355
356
357 protected void execLicensesApprovedTest(final Option option, String[] args) {
358 Pair<Option, String[]> arg1 = ImmutablePair.of(option, args);
359
360 assertDoesNotThrow(() -> {
361 ReportConfiguration config = generateConfig(arg1);
362 SortedSet<String> result = config.getLicenseIds(LicenseSetFactory.LicenseFilter.APPROVED);
363 assertThat(result).contains("one", "two");
364 });
365
366 Pair<Option, String[]> arg2 = ImmutablePair.of(
367 Arg.CONFIGURATION_NO_DEFAULTS.find("configuration-no-defaults"),
368 null
369 );
370
371 assertDoesNotThrow(() -> {
372 ReportConfiguration config = generateConfig(arg1, arg2);
373 SortedSet<String> result = config.getLicenseIds(LicenseSetFactory.LicenseFilter.APPROVED);
374 assertThat(result).containsExactly("one", "two");
375 });
376 }
377
378 protected void helpLicenses() {
379 ByteArrayOutputStream output = new ByteArrayOutputStream();
380 PrintStream origin = System.out;
381 try (PrintStream out = new PrintStream(output)) {
382 System.setOut(out);
383 generateConfig(ImmutablePair.of(HELP_LICENSES.option(), null));
384 } catch (IOException e) {
385 fail(e.getMessage());
386 } finally {
387 System.setOut(origin);
388 }
389 String txt = output.toString();
390 assertThat(txt).contains("====== Licenses ======", "====== Defined Matchers ======", "====== Defined Families ======");
391 }
392
393 protected void licensesApprovedFileTest() {
394 File outputFile = writeFile("licensesApproved.txt", Arrays.asList("one", "two"));
395 execLicensesApprovedTest(Arg.LICENSES_APPROVED_FILE.find("licenses-approved-file"),
396 new String[]{outputFile.getAbsolutePath()});
397 }
398
399 protected void licensesApprovedTest() {
400 execLicensesApprovedTest(Arg.LICENSES_APPROVED.find("licenses-approved"),
401 new String[]{"one, two"});
402 }
403
404 private void execLicensesDeniedTest(final Option option, final String[] args) {
405 assertDoesNotThrow(() -> {
406 ReportConfiguration config = generateConfig(ImmutablePair.of(option, args));
407 assertThat(config.getLicenseIds(LicenseSetFactory.LicenseFilter.ALL)).contains("ILLUMOS");
408 SortedSet<String> result = config.getLicenseIds(LicenseSetFactory.LicenseFilter.APPROVED);
409 assertThat(result).doesNotContain("ILLUMOS");
410 });
411 }
412
413 protected void licensesDeniedTest() {
414 execLicensesDeniedTest(Arg.LICENSES_DENIED.find("licenses-denied"), new String[]{"ILLUMOS"});
415 }
416
417 protected void licensesDeniedFileTest() {
418 File outputFile = writeFile("licensesDenied.txt", Collections.singletonList("ILLUMOS"));
419 execLicensesDeniedTest(Arg.LICENSES_DENIED_FILE.find("licenses-denied-file"),
420 new String[]{outputFile.getAbsolutePath()});
421 }
422
423 private void execLicenseFamiliesApprovedTest(final Option option, final String[] args) {
424 String catz = ILicenseFamily.makeCategory("catz");
425 Pair<Option, String[]> arg1 = ImmutablePair.of(option, args);
426
427 assertDoesNotThrow(() -> {
428 ReportConfiguration config = generateConfig(arg1);
429 SortedSet<String> result = config.getLicenseCategories(LicenseSetFactory.LicenseFilter.APPROVED);
430 assertThat(result).contains(catz);
431
432 Pair<Option, String[]> arg2 = ImmutablePair.of(Arg.CONFIGURATION_NO_DEFAULTS.find("configuration-no-defaults"), null);
433 config = generateConfig(arg1, arg2);
434 result = config.getLicenseCategories(LicenseSetFactory.LicenseFilter.APPROVED);
435 assertThat(result).containsExactly(catz);
436 });
437 }
438
439 protected void licenseFamiliesApprovedFileTest() {
440 File outputFile = writeFile("familiesApproved.txt", Collections.singletonList("catz"));
441 execLicenseFamiliesApprovedTest(Arg.FAMILIES_APPROVED_FILE.find("license-families-approved-file"),
442 new String[]{outputFile.getAbsolutePath()});
443 }
444
445 protected void licenseFamiliesApprovedTest() {
446 execLicenseFamiliesApprovedTest(Arg.FAMILIES_APPROVED.find("license-families-approved"),
447 new String[]{"catz"});
448 }
449
450 private void execLicenseFamiliesDeniedTest(final Option option, final String[] args) {
451 String gpl = ILicenseFamily.makeCategory("GPL");
452
453 assertDoesNotThrow(() -> {
454 ReportConfiguration config = generateConfig(ImmutablePair.of(option, args));
455 assertThat(config.getLicenseCategories(LicenseSetFactory.LicenseFilter.ALL)).contains(gpl);
456 SortedSet<String> result = config.getLicenseCategories(LicenseSetFactory.LicenseFilter.APPROVED);
457 assertThat(result).doesNotContain(gpl);
458 });
459 }
460
461 protected void licenseFamiliesDeniedFileTest() {
462 File outputFile = writeFile("familiesDenied.txt", Collections.singletonList("GPL"));
463 execLicenseFamiliesDeniedTest(Arg.FAMILIES_DENIED_FILE.find("license-families-denied-file"),
464 new String[]{outputFile.getAbsolutePath()});
465 }
466
467 protected void licenseFamiliesDeniedTest() {
468 execLicenseFamiliesDeniedTest(Arg.FAMILIES_DENIED.find("license-families-denied"),
469 new String[]{"GPL"});
470 }
471
472 protected void counterMaxTest() {
473 Option option = Arg.COUNTER_MAX.option();
474 String[] args = {null, null};
475
476 assertDoesNotThrow(() -> {
477 ReportConfiguration config = generateConfig(ImmutablePair.nullPair());
478 assertThat(config.getClaimValidator().getMax(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(0);
479 args[0] = "Unapproved:-1";
480 args[1] = "ignored:1";
481 config = generateConfig(ImmutablePair.of(option, args));
482 assertThat(config.getClaimValidator().getMax(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(Integer.MAX_VALUE);
483 assertThat(config.getClaimValidator().getMax(ClaimStatistic.Counter.IGNORED)).isEqualTo(1);
484 args[1] = "unapproved:5";
485 args[0] = "ignored:0";
486 config = generateConfig(ImmutablePair.of(option, args));
487 assertThat(config.getClaimValidator().getMax(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(5);
488 assertThat(config.getClaimValidator().getMax(ClaimStatistic.Counter.IGNORED)).isEqualTo(0);
489 });
490 }
491
492 protected void counterMinTest() {
493 Option option = Arg.COUNTER_MIN.option();
494 String[] args = {null, null};
495
496 assertDoesNotThrow(() -> {
497 ReportConfiguration config = generateConfig(ImmutablePair.nullPair());
498 assertThat(config.getClaimValidator().getMin(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(0);
499 args[0] = "Unapproved:1";
500 args[1] = "ignored:1";
501 config = generateConfig(ImmutablePair.of(option, args));
502 assertThat(config.getClaimValidator().getMin(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(1);
503 assertThat(config.getClaimValidator().getMin(ClaimStatistic.Counter.IGNORED)).isEqualTo(1);
504 args[1] = "unapproved:5";
505 args[0] = "ignored:0";
506 config = generateConfig(ImmutablePair.of(option, args));
507 assertThat(config.getClaimValidator().getMin(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(5);
508 assertThat(config.getClaimValidator().getMin(ClaimStatistic.Counter.IGNORED)).isEqualTo(0);
509 });
510 }
511
512 private String writeConfigXML(String name) {
513 String licenseText = """
514 Licensed to the Apache Software Foundation (ASF) under one or more
515 contributor license agreements. See the NOTICE file distributed with
516 this work for additional information regarding copyright ownership.
517 The ASF licenses this file to You under the Apache License, Version 2.0
518 (the "License"); you may not use this file except in compliance with
519 the License. You may obtain a copy of the License at
520
521 https:
522
523 Unless required by applicable law or agreed to in writing, software
524 distributed under the License is distributed on an "AS IS" BASIS,
525 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
526 See the License for the specific language governing permissions and
527 limitations under the License.""";
528 String capName = WordUtils.capitalize(name);
529 String upperName = name.toUpperCase(Locale.ROOT);
530
531 Path xmlPath = this.baseDir.toPath().resolve(".rat/" + capName + ".xml");
532 File f = xmlPath.toFile();
533 try {
534 FileUtils.forceMkdir(f.getParentFile());
535 try (FileWriter writer = new FileWriter(f);
536 XmlWriter xmlWriter = new XmlWriter(writer)) {
537
538 xmlWriter.startDocument()
539 .comment(licenseText)
540 .startElement("rat-config")
541 .startElement("families")
542 .startElement("family")
543 .attribute("id", upperName)
544 .attribute("name", "from " + capName + ".xml")
545 .closeElement("families")
546 .startElement("licenses")
547 .startElement("license")
548 .attribute("family", upperName)
549 .startElement("text")
550 .content(name)
551 .closeElement("rat-config");
552 }
553 } catch (IOException e) {
554 throw new RuntimeException(e);
555 }
556 return xmlPath.toString();
557 }
558
559 private void configTest(final Option option) {
560 String[] args = {writeConfigXML("one"), writeConfigXML("two")};
561 Pair<Option, String[]> arg1 = ImmutablePair.of(option, args);
562
563 assertDoesNotThrow(() -> {
564 ReportConfiguration config = generateConfig(arg1);
565 SortedSet<ILicense> set = config.getLicenses(LicenseSetFactory.LicenseFilter.ALL);
566 assertThat(set).hasSizeGreaterThan(2);
567 assertThat(LicenseSetFactory.search("ONE", "ONE", set)).isPresent();
568 assertThat(LicenseSetFactory.search("TWO", "TWO", set)).isPresent();
569
570 Pair<Option, String[]> arg2 = ImmutablePair.of(Arg.CONFIGURATION_NO_DEFAULTS.find("configuration-no-defaults"), null);
571
572 config = generateConfig(arg1, arg2);
573 set = config.getLicenses(LicenseSetFactory.LicenseFilter.ALL);
574 assertThat(set).hasSize(2);
575 assertThat(LicenseSetFactory.search("ONE", "ONE", set)).isPresent();
576 assertThat(LicenseSetFactory.search("TWO", "TWO", set)).isPresent();
577 });
578 }
579
580 protected void licensesTest() {
581 configTest(Arg.CONFIGURATION.find("licenses"));
582 }
583
584 protected void configTest() {
585 configTest(Arg.CONFIGURATION.find("config"));
586 }
587
588 private void noDefaultsTest(final Option arg) {
589 assertDoesNotThrow(() -> {
590 ReportConfiguration config = generateConfig(ImmutablePair.of(arg, null));
591 assertThat(config.getLicenses(LicenseSetFactory.LicenseFilter.ALL)).isEmpty();
592 config = generateConfig(ImmutablePair.nullPair());
593 assertThat(config.getLicenses(LicenseSetFactory.LicenseFilter.ALL)).isNotEmpty();
594 });
595 }
596
597 protected void noDefaultsTest() {
598 noDefaultsTest(Arg.CONFIGURATION_NO_DEFAULTS.find("no-default-licenses"));
599 }
600
601 protected void configurationNoDefaultsTest() {
602 noDefaultsTest(Arg.CONFIGURATION_NO_DEFAULTS.find("configuration-no-defaults"));
603 }
604
605 protected void dryRunTest() {
606 assertDoesNotThrow(() -> {
607 ReportConfiguration config = generateConfig(ImmutablePair.of(Arg.DRY_RUN.find("dry-run"), null));
608 assertThat(config.isDryRun()).isTrue();
609 config = generateConfig(ImmutablePair.nullPair());
610 assertThat(config.isDryRun()).isFalse();
611 });
612 }
613
614 private void editCopyrightTest(final Option option) {
615 assertDoesNotThrow(() -> {
616 Pair<Option, String[]> arg1 = ImmutablePair.of(option, new String[]{"MyCopyright"});
617 ReportConfiguration config;
618 try {
619 config = generateConfig(arg1);
620 assertThat(config.getCopyrightMessage()).as("Copyright without --edit-license should not work").isNull();
621 } catch (IOException e) {
622 if (e.getCause() != null) {
623 fail(e.getMessage() + ": " + e.getCause().getMessage());
624 }
625 throw e;
626 }
627
628 Pair<Option, String[]> arg2 = ImmutablePair.of(Arg.EDIT_ADD.find("edit-license"), null);
629 try {
630 config = generateConfig(arg1, arg2);
631 assertThat(config.getCopyrightMessage()).isEqualTo("MyCopyright");
632 } catch (IOException e) {
633 if (e.getCause() != null) {
634 fail(e.getMessage() + ": " + e.getCause().getMessage());
635 }
636 throw e;
637 }
638 });
639 }
640
641 protected void copyrightTest() {
642 editCopyrightTest(Arg.EDIT_COPYRIGHT.find("copyright"));
643 }
644
645 protected void editCopyrightTest() {
646 editCopyrightTest(Arg.EDIT_COPYRIGHT.find("edit-copyright"));
647 }
648
649 private void editLicenseTest(final Option option) {
650 assertDoesNotThrow(() -> {
651 ReportConfiguration config = generateConfig(ImmutablePair.of(option, null));
652 assertThat(config.isAddingLicenses()).isTrue();
653 config = generateConfig(ImmutablePair.nullPair());
654 assertThat(config.isAddingLicenses()).isFalse();
655 });
656 }
657
658 protected void addLicenseTest() {
659 editLicenseTest(Arg.EDIT_ADD.find("addLicense"));
660 }
661
662 protected void editLicenseTest() {
663 editLicenseTest(Arg.EDIT_ADD.find("edit-license"));
664 }
665
666 private void overwriteTest(final Option option) {
667 Pair<Option, String[]> arg1 = ImmutablePair.of(option, null);
668
669 assertDoesNotThrow(() -> {
670 ReportConfiguration config = generateConfig(arg1);
671 assertThat(config.isAddingLicensesForced()).isFalse();
672 Pair<Option, String[]> arg2 = ImmutablePair.of(Arg.EDIT_ADD.find("edit-license"), null);
673
674 config = generateConfig(arg1, arg2);
675 assertThat(config.isAddingLicensesForced()).isTrue();
676 });
677 }
678
679 protected void forceTest() {
680 overwriteTest(Arg.EDIT_OVERWRITE.find("force"));
681 }
682
683 protected void editOverwriteTest() {
684 overwriteTest(Arg.EDIT_OVERWRITE.find("edit-overwrite"));
685 }
686
687 protected void logLevelTest() {
688 Option option = Arg.LOG_LEVEL.find("log-level");
689 String[] args = {null};
690 Level logLevel = DefaultLog.getInstance().getLevel();
691 try {
692 for (Level level : Level.values()) {
693 try {
694 args[0] = level.name();
695 generateConfig(ImmutablePair.of(option, args));
696 assertThat(DefaultLog.getInstance().getLevel()).isEqualTo(level);
697 } catch (IOException e) {
698 fail(e.getMessage());
699 }
700 }
701 } finally {
702 DefaultLog.getInstance().setLevel(logLevel);
703 }
704 }
705
706 private void archiveTest(final Option option) {
707 String[] args = {null};
708
709 assertDoesNotThrow(() -> {
710 for (ReportConfiguration.Processing proc : ReportConfiguration.Processing.values()) {
711 args[0] = proc.name();
712 ReportConfiguration config = generateConfig(ImmutablePair.of(option, args));
713 assertThat(config.getArchiveProcessing()).isEqualTo(proc);
714 }
715 });
716 }
717
718 protected void outputArchiveTest() {
719 archiveTest(Arg.OUTPUT_ARCHIVE.find("output-archive"));
720 }
721
722 private void listFamilies(final Option option) {
723 String[] args = {null};
724
725 assertDoesNotThrow(() -> {
726 for (LicenseSetFactory.LicenseFilter filter : LicenseSetFactory.LicenseFilter.values()) {
727 args[0] = filter.name();
728 ReportConfiguration config = generateConfig(ImmutablePair.of(option, args));
729 assertThat(config.listFamilies()).isEqualTo(filter);
730 }
731 });
732 }
733
734 protected void listFamiliesTest() {
735 listFamilies(Arg.OUTPUT_FAMILIES.find("list-families"));
736 }
737
738 protected void outputFamiliesTest() {
739 listFamilies(Arg.OUTPUT_FAMILIES.find("output-families"));
740 }
741
742 private void outTest(final Option option) {
743 File outFile = new File(baseDir, "outexample-" + option.getLongOpt());
744 String[] args = new String[]{outFile.getAbsolutePath()};
745
746 assertDoesNotThrow(() -> {
747 ReportConfiguration config = generateConfig(ImmutablePair.of(option, args));
748 try (OutputStream os = config.getOutput().get()) {
749 os.write("Hello world".getBytes());
750 } catch (IOException e) {
751 throw new RuntimeException(e);
752 }
753 try (BufferedReader reader = new BufferedReader(new InputStreamReader(Files.newInputStream(outFile.toPath())))) {
754 assertThat(reader.readLine()).isEqualTo("Hello world");
755 } catch (IOException e) {
756 throw new RuntimeException(e);
757 }
758 });
759 }
760
761 protected void outTest() {
762 outTest(Arg.OUTPUT_FILE.find("out"));
763 }
764
765 protected void outputFileTest() {
766 outTest(Arg.OUTPUT_FILE.find("output-file"));
767 }
768
769 private void listLicenses(final Option option) {
770 String[] args = {null};
771
772 assertDoesNotThrow(() -> {
773 for (LicenseSetFactory.LicenseFilter filter : LicenseSetFactory.LicenseFilter.values()) {
774 args[0] = filter.name();
775 ReportConfiguration config = generateConfig(ImmutablePair.of(option, args));
776 assertThat(config.listLicenses()).isEqualTo(filter);
777 }
778 });
779 }
780
781 protected void listLicensesTest() {
782 listLicenses(Arg.OUTPUT_LICENSES.find("list-licenses"));
783 }
784
785 protected void outputLicensesTest() {
786 listLicenses(Arg.OUTPUT_LICENSES.find("output-licenses"));
787 }
788
789 private void standardTest(final Option option) {
790 String[] args = {null};
791 assertDoesNotThrow(() -> {
792 for (ReportConfiguration.Processing proc : ReportConfiguration.Processing.values()) {
793 args[0] = proc.name();
794 ReportConfiguration config = generateConfig(ImmutablePair.of(option, args));
795 assertThat(config.getStandardProcessing()).isEqualTo(proc);
796 }
797 });
798 }
799
800 protected void outputStandardTest() {
801 standardTest(Arg.OUTPUT_STANDARD.find("output-standard"));
802 }
803
804 private void styleSheetTest(final Option option) {
805
806 File file = new File(baseDir, "stylesheet-" + option.getLongOpt());
807 DocumentName xsltFile = DocumentName.builder(file).build();
808 try (
809 InputStream in = ReporterTest.class.getResourceAsStream("MatcherContainerResource.txt");
810 OutputStream out = Files.newOutputStream(file.toPath())) {
811 if (in == null) {
812 fail("Could not copy MatcherContainerResource.txt: resource not found");
813 } else {
814 IOUtils.copy(in, out);
815 }
816 } catch (IOException e) {
817 fail("Could not copy MatcherContainerResource.txt: " + e.getMessage());
818 }
819
820
821 String[] args = {null};
822 assertDoesNotThrow(() -> {
823 for (String sheet : new String[]{"plain-rat", "missing-headers", "unapproved-licenses", xsltFile.getName()}) {
824 args[0] = sheet;
825 ReportConfiguration config = generateConfig(ImmutablePair.of(option, args));
826 try (InputStream expected = StyleSheets.getStyleSheet(sheet, xsltFile.getBaseDocumentName()).ioSupplier().get();
827 InputStream actual = config.getStyleSheet().get()) {
828 String expectedStr = IOUtils.toString(expected, StandardCharsets.UTF_8);
829 String actualStr = IOUtils.toString(actual, StandardCharsets.UTF_8);
830 assertThat(actualStr).as(
831 () -> String.format("'%s' is not correct: %s != %s",
832 config.getStyleSheetDescriptor().name(),
833 actualStr, expectedStr))
834 .isEqualTo(expectedStr);
835 }
836 }
837 });
838 }
839
840 protected void styleSheetTest() {
841 styleSheetTest(Arg.OUTPUT_STYLE.find("stylesheet"));
842 }
843
844 protected void outputStyleTest() {
845 styleSheetTest(Arg.OUTPUT_STYLE.find("output-style"));
846 }
847
848 protected void scanHiddenDirectoriesTest() {
849 assertDoesNotThrow(() -> {
850 ReportConfiguration config = generateConfig(ImmutablePair.of(Arg.INCLUDE_STD.find("scan-hidden-directories"), null));
851 DocumentNameMatcher excluder = config.getDocumentExcluder(baseName());
852 assertThat(excluder.matches(mkDocName(".file"))).as(".file").isTrue();
853 });
854 }
855
856 protected void xmlTest() {
857 assertDoesNotThrow(() -> {
858 ReportConfiguration config = generateConfig(ImmutablePair.of(Arg.OUTPUT_STYLE.find("xml"), null));
859 try (InputStream expected = StyleSheets.getStyleSheet("xml", null).ioSupplier().get();
860 InputStream actual = config.getStyleSheet().get()) {
861 assertThat(IOUtils.contentEquals(expected, actual)).as("'xml' does not match").isTrue();
862 }
863 });
864 }
865 }