You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

WeaveTestCase.java 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. /* *******************************************************************
  2. * Copyright (c) 2002 Palo Alto Research Center, Incorporated (PARC).
  3. * All rights reserved.
  4. * This program and the accompanying materials are made available
  5. * under the terms of the Eclipse Public License v1.0
  6. * which accompanies this distribution and is available at
  7. * http://www.eclipse.org/legal/epl-v10.html
  8. *
  9. * Contributors:
  10. * PARC initial implementation
  11. * ******************************************************************/
  12. package org.aspectj.weaver.bcel;
  13. import java.io.File;
  14. import java.io.FileOutputStream;
  15. import java.io.IOException;
  16. import java.io.PrintStream;
  17. import java.util.ArrayList;
  18. import java.util.Iterator;
  19. import java.util.List;
  20. import org.aspectj.apache.bcel.Constants;
  21. import org.aspectj.apache.bcel.generic.InstructionFactory;
  22. import org.aspectj.apache.bcel.generic.InstructionList;
  23. import org.aspectj.apache.bcel.generic.InvokeInstruction;
  24. import org.aspectj.apache.bcel.generic.Type;
  25. import org.aspectj.testing.util.TestUtil;
  26. import org.aspectj.util.FileUtil;
  27. import org.aspectj.util.LangUtil;
  28. import org.aspectj.weaver.Advice;
  29. import org.aspectj.weaver.ShadowMunger;
  30. import org.aspectj.weaver.WeaverTestCase;
  31. import org.aspectj.weaver.patterns.FormalBinding;
  32. import org.aspectj.weaver.patterns.PerClause;
  33. import org.aspectj.weaver.patterns.Pointcut;
  34. import org.aspectj.weaver.patterns.SimpleScope;
  35. import junit.framework.TestCase;
  36. public abstract class WeaveTestCase extends TestCase {
  37. public boolean regenerate = false;
  38. public boolean runTests = true;
  39. public boolean behave15 = false;
  40. File outDir;
  41. String outDirPath;
  42. public BcelWorld world = new BcelWorld();
  43. {
  44. world.addPath(classDir);
  45. // Some of the tests in here rely on comparing output from dumping the delegates - if
  46. // we are using ASM delegates we don't know the names of parameters (they are irrelevant...)
  47. // and are missing from the dumping of asm delegates. This switch ensures we
  48. // continue to use BCEL for these tests.
  49. // world.setFastDelegateSupport(false);
  50. }
  51. public WeaveTestCase(String name) {
  52. super(name);
  53. }
  54. @Override
  55. public void setUp() throws Exception {
  56. outDir = WeaverTestCase.getOutdir();
  57. outDirPath = outDir.getAbsolutePath();
  58. }
  59. @Override
  60. public void tearDown() throws Exception {
  61. super.tearDown();
  62. WeaverTestCase.removeOutDir();
  63. outDir = null;
  64. outDirPath = null;
  65. }
  66. public static InstructionList getAdviceTag(BcelShadow shadow, String where) {
  67. String methodName = "ajc_" + where + "_" + shadow.getKind().toLegalJavaIdentifier();
  68. InstructionFactory fact = shadow.getFactory();
  69. InvokeInstruction il = fact.createInvoke("Aspect", methodName, Type.VOID, new Type[] {}, Constants.INVOKESTATIC);
  70. return new InstructionList(il);
  71. }
  72. public void weaveTest(String name, String outName, ShadowMunger planner) throws IOException {
  73. List<ShadowMunger> l = new ArrayList<ShadowMunger>(1);
  74. l.add(planner);
  75. weaveTest(name, outName, l);
  76. }
  77. // static String classDir = "../weaver/bin";
  78. static String classDir = WeaverTestCase.TESTDATA_PATH + File.separator + "bin";
  79. public void weaveTest(String name, String outName, List<ShadowMunger> planners) throws IOException {
  80. BcelWeaver weaver = new BcelWeaver(world);
  81. try {
  82. if (behave15)
  83. world.setBehaveInJava5Way(true);
  84. UnwovenClassFile classFile = makeUnwovenClassFile(classDir, name, outDirPath);
  85. weaver.addClassFile(classFile, false);
  86. weaver.setShadowMungers(planners);
  87. weaveTestInner(weaver, classFile, name, outName);
  88. } finally {
  89. if (behave15)
  90. world.setBehaveInJava5Way(false);
  91. }
  92. }
  93. protected void weaveTestInner(BcelWeaver weaver, UnwovenClassFile classFile, String name, String outName) throws IOException {
  94. // int preErrors = currentResult.errorCount();
  95. BcelObjectType classType = BcelWorld.getBcelObjectType(world.resolve(classFile.getClassName()));
  96. LazyClassGen gen = weaver.weave(classFile, classType);
  97. if (gen == null) {
  98. // we didn't do any weaving, but let's make a gen anyway
  99. gen = classType.getLazyClassGen(); // new LazyClassGen(classType);
  100. }
  101. try {
  102. String filenameToUse = findMostRelevantFile(outName);
  103. checkClass(gen, outDirPath, filenameToUse);
  104. if (runTests) {
  105. System.out.println("*******RUNNING: " + outName + " " + name + " *******");
  106. TestUtil.runMain(makeClassPath(outDirPath), name);
  107. }
  108. } catch (Error e) {
  109. System.err.println("Comparing to " + outName + ".txt");
  110. gen.print(System.err);
  111. throw e;
  112. } catch (RuntimeException e) {
  113. gen.print(System.err);
  114. throw e;
  115. }
  116. }
  117. public String findMostRelevantFile(String name) {
  118. double version = LangUtil.getVmVersion();
  119. while (version > 0) {
  120. String possibleFileName = name+"."+Double.toString(version)+".txt";
  121. if (new File(TESTDATA_DIR, possibleFileName).exists()) {
  122. return possibleFileName;
  123. }
  124. version--;
  125. }
  126. // Use the standard file
  127. return name+".txt";
  128. }
  129. public String makeClassPath(String outDir) {
  130. return outDir + File.pathSeparator + getTraceJar() + File.pathSeparator + classDir + File.pathSeparator
  131. + System.getProperty("java.class.path");
  132. }
  133. /**
  134. * '/' in the name indicates the location of the class
  135. */
  136. public static UnwovenClassFile makeUnwovenClassFile(String classDir, String name, String outDir) throws IOException {
  137. File outFile = new File(outDir, name + ".class");
  138. if (classDir.endsWith(".jar")) {
  139. String fname = name + ".class";
  140. UnwovenClassFile ret = new UnwovenClassFile(outFile.getAbsolutePath(), FileUtil.readAsByteArray(FileUtil
  141. .getStreamFromZip(classDir, fname)));
  142. return ret;
  143. } else {
  144. File inFile = new File(classDir, name + ".class");
  145. return new UnwovenClassFile(outFile.getAbsolutePath(), FileUtil.readAsByteArray(inFile));
  146. }
  147. }
  148. public void checkClass(LazyClassGen gen, String outDir, String expectedFile) throws IOException {
  149. if (regenerate)
  150. genClass(gen, outDir, expectedFile);
  151. else
  152. realCheckClass(gen, outDir, expectedFile);
  153. }
  154. static final File TESTDATA_DIR = new File(WeaverTestCase.TESTDATA_PATH);
  155. void genClass(LazyClassGen gen, String outDir, String expectedFile) throws IOException {
  156. // ClassGen b = getJavaClass(outDir, className);
  157. FileOutputStream out = new FileOutputStream(new File(TESTDATA_DIR, expectedFile));
  158. PrintStream ps = new PrintStream(out);
  159. gen.print(ps);
  160. ps.flush();
  161. }
  162. void realCheckClass(LazyClassGen gen, String outDir, String expectedFile) throws IOException {
  163. TestUtil.assertMultiLineStringEquals(expectedFile/* "classes" */,
  164. FileUtil.readAsString(new File(TESTDATA_DIR, expectedFile)), gen.toLongString());
  165. }
  166. // ----
  167. public ShadowMunger makeConcreteAdvice(String mungerString) {
  168. return makeConcreteAdvice(mungerString, 0, null);
  169. }
  170. public ShadowMunger makeConcreteAdvice(String mungerString, int extraArgFlag) {
  171. return makeConcreteAdvice(mungerString, extraArgFlag, null);
  172. }
  173. protected ShadowMunger makeConcreteAdvice(String mungerString, int extraArgFlag, PerClause perClause) {
  174. Advice myMunger = BcelTestUtils.shadowMunger(world, mungerString, extraArgFlag);
  175. // PerSingleton s = new PerSingleton();
  176. // s.concretize(world.resolve("Aspect"));
  177. // System.err.println(((KindedPointcut)myMunger.getPointcut().getPointcut()).getKind());
  178. Advice cm = (Advice) myMunger.concretize(myMunger.getDeclaringAspect().resolve(world), world, perClause);
  179. return cm;
  180. }
  181. public ShadowMunger makeAdviceField(String kind, String extraArgType) {
  182. return makeConcreteAdvice(kind + "(): get(* *.*) -> static void Aspect.ajc_" + kind + "_field_get(" + extraArgType + ")", 1);
  183. }
  184. public List<ShadowMunger> makeAdviceAll(String kind, boolean matchOnlyPrintln) {
  185. List<ShadowMunger> ret = new ArrayList<ShadowMunger>();
  186. if (matchOnlyPrintln) {
  187. ret.add(makeConcreteAdvice(kind + "(): call(* *.println(..)) -> static void Aspect.ajc_" + kind + "_method_execution()"));
  188. } else {
  189. ret.add(makeConcreteAdvice(kind + "(): call(* *.*(..)) -> static void Aspect.ajc_" + kind + "_method_call()"));
  190. ret.add(makeConcreteAdvice(kind + "(): call(*.new(..)) -> static void Aspect.ajc_" + kind + "_constructor_call()"));
  191. ret.add(makeConcreteAdvice(kind + "(): execution(* *.*(..)) -> static void Aspect.ajc_" + kind + "_method_execution()"));
  192. ret.add(makeConcreteAdvice(kind + "(): execution(*.new(..)) -> static void Aspect.ajc_" + kind
  193. + "_constructor_execution()"));
  194. // ret.add(
  195. // makeConcreteMunger(
  196. // kind
  197. // + "(): staticinitialization(*) -> static void Aspect.ajc_"
  198. // + kind
  199. // + "_staticinitialization()"));
  200. ret.add(makeConcreteAdvice(kind + "(): get(* *.*) -> static void Aspect.ajc_" + kind + "_field_get()"));
  201. // ret.add(
  202. // makeConcreteMunger(
  203. // kind + "(): set(* *.*) -> static void Aspect.ajc_" + kind + "_field_set()"));
  204. // XXX no test for advice execution, staticInitialization or (god help us) preInitialization
  205. }
  206. return ret;
  207. }
  208. public List<ShadowMunger> makeAdviceAll(final String kind) {
  209. return makeAdviceAll(kind, false);
  210. }
  211. public Pointcut makePointcutAll() {
  212. return makeConcretePointcut("get(* *.*) || call(* *.*(..)) || execution(* *.*(..)) || call(*.new(..)) || execution(*.new(..))");
  213. }
  214. public Pointcut makePointcutNoZeroArg() {
  215. return makeConcretePointcut("call(* *.*(*, ..)) || execution(* *.*(*, ..)) || call(*.new(*, ..)) || execution(*.new(*, ..))");
  216. }
  217. public Pointcut makePointcutPrintln() {
  218. return makeConcretePointcut("call(* *.println(..))");
  219. }
  220. public Pointcut makeConcretePointcut(String s) {
  221. return makeResolvedPointcut(s).concretize(null, null, 0);
  222. }
  223. public Pointcut makeResolvedPointcut(String s) {
  224. Pointcut pointcut0 = Pointcut.fromString(s);
  225. return pointcut0.resolve(new SimpleScope(world, FormalBinding.NONE));
  226. }
  227. // ----
  228. public String[] getStandardTargets() {
  229. return new String[] { "HelloWorld", "FancyHelloWorld" };
  230. }
  231. public String getTraceJar() {
  232. return WeaverTestCase.TESTDATA_PATH + "/tracing.jar";
  233. }
  234. // ----
  235. protected void weaveTest(String[] inClassNames, String outKind, ShadowMunger patternMunger) throws IOException {
  236. for (int i = 0; i < inClassNames.length; i++) {
  237. String inFileName = inClassNames[i];
  238. weaveTest(inFileName, outKind + inFileName, patternMunger);
  239. }
  240. }
  241. protected void weaveTest(String[] inClassNames, String outKind, List<ShadowMunger> patternMungers) throws IOException {
  242. for (int i = 0; i < inClassNames.length; i++) {
  243. String inFileName = inClassNames[i];
  244. weaveTest(inFileName, outKind + inFileName, patternMungers);
  245. }
  246. }
  247. protected List<ShadowMunger> addLexicalOrder(List<ShadowMunger> l) {
  248. int i = 10;
  249. for (ShadowMunger element: l) {
  250. ((Advice)element).setLexicalPosition(i += 10);
  251. }
  252. return l;
  253. }
  254. // XXX cut-and-paster from IdWeaveTestCase
  255. public void checkShadowSet(List l, String[] ss) {
  256. outer: for (int i = 0, len = ss.length; i < len; i++) {
  257. // inner:
  258. for (Iterator j = l.iterator(); j.hasNext();) {
  259. BcelShadow shadow = (BcelShadow) j.next();
  260. String shadowString = shadow.toString();
  261. if (shadowString.equals(ss[i])) {
  262. j.remove();
  263. continue outer;
  264. }
  265. }
  266. assertTrue("didn't find " + ss[i] + " in " + l, false);
  267. }
  268. assertTrue("too many things in " + l, l.size() == 0);
  269. }
  270. }