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.

NegativeSourceLocation.java 13KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. import org.aspectj.lang.*;
  2. import org.aspectj.lang.reflect.*;
  3. import org.aspectj.testing.*;
  4. /**
  5. * @testcase PR#525 validate presence/absence of thisEnclosingJoinPointStaticPart
  6. * @testcase PR#525 validate SourceLocation
  7. */
  8. public class NegativeSourceLocation {
  9. public static void main(String[] args) {
  10. Signal.expect(Const.EXPECTED);
  11. TargetClass target = new TargetClass();
  12. // run from outside code the compiler controls
  13. Thread t = new Thread(target, "NegativeSourceLocation");
  14. t.start();
  15. int i = 0;
  16. // todo: use Timer to add interrupt?
  17. while ((10 > i++) && t.isAlive()) {
  18. try { t.join(); }
  19. catch (InterruptedException e) {}
  20. }
  21. Signal.checkAll();
  22. }
  23. }
  24. /** indirection for test utility */
  25. class Signal {
  26. public static final void failed(String s) {
  27. //Thread.currentThread().dumpStack();
  28. Tester.checkFailed(s);
  29. }
  30. public static final void found(JoinPoint.StaticPart s) {
  31. Tester.event(s.toString());
  32. }
  33. public static final void found(String s) {
  34. Tester.event(s);
  35. }
  36. public static final void checkAll() {
  37. Tester.checkAllEvents();
  38. }
  39. public static final void expect(String[] sra) {
  40. Tester.expectEventsInString(sra);
  41. }
  42. } // class Signal
  43. /** TargetClass has most every join point, provoked by initializatin and run() */
  44. class TargetClass implements Runnable {
  45. TargetClass() {}
  46. static String staticString = "two"; // jp has -1 source location
  47. static {
  48. staticString = "one";
  49. String s = staticString + "asdf";
  50. }
  51. static {
  52. staticString = "three";
  53. }
  54. String string = "bar";
  55. public static void staticRun() { // execute
  56. staticString = "foo"; // set - static var
  57. String s = staticString; // get - static var
  58. s = s + "ss";
  59. staticString = s + "u"; // set - instance var
  60. TargetClass u = new TargetClass(); // initialization
  61. staticString = u.toString();
  62. }
  63. public void run() { // execute - no thisEnclosingJoinPoint when called from Thread.start()
  64. boolean doNotOptimize = (staticString != null);
  65. if (doNotOptimize) internalRun();
  66. }
  67. private void internalRun() { // execute
  68. staticString = "foo"; // set - static var
  69. staticRun(); // call static
  70. String s = staticString; // get - static var
  71. String t = string; // get - instance var
  72. s = s + t;
  73. string = s + t; // set - instance var
  74. final Error e = new Error("caught here");
  75. try {
  76. throw e;
  77. } catch (Error er) { // handler
  78. if (er != e) {
  79. Signal.failed("caught Error=" + er);
  80. } else {
  81. Signal.found("caught");
  82. }
  83. }
  84. }
  85. } // class TargetClass
  86. /**
  87. * This Aspect attempts to specify join points that have enclosing
  88. * join points and whether the source locations are valid.
  89. * It fails in using only pointcuts.
  90. * This is just a first cut. I (wes) have an AroundAll
  91. * which does this tracking...
  92. */
  93. aspect Aspect {
  94. // ------------------------------- pointcuts select logical sets of join points
  95. // 1.1 includes StringBuffer calls that weren't in 1.0
  96. pointcut allTargetJoinPoints()
  97. : within(TargetClass) &&
  98. !call(* StringBuffer.*(..)) && !call(StringBuffer.new(..))
  99. && !call(* String.valueOf(Object));
  100. /** these have no enclosing join point */
  101. pointcut noEnclosingJoinPoint()
  102. : ((call(public void TargetClass.run())) // called from Thread.start() (caller-side, but has callee-side?)
  103. //|| staticinitialization(TargetClass) // the enclosing jp here is itself
  104. );
  105. // || initialization(TargetClass.new())
  106. // || execution(TargetClass.new()) // todo: expect it to be self like in methods?
  107. /** these have enclosing join points */
  108. pointcut hasEnclosingJoinPoint()
  109. : allTargetJoinPoints()
  110. && !(noEnclosingJoinPoint())
  111. ;
  112. /** expecting an enclosing join point different from thisJoinPoint */
  113. pointcut enclosingDiffers()
  114. : get(* TargetClass.*)
  115. || set(* TargetClass.*)
  116. || call(* TargetClass.*(..))
  117. || handler(Error)
  118. ;
  119. pointcut hasDifferentEnclosingJoinPoint()
  120. : hasEnclosingJoinPoint()
  121. && enclosingDiffers()
  122. ;
  123. pointcut hasSameEnclosingJoinPoint()
  124. : hasEnclosingJoinPoint()
  125. && (!enclosingDiffers());
  126. /** synthetic join points have no source location */
  127. pointcut syntheticJoinPoints()
  128. : staticinitialization(TargetClass)
  129. || initialization(TargetClass.new(UnknownConstructor))
  130. ;
  131. pointcut joinPointHasValidSourceLocation()
  132. : allTargetJoinPoints()
  133. && (!syntheticJoinPoints())
  134. //&& if(expectSourceLocation(thisJoinPointStaticPart))
  135. ;
  136. pointcut enclosingJoinPointHasValidSourceLocation() // todo: cannot specify
  137. : hasEnclosingJoinPoint()
  138. && (!syntheticJoinPoints())
  139. //&& if(expectSourceLocation(thisEnclosingJoinPointStaticPart))
  140. ;
  141. // ---------------------- advice applies invariants to each logical set of join points
  142. /** @testcase all join points have non-null thisJoinPoint and thisJoinPointStaticPart */
  143. before(): allTargetJoinPoints() {
  144. Signal.found("before AllTargetJoinPoints " + thisJoinPointStaticPart);
  145. //System.err.println(thisJoinPointStaticPart + " at " + thisJoinPointStaticPart.getSourceLocation());
  146. String test = "all join points have non-null thisJoinPointStaticPart";
  147. if (null == thisJoinPoint) {
  148. Signal.failed(test + " failed with null thisJoinPoint: " + thisJoinPointStaticPart);
  149. }
  150. if (null == thisJoinPointStaticPart) {
  151. Signal.failed(test + " failed with null thisJoinPointStaticPart: " + thisJoinPoint);
  152. }
  153. }
  154. /** @testcase non-null thisEnclosingStaticJoinPoint at certain join points */
  155. before() : hasEnclosingJoinPoint() {
  156. String test = "failed (most join points have non-null thisEnclosingStaticJoinPoint) ";
  157. if (null == thisEnclosingJoinPointStaticPart) {
  158. String jpName = thisJoinPointStaticPart.toString();
  159. Signal.failed(test + render(thisJoinPointStaticPart, thisEnclosingJoinPointStaticPart));
  160. //if (!jpName.equals("execution(TargetClass.<init>)")) { // todo: unable to specify this...
  161. }
  162. }
  163. /** @testcase non-null thisEnclosingStaticJoinPoint at join points (except for tested exceptions) */
  164. before() : hasDifferentEnclosingJoinPoint() {
  165. String test = "join points with different thisEnclosingStaticJoinPoint";
  166. if (thisEnclosingJoinPointStaticPart != thisEnclosingJoinPointStaticPart) {
  167. Signal.failed(test + " different static part : " + thisJoinPointStaticPart);
  168. }
  169. }
  170. /** @testcase expecting valid source locations */
  171. before() : joinPointHasValidSourceLocation() {
  172. if (null == thisJoinPointStaticPart) {
  173. Signal.failed("null thisJoinPointStaticPart");
  174. } else {
  175. checkSourceLocation(thisJoinPointStaticPart);
  176. }
  177. }
  178. /** @testcase expecting valid source locations in enclosing join point */
  179. before() : enclosingJoinPointHasValidSourceLocation() {
  180. if (null == thisEnclosingJoinPointStaticPart) {
  181. Signal.failed("null thisEnclosingJoinPointStaticPart in " + thisJoinPointStaticPart);
  182. } else {
  183. checkSourceLocation(thisEnclosingJoinPointStaticPart);
  184. }
  185. }
  186. /** @testcase non-null thisEnclosingJoinPointStaticPart in static initializer if invoked within a join point? */
  187. before() : staticinitialization(AnotherTargetClass) {
  188. String test = "static initializer join points have non-null thisJoinPointStaticPart when invoked from CCC";
  189. if (null == thisJoinPoint) {
  190. Signal.failed(test + " failed with null thisJoinPoint: " + thisJoinPointStaticPart);
  191. }
  192. if (null == thisJoinPointStaticPart) {
  193. Signal.failed(test + " failed with null thisJoinPointStaticPart: " + thisJoinPoint);
  194. }
  195. Signal.found("staticinitialization(AnotherTargetClass))");
  196. //Signal.found(thisJoinPointStaticPart); // todo: relying on formatting of toString() - fix
  197. }
  198. /** @testcase no call from outside CCC has thisEnclosingJoinPointStaticPart (possible mistake) */
  199. before() : noEnclosingJoinPoint() {
  200. Signal.found("before noEnclosingJoinPoint " + thisJoinPointStaticPart);
  201. if (null != thisEnclosingJoinPointStaticPart) {
  202. Signal.failed("unexpected non-null thisEnclosingJoinPointStaticPart: "
  203. + thisEnclosingJoinPointStaticPart + " from " + thisJoinPointStaticPart);
  204. }
  205. }
  206. static String render(JoinPoint.StaticPart jp, JoinPoint.StaticPart ejp) {
  207. StringBuffer sb = new StringBuffer();
  208. sb.append("thisJoinPoint: ");
  209. sb.append(null == jp ? "null" : jp.toString());
  210. sb.append("thisEnclosingJoinPoint: ");
  211. sb.append(null == ejp ? "null" : ejp.toString());
  212. return sb.toString();
  213. }
  214. void checkSourceLocation(JoinPoint.StaticPart jp) { // todo: provide caller context?
  215. checkSourceLocation(jp.getSourceLocation(), jp.toString());
  216. }
  217. /** aborted attempt to check jp by name for jp without enclosing */
  218. private static boolean expectSourceLocation(JoinPoint.StaticPart jp) {
  219. if (null == jp) {
  220. return false;
  221. } else {
  222. String name = jp.toString();
  223. if (-1 != name.indexOf("TargetClass.<init>")) {
  224. return false;
  225. }
  226. }
  227. return true; // todo: overinclusive
  228. }
  229. private boolean inInitCode(JoinPoint.StaticPart jp) {
  230. return (-1 != jp.toString().indexOf("<init>"));
  231. }
  232. void checkSourceLocation(SourceLocation sl, String context) {
  233. if (sl == null) {
  234. Signal.failed(context + "null SourceLocation");
  235. } else {
  236. int i = sl.getLine();
  237. if (0 > i) {
  238. Signal.failed(context + " line<0: " + i);
  239. }
  240. // 1.1 doesn't provide column info
  241. // i = sl.getColumn();
  242. // if (0 > i) {
  243. // Signal.failed(context + " column<0: " + i);
  244. // }
  245. }
  246. }
  247. } // Aspect
  248. /** more readable to put expected messages at end of file */
  249. class Const {
  250. // todo: EXPECTED will break if JoinPoint.StaticPart.toString() changes
  251. public static final String[] EXPECTED = new String[]
  252. {
  253. "before AllTargetJoinPoints staticinitialization(TargetClass.<clinit>)"
  254. , "before AllTargetJoinPoints set(String TargetClass.staticString)"
  255. , "before AllTargetJoinPoints get(String TargetClass.staticString)"
  256. , "before AllTargetJoinPoints get(String TargetClass.staticString)"
  257. , "before AllTargetJoinPoints set(String TargetClass.staticString)"
  258. , "before AllTargetJoinPoints set(String TargetClass.staticString)"
  259. , "before AllTargetJoinPoints preinitialization(TargetClass())"
  260. , "before AllTargetJoinPoints initialization(java.lang.Runnable())"
  261. //, "before AllTargetJoinPoints execution(java.lang.Runnable())"
  262. , "before AllTargetJoinPoints initialization(TargetClass())"
  263. //, "before AllTargetJoinPoints execution(TargetClass.<init>)"
  264. , "before AllTargetJoinPoints set(String TargetClass.string)"
  265. , "before AllTargetJoinPoints execution(TargetClass())"
  266. , "before AllTargetJoinPoints execution(void TargetClass.run())"
  267. , "before AllTargetJoinPoints call(void TargetClass.internalRun())"
  268. , "before AllTargetJoinPoints execution(void TargetClass.internalRun())"
  269. , "before AllTargetJoinPoints set(String TargetClass.staticString)"
  270. , "before AllTargetJoinPoints call(void TargetClass.staticRun())"
  271. , "before AllTargetJoinPoints execution(void TargetClass.staticRun())"
  272. , "before AllTargetJoinPoints set(String TargetClass.staticString)"
  273. , "before AllTargetJoinPoints get(String TargetClass.staticString)"
  274. , "before AllTargetJoinPoints set(String TargetClass.staticString)"
  275. , "before AllTargetJoinPoints call(TargetClass())"
  276. , "before AllTargetJoinPoints preinitialization(TargetClass())"
  277. , "before AllTargetJoinPoints initialization(TargetClass())"
  278. , "before AllTargetJoinPoints initialization(java.lang.Runnable())"
  279. //, "before AllTargetJoinPoints execution(java.lang.Runnable())"
  280. //, "before AllTargetJoinPoints execution(TargetClass.<init>)"
  281. , "before AllTargetJoinPoints set(String TargetClass.string)"
  282. , "before AllTargetJoinPoints execution(TargetClass())"
  283. , "before AllTargetJoinPoints call(String java.lang.Object.toString())"
  284. , "before AllTargetJoinPoints set(String TargetClass.staticString)"
  285. , "before AllTargetJoinPoints get(String TargetClass.staticString)"
  286. , "before AllTargetJoinPoints get(String TargetClass.string)"
  287. , "before AllTargetJoinPoints set(String TargetClass.string)"
  288. , "before AllTargetJoinPoints call(java.lang.Error(String))"
  289. , "before AllTargetJoinPoints handler(catch(Error))"
  290. , "before AllTargetJoinPoints call(void Signal.found(String))"
  291. , "caught"
  292. };
  293. }