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.

CovarianceTests.java 11KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302
  1. /*******************************************************************************
  2. * Copyright (c) 2004 IBM Corporation and others.
  3. * All rights reserved. This program and the accompanying materials
  4. * are made available under the terms of the Common Public License v1.0
  5. * which accompanies this distribution, and is available at
  6. * http://www.eclipse.org/legal/cpl-v10.html
  7. *
  8. * Contributors:
  9. * Andy Clement - initial implementation
  10. *******************************************************************************/
  11. package org.aspectj.systemtest.ajc150;
  12. import java.io.File;
  13. import java.io.IOException;
  14. import java.util.ArrayList;
  15. import java.util.Collection;
  16. import java.util.HashSet;
  17. import java.util.Iterator;
  18. import java.util.List;
  19. import java.util.Set;
  20. import junit.framework.Test;
  21. import org.aspectj.bridge.IMessage;
  22. import org.aspectj.testing.XMLBasedAjcTestCase;
  23. import org.aspectj.tools.ajc.AjcTestCase;
  24. import org.aspectj.tools.ajc.CompilationResult;
  25. /*
  26. class Car {}
  27. class FastCar extends Car {}
  28. class Super {
  29. Car getCar() {
  30. return new Car();
  31. }
  32. }
  33. class Sub extends Super {
  34. FastCar getCar() {
  35. return new FastCar();
  36. }
  37. }
  38. public class CovBaseProgram01 {
  39. public static void main(String[] argv) {
  40. new CovBaseProgram01().run();
  41. }
  42. public void run() {
  43. Super instance_super = new Super();
  44. Sub instance_sub = new Sub();
  45. Car c1 = instance_super.getCar(); // Line 26
  46. Car c2 = instance_sub.getCar(); // Line 27
  47. }
  48. }
  49. // Line26: callJPs: call(Car Super.getCar())
  50. // Line27: callJPs: call(FastCar Sub.getCar()) call(Car Super.getCar())
  51. */
  52. /**
  53. * Covariance is simply where a type overrides some inherited implementation and narrows the return type.
  54. */
  55. public class CovarianceTests extends AjcTestCase {
  56. private boolean verbose = false;
  57. /**
  58. * call(* getCar()) should match both
  59. */
  60. public void testCOV001() {
  61. CompilationResult cR = binaryWeave("CovBaseProgram01.jar","CovAspect01.aj",0,0);
  62. verifyOutput(cR,new String[]{
  63. "weaveinfo Type 'CovBaseProgram01' (CovBaseProgram01.java:26) advised by before advice from 'CovAspect01' (CovAspect01.aj:5)",
  64. "weaveinfo Type 'CovBaseProgram01' (CovBaseProgram01.java:27) advised by before advice from 'CovAspect01' (CovAspect01.aj:5)"
  65. });
  66. }
  67. /**
  68. * call(* Super.getCar()) should match both
  69. *
  70. * This test required a change to the compiler. When we are looking at signatures and comparing them we walk up
  71. * the hierarchy looking for supertypes that declare the same method. The problem is that in the comparison for
  72. * whether to methods are compatible we were including the return type - this meant 'Car getCar()' on Super was
  73. * different to 'FastCar getCar()' on Sub - it thought they were entirely different methods. In fact the return
  74. * type is irrelevant here, we just want to make sure the names and the parameter types are the same - so I
  75. * added a parameterSignature to the Member class that looks like '()' where the full signature looks like
  76. * '()LFastCar;' (which includes the return type). If the full signature comparison fails then it looks at the
  77. * parameter signature - I did it that way to try and preserve some performance. I haven't changed the
  78. * definition of 'signature' for a member as trimming the return type off it seems rather serious !
  79. *
  80. * What might break:
  81. * - 'matches' can now return true for things that have different return types - I guess whether this is a problem
  82. * depends on what the caller of matches is expecting, their code will have been written before covariance was
  83. * a possibility. All the tests pass so I'll leave it like this for now.
  84. */
  85. public void testCOV002() {
  86. CompilationResult cR = binaryWeave("CovBaseProgram01.jar","CovAspect02.aj",0,0);
  87. verifyOutput(cR,new String[]{
  88. "weaveinfo Type 'CovBaseProgram01' (CovBaseProgram01.java:26) advised by before advice from 'CovAspect02' (CovAspect02.aj:5)",
  89. "weaveinfo Type 'CovBaseProgram01' (CovBaseProgram01.java:27) advised by before advice from 'CovAspect02' (CovAspect02.aj:5)"
  90. });
  91. }
  92. /**
  93. * call(Car getCar()) should match both
  94. *
  95. * Had to implement proper covariance support here...
  96. */
  97. public void testCOV003() {
  98. CompilationResult cR = binaryWeave("CovBaseProgram01.jar","CovAspect03.aj",0,0);
  99. verifyOutput(cR,new String[]{
  100. "weaveinfo Type 'CovBaseProgram01' (CovBaseProgram01.java:26) advised by before advice from 'CovAspect03' (CovAspect03.aj:5)",
  101. "weaveinfo Type 'CovBaseProgram01' (CovBaseProgram01.java:27) advised by before advice from 'CovAspect03' (CovAspect03.aj:5)"
  102. });
  103. }
  104. /**
  105. * *** Different base program, where Sub does not extend Super.
  106. * call(Car Super.getCar()) should only match first call to getCar()
  107. */
  108. public void testCOV004() {
  109. CompilationResult cR = binaryWeave("CovBaseProgram02.jar","CovAspect04.aj",0,0);
  110. verifyOutput(cR,new String[]{
  111. "weaveinfo Type 'CovBaseProgram02' (CovBaseProgram02.java:30) advised by before advice from 'CovAspect04' (CovAspect04.aj:5)"
  112. });
  113. }
  114. /**
  115. * *** Original base program
  116. * call(Car Super.getCar()) should match both
  117. */
  118. public void testCOV005() {
  119. CompilationResult cR = binaryWeave("CovBaseProgram01.jar","CovAspect05.aj",0,0);
  120. verifyOutput(cR,new String[]{
  121. "weaveinfo Type 'CovBaseProgram01' (CovBaseProgram01.java:26) advised by before advice from 'CovAspect05' (CovAspect05.aj:5)",
  122. "weaveinfo Type 'CovBaseProgram01' (CovBaseProgram01.java:27) advised by before advice from 'CovAspect05' (CovAspect05.aj:5)"
  123. });
  124. }
  125. /**
  126. * call(Car Sub.getCar()) should not match anything
  127. */
  128. public void testCOV006() {
  129. CompilationResult cR = binaryWeave("CovBaseProgram01.jar","CovAspect06.aj",0,1);
  130. verifyOutput(cR,new String[]{/* no expected output! */});
  131. assertTrue("Expected one xlint warning message for line 26, but got: "+cR.getWarningMessages(),
  132. cR.getWarningMessages().size()==1 && ((IMessage)cR.getWarningMessages().get(0)).toString().indexOf("26")!=-1);
  133. }
  134. /**
  135. * call(Car+ Sub.getCar()) should match 2nd call with xlint for the 1st call
  136. */
  137. public void testCOV007() {
  138. CompilationResult cR = binaryWeave("CovBaseProgram01.jar","CovAspect07.aj",0,1);
  139. verifyOutput(cR,new String[]{
  140. "weaveinfo Type 'CovBaseProgram01' (CovBaseProgram01.java:27) advised by before advice from 'CovAspect07' (CovAspect07.aj:5)"
  141. });
  142. assertTrue("Expected one xlint warning message for line 26, but got: "+cR.getWarningMessages(),
  143. cR.getWarningMessages().size()==1 && ((IMessage)cR.getWarningMessages().get(0)).toString().indexOf("26")!=-1);
  144. }
  145. /**
  146. * *** aspect now contains two pointcuts and two pieces of advice
  147. * call(FastCar getCar()) matches on 2nd call
  148. * call(FastCar Sub.getCar()) matches on 2nd call
  149. */
  150. public void testCOV008() {
  151. CompilationResult cR = binaryWeave("CovBaseProgram01.jar","CovAspect08.aj",0,0);
  152. verifyOutput(cR,new String[]{
  153. "weaveinfo Type 'CovBaseProgram01' (CovBaseProgram01.java:27) advised by before advice from 'CovAspect08' (CovAspect08.aj:11)",
  154. "weaveinfo Type 'CovBaseProgram01' (CovBaseProgram01.java:27) advised by before advice from 'CovAspect08' (CovAspect08.aj:5)"
  155. });
  156. }
  157. /**
  158. * call(FastCar Super.getCar()) matches nothing
  159. */
  160. public void testCOV009() {
  161. CompilationResult cR = binaryWeave("CovBaseProgram01.jar","CovAspect09.aj",0,0);
  162. verifyOutput(cR,new String[]{/* No matches */});
  163. assertTrue("Expected no warnings but got: "+cR.getWarningMessages(),cR.getWarningMessages().size()==0);
  164. }
  165. /**
  166. * call(Car+ getCar()) matches both
  167. */
  168. public void testCOV010() {
  169. CompilationResult cR = binaryWeave("CovBaseProgram01.jar","CovAspect10.aj",0,0);
  170. verifyOutput(cR,new String[]{
  171. "weaveinfo Type 'CovBaseProgram01' (CovBaseProgram01.java:26) advised by before advice from 'CovAspect10' (CovAspect10.aj:5)",
  172. "weaveinfo Type 'CovBaseProgram01' (CovBaseProgram01.java:27) advised by before advice from 'CovAspect10' (CovAspect10.aj:5)"
  173. });
  174. }
  175. //--------------------------------------------------------------------------------
  176. //--------------------------------------------------------------------------------
  177. //--------------------------------------------------------------------------------
  178. private File baseDir;
  179. protected void setUp() throws Exception {
  180. super.setUp();
  181. baseDir = new File("../tests/java5/covariance");
  182. }
  183. private CompilationResult binaryWeave(String inpath, String insource,int expErrors,int expWarnings) {
  184. String[] args = new String[] {"-inpath",inpath,insource,"-showWeaveInfo"};
  185. CompilationResult result = ajc(baseDir,args);
  186. if (verbose || result.hasErrorMessages()) System.out.println(result);
  187. assertTrue("Expected "+expErrors+" errors but got "+result.getErrorMessages().size()+":\n"+
  188. formatCollection(result.getErrorMessages()),result.getErrorMessages().size()==expErrors);
  189. assertTrue("Expected "+expWarnings+" warnings but got "+result.getWarningMessages().size()+":\n"+
  190. formatCollection(result.getWarningMessages()),result.getWarningMessages().size()==expWarnings);
  191. return result;
  192. }
  193. private List getWeavingMessages(List msgs) {
  194. List result = new ArrayList();
  195. for (Iterator iter = msgs.iterator(); iter.hasNext();) {
  196. IMessage element = (IMessage) iter.next();
  197. if (element.getKind()==IMessage.WEAVEINFO) {
  198. result.add(element.toString());
  199. }
  200. }
  201. return result;
  202. }
  203. private void verifyOutput(CompilationResult cR,String[] expected) {
  204. List weavingmessages = getWeavingMessages(cR.getInfoMessages());
  205. dump(weavingmessages);
  206. for (int i = 0; i < expected.length; i++) {
  207. boolean found = weavingmessages.contains(expected[i]);
  208. if (found) {
  209. weavingmessages.remove(expected[i]);
  210. } else {
  211. System.err.println(dump(getWeavingMessages(cR.getInfoMessages())));
  212. fail("Expected message not found.\nExpected:\n"+expected[i]+"\nObtained:\n"+dump(getWeavingMessages(cR.getInfoMessages())));
  213. }
  214. }
  215. if (weavingmessages.size()!=0) {
  216. fail("Unexpected messages obtained from program:\n"+dump(weavingmessages));
  217. }
  218. }
  219. private String formatCollection(Collection s) {
  220. StringBuffer sb = new StringBuffer();
  221. for (Iterator iter = s.iterator(); iter.hasNext();) {
  222. Object element = (Object) iter.next();
  223. sb.append(element).append("\n");
  224. }
  225. return sb.toString();
  226. }
  227. private static Set split(String input) {
  228. Set l = new HashSet();
  229. int idx = 0;
  230. while (input.indexOf("]",idx)!=-1) {
  231. int nextbreak = input.indexOf("]",idx);
  232. String s = input.substring(idx,nextbreak+1);
  233. l.add(s);
  234. idx = input.indexOf("[",nextbreak+1);
  235. if (idx==-1) break;
  236. }
  237. return l;
  238. }
  239. private void copyFile(String fromName) {
  240. copyFile(fromName,fromName);
  241. }
  242. private void copyFile(String from,String to) {
  243. try {
  244. org.aspectj.util.FileUtil.copyFile(new File(baseDir + File.separator + from),
  245. new File(ajc.getSandboxDirectory(),to));
  246. } catch (IOException ioe) {
  247. ioe.printStackTrace();
  248. }
  249. }
  250. private String dump(List l) {
  251. StringBuffer sb = new StringBuffer();
  252. int i =0;
  253. sb.append("--- Weaving Messages ---\n");
  254. for (Iterator iter = l.iterator(); iter.hasNext();) {
  255. sb.append(i+") "+iter.next()+"\n");
  256. }
  257. sb.append("------------------------\n");
  258. return sb.toString();
  259. }
  260. }