diff options
author | aclement <aclement> | 2007-01-11 16:04:29 +0000 |
---|---|---|
committer | aclement <aclement> | 2007-01-11 16:04:29 +0000 |
commit | cfd711b9628154e0b2eb2df174124699cf831f83 (patch) | |
tree | 83b9afa0e996777cf4cdcdff23f3b69f72df031b /ajde.core/testsrc | |
parent | 41fefd58f8b716468b2bdba2335eb921e5eb3a7b (diff) | |
download | aspectj-cfd711b9628154e0b2eb2df174124699cf831f83.tar.gz aspectj-cfd711b9628154e0b2eb2df174124699cf831f83.zip |
new ajde.core module
Diffstat (limited to 'ajde.core/testsrc')
21 files changed, 3853 insertions, 0 deletions
diff --git a/ajde.core/testsrc/org/aspectj/ajde/core/AjdeCoreModuleTests.java b/ajde.core/testsrc/org/aspectj/ajde/core/AjdeCoreModuleTests.java new file mode 100644 index 000000000..0015e79ec --- /dev/null +++ b/ajde.core/testsrc/org/aspectj/ajde/core/AjdeCoreModuleTests.java @@ -0,0 +1,28 @@ +/******************************************************************** + * 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 junit.framework.TestCase; +import junit.framework.TestSuite; + +public class AjdeCoreModuleTests extends TestCase { + + public static TestSuite suite() { + TestSuite suite = new TestSuite(AjdeCoreModuleTests.class.getName()); + suite.addTest(org.aspectj.ajde.core.AjdeCoreTests.suite()); + return suite; + } + + public AjdeCoreModuleTests(String name) { + super(name); + } + +} diff --git a/ajde.core/testsrc/org/aspectj/ajde/core/AjdeCoreTestCase.java b/ajde.core/testsrc/org/aspectj/ajde/core/AjdeCoreTestCase.java new file mode 100644 index 000000000..08ee203ff --- /dev/null +++ b/ajde.core/testsrc/org/aspectj/ajde/core/AjdeCoreTestCase.java @@ -0,0 +1,158 @@ +/******************************************************************** + * 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.Iterator; +import java.util.List; + +import junit.framework.AssertionFailedError; +import junit.framework.TestCase; + +import org.aspectj.asm.AsmManager; +import org.aspectj.tools.ajc.Ajc; + +/** + * 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 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 = Ajc.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) { + File projectSrc=new File(testdataSrcDir + File.separatorChar + projectName); + File destination=new File(getWorkingDir(),projectName); + if (!destination.exists()) {destination.mkdir();} + copy(projectSrc,destination); + projectDir = destination.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 ll = ((TestMessageHandler)compiler.getMessageHandler()).getMessages(); + for (Iterator iter = ll.iterator(); iter.hasNext();) { + Object element = (Object) iter.next(); + if (element.toString().indexOf(what) != -1) + return true; + } + return false; + } + + public void dumpTaskData() { + List ll = ((TestMessageHandler)compiler.getMessageHandler()).getMessages(); + for (Iterator iter = ll.iterator(); iter.hasNext();) { + Object element = (Object) iter.next(); + System.out.println("RecordedMessage>"+element); + } + } + + public List getSourceFileList(String[] files) { + List sourceFiles = new ArrayList(); + for (int i = 0; i < files.length; i++) { + sourceFiles.add(getAbsoluteProjectDir() + File.separator + files[i]); + } + return sourceFiles; + } + +} diff --git a/ajde.core/testsrc/org/aspectj/ajde/core/AjdeCoreTests.java b/ajde.core/testsrc/org/aspectj/ajde/core/AjdeCoreTests.java new file mode 100644 index 000000000..7e45b4757 --- /dev/null +++ b/ajde.core/testsrc/org/aspectj/ajde/core/AjdeCoreTests.java @@ -0,0 +1,60 @@ +/******************************************************************** + * 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 junit.framework.Test; +import junit.framework.TestCase; +import junit.framework.TestSuite; + +import org.aspectj.ajde.core.tests.AjConfigTests; +import org.aspectj.ajde.core.tests.BuildCancellingTests; +import org.aspectj.ajde.core.tests.CompilerMessagesTests; +import org.aspectj.ajde.core.tests.DuplicateManifestTests; +import org.aspectj.ajde.core.tests.InpathTests; +import org.aspectj.ajde.core.tests.JarManifestTests; +import org.aspectj.ajde.core.tests.OutxmlTests; +import org.aspectj.ajde.core.tests.ResourceCopyTests; +import org.aspectj.ajde.core.tests.ReweavableTests; +import org.aspectj.ajde.core.tests.ShowWeaveMessagesTests; +import org.aspectj.ajde.core.tests.model.AsmDeclarationsTests; +import org.aspectj.ajde.core.tests.model.AsmRelationshipsTests; +import org.aspectj.ajde.core.tests.model.SavedModelConsistencyTests; +import org.aspectj.ajde.core.tests.model.StructureModelTests; + +public class AjdeCoreTests extends TestCase { + + public static Test suite() { + TestSuite suite = new TestSuite(AjdeCoreTests.class.getName()); + // $JUnit-BEGIN$ + suite.addTestSuite(ShowWeaveMessagesTests.class); + suite.addTestSuite(DuplicateManifestTests.class); + suite.addTestSuite(StructureModelTests.class); + suite.addTestSuite(CompilerMessagesTests.class); + suite.addTestSuite(AsmDeclarationsTests.class); + suite.addTestSuite(AsmRelationshipsTests.class); + suite.addTestSuite(InpathTests.class); + suite.addTestSuite(ReweavableTests.class); + suite.addTestSuite(ResourceCopyTests.class); + suite.addTestSuite(SavedModelConsistencyTests. class); + suite.addTestSuite(BuildCancellingTests.class); + suite.addTestSuite(JarManifestTests.class); + suite.addTestSuite(OutxmlTests.class); + suite.addTestSuite(AjConfigTests.class); + + // $JUnit-END$ + return suite; + } + + public AjdeCoreTests(String name) { + super(name); + } + +} diff --git a/ajde.core/testsrc/org/aspectj/ajde/core/TestBuildProgressMonitor.java b/ajde.core/testsrc/org/aspectj/ajde/core/TestBuildProgressMonitor.java new file mode 100644 index 000000000..8d9f4dcc1 --- /dev/null +++ b/ajde.core/testsrc/org/aspectj/ajde/core/TestBuildProgressMonitor.java @@ -0,0 +1,95 @@ +/******************************************************************** + * 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.Iterator; +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 messagesReceived = new ArrayList(); + 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 (Iterator iter = messagesReceived.iterator(); iter.hasNext();) { + String element = (String) iter.next(); + if (element.startsWith(prefix) && + element.indexOf(distinguishingMarks)!=-1) return true; + } + return false; + } + + public void dumpMessages() { + System.out.println("ProgressMonitorMessages"); + for (Iterator iter = messagesReceived.iterator(); iter.hasNext();) { + String element = (String) iter.next(); + System.out.println(element); + } + } + + +} diff --git a/ajde.core/testsrc/org/aspectj/ajde/core/TestCompilerConfiguration.java b/ajde.core/testsrc/org/aspectj/ajde/core/TestCompilerConfiguration.java new file mode 100644 index 000000000..6ce4aa92e --- /dev/null +++ b/ajde.core/testsrc/org/aspectj/ajde/core/TestCompilerConfiguration.java @@ -0,0 +1,160 @@ +/******************************************************************** + * 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.HashMap; +import java.util.Hashtable; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.aspectj.tools.ajc.AjcTests; +import org.aspectj.util.FileUtil; + +/** + * 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 aspectpath; + private Set inpath; + private String outjar; + private Map javaOptions; + private String nonStandardOptions; + private List projectSourceFiles = new ArrayList(); + private Map sourcePathResources; + + private String srcDirName = "src"; + + private IOutputLocationManager outputLoc; + + public TestCompilerConfiguration(String projectPath) { + this.projectPath = projectPath; + } + + public Set getAspectPath() { + return aspectpath; + } + + public String getClasspath() { + return projectPath + + File.pathSeparator + + System.getProperty("sun.boot.class.path") + + File.pathSeparator + + AjcTests.aspectjrtClasspath(); + } + + public Set getInpath() { + return inpath; + } + + public Map getJavaOptionsMap() { + if (javaOptions == null) { + javaOptions = new Hashtable(); + 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 getProjectSourceFiles() { + return projectSourceFiles; + } + + public Map getSourcePathResources() { + if (sourcePathResources == null) { + sourcePathResources = new HashMap(); + + /* 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 aspectPath) { + this.aspectpath = aspectPath; + } + + public void setInpath(Set inpath) { + this.inpath = inpath; + } + + public void setOutjar(String outjar) { + this.outjar = outjar; + } + + public void setJavaOptions(Map javaOptions) { + this.javaOptions = javaOptions; + } + + public void setNonStandardOptions(String options) { + this.nonStandardOptions = options; + } + + public void setProjectSourceFiles(List projectSourceFiles) { + this.projectSourceFiles = projectSourceFiles; + } + + public void setSourcePathResources(Map sourcePathResources) { + this.sourcePathResources = sourcePathResources; + } + + public void setSourceDir(String srcDirName) { + this.srcDirName = srcDirName; + } + +} diff --git a/ajde.core/testsrc/org/aspectj/ajde/core/TestMessageHandler.java b/ajde.core/testsrc/org/aspectj/ajde/core/TestMessageHandler.java new file mode 100644 index 000000000..aab1e98e0 --- /dev/null +++ b/ajde.core/testsrc/org/aspectj/ajde/core/TestMessageHandler.java @@ -0,0 +1,105 @@ +/******************************************************************** + * 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 ignoring; + private List messages; + private List errors; + + public TestMessageHandler() { + ignoring = new ArrayList(); + messages = new ArrayList(); + errors = new ArrayList(); + 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 getMessages() { + return messages; + } + + public List 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/testsrc/org/aspectj/ajde/core/TestOutputLocationManager.java b/ajde.core/testsrc/org/aspectj/ajde/core/TestOutputLocationManager.java new file mode 100644 index 000000000..233c4239f --- /dev/null +++ b/ajde.core/testsrc/org/aspectj/ajde/core/TestOutputLocationManager.java @@ -0,0 +1,81 @@ +/******************************************************************** + * 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.List; + +/** + * 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 allOutputLocations; + + public TestOutputLocationManager(String testProjectPath) { + this.testProjectOutputPath = testProjectPath + File.separator + "bin"; + } + + public File getOutputLocationForClass(File compilationUnit) { + initLocations(); + return classOutputLoc; + } + + public File getOutputLocationForResource(File resource) { + initLocations(); + return resourceOutputLoc; + } + + // -------------- setter methods useful for testing ------------- + public void setOutputLocForClass(File f) { + classOutputLoc = f; + } + + public void setOutputLocForResource(File f) { + resourceOutputLoc = f; + } + + public List getAllOutputLocations() { + if(allOutputLocations == null) { + allOutputLocations = new ArrayList(); + initLocations(); + allOutputLocations.add(classOutputLoc); + if (!classOutputLoc.equals(resourceOutputLoc)) { + allOutputLocations.add(resourceOutputLoc); + } + } + return allOutputLocations; + } + + public File getDefaultOutputLocation() { + initLocations(); + return classOutputLoc; + } + + private void initLocations() { + if (classOutputLoc == null) { + classOutputLoc = new File(testProjectOutputPath); + } + if (resourceOutputLoc == null) { + resourceOutputLoc = new File(testProjectOutputPath); + } + } + + +} diff --git a/ajde.core/testsrc/org/aspectj/ajde/core/tests/AjConfigTests.java b/ajde.core/testsrc/org/aspectj/ajde/core/tests/AjConfigTests.java new file mode 100644 index 000000000..53dd64577 --- /dev/null +++ b/ajde.core/testsrc/org/aspectj/ajde/core/tests/AjConfigTests.java @@ -0,0 +1,226 @@ +/******************************************************************** + * 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.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 AjConfigTests extends AjdeCoreTestCase { + + private TestCompilerConfiguration compilerConfig; + private AjdeCoreBuildManager ajdeBuildManager; + + protected void setUp() throws Exception { + super.setUp(); + initialiseProject("SimpleProject"); + ajdeBuildManager = new AjdeCoreBuildManager(getCompiler()); + compilerConfig = (TestCompilerConfiguration) getCompiler().getCompilerConfiguration(); + } + + protected void tearDown() throws Exception { + super.tearDown(); + ajdeBuildManager = null; + compilerConfig = null; + } + + public void testJavaOptionsMap() { + Map options = JavaOptions.getDefaultJavaOptions(); + options.put(JavaOptions.WARN_DEPRECATION, JavaOptions.WARNING); + compilerConfig.setJavaOptions(options); + Map found = genAjBuildConfig().getOptions().getMap(); + String warning = (String) found.get(JavaOptions.WARN_DEPRECATION); + assertEquals("expected to be warning on deprecation but found setting " + + " was " + warning,JavaOptions.WARNING,warning); + } + + public void testAspectPath() { + Set aspects = new HashSet(); + compilerConfig.setAspectPath( aspects ); + AjBuildConfig buildConfig = genAjBuildConfig(); + List aPath = buildConfig.getAspectpath(); + assertTrue( "no aspect path", aPath.isEmpty() ); + + File f = new File( "jarone.jar" ); + aspects.add( f ); + buildConfig = genAjBuildConfig(); + List 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 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 jars = new HashSet(); + compilerConfig.setInpath( jars ); + AjBuildConfig buildConfig = genAjBuildConfig(); + List 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 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 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 m = new HashMap(); + m.put("newFile.txt", getWorkingDir()); + compilerConfig.setSourcePathResources(m); + AjBuildConfig buildConfig = genAjBuildConfig(); + Map found = buildConfig.getSourcePathResources(); + for (Iterator i = found.keySet().iterator(); i.hasNext(); ) { + String resource = (String)i.next(); + assertEquals("expected to find resource with name newFile.txt but " + + "found " + resource,"newFile.txt",resource); + File from = (File)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 found = genAjBuildConfig().getClasspath(); + StringBuffer sb = new StringBuffer(); + for (Iterator iterator = found.iterator(); iterator.hasNext();) { + String name = (String) 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() { + String f = getAbsoluteProjectDir() + File.separator + "C.java"; + List files = new ArrayList(); + files.add(f); + compilerConfig.setProjectSourceFiles(files); + AjBuildConfig buildConfig = genAjBuildConfig(); + String found = ((File)buildConfig.getFiles().get(0)).getAbsolutePath(); + assertEquals("expected source file " + f + ", but found " + + found, f, found); + } + + private AjBuildConfig genAjBuildConfig() { + AjBuildConfig buildConfig = ajdeBuildManager.genAjBuildConfig(); + assertNotNull("exepected to generate a non null AjBuildConfig but " + + "didn't", buildConfig); + return buildConfig; + } + + +} diff --git a/ajde.core/testsrc/org/aspectj/ajde/core/tests/BuildCancellingTests.java b/ajde.core/testsrc/org/aspectj/ajde/core/tests/BuildCancellingTests.java new file mode 100644 index 000000000..2e0bffaa0 --- /dev/null +++ b/ajde.core/testsrc/org/aspectj/ajde/core/tests/BuildCancellingTests.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 BuildCancellingTests 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/testsrc/org/aspectj/ajde/core/tests/CompilerMessagesTests.java b/ajde.core/testsrc/org/aspectj/ajde/core/tests/CompilerMessagesTests.java new file mode 100644 index 000000000..dda92a5b0 --- /dev/null +++ b/ajde.core/testsrc/org/aspectj/ajde/core/tests/CompilerMessagesTests.java @@ -0,0 +1,77 @@ +/* ******************************************************************* + * 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.bridge.IMessage; + +public class CompilerMessagesTests 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 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 msgs = handler.getMessages(); + IMessage msg = (IMessage)((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/testsrc/org/aspectj/ajde/core/tests/DuplicateManifestTests.java b/ajde.core/testsrc/org/aspectj/ajde/core/tests/DuplicateManifestTests.java new file mode 100644 index 000000000..997c49d72 --- /dev/null +++ b/ajde.core/testsrc/org/aspectj/ajde/core/tests/DuplicateManifestTests.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 DuplicateManifestTests 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 injars = new HashSet(); + injars.add(openFile(injarName)); + compilerConfig.setInpath(injars); + Set aspectpath = new HashSet(); + 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/testsrc/org/aspectj/ajde/core/tests/InpathTests.java b/ajde.core/testsrc/org/aspectj/ajde/core/tests/InpathTests.java new file mode 100644 index 000000000..4bcd6d1af --- /dev/null +++ b/ajde.core/testsrc/org/aspectj/ajde/core/tests/InpathTests.java @@ -0,0 +1,389 @@ +/* ******************************************************************* + * 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 InpathTests extends AjdeCoreTestCase { + + public static final FileFilter aspectjResourceFileFilter = + new FileFilter() { + 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; + + protected void setUp() throws Exception { + super.setUp(); + initialiseProject("InpathTest"); + handler = (TestMessageHandler) getCompiler().getMessageHandler(); + compilerConfig = (TestCompilerConfiguration) getCompiler() + .getCompilerConfiguration(); + } + + 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 inpath = new HashSet(); + 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 expectedOutputJarContents = new HashSet(); + // 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 inpath = new HashSet(); + 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 expectedBindirContents = new HashSet(); + // 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 inpath = new HashSet(); + 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 expectedOutputJarContents = new HashSet(); + // 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 inpath = new HashSet(); + 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 expectedBindirContents = new HashSet(); + + // 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 expectedOutputJarContents) { + + try { + assertTrue( + "outjar older than injar", + (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 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 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 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 = (ZipEntry)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/testsrc/org/aspectj/ajde/core/tests/JarManifestTests.java b/ajde.core/testsrc/org/aspectj/ajde/core/tests/JarManifestTests.java new file mode 100644 index 000000000..ec3a6c32c --- /dev/null +++ b/ajde.core/testsrc/org/aspectj/ajde/core/tests/JarManifestTests.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 JarManifestTests 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/testsrc/org/aspectj/ajde/core/tests/OutxmlTests.java b/ajde.core/testsrc/org/aspectj/ajde/core/tests/OutxmlTests.java new file mode 100644 index 000000000..28768722d --- /dev/null +++ b/ajde.core/testsrc/org/aspectj/ajde/core/tests/OutxmlTests.java @@ -0,0 +1,165 @@ +/******************************************************************** + * 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.bridge.Constants; + +public class OutxmlTests 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 roots = new HashSet(); + 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 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/testsrc/org/aspectj/ajde/core/tests/ResourceCopyTests.java b/ajde.core/testsrc/org/aspectj/ajde/core/tests/ResourceCopyTests.java new file mode 100644 index 000000000..84f21a405 --- /dev/null +++ b/ajde.core/testsrc/org/aspectj/ajde/core/tests/ResourceCopyTests.java @@ -0,0 +1,318 @@ +/******************************************************************** + * 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 ResourceCopyTests 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 testProps; + + 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" + }; + + protected void setUp() throws Exception { + super.setUp(); + initialiseProject(PROJECT_DIR); + handler = (TestMessageHandler) getCompiler().getMessageHandler(); + compilerConfig = (TestCompilerConfiguration) getCompiler() + .getCompilerConfiguration(); + testProps = getAbsoluteProjectDir() + File.separator + "src" + File.separator + "testsrc" + File.separator + "test.props"; + } + + 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 injars = new HashSet(); + 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 injars = new HashSet(); + 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 msgs = handler.getMessages(); + String exp = "duplicate resource: "; + String found = ((TestMessageHandler.TestMessage)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 injars = new HashSet(); + 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 injars = new HashSet(); + 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 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 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() { + 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 resources = new HashSet(); + + try { + assertTrue("outjar older than injar",(outjarFile.lastModified() > injarFile.lastModified())); + byte[] inManifest = listJarResources(injarFile,resources); + 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(); + + 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 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 resources = new HashSet(); + + try { + byte[] inManifest = listJarResources(injarFile,resources); + 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()); + } + } + private byte[] listJarResources (File injarFile, Set resources) { + 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() && !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/testsrc/org/aspectj/ajde/core/tests/ReweavableTests.java b/ajde.core/testsrc/org/aspectj/ajde/core/tests/ReweavableTests.java new file mode 100644 index 000000000..4443268e6 --- /dev/null +++ b/ajde.core/testsrc/org/aspectj/ajde/core/tests/ReweavableTests.java @@ -0,0 +1,410 @@ +/* ******************************************************************* + * 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 ReweavableTests 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; + + protected void setUp() throws Exception { + super.setUp(); + initialiseProject("ReweavableTest"); + handler = (TestMessageHandler) getCompiler().getMessageHandler(); + handler.dontIgnore(IMessage.INFO); + compilerConfig = (TestCompilerConfiguration) getCompiler() + .getCompilerConfiguration(); + } + + 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 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 paths = new HashSet(); + paths.add(openFile(binDir)); + compilerConfig.setInpath(paths); + String[] newFiles = new String[] { "SecondAspect.aj" }; + compilerConfig.setProjectSourceFiles(getSourceFileList(newFiles)); + + doBuild(true); + + String expMessage = "type Logger is needed by reweavable type 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 paths = new HashSet(); + paths.add(openFile(binDir)); + compilerConfig.setInpath(paths); + compilerConfig.setProjectSourceFiles(new ArrayList()); + doBuild(true); + + String expMessage = "type tjp.GetInfo is needed by reweavable type 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 paths = new HashSet(); + paths.add(openFile(binDir)); + compilerConfig.setInpath(paths); + compilerConfig.setProjectSourceFiles(new ArrayList()); + 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/testsrc/org/aspectj/ajde/core/tests/ShowWeaveMessagesTests.java b/ajde.core/testsrc/org/aspectj/ajde/core/tests/ShowWeaveMessagesTests.java new file mode 100644 index 000000000..7d4b578a0 --- /dev/null +++ b/ajde.core/testsrc/org/aspectj/ajde/core/tests/ShowWeaveMessagesTests.java @@ -0,0 +1,446 @@ +/* ******************************************************************* + * 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 ShowWeaveMessagesTests 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; + + 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"); + } + + 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 inpath = new HashSet(); + inpath.add(openFile("Simple.jar")); + compilerConfig.setInpath(inpath); + Set aspectpath = new HashSet(); + 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 inpath = new HashSet(); + inpath.add(openFile("Simple.jar")); + compilerConfig.setInpath(inpath); + Set aspectpath = new HashSet(); + 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 inpath = new HashSet(); + inpath.add(openFile("Simple.jar")); + compilerConfig.setInpath(inpath); + Set aspectpath = new HashSet(); + 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 inpath = new HashSet(); + inpath.add(openFile("Simple.jar")); + compilerConfig.setInpath(inpath); + Set aspectpath = new HashSet(); + 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 inpath = new HashSet(); + inpath.add(openFile("Simple.jar")); + compilerConfig.setInpath(inpath); + Set aspectpath = new HashSet(); + 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 inpath = new HashSet(); + inpath.add(openFile("Simple.jar")); + compilerConfig.setInpath(inpath); + Set aspectpath = new HashSet(); + 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 inpath = new HashSet(); + inpath.add(openFile("Simple_nodebug.jar")); + compilerConfig.setInpath(inpath); + Set aspectpath = new HashSet(); + 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 inpath = new HashSet(); + inpath.add(openFile("Simple_nodebug.jar")); + compilerConfig.setInpath(inpath); + Set 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 inpath = new HashSet(); + inpath.add(openFile("Simple_nodebug.jar")); + compilerConfig.setInpath(inpath); + Set aspectpath = new HashSet(); + 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 inpath = new HashSet(); + inpath.add(openFile("Simple_nodebug.jar")); + compilerConfig.setInpath(inpath); + Set aspectpath = new HashSet(); + 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 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 originalFileContents = new ArrayList(); + originalFileContents.addAll(fileContents); + + // See if the messages match + int msgCount = 0; + List l = handler.getMessages(); + for (Iterator iter = l.iterator(); iter.hasNext();) { + IMessage msg = ((TestMessageHandler.TestMessage) 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 l) { + StringBuffer result = new StringBuffer(); + for (Iterator iter = l.iterator(); iter.hasNext();) { + String str = (String) iter.next(); + 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 l = handler.getMessages(); + for (Iterator iter = l.iterator(); iter.hasNext();) { + IMessage msg = ((TestMessageHandler.TestMessage) 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 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/testsrc/org/aspectj/ajde/core/tests/model/AsmDeclarationsTests.java b/ajde.core/testsrc/org/aspectj/ajde/core/tests/model/AsmDeclarationsTests.java new file mode 100644 index 000000000..3da3f0fea --- /dev/null +++ b/ajde.core/testsrc/org/aspectj/ajde/core/tests/model/AsmDeclarationsTests.java @@ -0,0 +1,224 @@ +/* ******************************************************************* + * 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.ajde.core.TestMessageHandler; +import org.aspectj.asm.AsmManager; +import org.aspectj.asm.IHierarchy; +import org.aspectj.asm.IProgramElement; + +public class AsmDeclarationsTests extends AjdeCoreTestCase { + + private IHierarchy model = null; + + private String[] files = new String[]{ + "ModelCoverage.java", + "pkg" + File.separator + "InPackage.java" + }; + + private TestMessageHandler handler; + private TestCompilerConfiguration compilerConfig; + + protected void setUp() throws Exception { + super.setUp(); + initialiseProject("coverage"); + handler = (TestMessageHandler) getCompiler().getMessageHandler(); + compilerConfig = (TestCompilerConfiguration) getCompiler() + .getCompilerConfiguration(); + compilerConfig.setProjectSourceFiles(getSourceFileList(files)); + doBuild(); + model = AsmManager.getDefault().getHierarchy(); + } + + protected void tearDown() throws Exception { + super.tearDown(); + handler = null; + compilerConfig = null; + model = null; + } + + public void testRoot() { + IProgramElement root = (IProgramElement)model.getRoot(); + assertNotNull(root); + assertEquals("Expected root to be named 'coverage' but found " + + root.toLabelString(), root.toLabelString(), "coverage"); + } + + public void testAspectAccessibility() { + IProgramElement packageAspect = AsmManager.getDefault().getHierarchy().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 = AsmManager.getDefault().getHierarchy().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)root.getChildren().get(0)).toLabelString(), "ModelCoverage.java"); + } + + public void testDeclares() { + IProgramElement node = (IProgramElement)model.getRoot(); + assertNotNull(node); + + IProgramElement aspect = AsmManager.getDefault().getHierarchy().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 = (IProgramElement)model.getRoot(); + assertNotNull(node); + + IProgramElement aspect = AsmManager.getDefault().getHierarchy().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 = (IProgramElement)model.getRoot(); + assertNotNull(node); + + IProgramElement aspect = AsmManager.getDefault().getHierarchy().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 = (IProgramElement)model.getRoot(); + assertNotNull(node); + + IProgramElement aspect = AsmManager.getDefault().getHierarchy().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 = (IProgramElement)model.getRoot(); + assertNotNull(node); + + IProgramElement aspect = AsmManager.getDefault().getHierarchy().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/testsrc/org/aspectj/ajde/core/tests/model/AsmRelationshipsTests.java b/ajde.core/testsrc/org/aspectj/ajde/core/tests/model/AsmRelationshipsTests.java new file mode 100644 index 000000000..fca358138 --- /dev/null +++ b/ajde.core/testsrc/org/aspectj/ajde/core/tests/model/AsmRelationshipsTests.java @@ -0,0 +1,206 @@ +/* ******************************************************************* + * 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.ajde.core.TestMessageHandler; +import org.aspectj.ajdt.internal.core.builder.AsmHierarchyBuilder; +import org.aspectj.asm.AsmManager; +import org.aspectj.asm.IProgramElement; +import org.aspectj.asm.IRelationship; + +public class AsmRelationshipsTests extends AjdeCoreTestCase { + + private AsmManager manager = null; + + private String[] files = new String[]{ + "ModelCoverage.java", + "pkg" + File.separator + "InPackage.java" + }; + + private TestMessageHandler handler; + private TestCompilerConfiguration compilerConfig; + + protected void setUp() throws Exception { + super.setUp(); + initialiseProject("coverage"); + handler = (TestMessageHandler) getCompiler().getMessageHandler(); + compilerConfig = (TestCompilerConfiguration) getCompiler() + .getCompilerConfiguration(); + compilerConfig.setProjectSourceFiles(getSourceFileList(files)); + doBuild(); + manager = AsmManager.getDefault(); + } + + protected void tearDown() throws Exception { + super.tearDown(); + handler = null; + 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 = AsmManager.getDefault().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 rels = AsmManager.getDefault().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 = AsmManager.getDefault().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 = (String)rel.getTargets().get(0); + assertEquals(manager.getHierarchy().findElementForHandle(handle).toString(), to); + + IProgramElement clazz = AsmManager.getDefault().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 = (String)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 = AsmManager.getDefault().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 it = rel.getTargets().iterator(); it.hasNext(); ) { + String currHandle = (String)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 = AsmManager.getDefault().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 = (String)rel.getTargets().get(0); + assertEquals(manager.getHierarchy().findElementForHandle(handle).toString(), to); + + IProgramElement clazz = AsmManager.getDefault().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 = (String)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 = AsmManager.getDefault().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 = (String)rel.getTargets().get(0); + assertEquals(manager.getHierarchy().findElementForHandle(handle).toString(), to); + + IProgramElement clazz = AsmManager.getDefault().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 it = rel2.getTargets().iterator(); it.hasNext(); ) { + String currHandle = (String)it.next(); + if (manager.getHierarchy().findElementForHandle(currHandle).toLabelString().equals(from)) return; + } + fail(); // didn't find it + } +} diff --git a/ajde.core/testsrc/org/aspectj/ajde/core/tests/model/SavedModelConsistencyTests.java b/ajde.core/testsrc/org/aspectj/ajde/core/tests/model/SavedModelConsistencyTests.java new file mode 100644 index 000000000..99f6e354f --- /dev/null +++ b/ajde.core/testsrc/org/aspectj/ajde/core/tests/model/SavedModelConsistencyTests.java @@ -0,0 +1,119 @@ +/* ******************************************************************* + * 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.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 SavedModelConsistencyTests extends AjdeCoreTestCase { + + private String[] files = new String[]{ + "ModelCoverage.java", + "pkg" + File.separator + "InPackage.java" + }; + + private TestMessageHandler handler; + private TestCompilerConfiguration compilerConfig; + + 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()); + } + + protected void tearDown() throws Exception { + super.tearDown(); + handler = null; + compilerConfig = null; + } + + public void testInterfaceIsSameInBoth() { + AsmManager.getDefault().readStructureModel(getAbsoluteProjectDir()); + + IHierarchy model = AsmManager.getDefault().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.getDefault().readStructureModel(getAbsoluteProjectDir()); + IHierarchy model = AsmManager.getDefault().getHierarchy(); + assertTrue("model exists", model != null); + + final List preBuildKinds = new ArrayList(); + HierarchyWalker walker = new HierarchyWalker() { + public void preProcess(IProgramElement node) { + preBuildKinds.add(node.getKind()); + } + }; + AsmManager.getDefault().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 postBuildKinds = new ArrayList(); + HierarchyWalker walker2 = new HierarchyWalker() { + public void preProcess(IProgramElement node) { + postBuildKinds.add(node.getKind()); + } + }; + AsmManager.getDefault().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/testsrc/org/aspectj/ajde/core/tests/model/StructureModelTests.java b/ajde.core/testsrc/org/aspectj/ajde/core/tests/model/StructureModelTests.java new file mode 100644 index 000000000..8d9a7f836 --- /dev/null +++ b/ajde.core/testsrc/org/aspectj/ajde/core/tests/model/StructureModelTests.java @@ -0,0 +1,152 @@ +/* ******************************************************************* + * 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.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 StructureModelTests extends AjdeCoreTestCase { + + private AsmManager manager = null; + + private 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 TestMessageHandler handler; + private TestCompilerConfiguration compilerConfig; + + protected void setUp() throws Exception { + super.setUp(); + initialiseProject("figures-coverage"); + handler = (TestMessageHandler) getCompiler().getMessageHandler(); + compilerConfig = (TestCompilerConfiguration) getCompiler() + .getCompilerConfiguration(); + compilerConfig.setProjectSourceFiles(getSourceFileList(files)); + doBuild(); + manager = AsmManager.getDefault(); + } + + protected void tearDown() throws Exception { + super.tearDown(); + handler = null; + 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) ; + IProgramElement pNode = (IProgramElement)node; + String child = ((IProgramElement)pNode.getChildren().get(1)).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)((IProgramElement)node).getChildren().get(2); + 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", 3, node.getChildren().size()) ; + IProgramElement pNode = (IProgramElement)node; + assertTrue("found node: " + pNode.getName(), pNode.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 = (IProgramElement)((IProgramElement)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 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 it = node.getChildren().iterator(); it.hasNext(); ) { + if (it.next() == null) throw new NullPointerException("null child on node: " + node.getName()); + } + } + }; + manager.getHierarchy().getRoot().walk(walker); + } +} |