View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one   *
3    * or more contributor license agreements.  See the NOTICE file *
4    * distributed with this work for additional information        *
5    * regarding copyright ownership.  The ASF licenses this file   *
6    * to you under the Apache License, Version 2.0 (the            *
7    * "License"); you may not use this file except in compliance   *
8    * with the License.  You may obtain a copy of the License at   *
9    *                                                              *
10   *   http://www.apache.org/licenses/LICENSE-2.0                 *
11   *                                                              *
12   * Unless required by applicable law or agreed to in writing,   *
13   * software distributed under the License is distributed on an  *
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
15   * KIND, either express or implied.  See the License for the    *
16   * specific language governing permissions and limitations      *
17   * under the License.                                           *
18   */
19  package org.apache.rat.analysis;
20  
21  import static org.assertj.core.api.Assertions.assertThat;
22  
23  import java.io.ByteArrayInputStream;
24  import java.nio.charset.StandardCharsets;
25  import java.util.ArrayList;
26  import java.util.Arrays;
27  import java.util.Collection;
28  import java.util.HashMap;
29  import java.util.List;
30  import java.util.Map;
31  
32  import java.util.stream.Collectors;
33  import java.util.stream.Stream;
34  import org.apache.rat.Defaults;
35  import org.apache.rat.ReportConfiguration;
36  import org.apache.rat.api.Document;
37  import org.apache.rat.document.DocumentAnalyser;
38  import org.apache.rat.document.RatDocumentAnalysisException;
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.license.LicenseSetFactory.LicenseFilter;
43  import org.apache.rat.testhelpers.TestingLicense;
44  import org.apache.rat.testhelpers.TestingDocument;
45  import org.apache.rat.testhelpers.TestingMatcher;
46  import org.apache.rat.utils.DefaultLog;
47  import org.apache.rat.utils.Log;
48  import org.junit.jupiter.params.ParameterizedTest;
49  import org.junit.jupiter.params.provider.Arguments;
50  import org.junit.jupiter.params.provider.MethodSource;
51  
52  /**
53   * Tests the Default policy implementation.
54   */
55  public class DocumentAnalyserTest {
56  
57      private Document document;
58  
59      private void assertApproval(boolean state) {
60          if (state) {
61              assertThat(document.getMetaData().approvedLicenses().findAny()).isPresent();
62          } else {
63              assertThat(document.getMetaData().approvedLicenses().findAny()).isNotPresent();
64          }
65      }
66  
67      private void setMetadata(Document document, ILicenseFamily family) {
68          document.getMetaData().reportOnLicense(new TestingLicense(family.getFamilyCategory().trim(), new TestingMatcher(), family));
69      }
70  
71      private static ILicenseFamily makeFamily(String category, String name) {
72          return ILicenseFamily.builder().setLicenseFamilyCategory(category).setLicenseFamilyName(name).build();
73      }
74  
75      private Collection<String> asCategories(Collection<ILicenseFamily> families) {
76          return families.stream().map(ILicenseFamily::getFamilyCategory).collect(Collectors.toList());
77      }
78  
79      @ParameterizedTest(name = "{index} {0}")
80      @MethodSource("defaultAnalyserTestData")
81      void licenseSetFactoryTest(String name, ReportConfiguration configuration,
82                               Map<LicenseFilter, Collection<ILicenseFamily>> licenseFamilies,
83                               Map<LicenseFilter, Collection<ILicense>> licenses
84      ) {
85          DefaultLog.getInstance().log(Log.Level.DEBUG, "Running " + name);
86          LicenseSetFactory factory = configuration.getLicenseSetFactory();
87  
88          Collection<String> categories = asCategories(licenseFamilies.get(LicenseFilter.APPROVED));
89          assertThat(factory.getLicenseCategories(LicenseFilter.APPROVED)).containsExactlyInAnyOrderElementsOf(categories);
90          categories = asCategories(licenseFamilies.get(LicenseFilter.ALL));
91          assertThat(factory.getLicenseCategories(LicenseFilter.ALL)).containsExactlyInAnyOrderElementsOf(categories);
92          assertThat(factory.getLicenseCategories(LicenseFilter.NONE)).isEmpty();
93  
94          assertThat(factory.getLicenseFamilies(LicenseFilter.APPROVED)).containsExactlyInAnyOrderElementsOf(licenseFamilies.get(LicenseFilter.APPROVED));
95          assertThat(factory.getLicenseFamilies(LicenseFilter.ALL)).containsExactlyInAnyOrderElementsOf(licenseFamilies.get(LicenseFilter.ALL));
96          assertThat(factory.getLicenseFamilies(LicenseFilter.NONE)).isEmpty();
97  
98          assertThat(factory.getLicenses(LicenseFilter.APPROVED)).containsExactlyInAnyOrderElementsOf(licenses.get(LicenseFilter.APPROVED));
99          assertThat(factory.getLicenses(LicenseFilter.ALL)).containsExactlyInAnyOrderElementsOf(licenses.get(LicenseFilter.ALL));
100         assertThat(factory.getLicenses(LicenseFilter.NONE)).isEmpty();
101     }
102 
103     @ParameterizedTest(name = "{index} {0}")
104     @MethodSource("defaultAnalyserTestData")
105     void analyserTest(String name, ReportConfiguration configuration,
106                              Map<LicenseFilter, Collection<ILicenseFamily>> licenseFamilies,
107                              Map<LicenseFilter, Collection<ILicense>> licenses
108     ) throws RatDocumentAnalysisException {
109         DefaultLog.getInstance().log(Log.Level.DEBUG, "Running " + name);
110         DocumentAnalyser analyser = AnalyserFactory.createConfiguredAnalyser(configuration);
111 
112         // verify approved license families report approved.
113         for (ILicenseFamily family : licenseFamilies.get(LicenseFilter.APPROVED)) {
114             document = new TestingDocument(() -> new ByteArrayInputStream("Hello World".getBytes(StandardCharsets.UTF_8)), "subject");
115             setMetadata(document, family);
116             analyser.analyse(document);
117             assertApproval(true);
118         }
119 
120         // verify licenses report approved as per the licenses argument
121         for (ILicense license : licenses.get(LicenseFilter.ALL)) {
122             document = new TestingDocument(() -> new ByteArrayInputStream("Hello World".getBytes(StandardCharsets.UTF_8)), "subject");
123             document.getMetaData().reportOnLicense(license);
124             analyser.analyse(document);
125             assertApproval(licenses.get(LicenseFilter.APPROVED).contains(license));
126         }
127 
128         // verify that the unknown license is not approved.
129         document = new TestingDocument(() -> new ByteArrayInputStream("Hello World".getBytes(StandardCharsets.UTF_8)), "subject");
130         setMetadata(document, makeFamily("?????", "Unknown document"));
131         analyser.analyse(document);
132         assertApproval(false);
133 
134         // verify that the standard document without a license detected is not approved.
135         document = new TestingDocument(() -> new ByteArrayInputStream("Hello World".getBytes(StandardCharsets.UTF_8)), "subject");
136         document.getMetaData().setDocumentType(Document.Type.STANDARD);
137         analyser.analyse(document);
138         assertApproval(false);
139     }
140 
141     private static List<ILicenseFamily> defaultApprovedLicenseFamilies() {
142         return Arrays.asList(
143                 ILicenseFamily.builder().setLicenseFamilyCategory("AL").setLicenseFamilyName("Apache License Version 2.0").build(),
144                 ILicenseFamily.builder().setLicenseFamilyCategory("CDDL1").setLicenseFamilyName("COMMON DEVELOPMENT AND DISTRIBUTION LICENSE Version 1.0").build(),
145                 ILicenseFamily.builder().setLicenseFamilyCategory("MIT").setLicenseFamilyName("The MIT License").build(),
146                 ILicenseFamily.builder().setLicenseFamilyCategory("OASIS").setLicenseFamilyName("OASIS Open License").build(),
147                 ILicenseFamily.builder().setLicenseFamilyCategory("W3C").setLicenseFamilyName("W3C Software Copyright").build(),
148                 ILicenseFamily.builder().setLicenseFamilyCategory("W3CD").setLicenseFamilyName("W3C Document Copyright").build(),
149                 ILicenseFamily.builder().setLicenseFamilyCategory("BSD-3").setLicenseFamilyName("BSD 3 clause").build()
150         );
151     }
152 
153     private static List<ILicenseFamily> defaultAllLicenseFamilies() {
154         List<ILicenseFamily> result = new ArrayList<>(defaultApprovedLicenseFamilies());
155         result.add(ILicenseFamily.builder().setLicenseFamilyCategory("GPL").setLicenseFamilyName("GNU General Public License family").build());
156         return result;
157     }
158 
159     private static List<ILicense> defaultApprovedLicenses() {
160         return Arrays.asList(
161                 new TestingLicense("AL", "AL"),
162                 new TestingLicense("AL", "ASL"),
163                 new TestingLicense("BSD-3", "BSD-3"),
164                 new TestingLicense("BSD-3", "DOJO"),
165                 new TestingLicense("BSD-3", "TMF"),
166                 new TestingLicense("CDDL1", "CDDL1"),
167                 new TestingLicense("CDDL1", "ILLUMOS"),
168                 new TestingLicense("MIT", "MIT"),
169                 new TestingLicense("OASIS", "OASIS"),
170                 new TestingLicense("W3C", "W3C"),
171                 new TestingLicense("W3CD", "W3CD")
172         );
173     }
174 
175     private static List<ILicense> defaultAllLicenses() {
176         List<ILicense> result = new ArrayList<>(defaultApprovedLicenses());
177         result.addAll(Arrays.asList(new TestingLicense("GPL", "GPL1"),
178                 new TestingLicense("GPL", "GPL2"),
179                 new TestingLicense("GPL", "GPL3")));
180         return result;
181     }
182 
183     private static Stream<Arguments> defaultAnalyserTestData() {
184         List<Arguments> lst = new ArrayList<>();
185         Defaults defaults = Defaults.builder().build();
186 
187         ReportConfiguration config = new ReportConfiguration();
188         config.setFrom(defaults);
189 
190         // default setup
191         Map<LicenseFilter, Collection<ILicenseFamily>> licenseFamilies = new HashMap<>();
192         licenseFamilies.put(LicenseFilter.APPROVED, defaultApprovedLicenseFamilies());
193         licenseFamilies.put(LicenseFilter.ALL, defaultAllLicenseFamilies());
194 
195         Map<LicenseFilter, Collection<ILicense>> licenses = new HashMap<>();
196         licenses.put(LicenseFilter.APPROVED, defaultApprovedLicenses());
197         licenses.put(LicenseFilter.ALL, defaultAllLicenses());
198 
199         lst.add(Arguments.of("default", config, licenseFamilies, licenses));
200 
201         // GPL approved license id
202         config = new ReportConfiguration();
203         config.setFrom(defaults);
204         config.addApprovedLicenseId("GPL1");
205 
206         licenseFamilies = new HashMap<>();
207         licenseFamilies.put(LicenseFilter.APPROVED, defaultApprovedLicenseFamilies());
208         licenseFamilies.put(LicenseFilter.ALL, defaultAllLicenseFamilies());
209 
210         licenses = new HashMap<>();
211         List<ILicense> approvedLicenses = new ArrayList<>(defaultApprovedLicenses());
212         approvedLicenses.add(new TestingLicense("GPL", "GPL1"));
213         licenses.put(LicenseFilter.APPROVED, approvedLicenses);
214         licenses.put(LicenseFilter.ALL, defaultAllLicenses());
215 
216         lst.add(Arguments.of("GPL1 id added ", config, licenseFamilies, licenses));
217 
218         // GPL family added
219         config = new ReportConfiguration();
220         config.setFrom(defaults);
221         config.addApprovedLicenseCategory(ILicenseFamily.makeCategory("GPL"));
222 
223         licenseFamilies = new HashMap<>();
224         licenseFamilies.put(LicenseFilter.APPROVED, defaultAllLicenseFamilies());
225         licenseFamilies.put(LicenseFilter.ALL, defaultAllLicenseFamilies());
226 
227         licenses = new HashMap<>();
228         approvedLicenses = new ArrayList<>(defaultApprovedLicenses());
229         approvedLicenses.addAll(Arrays.asList(new TestingLicense("GPL", "GPL1"),
230                 new TestingLicense("GPL", "GPL2"),
231                 new TestingLicense("GPL", "GPL3")));
232         licenses.put(LicenseFilter.APPROVED, approvedLicenses);
233         licenses.put(LicenseFilter.ALL, defaultAllLicenses());
234 
235         lst.add(Arguments.of("GPL family added", config, licenseFamilies, licenses));
236 
237         // Add new license
238         config = new ReportConfiguration();
239         config.setFrom(defaults);
240         ILicense newLicense = new TestingLicense("FAM", "Testing");
241         config.addLicense(newLicense);
242 
243         licenseFamilies = new HashMap<>();
244         licenseFamilies.put(LicenseFilter.APPROVED, defaultApprovedLicenseFamilies());
245         ArrayList<ILicenseFamily> allFamilies = new ArrayList<>(defaultAllLicenseFamilies());
246         allFamilies.add(newLicense.getLicenseFamily());
247         licenseFamilies.put(LicenseFilter.ALL, allFamilies);
248 
249         licenses = new HashMap<>();
250         licenses.put(LicenseFilter.APPROVED, defaultApprovedLicenses());
251         ArrayList<ILicense> allLicenses = new ArrayList<>(defaultAllLicenses());
252         allLicenses.add(newLicense);
253         licenses.put(LicenseFilter.ALL, allLicenses);
254 
255         lst.add(Arguments.of("Testing license added", config, licenseFamilies, licenses));
256 
257         // Add new license approved by id
258         config = new ReportConfiguration();
259         config.setFrom(defaults);
260         newLicense = new TestingLicense("FAM", "Testing");
261         config.addLicense(newLicense);
262         config.addApprovedLicenseId(newLicense.getId());
263 
264         licenseFamilies = new HashMap<>();
265         licenseFamilies.put(LicenseFilter.APPROVED, defaultApprovedLicenseFamilies());
266         allFamilies = new ArrayList<>(defaultAllLicenseFamilies());
267         allFamilies.add(newLicense.getLicenseFamily());
268         licenseFamilies.put(LicenseFilter.ALL, allFamilies);
269 
270         licenses = new HashMap<>();
271 
272         approvedLicenses = new ArrayList<>(defaultApprovedLicenses());
273         approvedLicenses.add(newLicense);
274         licenses.put(LicenseFilter.APPROVED, approvedLicenses);
275         allLicenses = new ArrayList<>(defaultAllLicenses());
276         allLicenses.add(newLicense);
277         licenses.put(LicenseFilter.ALL, allLicenses);
278 
279         lst.add(Arguments.of("Testing license id approved", config, licenseFamilies, licenses));
280 
281         // Add new license approved by family
282         config = new ReportConfiguration();
283         config.setFrom(defaults);
284         newLicense = new TestingLicense("FAM", "Testing");
285         config.addLicense(newLicense);
286         config.addApprovedLicenseCategory(newLicense.getLicenseFamily());
287 
288         licenseFamilies = new HashMap<>();
289         ArrayList<ILicenseFamily> approvedFamilies = new ArrayList<>(defaultApprovedLicenseFamilies());
290         approvedFamilies.add(newLicense.getLicenseFamily());
291         licenseFamilies.put(LicenseFilter.APPROVED, approvedFamilies);
292         allFamilies = new ArrayList<>(defaultAllLicenseFamilies());
293         allFamilies.add(newLicense.getLicenseFamily());
294         licenseFamilies.put(LicenseFilter.ALL, allFamilies);
295 
296         licenses = new HashMap<>();
297         approvedLicenses = new ArrayList<>(defaultApprovedLicenses());
298         approvedLicenses.add(newLicense);
299         licenses.put(LicenseFilter.APPROVED, approvedLicenses);
300         allLicenses = new ArrayList<>(defaultAllLicenses());
301         allLicenses.add(newLicense);
302         licenses.put(LicenseFilter.ALL, allLicenses);
303 
304         lst.add(Arguments.of("Testing license family approved", config, licenseFamilies, licenses));
305 
306         return lst.stream();
307     }
308 
309     @ParameterizedTest(name = "{index} {0}")
310     @MethodSource("nonStandardDocumentData")
311     void testNonStandardDocumentsDoNotFailLicenseTests(Document.Type expected, Document document) throws RatDocumentAnalysisException {
312         Defaults defaults = Defaults.builder().build();
313         ReportConfiguration config = new ReportConfiguration();
314         config.setFrom(defaults);
315 
316         DocumentAnalyser analyser = AnalyserFactory.createConfiguredAnalyser(config);
317         analyser.analyse(document);
318         assertThat(document.getMetaData().getDocumentType()).isEqualTo(expected);
319         assertThat(document.getMetaData().licenses()).hasSize(0);
320     }
321     
322     private static Stream<Arguments> nonStandardDocumentData() {
323         List<Arguments> lst = new ArrayList<>();
324 
325         lst.add(Arguments.of(Document.Type.NOTICE, new TestingDocument(() -> new ByteArrayInputStream("Hello World".getBytes(StandardCharsets.UTF_8)), "NOTICE")));
326         byte[] zipMagic = new byte[]{0x50, 0x4B, 0x03, 0x06};
327         lst.add(Arguments.of(Document.Type.ARCHIVE, new TestingDocument(() -> new ByteArrayInputStream(zipMagic), "example.zip")));
328         byte[] gifMagic = new byte[]{0x47, 0x49, 0x46, 0x38, 0x37, 0x61};
329         lst.add(Arguments.of(Document.Type.BINARY, new TestingDocument(() -> new ByteArrayInputStream(gifMagic), "example.gif")));
330         lst.add(Arguments.of(Document.Type.IGNORED, new TestingDocument(() -> new ByteArrayInputStream("THIS FILE IS AUTOMATICALLY GENERATED".getBytes(StandardCharsets.UTF_8)), "example.ignored")));
331         return lst.stream();
332     }
333 }