diff options
author | aclement <aclement> | 2009-12-10 20:03:37 +0000 |
---|---|---|
committer | aclement <aclement> | 2009-12-10 20:03:37 +0000 |
commit | 1d471f7cfaf166d4321c56b52fe47859e9974441 (patch) | |
tree | 4214e926f363914f4e8475bc9e2ca652bee8d10f /loadtime/testsrc/org/aspectj | |
parent | 95ae07b5aa70a702bac463a7775ec36487936bb9 (diff) | |
download | aspectj-1d471f7cfaf166d4321c56b52fe47859e9974441.tar.gz aspectj-1d471f7cfaf166d4321c56b52fe47859e9974441.zip |
296734: various optimizations for LTW and aop.xml include/exclude processing
Diffstat (limited to 'loadtime/testsrc/org/aspectj')
-rw-r--r-- | loadtime/testsrc/org/aspectj/weaver/loadtime/ClassLoaderWeavingAdaptorTest.java | 456 |
1 files changed, 449 insertions, 7 deletions
diff --git a/loadtime/testsrc/org/aspectj/weaver/loadtime/ClassLoaderWeavingAdaptorTest.java b/loadtime/testsrc/org/aspectj/weaver/loadtime/ClassLoaderWeavingAdaptorTest.java index 805b989a6..58166e20c 100644 --- a/loadtime/testsrc/org/aspectj/weaver/loadtime/ClassLoaderWeavingAdaptorTest.java +++ b/loadtime/testsrc/org/aspectj/weaver/loadtime/ClassLoaderWeavingAdaptorTest.java @@ -10,42 +10,484 @@ *******************************************************************************/ package org.aspectj.weaver.loadtime; +import java.io.File; +import java.lang.reflect.Field; import java.net.URL; import java.net.URLClassLoader; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; import junit.framework.TestCase; +import org.aspectj.apache.bcel.classfile.JavaClass; +import org.aspectj.apache.bcel.util.ClassPath; +import org.aspectj.apache.bcel.util.SyntheticRepository; +import org.aspectj.lang.annotation.Aspect; +import org.aspectj.weaver.World; +import org.aspectj.weaver.World.TypeMap; +import org.aspectj.weaver.bcel.BcelWorld; +import org.aspectj.weaver.loadtime.definition.Definition; +import org.aspectj.weaver.tools.WeavingAdaptor; + public class ClassLoaderWeavingAdaptorTest extends TestCase { public void testClassLoaderWeavingAdaptor() { ClassLoader loader = new URLClassLoader(new URL[] {}, null); ClassLoaderWeavingAdaptor adaptor = new ClassLoaderWeavingAdaptor(); - adaptor.initialize(loader,null); + adaptor.initialize(loader, null); } public void testGetNamespace() { ClassLoader loader = new URLClassLoader(new URL[] {}, null); ClassLoaderWeavingAdaptor adaptor = new ClassLoaderWeavingAdaptor(); - adaptor.initialize(loader,null); + adaptor.initialize(loader, null); String namespace = adaptor.getNamespace(); - assertEquals("Namespace should be empty","",namespace); + assertEquals("Namespace should be empty", "", namespace); } public void testGeneratedClassesExistFor() { ClassLoader loader = new URLClassLoader(new URL[] {}, null); ClassLoaderWeavingAdaptor adaptor = new ClassLoaderWeavingAdaptor(); - adaptor.initialize(loader,null); + adaptor.initialize(loader, null); boolean exist = adaptor.generatedClassesExistFor("Junk"); - assertFalse("There should be no generated classes",exist); + assertFalse("There should be no generated classes", exist); } public void testFlushGeneratedClasses() { ClassLoader loader = new URLClassLoader(new URL[] {}, null); ClassLoaderWeavingAdaptor adaptor = new ClassLoaderWeavingAdaptor(); - adaptor.initialize(loader,null); + adaptor.initialize(loader, null); adaptor.flushGeneratedClasses(); boolean exist = adaptor.generatedClassesExistFor("Junk"); - assertFalse("There should be no generated classes",exist); + assertFalse("There should be no generated classes", exist); + } + + /** + * Testing fast excludes of the pattern "com.foo..*". World should not have any new types in it after rejection. + */ + public void testFastExclusionOne() throws Exception { + TestClassLoaderWeavingAdaptor adaptor = getAdaptor(null, "testdata..*"); + + String orangesSub = "testdata.sub.Oranges"; + JavaClass orangesClass = getClassFrom(orangesSub); + byte[] orangesBytes = orangesClass.getBytes(); + + boolean accepted = adaptor.accept(orangesSub, orangesBytes); + assertFalse("Should not be accepted", accepted); + TypeMap map = accessTypeMap(adaptor); + + // The aspect + assertEquals(1, map.getExpendableMap().size()); + + // primitives, void and jlObject + assertEquals(10, map.getMainMap().size()); + + // Important thing here is that the rejection of testdata.sub.Oranges did not require it to be loaded into the world at all + } + + /** + * Testing fast includes of the pattern "*". World should not have any new types in it after inclusion. + */ + public void testFastInclusionOne() throws Exception { + TestClassLoaderWeavingAdaptor adaptor = getAdaptor("*", null); + + String orangesSub = "testdata.sub.Oranges"; + JavaClass orangesClass = getClassFrom(orangesSub); + byte[] orangesBytes = orangesClass.getBytes(); + + boolean accepted = adaptor.accept(orangesSub, orangesBytes); + assertTrue("Should be accepted", accepted); + TypeMap map = accessTypeMap(adaptor); + + // The aspect + assertEquals(1, map.getExpendableMap().size()); + + // primitives, void and jlObject + assertEquals(10, map.getMainMap().size()); + + // Important thing here is that the rejection of testdata.sub.Oranges did not require it to be loaded into the world at all + } + + /** + * Testing fast excludes of the pattern "*Oranges". World should not have any new types in it after rejection. + */ + public void testFastExclusionTwo() throws Exception { + TestClassLoaderWeavingAdaptor adaptor = getAdaptor(null, "*Oranges"); + + String oranges = "testdata.Oranges"; + JavaClass orangesClass = getClassFrom(oranges); + byte[] orangesBytes = orangesClass.getBytes(); + + boolean accepted = adaptor.accept(oranges, orangesBytes); + assertFalse("Should not be accepted", accepted); + TypeMap map = accessTypeMap(adaptor); + + // The aspect + assertEquals(1, map.getExpendableMap().size()); + // primitives, void and jlObject + assertEquals(10, map.getMainMap().size()); + + String orangesSub = "testdata.sub.Oranges"; + + JavaClass orangesSubClass = getClassFrom(orangesSub); + byte[] orangesSubBytes = orangesSubClass.getBytes(); + + accepted = adaptor.accept(orangesSub, orangesSubBytes); + assertFalse("Should not be accepted", accepted); + map = accessTypeMap(adaptor); + + // The aspect + assertEquals(1, map.getExpendableMap().size()); + // primitives, void and jlObject + assertEquals(10, map.getMainMap().size()); + } + + /** + * Testing fast excludes of the pattern "*..*Oranges*". World should not have any new types in it after rejection. + */ + public void testFastExclusionThree() throws Exception { + TestClassLoaderWeavingAdaptor adaptor = getAdaptor(null, "*..*ran*"); + + String oranges = "testdata.Oranges"; + JavaClass orangesClass = getClassFrom(oranges); + byte[] orangesBytes = orangesClass.getBytes(); + + boolean accepted = adaptor.accept(oranges, orangesBytes); + assertFalse("Should not be accepted", accepted); + TypeMap map = accessTypeMap(adaptor); + + // The aspect + assertEquals(1, map.getExpendableMap().size()); + + // primitives, void and jlObject + assertEquals(10, map.getMainMap().size()); + + String orangesSub = "testdata.sub.Oranges"; + JavaClass orangesSubClass = getClassFrom(orangesSub); + byte[] orangesSubBytes = orangesSubClass.getBytes(); + + accepted = adaptor.accept(orangesSub, orangesSubBytes); + assertFalse("Should not be accepted", accepted); + map = accessTypeMap(adaptor); + + // The aspect + assertEquals(1, map.getExpendableMap().size()); + // primitives, void and jlObject + assertEquals(10, map.getMainMap().size()); + + String apples = "testdata.Apples"; + JavaClass applesClass = getClassFrom(apples); + byte[] applesBytes = applesClass.getBytes(); + + accepted = adaptor.accept(apples, applesBytes); + assertTrue("Should be accepted", accepted); + map = accessTypeMap(adaptor); + + // The aspect and the Apples type + assertEquals(1, map.getExpendableMap().size()); + // primitives, void and jlObject + assertEquals(10, map.getMainMap().size()); + } + + /** + * Testing fast inclusion checking of exact include names eg. "testdata.sub.Oranges" + */ + public void testFastInclusionTwo() throws Exception { + TestClassLoaderWeavingAdaptor adaptor = getAdaptor("testdata.sub.Oranges", null); + + String oranges = "testdata.Oranges"; + JavaClass orangesClass = getClassFrom(oranges); + byte[] orangesBytes = orangesClass.getBytes(); + + boolean accepted = adaptor.accept(oranges, orangesBytes); + assertFalse("Should not be accepted", accepted); + TypeMap map = accessTypeMap(adaptor); + + // The aspect + assertEquals(1, map.getExpendableMap().size()); + + // primitives, void and jlObject + assertEquals(10, map.getMainMap().size()); + + String orangesSub = "testdata.sub.Oranges"; + JavaClass orangesSubClass = getClassFrom(orangesSub); + byte[] orangesSubBytes = orangesSubClass.getBytes(); + + accepted = adaptor.accept(orangesSub, orangesSubBytes); + assertTrue("Should be accepted", accepted); + map = accessTypeMap(adaptor); + + // The aspect + assertEquals(1, map.getExpendableMap().size()); + // primitives, void and jlObject + assertEquals(10, map.getMainMap().size()); + + String apples = "testdata.Apples"; + JavaClass applesClass = getClassFrom(apples); + byte[] applesBytes = applesClass.getBytes(); + + accepted = adaptor.accept(apples, applesBytes); + assertFalse("Should not be accepted", accepted); + map = accessTypeMap(adaptor); + + // The aspect and the Apples type + assertEquals(1, map.getExpendableMap().size()); + // primitives, void and jlObject + assertEquals(10, map.getMainMap().size()); } + /** + * Testing fast excludes of the pattern groovy related pattern - + */ + // public void testFastExclusionFour() throws Exception { + // TestClassLoaderWeavingAdaptor adaptor = getAdaptor("*", "testdata..* && !testdata.sub.Oran*"); + // + // String oranges = "testdata.Oranges"; + // JavaClass orangesClass = getClassFrom(oranges); + // byte[] orangesBytes = orangesClass.getBytes(); + // + // boolean accepted = adaptor.accept(oranges, orangesBytes); + // assertFalse("Should not be accepted", accepted); + // TypeMap map = accessTypeMap(adaptor); + // + // // The aspect + // assertEquals(1, map.getExpendableMap().size()); + // + // // primitives, void and jlObject + // assertEquals(10, map.getMainMap().size()); + // + // String orangesSub = "testdata.sub.Oranges"; + // JavaClass orangesSubClass = getClassFrom(orangesSub); + // byte[] orangesSubBytes = orangesSubClass.getBytes(); + // + // accepted = adaptor.accept(orangesSub, orangesSubBytes); + // assertTrue("Should be accepted", accepted); + // map = accessTypeMap(adaptor); + // + // // The aspect + // assertEquals(1, map.getExpendableMap().size()); + // // primitives, void and jlObject + // assertEquals(10, map.getMainMap().size()); + // } + + public void testAcceptanceSpeedStarDotDotStar() throws Exception { + URLClassLoader loader = new URLClassLoader(new URL[] { new File("../loadtime/bin").toURI().toURL() }, null); + + JavaClass jc = getClassFrom("../loadtime/bin", "org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptorTest$TestOne"); + byte[] bs = jc.getBytes(); + jc = getClassFrom("../loadtime/bin", "org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptorTest$TestOneCGLIB"); + byte[] bs2 = jc.getBytes(); + // InputStream is = loader.getResourceAsStream("org.aspectj.weaver.loadtime.ClassLoaderWeaverAdaptorTests$TestOne"); + assertNotNull(bs); + TestWeavingContext wc = new TestWeavingContext(loader); + Definition d = new Definition(); + d.getExcludePatterns().add("*..*CGLIB*"); + d.getAspectClassNames().add("org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptorTest$AnAspect"); + wc.addDefinition(d); + ClassLoaderWeavingAdaptor adaptor = new ClassLoaderWeavingAdaptor(); + adaptor.initialize(loader, wc); + boolean exist = adaptor.generatedClassesExistFor("Junk"); + assertFalse("There should be no generated classes", exist); + + // before: + // Acceptance 331ms + // Rejection 3368ms + + // after: + // Acceptance 343ms + // Rejection 80ms + + long stime = System.currentTimeMillis(); + for (int i = 0; i < 100000; i++) { + boolean b = adaptor.accept("org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptorTest$TestOne", bs); + assertTrue("Should be accepted", b); + } + long etime = System.currentTimeMillis(); + System.out.println("Acceptance " + (etime - stime) + "ms"); + stime = System.currentTimeMillis(); + for (int i = 0; i < 100000; i++) { + adaptor.delegateForCurrentClass = null; + boolean b = adaptor.accept("org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptorTest$TestOneCGLIB", bs2); + assertFalse("Should not be accepting CGLIB", b); + } + etime = System.currentTimeMillis(); + System.out.println("Rejection " + (etime - stime) + "ms"); + + } + + // TODO + // shouldn't add it to the type patterns if we are going to fast handle it + // include for exact name, what does it mean? + // excludes="!xxxx" should also be fast matched... + + public void testAcceptanceSpeedExactName() throws Exception { + URLClassLoader loader = new URLClassLoader(new URL[] { new File("../loadtime/bin").toURI().toURL() }, null); + + JavaClass jc = getClassFrom("../loadtime/bin", "org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptorTest$TestOne"); + byte[] bs = jc.getBytes(); + jc = getClassFrom("../loadtime/bin", "org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptorTest$TestOneCGLIB"); + byte[] bs2 = jc.getBytes(); + // InputStream is = loader.getResourceAsStream("org.aspectj.weaver.loadtime.ClassLoaderWeaverAdaptorTests$TestOne"); + assertNotNull(bs); + TestWeavingContext wc = new TestWeavingContext(loader); + Definition d = new Definition(); + d.getExcludePatterns().add("org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptorTest.TestOneCGLIB"); + d.getAspectClassNames().add("org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptorTest$AnAspect"); + wc.addDefinition(d); + TestClassLoaderWeavingAdaptor adaptor = new TestClassLoaderWeavingAdaptor(); + adaptor.initialize(loader, wc); + boolean exist = adaptor.generatedClassesExistFor("Junk"); + assertFalse("There should be no generated classes", exist); + + // before: + // Acceptance 331ms + // Rejection 3160ms + + // after: + // Acceptance 379ms + // Rejection 103ms + + long stime = System.currentTimeMillis(); + for (int i = 0; i < 100000; i++) { + boolean b = adaptor.accept("org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptorTest$TestOne", bs); + assertTrue("Should be accepted", b); + } + long etime = System.currentTimeMillis(); + System.out.println("Acceptance " + (etime - stime) + "ms"); + stime = System.currentTimeMillis(); + for (int i = 0; i < 100000; i++) { + adaptor.delegateForCurrentClass = null; + boolean b = adaptor.accept("org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptorTest$TestOneCGLIB", bs2); + assertFalse("Should not be accepting CGLIB", b); + } + etime = System.currentTimeMillis(); + System.out.println("Rejection " + (etime - stime) + "ms"); + BcelWorld world = adaptor.getWorld(); + Field f = World.class.getDeclaredField("typeMap"); + f.setAccessible(true); + TypeMap typeMap = (TypeMap) f.get(world); + System.out.println(typeMap.getExpendableMap().size()); + System.out.println(typeMap.getMainMap().size()); + printExpendableMap(typeMap.getExpendableMap()); + printMainMap(typeMap.getMainMap()); + } + + // --- infrastructure --- + + private TypeMap accessTypeMap(TestClassLoaderWeavingAdaptor adaptor) { + try { + BcelWorld world = adaptor.getWorld(); + Field f = World.class.getDeclaredField("typeMap"); + f.setAccessible(true); + TypeMap typeMap = (TypeMap) f.get(world); + return typeMap; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public TestClassLoaderWeavingAdaptor getAdaptor(String includePattern, String excludePattern) { + return getAdaptor(includePattern == null ? null : new String[] { includePattern }, excludePattern == null ? null + : new String[] { excludePattern }); + } + + public TestClassLoaderWeavingAdaptor getAdaptor(String[] includePatterns, String[] excludePatterns) { + try { + URLClassLoader loader = new URLClassLoader(new URL[] { new File("../loadtime/bin").toURI().toURL() }, null); + TestWeavingContext wc = new TestWeavingContext(loader); + Definition d = new Definition(); + if (includePatterns != null) { + for (String s : includePatterns) { + d.getIncludePatterns().add(s); + } + } + if (excludePatterns != null) { + for (String s : excludePatterns) { + d.getExcludePatterns().add(s); + } + } + // need some random aspect or the weaver will shut down! + d.getAspectClassNames().add("org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptorTest$AnAspect"); + wc.addDefinition(d); + TestClassLoaderWeavingAdaptor adaptor = new TestClassLoaderWeavingAdaptor(); + adaptor.initialize(loader, wc); + return adaptor; + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + private void printMaps(TypeMap map) { + printExpendableMap(map.getExpendableMap()); + printMainMap(map.getMainMap()); + } + + private void printExpendableMap(Map m) { + for (Object o : m.keySet()) { + String sig = (String) o; + System.out.println(sig + "=" + m.get(sig)); + } + } + + private void printMainMap(Map m) { + for (Object o : m.keySet()) { + String sig = (String) o; + System.out.println(sig + "=" + m.get(sig)); + } + } + + static class TestClassLoaderWeavingAdaptor extends ClassLoaderWeavingAdaptor { + + public BcelWorld getWorld() { + return bcelWorld; + } + } + + public static JavaClass getClassFrom(String clazzname) throws ClassNotFoundException { + return getClassFrom("../loadtime/bin", clazzname); + } + + public static JavaClass getClassFrom(String frompath, String clazzname) throws ClassNotFoundException { + SyntheticRepository repos = createRepos(frompath); + return repos.loadClass(clazzname); + } + + public static SyntheticRepository createRepos(String cpentry) { + ClassPath cp = new ClassPath(cpentry + File.pathSeparator + System.getProperty("java.class.path")); + return SyntheticRepository.getInstance(cp); + } + + @Aspect + class AnAspect { + + } + + class TestOne { + + } + + class TestOneCGLIB { + + } + + static class TestWeavingContext extends DefaultWeavingContext { + + List testList = new ArrayList(); + + public TestWeavingContext(ClassLoader loader) { + super(loader); + } + + public void addDefinition(Definition d) { + testList.add(d); + } + + @Override + public List getDefinitions(final ClassLoader loader, final WeavingAdaptor adaptor) { + return testList; + } + } } + +// --- testclasses and aspects ---
\ No newline at end of file |