Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

TransparentWeavingTests.java 9.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  1. /*******************************************************************************
  2. * Copyright (c) 2008 Contributors
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Eclipse Public License v1.0
  5. * which accompanies this distribution, and is available at
  6. * http://www.eclipse.org/legal/epl-v10.html
  7. *
  8. * Contributors:
  9. * Andy Clement - initial API and implementation
  10. *******************************************************************************/
  11. package org.aspectj.systemtest.ajc169;
  12. import java.io.File;
  13. import java.lang.reflect.Modifier;
  14. import junit.framework.Test;
  15. import org.aspectj.apache.bcel.classfile.Field;
  16. import org.aspectj.apache.bcel.classfile.JavaClass;
  17. import org.aspectj.apache.bcel.classfile.Method;
  18. import org.aspectj.apache.bcel.classfile.annotation.AnnotationGen;
  19. import org.aspectj.testing.XMLBasedAjcTestCase;
  20. /**
  21. * What would a completely transparent weave be? Is there a minimal subset that makes sense? What is the roadmap to get there? What
  22. * needs testing
  23. *
  24. * --- 'Transparent' here is meaning that the resultant bytecode is more representative of the original declarations, so that it
  25. * looks like the intertype declaration and associated constructs have been seamless added to the affected targets.
  26. *
  27. *
  28. * Fully transparent weaving, what would we like to have: - ITDs appear exactly as declared: 'private int A.i' will create 'private
  29. * int i' in A
  30. *
  31. * - What is the benefit? - although this isn't really in keeping with the AspectJ definition of what an ITD represents, having the
  32. * end result look like the declaration does make it easier for users simply looking at the resultant class file or attempting
  33. * reflection to access what they just ITD'd in place
  34. *
  35. *
  36. * testing For transparent weaving of ITD fields - annotations on new fields - AJDT model - AjType support - what happens to it? -
  37. * advice on within() how does that get affected? - visibility - accessors created when required? - handling clashes with existing
  38. * fields - handling clashes with other aspects - generic declarations - interface declarations - initializers - static and
  39. * non-static - accessibility from advice, for read and write
  40. *
  41. * Design<br>
  42. * 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
  43. * wants to use the old or new naming should be apparent from the
  44. *
  45. * @author Andy Clement
  46. */
  47. public class TransparentWeavingTests extends org.aspectj.testing.XMLBasedAjcTestCase {
  48. // Simple private ITD onto a target
  49. public void testSimplePrivate() throws Exception {
  50. runTest("one - private");
  51. checkForField("OnePrivate", Modifier.PRIVATE, "x");
  52. }
  53. // Default visibility ITD field
  54. public void testSimpleDefault() throws Exception {
  55. runTest("one - default");
  56. checkForField("OneDefault", 0, "x");
  57. }
  58. // annotated private ITD
  59. public void testSimplePrivateAnnotated() throws Exception {
  60. runTest("one - private - annotated");
  61. Field f = checkForField("OnePrivateAnnotated", Modifier.PRIVATE, "x");
  62. AnnotationGen[] annos = f.getAnnotations();
  63. assertTrue(annos.length > 0); // 0==Anno 1==ajcITD
  64. assertEquals("LAnno;", annos[0].getTypeSignature());
  65. }
  66. // annotated default ITD
  67. public void testSimpleDefaultAnnotated() throws Exception {
  68. runTest("one - default - annotated");
  69. Field f = checkForField("OneDefaultAnnotated", 0, "x");
  70. AnnotationGen[] annos = f.getAnnotations();
  71. assertTrue(annos.length > 0); // 0==Anno 1==ajcITD
  72. assertEquals("LAnno;", annos[0].getTypeSignature());
  73. }
  74. // Simple private ITD with getter/setter usage
  75. public void testSimplePrivateWithAccessors() throws Exception {
  76. runTest("one - private - accessors");
  77. }
  78. // check initializer runs OK
  79. public void testSimplePrivateInitializer() throws Exception {
  80. runTest("one - private - initializer");
  81. }
  82. public void testDeclareAtOnPrivateItd() throws Exception {
  83. runTest("declare at on private itd");
  84. Field f = checkForField("OneDeclareAt", Modifier.PRIVATE, "x");
  85. AnnotationGen[] annos = f.getAnnotations();
  86. assertTrue(annos.length > 0); // 1==Anno 0==ajcITD
  87. assertEquals("LAnno;", annos[1].getTypeSignature());
  88. }
  89. // declare @field on a field that already has one
  90. public void testDeclareAtTwo() throws Exception {
  91. runTest("declare at two");
  92. Field f = checkForField("DeclareAtTwo", Modifier.PRIVATE, "x");
  93. AnnotationGen[] annos = f.getAnnotations();
  94. assertTrue(annos.length > 2); // 1==Anno 0==ajcITD
  95. assertEquals("LAnno;", annos[0].getTypeSignature());
  96. assertEquals("LAnno2;", annos[2].getTypeSignature());
  97. }
  98. public void testTwoItdsOnTarget() throws Exception {
  99. runTest("two itds on target");
  100. // Aspect X gets the field, aspect Y gets a mangled one
  101. if (hasField("TwoItdsOnTarget", "ajc$interField$Y$x")) {
  102. checkForField("TwoItdsOnTarget", Modifier.PRIVATE, "x");
  103. checkForField("TwoItdsOnTarget", Modifier.PUBLIC, "ajc$interField$Y$x");
  104. } else {
  105. checkForField("TwoItdsOnTarget", Modifier.PRIVATE, "x");
  106. checkForField("TwoItdsOnTarget", Modifier.PUBLIC, "ajc$interField$X$x");
  107. }
  108. }
  109. public void testTwoItdsOnTargetThatAlreadyHasIt() throws Exception {
  110. runTest("two itds on target that already has it");
  111. // Aspect X gets the field, aspect Y gets a mangled one
  112. checkForField("TwoItdsOnTargetHasAlready", Modifier.PUBLIC, "ajc$interField$X$x");
  113. checkForField("TwoItdsOnTargetHasAlready", Modifier.PUBLIC, "ajc$interField$Y$x");
  114. }
  115. public void testInteractingOldAndNew() throws Exception {
  116. runTest("interacting old and new");
  117. int SYNTHETIC = 0x00001000; // 4096
  118. if (hasField("InteractingOldAndNew", "ajc$interField$Y$i")) {
  119. checkForField("InteractingOldAndNew", Modifier.PRIVATE, "i");
  120. checkForField("InteractingOldAndNew", Modifier.PUBLIC, "ajc$interField$Y$i");
  121. } else {
  122. checkForField("InteractingOldAndNew", Modifier.PRIVATE, "i");
  123. checkForField("InteractingOldAndNew", Modifier.PUBLIC, "ajc$interField$X$i");
  124. }
  125. checkForMethod("InteractingOldAndNew", Modifier.PUBLIC | Modifier.STATIC, "main");
  126. checkForMethod("InteractingOldAndNew", Modifier.PUBLIC | Modifier.STATIC | SYNTHETIC, "ajc$get$i");
  127. checkForMethod("InteractingOldAndNew", Modifier.PUBLIC | Modifier.STATIC | SYNTHETIC, "ajc$set$i");
  128. checkForMethod("InteractingOldAndNew", Modifier.PUBLIC, "getI1");
  129. checkForMethod("InteractingOldAndNew", Modifier.PUBLIC, "getI2");
  130. checkForMethod("InteractingOldAndNew", Modifier.PUBLIC, "setI1");
  131. checkForMethod("InteractingOldAndNew", Modifier.PUBLIC, "setI2");
  132. }
  133. public void testPrivateGenerics() throws Exception {
  134. runTest("generics - private");
  135. Field f = checkForField("Generics", Modifier.PRIVATE, "listOfString");
  136. assertEquals("Ljava/util/List<Ljava/lang/String;>;", f.getGenericSignature());
  137. f = checkForField("Generics", Modifier.PRIVATE, "thing");
  138. assertEquals("TX;", f.getGenericSignature());
  139. }
  140. // ---
  141. private boolean hasField(String clazzname, String name) {
  142. try {
  143. JavaClass jc = getClassFrom(ajc.getSandboxDirectory(), clazzname);
  144. Field[] fs = jc.getFields();
  145. StringBuffer fields = new StringBuffer();
  146. for (Field f : fs) {
  147. fields.append(f.getName()).append(" ");
  148. if (f.getName().equals(name)) {
  149. return true;
  150. }
  151. }
  152. } catch (Exception e) {
  153. return false;
  154. }
  155. return false;
  156. }
  157. private Field checkForField(String clazzname, int modifiers, String name) throws Exception {
  158. JavaClass jc = getClassFrom(ajc.getSandboxDirectory(), clazzname);
  159. Field[] fs = jc.getFields();
  160. StringBuffer fields = new StringBuffer();
  161. for (Field f : fs) {
  162. fields.append(f.getName()).append(" ");
  163. if (f.getName().equals(name)) {
  164. if (f.getModifiers() != modifiers) {
  165. fail("Found field " + name + " in " + clazzname + " but modifiers were wrong, they were " + f.getModifiers());
  166. }
  167. return f;
  168. }
  169. }
  170. fail("Did not find field " + name + " in class " + clazzname + ". Found fields: " + fields.toString());
  171. return null;
  172. }
  173. private Method checkForMethod(String clazzname, int modifiers, String name) throws Exception {
  174. JavaClass jc = getClassFrom(ajc.getSandboxDirectory(), clazzname);
  175. Method[] fs = jc.getMethods();
  176. StringBuffer methods = new StringBuffer();
  177. methods.append("\n");
  178. for (Method f : fs) {
  179. methods.append(f.getName()).append("\n");
  180. if (f.getName().equals(name)) {
  181. if (f.getModifiers() != modifiers) {
  182. fail("Found method " + name + " in " + clazzname + " but modifiers were wrong, they were " + f.getModifiers());
  183. }
  184. return f;
  185. }
  186. System.out.println(f.getGenericSignature());
  187. }
  188. fail("Did not find method " + name + " in class " + clazzname + ". Found methods: " + methods.toString());
  189. return null;
  190. }
  191. // public itd onto a target that already has a field of that name
  192. // just to check what goes wrong and who checks it
  193. public void testPublicClash() throws Exception {
  194. runTest("two");
  195. }
  196. public void testPrivateClash() throws Exception {
  197. runTest("three");
  198. JavaClass jc = getClassFrom(ajc.getSandboxDirectory(), "Three");
  199. Field[] fs = jc.getFields();
  200. for (Field f : fs) {
  201. System.out.println(f);
  202. }
  203. // public int ajc$interField$X$xPrivate [RuntimeVisibleAnnotations]
  204. // public Integer ajc$interField$$yDefault [RuntimeVisibleAnnotations]
  205. // public String zPublic [RuntimeVisibleAnnotations]
  206. }
  207. // --
  208. public static Test suite() {
  209. return XMLBasedAjcTestCase.loadSuite(TransparentWeavingTests.class);
  210. }
  211. @Override
  212. protected java.net.URL getSpecFile() {
  213. return getClassResource("transparentweaving.xml");
  214. }
  215. }