diff options
author | Andy Clement <aclement@pivotal.io> | 2019-01-29 16:44:10 -0800 |
---|---|---|
committer | Andy Clement <aclement@pivotal.io> | 2019-01-29 16:44:10 -0800 |
commit | e770fb965370b4c4daf15b3e0f03b8ce77f75c0c (patch) | |
tree | af49d0213905fa98f9801e6fbb4327b4bb1ac22c /ajde.core/src/test | |
parent | c17032a561dc4b7643c2d1ee667482c18093b6df (diff) | |
download | aspectj-e770fb965370b4c4daf15b3e0f03b8ce77f75c0c.tar.gz aspectj-e770fb965370b4c4daf15b3e0f03b8ce77f75c0c.zip |
mavenizing ajde.core - done
Diffstat (limited to 'ajde.core/src/test')
19 files changed, 3694 insertions, 0 deletions
diff --git a/ajde.core/src/test/java/org/aspectj/ajde/core/AjdeCoreTestCase.java b/ajde.core/src/test/java/org/aspectj/ajde/core/AjdeCoreTestCase.java new file mode 100644 index 000000000..052d547c6 --- /dev/null +++ b/ajde.core/src/test/java/org/aspectj/ajde/core/AjdeCoreTestCase.java @@ -0,0 +1,150 @@ +/******************************************************************** + * Copyright (c) 2007 Contributors. All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://eclipse.org/legal/epl-v10.html + * + * Contributors: IBM Corporation - initial API and implementation + * Helen Hawkins - initial version + *******************************************************************/ +package org.aspectj.ajde.core; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import junit.framework.AssertionFailedError; +import junit.framework.TestCase; + +import org.aspectj.ajde.core.TestMessageHandler.TestMessage; +import org.aspectj.testing.util.TestUtil; + +/** + * Testcase class to be used by all ajde.core tests. Provides helper methods to set up the environment in a sandbox as well as to + * drive a build. + */ +public abstract class AjdeCoreTestCase extends TestCase { + + public final static String testdataSrcDir = "../ajde.core/testdata"; + protected static File sandboxDir; + + private String projectDir; + private AjCompiler compiler; + + protected void setUp() throws Exception { + super.setUp(); + // Create a sandbox in which to work + sandboxDir = TestUtil.createEmptySandbox(); + // AMC - added this next line as a temporary workaround for + // listener leakage in AsmManager induced by the Ajde test suite. + // AsmManager.getDefault().removeAllListeners(); + } + + protected void tearDown() throws Exception { + super.tearDown(); + compiler.clearLastState(); + compiler = null; + } + + /** + * Fill in the working directory with the project files and creates a compiler instance for this project + */ + public void initialiseProject(String projectName) throws IOException { + File projectSrc = new File(testdataSrcDir + File.separatorChar + projectName); + File destination = new File(getWorkingDir(), projectName); + if (!destination.exists()) { + destination.mkdir(); + } + copy(projectSrc, destination); + projectDir = destination.getCanonicalPath();// getAbsolutePath(); + + compiler = new AjCompiler(projectDir, new TestCompilerConfiguration(projectDir), new TestBuildProgressMonitor(), + new TestMessageHandler()); + } + + /** + * @return the working directory + */ + protected File getWorkingDir() { + return sandboxDir; + } + + /** + * @return the absolute path of the project directory for example c:\temp\ajcSandbox\ajcTest15200.tmp\myProject + */ + protected String getAbsoluteProjectDir() { + return projectDir; + } + + /** + * Copy the contents of some directory to another location - the copy is recursive. + */ + private void copy(File from, File to) { + String contents[] = from.list(); + if (contents == null) + return; + for (int i = 0; i < contents.length; i++) { + String string = contents[i]; + File f = new File(from, string); + File t = new File(to, string); + + if (f.isDirectory()) { + t.mkdir(); + copy(f, t); + } else if (f.isFile()) { + try { + org.aspectj.util.FileUtil.copyFile(f, t); + } catch (IOException e) { + throw new AssertionFailedError("Unable to copy " + f + " to " + t); + } + } + } + } + + protected File openFile(String path) { + return new File(projectDir + File.separatorChar + path); + } + + public void doBuild() { + doBuild(true); + } + + public void doBuild(boolean buildFresh) { + if (buildFresh) { + compiler.buildFresh(); + } else { + compiler.build(); + } + } + + public AjCompiler getCompiler() { + return compiler; + } + + public boolean checkFor(String what) { + List<TestMessage> ll = ((TestMessageHandler) compiler.getMessageHandler()).getMessages(); + for (TestMessage element: ll) { + if (element.toString().indexOf(what) != -1) + return true; + } + return false; + } + + public void dumpTaskData() { + List<TestMessage> ll = ((TestMessageHandler) compiler.getMessageHandler()).getMessages(); + for (TestMessage element: ll) { + System.out.println("RecordedMessage>" + element); + } + } + + public List<String> getSourceFileList(String[] files) { + List<String> sourceFiles = new ArrayList<String>(); + for (int i = 0; i < files.length; i++) { + sourceFiles.add(getAbsoluteProjectDir() + File.separator + files[i]); + } + return sourceFiles; + } + +} diff --git a/ajde.core/src/test/java/org/aspectj/ajde/core/TestBuildProgressMonitor.java b/ajde.core/src/test/java/org/aspectj/ajde/core/TestBuildProgressMonitor.java new file mode 100644 index 000000000..2a293b626 --- /dev/null +++ b/ajde.core/src/test/java/org/aspectj/ajde/core/TestBuildProgressMonitor.java @@ -0,0 +1,91 @@ +/******************************************************************** + * Copyright (c) 2007 Contributors. All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://eclipse.org/legal/epl-v10.html + * + * Contributors: IBM Corporation - initial API and implementation + * Helen Hawkins - initial version + *******************************************************************/ +package org.aspectj.ajde.core; + +import java.util.ArrayList; +import java.util.List; + +/** + * Test implementation of IBuildProgressMonitor which prints out + * progress to the console and enables users to cancel the build process + * after a specified string has been printed. + */ +public class TestBuildProgressMonitor implements IBuildProgressMonitor { + + private static boolean debugTests = false; + + public int numWovenClassMessages = 0; + public int numWovenAspectMessages = 0; + public int numCompiledMessages = 0; + + private String programmableString; + private int count; + private List<String> messagesReceived = new ArrayList<String>(); + private int currentVal; + private boolean isCancelRequested = false; + + public void finish(boolean wasFullBuild) { + System.out.println("build finished. Was full build: " + wasFullBuild); + } + + public boolean isCancelRequested() { + return isCancelRequested; + } + + public void setProgress(double percentDone) { + System.out.println("progress. Completed " + percentDone + " percent"); + } + + public void setProgressText(String text) { + System.out.println("progress text: " + text); + String newText = text+" [Percentage="+currentVal+"%]"; + messagesReceived.add(newText); + if (text.startsWith("woven aspect ")) numWovenAspectMessages++; + if (text.startsWith("woven class ")) numWovenClassMessages++; + if (text.startsWith("compiled:")) numCompiledMessages++; + if (programmableString != null + && text.indexOf(programmableString) != -1) { + count--; + if (count==0) { + if (debugTests) System.out.println("Just got message '"+newText+"' - asking build to cancel"); + isCancelRequested = true; + programmableString = null; + } + } + } + + public void begin() { + System.out.println("build started"); + currentVal = 0; + } + + // ------------- methods to help with testing ------------- + public void cancelOn(String string,int count) { + programmableString = string; + this.count = count; + } + + public boolean containsMessage(String prefix,String distinguishingMarks) { + for (String element: messagesReceived) { + if (element.startsWith(prefix) && + element.indexOf(distinguishingMarks)!=-1) return true; + } + return false; + } + + public void dumpMessages() { + System.out.println("ProgressMonitorMessages"); + for (String element: messagesReceived) { + System.out.println(element); + } + } + +} diff --git a/ajde.core/src/test/java/org/aspectj/ajde/core/TestCompilerConfiguration.java b/ajde.core/src/test/java/org/aspectj/ajde/core/TestCompilerConfiguration.java new file mode 100644 index 000000000..57d1ce73a --- /dev/null +++ b/ajde.core/src/test/java/org/aspectj/ajde/core/TestCompilerConfiguration.java @@ -0,0 +1,200 @@ +/******************************************************************** + * Copyright (c) 2007 Contributors. All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://eclipse.org/legal/epl-v10.html + * + * Contributors: IBM Corporation - initial API and implementation + * Helen Hawkins - initial version + *******************************************************************/ +package org.aspectj.ajde.core; + +import java.io.File; +import java.io.FileFilter; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.aspectj.testing.util.TestUtil; +import org.aspectj.util.FileUtil; +import org.aspectj.util.LangUtil; + +/** + * Test implementation of ICompilerConfiguration. Allows users to configure the settings via setter methods. By default returns null + * for all options except getClasspath(), getJavaOptionsMap() (by default returns that it's 1.3 compliant), + * getOutputLocationManager(), getSourcePathResources() (it recursively looks for them) and getProjectSourceFiles(). If no source + * files are specified by the user, then getProjectSourceFiles() returns an empty list. + */ +public class TestCompilerConfiguration implements ICompilerConfiguration { + + private String projectPath; + + private Set<File> aspectpath; + private Set<File> inpath; + private String outjar; + private Map<String, String> javaOptions; + private String nonStandardOptions; + private List<String> projectSourceFiles = new ArrayList<String>(); + private Map<String, File> sourcePathResources; + + private String srcDirName = "src"; + + private IOutputLocationManager outputLoc; + + public TestCompilerConfiguration(String projectPath) { + this.projectPath = projectPath; + } + + public Set<File> getAspectPath() { + return aspectpath; + } + + public List<String> getProjectXmlConfigFiles() { + return Collections.emptyList(); + } + + public String getClasspath() { + StringBuilder classpath = new StringBuilder(); + classpath.append(projectPath); + if (LangUtil.is19VMOrGreater()) { + classpath.append(File.pathSeparator).append(LangUtil.getJrtFsFilePath()); + } else { + classpath.append(File.pathSeparator).append(System.getProperty("sun.boot.class.path")); + } + classpath.append(File.pathSeparator).append(TestUtil.aspectjrtClasspath()); + return classpath.toString(); + } + + public Set<File> getInpath() { + return inpath; + } + + public Map<String, String> getJavaOptionsMap() { + if (javaOptions == null) { + javaOptions = new Hashtable<String, String>(); + javaOptions.put(JavaOptions.COMPLIANCE_LEVEL, JavaOptions.VERSION_13); + javaOptions.put(JavaOptions.SOURCE_COMPATIBILITY_LEVEL, JavaOptions.VERSION_13); + } + return javaOptions; + } + + public String getNonStandardOptions() { + return nonStandardOptions; + } + + public String getOutJar() { + return outjar; + } + + public IOutputLocationManager getOutputLocationManager() { + if (outputLoc == null) { + outputLoc = new TestOutputLocationManager(projectPath); + } + return outputLoc; + } + + public List<String> getProjectSourceFiles() { + return projectSourceFiles; + } + + public List<File> getProjectSourceFilesChanged() { + return null; + } + + public void configurationRead() { + } + + public Map<String, File> getSourcePathResources() { + if (sourcePathResources == null) { + sourcePathResources = new HashMap<String, File>(); + + /* Allow the user to override the testProjectPath by using sourceRoots */ + File[] srcBase = new File[] { new File(projectPath + File.separator + srcDirName) }; + + for (int j = 0; j < srcBase.length; j++) { + File[] fromResources = FileUtil.listFiles(srcBase[j], new FileFilter() { + public boolean accept(File pathname) { + String name = pathname.getName().toLowerCase(); + return !name.endsWith(".class") && !name.endsWith(".java") && !name.endsWith(".aj") + && !name.endsWith(".lst") && !name.endsWith(".jar"); + } + }); + for (int i = 0; i < fromResources.length; i++) { + String normPath = FileUtil.normalizedPath(fromResources[i], srcBase[j]); + sourcePathResources.put(normPath, fromResources[i]); + + } + } + } + return sourcePathResources; + } + + // -------------------- setter methods useful for testing --------------- + public void setAspectPath(Set<File> aspectPath) { + this.aspectpath = aspectPath; + } + + public void setInpath(Set<File> inpath) { + this.inpath = inpath; + } + + public void setOutjar(String outjar) { + this.outjar = outjar; + } + + public void setJavaOptions(Map<String,String> javaOptions) { + this.javaOptions = javaOptions; + } + + public void setNonStandardOptions(String options) { + this.nonStandardOptions = options; + } + + public void setProjectSourceFiles(List<String> projectSourceFiles) { + this.projectSourceFiles = projectSourceFiles; + } + + public void setSourcePathResources(Map<String, File> sourcePathResources) { + this.sourcePathResources = sourcePathResources; + } + + public void setSourceDir(String srcDirName) { + this.srcDirName = srcDirName; + } + + public int getConfigurationChanges() { + return ICompilerConfiguration.EVERYTHING; + } + + public List<String> getClasspathElementsWithModifiedContents() { + return null; + } + + public String getProjectEncoding() { + return null; + } + + public String getProcessor() { + return null; + } + + public String getProcessorPath() { + return null; + } + + @Override + public String getModulepath() { + return null; + } + + @Override + public String getModuleSourcepath() { + return null; + } + +} diff --git a/ajde.core/src/test/java/org/aspectj/ajde/core/TestMessageHandler.java b/ajde.core/src/test/java/org/aspectj/ajde/core/TestMessageHandler.java new file mode 100644 index 000000000..6cc8b8a8d --- /dev/null +++ b/ajde.core/src/test/java/org/aspectj/ajde/core/TestMessageHandler.java @@ -0,0 +1,100 @@ +/******************************************************************** + * Copyright (c) 2007 Contributors. All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://eclipse.org/legal/epl-v10.html + * + * Contributors: IBM Corporation - initial API and implementation + * Helen Hawkins - initial version + *******************************************************************/ +package org.aspectj.ajde.core; + +import java.util.ArrayList; +import java.util.List; + +import org.aspectj.bridge.AbortException; +import org.aspectj.bridge.IMessage; +import org.aspectj.bridge.IMessage.Kind; + +/** + * Test implementation of IBuildMessageHandler. By default it ignores INFO and WEAVEINFO messages. Stores all messages it's not + * ignoring in an ArrayList and ERRORS and ABORTS also in a separate ArrayList enabling users to query whether anything went wrong + * with the build. + */ +public class TestMessageHandler implements IBuildMessageHandler { + + private List<Kind> ignoring; + private List<TestMessage> messages; + private List<TestMessage> errors; + + public TestMessageHandler() { + ignoring = new ArrayList<Kind>(); + messages = new ArrayList<TestMessage>(); + errors = new ArrayList<TestMessage>(); + ignore(IMessage.INFO); + ignore(IMessage.WEAVEINFO); + } + + public boolean handleMessage(IMessage message) throws AbortException { + IMessage.Kind kind = message.getKind(); + if (isIgnoring(kind)) { + return true; + } + TestMessage t = new TestMessage(message); + messages.add(t); + if (kind.equals(IMessage.ABORT) || message.getThrown() != null) { + System.err.println("> AjCompiler error: " + message.getMessage()); //$NON-NLS-1$ + message.getThrown().printStackTrace(); + errors.add(t); + } else if (kind.equals(IMessage.ERROR)) { + errors.add(t); + } + System.out.println("> " + message); //$NON-NLS-1$ + return true; + } + + public void dontIgnore(Kind kind) { + if (null != kind) { + ignoring.remove(kind); + } + } + + public boolean isIgnoring(Kind kind) { + return ((null != kind) && (ignoring.contains(kind))); + } + + public void ignore(Kind kind) { + if ((null != kind) && (!ignoring.contains(kind))) { + ignoring.add(kind); + } + } + + public List<TestMessage> getMessages() { + return messages; + } + + public List<TestMessage> getErrors() { + return errors; + } + + public static class TestMessage { + IMessage message; + + public TestMessage(IMessage m) { + message = m; + } + + public IMessage getContainedMessage() { + return message; + } + + public String toString() { + String loc = "<no location>"; + if (null != message.getSourceLocation()) { + loc = message.getSourceLocation().getSourceFile() + ":" + message.getSourceLocation().getLine(); + } + return "TestMessage [" + message.getMessage() + ", " + loc + ", " + message.getKind() + "]"; + } + } +} diff --git a/ajde.core/src/test/java/org/aspectj/ajde/core/TestOutputLocationManager.java b/ajde.core/src/test/java/org/aspectj/ajde/core/TestOutputLocationManager.java new file mode 100644 index 000000000..4249d2d56 --- /dev/null +++ b/ajde.core/src/test/java/org/aspectj/ajde/core/TestOutputLocationManager.java @@ -0,0 +1,114 @@ +/******************************************************************** + * Copyright (c) 2007 Contributors. All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://eclipse.org/legal/epl-v10.html + * + * Contributors: IBM Corporation - initial API and implementation + * Helen Hawkins - initial version + *******************************************************************/ +package org.aspectj.ajde.core; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +/** + * Test implementation of IOutputLocationManager. By default returns the same location for both resources and classes, however, + * setter methods enable the user to specify different location for these. Note that the user is unable to specify different output + * location for different class files. + */ +public class TestOutputLocationManager implements IOutputLocationManager { + + private String testProjectOutputPath; + private File classOutputLoc; + private File resourceOutputLoc; + private List<File> allOutputLocations; + private Map<File,String> inpathMap = Collections.emptyMap(); + + public TestOutputLocationManager(String testProjectPath) { + this.testProjectOutputPath = testProjectPath + File.separator + "bin"; + } + + public TestOutputLocationManager(String string, Map<File,String> inpathMap) { + this(string); + this.inpathMap = inpathMap; + } + + @Override + public File getOutputLocationForClass(File compilationUnit) { + initLocations(); + return classOutputLoc; + } + + @Override + public File getOutputLocationForResource(File resource) { + initLocations(); + return resourceOutputLoc; + } + + @Override + public Map<File,String> getInpathMap() { + return inpathMap; + } + + // -------------- setter methods useful for testing ------------- + public void setOutputLocForClass(File f) { + classOutputLoc = f; + } + + public void setOutputLocForResource(File f) { + resourceOutputLoc = f; + } + + @Override + public List<File> getAllOutputLocations() { + if (allOutputLocations == null) { + allOutputLocations = new ArrayList<File>(); + initLocations(); + allOutputLocations.add(classOutputLoc); + if (!classOutputLoc.equals(resourceOutputLoc)) { + allOutputLocations.add(resourceOutputLoc); + } + } + return allOutputLocations; + } + + @Override + public File getDefaultOutputLocation() { + initLocations(); + return classOutputLoc; + } + + private void initLocations() { + if (classOutputLoc == null) { + classOutputLoc = new File(testProjectOutputPath); + } + if (resourceOutputLoc == null) { + resourceOutputLoc = new File(testProjectOutputPath); + } + } + + @Override + public String getSourceFolderForFile(File sourceFile) { + return null; + } + + @Override + public void reportFileWrite(String outputfile, int filetype) { + } + + @Override + public void reportFileRemove(String outputfile, int filetype) { + } + + @Override + public int discoverChangesSince(File dir, long buildtime) { + // TODO Auto-generated method stub + return 0; + } + +} diff --git a/ajde.core/src/test/java/org/aspectj/ajde/core/tests/AjConfigTest.java b/ajde.core/src/test/java/org/aspectj/ajde/core/tests/AjConfigTest.java new file mode 100644 index 000000000..eb7d67b9c --- /dev/null +++ b/ajde.core/src/test/java/org/aspectj/ajde/core/tests/AjConfigTest.java @@ -0,0 +1,201 @@ +/******************************************************************** + * Copyright (c) 2007 Contributors. All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://eclipse.org/legal/epl-v10.html + * + * Contributors: IBM Corporation - initial API and implementation + * Helen Hawkins - initial version + *******************************************************************/ +package org.aspectj.ajde.core.tests; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.aspectj.ajde.core.AjdeCoreTestCase; +import org.aspectj.ajde.core.IOutputLocationManager; +import org.aspectj.ajde.core.JavaOptions; +import org.aspectj.ajde.core.TestCompilerConfiguration; +import org.aspectj.ajde.core.internal.AjdeCoreBuildManager; +import org.aspectj.ajdt.internal.core.builder.AjBuildConfig; + +/** + * Tests that the AjBuildConfig is populated correctly from the ICompilerConfiguration + */ +public class AjConfigTest extends AjdeCoreTestCase { + + private TestCompilerConfiguration compilerConfig; + private AjdeCoreBuildManager ajdeBuildManager; + + @Override + protected void setUp() throws Exception { + super.setUp(); + initialiseProject("SimpleProject"); + ajdeBuildManager = new AjdeCoreBuildManager(getCompiler()); + compilerConfig = (TestCompilerConfiguration) getCompiler().getCompilerConfiguration(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + ajdeBuildManager = null; + compilerConfig = null; + } + + public void testJavaOptionsMap() { + Map<String,String> options = JavaOptions.getDefaultJavaOptions(); + options.put(JavaOptions.WARN_DEPRECATION, JavaOptions.WARNING); + compilerConfig.setJavaOptions(options); + Map<String,String> found = genAjBuildConfig().getOptions().getMap(); + String warning = found.get(JavaOptions.WARN_DEPRECATION); + assertEquals("expected to be warning on deprecation but found setting " + " was " + warning, JavaOptions.WARNING, warning); + } + + public void testAspectPath() { + Set<File> aspects = new HashSet<File>(); + compilerConfig.setAspectPath(aspects); + AjBuildConfig buildConfig = genAjBuildConfig(); + List<File> aPath = buildConfig.getAspectpath(); + assertTrue("no aspect path", aPath.isEmpty()); + + File f = new File("jarone.jar"); + aspects.add(f); + buildConfig = genAjBuildConfig(); + List<File> aPath2 = buildConfig.getAspectpath(); + assertEquals("expected one entry on the aspectpath but found " + aPath2.size(), 1, aPath2.size()); + assertTrue("expected to find file " + f.getName() + " on the aspectpath" + " but didn't", aPath2.contains(f)); + + File f2 = new File("jartwo.jar"); + aspects.add(f2); + buildConfig = genAjBuildConfig(); + List<File> aPath3 = buildConfig.getAspectpath(); + assertEquals("expected two entries on the aspectpath but found " + aPath3.size(), 2, aPath3.size()); + assertTrue("expected to find file " + f.getName() + " on the aspectpath" + " but didn't", aPath3.contains(f)); + assertTrue("expected to find file " + f2.getName() + " on the aspectpath" + " but didn't", aPath3.contains(f2)); + } + + public void testInpath() { + Set<File> jars = new HashSet<File>(); + compilerConfig.setInpath(jars); + AjBuildConfig buildConfig = genAjBuildConfig(); + List<File> inJars = buildConfig.getInpath(); + assertTrue("expected to find nothing on the inpath but found " + inJars, inJars.isEmpty()); + + File f = new File("jarone.jar"); + jars.add(f); + buildConfig = genAjBuildConfig(); + List<File> inJars2 = buildConfig.getInpath(); + assertTrue("expected to find one file on the inpath but found " + inJars2.size() + ": " + inJars2, inJars2.size() == 1); + assertTrue("expected to find file " + f.getName() + " on the inpath" + " but didn't", inJars2.contains(f)); + + File f2 = new File("jartwo.jar"); + jars.add(f2); + buildConfig = genAjBuildConfig(); + List<File> inJars3 = buildConfig.getInpath(); + assertEquals("expected two entries on the inpath but found " + inJars3.size(), 2, inJars3.size()); + assertTrue("expected to find file " + f.getName() + " on the inpath" + " but didn't", inJars3.contains(f)); + assertTrue("expected to find file " + f2.getName() + " on the inpath" + " but didn't", inJars3.contains(f2)); + } + + public void testOutJar() { + String outJar = "mybuild.jar"; + compilerConfig.setOutjar(outJar); + AjBuildConfig buildConfig = genAjBuildConfig(); + assertNotNull("expected to find a non null output jar but " + "didn't", buildConfig.getOutputJar()); + assertEquals("expected to find outjar 'mybuild.jar' but instead " + "found " + buildConfig.getOutputJar().toString(), + outJar, buildConfig.getOutputJar().toString()); + } + + public void testXHasMember() { + compilerConfig.setNonStandardOptions("-XhasMember"); + AjBuildConfig buildConfig = genAjBuildConfig(); + assertTrue("expected XhasMember to be enabled but wasn't ", buildConfig.isXHasMemberEnabled()); + } + + public void testOutputLocationManager() { + IOutputLocationManager mgr = compilerConfig.getOutputLocationManager(); + String expectedDefaultOutputDir = mgr.getDefaultOutputLocation().getAbsolutePath(); + AjBuildConfig buildConfig = genAjBuildConfig(); + String found = buildConfig.getCompilationResultDestinationManager().getDefaultOutputLocation().getAbsolutePath(); + assertEquals("expected to find default output location " + expectedDefaultOutputDir + " but found " + found, + expectedDefaultOutputDir, found); + } + + public void testSourcePathResources() { + Map<String, File> m = new HashMap<String, File>(); + m.put("newFile.txt", getWorkingDir()); + compilerConfig.setSourcePathResources(m); + AjBuildConfig buildConfig = genAjBuildConfig(); + Map<String, File> found = buildConfig.getSourcePathResources(); + for (Iterator<String> i = found.keySet().iterator(); i.hasNext();) { + String resource = i.next(); + assertEquals("expected to find resource with name newFile.txt but " + "found " + resource, "newFile.txt", resource); + File from = buildConfig.getSourcePathResources().get(resource); + assertEquals("expected to find resource with file " + getWorkingDir() + "but found " + from, getWorkingDir(), from); + } + } + + public void testClasspath() { + String classpath = compilerConfig.getClasspath(); + List<String> found = genAjBuildConfig().getClasspath(); + StringBuffer sb = new StringBuffer(); + for (Iterator<String> iterator = found.iterator(); iterator.hasNext();) { + String name = iterator.next(); + sb.append(name); + if (iterator.hasNext()) { + sb.append(File.pathSeparator); + } + } + assertEquals("expected to find classpath " + classpath + " but found " + sb.toString(), classpath, sb.toString()); + } + + public void testNonStandardOptions() { + compilerConfig.setNonStandardOptions("-XterminateAfterCompilation"); + AjBuildConfig buildConfig = genAjBuildConfig(); + assertTrue("XterminateAfterCompilation", buildConfig.isTerminateAfterCompilation()); + compilerConfig.setNonStandardOptions("-XserializableAspects"); + buildConfig = genAjBuildConfig(); + assertTrue("XserializableAspects", buildConfig.isXserializableAspects()); + compilerConfig.setNonStandardOptions("-XnoInline"); + buildConfig = genAjBuildConfig(); + assertTrue("XnoInline", buildConfig.isXnoInline()); + compilerConfig.setNonStandardOptions("-Xlint"); + buildConfig = genAjBuildConfig(); + assertEquals("Xlint", AjBuildConfig.AJLINT_DEFAULT, buildConfig.getLintMode()); + compilerConfig.setNonStandardOptions("-Xlint:error"); + buildConfig = genAjBuildConfig(); + assertEquals("Xlint", AjBuildConfig.AJLINT_ERROR, buildConfig.getLintMode()); + + // and a few options thrown in at once + compilerConfig.setNonStandardOptions("-Xlint -XnoInline -XserializableAspects"); + buildConfig = genAjBuildConfig(); + assertEquals("Xlint", AjBuildConfig.AJLINT_DEFAULT, buildConfig.getLintMode()); + assertTrue("XnoInline", buildConfig.isXnoInline()); + assertTrue("XserializableAspects", buildConfig.isXserializableAspects()); + } + + public void testProjectSourceFiles() throws IOException { + String f = getAbsoluteProjectDir() + File.separator + "C.java"; + List<String> files = new ArrayList<>(); + files.add(f); + compilerConfig.setProjectSourceFiles(files); + AjBuildConfig buildConfig = genAjBuildConfig(); + String found = buildConfig.getFiles().get(0).getCanonicalPath();// AbsolutePath(); + assertEquals("expected source file " + f + ", but found " + found, f, found); + } + + private AjBuildConfig genAjBuildConfig() { + AjBuildConfig buildConfig = ajdeBuildManager.generateAjBuildConfig(); + assertNotNull("exepected to generate a non null AjBuildConfig but " + "didn't", buildConfig); + return buildConfig; + } + +} diff --git a/ajde.core/src/test/java/org/aspectj/ajde/core/tests/BuildCancellingTest.java b/ajde.core/src/test/java/org/aspectj/ajde/core/tests/BuildCancellingTest.java new file mode 100644 index 000000000..75c37df84 --- /dev/null +++ b/ajde.core/src/test/java/org/aspectj/ajde/core/tests/BuildCancellingTest.java @@ -0,0 +1,272 @@ +/******************************************************************** + * Copyright (c) 2004 Contributors. + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andy Clement Initial version + * Helen Hawkins Converted to new interface (bug 148190) + * ******************************************************************/ +package org.aspectj.ajde.core.tests; + +import org.aspectj.ajde.core.AjdeCoreTestCase; +import org.aspectj.ajde.core.TestBuildProgressMonitor; +import org.aspectj.ajde.core.TestCompilerConfiguration; + +/** + * It is now possible to cancel the compiler during either the compilation or + * weaving phases - this testcase verifies a few cases, making sure the process + * stops when expected. It can check the disk contents, but it doesn't right + * now. + * + * Two different .lst files are used during these tests: LoadsaCode.lst and + * EvenMoreCode.lst which contain mixes of aspects and classes + * + * Here are some things to think about that will help you understand what is on + * the disk when we cancel the compiler. + * + * There are 3 important phases worth remembering : - Compile all the types - + * Weave all the aspects - Weave all the classes + * + * Each of those steps goes through all the types. This means during the 'weave + * all the aspects' step we are jumping over classes and during the 'weave all + * the classes ' step we are jumping over aspects. Why is this important? + * + * + * We only write bytes out during the 'weave all the classes ' phase and it is + * even during that phase that we write out the bytes for aspects. This means if + * you cancel during compilation or during the weaving of aspects - there will + * be nothing on the disk. If you cancel whilst in the 'weave all the classes ' + * phase then the disk will contain anything finished with by the cancellation + * point. + */ +public class BuildCancellingTest extends AjdeCoreTestCase { + + private final boolean debugTests = false; + private TestBuildProgressMonitor programmableBPM; + private TestCompilerConfiguration compilerConfig; + + private String[] loadsaCode = { "A1.aj", "A2.aj", "HW.java", "A3.aj", + "A4.aj" }; + private String[] evenMoreCode = { "A1.aj", "Cl1.java", "A2.aj", "Cl2.java", + "HW.java", "A3.aj", "Cl3.java", "A4.aj" }; + + protected void setUp() throws Exception { + super.setUp(); + initialiseProject("BuildCancelling"); + programmableBPM = (TestBuildProgressMonitor) getCompiler() + .getBuildProgressMonitor(); + compilerConfig = (TestCompilerConfiguration) getCompiler() + .getCompilerConfiguration(); + } + + protected void tearDown() throws Exception { + super.tearDown(); + programmableBPM = null; + compilerConfig = null; + } + + /** + * After first compilation message, get it to cancel, there should be one + * more warning message about cancelling the compile and their should be + * nothing on the disk. + */ + public void testCancelFirstCompile() { + if (debugTests) + System.out + .println("\n\n\ntestCancelFirstCompile: Building with LoadsaCode"); + + compilerConfig.setProjectSourceFiles(getSourceFileList(loadsaCode)); + programmableBPM.cancelOn("compiled:", 1); // Force a cancel after the + // first compile occurs + + doBuild(true); + + assertTrue("Should have cancelled after first compile?:" + + programmableBPM.numCompiledMessages, + programmableBPM.numCompiledMessages == 1); + // Comment out to check the disk contents + + // assertTrue("As weaving was cancelled, no files should have been + // written out, but I found:"+wovenClassesFound(), + // wovenClassesFound()==0); + + boolean expectedCancelMessageFound = checkFor("Compilation cancelled as requested"); + if (!expectedCancelMessageFound) + dumpTaskData(); // Useful for debugging + assertTrue( + "Failed to get warning message about compilation being cancelled!", + expectedCancelMessageFound); + } + + /** + * After third compilation message, get it to cancel, there should be one + * more warning message about cancelling the compile and their should be + * nothing on the disk. + */ + public void testCancelThirdCompile() { + if (debugTests) + System.out + .println("\n\n\ntestCancelThirdCompile: Building with LoadsaCode"); + + compilerConfig.setProjectSourceFiles(getSourceFileList(loadsaCode)); + programmableBPM.cancelOn("compiled:", 3); // Force a cancel after the + // third compile occurs + + doBuild(true); + + assertTrue("Should have cancelled after third compile?:" + + programmableBPM.numCompiledMessages, + programmableBPM.numCompiledMessages == 3); + // Comment out to check the disk contents + // assertTrue("As weaving was cancelled, no files should have been + // written out, but I found:"+wovenClassesFound(), + // wovenClassesFound()==0); + + boolean expectedCancelMessageFound = checkFor("Compilation cancelled as requested"); + if (!expectedCancelMessageFound) + dumpTaskData(); // Useful for debugging + assertTrue( + "Failed to get warning message about compilation being cancelled!", + expectedCancelMessageFound); + } + + /** + * After first weave aspect message, get it to cancel, there should be one + * more warning message about cancelling the weave and their should be + * nothing on the disk. + */ + public void testCancelFirstAspectWeave() { + if (debugTests) + System.out + .println("\n\n\ntestCancelFirstAspectWeave: Building with LoadsaCode"); + + compilerConfig.setProjectSourceFiles(getSourceFileList(loadsaCode)); + programmableBPM.cancelOn("woven aspect ", 1); // Force a cancel after + // the first weave + // aspect occurs + + doBuild(true); + + assertTrue("Should have cancelled after first aspect weave?:" + + programmableBPM.numWovenAspectMessages, + programmableBPM.numWovenAspectMessages == 1); + // Comment out to check the disk contents + // assertTrue("As weaving was cancelled, no files should have been + // written out?:"+wovenClassesFound(), + // wovenClassesFound()==0); + + boolean expectedCancelMessageFound = checkFor("Weaving cancelled as requested"); + if (!expectedCancelMessageFound) + dumpTaskData(); // Useful for debugging + assertTrue( + "Failed to get warning message about weaving being cancelled!", + expectedCancelMessageFound); + } + + /** + * After third weave aspect message, get it to cancel, there should be one + * more warning message about cancelling the weave and their should be + * nothing on the disk. + */ + public void testCancelThirdAspectWeave() { + if (debugTests) + System.out + .println("\n\n\ntestCancelThirdAspectWeave: Building with LoadsaCode"); + compilerConfig.setProjectSourceFiles(getSourceFileList(loadsaCode)); + // Force a cancel after the third weave occurs. + // This should leave two class files on disk - I think? + programmableBPM.cancelOn("woven aspect ", 3); + + doBuild(true); + assertTrue("Should have cancelled after third weave?:" + + programmableBPM.numWovenAspectMessages, + programmableBPM.numWovenAspectMessages == 3); + + // Comment out to check disk contents + // assertTrue("As weaving was cancelled, no files should have been + // written out?:"+wovenClassesFound(), + // wovenClassesFound()==0); + + boolean expectedCancelMessageFound = checkFor("Weaving cancelled as requested"); + if (!expectedCancelMessageFound) + dumpTaskData(); // Useful for debugging + assertTrue( + "Failed to get warning message about weaving being cancelled!", + expectedCancelMessageFound); + + } + + /** + * After first weave class message, get it to cancel, there should be one + * more warning message about cancelling the weave and their should be + * nothing on the disk. + * + * EvenMoreCode.lst contains: A1.aj Cl1.java A2.aj Cl2.java HW.java A3.aj + * Cl3.java A4.aj + * + */ + public void testCancelFirstClassWeave() { + if (debugTests) + System.out + .println("testCancelFirstClassWeave: Building with EvenMoreCode"); + compilerConfig.setProjectSourceFiles(getSourceFileList(evenMoreCode)); + programmableBPM.cancelOn("woven class", 1); + + doBuild(true); + + // Should just be A1 on the disk - uncomment this line to verify that! + // (and uncomment diskContents()) + // assertTrue("Incorrect disk contents found",diskContents("A1")); + + assertTrue("Should have cancelled after first class weave?:" + + programmableBPM.numWovenClassMessages, + programmableBPM.numWovenClassMessages == 1); + + boolean expectedCancelMessageFound = checkFor("Weaving cancelled as requested"); + if (!expectedCancelMessageFound) + dumpTaskData(); // Useful for debugging + assertTrue( + "Failed to get warning message about weaving being cancelled!", + expectedCancelMessageFound); + } + + /** + * After first weave aspect message, get it to cancel, there should be one + * more warning message about cancelling the weave and their should be + * nothing on the disk. + * + * EvenMoreCode.lst contains: A1.aj Cl1.java A2.aj Cl2.java HW.java A3.aj + * Cl3.java A4.aj + * + */ + public void testCancelSecondClassWeave() { + if (debugTests) + System.out + .println("testCancelSecondClassWeave: Building with EvenMoreCode"); + compilerConfig.setProjectSourceFiles(getSourceFileList(evenMoreCode)); + programmableBPM.cancelOn("woven class", 2); + + doBuild(true); + + // Uncomment this line to verify disk contents(and uncomment + // diskContents()) + // assertTrue("Incorrect disk contents found",diskContents("A1 Cl1 + // A2")); + + assertTrue("Should have cancelled after first class weave?:" + + programmableBPM.numWovenClassMessages, + programmableBPM.numWovenClassMessages == 2); + + boolean expectedCancelMessageFound = checkFor("Weaving cancelled as requested"); + if (!expectedCancelMessageFound) + dumpTaskData(); // Useful for debugging + assertTrue( + "Failed to get warning message about weaving being cancelled!", + expectedCancelMessageFound); + + } +} diff --git a/ajde.core/src/test/java/org/aspectj/ajde/core/tests/CompilerMessagesTest.java b/ajde.core/src/test/java/org/aspectj/ajde/core/tests/CompilerMessagesTest.java new file mode 100644 index 000000000..0284b3d10 --- /dev/null +++ b/ajde.core/src/test/java/org/aspectj/ajde/core/tests/CompilerMessagesTest.java @@ -0,0 +1,78 @@ +/* ******************************************************************* + * Copyright (c) 2003 Contributors. + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * AMC 2003 initial version + * Helen Hawkins Converted to new interface (bug 148190) + * ******************************************************************/ +package org.aspectj.ajde.core.tests; + +import java.io.File; +import java.io.IOException; +import java.util.List; + +import org.aspectj.ajde.core.AjdeCoreTestCase; +import org.aspectj.ajde.core.TestCompilerConfiguration; +import org.aspectj.ajde.core.TestMessageHandler; +import org.aspectj.ajde.core.TestMessageHandler.TestMessage; +import org.aspectj.bridge.IMessage; + +public class CompilerMessagesTest extends AjdeCoreTestCase { + + private TestMessageHandler handler; + private TestCompilerConfiguration compilerConfig; + private String[] files = { "apackage" + File.separator + "InitCatcher.java", + "apackage" + File.separator + "SomeClass.java" }; + + protected void setUp() throws Exception { + super.setUp(); + initialiseProject("declare-warning"); + handler = (TestMessageHandler) getCompiler().getMessageHandler(); + compilerConfig = (TestCompilerConfiguration) getCompiler().getCompilerConfiguration(); + compilerConfig.setProjectSourceFiles(getSourceFileList(files)); + doBuild(true); + } + + protected void tearDown() throws Exception { + super.tearDown(); + handler = null; + compilerConfig = null; + } + + public void testMessages() { + // bug 33474 + // The build has happened, what messages did the compiler give, and do they + // contain the information we expect? + List<TestMessage> msgs = handler.getMessages(); + if (2 != msgs.size()) { + assertTrue("not two messages: " + msgs, false); + } + assertEquals("Two warning messages should be produced",2,msgs.size()); + TestMessageHandler.TestMessage msg = + (TestMessageHandler.TestMessage) msgs.get(0); + assertEquals( 8, msg.getContainedMessage().getSourceLocation().getLine()); + assertEquals( "Please don't call init methods", msg.getContainedMessage().getMessage()); + try { + String fullyQualifiedFile = msg.getContainedMessage().getSourceLocation().getSourceFile().getCanonicalPath(); + // this name has a tester specific prefix, followed by the location of the file. + // we can validate the ending. + fullyQualifiedFile = fullyQualifiedFile.replace('\\','/'); // ignore platform differences in slashes + assertTrue( "Fully-qualified source file location returned", + fullyQualifiedFile.endsWith("/declare-warning/apackage/SomeClass.java")); + } catch (IOException ex) { + assertTrue( "Unable to convert source file location: " + msg.getContainedMessage().getSourceLocation().getSourceFile(), false); + } + } + + public void testDeclareMessageContents() { + List<TestMessage> msgs = handler.getMessages(); + IMessage msg = ((TestMessageHandler.TestMessage)msgs.get(1)).getContainedMessage(); + assertEquals( "Please don't call setters" , msg.getMessage()); + assertEquals("field-set(int apackage.SomeClass.x)", msg.getDetails()); + } +} diff --git a/ajde.core/src/test/java/org/aspectj/ajde/core/tests/DuplicateManifestTest.java b/ajde.core/src/test/java/org/aspectj/ajde/core/tests/DuplicateManifestTest.java new file mode 100644 index 000000000..b7c2a9251 --- /dev/null +++ b/ajde.core/src/test/java/org/aspectj/ajde/core/tests/DuplicateManifestTest.java @@ -0,0 +1,80 @@ +/******************************************************************************* + * Copyright (c) 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Matthew Webster - initial implementation + * Helen Hawkins - Converted to new interface (bug 148190) + *******************************************************************************/ +package org.aspectj.ajde.core.tests; + +import java.io.File; +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; +import java.util.jar.JarFile; +import java.util.jar.Manifest; + +import org.aspectj.ajde.core.AjdeCoreTestCase; +import org.aspectj.ajde.core.TestCompilerConfiguration; +import org.aspectj.ajde.core.TestMessageHandler; + +public class DuplicateManifestTest extends AjdeCoreTestCase { + + public static final String injarName = "injar.jar"; + public static final String aspectjarName = "aspectjar.jar"; + public static final String outjarName = "outjar.jar"; + + private TestMessageHandler handler; + private TestCompilerConfiguration compilerConfig; + + protected void setUp() throws Exception { + super.setUp(); + initialiseProject("DuplicateManifestTest"); + handler = (TestMessageHandler) getCompiler().getMessageHandler(); + compilerConfig = (TestCompilerConfiguration) getCompiler() + .getCompilerConfiguration(); + } + + protected void tearDown() throws Exception { + super.tearDown(); + handler = null; + compilerConfig = null; + } + + public void testWeave() { + Set<File> injars = new HashSet<File>(); + injars.add(openFile(injarName)); + compilerConfig.setInpath(injars); + Set<File> aspectpath = new HashSet<File>(); + aspectpath.add(openFile(aspectjarName)); + compilerConfig.setAspectPath(aspectpath); + File outjar = openFile(outjarName); + compilerConfig.setOutjar(outjar.getAbsolutePath()); + doBuild(true); + assertTrue("Expected no compiler errors or warnings but found " + + handler.getMessages(), handler.getMessages().isEmpty()); + compareManifests(openFile(injarName), openFile(outjarName)); + } + + private void compareManifests(File inFile, File outFile) { + + try { + JarFile inJar = new JarFile(inFile); + Manifest inManifest = inJar.getManifest(); + inJar.close(); + JarFile outJar = new JarFile(outFile); + Manifest outManifest = outJar.getManifest(); + outJar.close(); + assertTrue("The manifests in '" + inFile.getCanonicalPath() + + "' and '" + outFile.getCanonicalPath() + + "' sould be the same", inManifest.equals(outManifest)); + } catch (IOException ex) { + fail(ex.toString()); + } + } + +} diff --git a/ajde.core/src/test/java/org/aspectj/ajde/core/tests/InpathTest.java b/ajde.core/src/test/java/org/aspectj/ajde/core/tests/InpathTest.java new file mode 100644 index 000000000..af1040e5f --- /dev/null +++ b/ajde.core/src/test/java/org/aspectj/ajde/core/tests/InpathTest.java @@ -0,0 +1,348 @@ +/* ******************************************************************* + * Copyright (c) 2003 Contributors. + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Mik Kersten initial implementation + * Andy Clement Copied/changed for -inpath testing + * Helen Hawkins Changed to use new ajde interface (bug 148190) + * ******************************************************************/ +package org.aspectj.ajde.core.tests; + +import java.io.File; +import java.io.FileFilter; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.util.HashSet; +import java.util.Set; +import java.util.jar.JarInputStream; +import java.util.zip.ZipEntry; + +import org.aspectj.ajde.core.AjdeCoreTestCase; +import org.aspectj.ajde.core.TestCompilerConfiguration; +import org.aspectj.ajde.core.TestMessageHandler; +import org.aspectj.util.FileUtil; + +public class InpathTest extends AjdeCoreTestCase { + + public static final FileFilter aspectjResourceFileFilter = new FileFilter() { + @Override + public boolean accept(File pathname) { + String name = pathname.getName().toLowerCase(); + return (!name.endsWith(".class") && !name.endsWith(".java") && !name.endsWith(".aj")); + + } + }; + + public static final String indir1Name = "indir1"; + public static final String indir2Name = "indir2"; + public static final String injarName = "injar.jar"; + public static final String outjarName = "/bin/output.jar"; + + private String[] build1 = new String[] { "src1" + File.separator + "Main.java" }; + private String[] build2 = new String[] { "src2" + File.separator + "Aspect.java" }; + + private TestMessageHandler handler; + private TestCompilerConfiguration compilerConfig; + + @Override + protected void setUp() throws Exception { + super.setUp(); + initialiseProject("InpathTest"); + handler = (TestMessageHandler) getCompiler().getMessageHandler(); + compilerConfig = (TestCompilerConfiguration) getCompiler().getCompilerConfiguration(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + handler = null; + compilerConfig = null; + } + + /** + * Inputs to the compiler: inpath = 'indir1/' source = 'src' output = a jar file + * + * Expected result = output jar file contains contents of indir1 and class file for source that was in src + */ + public void testInpathToOutjar() { + Set<File> inpath = new HashSet<File>(); + File indir1 = openFile(indir1Name); + inpath.add(indir1); + compilerConfig.setInpath(inpath); + File outjar = openFile(outjarName); + compilerConfig.setOutjar(outjar.getAbsolutePath()); + + compilerConfig.setProjectSourceFiles(getSourceFileList(build1)); + + doBuild(true); + assertTrue("Expected no compiler errors or warnings but found " + handler.getMessages(), handler.getMessages().isEmpty()); + + Set<String> expectedOutputJarContents = new HashSet<String>(); + // From indir1 + // If we don't copy resources, these next three files won't make it. + // expectedOutputJarContents.add("META-INF/MANIFEST.MF"); + // expectedOutputJarContents.add("META-INF/test.xml"); + // expectedOutputJarContents.add("test/test.props"); + expectedOutputJarContents.add("test/TestProperties.class"); + // From src + expectedOutputJarContents.add("Main.class"); + compareJars(indir1, "src", outjar, expectedOutputJarContents); + } + + /** + * Similar to the first test but outputs to a directory rather than a jar. + * + */ + public void testInpathToBin() { + Set<File> inpath = new HashSet<File>(); + File indir1 = openFile(indir1Name); + inpath.add(indir1); + compilerConfig.setInpath(inpath); + compilerConfig.setProjectSourceFiles(getSourceFileList(build1)); + + doBuild(true); + assertTrue("Expected no compiler errors or warnings but found " + handler.getMessages(), handler.getMessages().isEmpty()); + + Set<String> expectedBindirContents = new HashSet<String>(); + // From indir1 + // If we don't copy resources, these next three files won't make it + // expectedBindirContents.add("META-INF/MANIFEST.MF"); + // expectedBindirContents.add("META-INF/test.xml"); + // expectedBindirContents.add("test/test.props"); + expectedBindirContents.add("test/TestProperties.class"); + // From src + expectedBindirContents.add("Main.class"); + + compareIndirToBin(indir1, "src", "bin", expectedBindirContents); + + } + + /** + * Inputs to the compiler: inpath is 'indir2' that contains a helloworld source file and class file. source is 'src2' which + * contains Aspect.java which weaves before advice into the HelloWorld code from 'indir2' + * + * Expected result: HelloWorld copied through to output jar and 'weaved'. Compiled version of Aspect.java put into the output + * jar. The HelloWorld.java source file is also copied through to the output jar. + * + * An extra check is done at the end of this test to verify that HelloWorld has changed size (due to the weaving). + */ + public void testInpathToOutjar2() { + Set<File> inpath = new HashSet<File>(); + File indir2 = openFile(indir2Name); + inpath.add(indir2); + compilerConfig.setInpath(inpath); + File outjar = openFile(outjarName); + compilerConfig.setOutjar(outjar.getAbsolutePath()); + + compilerConfig.setProjectSourceFiles(getSourceFileList(build2)); + + doBuild(true); + assertTrue("Expected no compiler errors or warnings but found " + handler.getMessages(), handler.getMessages().isEmpty()); + + Set<String> expectedOutputJarContents = new HashSet<String>(); + // From indir1 + expectedOutputJarContents.add("example/HelloWorld.class"); + + // If we don't copy resources, this file won't make it + // expectedOutputJarContents.add("example/HelloWorld.java"); + // From src + expectedOutputJarContents.add("Aspect.class"); + + compareJars(indir2, "src", outjar, expectedOutputJarContents); + + // Extra test. The HelloWorld class from the input directory should have been woven + // by the aspect - verify that the size of the HelloWorld class in the output directory + // is a different size to the input version. + int outputsize = fetchFromJar(outjar, "example/HelloWorld.class"); + try { + FileInputStream fis = new FileInputStream(openFile(indir2Name + "/example/HelloWorld.class")); + byte[] filedata = FileUtil.readAsByteArray(fis); + int inputsize = filedata.length; + assertTrue("Weaving of Aspect should have occurred but the input and output size for HelloWorld.class are the same", + (inputsize != outputsize)); + } catch (Exception e) { + e.printStackTrace(); + fail(); + } + } + + /** + * More complex inpath - a jar and a directory + * + * Inputs: -inpath injar.jar;indir2 source is 'src2' which contains Aspect.java + * + * Expected result: Result should be a directory containing the contents of injar.jar and indir2 and the Aspect.class file. + * + */ + public void testInpathAndInjarToBin() { + Set<File> inpath = new HashSet<File>(); + File indir2 = openFile(indir2Name); + inpath.add(indir2); + inpath.add(openFile(injarName)); + compilerConfig.setInpath(inpath); + compilerConfig.setProjectSourceFiles(getSourceFileList(build2)); + + doBuild(true); + assertTrue("Expected no compiler errors or warnings but found " + handler.getMessages(), handler.getMessages().isEmpty()); + + Set<String> expectedBindirContents = new HashSet<String>(); + + // From indir1 + expectedBindirContents.add("example/HelloWorld.class"); + + // If we don't copy resources, this file won't make it + // expectedBindirContents.add("example/HelloWorld.java"); + // From injar.jar + expectedBindirContents.add("props/resources.properties"); + // From src + expectedBindirContents.add("Aspect.class"); + + compareIndirToBin(indir2, "src", "bin", expectedBindirContents); + + // Check the input and output versions of HelloWorld.class are different sizes + try { + FileInputStream fis1 = new FileInputStream(openFile("indir2/example/HelloWorld.class")); + byte[] filedata1 = FileUtil.readAsByteArray(fis1); + int inputsize = filedata1.length; + FileInputStream fis2 = new FileInputStream(openFile("bin/example/HelloWorld.class")); + byte[] filedata2 = FileUtil.readAsByteArray(fis2); + int outputsize = filedata2.length; + assertTrue("Weaving of Aspect should have occurred but the input and output size for HelloWorld.class are the same", + (outputsize != inputsize)); + + fis1.close(); + fis2.close(); + } catch (Exception e) { + e.printStackTrace(); + fail(); + } + } + + /* + * Ensure -outjar contains all non-Java resouces from injars + */ + public void compareJars(File dirFile, String sourceDir, File outjarFile, Set<String> expectedOutputJarContents) { + + try { + assertTrue( + "outjar older than injar: outjarLastMod=" + outjarFile.lastModified() + " injarLastMod=" + + dirFile.lastModified(), (outjarFile.lastModified() >= dirFile.lastModified())); + + // Go through the output jar file, for each element, remove it from + // the expectedOutputJarContents - when we finish, the expectedOutputJarContents + // set should be empty! + JarInputStream outjar = new JarInputStream(new java.io.FileInputStream(outjarFile)); + ZipEntry entry; + while (null != (entry = outjar.getNextEntry())) { + String fileName = entry.getName(); + fileName = fileName.replace('\\', '/'); + if (fileName.indexOf("CVS") == -1) { + boolean b = expectedOutputJarContents.remove(fileName); + assertTrue("Unexpectedly found : " + fileName + " in outjar", b); + } + outjar.closeEntry(); + } + outjar.close(); + + assertTrue("Didnt make it into the output jar: " + expectedOutputJarContents.toString(), + expectedOutputJarContents.isEmpty()); + } catch (IOException ex) { + fail(ex.toString()); + } + } + + /* + * Ensure -outjar contains all non-Java resouces from source and injars + */ + public void compareSourceToOutjar(String indirName, File outjarFile) { + HashSet<String> resources = new HashSet<>(); + listSourceResources(indirName, resources); + + try { + + JarInputStream outjar = new JarInputStream(new java.io.FileInputStream(outjarFile)); + ZipEntry entry; + while (null != (entry = outjar.getNextEntry())) { + String fileName = entry.getName(); + + if (!fileName.endsWith(".class")) { + boolean b = resources.remove(fileName); + assertTrue(fileName, b); + } + outjar.closeEntry(); + } + outjar.close(); + + assertTrue("Missing resources: " + resources.toString(), resources.isEmpty()); + } catch (IOException ex) { + fail(ex.toString()); + } + } + + /* + * Ensure bin contains all non-Java resouces from source and injars + */ + public void compareIndirToBin(File indirFile, String sourceDir, String outdirName, Set<String> expectedOutdirContents) { + + // byte[] inManifest = null; + + File binBase = openFile(outdirName); + String[] toResources = FileUtil.listFiles(binBase); + for (int i = 0; i < toResources.length; i++) { + String fileName = toResources[i]; + if (fileName.indexOf("CVS") == -1) { + boolean b = expectedOutdirContents.remove(fileName); + assertTrue("Extraneous resources: " + fileName, b); + } + } + + assertTrue("Missing resources: " + expectedOutdirContents.toString(), expectedOutdirContents.isEmpty()); + } + + private void listSourceResources(String indirName, Set<String> resources) { + File srcBase = openFile(indirName); + File[] fromResources = FileUtil.listFiles(srcBase, aspectjResourceFileFilter); + for (int i = 0; i < fromResources.length; i++) { + String name = FileUtil.normalizedPath(fromResources[i], srcBase); + // System.err.println("Checking "+name); + if (!name.startsWith("CVS/") && (-1 == name.indexOf("/CVS/")) && !name.endsWith("/CVS")) { + resources.add(name); + } + } + } + + // Return the size of specified entry from the output jar file + public int fetchFromJar(File outjarFile, String filename) { + int ret = -1; + try { + JarInputStream outjar; + + outjar = new JarInputStream(new java.io.FileInputStream(outjarFile)); + + ZipEntry entry; + while (null != (entry = outjar.getNextEntry())) { + String zipentryname = entry.getName(); + if (zipentryname.equals(filename)) { + byte[] filedata = FileUtil.readAsByteArray(outjar); + ret = filedata.length; + outjar.closeEntry(); + break; + } + outjar.closeEntry(); + } + outjar.close(); + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + return ret; + } + +} diff --git a/ajde.core/src/test/java/org/aspectj/ajde/core/tests/JarManifestTest.java b/ajde.core/src/test/java/org/aspectj/ajde/core/tests/JarManifestTest.java new file mode 100644 index 000000000..242c3e3f3 --- /dev/null +++ b/ajde.core/src/test/java/org/aspectj/ajde/core/tests/JarManifestTest.java @@ -0,0 +1,82 @@ +/******************************************************************************* + * Copyright (c) 2004 IBM Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * IBM Corporation - initial API and implementation + * Helen Hawkins - Converted to new interface (bug 148190) + *******************************************************************************/ +package org.aspectj.ajde.core.tests; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.util.jar.JarInputStream; +import java.util.jar.Manifest; + +import org.aspectj.ajde.core.AjdeCoreTestCase; +import org.aspectj.ajde.core.TestCompilerConfiguration; +import org.aspectj.ajde.core.TestMessageHandler; + +public class JarManifestTest extends AjdeCoreTestCase { + + public static final String outjarName = "/bin/output.jar"; + + private String[] weave = { "src" + File.separator + "Main.java", + "src" + File.separator + "Logging.aj" }; + + private TestMessageHandler handler; + private TestCompilerConfiguration compilerConfig; + + protected void setUp() throws Exception { + super.setUp(); + initialiseProject("JarManifestTest"); + handler = (TestMessageHandler) getCompiler().getMessageHandler(); + compilerConfig = (TestCompilerConfiguration) getCompiler() + .getCompilerConfiguration(); + } + + protected void tearDown() throws Exception { + super.tearDown(); + handler = null; + compilerConfig = null; + } + + public void testWeave () { + File outjar = openFile(outjarName); + compilerConfig.setOutjar(outjar.getAbsolutePath()); + compilerConfig.setProjectSourceFiles(getSourceFileList(weave)); + doBuild(true); + assertTrue("Expected no compiler errors or warnings but found " + + handler.getMessages(), handler.getMessages().isEmpty()); + checkManifest(outjar); + } + + public void testNoWeave () { + File outjar = openFile(outjarName); + compilerConfig.setOutjar(outjar.getAbsolutePath()); + compilerConfig.setProjectSourceFiles(getSourceFileList(weave)); + compilerConfig.setNonStandardOptions("-XterminateAfterCompilation"); + doBuild(true); + assertTrue("Expected no compiler errors or warnings but found " + + handler.getMessages(), handler.getMessages().isEmpty()); + checkManifest(outjar); + } + + private void checkManifest (File outjarFile) { + Manifest manifest = null; + + try { + JarInputStream outjar = new JarInputStream(new FileInputStream(outjarFile)); + manifest = outjar.getManifest(); + outjar.close(); + assertNotNull("'" + outjarFile.getCanonicalPath() + "' should contain a manifest",manifest); + } + catch (IOException ex) { + fail(ex.toString()); + } + } +} diff --git a/ajde.core/src/test/java/org/aspectj/ajde/core/tests/OutxmlTest.java b/ajde.core/src/test/java/org/aspectj/ajde/core/tests/OutxmlTest.java new file mode 100644 index 000000000..7cf08b1c7 --- /dev/null +++ b/ajde.core/src/test/java/org/aspectj/ajde/core/tests/OutxmlTest.java @@ -0,0 +1,166 @@ +/******************************************************************** + * Copyright (c) 2003 Contributors. All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Matthew Webster initial implementation + * Helen Hawkins Converted to new interface (bug 148190) + *******************************************************************/ +package org.aspectj.ajde.core.tests; + +import java.io.File; +import java.io.IOException; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; + +import org.aspectj.ajde.core.AjdeCoreTestCase; +import org.aspectj.ajde.core.TestCompilerConfiguration; +import org.aspectj.ajde.core.TestMessageHandler; +import org.aspectj.ajde.core.TestMessageHandler.TestMessage; +import org.aspectj.bridge.Constants; + +public class OutxmlTest extends AjdeCoreTestCase { + + public static final String PROJECT_DIR = "OutxmlTest"; + public static final String BIN_DIR = "bin"; + public static final String OUTJAR_NAME = "/bin/test.jar"; + public static final String DEFAULT_AOPXML_NAME = Constants.AOP_AJC_XML; + public static final String CUSTOM_AOPXML_NAME = "custom/aop.xml"; + + private String[] files = new String[]{ + "src" + File.separator + "TestAbstractAspect.aj", + "src" + File.separator + "TestClass.java", + "src" + File.separator + "TestConcreteAspect.aj", + "src" + File.separator + "TestInterface.java" + }; + + private TestMessageHandler handler; + private TestCompilerConfiguration compilerConfig; + + protected void setUp() throws Exception { + super.setUp(); + initialiseProject(PROJECT_DIR); + handler = (TestMessageHandler) getCompiler().getMessageHandler(); + compilerConfig = (TestCompilerConfiguration) getCompiler() + .getCompilerConfiguration(); + } + + protected void tearDown() throws Exception { + super.tearDown(); + handler = null; + compilerConfig = null; + } + + /** + * Aim: Test "-outxml" option produces the correct xml file + */ + public void testOutxmlToFile () { + compilerConfig.setProjectSourceFiles(getSourceFileList(files)); + compilerConfig.setNonStandardOptions("-outxml"); + doBuild(true); + assertTrue("Expected no compiler errors or warnings but found " + + handler.getMessages(), handler.getMessages().isEmpty()); + File aopxml = openFile(BIN_DIR + "/" + DEFAULT_AOPXML_NAME); + assertTrue(DEFAULT_AOPXML_NAME + " missing",aopxml.exists()); + } + + /** + * Aim: Test "-outxmlfile filename" option produces the correct + * xml file + * + */ + public void testOutxmlfileToFile () { + compilerConfig.setProjectSourceFiles(getSourceFileList(files)); + compilerConfig.setNonStandardOptions("-outxmlfile custom/aop.xml"); + doBuild(true); + assertTrue("Expected no compiler errors or warnings but found " + + handler.getMessages(), handler.getMessages().isEmpty()); + + File aopxml = openFile(BIN_DIR + "/" + CUSTOM_AOPXML_NAME); + assertTrue(CUSTOM_AOPXML_NAME + " missing",aopxml.exists()); + } + + /** + * Aim: Test "-outxml" option produces the correct + * xml entry in outjar file + * + */ + public void testOutxmlToOutjar () { + File outjar = openFile(OUTJAR_NAME); + compilerConfig.setOutjar(outjar.getAbsolutePath()); + compilerConfig.setProjectSourceFiles(getSourceFileList(files)); + compilerConfig.setNonStandardOptions("-outxml"); + doBuild(true); + assertTrue("Expected no compiler errors or warnings but found " + + handler.getMessages(), handler.getMessages().isEmpty()); + + File aopxml = openFile(BIN_DIR + "/" + DEFAULT_AOPXML_NAME); + assertFalse(DEFAULT_AOPXML_NAME + " should not exisit",aopxml.exists()); + assertJarContainsEntry(outjar,DEFAULT_AOPXML_NAME); + } + + /** + * Aim: Test "-outxml" option produces a warning if "META-INF/aop.xml + * already exists in source + * + */ + public void testOutxmlToOutjarWithAop_xml () { + File f = new File( getAbsoluteProjectDir() + File.separator + "src-resources" + File.separator + "testjar.jar"); + Set<File> roots = new HashSet<File>(); + roots.add(f); + compilerConfig.setInpath(roots); + + File outjar = openFile(OUTJAR_NAME); + compilerConfig.setOutjar(outjar.getAbsolutePath()); + compilerConfig.setNonStandardOptions("-outxml"); + doBuild(true); + assertFalse("Expected compiler errors or warnings but didn't find any " + + handler.getMessages(), handler.getMessages().isEmpty()); + + List<TestMessage> msgs = handler.getMessages(); + String msg = ((TestMessageHandler.TestMessage)msgs.get(0)).getContainedMessage().getMessage(); + String exp = "-outxml/-outxmlfile option ignored because resource already exists:"; + assertTrue("Expected message to start with : " + exp + " but found message " + msg,msg.startsWith(exp)); + + File aopxml = openFile(BIN_DIR + "/" + DEFAULT_AOPXML_NAME); + assertFalse(DEFAULT_AOPXML_NAME + " should not exisit",aopxml.exists()); + assertJarContainsEntry(outjar,DEFAULT_AOPXML_NAME); + } + + + /** + * Aim: Test "-outxmlfile filename" option produces the correct + * xml entry in outjar file + */ + public void testOutxmlfileToOutjar () { + File outjar = openFile(OUTJAR_NAME); + compilerConfig.setOutjar(outjar.getAbsolutePath()); + compilerConfig.setProjectSourceFiles(getSourceFileList(files)); + compilerConfig.setNonStandardOptions("-outxmlfile custom/aop.xml"); + doBuild(true); + assertTrue("Expected no compiler errors or warnings but found " + + handler.getMessages(), handler.getMessages().isEmpty()); + + File aopxml = openFile(BIN_DIR + "/" + CUSTOM_AOPXML_NAME); + assertFalse(CUSTOM_AOPXML_NAME + " should not exisit",aopxml.exists()); + assertJarContainsEntry(outjar,CUSTOM_AOPXML_NAME); + } + + private void assertJarContainsEntry (File file, String entryName) { + + try { + JarFile jarFile = new JarFile(file); + JarEntry jarEntry = jarFile.getJarEntry(entryName); + assertNotNull(entryName + " missing",jarEntry); + } + catch (IOException ex) { + fail(ex.toString()); + } + } +} diff --git a/ajde.core/src/test/java/org/aspectj/ajde/core/tests/ResourceCopyTest.java b/ajde.core/src/test/java/org/aspectj/ajde/core/tests/ResourceCopyTest.java new file mode 100644 index 000000000..c75da5b04 --- /dev/null +++ b/ajde.core/src/test/java/org/aspectj/ajde/core/tests/ResourceCopyTest.java @@ -0,0 +1,321 @@ +/******************************************************************** + * Copyright (c) 2003 Contributors. All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Mik Kersten initial implementation + * Helen Hawkins Converted to new interface (bug 148190) + *******************************************************************/ +package org.aspectj.ajde.core.tests; + +import java.io.File; +import java.io.FileFilter; +import java.io.IOException; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.jar.JarInputStream; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +import org.aspectj.ajde.core.AjdeCoreTestCase; +import org.aspectj.ajde.core.TestCompilerConfiguration; +import org.aspectj.ajde.core.TestMessageHandler; +import org.aspectj.util.FileUtil; + +public class ResourceCopyTest extends AjdeCoreTestCase { + + public static final String PROJECT_DIR = "bug-36071a"; + public static final String srcDir = PROJECT_DIR + "/src"; + public static final String binDir = "bin"; + + public static final String injar1Name = "input1.jar"; + public static final String injar2Name = "input2.jar"; + public static final String outjarName = "/bin/output.jar"; + + private TestMessageHandler handler; + private TestCompilerConfiguration compilerConfig; + + private String[] config1 = new String[] { "src" + File.separator + "Main.java", + "src" + File.separator + "testsrc" + File.separator + "TestProperties.java" }; + + private String[] config2 = new String[] { "src" + File.separator + "aspects" + File.separator + "Logging.java" }; + + @Override + protected void setUp() throws Exception { + super.setUp(); + initialiseProject(PROJECT_DIR); + handler = (TestMessageHandler) getCompiler().getMessageHandler(); + compilerConfig = (TestCompilerConfiguration) getCompiler().getCompilerConfiguration(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + handler = null; + compilerConfig = null; + } + + public void testSrcToBin() { + assertTrue("Expected there to be no compiler messages but found " + handler.getMessages(), handler.getMessages().isEmpty()); + compilerConfig.setProjectSourceFiles(getSourceFileList(config1)); + doBuild(true); + compareDirs("src", "bin"); + } + + public void testInjarsToOutjar() { + Set<File> injars = new HashSet<File>(); + File injar1 = openFile(injar1Name); + injars.add(injar1); + compilerConfig.setInpath(injars); + File outjar = openFile(outjarName); + compilerConfig.setOutjar(outjar.getAbsolutePath()); + compilerConfig.setProjectSourceFiles(getSourceFileList(config2)); + doBuild(true); + assertTrue("Expected no compiler errors or warnings but found " + handler.getMessages(), handler.getMessages().isEmpty()); + compareJars(injar1, "src", outjar); + } + + public void testDuplicateResources() { + Set<File> injars = new HashSet<File>(); + File injar1 = openFile(injar1Name); + File injar2 = openFile(injar2Name); + injars.add(injar1); + injars.add(injar2); + compilerConfig.setInpath(injars); + File outjar = openFile(outjarName); + compilerConfig.setOutjar(outjar.getAbsolutePath()); + compilerConfig.setProjectSourceFiles(getSourceFileList(config2)); + doBuild(true); + assertFalse("Expected compiler errors or warnings but didn't find any", handler.getMessages().isEmpty()); + + List<TestMessageHandler.TestMessage> msgs = handler.getMessages(); + String exp = "duplicate resource: "; + String found = msgs.get(0).getContainedMessage().getMessage(); + assertTrue("Expected message to start with 'duplicate resource:' but found" + " message " + found, found.startsWith(exp)); + compareJars(injar1, "src", outjar); + } + + public void testSrcToOutjar() { + File outjar = openFile(outjarName); + compilerConfig.setOutjar(outjar.getAbsolutePath()); + compilerConfig.setProjectSourceFiles(getSourceFileList(config1)); + doBuild(true); + assertTrue("Expected no compiler errors or warnings but found " + handler.getMessages(), handler.getMessages().isEmpty()); + compareSourceToOutjar("src", outjar); + } + + public void testInjarsToBin() { + Set<File> injars = new HashSet<File>(); + File injar1 = openFile(injar1Name); + injars.add(injar1); + compilerConfig.setInpath(injars); + compilerConfig.setProjectSourceFiles(getSourceFileList(config2)); + doBuild(true); + assertTrue("Expected no compiler errors or warnings but found " + handler.getMessages(), handler.getMessages().isEmpty()); + compareInjarsToBin(injar1, "src", "bin"); + } + + // BAH! keeps whinging about CVS extraneous resources + // public void testInjarsToOddBin () { + // Set injars = new HashSet(); + // File injar1 = openFile(injar1Name); + // injars.add(injar1); + // ideManager.getProjectProperties().setOutputPath("crazy.jar"); + // ideManager.getProjectProperties().setInJars(injars); + // assertTrue("Build failed",doSynchronousBuild("config2.lst")); + // assertTrue("Build warnings",ideManager.getCompilationSourceLineTasks().isEmpty()); + // compareInjarsToBin(injar1,"src","crazy.jar"); + // } + + public void testInjarsToOutjarOddNames() { + Set<File> injars = new HashSet<File>(); + File injar1 = openFile("input1"); + File outjar = openFile(outjarName + ".fozout"); + injars.add(injar1); + compilerConfig.setInpath(injars); + compilerConfig.setOutjar(outjar.getAbsolutePath()); + compilerConfig.setProjectSourceFiles(getSourceFileList(config2)); + doBuild(true); + assertTrue("Expected no compiler errors or warnings but found " + handler.getMessages(), handler.getMessages().isEmpty()); + compareJars(injar1, "src", outjar); + } + + /* + * Ensure bin contains all non-Java resouces from source and injars + */ + public void compareDirs(String indirName, String outdirName) { + File binBase = openFile(outdirName); + File[] toResources = FileUtil.listFiles(binBase, aspectjResourceFileFilter); + + HashSet<String> resources = new HashSet<>(); + listSourceResources(indirName, resources); + + for (int i = 0; i < toResources.length; i++) { + String fileName = FileUtil.normalizedPath(toResources[i], binBase); + boolean b = resources.remove(fileName); + assertTrue("Extraneous resources: " + fileName, b); + } + + assertTrue("Missing resources: " + resources.toString(), resources.isEmpty()); + } + + private void listSourceResources(String indirName, Set<String> resources) { + File srcBase = openFile(indirName); + File[] fromResources = FileUtil.listFiles(srcBase, aspectjResourceFileFilter); + for (int i = 0; i < fromResources.length; i++) { + String name = FileUtil.normalizedPath(fromResources[i], srcBase); + if (!name.startsWith("CVS/") && (-1 == name.indexOf("/CVS/")) && !name.endsWith("/CVS")) { + resources.add(name); + } + } + } + + public static final FileFilter aspectjResourceFileFilter = new FileFilter() { + @Override + public boolean accept(File pathname) { + String name = pathname.getName().toLowerCase(); + boolean isCVSRelated = name.indexOf("/cvs/") != -1; + return (!isCVSRelated && !name.endsWith(".class") && !name.endsWith(".java") && !name.endsWith(".aj")); + } + }; + + /* + * Ensure -outjar contains all non-Java resouces from injars + */ + public void compareJars(File injarFile, String indirName, File outjarFile) { + + HashSet<String> resources = new HashSet<>(); + + try { + assertTrue( + "outjar older than injar: outjarLastMod=" + outjarFile.lastModified() + " injarLastMod=" + + injarFile.lastModified(), (outjarFile.lastModified() >= injarFile.lastModified())); + byte[] inManifest = listJarResources(injarFile, resources, true); + listSourceResources(indirName, resources); + + ZipInputStream outjar = new ZipInputStream(new java.io.FileInputStream(outjarFile)); + ZipEntry entry; + while (null != (entry = outjar.getNextEntry())) { + String fileName = entry.getName(); + if (!fileName.endsWith(".class")) { + + /* Ensure we copied right JAR manifest */ + if (fileName.equalsIgnoreCase("meta-inf/Manifest.mf")) { + byte[] outManifest = FileUtil.readAsByteArray(outjar); + assertTrue("Wrong manifest has been copied", Arrays.equals(inManifest, outManifest)); + } + + boolean b = resources.remove(fileName); + assertTrue(fileName, b); + } + outjar.closeEntry(); + } + outjar.close(); + resources.remove("META-INF/"); + assertTrue(resources.toString(), resources.isEmpty()); + } catch (IOException ex) { + fail(ex.toString()); + } + } + + /* + * Ensure -outjar conatins all non-Java resouces from source and injars + */ + public void compareSourceToOutjar(String indirName, File outjarFile) { + HashSet<String> resources = new HashSet<>(); + listSourceResources(indirName, resources); + + try { + + ZipInputStream outjar = new JarInputStream(new java.io.FileInputStream(outjarFile)); + ZipEntry entry; + while (null != (entry = outjar.getNextEntry())) { + String fileName = entry.getName(); + if (!fileName.endsWith(".class")) { + boolean b = resources.remove(fileName); + assertTrue(fileName, b); + } + outjar.closeEntry(); + } + outjar.close(); + + assertTrue("Missing resources: " + resources.toString(), resources.isEmpty()); + } catch (IOException ex) { + fail(ex.toString()); + } + } + + /* + * Ensure bin contains all non-Java resouces from source and injars + */ + public void compareInjarsToBin(File injarFile, String indirName, String outdirName) { + + HashSet<String> resources = new HashSet<>(); + + try { + byte[] inManifest = listJarResources(injarFile, resources, false); + listSourceResources(indirName, resources); + + File binBase = openFile(outdirName); + File[] toResources = FileUtil.listFiles(binBase, aspectjResourceFileFilter); + for (int i = 0; i < toResources.length; i++) { + String fileName = FileUtil.normalizedPath(toResources[i], binBase); + + /* Ensure we copied the right JAR manifest */ + if (fileName.equalsIgnoreCase("meta-inf/Manifest.mf")) { + byte[] outManifest = FileUtil.readAsByteArray(toResources[i]); + assertTrue("Wrong manifest has been copied", Arrays.equals(inManifest, outManifest)); + } + boolean b = resources.remove(fileName); + assertTrue("Extraneous resources: " + fileName, b); + } + + assertTrue("Missing resources: " + resources.toString(), resources.isEmpty()); + } catch (IOException ex) { + fail(ex.toString()); + } + } + + /** + * Look in the specified jar file for resources (anything not .class) and add it the resources Set. + * + * @param injarFile jar file to open up + * @param resources the set where resources should be accumulated + * @param wantDirectories should any directories found in the jar be included + * @return the byte data for any discovered manifest + */ + private byte[] listJarResources(File injarFile, Set<String> resources, boolean wantDirectories) { + byte[] manifest = null; + + try { + ZipInputStream injar = new ZipInputStream(new java.io.FileInputStream(injarFile)); + ZipEntry entry; + while (null != (entry = injar.getNextEntry())) { + String fileName = entry.getName(); + if (entry.isDirectory()) { + if (wantDirectories) { + resources.add(fileName); + } + } else if (!fileName.endsWith(".class")) { + + /* JAR manifests shouldn't be copied */ + if (fileName.equalsIgnoreCase("meta-inf/Manifest.mf")) { + manifest = FileUtil.readAsByteArray(injar); + } + resources.add(fileName); + } + injar.closeEntry(); + } + injar.close(); + } catch (IOException ex) { + fail(ex.toString()); + } + + return manifest; + } +} diff --git a/ajde.core/src/test/java/org/aspectj/ajde/core/tests/ReweavableTest.java b/ajde.core/src/test/java/org/aspectj/ajde/core/tests/ReweavableTest.java new file mode 100644 index 000000000..24723b253 --- /dev/null +++ b/ajde.core/src/test/java/org/aspectj/ajde/core/tests/ReweavableTest.java @@ -0,0 +1,373 @@ +/* ******************************************************************* + * Copyright (c) 2004 Contributors. + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andy Clement Initial version + * Helen Hawkins Converted to new interface (bug 148190) + * ******************************************************************/ +package org.aspectj.ajde.core.tests; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Set; + +import org.aspectj.ajde.core.AjdeCoreTestCase; +import org.aspectj.ajde.core.TestCompilerConfiguration; +import org.aspectj.ajde.core.TestMessageHandler; +import org.aspectj.bridge.IMessage; + +public class ReweavableTest extends AjdeCoreTestCase { + + private static final boolean debugTests = false; + + public static final String binDir = "bin"; + + public static final String indir1Name = "indir1"; + public static final String indir2Name = "indir2"; + public static final String injarName = "injar.jar"; + public static final String outjarName = "/bin/output.jar"; + + private TestMessageHandler handler; + private TestCompilerConfiguration compilerConfig; + + @Override + protected void setUp() throws Exception { + super.setUp(); + initialiseProject("ReweavableTest"); + handler = (TestMessageHandler) getCompiler().getMessageHandler(); + handler.dontIgnore(IMessage.INFO); + compilerConfig = (TestCompilerConfiguration) getCompiler().getCompilerConfiguration(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + handler = null; + compilerConfig = null; + } + + /** + * Aim: Check we haven't damaged 'normal compilation' when not supplying -Xreweavable. Also determines baseline sizes for the + * compiled class files for later comparison. + * + * Inputs to the compiler: NonReweavable1.lst -> CalculatePI.java -> Logger.aj -> -verbose -> -noExit + * + * Expected result = Compile successful, the types will not be reweavable and the weaver should not report it is running in + * reweavable mode. + */ + public void testNonReweavableCompile() { + if (debugTests) + System.out.println("testNonReweavableCompile: Building with NonReweavable1.lst"); + String[] files = new String[] { "CalculatePI.java", "Logger.aj" }; + compilerConfig.setProjectSourceFiles(getSourceFileList(files)); + compilerConfig.setNonStandardOptions("-verbose -noExit -XnotReweavable"); + + doBuild(true); + + assertFalse("Did not expect to find a message about the weaver operating " + "in reweavable mode", + checkFor("weaver operating in reweavable mode")); + + File fCalc = openFile("bin/CalculatePI.class"); + File fLog = openFile("bin/Logger.class"); + assertTrue("bin/CalculatePI.class should exist?!?", fCalc.exists()); + assertTrue("bin/Logger.class should exist?!?", fLog.exists()); + if (debugTests) + System.out.println("CalculatePI.class is of size: " + fCalc.length()); + if (debugTests) + System.out.println("Logger.class is of size: " + fLog.length()); + if (debugTests) + System.out.println("\n\n\n"); + /* nonreweavesize_CalculatePI = (int) */fCalc.length(); + /* nonreweavesize_Logger = (int) */fLog.length(); + } + + /** + * Aim: Basic call to -Xreweavable. Weaver should report it is in reweavable mode and the classes produced should be much larger + * than normal classes (those produced in the first test). + * + * Inputs to the compiler: Reweavable1.lst -> CalculatePI.java -> Logger.aj -> -Xreweavable -> -verbose -> -noExit + * + * Expected result = Compile successful, the types will be reweavable and the weaver should report it is running in reweavable + * mode. The files produced should be larger than those created during the last test. + */ + public void testReweavableCompile() { + if (debugTests) + System.out.println("testReweavableCompile: Building with Reweavable1.lst"); + String[] files = new String[] { "CalculatePI.java", "Logger.aj" }; + compilerConfig.setProjectSourceFiles(getSourceFileList(files)); + compilerConfig.setNonStandardOptions("-verbose -noExit"); + + doBuild(true); + + assertTrue("Expected a message about operating in reweavable mode, but " + "didn't get one", + checkFor("weaver operating in reweavable mode")); + + File fCalc = openFile("bin/CalculatePI.class"); + File fLog = openFile("bin/Logger.class"); + assertTrue("bin/CalculatePI.class should exist?!?", fCalc.exists()); + assertTrue("bin/Logger.class should exist?!?", fLog.exists()); + if (debugTests) + System.out.println("CalculatePI.class is of size: " + fCalc.length()); + if (debugTests) + System.out.println("Logger.class is of size: " + fLog.length()); + // Temporarily remove these tests - it seems the order in which the + // testXXX methods are run cannot be relied upon + // so reweavablesize_XXX fields might not have been set yet. + // assertTrue("Reweavable version should be larger than non-reweavable + // version of CalculatePI", + // fCalc.length()>nonreweavesize_CalculatePI); + // assertTrue("Reweavable version should be larger than non-reweavable + // version of Logger", + // fLog.length()>nonreweavesize_Logger); + + /* reweavablesize_CalculatePI = (int) */fCalc.length(); + /* reweavablesize_Logger = (int) */fLog.length(); + + if (debugTests) + System.out.println("\n\n\n"); + } + + /** + * Aim: Use the optional ':compress' modifier on -Xreweavable. This causes some of the meta-data for use in reweaving to be + * compressed. It should succeed and produce class files smaller than straight -Xreweavable but larger than without specifying + * -Xreweavable. + * + * Inputs to the compiler: ReweavableCompress1.lst -> CalculatePI.java -> Logger.aj -> -Xreweavable:compress -> -verbose -> + * -noExit + * + * Expected result = Compile successful, the types will be reweavable and the weaver should report it is running in reweavable + * mode. The files created should have a size between the non-reweavable versions and the reweavable (without compression) + * versions. + */ + public void testReweavableCompressCompile() { + if (debugTests) + System.out.println("testReweavableCompressCompile: Building with ReweavableCompress1.lst"); + + String[] files = new String[] { "CalculatePI.java", "Logger.aj" }; + compilerConfig.setProjectSourceFiles(getSourceFileList(files)); + compilerConfig.setNonStandardOptions("-Xreweavable:compress -verbose -noExit"); + + doBuild(true); + + assertTrue("Expected a message about operating in reweavable mode, but didn't get one", + checkFor("weaver operating in reweavable mode")); + + File fCalc = openFile("bin/CalculatePI.class"); + File fLog = openFile("bin/Logger.class"); + assertTrue("bin/CalculatePI.class should exist?!?", fCalc.exists()); + assertTrue("bin/Logger.class should exist?!?", fLog.exists()); + int calclen = (int) fCalc.length(); + int loglen = (int) fLog.length(); + if (debugTests) + System.out.println("CalculatePI.class is of size: " + calclen); + if (debugTests) + System.out.println("Logger.class is of size: " + loglen); + // Temporarily remove these tests - it seems the order in which the + // testXXX methods are run cannot be relied upon + // so reweavablesize_XXX fields might not have been set yet. + // assertTrue("Reweavable version should be larger than non-reweavable + // version of CalculatePI", + // calclen>nonreweavesize_CalculatePI); + // assertTrue("Reweavable version should be larger than non-reweavable + // version of Logger", + // loglen>nonreweavesize_Logger); + + // Temporarily remove these tests - it seems the order in which the + // testXXX methods are run cannot be relied upon + // so reweavablesize_XXX fields might not have been set yet. + // assertTrue("Reweavable (with compression) version should be smaller + // than reweavable (without compression) version of CalculatePI:" + + // " Compressed version:"+calclen+"bytes Non-compressed + // version:"+reweavablesize_CalculatePI+"bytes", + // calclen<reweavablesize_CalculatePI); + // assertTrue("Reweavable (with compression) version should be smaller + // than reweavable (without compression) version of Logger"+ + // " Compressed version:"+loglen+"bytes Non-compressed + // version:"+reweavablesize_Logger+"bytes", + // loglen<reweavablesize_Logger); + + if (debugTests) + System.out.println("\n\n\n"); + } + + /** + * Aim: The tests above have determined that reweaving appears to be behaving in terms of the .class files it is creating. Now + * lets actually attempt a reweave. For this, we build two files as reweavable and then build a single file whilst specifying an + * inpath that contains the .class files from the first compile. This should succeed. + * + * Inputs to the first compile: Reweavable1.lst -> CalculatePI.java -> Logger.aj -> -Xreweavable -> -verbose -> -noExit + * + * Input to the second compile: Reweavable2.lst -> SecondAspect.aj -> -Xreweavable -> -verbose -> -noExit -inpath bin\. + * + * Expected result = Both compiles will succeed. + */ + public void testReweavableSimpleCompile() { + if (debugTests) + System.out.println("testReweavableSimpleCompile: Building with Reweavable1.lst"); + + String[] files = new String[] { "CalculatePI.java", "Logger.aj" }; + compilerConfig.setProjectSourceFiles(getSourceFileList(files)); + compilerConfig.setNonStandardOptions("-verbose -noExit"); + + doBuild(true); + + assertTrue("Expected a message about operating in reweavable mode, but didn't get one", + checkFor("weaver operating in reweavable mode")); + + if (debugTests) + System.out.println("\ntestReweavableSimpleCompile: Building with Reweavable2.lst"); + Set<File> paths = new HashSet<>(); + paths.add(openFile(binDir)); + compilerConfig.setInpath(paths); + String[] newFiles = new String[] { "SecondAspect.aj" }; + compilerConfig.setProjectSourceFiles(getSourceFileList(newFiles)); + + doBuild(true); + + String expMessage = "successfully verified type Logger exists"; + assertTrue("Expected message '" + expMessage + "' but did not find it", checkFor(expMessage)); + + File fCalc = openFile("bin/CalculatePI.class"); + File fLog = openFile("bin/Logger.class"); + File fSec = openFile("bin/SecondAspect.class"); + assertTrue("bin/CalculatePI.class should exist?!?", fCalc.exists()); + assertTrue("bin/Logger.class should exist?!?", fLog.exists()); + assertTrue("bin/SecondAspect.class should exist?!?", fSec.exists()); + + if (debugTests) + System.out.println("\n\n\n"); + } + + /** + * Aim: Based on the test above, if we delete Logger.class between the first and second compiles the second compile should fail + * because there is not enough information to reweave CalculatePI + * + * Inputs to the first compile: Reweavable1.lst -> CalculatePI.java -> Logger.aj -> -Xreweavable -> -verbose -> -noExit + * + * Input to the second compile: Reweavable2.lst -> SecondAspect.aj -> -Xreweavable -> -verbose -> -noExit -inpath bin\. + * + * Expected result = Second compile will fail - reporting that Logger is missing (it 'touched' in the first compile CalculatePI) + */ + public void testForReweavableSimpleErrorCompile() { + if (debugTests) + System.out.println("testForReweavableSimpleErrorCompile: Building with Reweavable2.lst"); + + String[] files = new String[] { "CalculatePI.java", "Logger.aj" }; + compilerConfig.setProjectSourceFiles(getSourceFileList(files)); + compilerConfig.setNonStandardOptions("-verbose -noExit"); + + doBuild(true); + + assertTrue("Expected a message about operating in reweavable mode, but didn't get one", + checkFor("weaver operating in reweavable mode")); + + assertTrue("Could not delete bin/Logger.class??", openFile("bin/Logger.class").delete()); + + if (debugTests) + System.out.println("\ntestForReweavableSimpleErrorCompile: Building with Reweavable2.lst"); + Set<File> paths = new HashSet<>(); + paths.add(openFile(binDir)); + compilerConfig.setInpath(paths); + String[] newFiles = new String[] { "SecondAspect.aj" }; + compilerConfig.setProjectSourceFiles(getSourceFileList(newFiles)); + + doBuild(true); + + String expMessage = "aspect Logger cannot be found when reweaving CalculatePI"; + assertTrue("Expected message '" + expMessage + "' but did not find it", checkFor(expMessage)); + + File fCalc = openFile("bin/CalculatePI.class"); + File fLog = openFile("bin/Logger.class"); + File fSec = openFile("bin/SecondAspect.class"); + assertTrue("bin/CalculatePI.class should exist!", fCalc.exists()); + assertTrue("bin/Logger.class should not exist!", !fLog.exists()); + assertTrue("bin/SecondAspect.class should not exist!", fSec.exists()); + + if (debugTests) + System.out.println("\n\n\n"); + } + + /** + * Aim: Based on the test above, if we delete Logger.class between the first and second compiles the second compile should fail + * because there is not enough information to reweave CalculatePI + * + * Inputs to the first compile: TJP1.lst -> tjp/Demo.java -> tjp/GetInfo.java -> -Xreweavable -> -verbose -> -noExit + * + * Now, delete bin\tjp\GetInfo.class and do a compile with: TJP2.lst -> -Xreweavable -> -verbose -> -noExit -inpath bin\. + * + * Expected result = Second compile will fail - reporting that tjp.GetInfo is missing (it 'touched' in the first compile + * tjp.Demo) + */ + public void testErrorScenario2Compile() { + if (debugTests) + System.out.println("testErrorScenario2: Building with TJP1.lst"); + + String[] files = new String[] { "tjp" + File.separator + "Demo.java", "tjp" + File.separator + "GetInfo.java" }; + compilerConfig.setProjectSourceFiles(getSourceFileList(files)); + compilerConfig.setNonStandardOptions("-verbose -noExit"); + + doBuild(true); + + assertTrue("Expected a message about operating in reweavable mode, but didn't get one", + checkFor("weaver operating in reweavable mode")); + + assertTrue("Could not delete bin/tjp/GetInfo.class??", openFile("bin/tjp/GetInfo.class").delete()); + + if (debugTests) + System.out.println("\ntestErrorScenario2: Building with TJP2.lst"); + Set<File> paths = new HashSet<>(); + paths.add(openFile(binDir)); + compilerConfig.setInpath(paths); + compilerConfig.setProjectSourceFiles(new ArrayList<String>()); + doBuild(true); + + String expMessage = "aspect tjp.GetInfo cannot be found when reweaving tjp.Demo"; + assertTrue("Expected message '" + expMessage + "' but did not find it", checkFor(expMessage)); + + File fDemo = openFile("bin/tjp/Demo.class"); + File fGetInfo = openFile("bin/tjp/GetInfo.class"); + assertTrue("bin/tjp/Demo.class should exist!", fDemo.exists()); + assertTrue("bin/tjp/GetInfo.class should not exist!", !fGetInfo.exists()); + + if (debugTests) + System.out.println("\n\n\n"); + } + + public void testWorkingScenario2Compile() { + if (debugTests) + System.out.println("testWorkingScenario2: Building with TJP1.lst"); + String[] files = new String[] { "tjp" + File.separator + "Demo.java", "tjp" + File.separator + "GetInfo.java" }; + compilerConfig.setProjectSourceFiles(getSourceFileList(files)); + compilerConfig.setNonStandardOptions("-Xreweavable:compress -verbose -noExit"); + + doBuild(true); + + assertTrue("Expected a message about operating in reweavable mode, but didn't get one", + checkFor("weaver operating in reweavable mode")); + + if (debugTests) + System.out.println("\ntestWorkingScenario2: Building with TJP2.lst"); + Set<File> paths = new HashSet<>(); + paths.add(openFile(binDir)); + compilerConfig.setInpath(paths); + compilerConfig.setProjectSourceFiles(new ArrayList<String>()); + doBuild(true); + + String expMessage = "successfully verified type tjp.GetInfo exists"; + assertTrue("Expected message '" + expMessage + "' but did not find it", checkFor(expMessage)); + + File fGetInfo = openFile("bin/tjp/GetInfo.class"); + File fDemo = openFile("bin/tjp/Demo.class"); + assertTrue("bin/tjp/GetInfo.class should exist!", fGetInfo.exists()); + assertTrue("bin/tjp/Demo.class should not exist!", fDemo.exists()); + + if (debugTests) + System.out.println("\n\n\n"); + } +} diff --git a/ajde.core/src/test/java/org/aspectj/ajde/core/tests/ShowWeaveMessagesTest.java b/ajde.core/src/test/java/org/aspectj/ajde/core/tests/ShowWeaveMessagesTest.java new file mode 100644 index 000000000..c13462620 --- /dev/null +++ b/ajde.core/src/test/java/org/aspectj/ajde/core/tests/ShowWeaveMessagesTest.java @@ -0,0 +1,439 @@ +/* ******************************************************************* + * Copyright (c) 2004 Contributors. + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andy Clement Initial version + * Helen Hawkins Converted to new interface (bug 148190) + * ******************************************************************/ +package org.aspectj.ajde.core.tests; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Hashtable; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.aspectj.ajde.core.AjdeCoreTestCase; +import org.aspectj.ajde.core.JavaOptions; +import org.aspectj.ajde.core.TestCompilerConfiguration; +import org.aspectj.ajde.core.TestMessageHandler; +import org.aspectj.bridge.IMessage; +import org.aspectj.util.LangUtil; + +/** + * Weaving messages are complicated things. There are multiple places where weaving takes place and the places vary depending on + * whether we are doing a binary weave or going from source. All places that output weaving messages are tagged: // TAG: + * WeavingMessage so you can easily find them! + * + * Advice is the simplest to deal with as that is advice weaving is always done in the weaver. + * + * Next is intertype declarations. These are also always done in the weaver but in the case of a binary weave we don't know the + * originating source line for the ITD. + * + * Finally, declares. Declare Parents: extends Can only be done when going from source, if attempted by a binary weave then an error + * message (compiler limitation) is produced. Declare Parents: implements Is (currently!) done at both compile time and weave time. + * If going from source then the message is produced by the code in the compiler. if going from binary then the message is produced + * by the weaver. Declare Soft: Comes out with 'advice' as a special kind of advice: softener advice + * + * + * Q: Where are the messages turned on/off? A: It is a bit messy. See BuildArgParser.genBuildConfig(). Basically that method is the + * first time we parse the option set. Whether weaving messages are on or off is stored in the build config. As soon as we have + * parser the options and determined that weave messages are on, we grab the top level message handler and tell it not to ignore + * WeaveInfo messages. + * + * + * TODO - Other forms of declare? Do they need messages? e.g. declare precedence * + */ +public class ShowWeaveMessagesTest extends AjdeCoreTestCase { + + private static boolean regenerate; + private static boolean debugTests = false; + + static { + // Switch this to true for a single iteration if you want to reconstruct the + // 'expected weaving messages' files. + regenerate = false; + } + + public static final String PROJECT_DIR = "WeaveInfoMessagesTest"; + + public static final String binDir = "bin"; + public static final String expectedResultsDir = "expected"; + + public String[] one = new String[] { "AspectAdvice.aj", "Simple.java" }; + public String[] two = new String[] { "AspectITD.aj", "Simple.java" }; + public String[] three = new String[] { "AspectDeclare.aj", "Simple.java" }; + public String[] four = new String[] { "AspectDeclareExtends.aj", "Simple.java" }; + public String[] five = new String[] { "Simple.java", "AspectDeclareSoft.aj" }; + public String[] six = new String[] { "AspectDeclareAnnotations.aj" }; + public String[] seven = new String[] { "AspectDeclareAnnotations.aj" }; + public String[] empty = new String[] {}; + + private TestMessageHandler handler; + private TestCompilerConfiguration compilerConfig; + + @Override + protected void setUp() throws Exception { + super.setUp(); + initialiseProject(PROJECT_DIR); + handler = (TestMessageHandler) getCompiler().getMessageHandler(); + handler.dontIgnore(IMessage.WEAVEINFO); + compilerConfig = (TestCompilerConfiguration) getCompiler().getCompilerConfiguration(); + compilerConfig.setNonStandardOptions("-showWeaveInfo"); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + handler = null; + compilerConfig = null; + } + + /** + * Weave all the possible kinds of advice and verify the messages that come out. + */ + public void testWeaveMessagesAdvice() { + if (debugTests) + System.out.println("testWeaveMessagesAdvice: Building with One.lst"); + compilerConfig.setProjectSourceFiles(getSourceFileList(one)); + doBuild(); + assertTrue("Expected no compiler errors but found " + handler.getErrors(), handler.getErrors().isEmpty()); + verifyWeavingMessages("advice", true); + } + + /** + * Weave field and method ITDs and check the weave messages that come out. + */ + public void testWeaveMessagesITD() { + if (debugTests) + System.out.println("\ntestWeaveMessagesITD: Building with Two.lst"); + compilerConfig.setProjectSourceFiles(getSourceFileList(two)); + doBuild(); + assertTrue("Expected no compiler errors but found " + handler.getErrors(), handler.getErrors().isEmpty()); + verifyWeavingMessages("itd", true); + } + + /** + * Weave "declare parents: implements" and check the weave messages that come out. + */ + public void testWeaveMessagesDeclare() { + if (debugTests) + System.out.println("\ntestWeaveMessagesDeclare: Building with Three.lst"); + compilerConfig.setProjectSourceFiles(getSourceFileList(three)); + doBuild(); + assertTrue("Expected no compiler errors but found " + handler.getErrors(), handler.getErrors().isEmpty()); + verifyWeavingMessages("declare1", true); + } + + /** + * Weave "declare parents: extends" and check the weave messages that come out. Can't do equivalent binary test - as can't do + * extends in binary. + */ + public void testWeaveMessagesDeclareExtends() { + if (debugTests) + System.out.println("\ntestWeaveMessagesDeclareExtends: Building with Four.lst"); + compilerConfig.setProjectSourceFiles(getSourceFileList(four)); + doBuild(); + assertTrue("Expected no compiler errors but found " + handler.getErrors(), handler.getErrors().isEmpty()); + verifyWeavingMessages("declare.extends", true); + } + + /** + * Weave "declare soft: type: pointcut" and check the weave messages that come out. + */ + public void testWeaveMessagesDeclareSoft() { + if (debugTests) + System.out.println("\ntestWeaveMessagesDeclareSoft: Building with Five.lst"); + compilerConfig.setProjectSourceFiles(getSourceFileList(five)); + doBuild(); + assertTrue("Expected no compiler errors but found " + handler.getErrors(), handler.getErrors().isEmpty()); + verifyWeavingMessages("declare.soft", true); + } + + /** + * Weave 'declare @type, @constructor, @method and @field' and check the weave messages that come out. + */ + public void testWeaveMessagesDeclareAnnotation() { + if (!LangUtil.is15VMOrGreater()) + return; // annotation classes won't be about pre 15 + if (debugTests) + System.out.println("\ntestWeaveMessagesDeclareAnnotation: Building with Six.lst"); + compilerConfig.setProjectSourceFiles(getSourceFileList(six)); + setRunIn15Mode(); + compilerConfig.setNonStandardOptions("-showWeaveInfo -1.5"); + doBuild(); + assertTrue("Expected no compiler errors but found " + handler.getErrors(), handler.getErrors().isEmpty()); + verifyWeavingMessages("declare.annotation", true); + } + + /** + * Weave 'declare @type, @constructor, @method and @field' and check the weave messages don't come out without the + * -showWeaveInfo arg. + */ + public void testWeaveMessagesDeclareAnnotationWeaveInfoOff() { + if (debugTests) + System.out.println("\ntestWeaveMessagesDeclareAnnotation: Building with Seven.lst"); + compilerConfig.setProjectSourceFiles(getSourceFileList(seven)); + compilerConfig.setNonStandardOptions(""); + setRunIn15Mode(); + doBuild(); + assertTrue("Expected no compiler errors but found " + handler.getErrors(), handler.getErrors().isEmpty()); + verifyWeavingMessages("declare.annotationNoWeaveInfo", true); + } + + // BINARY WEAVING TESTS + + /** + * Binary weave variant of the advice weaving test above - to check messages are ok for binary weave. Unlike the source level + * weave, in this test we are using an aspect on the aspectpath - which means it has already had its necessary parts woven - so + * the list of weaving messages we expect is less. + */ + public void testWeaveMessagesBinaryAdvice() { + if (debugTests) + System.out.println("\ntestWeaveMessagesBinaryAdvice: Simple.jar + AspectAdvice.jar"); + Set<File> inpath = new HashSet<File>(); + inpath.add(openFile("Simple.jar")); + compilerConfig.setInpath(inpath); + Set<File> aspectpath = new HashSet<File>(); + aspectpath.add(openFile("AspectAdvice.jar")); + compilerConfig.setAspectPath(aspectpath); + doBuild(); + assertTrue("Expected no compiler errors but found " + handler.getErrors(), handler.getErrors().isEmpty()); + verifyWeavingMessages("advice.binary", true); + } + + public void testWeaveMessagesBinaryITD() { + if (debugTests) + System.out.println("\ntestWeaveMessagesBinaryITD: Simple.jar + AspectITD.jar"); + Set<File> inpath = new HashSet<File>(); + inpath.add(openFile("Simple.jar")); + compilerConfig.setInpath(inpath); + Set<File> aspectpath = new HashSet<File>(); + aspectpath.add(openFile("AspectITD.jar")); + compilerConfig.setAspectPath(aspectpath); + doBuild(); + assertTrue("Expected no compiler errors but found " + handler.getErrors(), handler.getErrors().isEmpty()); + verifyWeavingMessages("itd", false); + } + + public void testWeaveMessagesBinaryDeclare() { + if (debugTests) + System.out.println("\ntestWeaveMessagesBinaryDeclare: Simple.jar + AspectDeclare.jar"); + Set<File> inpath = new HashSet<File>(); + inpath.add(openFile("Simple.jar")); + compilerConfig.setInpath(inpath); + Set<File> aspectpath = new HashSet<File>(); + aspectpath.add(openFile("AspectDeclare.jar")); + compilerConfig.setAspectPath(aspectpath); + doBuild(); + assertTrue("Expected no compiler errors but found " + handler.getErrors(), handler.getErrors().isEmpty()); + verifyWeavingMessages("declare1", false); + } + + /** + * Weave "declare soft: type: pointcut" and check the weave messages that come out. + */ + public void testWeaveMessagesBinaryDeclareSoft() { + if (debugTests) + System.out.println("\ntestWeaveMessagesBinaryDeclareSoft: Simple.jar + AspectDeclareSoft.jar"); + Set<File> inpath = new HashSet<File>(); + inpath.add(openFile("Simple.jar")); + compilerConfig.setInpath(inpath); + Set<File> aspectpath = new HashSet<File>(); + aspectpath.add(openFile("AspectDeclareSoft.jar")); + compilerConfig.setAspectPath(aspectpath); + doBuild(); + assertTrue("Expected no compiler errors but found " + handler.getErrors(), handler.getErrors().isEmpty()); + verifyWeavingMessages("declare.soft.binary", true); + } + + public void testWeaveMessagesBinaryAdviceInPackageFromJar() { + if (debugTests) + System.out.println("\ntestWeaveMessagesBinaryAdviceInPackageFromJar: Simple.jar + AspectInPackage.jar"); + Set<File> inpath = new HashSet<File>(); + inpath.add(openFile("Simple.jar")); + compilerConfig.setInpath(inpath); + Set<File> aspectpath = new HashSet<File>(); + aspectpath.add(openFile("AspectInPackage.jar")); + compilerConfig.setAspectPath(aspectpath); + doBuild(); + assertTrue("Expected no compiler errors but found " + handler.getErrors(), handler.getErrors().isEmpty()); + verifyWeavingMessages("advice.binary.package.jar", true); + } + + public void testWeaveMessagesBinaryAdviceInPackage() { + if (debugTests) + System.out.println("\ntestWeaveMessagesBinaryAdviceInPackage: Simple.jar + AspectInPackage.jar"); + Set<File> inpath = new HashSet<File>(); + inpath.add(openFile("Simple.jar")); + compilerConfig.setInpath(inpath); + Set<File> aspectpath = new HashSet<File>(); + aspectpath.add(openFile("pkg")); + compilerConfig.setAspectPath(aspectpath); + doBuild(); + assertTrue("Expected no compiler errors but found " + handler.getErrors(), handler.getErrors().isEmpty()); + verifyWeavingMessages("advice.binary.package", true); + } + + // BINARY WEAVING WHEN WE'VE LOST THE SOURCE POINTERS + + public void testWeaveMessagesBinaryAdviceNoDebugInfo() { + if (debugTests) + System.out.println("\ntestWeaveMessagesBinaryAdvice: Simple.jar + AspectAdvice.jar"); + Set<File> inpath = new HashSet<File>(); + inpath.add(openFile("Simple_nodebug.jar")); + compilerConfig.setInpath(inpath); + Set<File> aspectpath = new HashSet<File>(); + aspectpath.add(openFile("AspectAdvice_nodebug.jar")); + compilerConfig.setAspectPath(aspectpath); + doBuild(); + assertTrue("Expected no compiler errors but found " + handler.getErrors(), handler.getErrors().isEmpty()); + verifyWeavingMessages("advice.binary.nodebug", true); + } + + public void testWeaveMessagesBinaryITDNoDebugInfo() { + if (debugTests) + System.out.println("\ntestWeaveMessagesBinaryITD: Simple.jar + AspectITD.jar"); + Set<File> inpath = new HashSet<>(); + inpath.add(openFile("Simple_nodebug.jar")); + compilerConfig.setInpath(inpath); + Set<File> aspectpath = new HashSet<>(); + aspectpath.add(openFile("AspectITD_nodebug.jar")); + compilerConfig.setAspectPath(aspectpath); + doBuild(); + assertTrue("Expected no compiler errors but found " + handler.getErrors(), handler.getErrors().isEmpty()); + verifyWeavingMessages("itd.nodebug", true); + } + + public void testWeaveMessagesBinaryDeclareNoDebugInfo() { + if (debugTests) + System.out.println("\ntestWeaveMessagesBinaryDeclareNoDebugInfo: Simple.jar + AspectDeclare.jar"); + Set<File> inpath = new HashSet<File>(); + inpath.add(openFile("Simple_nodebug.jar")); + compilerConfig.setInpath(inpath); + Set<File> aspectpath = new HashSet<File>(); + aspectpath.add(openFile("AspectDeclare_nodebug.jar")); + compilerConfig.setAspectPath(aspectpath); + doBuild(); + assertTrue("Expected no compiler errors but found " + handler.getErrors(), handler.getErrors().isEmpty()); + verifyWeavingMessages("declare1.nodebug", true); + } + + /** + * Weave "declare soft: type: pointcut" and check the weave messages that come out. + */ + public void testWeaveMessagesBinaryDeclareSoftNoDebugInfo() { + if (debugTests) + System.out.println("\ntestWeaveMessagesBinaryDeclareSoftNoDebugInfo: Simple.jar + AspectDeclareSoft.jar"); + Set<File> inpath = new HashSet<File>(); + inpath.add(openFile("Simple_nodebug.jar")); + compilerConfig.setInpath(inpath); + Set<File> aspectpath = new HashSet<File>(); + aspectpath.add(openFile("AspectDeclareSoft_nodebug.jar")); + compilerConfig.setAspectPath(aspectpath); + doBuild(); + assertTrue("Expected no compiler errors but found " + handler.getErrors(), handler.getErrors().isEmpty()); + verifyWeavingMessages("declare.soft.binary.nodebug", true); + } + + public void verifyWeavingMessages(String testid, boolean source) { + File expectedF = openFile(expectedResultsDir + File.separator + testid + ".txt"); + if (regenerate && source) { + // Create the file + saveWeaveMessages(expectedF); + } else { + // Verify the file matches what we have + compareWeaveMessages(expectedF); + } + } + + /** + * Compare weaving messages with what is in the file + */ + private void compareWeaveMessages(File f) { + List<String> fileContents = new ArrayList<>(); + BufferedReader fr; + try { + // Load the file in + fr = new BufferedReader(new FileReader(f)); + String line = null; + while ((line = fr.readLine()) != null) + fileContents.add(line); + List<String> originalFileContents = new ArrayList<>(); + originalFileContents.addAll(fileContents); + + // See if the messages match + int msgCount = 0; + List<TestMessageHandler.TestMessage> l = handler.getMessages(); + for (Iterator<TestMessageHandler.TestMessage> iter = l.iterator(); iter.hasNext();) { + IMessage msg = iter.next().getContainedMessage(); + if (debugTests) + System.out.println("Looking at [" + msg + "]"); + if (msg.getKind().equals(IMessage.WEAVEINFO)) { + if (!fileContents.contains(msg.getMessage())) { + fail("Could not find message '" + msg.getMessage() + "' in the expected results. Expected results are:\n" + + stringify(originalFileContents)); + } else { + fileContents.remove(msg.getMessage()); + } + msgCount++; + } + } + assertTrue("Didn't get these expected messages: " + fileContents, fileContents.size() == 0); + if (debugTests) + System.out.println("Successfully verified " + msgCount + " weaving messages"); + } catch (Exception e) { + fail("Unexpected exception saving weaving messages:" + e); + } + } + + private String stringify(List<String> l) { + StringBuffer result = new StringBuffer(); + for (String str: l) { + result.append(str); + result.append("\n"); + } + return result.toString(); + } + + /** + * Store the weaving messages in the specified file. + */ + private void saveWeaveMessages(File f) { + System.out.println("Saving weave messages into " + f.getName()); + FileWriter fw; + try { + fw = new FileWriter(f); + List<TestMessageHandler.TestMessage> l = handler.getMessages(); + for (Iterator<TestMessageHandler.TestMessage> iter = l.iterator(); iter.hasNext();) { + IMessage msg = iter.next().getContainedMessage(); + if (msg.getKind().equals(IMessage.WEAVEINFO)) { + fw.write(msg.getMessage() + "\n"); + } + } + fw.close(); + } catch (Exception e) { + fail("Unexpected exception saving weaving messages:" + e); + } + } + + private void setRunIn15Mode() { + Map<String, String> m = new Hashtable<>(); + m.put(JavaOptions.COMPLIANCE_LEVEL, JavaOptions.VERSION_15); + m.put(JavaOptions.SOURCE_COMPATIBILITY_LEVEL, JavaOptions.VERSION_15); + m.put(JavaOptions.TARGET_COMPATIBILITY_LEVEL, JavaOptions.VERSION_15); + compilerConfig.setJavaOptions(m); + } + +} diff --git a/ajde.core/src/test/java/org/aspectj/ajde/core/tests/model/AsmDeclarationsTest.java b/ajde.core/src/test/java/org/aspectj/ajde/core/tests/model/AsmDeclarationsTest.java new file mode 100644 index 000000000..7a2ec9fc5 --- /dev/null +++ b/ajde.core/src/test/java/org/aspectj/ajde/core/tests/model/AsmDeclarationsTest.java @@ -0,0 +1,223 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * ******************************************************************/ +package org.aspectj.ajde.core.tests.model; + +import java.io.File; + +import org.aspectj.ajde.core.AjdeCoreTestCase; +import org.aspectj.ajde.core.TestCompilerConfiguration; +import org.aspectj.asm.AsmManager; +import org.aspectj.asm.IHierarchy; +import org.aspectj.asm.IProgramElement; + +public class AsmDeclarationsTest extends AjdeCoreTestCase { + + private AsmManager manager = null; + private IHierarchy model = null; + + private final String[] files = new String[] { "ModelCoverage.java", "pkg" + File.separator + "InPackage.java" }; + + private TestCompilerConfiguration compilerConfig; + + protected void setUp() throws Exception { + super.setUp(); + initialiseProject("coverage"); + compilerConfig = (TestCompilerConfiguration) getCompiler().getCompilerConfiguration(); + compilerConfig.setProjectSourceFiles(getSourceFileList(files)); + compilerConfig.setNonStandardOptions("-Xset:minimalModel=false"); + doBuild(); + manager = AsmManager.lastActiveStructureModel; + model = AsmManager.lastActiveStructureModel.getHierarchy(); + } + + protected void tearDown() throws Exception { + super.tearDown(); + compilerConfig = null; + model = null; + } + + public void testRoot() { + IProgramElement root = model.getRoot(); + assertNotNull(root); + assertEquals("Expected root to be named 'coverage' but found " + root.toLabelString(), root.toLabelString(), "coverage"); + } + + public void testAspectAccessibility() { + IProgramElement packageAspect = model.findElementForType(null, "AdviceNamingCoverage"); + assertNotNull(packageAspect); + assertEquals(IProgramElement.Accessibility.PACKAGE, packageAspect.getAccessibility()); + assertEquals("aspect should not have public in it's signature", "aspect AdviceNamingCoverage", + packageAspect.getSourceSignature()); + } + + public void testStaticModifiers() { + IProgramElement aspect = model.findElementForType(null, "ModifiersCoverage"); + assertNotNull(aspect); + + IProgramElement staticA = model.findElementForSignature(aspect, IProgramElement.Kind.FIELD, "staticA"); + assertTrue(staticA.getModifiers().contains(IProgramElement.Modifiers.STATIC)); + + IProgramElement finalA = model.findElementForSignature(aspect, IProgramElement.Kind.FIELD, "finalA"); + assertTrue(!finalA.getModifiers().contains(IProgramElement.Modifiers.STATIC)); + assertTrue(finalA.getModifiers().contains(IProgramElement.Modifiers.FINAL)); + } + + public void testFileInPackageAndDefaultPackage() { + IProgramElement root = model.getRoot(); + assertEquals(root.toLabelString(), "coverage"); + IProgramElement pkg = (IProgramElement) root.getChildren().get(1); + assertEquals(pkg.toLabelString(), "pkg"); + assertEquals(((IProgramElement) pkg.getChildren().get(0)).toLabelString(), "InPackage.java"); + assertEquals(((IProgramElement) ((IProgramElement) root.getChildren().get(0)).getChildren().get(0)).toLabelString(), + "ModelCoverage.java"); + } + + public void testDeclares() { + IProgramElement node = model.getRoot(); + assertNotNull(node); + + IProgramElement aspect = model.findElementForType(null, "DeclareCoverage"); + assertNotNull(aspect); + + String label = "declare error: \"Illegal construct..\""; + IProgramElement decErrNode = model.findElementForSignature(aspect, IProgramElement.Kind.DECLARE_ERROR, "declare error"); + assertNotNull(decErrNode); + assertEquals(decErrNode.toLabelString(), label); + + String decWarnMessage = "declare warning: \"Illegal call.\""; + IProgramElement decWarnNode = model + .findElementForSignature(aspect, IProgramElement.Kind.DECLARE_WARNING, "declare warning"); + assertNotNull(decWarnNode); + assertEquals(decWarnNode.toLabelString(), decWarnMessage); + + String decParentsMessage = "declare parents: implements Serializable"; + IProgramElement decParentsNode = model.findElementForSignature(aspect, IProgramElement.Kind.DECLARE_PARENTS, + "declare parents"); + assertNotNull(decParentsNode); + assertEquals(decParentsNode.toLabelString(), decParentsMessage); + // check the next two relative to this one + int declareIndex = decParentsNode.getParent().getChildren().indexOf(decParentsNode); + String decParentsPtnMessage = "declare parents: extends Observable"; + assertEquals(decParentsPtnMessage, ((IProgramElement) aspect.getChildren().get(declareIndex + 1)).toLabelString()); + String decParentsTPMessage = "declare parents: extends Observable"; + assertEquals(decParentsTPMessage, ((IProgramElement) aspect.getChildren().get(declareIndex + 2)).toLabelString()); + + String decSoftMessage = "declare soft: SizeException"; + IProgramElement decSoftNode = model.findElementForSignature(aspect, IProgramElement.Kind.DECLARE_SOFT, "declare soft"); + assertNotNull(decSoftNode); + assertEquals(decSoftNode.toLabelString(), decSoftMessage); + + String decPrecMessage = "declare precedence: AdviceCoverage, InterTypeDecCoverage, <type pattern>"; + IProgramElement decPrecNode = model.findElementForSignature(aspect, IProgramElement.Kind.DECLARE_PRECEDENCE, + "declare precedence"); + assertNotNull(decPrecNode); + assertEquals(decPrecNode.toLabelString(), decPrecMessage); + } + + public void testInterTypeMemberDeclares() { + IProgramElement node = model.getRoot(); + assertNotNull(node); + + IProgramElement aspect = model.findElementForType(null, "InterTypeDecCoverage"); + assertNotNull(aspect); + + String fieldMsg = "Point.xxx"; + IProgramElement fieldNode = model.findElementForLabel(aspect, IProgramElement.Kind.INTER_TYPE_FIELD, fieldMsg); + assertNotNull(fieldNode); + assertEquals(fieldNode.toLabelString(), fieldMsg); + + String methodMsg = "Point.check(int,Line)"; + IProgramElement methodNode = model.findElementForLabel(aspect, IProgramElement.Kind.INTER_TYPE_METHOD, methodMsg); + assertNotNull(methodNode); + assertEquals(methodNode.toLabelString(), methodMsg); + + // TODO: enable + // String constructorMsg = "Point.new(int, int, int)"; + // ProgramElementNode constructorNode = model.findNode(aspect, ProgramElementNode.Kind.INTER_TYPE_CONSTRUCTOR, + // constructorMsg); + // assertNotNull(constructorNode); + // assertEquals(constructorNode.toLabelString(), constructorMsg); + } + + public void testPointcuts() { + IProgramElement node = model.getRoot(); + assertNotNull(node); + + IProgramElement aspect = model.findElementForType(null, "AdviceNamingCoverage"); + assertNotNull(aspect); + + String ptct = "named()"; + IProgramElement ptctNode = model.findElementForSignature(aspect, IProgramElement.Kind.POINTCUT, ptct); + assertNotNull(ptctNode); + assertEquals(ptctNode.toLabelString(), ptct); + + String params = "namedWithArgs(int,int)"; + IProgramElement paramsNode = model.findElementForSignature(aspect, IProgramElement.Kind.POINTCUT, params); + assertNotNull(paramsNode); + assertEquals(paramsNode.toLabelString(), params); + } + + public void testAbstract() { + IProgramElement node = model.getRoot(); + assertNotNull(node); + + IProgramElement aspect = model.findElementForType(null, "AbstractAspect"); + assertNotNull(aspect); + + String abst = "abPtct()"; + IProgramElement abstNode = model.findElementForSignature(aspect, IProgramElement.Kind.POINTCUT, abst); + assertNotNull(abstNode); + assertEquals(abstNode.toLabelString(), abst); + } + + public void testAdvice() { + IProgramElement node = model.getRoot(); + assertNotNull(node); + + IProgramElement aspect = model.findElementForType(null, "AdviceNamingCoverage"); + assertNotNull(aspect); + + String anon = "before(): <anonymous pointcut>"; + IProgramElement anonNode = model.findElementForLabel(aspect, IProgramElement.Kind.ADVICE, anon); + assertNotNull(anonNode); + assertEquals(anonNode.toLabelString(), anon); + + String named = "before(): named.."; + IProgramElement namedNode = model.findElementForLabel(aspect, IProgramElement.Kind.ADVICE, named); + assertNotNull(namedNode); + assertEquals(namedNode.toLabelString(), named); + + String namedWithOneArg = "around(int): namedWithOneArg.."; + IProgramElement namedWithOneArgNode = model.findElementForLabel(aspect, IProgramElement.Kind.ADVICE, namedWithOneArg); + assertNotNull(namedWithOneArgNode); + assertEquals(namedWithOneArgNode.toLabelString(), namedWithOneArg); + + String afterReturning = "afterReturning(int,int): namedWithArgs.."; + IProgramElement afterReturningNode = model.findElementForLabel(aspect, IProgramElement.Kind.ADVICE, afterReturning); + assertNotNull(afterReturningNode); + assertEquals(afterReturningNode.toLabelString(), afterReturning); + + String around = "around(int): namedWithOneArg.."; + IProgramElement aroundNode = model.findElementForLabel(aspect, IProgramElement.Kind.ADVICE, around); + assertNotNull(aroundNode); + assertEquals(aroundNode.toLabelString(), around); + + String compAnon = "before(int): <anonymous pointcut>.."; + IProgramElement compAnonNode = model.findElementForLabel(aspect, IProgramElement.Kind.ADVICE, compAnon); + assertNotNull(compAnonNode); + assertEquals(compAnonNode.toLabelString(), compAnon); + + String compNamed = "before(int): named().."; + IProgramElement compNamedNode = model.findElementForLabel(aspect, IProgramElement.Kind.ADVICE, compNamed); + assertNotNull(compNamedNode); + assertEquals(compNamedNode.toLabelString(), compNamed); + } + +} diff --git a/ajde.core/src/test/java/org/aspectj/ajde/core/tests/model/AsmRelationshipsTest.java b/ajde.core/src/test/java/org/aspectj/ajde/core/tests/model/AsmRelationshipsTest.java new file mode 100644 index 000000000..20b6e346e --- /dev/null +++ b/ajde.core/src/test/java/org/aspectj/ajde/core/tests/model/AsmRelationshipsTest.java @@ -0,0 +1,196 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * ******************************************************************/ + +package org.aspectj.ajde.core.tests.model; + +import java.io.File; +import java.util.Iterator; +import java.util.List; + +import org.aspectj.ajde.core.AjdeCoreTestCase; +import org.aspectj.ajde.core.TestCompilerConfiguration; +import org.aspectj.asm.AsmManager; +import org.aspectj.asm.IProgramElement; +import org.aspectj.asm.IRelationship; + +public class AsmRelationshipsTest extends AjdeCoreTestCase { + + private AsmManager manager = null; + + private final String[] files = new String[] { "ModelCoverage.java", "pkg" + File.separator + "InPackage.java" }; + + private TestCompilerConfiguration compilerConfig; + + @Override + protected void setUp() throws Exception { + super.setUp(); + initialiseProject("coverage"); + compilerConfig = (TestCompilerConfiguration) getCompiler().getCompilerConfiguration(); + compilerConfig.setProjectSourceFiles(getSourceFileList(files)); + doBuild(); + manager = AsmManager.lastActiveStructureModel; + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + compilerConfig = null; + manager = null; + } + + // // see pr148027 + // public void testUsesPointcut() { + // if (!AsmHierarchyBuilder.shouldAddUsesPointcut) return; + // + // IProgramElement ptUsage = AsmManager.getDefault().getHierarchy().findElementForType(null, "PointcutUsage"); + // assertNotNull(ptUsage); + // IProgramElement pts = AsmManager.getDefault().getHierarchy().findElementForType(null, "Pointcuts"); + // assertNotNull(pts); + // + // IProgramElement pUsesA = manager.getHierarchy().findElementForLabel( + // ptUsage, + // IProgramElement.Kind.POINTCUT, + // "usesA()"/*Point"*/); + // assertNotNull(pUsesA); + // + // IProgramElement ptsA = manager.getHierarchy().findElementForLabel( + // pts, + // IProgramElement.Kind.POINTCUT, + // "a()"/*Point"*/); + // assertNotNull(ptsA); + // + // assertTrue(AsmManager.getDefault().getRelationshipMap().get(pUsesA).size()>0); + // assertTrue(AsmManager.getDefault().getRelationshipMap().get(ptsA).size()>0); + // } + + public void testDeclareParents() { + IProgramElement aspect = manager.getHierarchy().findElementForType(null, "DeclareCoverage"); + + IProgramElement dp = manager.getHierarchy().findElementForLabel(aspect, IProgramElement.Kind.DECLARE_PARENTS, + "declare parents: implements Serializable"/* Point" */); + + assertNotNull(dp); + /* List relations = */manager.getRelationshipMap().get(dp); + + List<IRelationship> rels = manager.getRelationshipMap().get(dp); + assertTrue(rels.size() > 0); + + // assertTrue(rel.getTargets().size() > 0); + // + // checkDeclareMapping("DeclareCoverage", "Point", , + // "Point", "matched by", "matches declare", + // IProgramElement.Kind.DECLARE_PARENTS); + } + + public void testDeclareWarningAndError() { + checkDeclareMapping("DeclareCoverage", "Point", "declare warning: \"Illegal call.\"", "method-call(void Point.setX(int))", + "matched by", "matches declare", IProgramElement.Kind.DECLARE_WARNING); + } + + public void testInterTypeDeclarations() { + checkInterTypeMapping("InterTypeDecCoverage", "Point", "Point.xxx", "Point", "declared on", "aspect declarations", + IProgramElement.Kind.INTER_TYPE_FIELD); + checkInterTypeMapping("InterTypeDecCoverage", "Point", "Point.check(int,Line)", "Point", "declared on", + "aspect declarations", IProgramElement.Kind.INTER_TYPE_METHOD); + } + + public void testAdvice() { + checkMapping("AdvisesRelationshipCoverage", "Point", "before(): methodExecutionP..", "setX(int)", "advises", "advised by"); + checkUniDirectionalMapping("AdvisesRelationshipCoverage", "Point", "before(): getP..", "field-get(int Point.x)", "advises"); + checkUniDirectionalMapping("AdvisesRelationshipCoverage", "Point", "before(): setP..", "field-set(int Point.x)", "advises"); + } + + private void checkDeclareMapping(String fromType, String toType, String from, String to, String forwardRelName, + String backRelName, IProgramElement.Kind kind) { + + IProgramElement aspect = manager.getHierarchy().findElementForType(null, fromType); + assertNotNull(aspect); + String beforeExec = from; + IProgramElement beforeExecNode = manager.getHierarchy().findElementForLabel(aspect, kind, beforeExec); + assertNotNull(beforeExecNode); + IRelationship rel = manager.getRelationshipMap().get(beforeExecNode, IRelationship.Kind.DECLARE, forwardRelName); + assertTrue(rel.getTargets().size() > 0); + String handle = rel.getTargets().get(0); + assertEquals(manager.getHierarchy().findElementForHandle(handle).toString(), to); + + IProgramElement clazz = manager.getHierarchy().findElementForType(null, toType); + assertNotNull(clazz); + String set = to; + IProgramElement setNode = manager.getHierarchy().findElementForLabel(clazz, IProgramElement.Kind.CODE, set); + assertNotNull(setNode); + IRelationship rel2 = manager.getRelationshipMap().get(setNode, IRelationship.Kind.DECLARE, backRelName); + String handle2 = rel2.getTargets().get(0); + assertEquals(manager.getHierarchy().findElementForHandle(handle2).toString(), from); + } + + private void checkUniDirectionalMapping(String fromType, String toType, String from, String to, String relName) { + + IProgramElement aspect = manager.getHierarchy().findElementForType(null, fromType); + assertNotNull(aspect); + String beforeExec = from; + IProgramElement beforeExecNode = manager.getHierarchy() + .findElementForLabel(aspect, IProgramElement.Kind.ADVICE, beforeExec); + assertNotNull(beforeExecNode); + IRelationship rel = manager.getRelationshipMap().get(beforeExecNode, IRelationship.Kind.ADVICE, relName); + for (Iterator<String> it = rel.getTargets().iterator(); it.hasNext();) { + String currHandle = it.next(); + if (manager.getHierarchy().findElementForHandle(currHandle).toLabelString().equals(to)) + return; + } + fail(); // didn't find it + } + + private void checkMapping(String fromType, String toType, String from, String to, String forwardRelName, String backRelName) { + + IProgramElement aspect = manager.getHierarchy().findElementForType(null, fromType); + assertNotNull(aspect); + String beforeExec = from; + IProgramElement beforeExecNode = manager.getHierarchy() + .findElementForLabel(aspect, IProgramElement.Kind.ADVICE, beforeExec); + assertNotNull(beforeExecNode); + IRelationship rel = manager.getRelationshipMap().get(beforeExecNode, IRelationship.Kind.ADVICE, forwardRelName); + String handle = rel.getTargets().get(0); + assertEquals(manager.getHierarchy().findElementForHandle(handle).toString(), to); + + IProgramElement clazz = manager.getHierarchy().findElementForType(null, toType); + assertNotNull(clazz); + String set = to; + IProgramElement setNode = manager.getHierarchy().findElementForLabel(clazz, IProgramElement.Kind.METHOD, set); + assertNotNull(setNode); + IRelationship rel2 = manager.getRelationshipMap().get(setNode, IRelationship.Kind.ADVICE, backRelName); + String handle2 = rel2.getTargets().get(0); + assertEquals(manager.getHierarchy().findElementForHandle(handle2).toString(), from); + } + + private void checkInterTypeMapping(String fromType, String toType, String from, String to, String forwardRelName, + String backRelName, IProgramElement.Kind declareKind) { + + IProgramElement aspect = manager.getHierarchy().findElementForType(null, fromType); + assertNotNull(aspect); + String beforeExec = from; + IProgramElement fromNode = manager.getHierarchy().findElementForLabel(aspect, declareKind, beforeExec); + assertNotNull(fromNode); + IRelationship rel = manager.getRelationshipMap().get(fromNode, IRelationship.Kind.DECLARE_INTER_TYPE, forwardRelName); + String handle = rel.getTargets().get(0); + assertEquals(manager.getHierarchy().findElementForHandle(handle).toString(), to); + + IProgramElement clazz = manager.getHierarchy().findElementForType(null, toType); + assertNotNull(clazz); + // String set = to; + IRelationship rel2 = manager.getRelationshipMap().get(clazz, IRelationship.Kind.DECLARE_INTER_TYPE, backRelName); + // String handle2 = (String)rel2.getTargets().get(0); + for (Iterator<String> it = rel2.getTargets().iterator(); it.hasNext();) { + String currHandle = it.next(); + if (manager.getHierarchy().findElementForHandle(currHandle).toLabelString().equals(from)) + return; + } + fail(); // didn't find it + } +} diff --git a/ajde.core/src/test/java/org/aspectj/ajde/core/tests/model/SavedModelConsistencyTest.java b/ajde.core/src/test/java/org/aspectj/ajde/core/tests/model/SavedModelConsistencyTest.java new file mode 100644 index 000000000..6430cead1 --- /dev/null +++ b/ajde.core/src/test/java/org/aspectj/ajde/core/tests/model/SavedModelConsistencyTest.java @@ -0,0 +1,118 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Mik Kersten initial implementation + * Helen Hawkins Converted to new interface (bug 148190) + * ******************************************************************/ +package org.aspectj.ajde.core.tests.model; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.aspectj.ajde.core.AjdeCoreTestCase; +import org.aspectj.ajde.core.TestCompilerConfiguration; +import org.aspectj.ajde.core.TestMessageHandler; +import org.aspectj.asm.AsmManager; +import org.aspectj.asm.HierarchyWalker; +import org.aspectj.asm.IHierarchy; +import org.aspectj.asm.IProgramElement; + +public class SavedModelConsistencyTest extends AjdeCoreTestCase { + + private final String[] files = new String[] { "ModelCoverage.java", "pkg" + File.separator + "InPackage.java" }; + + private TestMessageHandler handler; + private TestCompilerConfiguration compilerConfig; + + @Override + protected void setUp() throws Exception { + super.setUp(); + initialiseProject("coverage"); + handler = (TestMessageHandler) getCompiler().getMessageHandler(); + compilerConfig = (TestCompilerConfiguration) getCompiler().getCompilerConfiguration(); + compilerConfig.setProjectSourceFiles(getSourceFileList(files)); + // In order to get a model on the disk to read in, do a build with the right flag set ! + try { + AsmManager.dumpModelPostBuild = true; + doBuild(); + } finally { + AsmManager.dumpModelPostBuild = false; + } + assertTrue("Expected no compiler errors but found " + handler.getErrors(), handler.getErrors().isEmpty()); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + handler = null; + compilerConfig = null; + } + + public void testInterfaceIsSameInBoth() { + AsmManager asm = AsmManager.createNewStructureModel(Collections.<File,String>emptyMap()); + asm.readStructureModel(getAbsoluteProjectDir()); + + IHierarchy model = asm.getHierarchy(); + assertTrue("model exists", model != null); + + assertTrue("root exists", model.getRoot() != null); // TODO-path + File testFile = openFile("ModelCoverage.java"); + assertTrue("Expected " + testFile.getAbsolutePath() + " to exist, but it did not", testFile.exists()); + + IProgramElement nodePreBuild = model.findElementForSourceLine(testFile.getAbsolutePath(), 5); + + doBuild(); + assertTrue("Expected no compiler errors but found " + handler.getErrors(), handler.getErrors().isEmpty()); + + IProgramElement nodePostBuild = model.findElementForSourceLine(testFile.getAbsolutePath(), 5); + + assertTrue( + "Nodes should be identical: Prebuild kind = " + nodePreBuild.getKind() + " Postbuild kind = " + + nodePostBuild.getKind(), nodePreBuild.getKind().equals(nodePostBuild.getKind())); + + } + + public void testModelIsSamePreAndPostBuild() { + AsmManager asm = AsmManager.createNewStructureModel(Collections.<File,String>emptyMap()); + asm.readStructureModel(getAbsoluteProjectDir()); + // AsmManager.getDefault().readStructureModel(getAbsoluteProjectDir()); + IHierarchy model = asm.getHierarchy(); + assertTrue("model exists", model != null); + + final List<IProgramElement.Kind> preBuildKinds = new ArrayList<>(); + HierarchyWalker walker = new HierarchyWalker() { + @Override + public void preProcess(IProgramElement node) { + preBuildKinds.add(node.getKind()); + } + }; + asm.getHierarchy().getRoot().walk(walker); + assertFalse("Expected there to be build kinds but didn't " + "find any", preBuildKinds.isEmpty()); + + doBuild(); + assertTrue("Expected no compiler errors but found " + handler.getErrors(), handler.getErrors().isEmpty()); + + final List<IProgramElement.Kind> postBuildKinds = new ArrayList<>(); + HierarchyWalker walker2 = new HierarchyWalker() { + @Override + public void preProcess(IProgramElement node) { + postBuildKinds.add(node.getKind()); + } + }; + asm.getHierarchy().getRoot().walk(walker2); + assertFalse("Expected there to be build kinds but didn't " + "find any", preBuildKinds.isEmpty()); + + assertTrue("Lists should be the same: PRE" + preBuildKinds.toString() + " POST" + postBuildKinds.toString(), + preBuildKinds.equals(postBuildKinds)); + + } + +} diff --git a/ajde.core/src/test/java/org/aspectj/ajde/core/tests/model/StructureModelTest.java b/ajde.core/src/test/java/org/aspectj/ajde/core/tests/model/StructureModelTest.java new file mode 100644 index 000000000..6755ca57e --- /dev/null +++ b/ajde.core/src/test/java/org/aspectj/ajde/core/tests/model/StructureModelTest.java @@ -0,0 +1,142 @@ +/* ******************************************************************* + * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC). + * All rights reserved. + * This program and the accompanying materials are made available + * under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Xerox/PARC initial implementation + * AMC 21.01.2003 fixed for new source location in eclipse.org + * Helen Hawkins Converted to new interface (bug 148190) + * ******************************************************************/ +package org.aspectj.ajde.core.tests.model; + +import java.io.File; +import java.io.IOException; +import java.util.Iterator; + +import org.aspectj.ajde.core.AjdeCoreTestCase; +import org.aspectj.ajde.core.TestCompilerConfiguration; +import org.aspectj.asm.AsmManager; +import org.aspectj.asm.HierarchyWalker; +import org.aspectj.asm.IHierarchy; +import org.aspectj.asm.IProgramElement; + +public class StructureModelTest extends AjdeCoreTestCase { + + private AsmManager manager = null; + + private final String[] files = new String[] { "figures" + File.separator + "Debug.java", + "figures" + File.separator + "Figure.java", "figures" + File.separator + "FigureElement.java", + "figures" + File.separator + "Main.java", "figures" + File.separator + "composites" + File.separator + "Line.java", + "figures" + File.separator + "composites" + File.separator + "Square.java", + "figures" + File.separator + "primitives" + File.separator + "planar" + File.separator + "Point.java", + "figures" + File.separator + "primitives" + File.separator + "solid" + File.separator + "SolidPoint.java" }; + + private TestCompilerConfiguration compilerConfig; + + protected void setUp() throws Exception { + super.setUp(); + initialiseProject("figures-coverage"); + compilerConfig = (TestCompilerConfiguration) getCompiler().getCompilerConfiguration(); + compilerConfig.setProjectSourceFiles(getSourceFileList(files)); + compilerConfig.setNonStandardOptions("-Xset:minimalModel=false"); + doBuild(); + manager = AsmManager.lastActiveStructureModel; + } + + protected void tearDown() throws Exception { + super.tearDown(); + compilerConfig = null; + manager = null; + } + + public void testRootForSourceFile() throws IOException { + File testFile = openFile("figures" + File.separator + "Figure.java"); + IProgramElement node = manager.getHierarchy().findElementForSourceFile(testFile.getAbsolutePath()); + assertTrue("find result", node != null); + String child = ((IProgramElement) node.getChildren().get(2)).getName(); + assertTrue("expected Figure got child " + child, child.equals("Figure")); + } + + public void testPointcutName() throws IOException { + File testFile = openFile("figures" + File.separator + "Main.java"); + IProgramElement node = manager.getHierarchy().findElementForSourceFile(testFile.getAbsolutePath()); + assertTrue("find result", node != null); + IProgramElement pNode = (IProgramElement) (node).getChildren().get(3); + assertEquals(IProgramElement.Kind.ASPECT, pNode.getKind()); + IProgramElement pointcut = (IProgramElement) pNode.getChildren().get(0); + assertTrue("kind", pointcut.getKind().equals(IProgramElement.Kind.POINTCUT)); + assertTrue("found node: " + pointcut.getName(), pointcut.toLabelString().equals("testptct()")); + } + + public void testFileNodeFind() throws IOException { + File testFile = openFile("figures" + File.separator + "Main.java"); + + // System.err.println(((IProgramElement)((IProgramElement)Ajde.getDefault().getStructureModelManager().getHierarchy().getRoot().getChildren().get(0)).getChildren().get(3)).getSourceLocation().getSourceFile().getAbsolutePath()); + // System.err.println(testFile.getAbsolutePath()); + + IProgramElement node = manager.getHierarchy().findElementForSourceLine(testFile.getAbsolutePath(), 1); + assertTrue("find result", node != null); + assertEquals("find result has children", 4, node.getChildren().size()); // package, import and 2 types + assertTrue("found node: " + node.getName(), node.getKind().equals(IProgramElement.Kind.FILE_JAVA)); + } + + /** + * @todo add negative test to make sure things that aren't runnable aren't annotated + */ + public void testMainClassNodeInfo() throws IOException { + IHierarchy model = manager.getHierarchy(); + assertTrue("model exists", model != null); + assertTrue("root exists", model.getRoot() != null); + File testFile = openFile("figures" + File.separator + "Main.java"); + IProgramElement node = model.findElementForSourceLine(testFile.getAbsolutePath(), 11); + assertTrue("find result", node != null); + IProgramElement pNode = node.getParent(); + if (null == pNode) { + assertTrue("null parent of " + node, false); + } + assertTrue("found node: " + pNode.getName(), pNode.isRunnable()); + } + + /** + * Integrity could be checked somewhere in the API. + */ + public void testModelIntegrity() { + IProgramElement modelRoot = manager.getHierarchy().getRoot(); + assertTrue("root exists", modelRoot != null); + + try { + testModelIntegrityHelper(modelRoot); + } catch (Exception e) { + assertTrue(e.toString(), false); + } + } + + private void testModelIntegrityHelper(IProgramElement node) throws Exception { + for (Iterator<IProgramElement> it = node.getChildren().iterator(); it.hasNext();) { + IProgramElement child = (IProgramElement) it.next(); + if (node == child.getParent()) { + testModelIntegrityHelper(child); + } else { + throw new Exception("parent-child check failed for child: " + child.toString()); + } + } + } + + public void testNoChildIsNull() { + HierarchyWalker walker = new HierarchyWalker() { + public void preProcess(IProgramElement node) { + if (node.getChildren() == null) + return; + for (Iterator<IProgramElement> it = node.getChildren().iterator(); it.hasNext();) { + if (it.next() == null) + throw new NullPointerException("null child on node: " + node.getName()); + } + } + }; + manager.getHierarchy().getRoot().walk(walker); + } +} |