]> source.dussan.org Git - aspectj.git/commitdiff
test and fix for 166580: multiple output locations and incremental compilation
authoraclement <aclement>
Tue, 9 Jan 2007 09:37:59 +0000 (09:37 +0000)
committeraclement <aclement>
Tue, 9 Jan 2007 09:37:59 +0000 (09:37 +0000)
17 files changed:
tests/multiIncremental/MultipleOutputFolders/base/srcRootThree/c/C.java [new file with mode: 0644]
tests/multiIncremental/MultipleOutputFolders/base/srcRootTwo/b/ClassContainingAspect.java [new file with mode: 0644]
tests/multiIncremental/MultipleOutputFolders/inc1/srcRootThree/c/C.java [new file with mode: 0644]
tests/multiIncremental/PR166580/base/src1/pkg/C1.java [new file with mode: 0644]
tests/multiIncremental/PR166580/base/src2/pkg/C2.java [new file with mode: 0644]
tests/multiIncremental/PR166580/inc1/src1/pkg/C1.java [new file with mode: 0644]
tests/multiIncremental/inpathTesting/README.txt
tests/multiIncremental/inpathTesting/base/injarBin/pkg/inDirResource.txt [new file with mode: 0644]
tests/multiIncremental/inpathTesting/base/inpathJar.jar [new file with mode: 0644]
tests/multiIncremental/inpathTesting/origInpathClass/inpathResource.txt [new file with mode: 0644]
tests/src/org/aspectj/systemtest/AllTests15.java
tests/src/org/aspectj/systemtest/incremental/tools/AbstractMultiProjectIncrementalAjdeInteractionTestbed.java
tests/src/org/aspectj/systemtest/incremental/tools/AjdeInteractionTestbed.java
tests/src/org/aspectj/systemtest/incremental/tools/IncrementalOutputLocationManagerTests.java [new file with mode: 0644]
tests/src/org/aspectj/systemtest/incremental/tools/MoreOutputLocationManagerTests.java [new file with mode: 0644]
tests/src/org/aspectj/systemtest/incremental/tools/MultiProjectIncrementalTests.java
tests/src/org/aspectj/systemtest/incremental/tools/OutputLocationManagerTests.java

diff --git a/tests/multiIncremental/MultipleOutputFolders/base/srcRootThree/c/C.java b/tests/multiIncremental/MultipleOutputFolders/base/srcRootThree/c/C.java
new file mode 100644 (file)
index 0000000..39412f2
--- /dev/null
@@ -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 (file)
index 0000000..c7b80eb
--- /dev/null
@@ -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 (file)
index 0000000..6f389cb
--- /dev/null
@@ -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 (file)
index 0000000..a40eed5
--- /dev/null
@@ -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 (file)
index 0000000..57a8e5b
--- /dev/null
@@ -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 (file)
index 0000000..9525ab5
--- /dev/null
@@ -0,0 +1,9 @@
+package pkg;
+
+public class C1 {
+       
+       public void foo() {
+               System.out.println("blah");
+       }
+       
+}
index 34e5f779892e26db046eeb68650c8f4c01754845..c022fd28e0227e05a3aa98bf5c44cc545a29dee9 100644 (file)
@@ -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 (file)
index 0000000..547066c
--- /dev/null
@@ -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 (file)
index 0000000..25000ec
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 (file)
index 0000000..2969d26
--- /dev/null
@@ -0,0 +1 @@
+resource on inpath...
\ No newline at end of file
index e0a372662fc431d9a19e141e1c2a003531eefd06..bc0c52a55daa7fcf47a5f523ea9a83b93f6bac9f 100644 (file)
@@ -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;
index 7c30f2c02e7499c9c2699e2414527065cf44b73b..f1e7caf8a0b9506ade82fbbb516b7f0f2bb9ac45 100644 (file)
@@ -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");
+                               }
+                       }
+
 }
index 61d84f4b8cb1c490ec88d5ea6794f12926923f43..4d67e7eba4fa495e8f51d660d7b79b4ec6eb7bfc 100644 (file)
@@ -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 (file)
index 0000000..2630660
--- /dev/null
@@ -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 (file)
index 0000000..037c628
--- /dev/null
@@ -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;
+               }
+       }
+       
+}
index 04a464750504a57254a85526314d88ed740f97a2..cd20f3476c50a722f6cf6be3f8ecacc59c0eb6a0 100644 (file)
@@ -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);
index dbe7b0449c7650f5867a9c9dc5a0c7eb7cfa47eb..d326709067c3c9a6c9fd98f1650c60bfa88b511f 100644 (file)
@@ -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");
+               }
        }
 }