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

21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
15 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
6 years ago
21 years ago
21 years ago
21 years ago
6 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
21 years ago
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.BcweaverTests;
  30. import org.aspectj.weaver.ShadowMunger;
  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 = BcweaverTests.getOutdir();
  57. outDirPath = outDir.getAbsolutePath();
  58. }
  59. @Override
  60. public void tearDown() throws Exception {
  61. super.tearDown();
  62. BcweaverTests.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 = BcweaverTests.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(BcweaverTests.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 BcweaverTests.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. }