1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.rat.mp;
18
19 import static java.lang.String.format;
20 import static java.nio.charset.StandardCharsets.UTF_8;
21 import static org.apache.rat.mp.RatTestHelpers.ensureRatReportIsCorrect;
22 import static org.assertj.core.api.Assertions.assertThat;
23 import static org.assertj.core.api.Fail.fail;
24
25 import java.io.File;
26
27 import java.io.IOException;
28 import java.nio.file.Files;
29 import java.nio.file.Path;
30 import java.util.ArrayList;
31 import java.util.Arrays;
32 import java.util.HashMap;
33 import java.util.List;
34 import java.util.Map;
35 import javax.xml.xpath.XPath;
36 import javax.xml.xpath.XPathFactory;
37 import org.apache.commons.io.FileUtils;
38 import org.apache.rat.ReportConfiguration;
39 import org.apache.rat.ReportConfigurationTest;
40 import org.apache.rat.ReporterTestUtils;
41 import org.apache.rat.api.Document;
42 import org.apache.rat.commandline.Arg;
43 import org.apache.rat.license.ILicenseFamily;
44 import org.apache.rat.license.LicenseSetFactory;
45 import org.apache.rat.license.LicenseSetFactory.LicenseFilter;
46 import org.apache.rat.report.claim.ClaimStatistic;
47 import org.apache.rat.test.AbstractConfigurationOptionsProvider;
48 import org.apache.rat.test.utils.Resources;
49 import org.apache.rat.testhelpers.TextUtils;
50 import org.apache.rat.testhelpers.XmlUtils;
51 import org.junit.jupiter.api.AfterAll;
52 import org.junit.jupiter.api.Assertions;
53 import org.junit.jupiter.api.Test;
54 import org.junit.jupiter.api.condition.EnabledOnOs;
55 import org.junit.jupiter.api.condition.OS;
56 import org.junit.jupiter.api.io.TempDir;
57 import org.w3c.dom.NamedNodeMap;
58 import org.w3c.dom.NodeList;
59
60
61
62
63 public class RatCheckMojoTest {
64
65 @TempDir
66 static Path tempDir;
67
68 private final static XPath xPath = XPathFactory.newInstance().newXPath();
69
70 @AfterAll
71 static void preserveData() {
72 AbstractConfigurationOptionsProvider.preserveData(tempDir.toFile(), "unit");
73 }
74
75 @AfterAll
76 @EnabledOnOs(OS.WINDOWS)
77 static void cleanup() {
78 System.gc();
79 }
80
81 private RatCheckMojo getMojo(File pomFile) throws IOException {
82 try {
83 final RatCheckMojo mojo = new OptionMojoTest.SimpleMojoTestcase() {
84 }.getMojo(pomFile);
85 Assertions.assertNotNull(mojo);
86 return mojo;
87 } catch (IOException e) {
88 throw e;
89 } catch (Exception e) {
90 throw new IOException(format("Unable to generate mojo for %s", pomFile), e);
91 }
92 }
93
94
95
96
97
98
99
100
101
102 private RatCheckMojo newRatMojo(String testDir) throws Exception {
103 Arg.reset();
104 final File sourceDir = Resources.getResourceDirectory(format("unit/%s", testDir));
105 final File baseDir = tempDir.resolve(testDir).toFile();
106 FileUtils.copyDirectory(sourceDir, baseDir);
107 final File pomFile = new File(baseDir, "pom.xml");
108 RatCheckMojo mojo = getMojo(pomFile);
109 assertThat(mojo).isNotNull();
110 assertThat(mojo.getProject())
111 .as("The mojo is missing its MavenProject, which will result in an NPE during RAT runs.")
112 .isNotNull();
113
114 File buildDirectory = new File(baseDir, "target");
115 assertThat(buildDirectory.mkdirs()).isTrue();
116 final File ratTxtFile = new File(buildDirectory, "rat.txt");
117 FileUtils.write(ratTxtFile, "", UTF_8);
118 mojo.setOutputFile(ratTxtFile.getAbsolutePath());
119 return mojo;
120 }
121
122
123
124
125
126
127 @Test
128 void it1() throws Exception {
129 final RatCheckMojo mojo = newRatMojo("it1");
130 final File ratTxtFile = mojo.getRatTxtFile();
131
132 ReportConfiguration config = mojo.getConfiguration();
133 ReportConfigurationTest.validateDefault(config);
134
135 mojo.execute();
136 Map<ClaimStatistic.Counter, String> data = new HashMap<>();
137 data.put(ClaimStatistic.Counter.ARCHIVES, "0");
138 data.put(ClaimStatistic.Counter.APPROVED, "1");
139 data.put(ClaimStatistic.Counter.BINARIES, "0");
140 data.put(ClaimStatistic.Counter.DOCUMENT_TYPES, "2");
141 data.put(ClaimStatistic.Counter.IGNORED, "2");
142 data.put(ClaimStatistic.Counter.LICENSE_CATEGORIES, "1");
143 data.put(ClaimStatistic.Counter.LICENSE_NAMES, "1");
144 data.put(ClaimStatistic.Counter.NOTICES, "0");
145 data.put(ClaimStatistic.Counter.STANDARDS, "1");
146 data.put(ClaimStatistic.Counter.UNAPPROVED, "0");
147 data.put(ClaimStatistic.Counter.UNKNOWN, "0");
148
149 org.w3c.dom.Document document = XmlUtils.toDom(Files.newInputStream(ratTxtFile.toPath()));
150 XPath xPath = XPathFactory.newInstance().newXPath();
151
152 for (ClaimStatistic.Counter counter : ClaimStatistic.Counter.values()) {
153 String xpath = String.format("/rat-report/statistics/statistic[@name='%s']", counter.displayName());
154 Map<String, String> map = mapOf("approval", "true", "count", data.get(counter),
155 "description", counter.getDescription());
156 XmlUtils.assertAttributes(document, xPath, xpath, map);
157 }
158
159 XmlUtils.assertAttributes(document, xPath, "/rat-report/resource[@name='/.bzrignore']",
160 mapOf("mediaType", "application/octet-stream", "type", "IGNORED"));
161
162 XmlUtils.assertAttributes(document, xPath, "/rat-report/resource[@name='/pom.xml']",
163 mapOf("mediaType", "application/xml", "type", "STANDARD", "encoding", "ISO-8859-1"));
164 }
165
166 private static Map<String, String> mapOf(String... parts) {
167 Map<String, String> map = new HashMap<>();
168 for (int i = 0; i < parts.length; i += 2) {
169 map.put(parts[i], parts[i + 1]);
170 }
171 return map;
172 }
173
174
175
176
177
178
179 @Test
180 void it2() throws Exception {
181 final RatCheckMojo mojo = newRatMojo("it2");
182 final File ratTxtFile = mojo.getRatTxtFile();
183 final String[] expected = {
184 "^Files with unapproved licenses\\s+\\*+\\s+\\Q/src.txt\\E\\s+",
185 ReporterTestUtils.counterText(ClaimStatistic.Counter.NOTICES, 0, false),
186 ReporterTestUtils.counterText(ClaimStatistic.Counter.BINARIES, 0, false),
187 ReporterTestUtils.counterText(ClaimStatistic.Counter.ARCHIVES, 0, false),
188 ReporterTestUtils.counterText(ClaimStatistic.Counter.STANDARDS, 2, false),
189 ReporterTestUtils.counterText(ClaimStatistic.Counter.IGNORED, 1, false),
190 ReporterTestUtils.apacheLicenseVersion2(1),
191 ReporterTestUtils.unknownLicense(1),
192 ReporterTestUtils.documentOut(false, Document.Type.STANDARD, "/src.txt") +
193 ReporterTestUtils.UNKNOWN_LICENSE,
194 ReporterTestUtils.documentOut(true, Document.Type.STANDARD, "/pom.xml") +
195 ReporterTestUtils.APACHE_LICENSE
196 };
197 try {
198 mojo.execute();
199 fail("Expected RatCheckException");
200 } catch (RatCheckException e) {
201 final String msg = e.getMessage();
202 assertThat(msg.contains(ratTxtFile.getName())).as(() -> format("report filename was not contained in '%s'", msg))
203 .isTrue();
204 assertThat(msg.toUpperCase()).contains("UNAPPROVED EXCEEDED MINIMUM");
205
206 ensureRatReportIsCorrect(ratTxtFile, expected, TextUtils.EMPTY);
207 }
208 }
209
210
211
212
213 @Test
214 void it3() throws Exception {
215 final RatCheckMojo mojo = newRatMojo("it3");
216 final File ratTxtFile = mojo.getRatTxtFile();
217
218 ReportConfiguration config = mojo.getConfiguration();
219 assertThat(config.isAddingLicenses()).as("should be adding licenses").isTrue();
220 mojo.execute();
221 org.w3c.dom.Document document = XmlUtils.toDom(Files.newInputStream(ratTxtFile.toPath()));
222
223 XmlUtils.assertAttributes(document, xPath, "/rat-report/resource[@name='/pom.xml']", "type",
224 "STANDARD");
225 XmlUtils.assertAttributes(document, xPath, "/rat-report/resource[@name='/src.apt']", "type",
226 "STANDARD");
227 XmlUtils.assertIsPresent(document, xPath, "/rat-report/resource[@name='/src.apt']/license[@approval='false']");
228
229 XmlUtils.assertAttributes(document, xPath, "/rat-report/resource[@name='/src.apt']", "type",
230 "STANDARD");
231
232 for (Document.Type type : Document.Type.values()) {
233 if (type == Document.Type.STANDARD) {
234 XmlUtils.assertAttributes(document, xPath, "/rat-report/statistics/documentType[@name='STANDARD']", "count",
235 "2");
236 } else if (type == Document.Type.IGNORED) {
237 XmlUtils.assertAttributes(document, xPath, "/rat-report/statistics/documentType[@name='IGNORED']", "count",
238 "1");
239 } else {
240 XmlUtils.assertIsNotPresent(document, xPath, format("/rat-report/statistics/documentType[@name='%s']", type));
241 }
242 }
243 }
244
245
246
247
248 @Test
249 void it5() throws Exception {
250 final RatCheckMojo mojo = newRatMojo("it5");
251 final File ratTxtFile = mojo.getRatTxtFile();
252
253 ReportConfiguration config = mojo.getConfiguration();
254 assertThat(config.isAddingLicenses()).as("Should not be adding licenses").isFalse();
255 assertThat(config.isAddingLicensesForced()).as("Should not be forcing licenses").isFalse();
256
257 ReportConfigurationTest.validateDefaultApprovedLicenses(config, 1);
258 assertThat(config.getLicenseCategories(LicenseFilter.APPROVED)).doesNotContain(ILicenseFamily.makeCategory("YAL"))
259 .contains(ILicenseFamily.makeCategory("CC"));
260 ReportConfigurationTest.validateDefaultLicenseFamilies(config, "YAL", "CC");
261 assertThat(LicenseSetFactory.familySearch("YAL", config.getLicenseFamilies(LicenseFilter.APPROVED))).isNull();
262 assertThat(LicenseSetFactory.familySearch("YAL", config.getLicenseFamilies(LicenseFilter.ALL))).isNotNull();
263 assertThat(LicenseSetFactory.familySearch("CC", config.getLicenseFamilies(LicenseFilter.APPROVED))).isNotNull();
264 assertThat(LicenseSetFactory.familySearch("CC", config.getLicenseFamilies(LicenseFilter.ALL))).isNotNull();
265
266 ReportConfigurationTest.validateDefaultLicenses(config, "CC-BY-NC-ND", "YAL");
267 assertThat(LicenseSetFactory.search("YAL", "YAL", config.getLicenses(LicenseFilter.ALL))).isPresent();
268
269 mojo.execute();
270
271 Map<ClaimStatistic.Counter, String> data = new HashMap<>();
272 data.put(ClaimStatistic.Counter.APPROVED, "1");
273 data.put(ClaimStatistic.Counter.ARCHIVES, "0");
274 data.put(ClaimStatistic.Counter.BINARIES, "0");
275 data.put(ClaimStatistic.Counter.DOCUMENT_TYPES, "2");
276 data.put(ClaimStatistic.Counter.IGNORED, "3");
277 data.put(ClaimStatistic.Counter.LICENSE_CATEGORIES, "1");
278 data.put(ClaimStatistic.Counter.LICENSE_NAMES, "1");
279 data.put(ClaimStatistic.Counter.NOTICES, "0");
280 data.put(ClaimStatistic.Counter.STANDARDS, "1");
281 data.put(ClaimStatistic.Counter.UNAPPROVED, "0");
282 data.put(ClaimStatistic.Counter.UNKNOWN, "0");
283
284 org.w3c.dom.Document document = XmlUtils.toDom(Files.newInputStream(ratTxtFile.toPath()));
285 XPath xPath = XPathFactory.newInstance().newXPath();
286
287 for (ClaimStatistic.Counter counter : ClaimStatistic.Counter.values()) {
288 String xpath = String.format("/rat-report/statistics/statistic[@name='%s']", counter.displayName());
289 Map<String, String> map = mapOf("approval",
290 "true",
291 "count", data.get(counter),
292 "description", counter.getDescription());
293 XmlUtils.assertAttributes(document, xPath, xpath, map);
294 }
295
296 XmlUtils.assertAttributes(document, xPath, "/rat-report/resource[@name='/.rat']",
297 "mediaType", "application/octet-stream", "type", "IGNORED", "isDirectory", "true");
298 XmlUtils.assertAttributes(document, xPath, "/rat-report/resource[@name='/pom.xml']",
299 "mediaType", "application/xml", "type", "IGNORED", "isDirectory", "false");
300 XmlUtils.assertAttributes(document, xPath, "/rat-report/resource[@name='/src/main/java/nl/basjes/something/Something.java']",
301 "mediaType", "text/x-java-source", "type", "STANDARD", "encoding", "ISO-8859-1");
302 XmlUtils.assertAttributes(document, xPath, "/rat-report/resource[@name='/src/main/java/nl/basjes/something/Something.java']/license",
303 "approval", "true", "family", ILicenseFamily.makeCategory("CC"), "id", "CC-BY-NC-ND", "name",
304 "Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International");
305 }
306
307
308
309
310
311
312 @Test
313 void rat343() throws Exception {
314 final RatCheckMojo mojo = newRatMojo("RAT-343");
315 final File ratTxtFile = mojo.getRatTxtFile();
316
317 final String[] expected = {
318 ReporterTestUtils.documentOut(false, Document.Type.STANDARD, "/pom.xml") +
319 ReporterTestUtils.APACHE_LICENSE +
320 ReporterTestUtils.licenseOut("BSD", "BSD") +
321 ReporterTestUtils.licenseOut("CC BY", "Creative Commons Attribution (Unapproved)"),
322 ReporterTestUtils.counterText(ClaimStatistic.Counter.NOTICES, 0, false),
323 ReporterTestUtils.counterText(ClaimStatistic.Counter.BINARIES, 0, false),
324 ReporterTestUtils.counterText(ClaimStatistic.Counter.ARCHIVES, 0, false),
325 ReporterTestUtils.counterText(ClaimStatistic.Counter.STANDARDS, 1, false),
326 ReporterTestUtils.counterText(ClaimStatistic.Counter.IGNORED, 1, false),
327 ReporterTestUtils.apacheLicenseVersion2(1),
328 "^BSD: 1 ",
329 "^Creative Commons Attribution: 1 ",
330 };
331 final String[] notExpected = {
332 "^Unknown License:"
333 };
334
335 ReportConfiguration config = mojo.getConfiguration();
336
337 assertThat(config.isAddingLicenses()).isFalse();
338 assertThat(config.isAddingLicensesForced()).isFalse();
339 assertThat(config.getCopyrightMessage()).isNull();
340 assertThat(config.getStyleSheet()).withFailMessage("Stylesheet should not be null").isNotNull();
341
342 ReportConfigurationTest.validateDefaultApprovedLicenses(config, 1);
343 ReportConfigurationTest.validateDefaultLicenseFamilies(config, "BSD", "CC BY");
344 ReportConfigurationTest.validateDefaultLicenses(config, "BSD", "CC BY");
345
346 mojo.execute();
347 ensureRatReportIsCorrect(ratTxtFile, expected, notExpected);
348 }
349
350
351
352
353 @Test
354 void rat335() throws Exception {
355 final RatCheckMojo mojo = newRatMojo("RAT-335");
356 final File ratTxtFile = mojo.getRatTxtFile();
357 try {
358 mojo.execute();
359 fail("Expected RatCheckException");
360 } catch (RatCheckException e) {
361 final String msg = e.getMessage();
362 assertThat(msg).contains(ratTxtFile.getName());
363 assertThat(msg).contains("UNAPPROVED exceeded minimum");
364
365 Map<ClaimStatistic.Counter, String> data = new HashMap<>();
366 data.put(ClaimStatistic.Counter.APPROVED, "1");
367 data.put(ClaimStatistic.Counter.ARCHIVES, "0");
368 data.put(ClaimStatistic.Counter.BINARIES, "0");
369 data.put(ClaimStatistic.Counter.DOCUMENT_TYPES, "3");
370 data.put(ClaimStatistic.Counter.IGNORED, "6");
371 data.put(ClaimStatistic.Counter.LICENSE_CATEGORIES, "2");
372 data.put(ClaimStatistic.Counter.LICENSE_NAMES, "2");
373 data.put(ClaimStatistic.Counter.NOTICES, "1");
374 data.put(ClaimStatistic.Counter.STANDARDS, "5");
375 data.put(ClaimStatistic.Counter.UNAPPROVED, "4");
376 data.put(ClaimStatistic.Counter.UNKNOWN, "4");
377
378 org.w3c.dom.Document document = XmlUtils.toDom(Files.newInputStream(ratTxtFile.toPath()));
379
380 for (ClaimStatistic.Counter counter : ClaimStatistic.Counter.values()) {
381 String xpath = String.format("/rat-report/statistics/statistic[@name='%s']", counter.displayName());
382 Map<String, String> map = mapOf("approval",
383 counter == ClaimStatistic.Counter.UNAPPROVED ? "false" : "true",
384 "count", data.get(counter),
385 "description", counter.getDescription());
386 XmlUtils.assertAttributes(document, xPath, xpath, map);
387 }
388
389
390 XmlUtils.assertAttributes(document, xPath, "/rat-report/statistics/licenseCategory[@name='?????']",
391 mapOf("count", "4"));
392
393 XmlUtils.assertAttributes(document, xPath, "/rat-report/statistics/licenseCategory[@name='AL ']",
394 mapOf("count", "1"));
395
396
397 XmlUtils.assertAttributes(document, xPath, "/rat-report/statistics/licenseName[@name='Apache License 2.0']",
398 mapOf("count", "1"));
399
400 XmlUtils.assertAttributes(document, xPath, "/rat-report/statistics/licenseName[@name='Unknown license']",
401 mapOf("count", "4"));
402
403
404 XmlUtils.assertAttributes(document, xPath, "/rat-report/statistics/documentType[@name='IGNORED']",
405 mapOf("count", "6"));
406
407 XmlUtils.assertAttributes(document, xPath, "/rat-report/statistics/documentType[@name='NOTICE']",
408 mapOf("count", "1"));
409
410 XmlUtils.assertAttributes(document, xPath, "/rat-report/statistics/documentType[@name='STANDARD']",
411 mapOf("count", "5"));
412
413 List<String> ignoredFiles = new ArrayList<>(Arrays.asList(
414 "/dir1/dir1.txt",
415 "/dir1/.gitignore",
416 "/dir2/dir2.md",
417 "/dir3/dir3.log",
418 "/.gitignore",
419 "/root.md"));
420
421 NodeList nodeList = XmlUtils.getNodeList(document, xPath, "/rat-report/resource[@type='IGNORED']");
422 for (int i = 0; i < nodeList.getLength(); i++) {
423 NamedNodeMap attr = nodeList.item(i).getAttributes();
424 String s = attr.getNamedItem("name").getNodeValue();
425 assertThat(ignoredFiles).contains(s);
426 ignoredFiles.remove(s);
427 }
428 assertThat(ignoredFiles).isEmpty();
429 }
430 }
431
432
433
434
435
436
437
438
439 @Test
440 void rat362() throws Exception {
441 final RatCheckMojo mojo = newRatMojo("RAT-362");
442 final File ratTxtFile = mojo.getRatTxtFile();
443 try {
444 mojo.execute();
445 fail("Expected RatCheckException");
446 } catch (RatCheckException e) {
447 final String msg = e.getMessage();
448 assertThat(msg).contains(ratTxtFile.getName());
449 assertThat(msg).contains("UNAPPROVED exceeded minimum");
450
451 org.w3c.dom.Document document = XmlUtils.toDom(Files.newInputStream(ratTxtFile.toPath()));
452
453 XmlUtils.assertAttributes(document, xPath, "/rat-report/statistics/documentType[@name='IGNORED']",
454 "count", "3");
455
456 XmlUtils.assertAttributes(document, xPath, "/rat-report/resource[@name='/bar.md']",
457 "type", "STANDARD");
458 XmlUtils.assertAttributes(document, xPath, "/rat-report/resource[@name='/foo.md']",
459 "type", "IGNORED");
460 }
461 }
462
463
464
465
466 @Test
467 void rat107() throws Exception {
468 final RatCheckMojo mojo = newRatMojo("RAT-107");
469 final File ratTxtFile = mojo.getRatTxtFile();
470 final String[] expected = {};
471 final String[] notExpected = {};
472
473 mojo.setInputExcludeParsedScm("MAVEN");
474 mojo.setInputExcludeParsedScm("idea");
475 mojo.setInputExcludeParsedScm("eclipse");
476 mojo.execute();
477
478 ensureRatReportIsCorrect(ratTxtFile, expected, notExpected);
479 }
480 }