1 /*******************************************************************************
2  * Copyright (c) 2000, 2019 IBM Corporation and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     IBM Corporation - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.jdt.core.tests.util;
15 
16 import java.io.File;
17 import java.lang.reflect.Constructor;
18 import java.lang.reflect.InvocationTargetException;
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.List;
22 import java.util.Map;
23 
24 import junit.framework.Test;
25 import junit.framework.TestSuite;
26 
27 import org.eclipse.core.runtime.IPath;
28 import org.eclipse.core.runtime.Path;
29 import org.eclipse.jdt.core.tests.compiler.regression.RegressionTestSetup;
30 import org.eclipse.jdt.core.tests.junit.extension.TestCase;
31 import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
32 import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
33 
34 @SuppressWarnings({ "unchecked", "rawtypes" })
35 public class AbstractCompilerTest extends TestCase {
36 
37 	public static final int F_1_3 = 0x01;
38 	public static final int F_1_4 = 0x02;
39 	public static final int F_1_5 = 0x04;
40 	public static final int F_1_6 = 0x08;
41 	public static final int F_1_7 = 0x10;
42 	public static final int F_1_8 = 0x20;
43 	public static final int F_9   = 0x40;
44 	public static final int F_10  = 0x80;
45 	public static final int F_11  = 0x100;
46 	public static final int F_12  = 0x200;
47 	public static final int F_13  = 0x400;
48 	public static final int F_14  = 0x800;
49 
50 	public static final boolean RUN_JAVAC = CompilerOptions.ENABLED.equals(System.getProperty("run.javac"));
51 	private static final int UNINITIALIZED = -1;
52 	private static final int NONE = 0;
53 	private static int possibleComplianceLevels = UNINITIALIZED;
54 
55 	protected long complianceLevel;
56 	protected boolean enableAPT = false;
57 	protected static boolean isJRE9Plus = false; // Stop gap, so tests need not be run at 9, but some tests can be adjusted for JRE 9
58 	protected static boolean isJRE11Plus = false;
59 	protected static boolean isJRE12Plus = false;
60 	protected static boolean isJRE13Plus = false;
61 	protected static boolean isJRE14Plus = false;
62 	protected static boolean reflectNestedClassUseDollar;
63 
64 	/**
65 	 * Build a test suite made of test suites for all possible running VM compliances .
66 	 *
67 	 * @see #buildUniqueComplianceTestSuite(Class, long) for test suite children content.
68 	 *
69 	 * @param evaluationTestClass The main test suite to build.
70 	 * @return built test suite (see {@link TestSuite}
71 	 */
buildAllCompliancesTestSuite(Class evaluationTestClass)72 	public static Test buildAllCompliancesTestSuite(Class evaluationTestClass) {
73 		TestSuite suite = new TestSuite(evaluationTestClass.getName());
74 		buildAllCompliancesTestSuite(suite, evaluationTestClass);
75 		return suite;
76 	}
buildAllCompliancesTestSuite(TestSuite suite, Class evaluationTestClass)77 	public static void buildAllCompliancesTestSuite(TestSuite suite, Class evaluationTestClass) {
78 		int complianceLevels = AbstractCompilerTest.getPossibleComplianceLevels();
79 		if ((complianceLevels & AbstractCompilerTest.F_1_3) != 0) {
80 			suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, ClassFileConstants.JDK1_3));
81 		}
82 		if ((complianceLevels & AbstractCompilerTest.F_1_4) != 0) {
83 			suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, ClassFileConstants.JDK1_4));
84 		}
85 		if ((complianceLevels & AbstractCompilerTest.F_1_5) != 0) {
86 			suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, ClassFileConstants.JDK1_5));
87 		}
88 		if ((complianceLevels & AbstractCompilerTest.F_1_6) != 0) {
89 			suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, ClassFileConstants.JDK1_6));
90 		}
91 		if ((complianceLevels & AbstractCompilerTest.F_1_7) != 0) {
92 			suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, ClassFileConstants.JDK1_7));
93 		}
94 		if ((complianceLevels & AbstractCompilerTest.F_1_8) != 0) {
95 			suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, ClassFileConstants.JDK1_8));
96 		}
97 		if ((complianceLevels & AbstractCompilerTest.F_9) != 0) {
98 			suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, ClassFileConstants.JDK9));
99 		}
100 		if ((complianceLevels & AbstractCompilerTest.F_10) != 0) {
101 			suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, ClassFileConstants.JDK10));
102 		}
103 		if ((complianceLevels & AbstractCompilerTest.F_11) != 0) {
104 			suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, ClassFileConstants.getComplianceLevelForJavaVersion(ClassFileConstants.MAJOR_VERSION_11)));
105 		}
106 		if ((complianceLevels & AbstractCompilerTest.F_12) != 0) {
107 			suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, ClassFileConstants.getComplianceLevelForJavaVersion(ClassFileConstants.MAJOR_VERSION_12)));
108 		}
109 		if ((complianceLevels & AbstractCompilerTest.F_13) != 0) {
110 			suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, ClassFileConstants.getComplianceLevelForJavaVersion(ClassFileConstants.MAJOR_VERSION_13)));
111 		}
112 		if ((complianceLevels & AbstractCompilerTest.F_14) != 0) {
113 			suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, ClassFileConstants.getComplianceLevelForJavaVersion(ClassFileConstants.MAJOR_VERSION_14)));
114 		}
115 	}
116 
117 	/**
118 	 * Build a test suite made of test suites for all possible running VM compliances .
119 	 *
120 	 * @see #buildComplianceTestSuite(List, Class, long) for test suite children content.
121 	 *
122 	 * @param testSuiteClass The main test suite to build.
123 	 * @param setupClass The compiler setup to class to use to bundle given tets suites tests.
124 	 * @param testClasses The list of test suites to include in main test suite.
125 	 * @return built test suite (see {@link TestSuite}
126 	 */
buildAllCompliancesTestSuite(Class testSuiteClass, Class setupClass, List testClasses)127 	public static Test buildAllCompliancesTestSuite(Class testSuiteClass, Class setupClass, List testClasses) {
128 		TestSuite suite = new TestSuite(testSuiteClass.getName());
129 		int complianceLevels = AbstractCompilerTest.getPossibleComplianceLevels();
130 		if ((complianceLevels & AbstractCompilerTest.F_1_3) != 0) {
131 			suite.addTest(buildComplianceTestSuite(testClasses, setupClass, ClassFileConstants.JDK1_3));
132 		}
133 		if ((complianceLevels & AbstractCompilerTest.F_1_4) != 0) {
134 			suite.addTest(buildComplianceTestSuite(testClasses, setupClass, ClassFileConstants.JDK1_4));
135 		}
136 		if ((complianceLevels & AbstractCompilerTest.F_1_5) != 0) {
137 			suite.addTest(buildComplianceTestSuite(testClasses, setupClass, ClassFileConstants.JDK1_5));
138 		}
139 		if ((complianceLevels & AbstractCompilerTest.F_1_6) != 0) {
140 			suite.addTest(buildComplianceTestSuite(testClasses, setupClass, ClassFileConstants.JDK1_6));
141 		}
142 		if ((complianceLevels & AbstractCompilerTest.F_1_7) != 0) {
143 			suite.addTest(buildComplianceTestSuite(testClasses, setupClass, ClassFileConstants.JDK1_7));
144 		}
145 		if ((complianceLevels & AbstractCompilerTest.F_1_8) != 0) {
146 			suite.addTest(buildComplianceTestSuite(testClasses, setupClass, ClassFileConstants.JDK1_8));
147 		}
148 		if ((complianceLevels & AbstractCompilerTest.F_9) != 0) {
149 			suite.addTest(buildComplianceTestSuite(testClasses, setupClass, ClassFileConstants.JDK9));
150 		}
151 		if ((complianceLevels & AbstractCompilerTest.F_10) != 0) {
152 			suite.addTest(buildComplianceTestSuite(testClasses, setupClass, ClassFileConstants.JDK10));
153 		}
154 		if ((complianceLevels & AbstractCompilerTest.F_11) != 0) {
155 			suite.addTest(buildComplianceTestSuite(testClasses, setupClass, ClassFileConstants.getComplianceLevelForJavaVersion(ClassFileConstants.MAJOR_VERSION_11)));
156 		}
157 		if ((complianceLevels & AbstractCompilerTest.F_12) != 0) {
158 			suite.addTest(buildComplianceTestSuite(testClasses, setupClass, ClassFileConstants.getComplianceLevelForJavaVersion(ClassFileConstants.MAJOR_VERSION_12)));
159 		}
160 		if ((complianceLevels & AbstractCompilerTest.F_13) != 0) {
161 			suite.addTest(buildComplianceTestSuite(testClasses, setupClass, ClassFileConstants.getComplianceLevelForJavaVersion(ClassFileConstants.MAJOR_VERSION_13)));
162 		}
163 		if ((complianceLevels & AbstractCompilerTest.F_14) != 0) {
164 			suite.addTest(buildComplianceTestSuite(testClasses, setupClass, ClassFileConstants.getComplianceLevelForJavaVersion(ClassFileConstants.MAJOR_VERSION_14)));
165 		}
166 		return suite;
167 	}
168 
setpossibleComplianceLevels(int complianceLevel)169 	 public static void setpossibleComplianceLevels(int complianceLevel) {
170          possibleComplianceLevels = complianceLevel;
171 	 }
172 
173 	/**
174 	 * Build a test suite for a compliance and a list of test suites.
175 	 * Returned test suite has only one child: {@link RegressionTestSetup} test suite.
176 	 * Name of returned suite is the given compliance level.
177 	 *
178 	 * @see #buildComplianceTestSuite(List, Class, long) for child test suite content.
179 	 *
180 	 * @param complianceLevel The compliance level used for this test suite.
181 	 * @param testClasses The list of test suites to include in main test suite.
182 	 * @return built test suite (see {@link TestSuite}
183 	 */
buildComplianceTestSuite(long complianceLevel, List testClasses)184 	public static Test buildComplianceTestSuite(long complianceLevel, List testClasses) {
185 		return buildComplianceTestSuite(testClasses, RegressionTestSetup.class, complianceLevel);
186 	}
187 
188 	/**
189 	 * Build a test suite for a compliance and a list of test suites.
190 	 * Children of returned test suite are setup test suites (see {@link CompilerTestSetup}).
191 	 * Name of returned suite is the given compliance level.
192 	 *
193 	 * @param complianceLevel The compliance level used for this test suite.
194 	 * @param testClasses The list of test suites to include in main test suite.
195 	 * @return built test suite (see {@link TestSuite}
196 	 */
buildComplianceTestSuite(List testClasses, Class setupClass, long complianceLevel)197 	private static Test buildComplianceTestSuite(List testClasses, Class setupClass, long complianceLevel) {
198 		// call the setup constructor with the compliance level
199 		TestSuite complianceSuite = null;
200 		try {
201 			Constructor constructor = setupClass.getConstructor(new Class[]{long.class});
202 			complianceSuite = (TestSuite)constructor.newInstance(new Object[]{new Long(complianceLevel)});
203 		} catch (IllegalAccessException e) {
204 			e.printStackTrace();
205 		} catch (InstantiationException e) {
206 			e.printStackTrace();
207 		} catch (InvocationTargetException e) {
208 			e.getTargetException().printStackTrace();
209 		} catch (NoSuchMethodException e) {
210 			e.printStackTrace();
211 		}
212 		if (complianceSuite == null)
213 			return null;
214 
215 		// add tests
216 		for (int i=0, m=testClasses.size(); i<m ; i++) {
217 			Class testClass = (Class)testClasses.get(i);
218 			TestSuite suite = new TestSuite(testClass.getName());
219 			List tests = buildTestsList(testClass);
220 			for (int index=0, size=tests.size(); index<size; index++) {
221 				suite.addTest((Test)tests.get(index));
222 			}
223 			complianceSuite.addTest(suite);
224 		}
225 		return complianceSuite;
226 	}
227 
228 	/**
229 	 * Build a regression test setup suite for a minimal compliance and a test suite to run.
230 	 * Returned test suite has only one child: {@link RegressionTestSetup} test suite.
231 	 * Name of returned suite is the name of given test suite class.
232 	 * The test suite will be run iff the compliance is at least the specified one.
233 	 *
234 	 * @param minimalCompliance The unqie compliance level used for this test suite.
235 	 * @param evaluationTestClass The test suite to run.
236 	 * @return built test suite (see {@link TestSuite}
237 	 */
buildMinimalComplianceTestSuite(Class evaluationTestClass, int minimalCompliance)238 	public static Test buildMinimalComplianceTestSuite(Class evaluationTestClass, int minimalCompliance) {
239 		TestSuite suite = new TestSuite(evaluationTestClass.getName());
240 		int complianceLevels = AbstractCompilerTest.getPossibleComplianceLevels();
241 		int level13 = complianceLevels & AbstractCompilerTest.F_1_3;
242 		if (level13 != 0) {
243 			if (level13 < minimalCompliance) {
244 				System.err.println("Cannot run "+evaluationTestClass.getName()+" at compliance "+CompilerOptions.versionFromJdkLevel(ClassFileConstants.JDK1_3)+"!");
245 			} else {
246 				suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, ClassFileConstants.JDK1_3));
247 			}
248 		}
249 		int level14 = complianceLevels & AbstractCompilerTest.F_1_4;
250 		if (level14 != 0) {
251 			if (level14 < minimalCompliance) {
252 				System.err.println("Cannot run "+evaluationTestClass.getName()+" at compliance "+CompilerOptions.versionFromJdkLevel(ClassFileConstants.JDK1_4)+"!");
253 			} else {
254 				suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, ClassFileConstants.JDK1_4));
255 			}
256 		}
257 		int level15 = complianceLevels & AbstractCompilerTest.F_1_5;
258 		if (level15 != 0) {
259 			if (level15 < minimalCompliance) {
260 				System.err.println("Cannot run "+evaluationTestClass.getName()+" at compliance "+CompilerOptions.versionFromJdkLevel(ClassFileConstants.JDK1_5)+"!");
261 			} else {
262 				suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, ClassFileConstants.JDK1_5));
263 			}
264 		}
265 		int level16 = complianceLevels & AbstractCompilerTest.F_1_6;
266 		if (level16 != 0) {
267 			if (level16 < minimalCompliance) {
268 				System.err.println("Cannot run "+evaluationTestClass.getName()+" at compliance "+CompilerOptions.versionFromJdkLevel(ClassFileConstants.JDK1_6)+"!");
269 			} else {
270 				suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, ClassFileConstants.JDK1_6));
271 			}
272 		}
273 		int level17 = complianceLevels & AbstractCompilerTest.F_1_7;
274 		if (level17 != 0) {
275 			if (level17 < minimalCompliance) {
276 				System.err.println("Cannot run "+evaluationTestClass.getName()+" at compliance "+CompilerOptions.versionFromJdkLevel(ClassFileConstants.JDK1_7)+"!");
277 			} else {
278 				suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, ClassFileConstants.JDK1_7));
279 			}
280 		}
281 		int level18 = complianceLevels & AbstractCompilerTest.F_1_8;
282 		if (level18 != 0) {
283 			if (level18 < minimalCompliance) {
284 				System.err.println("Cannot run "+evaluationTestClass.getName()+" at compliance "+CompilerOptions.versionFromJdkLevel(ClassFileConstants.JDK1_8)+"!");
285 			} else {
286 				suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, ClassFileConstants.JDK1_8));
287 			}
288 		}
289 		int level19 = complianceLevels & AbstractCompilerTest.F_9;
290 		if (level19 != 0) {
291 			if (level19 < minimalCompliance) {
292 				System.err.println("Cannot run "+evaluationTestClass.getName()+" at compliance "+CompilerOptions.versionFromJdkLevel(ClassFileConstants.JDK9)+"!");
293 			} else {
294 				suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, ClassFileConstants.JDK9));
295 			}
296 		}
297 		int level10 = complianceLevels & AbstractCompilerTest.F_10;
298 		if (level10 != 0) {
299 			if (level10 < minimalCompliance) {
300 				System.err.println("Cannot run "+evaluationTestClass.getName()+" at compliance "+CompilerOptions.versionFromJdkLevel(ClassFileConstants.JDK10)+"!");
301 			} else {
302 				suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, ClassFileConstants.JDK10));
303 			}
304 		}
305 		int level11 = complianceLevels & AbstractCompilerTest.F_11;
306 		if (level11 != 0) {
307 			if (level11 < minimalCompliance) {
308 				System.err.println("Cannot run "+evaluationTestClass.getName()+" at compliance 11!");
309 			} else {
310 				suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, ClassFileConstants.getComplianceLevelForJavaVersion(ClassFileConstants.MAJOR_VERSION_11)));
311 			}
312 		}
313 		int level12 = complianceLevels & AbstractCompilerTest.F_12;
314 		if (level12 != 0) {
315 			if (level12 < minimalCompliance) {
316 				System.err.println("Cannot run "+evaluationTestClass.getName()+" at compliance 12!");
317 			} else {
318 				suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, ClassFileConstants.getComplianceLevelForJavaVersion(ClassFileConstants.MAJOR_VERSION_12)));
319 			}
320 		}
321 		int level_13 = complianceLevels & AbstractCompilerTest.F_13;
322 		if (level_13 != 0) {
323 			if (level_13 < minimalCompliance) {
324 				System.err.println("Cannot run "+evaluationTestClass.getName()+" at compliance 13!");
325 			} else {
326 				suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, ClassFileConstants.getComplianceLevelForJavaVersion(ClassFileConstants.MAJOR_VERSION_13)));
327 			}
328 		}
329 		checkCompliance(evaluationTestClass, minimalCompliance, suite, complianceLevels, AbstractCompilerTest.F_14, ClassFileConstants.MAJOR_VERSION_14, 14);
330 		return suite;
331 	}
checkCompliance(Class evaluationTestClass, int minimalCompliance, TestSuite suite, int complianceLevels, int abstractCompilerTestCompliance, int classFileConstantsVersion, int errMessageCompliance)332 	private static void checkCompliance(Class evaluationTestClass, int minimalCompliance, TestSuite suite,
333 			int complianceLevels, int abstractCompilerTestCompliance, int classFileConstantsVersion, int errMessageCompliance) {
334 		int lev = complianceLevels & abstractCompilerTestCompliance;
335 		if (lev != 0) {
336 			if (lev < minimalCompliance) {
337 				System.err.println("Cannot run "+evaluationTestClass.getName()+" at compliance" + errMessageCompliance + "!");
338 			} else {
339 				suite.addTest(buildUniqueComplianceTestSuite(evaluationTestClass, ClassFileConstants.getComplianceLevelForJavaVersion(classFileConstantsVersion)));
340 			}
341 		}
342 	}
343 
344 	/**
345 	 * Build a regression test setup suite for a compliance and a test suite to run.
346 	 * Returned test suite has only one child: {@link RegressionTestSetup} test suite.
347 	 * Name of returned suite is the name of given test suite class.
348 	 *
349 	 * @param uniqueCompliance The unique compliance level used for this test suite.
350 	 * @param evaluationTestClass The test suite to run.
351 	 * @return built test suite (see {@link TestSuite}
352 	 */
buildUniqueComplianceTestSuite(Class evaluationTestClass, long uniqueCompliance)353 	public static Test buildUniqueComplianceTestSuite(Class evaluationTestClass, long uniqueCompliance) {
354 		long highestLevel = highestComplianceLevels();
355 		if (highestLevel < uniqueCompliance) {
356 			String complianceString;
357 			if (highestLevel == ClassFileConstants.JDK10)
358 				complianceString = "10";
359 			else if (highestLevel == ClassFileConstants.JDK9)
360 				complianceString = "9";
361 			else if (highestLevel == ClassFileConstants.JDK1_8)
362 				complianceString = "1.8";
363 			else if (highestLevel == ClassFileConstants.JDK1_7)
364 				complianceString = "1.7";
365 			else if (highestLevel == ClassFileConstants.JDK1_6)
366 				complianceString = "1.6";
367 			else if (highestLevel == ClassFileConstants.JDK1_5)
368 				complianceString = "1.5";
369 			else if (highestLevel == ClassFileConstants.JDK1_4)
370 				complianceString = "1.4";
371 			else if (highestLevel == ClassFileConstants.JDK1_3)
372 				complianceString = "1.3";
373 			else {
374 				highestLevel = ClassFileConstants.getLatestJDKLevel();
375 				if (highestLevel > 0) {
376 					complianceString = CompilerOptions.versionFromJdkLevel(highestLevel);
377 				} else {
378 					complianceString = "unknown";
379 				}
380 
381 			}
382 
383 			System.err.println("Cannot run "+evaluationTestClass.getName()+" at compliance "+complianceString+"!");
384 			return new TestSuite();
385 		}
386 		TestSuite complianceSuite = new RegressionTestSetup(uniqueCompliance);
387 		List tests = buildTestsList(evaluationTestClass);
388 		for (int index=0, size=tests.size(); index<size; index++) {
389 			complianceSuite.addTest((Test)tests.get(index));
390 		}
391 		return complianceSuite;
392 	}
393 
394 	/*
395 	 * Returns the highest compliance level this VM instance can run.
396 	 */
highestComplianceLevels()397 	public static long highestComplianceLevels() {
398 		int complianceLevels = AbstractCompilerTest.getPossibleComplianceLevels();
399 		if ((complianceLevels & AbstractCompilerTest.F_14) != 0) {
400 			return ClassFileConstants.getComplianceLevelForJavaVersion(ClassFileConstants.MAJOR_VERSION_14);
401 		}
402 		if ((complianceLevels & AbstractCompilerTest.F_13) != 0) {
403 			return ClassFileConstants.getComplianceLevelForJavaVersion(ClassFileConstants.MAJOR_VERSION_13);
404 		}
405 		if ((complianceLevels & AbstractCompilerTest.F_12) != 0) {
406 			return ClassFileConstants.getComplianceLevelForJavaVersion(ClassFileConstants.MAJOR_VERSION_12);
407 		}
408 		if ((complianceLevels & AbstractCompilerTest.F_11) != 0) {
409 			return ClassFileConstants.getComplianceLevelForJavaVersion(ClassFileConstants.MAJOR_VERSION_11);
410 		}
411 		if ((complianceLevels & AbstractCompilerTest.F_10) != 0) {
412 			return ClassFileConstants.JDK10;
413 		}
414 		if ((complianceLevels & AbstractCompilerTest.F_9) != 0) {
415 			return ClassFileConstants.JDK9;
416 		}
417 		if ((complianceLevels & AbstractCompilerTest.F_1_8) != 0) {
418 			return ClassFileConstants.JDK1_8;
419 		}
420 		if ((complianceLevels & AbstractCompilerTest.F_1_7) != 0) {
421 			return ClassFileConstants.JDK1_7;
422 		}
423 		if ((complianceLevels & AbstractCompilerTest.F_1_6) != 0) {
424 			return ClassFileConstants.JDK1_6;
425 		}
426 		if ((complianceLevels & AbstractCompilerTest.F_1_5) != 0) {
427 			return ClassFileConstants.JDK1_5;
428 		}
429 		if ((complianceLevels & AbstractCompilerTest.F_1_4) != 0) {
430 			return ClassFileConstants.JDK1_4;
431 		}
432 		return ClassFileConstants.JDK1_3;
433 	}
434 
initReflectionVersion()435 	static void initReflectionVersion() {
436 		if (isJRE9Plus) {
437 			reflectNestedClassUseDollar = true;
438 			System.out.println("reflectNestedClassUseDollar="+reflectNestedClassUseDollar+" due to isJRE9Plus");
439 		} else {
440 			String version = System.getProperty("java.version");
441 			if (version.startsWith("1.8.0_")) {
442 				int build = Integer.parseInt(version.substring("1.8.0_".length()));
443 				reflectNestedClassUseDollar = build >= 171;
444 			} else if (version.startsWith("1.8.0-")) {
445 				// Some versions start with 1.8.0- but don't have build qualifier.
446 				// Just assume they are > 171 build. Nothing much can be done.
447 				reflectNestedClassUseDollar = true;
448 			} else {
449 				throw new IllegalStateException("Unrecognized Java version: "+version);
450 			}
451 			System.out.println("reflectNestedClassUseDollar="+reflectNestedClassUseDollar+" based on version="+version);
452 		}
453 	}
454 
455 	/*
456 	 * Returns the possible compliance levels this VM instance can run.
457 	 */
getPossibleComplianceLevels()458 	public static int getPossibleComplianceLevels() {
459 		if (possibleComplianceLevels == UNINITIALIZED) {
460 			String specVersion = System.getProperty("java.specification.version");
461 			isJRE14Plus = CompilerOptions.VERSION_14.equals(specVersion);
462 			isJRE13Plus = isJRE14Plus || CompilerOptions.VERSION_13.equals(specVersion);
463 			isJRE12Plus = isJRE13Plus || CompilerOptions.VERSION_12.equals(specVersion);
464 			isJRE11Plus = isJRE12Plus || CompilerOptions.VERSION_11.equals(specVersion);
465 			isJRE9Plus = isJRE11Plus || CompilerOptions.VERSION_9.equals(specVersion)
466 					||	CompilerOptions.VERSION_10.equals(specVersion);
467 			initReflectionVersion();
468 			String compliances = System.getProperty("compliance");
469 			if (compliances != null) {
470 				possibleComplianceLevels = 0;
471 				for (String compliance : compliances.split(",")) {
472 					if (CompilerOptions.VERSION_1_3.equals(compliance)) {
473 						possibleComplianceLevels |= RUN_JAVAC ? NONE : F_1_3;
474 					} else if (CompilerOptions.VERSION_1_4.equals(compliance)) {
475 						possibleComplianceLevels |= RUN_JAVAC ? NONE : F_1_4;
476 					} else if (CompilerOptions.VERSION_1_5.equals(compliance)) {
477 						possibleComplianceLevels |= F_1_5;
478 					} else if (CompilerOptions.VERSION_1_6.equals(compliance)) {
479 						possibleComplianceLevels |= F_1_6;
480 					} else if (CompilerOptions.VERSION_1_7.equals(compliance)) {
481 						possibleComplianceLevels |= F_1_7;
482 					} else if (CompilerOptions.VERSION_1_8.equals(compliance)) {
483 						possibleComplianceLevels |= F_1_8;
484 					} else if (CompilerOptions.VERSION_9.equals(compliance)) {
485 						possibleComplianceLevels |= F_9;
486 					} else if (CompilerOptions.VERSION_10.equals(compliance)) {
487 						possibleComplianceLevels |= F_10;
488 					} else if (CompilerOptions.VERSION_11.equals(compliance)) {
489 						possibleComplianceLevels |= F_11;
490 					} else if (CompilerOptions.VERSION_12.equals(compliance)) {
491 						possibleComplianceLevels |= F_12;
492 					} else if (CompilerOptions.VERSION_13.equals(compliance)) {
493 						possibleComplianceLevels |= F_13;
494 					} else if (CompilerOptions.VERSION_14.equals(compliance)) {
495 						possibleComplianceLevels |= F_14;
496 					} else {
497 						System.out.println("Ignoring invalid compliance (" + compliance + ")");
498 						System.out.print("Use one of ");
499 						System.out.print(CompilerOptions.VERSION_1_3 + ", ");
500 						System.out.print(CompilerOptions.VERSION_1_4 + ", ");
501 						System.out.print(CompilerOptions.VERSION_1_5 + ", ");
502 						System.out.print(CompilerOptions.VERSION_1_6 + ", ");
503 						System.out.print(CompilerOptions.VERSION_1_7 + ", ");
504 						System.out.print(CompilerOptions.VERSION_1_8 + ", ");
505 						System.out.print(CompilerOptions.VERSION_1_8 + ", ");
506 						System.out.print(CompilerOptions.VERSION_9 + ", ");
507 						System.out.print(CompilerOptions.VERSION_10 + ", ");
508 						System.out.print(CompilerOptions.VERSION_11 + ", ");
509 						System.out.print(CompilerOptions.VERSION_12 + ", ");
510 						System.out.print(CompilerOptions.VERSION_13 + ", ");
511 						System.out.println(CompilerOptions.VERSION_14);
512 					}
513 				}
514 				if (possibleComplianceLevels == 0) {
515 					System.out.println("Defaulting to all possible compliances");
516 					possibleComplianceLevels = UNINITIALIZED;
517 				}
518 			}
519 			if (possibleComplianceLevels == UNINITIALIZED) {
520 				if (!RUN_JAVAC) {
521 					possibleComplianceLevels = F_1_3;
522 					boolean canRun1_4 = !"1.0".equals(specVersion)
523 						&& !CompilerOptions.VERSION_1_1.equals(specVersion)
524 						&& !CompilerOptions.VERSION_1_2.equals(specVersion)
525 						&& !CompilerOptions.VERSION_1_3.equals(specVersion);
526 					if (canRun1_4) {
527 						possibleComplianceLevels |= F_1_4;
528 					}
529 					boolean canRun1_5 = canRun1_4 && !CompilerOptions.VERSION_1_4.equals(specVersion);
530 					if (canRun1_5) {
531 						possibleComplianceLevels |= F_1_5;
532 					}
533 					boolean canRun1_6 = canRun1_5 && !CompilerOptions.VERSION_1_5.equals(specVersion);
534 					if (canRun1_6) {
535 						possibleComplianceLevels |= F_1_6;
536 					}
537 					boolean canRun1_7 = canRun1_6 && !CompilerOptions.VERSION_1_6.equals(specVersion);
538 					if (canRun1_7) {
539 						possibleComplianceLevels |= F_1_7;
540 					}
541 					boolean canRun1_8 = canRun1_7 && !CompilerOptions.VERSION_1_7.equals(specVersion);
542 					if (canRun1_8) {
543 						possibleComplianceLevels |= F_1_8;
544 					}
545 					boolean canRun9 = canRun1_8 && !CompilerOptions.VERSION_1_8.equals(specVersion);
546 					if (canRun9) {
547 						possibleComplianceLevels |= F_9;
548 					}
549 					boolean canRun10 = canRun9 && !CompilerOptions.VERSION_9.equals(specVersion);
550 					if (canRun10) {
551 						possibleComplianceLevels |= F_10;
552 					}
553 					boolean canRun11 = canRun10 && !CompilerOptions.VERSION_10.equals(specVersion);
554 					if (canRun11) {
555 						possibleComplianceLevels |= F_11;
556 					}
557 					boolean canRun12 = canRun11 && !CompilerOptions.VERSION_11.equals(specVersion);
558 					if (canRun12) {
559 						possibleComplianceLevels |= F_12;
560 					}
561 					boolean canRun13 = canRun12 && !CompilerOptions.VERSION_12.equals(specVersion);
562 					if (canRun13) {
563 						possibleComplianceLevels |= F_13;
564 					}
565 					boolean canRun14 = canRun13 && !CompilerOptions.VERSION_13.equals(specVersion);
566 					if (canRun14) {
567 						possibleComplianceLevels |= F_14;
568 					}
569 				} else if ("1.0".equals(specVersion)
570 							|| CompilerOptions.VERSION_1_1.equals(specVersion)
571 							|| CompilerOptions.VERSION_1_2.equals(specVersion)
572 							|| CompilerOptions.VERSION_1_3.equals(specVersion)
573 							|| CompilerOptions.VERSION_1_4.equals(specVersion)) {
574 					possibleComplianceLevels = NONE;
575 				} else {
576 					possibleComplianceLevels = F_1_5;
577 					if (!CompilerOptions.VERSION_1_5.equals(specVersion)) {
578 						possibleComplianceLevels |= F_1_6;
579 						if (!CompilerOptions.VERSION_1_6.equals(specVersion)) {
580 							possibleComplianceLevels |= F_1_7;
581 							if (!CompilerOptions.VERSION_1_7.equals(specVersion)) {
582 								possibleComplianceLevels |= F_1_8;
583 								if (!CompilerOptions.VERSION_1_8.equals(specVersion)) {
584 									possibleComplianceLevels |= F_9;
585 									if (!CompilerOptions.VERSION_9.equals(specVersion)) {
586 										possibleComplianceLevels |= F_10;
587 										if (!CompilerOptions.VERSION_10.equals(specVersion)) {
588 											possibleComplianceLevels |= F_11;
589 											if (!CompilerOptions.VERSION_11.equals(specVersion)) {
590 												possibleComplianceLevels |= F_12;
591 												if (!CompilerOptions.VERSION_12.equals(specVersion)) {
592 													possibleComplianceLevels |= F_13;
593 													if (!CompilerOptions.VERSION_13.equals(specVersion)) {
594 														possibleComplianceLevels |= F_14;
595 													}
596 												}
597 											}
598 										}
599 									}
600 								}
601 							}
602 						}
603 					}
604 				}
605 			}
606 		}
607 		if (possibleComplianceLevels == NONE) {
608 			System.out.println("Skipping all compliances (found none compatible with run.javac=enabled).");
609 		}
610 		return possibleComplianceLevels;
611 	}
612 
613 	/*
614 	 * Returns a test suite including the tests defined by the given classes for all possible complianceLevels
615 	 * and using the given setup class (CompilerTestSetup or a subclass)
616 	 */
suite(String suiteName, Class setupClass, ArrayList testClasses)617 	public static Test suite(String suiteName, Class setupClass, ArrayList testClasses) {
618 		TestSuite all = new TestSuite(suiteName);
619 		int complianceLevels = AbstractCompilerTest.getPossibleComplianceLevels();
620 		if ((complianceLevels & AbstractCompilerTest.F_1_3) != 0) {
621 			all.addTest(suiteForComplianceLevel(ClassFileConstants.JDK1_3, setupClass, testClasses));
622 		}
623 		if ((complianceLevels & AbstractCompilerTest.F_1_4) != 0) {
624 			all.addTest(suiteForComplianceLevel(ClassFileConstants.JDK1_4, setupClass, testClasses));
625 		}
626 		if ((complianceLevels & AbstractCompilerTest.F_1_5) != 0) {
627 			all.addTest(suiteForComplianceLevel(ClassFileConstants.JDK1_5, setupClass, testClasses));
628 		}
629 		return all;
630 	}
631 
632 	/*
633 	 * Returns a test suite including the tests defined by the given classes for the given complianceLevel
634 	 * (see AbstractCompilerTest for valid values) and using the given setup class (CompilerTestSetup or a subclass)
635 	 */
suiteForComplianceLevel(long complianceLevel, Class setupClass, ArrayList testClasses)636 	public static Test suiteForComplianceLevel(long complianceLevel, Class setupClass, ArrayList testClasses) {
637 		// call the setup constructor with the compliance level
638 		TestSuite suite = null;
639 		try {
640 			Constructor constructor = setupClass.getConstructor(new Class[]{String.class});
641 			suite = (TestSuite)constructor.newInstance(new Object[]{CompilerOptions.versionFromJdkLevel(complianceLevel)});
642 		} catch (IllegalAccessException e) {
643 			e.printStackTrace();
644 		} catch (InstantiationException e) {
645 			e.printStackTrace();
646 		} catch (InvocationTargetException e) {
647 			e.getTargetException().printStackTrace();
648 		} catch (NoSuchMethodException e) {
649 			e.printStackTrace();
650 		}
651 		if (suite == null)
652 			return null;
653 
654 		// add tests
655 		Class testClass;
656 		if (testClasses.size() == 1) {
657 			suite = new TestSuite(testClass = (Class)testClasses.get(0), CompilerOptions.versionFromJdkLevel(complianceLevel));
658 			TESTS_COUNTERS.put(testClass.getName(), Integer.valueOf(suite.countTestCases()));
659 		} else {
660 			suite = new TestSuite(CompilerOptions.versionFromJdkLevel(complianceLevel));
661 			for (int i = 0, length = testClasses.size(); i < length; i++) {
662 				TestSuite innerSuite = new TestSuite(testClass = (Class)testClasses.get(i));
663 				TESTS_COUNTERS.put(testClass.getName(), Integer.valueOf(innerSuite.countTestCases()));
664 				suite.addTest(innerSuite);
665 			}
666 		}
667 		return suite;
668 	}
669 
setupSuite(Class clazz)670 	public static Test setupSuite(Class clazz) {
671 		ArrayList testClasses = new ArrayList();
672 		testClasses.add(clazz);
673 		return suite(clazz.getName(), RegressionTestSetup.class, testClasses);
674 	}
675 
buildTestSuite(Class evaluationTestClass)676 	public static Test buildTestSuite(Class evaluationTestClass) {
677 		if (TESTS_PREFIX != null || TESTS_NAMES != null || TESTS_NUMBERS!=null || TESTS_RANGE !=null) {
678 			return buildTestSuite(evaluationTestClass, highestComplianceLevels());
679 		}
680 		return setupSuite(evaluationTestClass);
681 	}
682 
buildTestSuite(Class evaluationTestClass, long complianceLevel)683 	public static Test buildTestSuite(Class evaluationTestClass, long complianceLevel) {
684 		TestSuite suite = new RegressionTestSetup(complianceLevel);
685 		List tests = buildTestsList(evaluationTestClass);
686 		for (int index=0, size=tests.size(); index<size; index++) {
687 			suite.addTest((Test)tests.get(index));
688 		}
689 		String className = evaluationTestClass.getName();
690 		Integer testsNb;
691 		int newTestsNb = suite.countTestCases();
692 		if ((testsNb = (Integer) TESTS_COUNTERS.get(className)) != null)
693 			newTestsNb += testsNb.intValue();
694 		TESTS_COUNTERS.put(className, Integer.valueOf(newTestsNb));
695 		return suite;
696 	}
697 
698 
isJRELevel(int compliance)699 	public static boolean isJRELevel(int compliance) {
700 		return (AbstractCompilerTest.getPossibleComplianceLevels() & compliance) != 0;
701 	}
702 
decorateAnnotationValueLiteral(String val)703 	public String decorateAnnotationValueLiteral(String val) {
704 		if (!isJRE9Plus) {
705 			return val;
706 		}
707 		StringBuilder builder = new StringBuilder(val);
708 		builder.insert(0, "\"");
709 		builder.append("\"");
710 		return builder.toString();
711 	}
712 
AbstractCompilerTest(String name)713 	public AbstractCompilerTest(String name) {
714 		super(name);
715 	}
716 
getCompilerOptions()717 	protected Map getCompilerOptions() {
718 		Map options = new CompilerOptions().getMap();
719 		options.put(CompilerOptions.OPTION_ReportUnusedLocal, CompilerOptions.IGNORE);
720 		if (this.complianceLevel == ClassFileConstants.JDK1_3) {
721 			options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_3);
722 			options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_3);
723 			options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_1);
724 		} else if (this.complianceLevel == ClassFileConstants.JDK1_4) {
725 			options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_4);
726 			options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_4);
727 			options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_4);
728 		} else if (this.complianceLevel == ClassFileConstants.JDK1_5) {
729 			options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_5);
730 			options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_5);
731 			options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_5);
732 		} else if (this.complianceLevel == ClassFileConstants.JDK1_6) {
733 			options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_6);
734 			options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_6);
735 			options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_6);
736 		} else if (this.complianceLevel == ClassFileConstants.JDK1_7) {
737 			options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_7);
738 			options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_7);
739 			options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_7);
740 		} else if (this.complianceLevel == ClassFileConstants.JDK1_8) {
741 			options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_8);
742 			options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_8);
743 			options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_8);
744 		} else if (this.complianceLevel == ClassFileConstants.JDK9) {
745 			options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_9);
746 			options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_9);
747 			options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_9);
748 		} else if (this.complianceLevel == ClassFileConstants.JDK10) {
749 			options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_10);
750 			options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_10);
751 			options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_10);
752 		} else {
753 			// This is already good enough to cover versions from future
754 			// (as long as versionFromJdkLevel does its job)
755 			String ver = CompilerOptions.versionFromJdkLevel(this.complianceLevel);
756 			options.put(CompilerOptions.OPTION_Compliance, ver);
757 			options.put(CompilerOptions.OPTION_Source, ver);
758 			options.put(CompilerOptions.OPTION_TargetPlatform, ver);
759 		}
760 		return options;
761 	}
762 
getName()763 	public String getName() {
764 		String name = super.getName();
765 		if (this.complianceLevel != 0) {
766 			name = name + " - " + CompilerOptions.versionFromJdkLevel(this.complianceLevel);
767 		}
768 		return name;
769 	}
770 
getVersionString(long compliance)771 	protected static String getVersionString(long compliance) {
772 		String version = "version 14 : 58.0";
773 		if (compliance < ClassFileConstants.JDK9) return "version 1.8 : 52.0";
774 		if (compliance == ClassFileConstants.JDK9) return "version 9 : 53.0";
775 		if (compliance == ClassFileConstants.JDK10) return "version 10 : 54.0";
776 		if (compliance > ClassFileConstants.JDK10) {
777 			String ver = CompilerOptions.versionFromJdkLevel(compliance);
778 			int major = Integer.parseInt(ver) + ClassFileConstants.MAJOR_VERSION_0;
779 			return "version " + ver + " : " + major + ".0";
780 		}
781 		if (compliance >= ClassFileConstants.getComplianceLevelForJavaVersion(ClassFileConstants.MAJOR_VERSION_14)) return version; // keep this stmt for search for next bump up
782 		return version;
783 	}
784 
initialize(CompilerTestSetup setUp)785 	public void initialize(CompilerTestSetup setUp) {
786 		this.complianceLevel = setUp.complianceLevel;
787 		this.enableAPT = System.getProperty("enableAPT") != null;
788 	}
789 
testName()790 	protected String testName() {
791 		return super.getName();
792 	}
793 
794 	// Output files management
795 	protected IPath outputRootDirectoryPath = new Path(Util.getOutputDirectory());
796 	protected File outputTestDirectory;
797 
798 	/**
799 	 * Create a test specific output directory as a subdirectory of
800 	 * outputRootDirectory, given a subdirectory path. The whole
801 	 * subtree is created as needed. outputTestDirectoryPath is
802 	 * modified according to the latest call to this method.
803 	 * @param suffixPath a valid relative path for the subdirectory
804 	 */
createOutputTestDirectory(String suffixPath)805 	protected void createOutputTestDirectory(String suffixPath) {
806 		this.outputTestDirectory =  new File(this.outputRootDirectoryPath.toFile(), suffixPath);
807 		if (!this.outputTestDirectory.exists()) {
808 			this.outputTestDirectory.mkdirs();
809 		}
810 	}
811 	/*
812 	 * Write given source test files in current output sub-directory.
813 	 * Use test name for this sub-directory name (ie. test001, test002, etc...)
814 	 */
writeFiles(String[] testFiles)815 	protected void writeFiles(String[] testFiles) {
816 		createOutputTestDirectory(testName());
817 
818 		// Write each given test file
819 		for (int i = 0, length = testFiles.length; i < length; ) {
820 			String fileName = testFiles[i++];
821 			String contents = testFiles[i++];
822 			File file = new File(this.outputTestDirectory, fileName);
823 			if (fileName.lastIndexOf('/') >= 0) {
824 				File dir = file.getParentFile();
825 				if (!dir.exists()) {
826 					dir.mkdirs();
827 				}
828 			}
829 			Util.writeToFile(contents, file.getPath());
830 		}
831 	}
832 
833 	// Summary display
834 	// Used by AbstractRegressionTest for javac comparison tests
835 	protected static Map TESTS_COUNTERS = new HashMap();
836 }
837