1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.rat.testhelpers.data;
20
21 import java.io.ByteArrayOutputStream;
22 import java.io.File;
23 import java.io.FileReader;
24 import java.io.FileWriter;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.io.OutputStream;
28 import java.io.PrintStream;
29 import java.nio.charset.StandardCharsets;
30 import java.nio.file.Files;
31 import java.nio.file.Path;
32 import java.util.Arrays;
33 import java.util.Collections;
34 import java.util.List;
35 import java.util.Locale;
36 import java.util.Objects;
37 import java.util.Set;
38 import java.util.function.Consumer;
39 import java.util.function.Supplier;
40 import javax.xml.xpath.XPath;
41 import javax.xml.xpath.XPathExpressionException;
42 import javax.xml.xpath.XPathFactory;
43 import org.apache.commons.cli.Option;
44 import org.apache.commons.io.IOUtils;
45 import org.apache.commons.lang3.tuple.ImmutablePair;
46 import org.apache.rat.ReportConfiguration;
47 import org.apache.rat.api.RatException;
48 import org.apache.rat.commandline.Arg;
49 import org.apache.rat.commandline.StyleSheets;
50 import org.apache.rat.config.exclusion.StandardCollection;
51 import org.apache.rat.config.results.ClaimValidator;
52 import org.apache.rat.document.DocumentName;
53 import org.apache.rat.license.LicenseSetFactory;
54 import org.apache.rat.report.claim.ClaimStatistic;
55 import org.apache.rat.report.xml.writer.XmlWriter;
56 import org.apache.rat.utils.FileUtils;
57 import org.apache.rat.testhelpers.TestingLog;
58 import org.apache.rat.testhelpers.TextUtils;
59 import org.apache.rat.testhelpers.XmlUtils;
60 import org.apache.rat.utils.DefaultLog;
61 import org.apache.rat.utils.Log;
62 import org.w3c.dom.Document;
63
64 import static org.apache.rat.utils.FileUtils.writeFile;
65 import static org.apache.rat.testhelpers.data.DataUtils.NO_SETUP;
66 import static org.assertj.core.api.Assertions.assertThat;
67 import static org.assertj.core.api.Fail.fail;
68 import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
69
70
71
72
73
74
75
76
77
78
79
80 public class ReportTestDataProvider extends AbstractTestDataProvider {
81
82 public static final RatException NO_LICENSES_EXCEPTION = new RatException("At least one license must be defined");
83
84 private final XPath xpath = XPathFactory.newInstance().newXPath();
85
86
87
88
89 private final Consumer<Path> mkRat = basePath -> {
90 DefaultLog.getInstance().warn("mkRat setup for " + basePath);
91 File baseDir = basePath.toFile();
92 File ratDir = new File(baseDir, ".rat");
93 FileUtils.mkDir(ratDir);
94 };
95
96
97
98
99
100
101 private void assertStandardFile(Document document, String fname) {
102 try {
103 XmlUtils.assertIsPresent(document, xpath,
104 String.format("/rat-report/resource[@name='/%s'][@type='STANDARD']", fname));
105 } catch (XPathExpressionException e) {
106 throw new RuntimeException(e);
107 }
108 }
109
110
111
112
113
114
115 private void assertIgnoredFile(Document document, String fname) {
116 try {
117 XmlUtils.assertIsPresent(document, xpath,
118 String.format("/rat-report/resource[@name='/%s'][@type='IGNORED']", fname));
119 } catch (XPathExpressionException e) {
120 throw new RuntimeException(e);
121 }
122 }
123
124
125
126
127
128
129
130 private void assertCounter(ValidatorData data, ClaimStatistic.Counter counter, int count) {
131 assertThat(data.getStatistic().getCounter(counter)).as(counter.name()).isEqualTo(count);
132 }
133
134
135 private List<TestData> execExcludeTest(final Option option, final Supplier<String[]> args, Consumer<Path> setupFiles) {
136 Consumer<Path> setup = setupFiles.andThen(mkRat).andThen(basePath -> {
137 DefaultLog.getInstance().warn("execExcludeTest setup for " + basePath);
138 File baseDir = basePath.toFile();
139 writeFile(baseDir, "notbaz");
140 writeFile(baseDir, "well._afile");
141 writeFile(baseDir, "some.foo");
142 writeFile(baseDir, "B.bar");
143 writeFile(baseDir, "justbaz");
144 });
145
146 TestData test1 = new TestData(DataUtils.asDirName(option), NO_OPTIONS,
147 setup,
148 validatorData -> {
149 DefaultLog.getInstance().warn("validating execExcludeTest for " + validatorData.getBaseDir());
150 assertCounter(validatorData, ClaimStatistic.Counter.STANDARDS, 5);
151 assertCounter(validatorData, ClaimStatistic.Counter.IGNORED, 1);
152 });
153
154 String[] ignored = {"B.bar", "justbaz", "some.foo", ".rat"};
155 String[] standard = {"well._afile", "notbaz"};
156 TestData test2 = new TestData("", Collections.singletonList(ImmutablePair.of(option, args.get())),
157 setup,
158 validatorData -> {
159 DefaultLog.getInstance().warn("validating execExcludeTest for " + validatorData.getBaseDir());
160 assertCounter(validatorData, ClaimStatistic.Counter.STANDARDS, standard.length);
161 assertCounter(validatorData, ClaimStatistic.Counter.IGNORED, ignored.length);
162 for (String fileName : ignored) {
163 assertIgnoredFile(validatorData.getDocument(), fileName);
164 }
165 for (String fileName : standard) {
166 assertStandardFile(validatorData.getDocument(), fileName);
167 }
168 });
169 return Arrays.asList(test1, test2);
170 }
171
172 @Override
173 protected void inputExcludeFileTest(final Set<TestData> result, final Option option) {
174 Consumer<Path> setup = mkRat.andThen(baseDir -> {
175 File dir = baseDir.resolve(".rat").toFile();
176 writeFile(dir, "exclude.txt", Arrays.asList(AbstractTestDataProvider.EXCLUDE_ARGS));
177 });
178 Supplier<String[]> args = () -> new String[]{".rat/exclude.txt"};
179 result.addAll(execExcludeTest(option, args, setup));
180 }
181
182 @Override
183 protected void inputExcludeTest(final Set<TestData> result, final Option option) {
184 result.addAll(execExcludeTest(option, () -> AbstractTestDataProvider.EXCLUDE_ARGS, x -> {
185 }));
186 }
187
188 @Override
189 protected void inputExcludeStdTest(final Set<TestData> result, final Option option) {
190 String[] args = {StandardCollection.MAVEN.name()};
191 String[] defaultExcluded = {"afile~", ".#afile", "%afile%", "._afile"};
192 String[] defaultIncluded = {"afile~more", "what.#afile", "%afile%withMore", "well._afile"};
193 String mavenFile = "build.log";
194 Consumer<Path> setup = basePath -> {
195 DefaultLog.getInstance().warn("inputExcludeStdTest setup for " + basePath);
196 File baseDir = basePath.toFile();
197 for (String fileName : defaultExcluded) {
198 writeFile(baseDir, fileName);
199 }
200 for (String fileName : defaultIncluded) {
201 writeFile(baseDir, fileName);
202 }
203 writeFile(baseDir, mavenFile);
204 };
205 result.add(new TestData(DataUtils.asDirName(option), Collections.singletonList(ImmutablePair.nullPair()),
206 setup,
207 validatorData -> {
208 DefaultLog.getInstance().warn("validating inputExcludeStdTest for " + validatorData.getBaseDir());
209 assertCounter(validatorData, ClaimStatistic.Counter.STANDARDS, defaultIncluded.length + 1);
210 assertCounter(validatorData, ClaimStatistic.Counter.IGNORED, defaultExcluded.length);
211 for (String fileName : defaultIncluded) {
212 assertStandardFile(validatorData.getDocument(), fileName);
213 }
214 for (String fileName : defaultExcluded) {
215 assertIgnoredFile(validatorData.getDocument(), fileName);
216 }
217 }));
218
219 result.add(new TestData("", Collections.singletonList(ImmutablePair.of(option, args)),
220 setup,
221 validatorData -> {
222 DefaultLog.getInstance().warn("validating inputExcludeStdTest for " + validatorData.getBaseDir());
223 assertCounter(validatorData, ClaimStatistic.Counter.STANDARDS, defaultIncluded.length);
224 assertCounter(validatorData, ClaimStatistic.Counter.IGNORED, defaultExcluded.length + 1);
225 for (String fileName : defaultIncluded) {
226 assertStandardFile(validatorData.getDocument(), fileName);
227 }
228 for (String fileName : defaultExcluded) {
229 assertIgnoredFile(validatorData.getDocument(), fileName);
230 }
231 assertIgnoredFile(validatorData.getDocument(), mavenFile);
232 }));
233 }
234
235 @Override
236 protected void inputExcludeParsedScmTest(final Set<TestData> result, final Option option) {
237 Consumer<Path> setup = basePath -> {
238 DefaultLog.getInstance().warn("inputExcludeParsedScmTest setup for " + basePath);
239 File baseDir = basePath.toFile();
240 String[] lines = {
241 "# somethings",
242 "!thingone", "thing*", System.lineSeparator(),
243 "# some fish",
244 "**/fish", "*_fish",
245 "# some colorful directories",
246 "red/", "blue/*/"};
247 writeFile(baseDir, ".gitignore", Arrays.asList(lines));
248 writeFile(baseDir, "thingone");
249 writeFile(baseDir, "thingtwo");
250 File dir = new File(baseDir, "dir");
251 FileUtils.mkDir(dir);
252 FileUtils.writeFile(dir, "fish_two");
253 FileUtils.writeFile(dir, "fish");
254
255 dir = new File(baseDir, "red");
256 FileUtils.mkDir(dir);
257 FileUtils.writeFile(dir, "fish");
258
259 dir = new File(baseDir, "blue/fish");
260 FileUtils.mkDir(dir);
261 FileUtils.writeFile(dir, "dory");
262
263 dir = new File(baseDir, "some");
264 FileUtils.mkDir(dir);
265 FileUtils.writeFile(dir, "fish");
266 FileUtils.writeFile(dir, "things");
267 FileUtils.writeFile(dir, "thingone");
268
269 dir = new File(baseDir, "another");
270 FileUtils.mkDir(dir);
271 FileUtils.writeFile(dir, "red_fish");
272 };
273
274 result.add(new TestData(DataUtils.asDirName(option), Collections.singletonList(ImmutablePair.nullPair()),
275 setup,
276 validatorData -> {
277 DefaultLog.getInstance().warn("validating inputExcludeParsedScmTest for " + validatorData.getBaseDir());
278 assertCounter(validatorData, ClaimStatistic.Counter.STANDARDS, 11);
279
280 assertCounter(validatorData, ClaimStatistic.Counter.IGNORED, 0);
281 }));
282
283 result.add(new TestData("GIT", Collections.singletonList(ImmutablePair.of(option, new String[]{"GIT"})),
284 setup,
285 validatorData -> {
286 DefaultLog.getInstance().warn("validating inputExcludeParsedScmTest for " + validatorData.getBaseDir());
287 assertCounter(validatorData, ClaimStatistic.Counter.STANDARDS, 3);
288
289 assertCounter(validatorData, ClaimStatistic.Counter.IGNORED, 8);
290 }));
291 }
292
293 @Override
294 protected void inputExcludeSizeTest(final Set<TestData> result, final Option option) {
295 String[] notExcluded = {"Hello.txt", "HelloWorld.txt"};
296 String[] excluded = {"Hi.txt"};
297
298 Consumer<Path> setup = basePath -> {
299 DefaultLog.getInstance().warn("inputExcludeSizeTest setup for " + basePath);
300 File baseDir = basePath.toFile();
301 writeFile(baseDir, "Hi.txt", Collections.singletonList("Hi"));
302 writeFile(baseDir, "Hello.txt", Collections.singletonList("Hello"));
303 writeFile(baseDir, "HelloWorld.txt", Collections.singletonList("HelloWorld"));
304 };
305
306 result.add(new TestData(DataUtils.asDirName(option), Collections.singletonList(ImmutablePair.of(null, null)),
307 setup,
308 validatorData -> {
309 DefaultLog.getInstance().warn("validating inputExcludeSizeTest for " + validatorData.getBaseDir());
310 assertCounter(validatorData, ClaimStatistic.Counter.STANDARDS, 3);
311 assertCounter(validatorData, ClaimStatistic.Counter.IGNORED, 0);
312 for (String fname : excluded) {
313 assertStandardFile(validatorData.getDocument(), fname);
314 }
315 for (String fname : notExcluded) {
316 assertStandardFile(validatorData.getDocument(), fname);
317 }
318 }));
319
320 result.add(new TestData("", Collections.singletonList(ImmutablePair.of(option, new String[]{"5"})),
321 setup,
322 validatorData -> {
323 DefaultLog.getInstance().warn("validating inputExcludeSizeTest for " + validatorData.getBaseDir());
324 assertCounter(validatorData, ClaimStatistic.Counter.STANDARDS, 2);
325 assertCounter(validatorData, ClaimStatistic.Counter.IGNORED, 1);
326 for (String fname : excluded) {
327 assertIgnoredFile(validatorData.getDocument(), fname);
328 }
329 for (String fname : notExcluded) {
330 assertStandardFile(validatorData.getDocument(), fname);
331 }
332 }));
333 }
334
335
336 private List<TestData> execIncludeTest(final Option option, String[] args, Consumer<Path> setupFiles) {
337 Option excludeOption = Arg.EXCLUDE.option();
338 Consumer<Path> setup = setupFiles.andThen(basePath -> {
339 DefaultLog.getInstance().warn("execIncludeTest setup for " + basePath);
340 File baseDir = basePath.toFile();
341 writeFile(baseDir, "notbaz");
342 writeFile(baseDir, "some.foo");
343 writeFile(baseDir, "B.bar");
344 writeFile(baseDir, "justbaz");
345 });
346
347
348 TestData test1 = new TestData(DataUtils.asDirName(option), NO_OPTIONS,
349 setup,
350 validatorData -> {
351 DefaultLog.getInstance().warn("validating execIncludeTest for " + validatorData.getBaseDir());
352 assertCounter(validatorData, ClaimStatistic.Counter.STANDARDS, 4);
353 assertCounter(validatorData, ClaimStatistic.Counter.IGNORED, 1);
354 });
355
356
357 TestData test2 = new TestData(DataUtils.asDirName(option), Collections.singletonList(ImmutablePair.of(excludeOption, AbstractTestDataProvider.EXCLUDE_ARGS)),
358 setup,
359 validatorData -> {
360 DefaultLog.getInstance().warn("validating execIncludeTest for " + validatorData.getBaseDir());
361 assertCounter(validatorData, ClaimStatistic.Counter.STANDARDS, 1);
362
363 assertCounter(validatorData, ClaimStatistic.Counter.IGNORED, 4);
364 });
365
366 TestData test3 = new TestData("", Arrays.asList(ImmutablePair.of(option, args), ImmutablePair.of(excludeOption, AbstractTestDataProvider.EXCLUDE_ARGS)),
367 setup,
368 validatorData -> {
369 DefaultLog.getInstance().warn("validating execIncludeTest for " + validatorData.getBaseDir());
370 assertCounter(validatorData, ClaimStatistic.Counter.STANDARDS, 3);
371
372 assertCounter(validatorData, ClaimStatistic.Counter.IGNORED, 2);
373 });
374 return Arrays.asList(test1, test2, test3);
375 }
376
377 @Override
378 protected void inputIncludeFileTest(final Set<TestData> result, final Option option) {
379 Consumer<Path> setup = mkRat.andThen(basePath -> {
380 DefaultLog.getInstance().warn("inputIncludeFileTest setup for " + basePath);
381 File dir = basePath.resolve(".rat").toFile();
382 writeFile(dir, "include.txt", Arrays.asList(AbstractTestDataProvider.INCLUDE_ARGS));
383 });
384 result.addAll(execIncludeTest(option, new String[]{".rat/include.txt"}, setup));
385 }
386
387 @Override
388 protected void inputIncludeTest(final Set<TestData> result, final Option option) {
389 result.addAll(execIncludeTest(option, AbstractTestDataProvider.INCLUDE_ARGS, mkRat));
390 }
391
392 @Override
393 protected void inputIncludeStdTest(final Set<TestData> result, final Option option) {
394 Consumer<Path> setup = basePath -> {
395 DefaultLog.getInstance().warn("inputIncludeStdTest setup for " + basePath);
396 File baseDir = basePath.toFile();
397 writeFile(baseDir, "afile~more");
398 writeFile(baseDir, "afile~");
399 writeFile(baseDir, ".#afile");
400 writeFile(baseDir, "%afile%");
401 writeFile(baseDir, "._afile");
402 writeFile(baseDir, "what.#afile");
403 writeFile(baseDir, "%afile%withMore");
404 writeFile(baseDir, "well._afile");
405 writeFile(baseDir, ".hiddenFile", "The hidden file");
406 File hiddenDir = new File(baseDir, ".hiddenDir");
407 FileUtils.mkDir(hiddenDir);
408 writeFile(hiddenDir, "aFile", "File in hidden directory");
409 };
410 if (Arg.EXCLUDE.isEmpty()) {
411 throw new RuntimeException(String.format("Can not test %s if there are no exclude file options supported", option.getKey()));
412 }
413 ImmutablePair<Option, String[]> excludes = ImmutablePair.of(Arg.EXCLUDE.option(),
414 new String[]{"*~more", "*~"});
415
416
417 result.add(new TestData("includeStdValidation", Collections.singletonList(excludes),
418 setup,
419 validatorData -> {
420 DefaultLog.getInstance().warn("validating inputIncludeStdTest for " + validatorData.getBaseDir());
421 assertCounter(validatorData, ClaimStatistic.Counter.STANDARDS, 4);
422 assertCounter(validatorData, ClaimStatistic.Counter.IGNORED, 6);
423 }));
424
425 if (!option.hasArg()) {
426 if (option.getKey().equals("scan-hidden-directories")) {
427 result.add(new TestData("",
428 Arrays.asList(ImmutablePair.of(option, null), excludes),
429 setup,
430 validatorData -> {
431 DefaultLog.getInstance().warn("validating inputIncludeStdTest for " + validatorData.getBaseDir());
432 assertCounter(validatorData, ClaimStatistic.Counter.STANDARDS, 5);
433 assertCounter(validatorData, ClaimStatistic.Counter.IGNORED, 5);
434 assertIgnoredFile(validatorData.getDocument(), "._afile");
435 assertStandardFile(validatorData.getDocument(), ".hiddenDir/aFile");
436 }));
437 } else {
438 throw new RuntimeException("Unknown option: " + option.getKey());
439 }
440 } else {
441 result.add(new TestData(StandardCollection.MISC.name().toLowerCase(Locale.ROOT), Arrays.asList(ImmutablePair.of(option, new String[]{StandardCollection.MISC.name()}), excludes),
442 setup,
443 validatorData -> {
444 DefaultLog.getInstance().warn("validating inputIncludeStdTest for " + validatorData.getBaseDir());
445 assertCounter(validatorData, ClaimStatistic.Counter.STANDARDS, 8);
446 assertCounter(validatorData, ClaimStatistic.Counter.IGNORED, 2);
447 }));
448
449 result.add(new TestData(StandardCollection.HIDDEN_FILE.name().toLowerCase(Locale.ROOT),
450 Arrays.asList(ImmutablePair.of(option, new String[]{StandardCollection.HIDDEN_FILE.name()}), excludes),
451 setup,
452 validatorData -> {
453 DefaultLog.getInstance().warn("validating inputIncludeStdTest for " + validatorData.getBaseDir());
454 assertCounter(validatorData, ClaimStatistic.Counter.STANDARDS, 6);
455 assertCounter(validatorData, ClaimStatistic.Counter.IGNORED, 4);
456 assertStandardFile(validatorData.getDocument(), "._afile");
457 assertIgnoredFile(validatorData.getDocument(), ".hiddenDir");
458 }));
459
460 result.add(new TestData(StandardCollection.HIDDEN_DIR.name().toLowerCase(Locale.ROOT),
461 Arrays.asList(ImmutablePair.of(option, new String[]{StandardCollection.HIDDEN_DIR.name()}), excludes),
462 setup,
463 validatorData -> {
464 DefaultLog.getInstance().warn("validating inputIncludeStdTest for " + validatorData.getBaseDir());
465 assertCounter(validatorData, ClaimStatistic.Counter.STANDARDS, 5);
466 assertCounter(validatorData, ClaimStatistic.Counter.IGNORED, 5);
467 assertIgnoredFile(validatorData.getDocument(), "._afile");
468 assertStandardFile(validatorData.getDocument(), ".hiddenDir/aFile");
469 }));
470 }
471 }
472
473 @Override
474 protected void inputSourceTest(final Set<TestData> result, final Option option) {
475 Consumer<Path> setup = basePath -> {
476 DefaultLog.getInstance().warn("inputSourceTest setup for " + basePath);
477 File baseDir = basePath.toFile();
478 writeFile(baseDir, "codefile", "https://www.apache.org/licenses/LICENSE-2.0");
479 writeFile(baseDir, "input.txt", "codefile");
480 writeFile(baseDir, "notcodeFile");
481 };
482
483 result.add(new TestData(DataUtils.asDirName(option), NO_OPTIONS,
484 setup,
485 validatorData -> {
486 DefaultLog.getInstance().warn("validating inputSourceTest for " + validatorData.getBaseDir());
487 assertCounter(validatorData, ClaimStatistic.Counter.STANDARDS, 3);
488 assertCounter(validatorData, ClaimStatistic.Counter.IGNORED, 0);
489 }));
490
491 result.add(new TestData("", Collections.singletonList(ImmutablePair.of(option, new String[]{"input.txt"})),
492 setup,
493 validatorData -> {
494 DefaultLog.getInstance().warn("validating inputSourceTest for " + validatorData.getBaseDir());
495 assertCounter(validatorData, ClaimStatistic.Counter.STANDARDS, 1);
496 assertCounter(validatorData, ClaimStatistic.Counter.IGNORED, 0);
497 }));
498 }
499
500
501 protected List<TestData> execLicensesApprovedTest(final Option option, String[] args, Consumer<Path> extraSetup) {
502 Consumer<Path> setup = extraSetup.andThen(
503 basePath -> {
504 DefaultLog.getInstance().warn("execLicensesApprovedTest setup for " + basePath);
505 File baseDir = basePath.toFile();
506 writeFile(baseDir, "catz.txt", "SPDX-License-Identifier: catz");
507 writeFile(baseDir, "apl.txt", "SPDX-License-Identifier: Apache-2.0");
508 }
509 );
510
511 TestData test1 = new TestData(DataUtils.asDirName(option), NO_OPTIONS,
512 setup,
513 validatorData -> {
514 DefaultLog.getInstance().warn("validating execLicensesApprovedTest for " + validatorData.getBaseDir());
515 assertCounter(validatorData, ClaimStatistic.Counter.STANDARDS, 2);
516 assertCounter(validatorData, ClaimStatistic.Counter.APPROVED, 1);
517 assertCounter(validatorData, ClaimStatistic.Counter.UNAPPROVED, 1);
518 });
519
520 TestData test2 = new TestData("withoutLicenseDef", Collections.singletonList(ImmutablePair.of(option, args)),
521 setup,
522 validatorData -> {
523 DefaultLog.getInstance().warn("validating execLicensesApprovedTest for " + validatorData.getBaseDir());
524 assertCounter(validatorData, ClaimStatistic.Counter.STANDARDS, 2);
525 assertCounter(validatorData, ClaimStatistic.Counter.APPROVED, 1);
526 assertCounter(validatorData, ClaimStatistic.Counter.UNAPPROVED, 1);
527 });
528
529 Option configOpt = Arg.CONFIGURATION.option();
530 TestData test3 = new TestData("withLicenseDef", Arrays.asList(ImmutablePair.of(option, args),
531 ImmutablePair.of(configOpt, new String[]{".rat/catz.xml"})),
532 setup.andThen(mkRat).andThen(
533 basePath -> {
534 DefaultLog.getInstance().warn("withLicenseDef setup for " + basePath);
535 DataUtils.generateSpdxConfig(basePath.resolve(".rat").resolve("catz.xml"), "catz", "catz");
536 }),
537 validatorData -> {
538 DefaultLog.getInstance().warn("validating execLicensesApprovedTest for " + validatorData.getBaseDir());
539 assertCounter(validatorData, ClaimStatistic.Counter.STANDARDS, 2);
540 assertCounter(validatorData, ClaimStatistic.Counter.APPROVED, 2);
541 assertCounter(validatorData, ClaimStatistic.Counter.UNAPPROVED, 0);
542 });
543 return Arrays.asList(test1, test2, test3);
544 }
545
546 @Override
547 protected void helpLicenses(final Set<TestData> result, final Option option) {
548 PrintStream origin = System.out;
549 ByteArrayOutputStream baos = new ByteArrayOutputStream();
550 PrintStream out = new PrintStream(baos);
551
552 result.add(new TestData("stdOut",
553 Collections.singletonList(ImmutablePair.of(option, null)),
554 basePath -> {
555 DefaultLog.getInstance().warn("helpLicenses setup for " + basePath);
556 System.setOut(out);
557 },
558 validatorData -> {
559 DefaultLog.getInstance().warn("validating helpLicenses for " + validatorData.getBaseDir());
560 System.setOut(origin);
561 String txt = baos.toString();
562 assertThat(txt).contains("====== Licenses ======", "====== Defined Matchers ======", "====== Defined Families ======");
563 }));
564 }
565
566 @Override
567 protected void licensesApprovedFileTest(final Set<TestData> result, final Option option) {
568 result.addAll(execLicensesApprovedTest(option, new String[]{".rat/licensesApproved.txt"},
569 mkRat.andThen(
570 basePath -> {
571 DefaultLog.getInstance().warn("licensesApprovedFileTest setup for " + basePath);
572 writeFile(basePath.resolve(".rat").toFile(), "licensesApproved.txt", List.of("catz"));
573 })));
574 }
575
576 @Override
577 protected void licensesApprovedTest(final Set<TestData> result, final Option option) {
578 result.addAll(execLicensesApprovedTest(option, new String[]{"catz"}, NO_SETUP));
579 }
580
581 private List<TestData> execLicensesDeniedTest(final Option option, final String[] args, Consumer<Path> setupFiles) {
582 Consumer<Path> setup = setupFiles.andThen(basePath -> {
583 DefaultLog.getInstance().warn("execLicensesDeniedTest setup for " + basePath);
584 File baseDir = basePath.toFile();
585 writeFile(baseDir, "illumousFile.java", "The contents of this file are " +
586 "subject to the terms of the Common Development and Distribution License (the \"License\") You " +
587 "may not use this file except in compliance with the License.");
588 });
589 TestData test1 = new TestData("ILLUMOS", Collections.singletonList(ImmutablePair.of(option, args)),
590 setup,
591 validatorData -> {
592 DefaultLog.getInstance().warn("validating execLicensesDeniedTest for " + validatorData.getBaseDir());
593 ClaimStatistic claimStatistic = validatorData.getStatistic();
594 ClaimValidator validator = validatorData.getConfiguration().getClaimValidator();
595 assertThat(validator.listIssues(claimStatistic)).containsExactly("UNAPPROVED");
596 });
597 return Collections.singletonList(test1);
598 }
599
600 @Override
601 protected void licensesDeniedTest(final Set<TestData> result, final Option option) {
602 result.addAll(execLicensesDeniedTest(option, new String[]{"ILLUMOS"}, NO_SETUP));
603 }
604
605 @Override
606 protected void licensesDeniedFileTest(final Set<TestData> result, final Option option) {
607 result.addAll(execLicensesDeniedTest(option, new String[]{"licensesDenied.txt"},
608 basePath -> writeFile(basePath.toFile(), "licensesDenied.txt", Collections.singletonList("ILLUMOS"))));
609 }
610
611 private List<TestData> execLicenseFamiliesApprovedTest(final Option option, final String[] args, Consumer<Path> extraSetup) {
612 Consumer<Path> setup = extraSetup.andThen(
613 basePath -> {
614 DefaultLog.getInstance().warn("execLicenseFamiliesApprovedTest setup for " + basePath);
615 File baseDir = basePath.toFile();
616 writeFile(baseDir, "catz.txt", "SPDX-License-Identifier: catz");
617 });
618
619 TestData test1 = new TestData(DataUtils.asDirName(option), NO_OPTIONS,
620 setup,
621 validatorData -> {
622 DefaultLog.getInstance().warn("validating execLicenseFamiliesApprovedTest for " + validatorData.getBaseDir());
623 assertCounter(validatorData, ClaimStatistic.Counter.STANDARDS, 1);
624 assertCounter(validatorData, ClaimStatistic.Counter.APPROVED, 0);
625 assertCounter(validatorData, ClaimStatistic.Counter.UNAPPROVED, 1);
626 });
627
628 TestData test2 = new TestData("withoutLicenseDef", Collections.singletonList(ImmutablePair.of(option, args)),
629 setup,
630 validatorData -> {
631 DefaultLog.getInstance().warn("validating execLicenseFamiliesApprovedTest for " + validatorData.getBaseDir());
632 assertCounter(validatorData, ClaimStatistic.Counter.STANDARDS, 1);
633 assertCounter(validatorData, ClaimStatistic.Counter.APPROVED, 0);
634 assertCounter(validatorData, ClaimStatistic.Counter.UNAPPROVED, 1);
635 });
636 Option configOpt = Arg.CONFIGURATION.option();
637 TestData test3 = new TestData("withLicenseDef", Arrays.asList(ImmutablePair.of(option, args),
638 ImmutablePair.of(configOpt, new String[]{".rat/catz.xml"})),
639 setup.andThen(mkRat).andThen(
640 basePath -> {
641 DefaultLog.getInstance().warn("withLicenseDef setup for " + basePath);
642 Path ratDir = basePath.resolve(".rat");
643 Path catzXml = ratDir.resolve("catz.xml");
644 DataUtils.generateSpdxConfig(catzXml, "catz", "catz");
645 }),
646 validatorData -> {
647 DefaultLog.getInstance().warn("validating execLicenseFamiliesApprovedTest for " + validatorData.getBaseDir());
648 assertCounter(validatorData, ClaimStatistic.Counter.STANDARDS, 1);
649 assertCounter(validatorData, ClaimStatistic.Counter.APPROVED, 1);
650 assertCounter(validatorData, ClaimStatistic.Counter.UNAPPROVED, 0);
651 });
652 return Arrays.asList(test1, test2, test3);
653 }
654
655 @Override
656 protected void licenseFamiliesApprovedFileTest(final Set<TestData> result, final Option option) {
657 result.addAll(execLicenseFamiliesApprovedTest(option, new String[]{".rat/familiesApproved.txt"},
658 mkRat.andThen(basePath -> {
659 DefaultLog.getInstance().warn("licenseFamiliesApprovedFileTest setup for " + basePath);
660 writeFile(basePath.resolve(".rat").toFile(), "familiesApproved.txt", Collections.singletonList("catz"));
661 })));
662 }
663
664 @Override
665 protected void licenseFamiliesApprovedTest(final Set<TestData> result, final Option option) {
666 result.addAll(execLicenseFamiliesApprovedTest(option, new String[]{"catz"}, NO_SETUP));
667 }
668
669 private List<TestData> execLicenseFamiliesDeniedTest(final Option option, final String[] args, Consumer<Path> extraSetup) {
670 Consumer<Path> setup = extraSetup.andThen(
671 basePath -> {
672 DefaultLog.getInstance().warn("execLicenseFamiliesDeniedTest setup for " + basePath);
673 File baseDir = basePath.toFile();
674 writeFile(baseDir, "bsd.txt", "SPDX-License-Identifier: BSD-3-Clause");
675 });
676
677 TestData test1 = new TestData(DataUtils.asDirName(option), NO_OPTIONS,
678 setup,
679 validatorData -> {
680 DefaultLog.getInstance().warn("validating execLicenseFamiliesDeniedTest for " + validatorData.getBaseDir());
681 assertCounter(validatorData, ClaimStatistic.Counter.STANDARDS, 1);
682 assertCounter(validatorData, ClaimStatistic.Counter.APPROVED, 1);
683 assertCounter(validatorData, ClaimStatistic.Counter.UNAPPROVED, 0);
684 });
685
686 TestData test2 = new TestData("", Collections.singletonList(ImmutablePair.of(option, args)),
687 setup,
688 validatorData -> {
689 DefaultLog.getInstance().warn("validating execLicenseFamiliesDeniedTest for " + validatorData.getBaseDir());
690 assertCounter(validatorData, ClaimStatistic.Counter.STANDARDS, 1);
691 assertCounter(validatorData, ClaimStatistic.Counter.APPROVED, 0);
692 assertCounter(validatorData, ClaimStatistic.Counter.UNAPPROVED, 1);
693 });
694
695 return Arrays.asList(test1, test2);
696 }
697
698 @Override
699 protected void licenseFamiliesDeniedFileTest(final Set<TestData> result, final Option option) {
700 result.addAll(execLicenseFamiliesDeniedTest(option, new String[]{".rat/familiesDenied.txt"},
701 mkRat.andThen(
702 basePath -> {
703 DefaultLog.getInstance().warn("licenseFamiliesDeniedFileTest setup for " + basePath);
704 writeFile(basePath.resolve(".rat").toFile(), "familiesDenied.txt", Collections.singletonList("BSD-3"));
705 })));
706 }
707
708 @Override
709 protected void licenseFamiliesDeniedTest(final Set<TestData> result, final Option option) {
710 result.addAll(execLicenseFamiliesDeniedTest(option, new String[]{"BSD-3"}, NO_SETUP));
711 }
712
713 @Override
714 protected void counterMaxTest(final Set<TestData> result, final Option option) {
715 result.add(new TestData(DataUtils.asDirName(option), Collections.singletonList(ImmutablePair.of(null, null)),
716 basePath -> {
717 DefaultLog.getInstance().warn("counterMaxTest setup for " + basePath);
718 File baseDir = basePath.toFile();
719 writeFile(baseDir, "Test.java", Arrays.asList("/*\n", "SPDX-License-Identifier: Unapproved\n",
720 "*/\n\n", "class Test {}\n"));
721 },
722 validatorData -> {
723 DefaultLog.getInstance().warn("validating counterMaxTest for " + validatorData.getBaseDir());
724 ClaimStatistic claimStatistic = validatorData.getStatistic();
725 ClaimValidator validator = validatorData.getConfiguration().getClaimValidator();
726 assertThat(validator.listIssues(claimStatistic)).containsExactly("UNAPPROVED");
727 }));
728
729 result.add(new TestData("Unapproved1", Collections.singletonList(ImmutablePair.of(option, new String[]{"Unapproved:1"})),
730 basePath -> {
731 DefaultLog.getInstance().warn("counterMaxTest setup for " + basePath);
732 File baseDir = basePath.toFile();
733 writeFile(baseDir, "Test.java", Arrays.asList("/*\n", "SPDX-License-Identifier: Unapproved\n",
734 "*/\n\n", "class Test {}\n"));
735 },
736 validatorData -> {
737 DefaultLog.getInstance().warn("validating counterMaxTest for " + validatorData.getBaseDir());
738 ClaimStatistic claimStatistic = validatorData.getStatistic();
739 ClaimValidator validator = validatorData.getConfiguration().getClaimValidator();
740 assertThat(validator.listIssues(claimStatistic)).isEmpty();
741 }));
742 }
743
744 @Override
745 protected void counterMinTest(final Set<TestData> result, final Option option) {
746 result.add(new TestData(DataUtils.asDirName(option), NO_OPTIONS,
747 basePath -> {
748 DefaultLog.getInstance().warn("counterMinTest setup for " + basePath);
749 File baseDir = basePath.toFile();
750 writeFile(baseDir, "Test.java", Arrays.asList("/*\n", "SPDX-License-Identifier: Unapproved\n",
751 "*/\n\n", "class Test {}\n"));
752 },
753 validatorData -> {
754 DefaultLog.getInstance().warn("validating counterMinTest for " + validatorData.getBaseDir());
755 ClaimStatistic claimStatistic = validatorData.getStatistic();
756 ClaimValidator validator = validatorData.getConfiguration().getClaimValidator();
757 assertThat(validator.listIssues(claimStatistic)).containsExactly("UNAPPROVED");
758 }));
759
760 result.add(new TestData("", Collections.singletonList(ImmutablePair.of(option, new String[]{"Unapproved:1"})),
761 basePath -> {
762 DefaultLog.getInstance().warn("counterMinTest setup for " + basePath);
763 File baseDir = basePath.toFile();
764 writeFile(baseDir, "Test.java", Arrays.asList("/*\n", "SPDX-License-Identifier: Unapproved\n",
765 "*/\n\n", "class Test {}\n"));
766 },
767 validatorData -> {
768 DefaultLog.getInstance().warn("validating counterMinTest for " + validatorData.getBaseDir());
769 ClaimStatistic claimStatistic = validatorData.getStatistic();
770 ClaimValidator validator = validatorData.getConfiguration().getClaimValidator();
771 assertThat(validator.listIssues(claimStatistic)).isEmpty();
772 }));
773 }
774
775 @Override
776 protected void configTest(final Set<TestData> result, final Option option) {
777 Consumer<Path> setup = mkRat.andThen(basePath -> {
778 DefaultLog.getInstance().warn("configTest setup for " + basePath);
779 Path ratDir = basePath.resolve(".rat");
780 Path oneXml = ratDir.resolve("One.xml");
781 DataUtils.generateTextConfig(oneXml, "ONE", "one");
782
783 Path twoXml = ratDir.resolve("Two.xml");
784 DataUtils.generateTextConfig(twoXml, "TWO", "two");
785
786 File baseDir = basePath.toFile();
787 writeFile(baseDir, "bsd.txt", "SPDX-License-Identifier: BSD-3-Clause");
788 writeFile(baseDir, "one.txt", "one is the loneliest number");
789 });
790 String[] args = {".rat/One.xml", ".rat/Two.xml"};
791
792 ImmutablePair<Option, String[]> underTest = ImmutablePair.of(option, args);
793
794 result.add(new TestData(DataUtils.asDirName(option), NO_OPTIONS,
795 setup,
796 validatorData -> {
797 DefaultLog.getInstance().warn("validating configTest for " + validatorData.getBaseDir());
798 assertCounter(validatorData, ClaimStatistic.Counter.STANDARDS, 2);
799 assertCounter(validatorData, ClaimStatistic.Counter.APPROVED, 1);
800 assertCounter(validatorData, ClaimStatistic.Counter.UNAPPROVED, 1);
801 }));
802
803 result.add(new TestData("withDefaults", Collections.singletonList(underTest),
804 setup,
805 validatorData -> {
806 DefaultLog.getInstance().warn("validating configTest for " + validatorData.getBaseDir());
807 assertCounter(validatorData, ClaimStatistic.Counter.STANDARDS, 2);
808 assertCounter(validatorData, ClaimStatistic.Counter.APPROVED, 2);
809 assertCounter(validatorData, ClaimStatistic.Counter.UNAPPROVED, 0);
810 }));
811
812 if (!Arg.CONFIGURATION_NO_DEFAULTS.isEmpty()) {
813 result.add(new TestData("noDefaults", Arrays.asList(underTest,
814 ImmutablePair.of(Arg.CONFIGURATION_NO_DEFAULTS.find("configuration-no-defaults"), null)),
815 setup,
816
817 validatorData -> {
818 DefaultLog.getInstance().warn("validating configTest for " + validatorData.getBaseDir());
819 assertCounter(validatorData, ClaimStatistic.Counter.STANDARDS, 2);
820 assertCounter(validatorData, ClaimStatistic.Counter.APPROVED, 1);
821 assertCounter(validatorData, ClaimStatistic.Counter.UNAPPROVED, 1);
822 }));
823 }
824 }
825
826 @Override
827 protected void configurationNoDefaultsTest(final Set<TestData> result, final Option option) {
828 TestData test1 = new TestData("", Collections.singletonList(ImmutablePair.of(option, null)),
829 basePath -> {
830 DefaultLog.getInstance().warn("configurationNoDefaultsTest setup for " + basePath);
831 File baseDir = basePath.toFile();
832 writeFile(baseDir, "Test.java", Arrays.asList("/*\n", "SPDX-License-Identifier: Apache-2.0\n",
833 "*/\n\n", "class Test {}\n"));
834 },
835 validatorData -> {
836 DefaultLog.getInstance().warn("validating configurationNoDefaultsTest for " + validatorData.getBaseDir());
837 assertThat(validatorData.getConfiguration().getLicenses(LicenseSetFactory.LicenseFilter.ALL)).isEmpty();
838 });
839 test1.setException(NO_LICENSES_EXCEPTION);
840 result.add(test1);
841 }
842
843 @Override
844 protected void dryRunTest(final Set<TestData> result, final Option option) {
845 result.add(new TestData("stdRun", Collections.singletonList(ImmutablePair.of(option, null)),
846 NO_SETUP,
847 validatorData -> {
848 DefaultLog.getInstance().warn("validating dryRunTest for " + validatorData.getBaseDir());
849 assertThat(validatorData.getConfiguration().isDryRun()).as("testing getConfiguration().isDryRun() flag").isTrue();
850 }));
851
852 result.add(new TestData(DataUtils.asDirName(option), NO_OPTIONS,
853 NO_SETUP,
854 validatorData -> {
855 DefaultLog.getInstance().warn("validating dryRunTest for " + validatorData.getBaseDir());
856 assertThat(validatorData.getConfiguration().isDryRun()).as("testing getConfiguration().isDryRun() flag").isFalse();
857 }));
858 }
859
860 @Override
861 protected void editCopyrightTest(final Set<TestData> result, final Option option) {
862 Consumer<Path> setup = basePath -> {
863 DefaultLog.getInstance().warn("editCopyrightTest setup for " + basePath);
864 File baseDir = basePath.toFile();
865 writeFile(baseDir, "Missing.java", Arrays.asList("/* no license */\n\n", "class Test {}\n"));
866 };
867 ImmutablePair<Option, String[]> copyright = ImmutablePair.of(option, new String[]{"MyCopyright"});
868 if (Arg.EDIT_ADD.isEmpty()) {
869 throw new RuntimeException("Can not execute copyright tests without an EDIT_ADD option available");
870 }
871 ImmutablePair<Option, String[]> editLicense = ImmutablePair.of(Arg.EDIT_ADD.option(), null);
872
873 result.add(new TestData("noEditLicense", Collections.singletonList(copyright),
874 setup,
875 validatorData -> {
876 DefaultLog.getInstance().warn("validating editCopyrightTest for " + validatorData.getBaseDir());
877 try {
878 String actualText = TextUtils.readFile(validatorData.getBaseDir().resolve("Missing.java").toFile());
879 assertThat(actualText).doesNotContain("MyCopyright");
880 } catch (IOException ex) {
881 throw new RuntimeException(ex);
882 }
883 }));
884
885 result.add(new TestData(DataUtils.asDirName(editLicense.getLeft()), Arrays.asList(copyright, editLicense),
886 setup,
887 validatorData -> {
888 DefaultLog.getInstance().warn("validating editCopyrightTest for " + validatorData.getBaseDir());
889 try {
890 String actualText = TextUtils.readFile(validatorData.getBaseDir().resolve("Missing.java").toFile());
891 assertThat(actualText).doesNotContain("MyCopyright");
892 assertThat(validatorData.getBaseDir().resolve("Missing.java.new")).exists();
893 actualText = TextUtils.readFile(validatorData.getBaseDir().resolve("Missing.java.new").toFile());
894 assertThat(actualText).contains("MyCopyright");
895 } catch (IOException ex) {
896 throw new RuntimeException(ex);
897 }
898 }));
899
900 if (!Arg.DRY_RUN.isEmpty()) {
901 Option dryRun = Arg.DRY_RUN.option();
902 result.add(new TestData(DataUtils.asDirName(dryRun),
903 Arrays.asList(copyright, ImmutablePair.of(dryRun, null), editLicense),
904 setup,
905 validatorData -> {
906 DefaultLog.getInstance().warn("validating editCopyrightTest for " + validatorData.getBaseDir());
907 try {
908 String actualText = TextUtils.readFile(validatorData.getBaseDir().resolve("Missing.java").toFile());
909 assertThat(actualText).doesNotContain("MyCopyright");
910 } catch (IOException ex) {
911 throw new RuntimeException(ex);
912 }
913 assertThat(validatorData.getBaseDir().resolve("Missing.java.new")).doesNotExist();
914 }));
915 }
916
917 if (!Arg.EDIT_OVERWRITE.isEmpty()) {
918 Option overwrite = Arg.EDIT_OVERWRITE.option();
919 result.add(new TestData(DataUtils.asDirName(overwrite), Arrays.asList(copyright, editLicense, ImmutablePair.of(overwrite, null)),
920 setup,
921 validatorData -> {
922 DefaultLog.getInstance().warn("validating editCopyrightTest for " + validatorData.getBaseDir());
923 try {
924 String actualText = TextUtils.readFile(validatorData.getBaseDir().resolve("Missing.java").toFile());
925 assertThat(actualText).contains("MyCopyright");
926 assertThat(validatorData.getBaseDir().resolve("Missing.java.new")).doesNotExist();
927 } catch (IOException ex) {
928 throw new RuntimeException(ex);
929 }
930 }));
931 }
932 }
933
934 @Override
935 protected void editLicenseTest(final Set<TestData> result, final Option option) {
936 result.add(new TestData("", Collections.singletonList(ImmutablePair.of(option, null)),
937 basePath -> {
938 DefaultLog.getInstance().warn("editLicenseTest setup for " + basePath);
939 File baseDir = basePath.toFile();
940 writeFile(baseDir, "NoLicense.java", "class NoLicense {}");
941 },
942 validatorData -> {
943 DefaultLog.getInstance().warn("validating editLicenseTest for " + validatorData.getBaseDir());
944 try {
945 assertThat(validatorData.getStatistic()).isNotNull();
946 File javaFile = validatorData.getBaseDir().resolve("NoLicense.java").toFile();
947 String contents = String.join("\n", IOUtils.readLines(new FileReader(javaFile, StandardCharsets.UTF_8)));
948 assertThat(contents).isEqualTo("class NoLicense {}");
949 File resultFile = validatorData.getBaseDir().resolve("NoLicense.java.new").toFile();
950 assertThat(resultFile).exists();
951 contents = String.join("\n", IOUtils.readLines(new FileReader(resultFile, StandardCharsets.UTF_8)));
952 assertThat(contents).isEqualTo("""
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972 class NoLicense {}""");
973 } catch (IOException e) {
974 throw new RuntimeException(e);
975 }
976 }));
977 }
978
979 @Override
980 protected void editOverwriteTest(final Set<TestData> result, final Option option) {
981 result.add(new TestData("noEditLicense", Collections.singletonList(ImmutablePair.of(option, null)),
982 NO_SETUP,
983 validatorData -> {
984 DefaultLog.getInstance().warn("validating editOverwriteTest for " + validatorData.getBaseDir());
985 assertThat(validatorData.getConfiguration().isAddingLicensesForced())
986 .describedAs("Without edit-license should be false").isFalse();
987 }));
988
989 if (!Arg.EDIT_ADD.isEmpty()) {
990 result.add(new TestData("", Arrays.asList(ImmutablePair.of(option, null),
991 ImmutablePair.of(Arg.EDIT_ADD.find("edit-license"), null)),
992 NO_SETUP,
993 validatorData -> {
994 DefaultLog.getInstance().warn("validating editOverwriteTest for " + validatorData.getBaseDir());
995 assertThat(validatorData.getConfiguration().isAddingLicensesForced())
996 .as("testing getConfiguration().isAddingLicensesForced() flag").isTrue();
997 }));
998 }
999 }
1000
1001 @Override
1002 protected void logLevelTest(final Set<TestData> result, final Option option) {
1003 final TestingLog testingLog = new TestingLog();
1004
1005 Consumer<Path> setup = basePath -> {
1006 DefaultLog.getInstance().warn("logLevelTest setup for " + basePath);
1007 DefaultLog.setInstance(testingLog);
1008 testingLog.clear();
1009 };
1010
1011 result.add(new TestData(Log.Level.INFO.name(),
1012 Collections.singletonList(ImmutablePair.of(option, new String[]{Log.Level.INFO.name()})),
1013 setup,
1014 validatorData -> {
1015 DefaultLog.getInstance().warn("validating logLevelTest for " + validatorData.getBaseDir());
1016 try {
1017 assertThat(testingLog.getCaptured()).doesNotContain("DEBUG");
1018 } finally {
1019 DefaultLog.setInstance(null);
1020 }
1021 }));
1022
1023 result.add(new TestData(Log.Level.DEBUG.name(),
1024 Collections.singletonList(ImmutablePair.of(option, new String[]{Log.Level.DEBUG.name()})),
1025 setup,
1026 validatorData -> {
1027 DefaultLog.getInstance().warn("validating logLevelTest for " + validatorData.getBaseDir());
1028 try {
1029 assertThat(testingLog.getCaptured()).contains("DEBUG");
1030 } finally {
1031 DefaultLog.setInstance(null);
1032 }
1033 }));
1034 }
1035
1036 @Override
1037 protected void outputArchiveTest(final Set<TestData> result, final Option option) {
1038 for (ReportConfiguration.Processing processing : ReportConfiguration.Processing.values()) {
1039 result.add(new TestData(processing.name().toLowerCase(Locale.ROOT),
1040 Collections.singletonList(ImmutablePair.of(option, new String[]{processing.name()})),
1041 basePath -> {
1042 DefaultLog.getInstance().warn("outputArchiveTest setup for " + basePath);
1043 File localArchive = new File(basePath.toFile(), "dummy.jar");
1044 try (InputStream in = ReportTestDataProvider.class.getResourceAsStream("/tikaFiles/archive/dummy.jar");
1045 OutputStream out = Files.newOutputStream(localArchive.toPath())) {
1046 Objects.requireNonNull(in);
1047 IOUtils.copy(in, out);
1048 } catch (IOException e) {
1049 throw new RuntimeException(e);
1050 }
1051 },
1052 validatorData -> {
1053 DefaultLog.getInstance().warn("validating outputArchiveTest for " + validatorData.getBaseDir());
1054 Document document = validatorData.getDocument();
1055 try {
1056 XmlUtils.assertIsPresent(processing.name(), document, xpath, "/rat-report/resource[@name='/dummy.jar']");
1057 switch (processing) {
1058 case ABSENCE:
1059 XmlUtils.assertIsPresent(processing.name(), document, xpath, "/rat-report/resource[@name='/dummy.jar']/license[@family='AL ']");
1060 XmlUtils.assertIsPresent(processing.name(), document, xpath, "/rat-report/resource[@name='/dummy.jar']/license[@family='?????']");
1061 break;
1062 case PRESENCE:
1063 XmlUtils.assertIsPresent(processing.name(), document, xpath, "/rat-report/resource[@name='/dummy.jar']/license[@family='AL ']");
1064 XmlUtils.assertIsNotPresent(processing.name(), document, xpath, "/rat-report/resource[@name='/dummy.jar']/license[@family='?????']");
1065 break;
1066 case NOTIFICATION:
1067 XmlUtils.assertIsNotPresent(processing.name(), document, xpath, "/rat-report/resource[@name='/dummy.jar']/license[@family='AL ']");
1068 XmlUtils.assertIsNotPresent(processing.name(), document, xpath, "/rat-report/resource[@name='/dummy.jar']/license[@family='?????']");
1069 break;
1070 default:
1071 throw new IllegalArgumentException("Unexpected processing " + processing);
1072 }
1073 } catch (XPathExpressionException e) {
1074 throw new RuntimeException(e);
1075 }
1076 })
1077 );
1078 }
1079 }
1080
1081 @Override
1082 protected void outputFamiliesTest(final Set<TestData> result, final Option option) {
1083 for (LicenseSetFactory.LicenseFilter filter : LicenseSetFactory.LicenseFilter.values()) {
1084 result.add(new TestData(filter.name().toLowerCase(Locale.ROOT),
1085 Collections.singletonList(ImmutablePair.of(option, new String[]{filter.name()})),
1086 NO_SETUP,
1087 validatorData -> {
1088 DefaultLog.getInstance().warn("validating outputFamiliesTest for " + validatorData.getBaseDir());
1089 Document document = validatorData.getDocument();
1090 try {
1091 switch (filter) {
1092 case ALL:
1093 XmlUtils.assertIsPresent(filter.name(), document, xpath, "/rat-report/rat-config/families/family[@id='AL']");
1094 XmlUtils.assertIsPresent(filter.name(), document, xpath, "/rat-report/rat-config/families/family[@id='GPL']");
1095 break;
1096 case APPROVED:
1097 XmlUtils.assertIsPresent(filter.name(), document, xpath, "/rat-report/rat-config/families/family[@id='AL']");
1098 XmlUtils.assertIsNotPresent(filter.name(), document, xpath, "/rat-report/rat-config/families/family[@id='GPL']");
1099 break;
1100 case NONE:
1101 XmlUtils.assertIsNotPresent(filter.name(), document, xpath, "/rat-report/rat-config/families/family[@id='AL']");
1102 XmlUtils.assertIsNotPresent(filter.name(), document, xpath, "/rat-report/rat-config/families/family[@id='GPL']");
1103 break;
1104 default:
1105 throw new IllegalArgumentException("Unexpected filter: " + filter);
1106 }
1107 } catch (XPathExpressionException e) {
1108 throw new RuntimeException(e);
1109 }
1110 })
1111 );
1112 }
1113 }
1114
1115 @Override
1116 protected void outputFileTest(final Set<TestData> result, final Option option) {
1117 result.add(new TestData("", Collections.singletonList(ImmutablePair.of(option, new String[]{"outexample"})),
1118 basePath -> {
1119 DefaultLog.getInstance().warn("outputFileTest setup for " + basePath);
1120 File baseDir = basePath.toFile();
1121 writeFile(baseDir, "apl.txt", "SPDX-License-Identifier: Apache-2.0");
1122 },
1123 validatorData -> {
1124 DefaultLog.getInstance().warn("validating outputFamiliesTest for " + validatorData.getBaseDir());
1125 assertCounter(validatorData, ClaimStatistic.Counter.STANDARDS, 1);
1126 assertCounter(validatorData, ClaimStatistic.Counter.APPROVED, 1);
1127 assertCounter(validatorData, ClaimStatistic.Counter.UNAPPROVED, 0);
1128 File outFile = validatorData.getBaseDir().resolve("outexample").toFile();
1129
1130 try {
1131 String actualText = TextUtils.readFile(outFile);
1132 assertThat(actualText).containsPattern("Apache License 2.0: \\d")
1133 .containsPattern("STANDARD:\\s+\\d");
1134 } catch (IOException e) {
1135 throw new RuntimeException(e);
1136 }
1137 })
1138 );
1139 }
1140
1141 @Override
1142 protected void outputLicensesTest(final Set<TestData> result, final Option option) {
1143 for (LicenseSetFactory.LicenseFilter filter : LicenseSetFactory.LicenseFilter.values()) {
1144 result.add(new TestData(filter.name(), Collections.singletonList(ImmutablePair.of(option, new String[]{filter.name()})),
1145 NO_SETUP,
1146 validatorData -> {
1147 DefaultLog.getInstance().warn("validating outputLicensesTest for " + validatorData.getBaseDir());
1148 Document document = validatorData.getDocument();
1149 try {
1150 switch (filter) {
1151 case ALL:
1152 XmlUtils.assertIsPresent(filter.name(), document, xpath, "/rat-report/rat-config/licenses/license[@id='AL2.0']");
1153 XmlUtils.assertIsPresent(filter.name(), document, xpath, "/rat-report/rat-config/licenses/license[@id='GPL1']");
1154 break;
1155 case APPROVED:
1156 XmlUtils.assertIsPresent(filter.name(), document, xpath, "/rat-report/rat-config/licenses/license[@id='AL2.0']");
1157 XmlUtils.assertIsNotPresent(filter.name(), document, xpath, "/rat-report/rat-config/licenses/license[@id='GPL1']");
1158 break;
1159 case NONE:
1160 XmlUtils.assertIsNotPresent(filter.name(), document, xpath, "/rat-report/rat-config/licenses/license[@id='AL2.0']");
1161 XmlUtils.assertIsNotPresent(filter.name(), document, xpath, "/rat-report/rat-config/licenses/license[@id='GPL1']");
1162 break;
1163 default:
1164 throw new IllegalArgumentException("Unexpected filter: " + filter);
1165 }
1166 } catch (XPathExpressionException e) {
1167 throw new RuntimeException(e);
1168 }
1169 }));
1170 }
1171 }
1172
1173 @Override
1174 protected void outputStandardTest(final Set<TestData> result, final Option option) {
1175 for (ReportConfiguration.Processing proc : ReportConfiguration.Processing.values()) {
1176 result.add(new TestData(proc.name().toLowerCase(Locale.ROOT), Collections.singletonList(ImmutablePair.of(option, new String[]{proc.name()})),
1177 basePath -> {
1178 DefaultLog.getInstance().warn("outputStandardTest setup for " + basePath);
1179 File baseDir = basePath.toFile();
1180 writeFile(baseDir, "Test.java", Arrays.asList("/*\n", "SPDX-License-Identifier: Apache-2.0\n",
1181 "*/\n\n", "class Test {}\n"));
1182 writeFile(baseDir, "Missing.java", Arrays.asList("/* no license */\n\n", "class Test {}\n"));
1183 },
1184 validatorData -> {
1185 DefaultLog.getInstance().warn("validating outputStandardTest for " + validatorData.getBaseDir());
1186 Document document = validatorData.getDocument();
1187 String testDoc = "/rat-report/resource[@name='/Test.java']";
1188 String missingDoc = "/rat-report/resource[@name='/Missing.java']";
1189 try {
1190 XmlUtils.assertIsPresent(proc.name(), document, xpath, testDoc);
1191 XmlUtils.assertIsPresent(proc.name(), document, xpath, missingDoc);
1192
1193 switch (proc) {
1194 case ABSENCE:
1195 XmlUtils.assertIsPresent(proc.name(), document, xpath, testDoc + "/license[@family='AL ']");
1196 XmlUtils.assertIsPresent(proc.name(), document, xpath, missingDoc + "/license[@family='?????']");
1197 break;
1198 case PRESENCE:
1199 XmlUtils.assertIsPresent(proc.name(), document, xpath, testDoc + "/license[@family='AL ']");
1200 XmlUtils.assertIsNotPresent(proc.name(), document, xpath, missingDoc + "/license[@family='?????']");
1201 break;
1202 case NOTIFICATION:
1203 XmlUtils.assertIsNotPresent(proc.name(), document, xpath, testDoc + "/license[@family='AL ']");
1204 XmlUtils.assertIsNotPresent(proc.name(), document, xpath, missingDoc + "/license[@family='?????']");
1205 break;
1206 default:
1207 throw new IllegalArgumentException("Unexpected processing " + proc);
1208 }
1209 } catch (XPathExpressionException ex) {
1210 throw new RuntimeException(ex);
1211 }
1212 }));
1213 }
1214 }
1215
1216 @Override
1217 protected void outputStyleTest(final Set<TestData> result, final Option option) {
1218 Consumer<Path> createFile = basePath -> {
1219 DefaultLog.getInstance().warn("outputStyleTest setup for " + basePath);
1220 File baseDir = basePath.toFile();
1221 writeFile(baseDir, "Test.java", Arrays.asList("/*\n", "SPDX-License-Identifier: Apache-2.0\n",
1222 "*/\n\n", "class Test {}\n"));
1223 writeFile(baseDir, "Missing.java", Arrays.asList("/* no license */\n\n", "class Test {}\n"));
1224 };
1225
1226 ByteArrayOutputStream baos = new ByteArrayOutputStream();
1227 if (!option.hasArg()) {
1228 if (option.getLongOpt().equals("xml")) {
1229 result.add(new TestData("", Collections.singletonList(ImmutablePair.of(option, null)),
1230 createFile,
1231 validatorData -> {
1232 DefaultLog.getInstance().warn("validating outputStyleTest for " + validatorData.getBaseDir());
1233 try (InputStream expected = StyleSheets.XML.getStyleSheet().ioSupplier().get();
1234 InputStream actual = validatorData.getConfiguration().getStyleSheet().get()) {
1235 assertThat(IOUtils.contentEquals(expected, actual)).as(() -> String.format("'%s' does not match", StyleSheets.XML)).isTrue();
1236 baos.reset();
1237 validatorData.getOutput().format(validatorData.getConfiguration().getStyleSheet(), () -> baos);
1238 String actualText = baos.toString();
1239 assertThat(actualText).containsOnlyOnce("<resource encoding=\"windows-1252\" mediaType=\"text/x-java-source\" name=\"/Test.java\" type=\"STANDARD\">")
1240 .containsOnlyOnce("<resource encoding=\"windows-1252\" mediaType=\"text/x-java-source\" name=\"/Missing.java\" type=\"STANDARD\">");
1241 } catch (IOException | RatException e) {
1242 throw new RuntimeException(e);
1243 }
1244 }));
1245 }
1246 } else {
1247 for (StyleSheets sheet : StyleSheets.values()) {
1248 result.add(new TestData(sheet.name().toLowerCase(Locale.ROOT), Collections.singletonList(ImmutablePair.of(option, new String[]{sheet.arg()})),
1249 createFile,
1250 validatorData -> {
1251 DefaultLog.getInstance().warn("validating outputStyleTest for " + validatorData.getBaseDir());
1252 try (InputStream expected = sheet.getStyleSheet().ioSupplier().get();
1253 InputStream actual = validatorData.getConfiguration().getStyleSheet().get()) {
1254 assertThat(IOUtils.contentEquals(expected, actual)).as(() -> String.format("'%s' does not match", sheet)).isTrue();
1255 baos.reset();
1256 validatorData.getOutput().format(validatorData.getConfiguration().getStyleSheet(), () -> baos);
1257 String actualText = baos.toString();
1258 switch (sheet) {
1259 case MISSING_HEADERS:
1260 assertThat(actualText).containsOnlyOnce("Files with missing headers:" + System.lineSeparator() +
1261 " /Missing.java");
1262 break;
1263 case PLAIN:
1264 assertThat(actualText).containsOnlyOnce("Unknown license: 1 ")
1265 .containsOnlyOnce("?????: 1 ");
1266 break;
1267 case XML:
1268 assertThat(actualText).containsOnlyOnce("<resource encoding=\"windows-1252\" mediaType=\"text/x-java-source\" name=\"/Test.java\" type=\"STANDARD\">")
1269 .containsOnlyOnce("<resource encoding=\"windows-1252\" mediaType=\"text/x-java-source\" name=\"/Missing.java\" type=\"STANDARD\">");
1270 break;
1271 case UNAPPROVED_LICENSES:
1272 assertThat(actualText).containsOnlyOnce("Files with unapproved licenses:" + System.lineSeparator() + " /Missing.java");
1273 break;
1274 case XHTML5:
1275 assertThat(actualText).containsPattern("<td>Approved</td>\\s+<td>\\d+</td>\\s+<td>A count of approved licenses.</td>");
1276 break;
1277 default:
1278 fail("No test for stylesheet " + sheet);
1279 break;
1280 }
1281 } catch (IOException | RatException e) {
1282 throw new RuntimeException(e);
1283 }
1284 }));
1285 }
1286
1287 result.add(new TestData("fileStyleSheet",
1288 Collections.singletonList(ImmutablePair.of(option, new String[]{"fileStyleSheet.xslt"})),
1289 basePath -> {
1290 DefaultLog.getInstance().warn("outputStyleTest setup for " + basePath);
1291 DocumentName name = DocumentName.builder().setName("fileStyleSheet.xslt")
1292 .setBaseName(basePath.toString()).build();
1293 assertDoesNotThrow(() -> {
1294 try (FileWriter fileWriter = new FileWriter(name.asFile(), StandardCharsets.UTF_8);
1295 XmlWriter writer = new XmlWriter(fileWriter)) {
1296 writer.startDocument()
1297 .comment(DataUtils.ASF_TEXT)
1298 .startElement("xsl:stylesheet")
1299 .attribute("version", "1.0")
1300 .attribute("xmlns:xsl", "http://www.w3.org/1999/XSL/Transform")
1301 .startElement("xsl:template")
1302 .attribute("match", "@*|node()")
1303 .content("Hello World")
1304 .closeDocument();
1305 }
1306 });
1307 },
1308
1309 validatorData -> {
1310 DefaultLog.getInstance().warn("validating outputStyleTest for " + validatorData.getBaseDir());
1311 try (InputStream expected = StyleSheets.getStyleSheet("fileStyleSheet.xslt", validatorData.getBaseName()).ioSupplier().get();
1312 InputStream actual = validatorData.getConfiguration().getStyleSheet().get()) {
1313 assertThat(IOUtils.contentEquals(expected, actual)).as(() -> "'fileStyleSheet.xslt' does not match").isTrue();
1314 baos.reset();
1315 validatorData.getOutput().format(validatorData.getConfiguration().getStyleSheet(), () -> baos);
1316 String actualText = baos.toString();
1317 assertThat(actualText).containsOnlyOnce("Hello World");
1318 } catch (IOException | RatException e) {
1319 throw new RuntimeException(e);
1320 }
1321 }));
1322 }
1323 }
1324 }