From: aclement Date: Tue, 9 Jan 2007 09:37:59 +0000 (+0000) Subject: test and fix for 166580: multiple output locations and incremental compilation X-Git-Tag: Root_extensions~57 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=6cf03da38e931dd898a845dd94d6f92a981c12f0;p=aspectj.git test and fix for 166580: multiple output locations and incremental compilation --- diff --git a/tests/multiIncremental/MultipleOutputFolders/base/srcRootThree/c/C.java b/tests/multiIncremental/MultipleOutputFolders/base/srcRootThree/c/C.java new file mode 100644 index 000000000..39412f297 --- /dev/null +++ b/tests/multiIncremental/MultipleOutputFolders/base/srcRootThree/c/C.java @@ -0,0 +1,5 @@ +package c; + +public class C { + +} diff --git a/tests/multiIncremental/MultipleOutputFolders/base/srcRootTwo/b/ClassContainingAspect.java b/tests/multiIncremental/MultipleOutputFolders/base/srcRootTwo/b/ClassContainingAspect.java new file mode 100644 index 000000000..c7b80ebe7 --- /dev/null +++ b/tests/multiIncremental/MultipleOutputFolders/base/srcRootTwo/b/ClassContainingAspect.java @@ -0,0 +1,10 @@ +package b; + +public class ClassContainingAspect { + + + static aspect InnerAspect { + + } + +} diff --git a/tests/multiIncremental/MultipleOutputFolders/inc1/srcRootThree/c/C.java b/tests/multiIncremental/MultipleOutputFolders/inc1/srcRootThree/c/C.java new file mode 100644 index 000000000..6f389cb55 --- /dev/null +++ b/tests/multiIncremental/MultipleOutputFolders/inc1/srcRootThree/c/C.java @@ -0,0 +1,8 @@ +package c; + +public class C { + + static aspect AnAspect { + + } +} diff --git a/tests/multiIncremental/PR166580/base/src1/pkg/C1.java b/tests/multiIncremental/PR166580/base/src1/pkg/C1.java new file mode 100644 index 000000000..a40eed53c --- /dev/null +++ b/tests/multiIncremental/PR166580/base/src1/pkg/C1.java @@ -0,0 +1,9 @@ +package pkg; + +public class C1 { + + public void foo() { + + } + +} diff --git a/tests/multiIncremental/PR166580/base/src2/pkg/C2.java b/tests/multiIncremental/PR166580/base/src2/pkg/C2.java new file mode 100644 index 000000000..57a8e5bdd --- /dev/null +++ b/tests/multiIncremental/PR166580/base/src2/pkg/C2.java @@ -0,0 +1,9 @@ +package pkg; + +public class C2 { + + public void foo() { + + } + +} diff --git a/tests/multiIncremental/PR166580/inc1/src1/pkg/C1.java b/tests/multiIncremental/PR166580/inc1/src1/pkg/C1.java new file mode 100644 index 000000000..9525ab5da --- /dev/null +++ b/tests/multiIncremental/PR166580/inc1/src1/pkg/C1.java @@ -0,0 +1,9 @@ +package pkg; + +public class C1 { + + public void foo() { + System.out.println("blah"); + } + +} diff --git a/tests/multiIncremental/inpathTesting/README.txt b/tests/multiIncremental/inpathTesting/README.txt index 34e5f7798..c022fd28e 100644 --- a/tests/multiIncremental/inpathTesting/README.txt +++ b/tests/multiIncremental/inpathTesting/README.txt @@ -8,4 +8,10 @@ To regenerate the class copied over as part of the test: javac newInpathClass\InpathClass.java +To regenerate the jar file base\inpathJar.jar + javac origInpathClass\InpathClass.java + cd origInpathClass + jar cf inpathJar.jar InpathClass.class inpathResource.txt + +copy resultant jar file to ..\base diff --git a/tests/multiIncremental/inpathTesting/base/injarBin/pkg/inDirResource.txt b/tests/multiIncremental/inpathTesting/base/injarBin/pkg/inDirResource.txt new file mode 100644 index 000000000..547066cc7 --- /dev/null +++ b/tests/multiIncremental/inpathTesting/base/injarBin/pkg/inDirResource.txt @@ -0,0 +1 @@ +resource in directory on inpath \ No newline at end of file diff --git a/tests/multiIncremental/inpathTesting/base/inpathJar.jar b/tests/multiIncremental/inpathTesting/base/inpathJar.jar new file mode 100644 index 000000000..25000ec0a Binary files /dev/null and b/tests/multiIncremental/inpathTesting/base/inpathJar.jar differ diff --git a/tests/multiIncremental/inpathTesting/origInpathClass/inpathResource.txt b/tests/multiIncremental/inpathTesting/origInpathClass/inpathResource.txt new file mode 100644 index 000000000..2969d2632 --- /dev/null +++ b/tests/multiIncremental/inpathTesting/origInpathClass/inpathResource.txt @@ -0,0 +1 @@ +resource on inpath... \ No newline at end of file diff --git a/tests/src/org/aspectj/systemtest/AllTests15.java b/tests/src/org/aspectj/systemtest/AllTests15.java index e0a372662..bc0c52a55 100644 --- a/tests/src/org/aspectj/systemtest/AllTests15.java +++ b/tests/src/org/aspectj/systemtest/AllTests15.java @@ -11,8 +11,10 @@ import org.aspectj.systemtest.ajc150.ataspectj.AtAjAnnotationGenTests; import org.aspectj.systemtest.ajc151.AllTestsAspectJ151; import org.aspectj.systemtest.ajc152.AllTestsAspectJ152; import org.aspectj.systemtest.ajc153.AllTestsAspectJ153; -import org.aspectj.systemtest.model.Model5Tests; +import org.aspectj.systemtest.incremental.tools.IncrementalOutputLocationManagerTests; +import org.aspectj.systemtest.incremental.tools.MoreOutputLocationManagerTests; import org.aspectj.systemtest.incremental.tools.MultiProjectIncrementalTests; +import org.aspectj.systemtest.model.Model5Tests; import org.aspectj.systemtest.xlint.XLint5Tests; public class AllTests15 { @@ -33,6 +35,8 @@ public class AllTests15 { * for the moment. */ suite.addTestSuite(MultiProjectIncrementalTests.class); + suite.addTestSuite(MoreOutputLocationManagerTests.class); + suite.addTestSuite(IncrementalOutputLocationManagerTests.class); suite.addTest(XLint5Tests.suite()); //$JUnit-END$ return suite; diff --git a/tests/src/org/aspectj/systemtest/incremental/tools/AbstractMultiProjectIncrementalAjdeInteractionTestbed.java b/tests/src/org/aspectj/systemtest/incremental/tools/AbstractMultiProjectIncrementalAjdeInteractionTestbed.java index 7c30f2c02..f1e7caf8a 100644 --- a/tests/src/org/aspectj/systemtest/incremental/tools/AbstractMultiProjectIncrementalAjdeInteractionTestbed.java +++ b/tests/src/org/aspectj/systemtest/incremental/tools/AbstractMultiProjectIncrementalAjdeInteractionTestbed.java @@ -1,8 +1,10 @@ package org.aspectj.systemtest.incremental.tools; +import java.io.BufferedReader; import java.io.DataOutputStream; import java.io.File; import java.io.FileOutputStream; +import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.Iterator; @@ -103,6 +105,17 @@ public class AbstractMultiProjectIncrementalAjdeInteractionTestbed extends copy(projectSrc,destination);//,false); } + /* + * Applies an overlay onto the project being tested - copying + * the contents of the specified overlay directory. + */ + public void alter(String projectName,String overlayDirectory) { + File projectSrc =new File(testdataSrcDir+File.separatorChar+projectName+ + File.separatorChar+overlayDirectory); + File destination=new File(getWorkingDir(),projectName); + copy(projectSrc,destination); + } + /** * Copy the contents of some directory to another location - the * copy is recursive. @@ -127,4 +140,40 @@ public class AbstractMultiProjectIncrementalAjdeInteractionTestbed extends } } + /** + * Count the number of times a specified aspectName appears in the default + * aop.xml file and compare with the expected number of occurrences. If just + * want to count the number of aspects mentioned within the file then + * pass "" for the aspectName, otherwise, specify the name of the + * aspect interested in. + */ + protected void checkXMLAspectCount(String projectName, String aspectName, + int expectedOccurrences, String outputDir) { + int aspectCount = 0; + File aopXML = new File(outputDir + File.separatorChar + "META-INF" + File.separatorChar + "aop-ajc.xml"); + + if (!aopXML.exists()) { + fail("Expected file " + aopXML.getAbsolutePath() + " to exist but it doesn't"); + } + try { + BufferedReader reader = new BufferedReader(new FileReader(aopXML)); + String line = reader.readLine(); + while (line != null) { + if (aspectName.equals("") && line.indexOf("aspect name=\"") != -1) { + aspectCount++; + } else if (line.indexOf("aspect name=\""+aspectName+"\"") != -1) { + aspectCount++; + } + line = reader.readLine(); + } + reader.close(); + } catch (IOException ie) { + ie.printStackTrace(); + } + if (aspectCount != expectedOccurrences) { + fail("Expected aspect " + aspectName + " to appear " + expectedOccurrences + " times" + + " in the aop.xml file but found " + aspectCount + " occurrences"); + } + } + } diff --git a/tests/src/org/aspectj/systemtest/incremental/tools/AjdeInteractionTestbed.java b/tests/src/org/aspectj/systemtest/incremental/tools/AjdeInteractionTestbed.java index 61d84f4b8..4d67e7eba 100644 --- a/tests/src/org/aspectj/systemtest/incremental/tools/AjdeInteractionTestbed.java +++ b/tests/src/org/aspectj/systemtest/incremental/tools/AjdeInteractionTestbed.java @@ -83,6 +83,10 @@ public class AjdeInteractionTestbed extends TestCase { MyProjectPropertiesAdapter.setOutputLocationManager(mgr); } + public static void configureOutputLocationManager(OutputLocationManager mgr, boolean hasOutputPath) { + MyProjectPropertiesAdapter.setOutputLocationManager(mgr,hasOutputPath); + } + public static void configureResourceMap(Map resourcesMap) { MyProjectPropertiesAdapter.setSourcePathResources(resourcesMap); } @@ -101,11 +105,14 @@ public class AjdeInteractionTestbed extends TestCase { // Create a sandbox in which to work sandboxDir = Ajc.createEmptySandbox(); + + IncrementalStateManager.debugIncrementalStates = true; } protected void tearDown() throws Exception { super.tearDown(); AjState.stateListener=null; + IncrementalStateManager.clearIncrementalStates(); } /** Drives a build */ @@ -284,6 +291,26 @@ public class AjdeInteractionTestbed extends TestCase { System.out.println("============================================="); } + /** + * Check we compiled/wove the right number of files, passing '-1' indicates you don't care about + * that number. + */ + public void checkCompileWeaveCount(int expCompile,int expWoven) { + if (expCompile!=-1 && getCompiledFiles().size()!=expCompile) + fail("Expected compilation of "+expCompile+" files but compiled "+getCompiledFiles().size()+ + "\n"+printCompiledAndWovenFiles()); + if (expWoven!=-1 && getWovenClasses().size()!=expWoven) + fail("Expected weaving of "+expWoven+" files but wove "+getWovenClasses().size()+ + "\n"+printCompiledAndWovenFiles()); + } + + public void checkWasntFullBuild() { + assertTrue("Shouldn't have been a full (batch) build",!wasFullBuild()); + } + + public void checkWasFullBuild() { + assertTrue("Should have been a full (batch) build",wasFullBuild()); + } public boolean wasFullBuild() { // alternatives: statelistener is debug interface, progressmonitor is new proper interface (see pr145689) @@ -361,7 +388,6 @@ public class AjdeInteractionTestbed extends TestCase { static MyProjectPropertiesAdapter _instance = new MyProjectPropertiesAdapter(); private MyProjectPropertiesAdapter() {} - public static MyProjectPropertiesAdapter getInstance() { return _instance; } @@ -371,14 +397,18 @@ public class AjdeInteractionTestbed extends TestCase { _instance.inpath = null; _instance.sourcePathResources=null; _instance.outputLocationManager=null; + _instance.hasOutputPath = true; + _instance.outputPath = null; } private String projectName = null; + private String outputPath = null; private String classPath = ""; private Set aspectPath = null; private Set inpath = null; private Map sourcePathResources = null; private OutputLocationManager outputLocationManager = null; + private boolean hasOutputPath = true; public static void setActiveProject(String n) { _instance.projectName = n; @@ -409,10 +439,9 @@ public class AjdeInteractionTestbed extends TestCase { _instance.aspectPath = path; } - public static void setInpath(Set inpath) { - _instance.inpath = inpath; + public static void setInpath(Set path) { + _instance.inpath = path; } - // interface impl below @@ -457,7 +486,22 @@ public class AjdeInteractionTestbed extends TestCase { // DOESSOMETHING public String getClasspath() { log("MyProjectProperties.getClasspath()"); + // AJDT has all the output directories on it's classpath + StringBuffer sb = new StringBuffer(); + String outputPath = getOutputPath(); + sb.append(outputPath); + if (outputLocationManager != null) { + List allOutputPaths = outputLocationManager.getAllOutputLocations(); + for (Iterator iterator = allOutputPaths.iterator(); iterator + .hasNext();) { + File dir = (File) iterator.next(); + if (!dir.getAbsolutePath().equals(getOutputPath())) { + sb.append(File.pathSeparator + dir.getAbsolutePath()); + } + } + } String cp = + sb.toString() + File.pathSeparator + new File(testdataSrcDir) + File.pathSeparator + System.getProperty("sun.boot.class.path") + File.pathSeparator + "../runtime/bin" + @@ -482,9 +526,17 @@ public class AjdeInteractionTestbed extends TestCase { } public String getOutputPath() { + if (!hasOutputPath) return null; + String dir = getFile(projectName,"bin"); log("MyProjectProperties.getOutputPath() [returning "+dir+"]"); return dir; + //return null; + } + + public static void setOutputLocationManager(OutputLocationManager mgr,boolean hasOutputPath ) { + _instance.hasOutputPath = hasOutputPath; + _instance.outputLocationManager = mgr; } public static void setOutputLocationManager(OutputLocationManager mgr) { @@ -492,7 +544,11 @@ public class AjdeInteractionTestbed extends TestCase { } public OutputLocationManager getOutputLocationManager() { - return this.outputLocationManager; + return outputLocationManager; +// if (testHasSetOutputLocationManager) { +// return outputLocationManager; +// } +// return new MyOutputLocationManager(sandboxDir + File.separator + projectName); } public String getBootClasspath() { @@ -521,7 +577,7 @@ public class AjdeInteractionTestbed extends TestCase { } public Set getInpath() { - log("MyProjectProperties.getInPath(" + inpath +")"); + log("MyProjectProperties.getInPath(" + inpath + ")"); return inpath; } @@ -835,6 +891,44 @@ public class AjdeInteractionTestbed extends TestCase { return false; } } + + // ---- + + static class MyOutputLocationManager implements OutputLocationManager { + + private File classOutputLoc; + private File resourceOutputLoc; + private String testProjectOutputPath; + private List allOutputLocations; + private File outputLoc; + + public MyOutputLocationManager(String testProjectPath) { + this.testProjectOutputPath = testProjectPath + File.separator + "bin"; + outputLoc = new File(testProjectOutputPath); + + allOutputLocations = new ArrayList(); + allOutputLocations.add(outputLoc); + } + + public File getOutputLocationForClass(File compilationUnit) { + return outputLoc; + } + + public File getOutputLocationForResource(File resource) { + return outputLoc; + } + + public List /*File*/ getAllOutputLocations() { + return allOutputLocations; + } + + public File getDefaultOutputLocation() { + return outputLoc; + } + + } + + // ---- static class MyStateListener extends AbstractStateListener { diff --git a/tests/src/org/aspectj/systemtest/incremental/tools/IncrementalOutputLocationManagerTests.java b/tests/src/org/aspectj/systemtest/incremental/tools/IncrementalOutputLocationManagerTests.java new file mode 100644 index 000000000..26306608e --- /dev/null +++ b/tests/src/org/aspectj/systemtest/incremental/tools/IncrementalOutputLocationManagerTests.java @@ -0,0 +1,87 @@ +/******************************************************************** + * Copyright (c) 2006 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.systemtest.incremental.tools; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +import org.aspectj.ajde.OutputLocationManager; + + +/** + * OutputLocationManger tests which check whether the correct type of build has happened. + */ +public class IncrementalOutputLocationManagerTests extends AbstractMultiProjectIncrementalAjdeInteractionTestbed { + + public void testPr166580() { + initialiseProject("PR166580"); + configureOutputLocationManager(new MyOutputLocationManager("PR166580",2)); + build("PR166580"); + checkWasFullBuild(); + alter("PR166580","inc1"); + build("PR166580"); + checkWasntFullBuild(); + } + + + /** + * Will send output from src dir 'srcX' to directory 'binX' + */ + private class MyOutputLocationManager implements OutputLocationManager { + + private String projectDir; + private int numberOfSrcDirs; + private List allOutputDirs; + + public MyOutputLocationManager(String projectName, int numberOfSrcDirs) { + projectDir = getWorkingDir() + File.separator + projectName; + this.numberOfSrcDirs = numberOfSrcDirs; + } + + public File getOutputLocationForClass(File compilationUnit) { + String path = compilationUnit.getAbsolutePath(); + int index = path.indexOf("src"); + String number = path.substring(index +3,index + 4); + File ret = new File(projectDir + File.separator + "bin" + number); + if (!ret.exists()) { + ret.mkdirs(); + } + return ret; + } + + public File getOutputLocationForResource(File resource) { + return getOutputLocationForClass(resource); + } + + public List getAllOutputLocations() { + if (allOutputDirs == null) { + allOutputDirs = new ArrayList(); + for (int i = 0; i < numberOfSrcDirs + 1; i++) { + File f = null; + if (i == 0) { + f = new File(projectDir + File.separator + "bin"); + } else { + f = new File(projectDir + File.separator + "bin" + i); + } + allOutputDirs.add(f); + } + } + return allOutputDirs; + } + + public File getDefaultOutputLocation() { + return new File(projectDir + File.separator + "bin"); + } + + } + +} diff --git a/tests/src/org/aspectj/systemtest/incremental/tools/MoreOutputLocationManagerTests.java b/tests/src/org/aspectj/systemtest/incremental/tools/MoreOutputLocationManagerTests.java new file mode 100644 index 000000000..037c628f2 --- /dev/null +++ b/tests/src/org/aspectj/systemtest/incremental/tools/MoreOutputLocationManagerTests.java @@ -0,0 +1,375 @@ +/******************************************************************** + * Copyright (c) 2006 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.systemtest.incremental.tools; + +import java.io.File; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.aspectj.ajde.OutputLocationManager; +import org.aspectj.ajdt.internal.core.builder.AjBuildConfig; +import org.aspectj.ajdt.internal.core.builder.AjBuildManager; +import org.aspectj.ajdt.internal.core.builder.AjState; +import org.aspectj.ajdt.internal.core.builder.IncrementalStateManager; +import org.aspectj.util.FileUtil; +import org.aspectj.weaver.bcel.UnwovenClassFile; + +/** + * Similar to OutputLocationManagerTests, however, tests the different + * scenarios when no outputDir is set but instead there is an + * OutputLocationManager which returns the same output location for all + * files and resources. + * + * There are eight places where AjBuildConfig.getOutputDir() is called + * that are tested here: + * + * AjBuildManager.getOutputClassFileName(..) - testCorrectInfoWhenNoOutputPath + * AjBuildManager.initBcelWorld(..) - testPathResolutionWithInpathDirAndNoOutputPath + * testPathResolutionWithInpathJarAndNoOutputPath + * AjBuildManager.writeManifest(..) - testCopyManifest + * AjBuildManager.writeOutxml(..) - testOutxml + * - testOutXmlForAspectsWithDifferentOutputDirs + * AjState.createUnwovenClassFile(..) - testPathResolutionAfterChangeInClassOnInpath + * AjState.deleteResources(..) - testAjStateDeleteResources + * AjState.maybeDeleteResources(..) - testAjStateDeleteResourcesInInputDir + * AjState.removeAllResultsOfLastBuild(..) - testAllResourcesAreDeletedCorrectlyOnPathChange + * IncrementalStateManager.findStateManagingOutputLocation(..) - testFindStateManagingOutputLocation + * + * The other three places are not tested here because they were implemented + * when OutputLocationManager was introduced. + * + */ +public class MoreOutputLocationManagerTests extends AbstractMultiProjectIncrementalAjdeInteractionTestbed { + + private String inpathTestingDir; + private String expectedOutputDir; + + protected void setUp() throws Exception { + super.setUp(); + initialiseProject("inpathTesting"); + inpathTestingDir = getWorkingDir() + File.separator + "inpathTesting"; + expectedOutputDir = inpathTestingDir + File.separator + "bin"; + configureOutputLocationManager(new MyOutputLocationManager(inpathTestingDir), false); + } + + /** + * Tests that the UnwovenClassFiles have the correct path when there + * is no outputDir but there is an OutputLocationManager. Is a simple + * project that has no inpath setting + */ + public void testCorrectInfoWhenNoOutputPath() { + build("inpathTesting"); + AjState state = getState(); + + Map classNameToFileMap = state.getClassNameToFileMap(); + assertFalse("expected there to be classes ",classNameToFileMap.isEmpty()); + Set entrySet = classNameToFileMap.entrySet(); + for (Iterator iterator = entrySet.iterator(); iterator.hasNext();) { + Map.Entry entry = (Map.Entry) iterator.next(); + String className = (String) entry.getKey(); + String fullClassName = expectedOutputDir + File.separator + className.replace('.',File.separatorChar) + ".class"; + File file = (File) entry.getValue(); + assertEquals("expected file to have path \n" + fullClassName + ", but" + + " found path \n" + file.getAbsolutePath(),fullClassName, + file.getAbsolutePath()); + } + } + + /** + * Tests that can retieve the state that manages a given output location + * when there is no outputDir set + */ + public void testFindStateManagingOutputLocation() { + build("inpathTesting"); + AjState state = IncrementalStateManager.findStateManagingOutputLocation(new File(expectedOutputDir)); + assertNotNull("Expected to find a state that managed output location " + + expectedOutputDir + ", but did not", state); + + } + + /** + * Tests that the UnwovenClassFiles corresponding to classes on the + * inpath have the correct class name when there is no output directory + * (ultimately tests AjBuildManager.initBcelWorld() when there is a + * jar on the inpath). Only does one build. + */ + public void testPathResolutionWithInpathDirAndNoOutputPath() { + String inpathDir = inpathTestingDir + File.separator + "injarBin" + File.separator + "pkg"; + addInpathEntry(inpathDir); + build("inpathTesting"); + + // expect to compile the aspect in 'inpathTesting' project and weave + // both the aspect and the class on the inpath. + checkCompileWeaveCount(1,2); + + // get hold of the state for this project - expect to find one + AjState state = getState(); + + // the classes onthe inpath are recorded against the AjBuildManager + // (they are deleted from the ajstate whilst cleaning up after a build) + Map binarySources = state.getAjBuildManager().getBinarySourcesForThisWeave(); + assertFalse("expected there to be binary sources from the inpath setting but didn't find any",binarySources.isEmpty()); + + List unwovenClassFiles = (List) binarySources.get(inpathDir + File.separator + "InpathClass.class"); + List fileNames = new ArrayList(); + // the unwovenClassFiles should have filenames that point to the output dir + // (which in this case is the sandbox dir) and not where they came from. + for (Iterator iterator = unwovenClassFiles.iterator(); iterator.hasNext();) { + UnwovenClassFile ucf = (UnwovenClassFile) iterator.next(); + if (ucf.getFilename().indexOf(expectedOutputDir) == -1) { + fileNames.add(ucf.getFilename()); + } + } + assertTrue("expected to find UnwovenClassFile from directory\n" + expectedOutputDir + + ", \n but found files " + fileNames, fileNames.isEmpty()); + } + + /** + * Tests that the UnwovenClassFiles corresponding to classes on the + * inpath have the correct class name when there is no output directory + * (ultimately tests AjState.createUnwovenClassFile(BinarySourceFile) + * and ensures the unwovenClassFile has the correct name. Makes a change to + * a class file on the inpath to ensure we enter this method (there is a + * check that says are we the first build)) + */ + public void testPathResolutionAfterChangeInClassOnInpath() throws Exception { + String inpathDir = inpathTestingDir + File.separator + "injarBin" + File.separator + "pkg"; + addInpathEntry(inpathDir); + build("inpathTesting"); + + // build again so that we enter + // AjState.createUnwovenClassFile(BinarySourceFile) + File from = new File(testdataSrcDir+File.separatorChar+"inpathTesting" + +File.separatorChar+"newInpathClass" + File.separatorChar + "InpathClass.class"); + File destination = new File(inpathDir + File.separatorChar + "InpathClass.class"); + FileUtil.copyFile(from,destination); + + // get hold of the state for this project - expect to find one + AjState state = getState(); + AjBuildConfig buildConfig = state.getBuildConfig(); + state.prepareForNextBuild(buildConfig); + + Map binarySources = state.getBinaryFilesToCompile(true); + assertFalse("expected there to be binary sources from the inpath setting but didn't find any",binarySources.isEmpty()); + + List unwovenClassFiles = (List) binarySources.get(inpathDir + File.separator + "InpathClass.class"); + List fileNames = new ArrayList(); + // the unwovenClassFiles should have filenames that point to the output dir + // (which in this case is the sandbox dir) and not where they came from. + for (Iterator iterator = unwovenClassFiles.iterator(); iterator.hasNext();) { + UnwovenClassFile ucf = (UnwovenClassFile) iterator.next(); + if (ucf.getFilename().indexOf(expectedOutputDir) == -1) { + fileNames.add(ucf.getFilename()); + } + } + assertTrue("expected to find UnwovenClassFile from directory\n" + expectedOutputDir + + ", \n but found files " + fileNames, fileNames.isEmpty()); + } + + /** + * Tests that the UnwovenClassFiles corresponding to jars on the + * inpath have the correct class name when there is no output path + * (ultimately tests AjBuildManager.initBcelWorld() when there is a + * jar on the inpath). Only does one build. + */ + public void testPathResolutionWithInpathJarAndNoOutputPath() { + String inpathDir = inpathTestingDir + File.separator + "inpathJar.jar"; + addInpathEntry(inpathDir); + build("inpathTesting"); + // expect to compile the aspect in 'inpathTesting' project and weave + // both the aspect and the class in the jar on the inpath. + checkCompileWeaveCount(1,2); + + AjState state = getState(); + + // tests AjState.createUnwovenClassFile(BinarySourceFile) + Map binarySources = state.getAjBuildManager().getBinarySourcesForThisWeave(); + assertFalse("expected there to be binary sources from the inpath setting but didn't find any",binarySources.isEmpty()); + + List unwovenClassFiles = (List) binarySources.get(inpathDir); + List fileNames = new ArrayList(); + + for (Iterator iterator = unwovenClassFiles.iterator(); iterator.hasNext();) { + UnwovenClassFile ucf = (UnwovenClassFile) iterator.next(); + if (ucf.getFilename().indexOf(expectedOutputDir) == -1) { + fileNames.add(ucf.getFilename()); + } + } + assertTrue("expected to find UnwovenClassFile from directory\n" + expectedOutputDir + + ", \n but found files " + fileNames, fileNames.isEmpty()); + + } + + /** + * A manifest file is in the jar on the inpath - check that it's + * copied to the correct place + */ + public void testCopyManifest() { + String inpathDir = inpathTestingDir + File.separator + "inpathJar.jar"; + addInpathEntry(inpathDir); + + build("inpathTesting"); + String resource = expectedOutputDir + File.separator + "META-INF" + File.separator + "MANIFEST.MF"; + File f = new File(resource); + assertTrue("expected file " + resource + " to exist but it did not",f.exists()); + } + + /** + * "resources" are contained within inpath jars - check that + * a text file contained within a jar is copied and then + * deleted correctly. Essentially tests AjState.deleteResources(). + */ + public void testAjStateDeleteResources() { + String inpathDir = inpathTestingDir + File.separator + "inpathJar.jar"; + addInpathEntry(inpathDir); + + build("inpathTesting"); + + AjState state = getState(); + + String resource = expectedOutputDir + File.separator + "inpathResource.txt"; + File f = new File(resource); + assertTrue("expected file " + resource + " to exist but it did not",f.exists()); + // this call should delete the resources + state.getFilesToCompile(true); + assertFalse("did not expect the file " + resource + " to exist but it does",f.exists()); + } + + /** + * Can set to copy resources that are in inpath dirs - check that + * a text file contained within such a dir is copied and then + * deleted correctly. Essentially tests AjState.maybeDeleteResources(). + */ + public void testAjStateDeleteResourcesInInputDir() { + AjBuildManager.COPY_INPATH_DIR_RESOURCES = true; + try { + String inpathDir = inpathTestingDir + File.separator + "injarBin" + + File.separator + "pkg"; + addInpathEntry(inpathDir); + build("inpathTesting"); + AjState state = getState(); + String resource = "inDirResource.txt"; + assertTrue("expected state to have resource " + resource + "but it did not", + state.hasResource(resource)); + // this call should delete the resources - tests AjState.deleteResources() + state.getFilesToCompile(true); + assertFalse("did not expect state to have resource " + resource + + " but found that it did", state.hasResource(resource)); + } finally { + AjBuildManager.COPY_INPATH_DIR_RESOURCES = false; + } + + } + + /** + * Changing inpath entry from a jar to a directory between builds means + * that AjState should realise somethings changed. This causes all resources + * (Manifest and txt files) to be deleted. Also should be a full build. + * Essentially tests AjState.removeAllResultsFromLastBuild(). + */ + public void testAllResourcesAreDeletedCorrectlyOnPathChange() { + String inpathJar = inpathTestingDir + File.separator + "inpathJar.jar"; + + addInpathEntry(inpathJar); + build("inpathTesting"); + + String resource = expectedOutputDir + File.separator + "inpathResource.txt"; + File f = new File(resource); + assertTrue("expected file " + resource + " to exist but it did not",f.exists()); + + // this should force a change and the file is deleted + // tests AjState.removeAllResultsFromLastBuild() + addInpathEntry(null); + build("inpathTesting"); + assertFalse("did not expect the file " + resource + " to exist but it does",f.exists()); + + checkWasFullBuild(); + } + + public void testOutxml() { + configureNonStandardCompileOptions("-outxml"); + build("inpathTesting"); + String resource = expectedOutputDir + File.separator + "META-INF" + File.separator + "aop-ajc.xml"; + File f = new File(resource); + assertTrue("expected file " + resource + " to exist but it did not",f.exists()); + } + + public void testAspectsRecordedOnlyOnceInState() { + configureNonStandardCompileOptions("-outxml"); + build("inpathTesting"); + AjState state = getState(); + Map m = state.getAspectNamesToFileNameMap(); + assertEquals("Expected only one aspect recored in the state but found " + m.size(),1,m.size()); + build("inpathTesting"); + m = state.getAspectNamesToFileNameMap(); + assertEquals("Expected only one aspect recored in the state but found " + m.size(),1,m.size()); + } + + private AjState getState() { + // get hold of the state for this project - expect to find one + AjState state = IncrementalStateManager.retrieveStateFor(inpathTestingDir + File.separator + "build.lst" ); + assertNotNull("expected to find AjState for build config " + inpathTestingDir + + File.separator + "build.lst but didn't", state); + return state; + } + + private void addInpathEntry(String entry) { + if (entry == null) { + configureInPath(null); + return; + } + File f = new File(entry); + Set s = new HashSet(); + s.add(f); + configureInPath(s); + } + + /** + * Sends all output to the same directory + */ + private static class SingleDirOutputLocMgr implements OutputLocationManager { + + private File classOutputLoc; + private File resourceOutputLoc; + private String testProjectOutputPath; + private List allOutputLocations; + private File outputLoc; + + public SingleDirOutputLocMgr(String testProjectPath) { + this.testProjectOutputPath = testProjectPath + File.separator + "bin"; + outputLoc = new File(testProjectOutputPath); + + allOutputLocations = new ArrayList(); + allOutputLocations.add(outputLoc); + } + + public File getOutputLocationForClass(File compilationUnit) { + return outputLoc; + } + + public File getOutputLocationForResource(File resource) { + return outputLoc; + } + + public List /*File*/ getAllOutputLocations() { + return allOutputLocations; + } + + public File getDefaultOutputLocation() { + return outputLoc; + } + } + +} diff --git a/tests/src/org/aspectj/systemtest/incremental/tools/MultiProjectIncrementalTests.java b/tests/src/org/aspectj/systemtest/incremental/tools/MultiProjectIncrementalTests.java index 04a464750..cd20f3476 100644 --- a/tests/src/org/aspectj/systemtest/incremental/tools/MultiProjectIncrementalTests.java +++ b/tests/src/org/aspectj/systemtest/incremental/tools/MultiProjectIncrementalTests.java @@ -11,9 +11,7 @@ * ******************************************************************/ package org.aspectj.systemtest.incremental.tools; -import java.io.BufferedReader; import java.io.File; -import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import java.util.HashSet; @@ -1013,46 +1011,48 @@ public class MultiProjectIncrementalTests extends AbstractMultiProjectIncrementa initialiseProject("PR131505"); build("PR131505"); checkWasFullBuild(); + String outputDir = getWorkingDir().getAbsolutePath() + File.separatorChar + + "PR131505" + File.separatorChar + "bin"; // aop.xml file shouldn't contain any aspects - checkXMLAspectCount("PR131505","",0); + checkXMLAspectCount("PR131505","",0, outputDir); // add a new aspect A which should be included in the aop.xml file alter("PR131505","inc1"); build("PR131505"); checkWasFullBuild(); - checkXMLAspectCount("PR131505","",1); - checkXMLAspectCount("PR131505","A",1); + checkXMLAspectCount("PR131505","",1, outputDir); + checkXMLAspectCount("PR131505","A",1, outputDir); // make changes to the class file which shouldn't affect the contents // of the aop.xml file alter("PR131505","inc2"); build("PR131505"); checkWasntFullBuild(); - checkXMLAspectCount("PR131505","",1); - checkXMLAspectCount("PR131505","A",1); + checkXMLAspectCount("PR131505","",1, outputDir); + checkXMLAspectCount("PR131505","A",1, outputDir); // add another new aspect A1 which should also be included in the aop.xml file // ...there should be no duplicate entries in the file alter("PR131505","inc3"); build("PR131505"); checkWasFullBuild(); - checkXMLAspectCount("PR131505","",2); - checkXMLAspectCount("PR131505","A1",1); - checkXMLAspectCount("PR131505","A",1); + checkXMLAspectCount("PR131505","",2, outputDir); + checkXMLAspectCount("PR131505","A1",1, outputDir); + checkXMLAspectCount("PR131505","A",1, outputDir); // delete aspect A1 which meanss that aop.xml file should only contain A File a1 = new File(getWorkingDir().getAbsolutePath() + File.separatorChar + "PR131505" + File.separatorChar + "A1.aj"); a1.delete(); build("PR131505"); checkWasFullBuild(); - checkXMLAspectCount("PR131505","",1); - checkXMLAspectCount("PR131505","A1",0); - checkXMLAspectCount("PR131505","A",1); + checkXMLAspectCount("PR131505","",1, outputDir); + checkXMLAspectCount("PR131505","A1",0, outputDir); + checkXMLAspectCount("PR131505","A",1, outputDir); // add another aspect called A which is in a different package, both A // and pkg.A should be included in the aop.xml file alter("PR131505","inc4"); build("PR131505"); checkWasFullBuild(); - checkXMLAspectCount("PR131505","",2); - checkXMLAspectCount("PR131505","A",1); - checkXMLAspectCount("PR131505","pkg.A",1); + checkXMLAspectCount("PR131505","",2, outputDir); + checkXMLAspectCount("PR131505","A",1, outputDir); + checkXMLAspectCount("PR131505","pkg.A",1, outputDir); } public void testPr136585() { @@ -1673,7 +1673,7 @@ public class MultiProjectIncrementalTests extends AbstractMultiProjectIncrementa " error but only found that one",errors.size() > 1); } } - + public void testPr168840() throws Exception { initialiseProject("inpathTesting"); @@ -1800,26 +1800,6 @@ public class MultiProjectIncrementalTests extends AbstractMultiProjectIncrementa // --------------------------------------------------------------------------------------------------- - /** - * Check we compiled/wove the right number of files, passing '-1' indicates you don't care about - * that number. - */ - private void checkCompileWeaveCount(int expCompile,int expWoven) { - if (expCompile!=-1 && getCompiledFiles().size()!=expCompile) - fail("Expected compilation of "+expCompile+" files but compiled "+getCompiledFiles().size()+ - "\n"+printCompiledAndWovenFiles()); - if (expWoven!=-1 && getWovenClasses().size()!=expWoven) - fail("Expected weaving of "+expWoven+" files but wove "+getWovenClasses().size()+ - "\n"+printCompiledAndWovenFiles()); - } - - private void checkWasntFullBuild() { - assertTrue("Shouldn't have been a full (batch) build",!wasFullBuild()); - } - - private void checkWasFullBuild() { - assertTrue("Should have been a full (batch) build",wasFullBuild()); - } private IProgramElement checkForNode(String packageName,String typeName,boolean shouldBeFound) { IProgramElement ipe = AsmManager.getDefault().getHierarchy().findElementForType(packageName,typeName); @@ -1842,59 +1822,10 @@ public class MultiProjectIncrementalTests extends AbstractMultiProjectIncrementa } } - - /* - * Applies an overlay onto the project being tested - copying - * the contents of the specified overlay directory. - */ - private void alter(String projectName,String overlayDirectory) { - File projectSrc =new File(testdataSrcDir+File.separatorChar+projectName+ - File.separatorChar+overlayDirectory); - File destination=new File(getWorkingDir(),projectName); - copy(projectSrc,destination); - } - private static void log(String msg) { if (VERBOSE) System.out.println(msg); } - /** - * Count the number of times a specified aspectName appears in the default - * aop.xml file and compare with the expected number of occurrences. If just - * want to count the number of aspects mentioned within the file then - * pass "" for the aspectName, otherwise, specify the name of the - * aspect interested in. - */ - private void checkXMLAspectCount(String projectName, String aspectName, int expectedOccurrences) { - int aspectCount = 0; - File aopXML = new File(getWorkingDir().getAbsolutePath() - + File.separatorChar + projectName + File.separatorChar - + "bin" + File.separatorChar + "META-INF" + File.separatorChar + "aop-ajc.xml"); - - if (!aopXML.exists()) { - fail("Expected file " + aopXML.getAbsolutePath() + " to exist but it doesn't"); - } - try { - BufferedReader reader = new BufferedReader(new FileReader(aopXML)); - String line = reader.readLine(); - while (line != null) { - if (aspectName.equals("") && line.indexOf("aspect name=\"") != -1) { - aspectCount++; - } else if (line.indexOf("aspect name=\""+aspectName+"\"") != -1) { - aspectCount++; - } - line = reader.readLine(); - } - reader.close(); - } catch (IOException ie) { - ie.printStackTrace(); - } - if (aspectCount != expectedOccurrences) { - fail("Expected aspect " + aspectName + " to appear " + expectedOccurrences + " times" + - " in the aop.xml file but found " + aspectCount + " occurrences"); - } - } - private File getProjectRelativePath(String p,String filename) { File projDir = new File(getWorkingDir(),p); return new File(projDir,filename); diff --git a/tests/src/org/aspectj/systemtest/incremental/tools/OutputLocationManagerTests.java b/tests/src/org/aspectj/systemtest/incremental/tools/OutputLocationManagerTests.java index dbe7b0449..d32670906 100644 --- a/tests/src/org/aspectj/systemtest/incremental/tools/OutputLocationManagerTests.java +++ b/tests/src/org/aspectj/systemtest/incremental/tools/OutputLocationManagerTests.java @@ -12,7 +12,9 @@ package org.aspectj.systemtest.incremental.tools; import java.io.File; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.aspectj.ajde.OutputLocationManager; @@ -64,6 +66,27 @@ public class OutputLocationManagerTests extends AbstractMultiProjectIncrementalA assertFileExists(PROJECT_NAME,"target/main/classes/a/A$AjcClosure1.class"); } + /** + * Tests the case when we have two aspects, each of which are + * sent to a different output location. There should be an + * aop.xml file in each of the two output directories. + */ + public void testOutXmlForAspectsWithDifferentOutputDirs() { + configureNonStandardCompileOptions("-outxml"); + build(PROJECT_NAME); + assertFileExists(PROJECT_NAME,"target/main/classes/META-INF/aop-ajc.xml"); + assertFileExists(PROJECT_NAME,"target/test/classes/META-INF/aop-ajc.xml"); + // aop.xml file should exist even if there aren't any aspects (mirrors + // what happens when there's one output dir) + checkXMLAspectCount(PROJECT_NAME,"",0,getFile(PROJECT_NAME,"target/anotherTest/classes")); + // add aspects to the srcRootThree src dir and they should appear in the + // corresponding aop.xml file + alter(PROJECT_NAME,"inc1"); + build(PROJECT_NAME); + checkXMLAspectCount(PROJECT_NAME,"c.C$AnAspect",1,getFile(PROJECT_NAME,"target/anotherTest/classes")); + } + + protected void assertFileExists(String project, String relativePath) { assertTrue("file " + relativePath + " should have been created as a result of building " + project, new File(getFile(project, relativePath)).exists()); @@ -72,9 +95,11 @@ public class OutputLocationManagerTests extends AbstractMultiProjectIncrementalA private static class MyOutputLocationManager implements OutputLocationManager { private File projectHome; + private List allOutputDirs; public MyOutputLocationManager(File projectHome) { this.projectHome = projectHome; + } public File getOutputLocationForClass(File compilationUnit) { @@ -84,6 +109,8 @@ public class OutputLocationManagerTests extends AbstractMultiProjectIncrementalA relativePath = "target/main/classes"; } else if (compilationUnitName.indexOf("srcRootTwo") != -1) { relativePath = "target/test/classes"; + } else if (compilationUnitName.indexOf("srcRootThree") != -1) { + relativePath = "target/anotherTest/classes"; } File ret = new File(projectHome,relativePath); if (!ret.exists()) { @@ -95,6 +122,19 @@ public class OutputLocationManagerTests extends AbstractMultiProjectIncrementalA public File getOutputLocationForResource(File resource) { return getOutputLocationForClass(resource); } - + + public List getAllOutputLocations() { + if (allOutputDirs == null) { + allOutputDirs = new ArrayList(); + allOutputDirs.add(new File(projectHome,"target/main/classes")); + allOutputDirs.add(new File(projectHome,"target/test/classes")); + allOutputDirs.add(new File(projectHome,"target/anotherTest/classes")); + } + return allOutputDirs; + } + + public File getDefaultOutputLocation() { + return new File(projectHome,"target/main/classes"); + } } }