View Javadoc
1   package org.codehaus.plexus.compiler;
2   
3   /**
4    * The MIT License
5    *
6    * Copyright (c) 2004, The Codehaus
7    *
8    * Permission is hereby granted, free of charge, to any person obtaining a copy of
9    * this software and associated documentation files (the "Software"), to deal in
10   * the Software without restriction, including without limitation the rights to
11   * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12   * of the Software, and to permit persons to whom the Software is furnished to do
13   * so, subject to the following conditions:
14   *
15   * The above copyright notice and this permission notice shall be included in all
16   * copies or substantial portions of the Software.
17   *
18   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24   * SOFTWARE.
25   */
26  import javax.inject.Inject;
27  
28  import java.io.File;
29  import java.util.ArrayList;
30  import java.util.Collection;
31  import java.util.Collections;
32  import java.util.Iterator;
33  import java.util.List;
34  import java.util.Map;
35  import java.util.stream.Collectors;
36  
37  import org.apache.maven.RepositoryUtils;
38  import org.apache.maven.artifact.Artifact;
39  import org.apache.maven.artifact.DefaultArtifact;
40  import org.apache.maven.artifact.handler.DefaultArtifactHandler;
41  import org.apache.maven.artifact.versioning.VersionRange;
42  import org.codehaus.plexus.testing.PlexusTest;
43  import org.codehaus.plexus.util.FileUtils;
44  import org.codehaus.plexus.util.StringUtils;
45  import org.eclipse.aether.DefaultRepositorySystemSession;
46  import org.eclipse.aether.RepositorySystemSession;
47  import org.eclipse.aether.impl.LocalRepositoryProvider;
48  import org.eclipse.aether.repository.LocalRepository;
49  import org.eclipse.aether.repository.LocalRepositoryManager;
50  import org.hamcrest.io.FileMatchers;
51  import org.junit.jupiter.api.BeforeEach;
52  import org.junit.jupiter.api.Test;
53  
54  import static org.hamcrest.MatcherAssert.assertThat;
55  import static org.hamcrest.Matchers.containsInAnyOrder;
56  import static org.hamcrest.Matchers.is;
57  import static org.hamcrest.Matchers.notNullValue;
58  
59  /**
60   *
61   */
62  @PlexusTest
63  public abstract class AbstractCompilerTest {
64      private boolean compilerDebug = false;
65  
66      private boolean compilerDeprecationWarnings = false;
67  
68      private boolean forceJavacCompilerUse = false;
69  
70      @Inject
71      private Map<String, Compiler> compilers;
72  
73      @Inject
74      private LocalRepositoryProvider localRepositoryProvider;
75  
76      private LocalRepositoryManager localRepositoryManager;
77  
78      protected abstract String getRoleHint();
79  
80      @BeforeEach
81      final void setUpLocalRepo() throws Exception {
82          String localRepo = System.getProperty("maven.repo.local");
83          assertThat("system property maven.repo.local", localRepo, notNullValue());
84  
85          LocalRepository localRepository = new LocalRepository(localRepo);
86          assertThat(
87                  "test prerequisite: local repository path: " + localRepository.getBasedir(),
88                  localRepository.getBasedir(),
89                  FileMatchers.aReadableFile());
90  
91          RepositorySystemSession session = new DefaultRepositorySystemSession();
92          localRepositoryManager = localRepositoryProvider.newLocalRepositoryManager(session, localRepository);
93      }
94  
95      protected void setCompilerDebug(boolean flag) {
96          compilerDebug = flag;
97      }
98  
99      protected void setCompilerDeprecationWarnings(boolean flag) {
100         compilerDeprecationWarnings = flag;
101     }
102 
103     public void setForceJavacCompilerUse(boolean forceJavacCompilerUse) {
104         this.forceJavacCompilerUse = forceJavacCompilerUse;
105     }
106 
107     protected final Compiler getCompiler() {
108         return compilers.get(getRoleHint());
109     }
110 
111     protected List<String> getClasspath() throws Exception {
112         List<String> cp = new ArrayList<>();
113 
114         File file = getLocalArtifactPath("commons-lang", "commons-lang", "2.0", "jar");
115 
116         assertThat(
117                 "test prerequisite: commons-lang library must be available in local repository at " + file,
118                 file,
119                 FileMatchers.aReadableFile());
120 
121         cp.add(file.getAbsolutePath());
122 
123         return cp;
124     }
125 
126     protected void configureCompilerConfig(CompilerConfiguration compilerConfig) {}
127 
128     @Test
129     public void testCompilingSources() throws Exception {
130         List<CompilerMessage> messages = new ArrayList<>();
131         Collection<String> files = new ArrayList<>();
132 
133         for (CompilerConfiguration compilerConfig : getCompilerConfigurations()) {
134             File outputDir = new File(compilerConfig.getOutputLocation());
135 
136             messages.addAll(getCompiler().performCompile(compilerConfig).getCompilerMessages());
137 
138             if (outputDir.isDirectory()) {
139                 files.addAll(normalizePaths(FileUtils.getFileNames(outputDir, null, null, false)));
140             }
141         }
142 
143         int numCompilerErrors = compilerErrorCount(messages);
144 
145         int numCompilerWarnings = messages.size() - numCompilerErrors;
146 
147         int expectedErrors = expectedErrors();
148 
149         if (expectedErrors != numCompilerErrors) {
150             System.out.println(numCompilerErrors + " error(s) found:");
151             List<String> errors = new ArrayList<>();
152             for (CompilerMessage error : messages) {
153                 if (!error.isError()) {
154                     continue;
155                 }
156 
157                 System.out.println("----");
158                 System.out.println(error.getFile());
159                 System.out.println(error.getMessage());
160                 System.out.println("----");
161                 errors.add(error.getMessage());
162             }
163 
164             assertThat(
165                     "Wrong number of compilation errors (" + numCompilerErrors + "/" + expectedErrors //
166                             + ") : " + displayLines(errors),
167                     numCompilerErrors,
168                     is(expectedErrors));
169         }
170 
171         int expectedWarnings = expectedWarnings();
172         if (expectedWarnings != numCompilerWarnings) {
173             List<String> warnings = new ArrayList<>();
174             System.out.println(numCompilerWarnings + " warning(s) found:");
175             for (CompilerMessage error : messages) {
176                 if (error.isError()) {
177                     continue;
178                 }
179 
180                 System.out.println("----");
181                 System.out.println(error.getFile());
182                 System.out.println(error.getMessage());
183                 System.out.println("----");
184                 warnings.add(error.getMessage());
185             }
186 
187             assertThat(
188                     "Wrong number ("
189                             + numCompilerWarnings + "/" + expectedWarnings + ") of compilation warnings: "
190                             + displayLines(warnings),
191                     numCompilerWarnings,
192                     is(expectedWarnings));
193         }
194 
195         assertThat(
196                 files, containsInAnyOrder(normalizePaths(expectedOutputFiles()).toArray(new String[0])));
197     }
198 
199     protected String displayLines(List<String> warnings) {
200         // with java8 could be as simple as String.join(System.lineSeparator(), warnings)
201         StringBuilder sb = new StringBuilder(System.lineSeparator());
202         for (String warning : warnings) {
203             sb.append('-').append(warning).append(System.lineSeparator());
204         }
205         return sb.toString();
206     }
207 
208     private List<CompilerConfiguration> getCompilerConfigurations() throws Exception {
209         String sourceDir = "src/test-input/src/main";
210 
211         List<String> filenames = FileUtils.getFileNames(new File(sourceDir), "**/*.java", null, false, true);
212         Collections.sort(filenames);
213 
214         List<CompilerConfiguration> compilerConfigurations = new ArrayList<>();
215 
216         int index = 0;
217         for (Iterator<String> it = filenames.iterator(); it.hasNext(); index++) {
218             String filename = it.next();
219 
220             CompilerConfiguration compilerConfig = new CompilerConfiguration();
221 
222             compilerConfig.setDebug(compilerDebug);
223 
224             compilerConfig.setShowDeprecation(compilerDeprecationWarnings);
225 
226             compilerConfig.setClasspathEntries(getClasspath());
227 
228             compilerConfig.addSourceLocation(sourceDir);
229 
230             compilerConfig.setOutputLocation("target/" + getRoleHint() + "/classes-" + index);
231 
232             FileUtils.deleteDirectory(compilerConfig.getOutputLocation());
233 
234             compilerConfig.addInclude(filename);
235 
236             compilerConfig.setForceJavacCompilerUse(this.forceJavacCompilerUse);
237 
238             configureCompilerConfig(compilerConfig);
239 
240             String target = getTargetVersion();
241             if (StringUtils.isNotEmpty(target)) {
242                 compilerConfig.setTargetVersion(target);
243             }
244 
245             String source = getSourceVersion();
246             if (StringUtils.isNotEmpty(source)) {
247                 compilerConfig.setSourceVersion(source);
248             }
249 
250             compilerConfigurations.add(compilerConfig);
251         }
252 
253         return compilerConfigurations;
254     }
255 
256     public String getTargetVersion() {
257         return null;
258     }
259 
260     public String getSourceVersion() {
261         return null;
262     }
263 
264     private List<String> normalizePaths(Collection<String> relativePaths) {
265         return relativePaths.stream()
266                 .map(s -> s.replace(File.separatorChar, '/'))
267                 .collect(Collectors.toList());
268     }
269 
270     protected int compilerErrorCount(List<CompilerMessage> messages) {
271         int count = 0;
272 
273         for (CompilerMessage message : messages) {
274             count += message.isError() ? 1 : 0;
275         }
276 
277         return count;
278     }
279 
280     protected int expectedErrors() {
281         return 1;
282     }
283 
284     protected int expectedWarnings() {
285         return 0;
286     }
287 
288     protected Collection<String> expectedOutputFiles() {
289         return Collections.emptyList();
290     }
291 
292     protected File getLocalArtifactPath(String groupId, String artifactId, String version, String type) {
293         VersionRange versionRange = VersionRange.createFromVersion(version);
294 
295         Artifact artifact = new DefaultArtifact(
296                 groupId,
297                 artifactId,
298                 versionRange,
299                 Artifact.SCOPE_COMPILE,
300                 type,
301                 null,
302                 new DefaultArtifactHandler(type));
303 
304         return getLocalArtifactPath(artifact);
305     }
306 
307     protected String getJavaVersion() {
308 
309         String javaVersion = System.getProperty("java.version");
310         String realJavaVersion = javaVersion;
311 
312         int dotIdx = javaVersion.indexOf(".");
313         if (dotIdx > -1) {
314             int lastDot = dotIdx;
315 
316             // find the next dot, so we can trim up to this point.
317             dotIdx = javaVersion.indexOf(".", lastDot + 1);
318             if (dotIdx > lastDot) {
319                 javaVersion = javaVersion.substring(0, dotIdx);
320             }
321         }
322 
323         System.out.println("java.version is: " + realJavaVersion + "\ntrimmed java version is: " + javaVersion
324                 + "\ncomparison: \"1.5\".compareTo( \"" + javaVersion + "\" ) == " + ("1.5".compareTo(javaVersion))
325                 + "\n");
326 
327         return javaVersion;
328     }
329 
330     protected File getLocalArtifactPath(Artifact artifact) {
331         return new File(
332                 localRepositoryManager.getRepository().getBasedir(),
333                 localRepositoryManager.getPathForLocalArtifact(RepositoryUtils.toArtifact(artifact)));
334     }
335 }