| /********************************************************************** |
| * This file is part of "Object Teams Development Tooling"-Software |
| * |
| * Copyright 2004, 2014 Fraunhofer Gesellschaft, Munich, Germany, |
| * for its Fraunhofer Institute and Computer Architecture and Software |
| * Technology (FIRST), Berlin, Germany and Technical University Berlin, |
| * Germany. |
| * |
| * This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License 2.0 |
| * which accompanies this distribution, and is available at |
| * https://www.eclipse.org/legal/epl-2.0/ |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Please visit http://www.eclipse.org/objectteams for updates and contact. |
| * |
| * Contributors: |
| * Fraunhofer FIRST - Initial API and implementation |
| * Technical University Berlin - Initial API and implementation |
| **********************************************************************/ |
| package org.eclipse.objectteams.otdt.tests.compiler; |
| import java.io.File; |
| import java.io.FileNotFoundException; |
| import java.io.FileOutputStream; |
| import java.io.FileWriter; |
| import java.io.IOException; |
| import java.io.PrintWriter; |
| import java.lang.reflect.Constructor; |
| import java.lang.reflect.InvocationTargetException; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| |
| import junit.framework.Test; |
| import junit.framework.TestCase; |
| import junit.framework.TestSuite; |
| import junit.textui.TestRunner; |
| |
| import org.eclipse.core.runtime.Path; |
| import org.eclipse.jdt.core.compiler.IProblem; |
| import org.eclipse.jdt.core.tests.util.Util; |
| import org.eclipse.jdt.internal.compiler.batch.Main; |
| import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; |
| import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; |
| import org.eclipse.objectteams.otdt.core.ext.WeavingScheme; |
| import org.eclipse.objectteams.otdt.tests.ClasspathUtil; |
| |
| /** |
| * This class represents a base for testing the compiler with several files. |
| * |
| * @author Jan Wloka |
| */ |
| public class TestBase extends TestCase |
| { |
| |
| public static final String NL = "\r\n"; |
| |
| public static final String CLASS_FILE_EXTENSION = ".class"; |
| public static final String JAVA_FILE_EXTENSION = ".java"; |
| public static final String LOG_FILE_EXTENSION = ".log"; |
| |
| public static final String WORKSPACE_NAME = "testing-workspace"; |
| public static final String PROJECT_NAME = "TestProject"; |
| |
| public static final String JAVA_HOME = System.getProperty("java.home"); |
| public static final String USER_HOME = System.getProperty("user.home"); |
| |
| private WeavingScheme weavingScheme = WeavingScheme.OTDRE; // FIXME: test OTRE, too! |
| |
| public static final String JRE_JAR_PATH; |
| static { |
| String javaVersion = System.getProperty("java.version"); |
| if (javaVersion.length() > 3) { |
| javaVersion = javaVersion.substring(0, 3); |
| } |
| long jdkLevel = CompilerOptions.versionToJdkLevel(javaVersion); |
| if (jdkLevel >= ClassFileConstants.JDK9) { |
| String jreDir = Util.getJREDirectory(); |
| JRE_JAR_PATH = Util.toNativePath(jreDir + "/lib/jrt-fs.jar"); |
| } else { |
| String path = JAVA_HOME+File.separator+"lib"+File.separator+"rt.jar"; |
| if ((new File(path).exists())) { |
| JRE_JAR_PATH = path; |
| } else { |
| JRE_JAR_PATH = JAVA_HOME+File.separator+"lib"+File.separator+"vm.jar"; |
| System.err.println("TestBase: using alternate jre "+JRE_JAR_PATH); |
| } |
| } |
| } |
| |
| public static final String PROJECT_PATH = USER_HOME |
| + File.separator |
| + WORKSPACE_NAME |
| + File.separator |
| + PROJECT_NAME; |
| |
| |
| private Main _compiler; |
| private String _logFileName; |
| private File _workingDir; |
| |
| public TestBase(String testName) |
| { |
| super(testName); |
| } |
| |
| private void cleanWorkingDirectory() |
| { |
| if (!_workingDir.isDirectory()) |
| { |
| return; |
| } |
| cleanRecursively(_workingDir); |
| // File[] containedFiles = _workingDir.listFiles(); |
| // |
| // for (int idx = 0; idx < containedFiles.length; idx++) |
| // { |
| // containedFiles[idx].delete(); |
| // } |
| // |
| // _workingDir.delete(); |
| } |
| private void cleanRecursively(File file) { |
| if (file.isDirectory()) { |
| for (File child : file.listFiles()) { |
| cleanRecursively(child); |
| } |
| } |
| file.delete(); |
| } |
| |
| // -- use default options: -- |
| public void compileFile(String fname) |
| { |
| compileFile(fname, null); |
| } |
| public void compileFile(String fname, String[] classpath) |
| { |
| Map<String,String> options= new HashMap<String,String>(); |
| options.put(CompilerOptions.OPTION_Source, CompilerOptions.VERSION_1_5); |
| options.put(CompilerOptions.OPTION_Compliance, CompilerOptions.VERSION_1_5); |
| options.put(CompilerOptions.OPTION_TargetPlatform, CompilerOptions.VERSION_1_5); |
| options.put(CompilerOptions.OPTION_DocCommentSupport, CompilerOptions.ENABLED); |
| options.put(CompilerOptions.OPTION_ReportInvalidJavadoc, CompilerOptions.ERROR); |
| options.put(CompilerOptions.OPTION_ReportInvalidJavadocTags, CompilerOptions.ERROR); |
| compileFile(fname, classpath, options); |
| } |
| // -- use custom options: -- |
| public void compileFile(String fname, String[] classpath, Map options) |
| { |
| System.out.println("*************************** " |
| + this.getClass().getName() |
| +" " |
| + this.getName() |
| + " ***************************"); |
| _logFileName = fname; |
| |
| try |
| { |
| String missing; |
| if ((missing = missingClasspathEntry()) != null) |
| { |
| throw new FileNotFoundException("Missing library "+missing); |
| } |
| |
| String[] args = (classpath == null) |
| ? createClassPath(fname) |
| : classpath; |
| |
| File javaFile = new File(_workingDir.getAbsolutePath() |
| + File.separator |
| + fname |
| + JAVA_FILE_EXTENSION); |
| |
| if(!javaFile.exists()) |
| { |
| throw new FileNotFoundException("File to compile was not found!: " + _logFileName); |
| } |
| |
| _compiler = |
| new Main( |
| new PrintWriter( |
| new FileOutputStream(PROJECT_PATH |
| + File.separator |
| + _logFileName |
| + LOG_FILE_EXTENSION)), |
| new PrintWriter( |
| new FileOutputStream(PROJECT_PATH |
| + File.separator |
| + _logFileName |
| + LOG_FILE_EXTENSION)), |
| false, |
| options, |
| null); |
| |
| _compiler.compile(args); |
| } |
| catch (FileNotFoundException ex) |
| { |
| handleException(ex); |
| } |
| } |
| |
| private String missingClasspathEntry() |
| { |
| String otrePath = ClasspathUtil.getOTREPath(this.weavingScheme); |
| File otreJar = new File(otrePath); |
| File jreJar = new File(JRE_JAR_PATH); |
| |
| if (!otreJar.exists()) |
| return otrePath; |
| if (!jreJar.exists()) |
| return JRE_JAR_PATH; |
| return null; |
| } |
| |
| public void createFile(String fname, String content) |
| { |
| try |
| { |
| File pkgDir = createPackageDirectory(content); |
| File file = new File(pkgDir.getAbsolutePath() |
| + File.separator |
| + fname |
| + JAVA_FILE_EXTENSION); |
| file.deleteOnExit(); |
| |
| FileWriter writer = new FileWriter(file); |
| writer.write(content); |
| writer.close(); |
| } |
| catch (IOException ex) |
| { |
| handleException(ex); |
| } |
| } |
| |
| /** |
| * Creates a file at given relative position and all necessary directories |
| * The content of package is not evaluatet for saving location |
| * @param fname the name of the new file to create |
| * @param relPath the relative path where to store the file |
| * @param content the content |
| */ |
| public void createFileAt(String fname, String relPath, String content) |
| { |
| try |
| { |
| String curPath = _workingDir.getAbsolutePath(); |
| |
| if(relPath.trim().length() > 0) |
| { |
| curPath+= File.separator + relPath; |
| } |
| |
| File pkgDir = new File(curPath); |
| pkgDir.mkdirs(); |
| |
| File file = new File(pkgDir.getAbsolutePath() |
| + File.separator |
| + fname |
| + JAVA_FILE_EXTENSION); |
| file.deleteOnExit(); |
| |
| FileWriter writer = new FileWriter(file); |
| writer.write(content); |
| writer.close(); |
| } |
| catch (IOException ex) |
| { |
| handleException(ex); |
| } |
| } |
| |
| private File createPackageDirectory(String fileContent) throws IOException |
| { |
| String qualPkgName = getQualifiedPackageName(fileContent); |
| String dirPath = getDirectoryPath(qualPkgName); |
| |
| String curPath = _workingDir.getAbsolutePath() + File.separator + dirPath; |
| File result = new File(curPath); |
| result.mkdirs(); |
| |
| return result; |
| } |
| |
| private String getDirectoryPath(String qualPkgName) |
| { |
| if ((qualPkgName == null) || (qualPkgName.trim().length() == 0)) |
| { |
| return ""; |
| } |
| |
| if (qualPkgName.indexOf('.') == -1) |
| { |
| return qualPkgName; |
| } |
| else |
| { |
| return qualPkgName.replaceAll("[.]", File.separator); |
| } |
| } |
| |
| private String getQualifiedPackageName(String fileContent) |
| { |
| String packageKeyword = "package "; |
| |
| int pos1 = fileContent.indexOf(packageKeyword); |
| if (pos1 == -1) |
| { |
| return ""; |
| } |
| |
| int pos2 = fileContent.indexOf(';', pos1); |
| if (pos2 == -1) |
| { |
| return ""; |
| } |
| |
| |
| return fileContent.substring(pos1 + packageKeyword.length(), pos2); |
| } |
| |
| private void handleException(Exception ex) |
| { |
| System.out.println("UNCAUGHT EXCEPTION: " + ex); |
| ex.printStackTrace(System.out); |
| } |
| |
| |
| /** |
| * checks whether the compiler has proceeded without errors or warnings |
| */ |
| public boolean isCompilationSuccessful() |
| { |
| if (_compiler.globalErrorsCount != 0) |
| { |
| printAllProblems(); |
| return false; |
| } |
| else |
| { |
| File file = new File(_workingDir.getAbsolutePath() |
| + File.separator |
| + _logFileName |
| + LOG_FILE_EXTENSION); |
| file.delete(); |
| return true; |
| } |
| } |
| |
| /** |
| * checks whether the compiler has generated the expected errors and warnings, |
| * if it created more problems than specified this is OK for this method. |
| * @param problemIDs IDs of the expected errors and warnings as specified in |
| * org.eclipse.jdt.core.compiler.IProblem |
| */ |
| public boolean hasAtLeastExpectedProblems(int[] problemIDs) |
| { |
| expected: for (int i = 0; i < problemIDs.length; i++) { |
| for (int j = 0; j < _compiler.logger.globalProblems.size(); j++) { |
| if (problemIDs[i] == ((IProblem)_compiler.logger.globalProblems.get(j)).getID()) |
| continue expected; |
| } |
| printAllProblems(); |
| return false; |
| } |
| File file = new File(_workingDir.getAbsolutePath() |
| + File.separator |
| + _logFileName |
| + LOG_FILE_EXTENSION); |
| file.delete(); |
| return true; |
| } |
| |
| /** |
| * checks whether the compiler has generated the expected errors and warnings |
| * @param problemIDs IDs of the expected errors and warnings as specified in |
| * org.eclipse.jdt.core.compiler.IProblem |
| */ |
| public boolean hasExpectedProblems(int[] problemIDs) |
| { |
| if ( areProblemsEqual(_compiler.logger.globalProblems, problemIDs) ) |
| { |
| File file = new File(_workingDir.getAbsolutePath() |
| + File.separator |
| + _logFileName |
| + LOG_FILE_EXTENSION); |
| file.delete(); |
| |
| return true; |
| } |
| else |
| { |
| printAllProblems(); |
| return false; |
| } |
| } |
| |
| private void printAllProblems() |
| { |
| for (Iterator iter = _compiler.logger.globalProblems.iterator(); iter.hasNext();) |
| { |
| IProblem prob = (IProblem)iter.next(); |
| System.err.println(prob.toString()); |
| if (prob.getID() == IProblem.Unclassified) // it was an exception. |
| throw new InternalError(prob.toString()); |
| } |
| } |
| |
| /** |
| * checks whether the compiler has generated the expected errors and warnings |
| * @param errorIDs IDs of the expected errors as specified in |
| * org.eclipse.jdt.core.compiler.IProblem |
| * @param warningIDs analogous |
| */ |
| public boolean hasExpectedProblems(int[] errorIDs, int[] warningIDs) |
| { |
| if ( areProblemsEqual(_compiler.logger.globalErrors, errorIDs) |
| && areProblemsEqual(_compiler.logger.globalWarnings, warningIDs) ) |
| { |
| |
| File file = new File(_workingDir.getAbsolutePath() |
| + File.separator |
| + _logFileName |
| + LOG_FILE_EXTENSION); |
| file.delete(); |
| |
| return true; |
| } |
| else |
| { |
| return false; |
| } |
| } |
| |
| |
| /** |
| * @param problems Vector elements of type IProblem |
| */ |
| private boolean areProblemsEqual(List problems, int[] problemIDs) |
| { |
| if ( problemIDs == null) |
| { |
| return problems.isEmpty(); |
| } |
| |
| boolean result = true; |
| |
| if (problems.size() != problemIDs.length) |
| { |
| result = false; |
| } |
| for (Iterator iter = problems.iterator(); result && iter.hasNext();) |
| { |
| IProblem curProblem = (IProblem) iter.next(); |
| int curProblemID = curProblem.getID(); |
| |
| boolean found = false; |
| int idx = 0; |
| |
| while (!found && (idx < problemIDs.length)) |
| { |
| if (curProblemID == problemIDs[idx]) |
| { |
| found = true; |
| } |
| idx++; |
| } |
| if (!found) |
| { |
| result = false; |
| } |
| } |
| return result; |
| } |
| |
| // public boolean isCompilationSuccessful(int errors, int warnings) |
| // { |
| // if (_compiler.globalErrorsCount != errors |
| // || _compiler.globalProblemsCount > (errors + warnings) |
| // || _compiler.globalWarningsCount != warnings) |
| // { |
| // return false; |
| // } |
| // else |
| // { |
| // // TODO (SH): check whether we have the expected problems. |
| // File file = new File(_workingDir.getAbsolutePath() |
| // + File.separator |
| // + _logFileName |
| // + LOG_FILE_EXTENSION); |
| // file.delete(); |
| // |
| // return true; |
| // } |
| // } |
| |
| |
| private String[] createClassPath(String fname) |
| { |
| File javaFile = new File(_workingDir.getAbsolutePath() |
| + File.separator |
| + fname |
| + JAVA_FILE_EXTENSION); |
| |
| String[] args = |
| { |
| "-classpath", |
| new Path(ClasspathUtil.getOTREPath(this.weavingScheme)).toString() |
| + File.pathSeparator |
| + new Path(JRE_JAR_PATH).toString() |
| + File.pathSeparator |
| + new Path(_workingDir.getAbsolutePath() |
| + File.separator).toString(), |
| javaFile.getAbsolutePath() |
| }; |
| |
| return args; |
| } |
| |
| protected String[] createClassPathNoOTRE(String fname) |
| { |
| File javaFile = new File(_workingDir.getAbsolutePath() |
| + File.separator |
| + fname |
| + JAVA_FILE_EXTENSION); |
| |
| String[] args = |
| { |
| "-classpath", |
| new Path(JRE_JAR_PATH).toString() |
| + File.pathSeparator |
| + new Path(_workingDir.getAbsolutePath() |
| + File.separator).toString(), |
| javaFile.getAbsolutePath() |
| }; |
| |
| return args; |
| } |
| |
| |
| protected void setUp() throws Exception |
| { |
| _workingDir = new File(PROJECT_PATH); |
| cleanWorkingDirectory(); |
| _workingDir.mkdirs(); |
| } |
| |
| protected void tearDown() throws Exception |
| { |
| |
| } |
| |
| /** |
| * This method was added for convenient testing of single testmethods in testclasses. |
| * The first commandline argument is expected to be the class where the |
| * testmethod can be found. The following arguments are the testmethodnames |
| * that should run. |
| * example: |
| * java Testbase org.eclipse.objectteams.otdt.tests.compiler.errorreporting.compiler.CalloutBindingTest testMultipleCalloutBinding1 |
| * @param args |
| * @throws ClassNotFoundException |
| * @throws SecurityException |
| * @throws NoSuchMethodException |
| * @throws IllegalArgumentException |
| * @throws InstantiationException |
| * @throws IllegalAccessException |
| * @throws InvocationTargetException |
| */ |
| |
| public static void main(String[] args) throws ClassNotFoundException, SecurityException, NoSuchMethodException, IllegalArgumentException, InstantiationException, IllegalAccessException, InvocationTargetException |
| { |
| TestSuite selected = null; |
| Constructor clsConst =null; |
| |
| switch (args.length) |
| { |
| case 0: |
| { |
| System.err.println("You must specify the class containing the testcases as argument."); |
| System.exit(1); |
| break; // duh |
| } |
| |
| case 1: // take all methods |
| { |
| Class testClass = Class.forName(args[0]); |
| selected = new TestSuite(testClass); |
| break; |
| } |
| |
| default: // single methods to execute given |
| { |
| Class<?> testClass = Class.forName(args[0]); |
| clsConst = testClass.getConstructor( new Class<?>[] { String.class } ); |
| selected = new TestSuite(); |
| |
| for (int idx = 1; idx < args.length; idx++) |
| { |
| selected.addTest((Test)clsConst.newInstance( new Object[] { args[idx] } )); |
| } |
| } |
| } |
| |
| TestRunner.run(selected); |
| } |
| } |