diff options
author | aclement <aclement> | 2010-01-21 18:39:53 +0000 |
---|---|---|
committer | aclement <aclement> | 2010-01-21 18:39:53 +0000 |
commit | f91ffb032fae7c7d9f59f4aedf27f067ba60919e (patch) | |
tree | df21f06a213e08536473f9b1e21542909c28d0a3 | |
parent | f7591e67250f1e6717bbebb23b5bb9c47fb05204 (diff) | |
download | aspectj-f91ffb032fae7c7d9f59f4aedf27f067ba60919e.tar.gz aspectj-f91ffb032fae7c7d9f59f4aedf27f067ba60919e.zip |
299552: private ITD fields stay private in target (with unmangled name)
16 files changed, 510 insertions, 0 deletions
diff --git a/tests/features169/transparent/DeclareAtTwo.java b/tests/features169/transparent/DeclareAtTwo.java new file mode 100644 index 000000000..57c321afe --- /dev/null +++ b/tests/features169/transparent/DeclareAtTwo.java @@ -0,0 +1,17 @@ +import java.lang.annotation.*; + +public class DeclareAtTwo { +} + +aspect X { + declare @field: int DeclareAtTwo.x: @Anno2; + + @Anno + private int DeclareAtTwo.x; +} + +@Retention(RetentionPolicy.RUNTIME) +@interface Anno {} + +@Retention(RetentionPolicy.RUNTIME) +@interface Anno2 {} diff --git a/tests/features169/transparent/Generics.java b/tests/features169/transparent/Generics.java new file mode 100644 index 000000000..c1cc12614 --- /dev/null +++ b/tests/features169/transparent/Generics.java @@ -0,0 +1,37 @@ +import java.util.*; + +public class Generics<X> { + public static void main(String []argv) { + Generics<String> inst = new Generics<String>(); + List<String> ls = new ArrayList<String>(); + inst.setter(ls); + List<String> newls = inst.getter(); + + inst.setThing("abc"); + String s = inst.getThing(); + } +} + +aspect X { + private List<String> Generics.listOfString; + + public List<String> Generics.getter() { + return listOfString; + } + + public void Generics.setter(List<String> los) { + listOfString = los; + } +} + +aspect Y { + private T Generics<T>.thing; + + public T Generics<T>.getThing() { + return thing; + } + + public void Generics<T>.setThing(T thing) { + this.thing = thing; + } +} diff --git a/tests/features169/transparent/InteractingOldAndNew.java b/tests/features169/transparent/InteractingOldAndNew.java new file mode 100644 index 000000000..387b21d55 --- /dev/null +++ b/tests/features169/transparent/InteractingOldAndNew.java @@ -0,0 +1,38 @@ +// Interacting private ITDs + +public class InteractingOldAndNew { + public static void main(String []argv) { + InteractingOldAndNew inst = new InteractingOldAndNew(); + inst.setI1(12); + inst.setI2(65); + int value = inst.getI1(); + if (value!=12) { throw new RuntimeException(Integer.toString(value)); } + value = inst.getI2(); + if (value!=65) { throw new RuntimeException(Integer.toString(value)); } + } +} + + +aspect X { + private int InteractingOldAndNew.i; + + public int InteractingOldAndNew.getI1() { + return i; + } + + public void InteractingOldAndNew.setI1(int newvalue) { + i = newvalue; + } +} + +aspect Y { + private int InteractingOldAndNew.i; + + public int InteractingOldAndNew.getI2() { + return i; + } + + public void InteractingOldAndNew.setI2(int newvalue) { + i = newvalue; + } +} diff --git a/tests/features169/transparent/OneDeclareAt.java b/tests/features169/transparent/OneDeclareAt.java new file mode 100644 index 000000000..3daa279d4 --- /dev/null +++ b/tests/features169/transparent/OneDeclareAt.java @@ -0,0 +1,13 @@ +import java.lang.annotation.*; + +public class OneDeclareAt { +} + +aspect X { + declare @field: int OneDeclareAt.x: @Anno; + + private int OneDeclareAt.x; +} + +@Retention(RetentionPolicy.RUNTIME) +@interface Anno {} diff --git a/tests/features169/transparent/OneDefault.java b/tests/features169/transparent/OneDefault.java new file mode 100644 index 000000000..b05375681 --- /dev/null +++ b/tests/features169/transparent/OneDefault.java @@ -0,0 +1,6 @@ +public class OneDefault { +} + +aspect X { + int OneDefault.x; +} diff --git a/tests/features169/transparent/OneDefaultAnnotated.java b/tests/features169/transparent/OneDefaultAnnotated.java new file mode 100644 index 000000000..3b603f9ee --- /dev/null +++ b/tests/features169/transparent/OneDefaultAnnotated.java @@ -0,0 +1,12 @@ +import java.lang.annotation.*; + +public class OneDefaultAnnotated { +} + +aspect X { + @Anno + int OneDefaultAnnotated.x; +} + +@Retention(RetentionPolicy.RUNTIME) +@interface Anno {} diff --git a/tests/features169/transparent/OnePrivate.java b/tests/features169/transparent/OnePrivate.java new file mode 100644 index 000000000..a0de744c7 --- /dev/null +++ b/tests/features169/transparent/OnePrivate.java @@ -0,0 +1,6 @@ +public class OnePrivate { +} + +aspect X { + private int OnePrivate.x; +} diff --git a/tests/features169/transparent/OnePrivateAccessors.java b/tests/features169/transparent/OnePrivateAccessors.java new file mode 100644 index 000000000..07bfbc98c --- /dev/null +++ b/tests/features169/transparent/OnePrivateAccessors.java @@ -0,0 +1,21 @@ +import java.lang.annotation.*; + +public class OnePrivateAccessors { + public static void main(String[] argv) { + int i = new OnePrivateAccessors().run(); + if (i!=37) throw new RuntimeException(Integer.toString(i)); + } +} + +aspect X { + @Anno + private int OnePrivateAccessors.x; + + public int OnePrivateAccessors.run() { + x = 37; + return x; + } +} + +@Retention(RetentionPolicy.RUNTIME) +@interface Anno {} diff --git a/tests/features169/transparent/OnePrivateAnnotated.java b/tests/features169/transparent/OnePrivateAnnotated.java new file mode 100644 index 000000000..c5e4e798d --- /dev/null +++ b/tests/features169/transparent/OnePrivateAnnotated.java @@ -0,0 +1,12 @@ +import java.lang.annotation.*; + +public class OnePrivateAnnotated { +} + +aspect X { + @Anno + private int OnePrivateAnnotated.x; +} + +@Retention(RetentionPolicy.RUNTIME) +@interface Anno {} diff --git a/tests/features169/transparent/OnePrivateInitializer.java b/tests/features169/transparent/OnePrivateInitializer.java new file mode 100644 index 000000000..33d9822af --- /dev/null +++ b/tests/features169/transparent/OnePrivateInitializer.java @@ -0,0 +1,16 @@ +import java.lang.annotation.*; + +public class OnePrivateInitializer { + public static void main(String[] argv) { + int i = new OnePrivateInitializer().run(); + if (i!=42) throw new RuntimeException(Integer.toString(i)); + } +} + +aspect X { + private int OnePrivateInitializer.x = 42; + + public int OnePrivateInitializer.run() { + return x; + } +} diff --git a/tests/features169/transparent/Three.java b/tests/features169/transparent/Three.java new file mode 100644 index 000000000..f288ce35b --- /dev/null +++ b/tests/features169/transparent/Three.java @@ -0,0 +1,7 @@ +public class Three { + private int x; +} + +aspect X { + private int Three.x; +} diff --git a/tests/features169/transparent/Two.java b/tests/features169/transparent/Two.java new file mode 100644 index 000000000..c01cdd74a --- /dev/null +++ b/tests/features169/transparent/Two.java @@ -0,0 +1,7 @@ +public class Two { + public int x; +} + +aspect X { + public int Two.x; +} diff --git a/tests/features169/transparent/TwoItdsOnTarget.java b/tests/features169/transparent/TwoItdsOnTarget.java new file mode 100644 index 000000000..d83a15210 --- /dev/null +++ b/tests/features169/transparent/TwoItdsOnTarget.java @@ -0,0 +1,10 @@ +public class TwoItdsOnTarget { +} + +aspect X { + private int TwoItdsOnTarget.x; +} + +aspect Y { + private int TwoItdsOnTarget.x; +} diff --git a/tests/features169/transparent/TwoItdsOnTargetHasAlready.java b/tests/features169/transparent/TwoItdsOnTargetHasAlready.java new file mode 100644 index 000000000..f26dbcd6d --- /dev/null +++ b/tests/features169/transparent/TwoItdsOnTargetHasAlready.java @@ -0,0 +1,11 @@ +public class TwoItdsOnTargetHasAlready { + private int x; +} + +aspect X { + private int TwoItdsOnTargetHasAlready.x; +} + +aspect Y { + private int TwoItdsOnTargetHasAlready.x; +} diff --git a/tests/src/org/aspectj/systemtest/ajc169/TransparentWeavingTests.java b/tests/src/org/aspectj/systemtest/ajc169/TransparentWeavingTests.java new file mode 100644 index 000000000..5086c0ead --- /dev/null +++ b/tests/src/org/aspectj/systemtest/ajc169/TransparentWeavingTests.java @@ -0,0 +1,229 @@ +/******************************************************************************* + * Copyright (c) 2008 Contributors + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Andy Clement - initial API and implementation + *******************************************************************************/ +package org.aspectj.systemtest.ajc169; + +import java.io.File; +import org.aspectj.apache.bcel.classfile.Method; +import java.lang.reflect.Modifier; + +import junit.framework.Test; + +import org.aspectj.apache.bcel.classfile.Field; +import org.aspectj.apache.bcel.classfile.JavaClass; +import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen; +import org.aspectj.apache.bcel.util.ClassPath; +import org.aspectj.apache.bcel.util.SyntheticRepository; +import org.aspectj.testing.XMLBasedAjcTestCase; + +/** + * What would a completely transparent weave be? Is there a minimal subset that makes sense? What is the roadmap to get there? What + * needs testing + * + * --- 'Transparent' here is meaning that the resultant bytecode is more representative of the original declarations, so that it + * looks like the intertype declaration and associated constructs have been seamless added to the affected targets. + * + * + * Fully transparent weaving, what would we like to have: - ITDs appear exactly as declared: 'private int A.i' will create 'private + * int i' in A + * + * - What is the benefit? - although this isn't really in keeping with the AspectJ definition of what an ITD represents, having the + * end result look like the declaration does make it easier for users simply looking at the resultant class file or attempting + * reflection to access what they just ITD'd in place + * + * + * testing For transparent weaving of ITD fields - annotations on new fields - AJDT model - AjType support - what happens to it? - + * advice on within() how does that get affected? - visibility - accessors created when required? - handling clashes with existing + * fields - handling clashes with other aspects - generic declarations - interface declarations - initializers - static and + * non-static - accessibility from advice, for read and write + * + * Design<br> + * The intention will be 'new code' uses the new style whilst old code continues to cause the old code to be built. Whether the code + * wants to use the old or new naming should be apparent from the + * + * @author Andy Clement + */ +public class TransparentWeavingTests extends org.aspectj.testing.XMLBasedAjcTestCase { + + // Simple private ITD onto a target + public void testSimplePrivate() throws Exception { + runTest("one - private"); + checkForField("OnePrivate", Modifier.PRIVATE, "x"); + } + + // Default visibility ITD field + public void testSimpleDefault() throws Exception { + runTest("one - default"); + checkForField("OneDefault", 0, "x"); + } + + // annotated private ITD + public void testSimplePrivateAnnotated() throws Exception { + runTest("one - private - annotated"); + Field f = checkForField("OnePrivateAnnotated", Modifier.PRIVATE, "x"); + AnnotationGen[] annos = f.getAnnotations(); + assertTrue(annos.length > 0); // 0==Anno 1==ajcITD + assertEquals("LAnno;", annos[0].getTypeSignature()); + } + + // annotated default ITD + public void testSimpleDefaultAnnotated() throws Exception { + runTest("one - default - annotated"); + Field f = checkForField("OneDefaultAnnotated", 0, "x"); + AnnotationGen[] annos = f.getAnnotations(); + assertTrue(annos.length > 0); // 0==Anno 1==ajcITD + assertEquals("LAnno;", annos[0].getTypeSignature()); + } + + // Simple private ITD with getter/setter usage + public void testSimplePrivateWithAccessors() throws Exception { + runTest("one - private - accessors"); + } + + // check initializer runs OK + public void testSimplePrivateInitializer() throws Exception { + runTest("one - private - initializer"); + } + + public void testDeclareAtOnPrivateItd() throws Exception { + runTest("declare at on private itd"); + Field f = checkForField("OneDeclareAt", Modifier.PRIVATE, "x"); + AnnotationGen[] annos = f.getAnnotations(); + assertTrue(annos.length > 0); // 1==Anno 0==ajcITD + assertEquals("LAnno;", annos[1].getTypeSignature()); + } + + // declare @field on a field that already has one + public void testDeclareAtTwo() throws Exception { + runTest("declare at two"); + Field f = checkForField("DeclareAtTwo", Modifier.PRIVATE, "x"); + AnnotationGen[] annos = f.getAnnotations(); + assertTrue(annos.length > 2); // 1==Anno 0==ajcITD + assertEquals("LAnno;", annos[0].getTypeSignature()); + assertEquals("LAnno2;", annos[2].getTypeSignature()); + } + + public void testTwoItdsOnTarget() throws Exception { + runTest("two itds on target"); + // Aspect X gets the field, aspect Y gets a mangled one + checkForField("TwoItdsOnTarget", Modifier.PRIVATE, "x"); + checkForField("TwoItdsOnTarget", Modifier.PUBLIC, "ajc$interField$Y$x"); + } + + public void testTwoItdsOnTargetThatAlreadyHasIt() throws Exception { + runTest("two itds on target that already has it"); + // Aspect X gets the field, aspect Y gets a mangled one + checkForField("TwoItdsOnTargetHasAlready", Modifier.PUBLIC, "ajc$interField$X$x"); + checkForField("TwoItdsOnTargetHasAlready", Modifier.PUBLIC, "ajc$interField$Y$x"); + } + + public void testInteractingOldAndNew() throws Exception { + runTest("interacting old and new"); + int SYNTHETIC = 0x00001000; // 4096 + checkForField("InteractingOldAndNew", Modifier.PRIVATE, "i"); + checkForField("InteractingOldAndNew", Modifier.PUBLIC, "ajc$interField$Y$i"); + checkForMethod("InteractingOldAndNew", Modifier.PUBLIC | Modifier.STATIC, "main"); + checkForMethod("InteractingOldAndNew", Modifier.PUBLIC | Modifier.STATIC | SYNTHETIC, "ajc$get$i"); + checkForMethod("InteractingOldAndNew", Modifier.PUBLIC | Modifier.STATIC | SYNTHETIC, "ajc$set$i"); + checkForMethod("InteractingOldAndNew", Modifier.PUBLIC, "getI1"); + checkForMethod("InteractingOldAndNew", Modifier.PUBLIC, "getI2"); + checkForMethod("InteractingOldAndNew", Modifier.PUBLIC, "setI1"); + checkForMethod("InteractingOldAndNew", Modifier.PUBLIC, "setI2"); + } + + public void testPrivateGenerics() throws Exception { + runTest("generics - private"); + Field f = checkForField("Generics", Modifier.PRIVATE, "listOfString"); + assertEquals("Ljava/util/List<Ljava/lang/String;>;", f.getGenericSignature()); + f = checkForField("Generics", Modifier.PRIVATE, "thing"); + assertEquals("TX;", f.getGenericSignature()); + } + + // --- + + private Field checkForField(String clazzname, int modifiers, String name) throws Exception { + JavaClass jc = getClassFrom(ajc.getSandboxDirectory(), clazzname); + Field[] fs = jc.getFields(); + StringBuffer fields = new StringBuffer(); + for (Field f : fs) { + fields.append(f.getName()).append(" "); + if (f.getName().equals(name)) { + if (f.getModifiers() != modifiers) { + fail("Found field " + name + " in " + clazzname + " but modifiers were wrong, they were " + f.getModifiers()); + } + return f; + } + } + fail("Did not find field " + name + " in class " + clazzname + ". Found fields: " + fields.toString()); + return null; + } + + private Method checkForMethod(String clazzname, int modifiers, String name) throws Exception { + JavaClass jc = getClassFrom(ajc.getSandboxDirectory(), clazzname); + Method[] fs = jc.getMethods(); + StringBuffer methods = new StringBuffer(); + methods.append("\n"); + for (Method f : fs) { + methods.append(f.getName()).append("\n"); + if (f.getName().equals(name)) { + if (f.getModifiers() != modifiers) { + fail("Found method " + name + " in " + clazzname + " but modifiers were wrong, they were " + f.getModifiers()); + } + return f; + } + System.out.println(f.getGenericSignature()); + } + fail("Did not find method " + name + " in class " + clazzname + ". Found methods: " + methods.toString()); + return null; + } + + // public itd onto a target that already has a field of that name + // just to check what goes wrong and who checks it + public void testPublicClash() throws Exception { + runTest("two"); + } + + public void testPrivateClash() throws Exception { + runTest("three"); + + JavaClass jc = getClassFrom(ajc.getSandboxDirectory(), "Three"); + Field[] fs = jc.getFields(); + for (Field f : fs) { + System.out.println(f); + } + + // public int ajc$interField$X$xPrivate [RuntimeVisibleAnnotations] + // public Integer ajc$interField$$yDefault [RuntimeVisibleAnnotations] + // public String zPublic [RuntimeVisibleAnnotations] + + } + + // -- + + public SyntheticRepository createRepos(File cpentry) { + ClassPath cp = new ClassPath(cpentry + File.pathSeparator + System.getProperty("java.class.path")); + return SyntheticRepository.getInstance(cp); + } + + protected JavaClass getClassFrom(File where, String clazzname) throws ClassNotFoundException { + SyntheticRepository repos = createRepos(where); + return repos.loadClass(clazzname); + } + + public static Test suite() { + return XMLBasedAjcTestCase.loadSuite(TransparentWeavingTests.class); + } + + @Override + protected File getSpecFile() { + return new File("../tests/src/org/aspectj/systemtest/ajc169/transparentweaving.xml"); + } + +}
\ No newline at end of file diff --git a/tests/src/org/aspectj/systemtest/ajc169/transparentweaving.xml b/tests/src/org/aspectj/systemtest/ajc169/transparentweaving.xml new file mode 100644 index 000000000..10351bdc4 --- /dev/null +++ b/tests/src/org/aspectj/systemtest/ajc169/transparentweaving.xml @@ -0,0 +1,68 @@ +<!DOCTYPE suite SYSTEM "../tests/ajcTestSuite.dtd"[]> + +<suite> + + <ajc-test dir="features169/transparent" title="one - private"> + <compile files="OnePrivate.java" options="-1.5"/> + </ajc-test> + + <ajc-test dir="features169/transparent" title="one - default"> + <compile files="OneDefault.java" options="-1.5"/> + </ajc-test> + + <ajc-test dir="features169/transparent" title="one - private - annotated"> + <compile files="OnePrivateAnnotated.java" options="-1.5"/> + </ajc-test> + + <ajc-test dir="features169/transparent" title="one - default - annotated"> + <compile files="OneDefaultAnnotated.java" options="-1.5"/> + </ajc-test> + + <ajc-test dir="features169/transparent" title="one - private - accessors"> + <compile files="OnePrivateAccessors.java" options="-1.5"/> + <run class="OnePrivateAccessors"/> + </ajc-test> + + <ajc-test dir="features169/transparent" title="interacting old and new"> + <compile files="InteractingOldAndNew.java" options="-1.5"/> + <run class="InteractingOldAndNew"/> + </ajc-test> + + <ajc-test dir="features169/transparent" title="one - private - initializer"> + <compile files="OnePrivateInitializer.java" options="-1.5"/> + <run class="OnePrivateInitializer"/> + </ajc-test> + + <ajc-test dir="features169/transparent" title="two"> + <compile files="Two.java" options="-1.5"> + <message kind="error" text="inter-type declaration from X conflicts with existing member: int Two.x"/> + </compile> + </ajc-test> + + <ajc-test dir="features169/transparent" title="two itds on target"> + <compile files="TwoItdsOnTarget.java" options="-1.5"/> + </ajc-test> + + <ajc-test dir="features169/transparent" title="two itds on target that already has it"> + <compile files="TwoItdsOnTargetHasAlready.java" options="-1.5"/> + </ajc-test> + + <ajc-test dir="features169/transparent" title="declare at on private itd"> + <compile files="OneDeclareAt.java" options="-1.5"/> + </ajc-test> + + <ajc-test dir="features169/transparent" title="declare at two"> + <compile files="DeclareAtTwo.java" options="-1.5"/> + </ajc-test> + + <ajc-test dir="features169/transparent" title="three"> + <compile files="Three.java" options="-1.5"/> + </ajc-test> + + <ajc-test dir="features169/transparent" title="generics - private"> + <compile files="Generics.java" options="-1.5"/> + <run class="Generics"/> + </ajc-test> + + +</suite>
\ No newline at end of file |