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.

MultiProjectIncrementalTests.java 38KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063
  1. /* *******************************************************************
  2. * Copyright (c) 2005 Contributors.
  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://eclipse.org/legal/epl-v10.html
  8. *
  9. * Contributors:
  10. * Andy Clement initial implementation
  11. * ******************************************************************/
  12. package org.aspectj.systemtest.incremental.tools;
  13. import java.io.BufferedReader;
  14. import java.io.DataOutputStream;
  15. import java.io.File;
  16. import java.io.FileOutputStream;
  17. import java.io.FileReader;
  18. import java.io.IOException;
  19. import java.util.ArrayList;
  20. import java.util.HashSet;
  21. import java.util.Iterator;
  22. import java.util.List;
  23. import java.util.Set;
  24. import org.aspectj.ajdt.internal.core.builder.AjState;
  25. import org.aspectj.ajdt.internal.core.builder.IncrementalStateManager;
  26. import org.aspectj.asm.AsmManager;
  27. import org.aspectj.asm.IProgramElement;
  28. import org.aspectj.bridge.IMessage;
  29. import org.aspectj.testing.util.FileUtil;
  30. /**
  31. * The superclass knows all about talking through Ajde to the compiler.
  32. * The superclass isn't in charge of knowing how to simulate overlays
  33. * for incremental builds, that is in here. As is the ability to
  34. * generate valid build configs based on a directory structure. To
  35. * support this we just need access to a sandbox directory - this
  36. * sandbox is managed by the superclass (it only assumes all builds occur
  37. * in <sandboxDir>/<projectName>/ )
  38. *
  39. * The idea is you can initialize multiple projects in the sandbox and
  40. * they can all be built independently, hopefully exploiting
  41. * incremental compilation. Between builds you can alter the contents
  42. * of a project using the alter() method that overlays some set of
  43. * new files onto the current set (adding new files/changing existing
  44. * ones) - you can then drive a new build and check it behaves as
  45. * expected.
  46. */
  47. public class MultiProjectIncrementalTests extends AjdeInteractionTestbed {
  48. public static boolean VERBOSE = false;
  49. protected void setUp() throws Exception {
  50. super.setUp();
  51. AjdeInteractionTestbed.VERBOSE = VERBOSE;
  52. AjState.FORCE_INCREMENTAL_DURING_TESTING = true;
  53. }
  54. protected void tearDown() throws Exception {
  55. super.tearDown();
  56. AjState.FORCE_INCREMENTAL_DURING_TESTING = false;
  57. }
  58. // Compile a single simple project
  59. public void testTheBasics() {
  60. initialiseProject("P1");
  61. build("P1"); // This first build will be batch
  62. build("P1");
  63. checkWasntFullBuild();
  64. checkCompileWeaveCount(0,0);
  65. }
  66. // source code doesnt matter, we are checking invalid path handling
  67. public void testInvalidAspectpath_pr121395() {
  68. initialiseProject("P1");
  69. File f = new File("foo.jar");
  70. Set s = new HashSet();
  71. s.add(f);
  72. configureAspectPath(s);
  73. build("P1"); // This first build will be batch
  74. checkForError("invalid aspectpath entry");
  75. }
  76. // Make simple changes to a project, adding a class
  77. public void testSimpleChanges() {
  78. initialiseProject("P1");
  79. build("P1"); // This first build will be batch
  80. alter("P1","inc1"); // adds a single class
  81. build("P1");
  82. checkCompileWeaveCount(1,-1);
  83. build("P1");
  84. checkCompileWeaveCount(0,-1);
  85. }
  86. // Make simple changes to a project, adding a class and an aspect
  87. public void testAddingAnAspect() {
  88. initialiseProject("P1");
  89. build("P1"); // build 1, weave 1
  90. alter("P1","inc1"); // adds a class
  91. alter("P1","inc2"); // adds an aspect
  92. build("P1"); // build 1,
  93. long timeTakenForFullBuildAndWeave = getTimeTakenForBuild();
  94. checkWasFullBuild(); // it *will* be a full build under the new
  95. // "back-to-the-source strategy
  96. checkCompileWeaveCount(5,3); // we compile X and A (the delta) find out that
  97. // an aspect has changed, go back to the source
  98. // and compile X,A,C, then weave them all.
  99. build("P1");
  100. long timeTakenForSimpleIncBuild = getTimeTakenForBuild();
  101. // I don't think this test will have timing issues as the times should be *RADICALLY* different
  102. // On my config, first build time is 2093ms and the second is 30ms
  103. assertTrue("Should not take longer for the trivial incremental build! first="+timeTakenForFullBuildAndWeave+
  104. "ms second="+timeTakenForSimpleIncBuild+"ms",
  105. timeTakenForSimpleIncBuild<timeTakenForFullBuildAndWeave);
  106. }
  107. public void testBuildingTwoProjectsInTurns() {
  108. configureBuildStructureModel(true);
  109. initialiseProject("P1");
  110. initialiseProject("P2");
  111. build("P1");
  112. build("P2");
  113. build("P1");
  114. checkWasntFullBuild();
  115. build("P2");
  116. checkWasntFullBuild();
  117. }
  118. /**
  119. * In order for this next test to run, I had to move the weaver/world pair we keep in the
  120. * AjBuildManager instance down into the state object - this makes perfect sense - otherwise
  121. * when reusing the state for another project we'd not be switching to the right weaver/world
  122. * for that project.
  123. */
  124. public void testBuildingTwoProjectsMakingSmallChanges() {
  125. configureBuildStructureModel(true);
  126. initialiseProject("P1");
  127. initialiseProject("P2");
  128. build("P1");
  129. build("P2");
  130. build("P1");
  131. checkWasntFullBuild();
  132. build("P2");
  133. checkWasntFullBuild();
  134. alter("P1","inc1"); // adds a class
  135. alter("P1","inc2"); // adds an aspect
  136. build("P1");
  137. checkWasFullBuild(); // adding an aspect makes us go back to the source
  138. }
  139. /**
  140. * Setup up two simple projects and build them in turn - check the
  141. * structure model is right after each build
  142. */
  143. public void testBuildingTwoProjectsAndVerifyingModel() {
  144. configureBuildStructureModel(true);
  145. initialiseProject("P1");
  146. initialiseProject("P2");
  147. build("P1");
  148. checkForNode("pkg","C",true);
  149. build("P2");
  150. checkForNode("pkg","C",false);
  151. build("P1");
  152. checkForNode("pkg","C",true);
  153. build("P2");
  154. checkForNode("pkg","C",false);
  155. }
  156. // Setup up two simple projects and build them in turn - check the
  157. // structure model is right after each build
  158. public void testBuildingTwoProjectsAndVerifyingStuff() {
  159. configureBuildStructureModel(true);
  160. initialiseProject("P1");
  161. initialiseProject("P2");
  162. build("P1");
  163. checkForNode("pkg","C",true);
  164. build("P2");
  165. checkForNode("pkg","C",false);
  166. build("P1");
  167. checkForNode("pkg","C",true);
  168. build("P2");
  169. checkForNode("pkg","C",false);
  170. }
  171. /**
  172. * Complex. Here we are testing that a state object records structural changes since
  173. * the last full build correctly. We build a simple project from scratch - this will
  174. * be a full build and so the structural changes since last build count should be 0.
  175. * We then alter a class, adding a new method and check structural changes is 1.
  176. */
  177. public void testStateManagement1() {
  178. File binDirectoryForP1 = new File(getFile("P1","bin"));
  179. initialiseProject("P1");
  180. build("P1"); // full build
  181. AjState ajs = IncrementalStateManager.findStateManagingOutputLocation(binDirectoryForP1);
  182. assertTrue("There should be a state object for project P1",ajs!=null);
  183. assertTrue("Should be no structural changes as it was a full build but found: "+
  184. ajs.getNumberOfStructuralChangesSinceLastFullBuild(),
  185. ajs.getNumberOfStructuralChangesSinceLastFullBuild()==0);
  186. alter("P1","inc3"); // adds a method to the class C.java
  187. build("P1");
  188. checkWasntFullBuild();
  189. ajs = IncrementalStateManager.findStateManagingOutputLocation(new File(getFile("P1","bin")));
  190. assertTrue("There should be state for project P1",ajs!=null);
  191. checkWasntFullBuild();
  192. assertTrue("Should be one structural changes as it was a full build but found: "+
  193. ajs.getNumberOfStructuralChangesSinceLastFullBuild(),
  194. ajs.getNumberOfStructuralChangesSinceLastFullBuild()==1);
  195. }
  196. /**
  197. * Complex. Here we are testing that a state object records structural changes since
  198. * the last full build correctly. We build a simple project from scratch - this will
  199. * be a full build and so the structural changes since last build count should be 0.
  200. * We then alter a class, changing body of a method, not the structure and
  201. * check struc changes is still 0.
  202. */
  203. public void testStateManagement2() {
  204. File binDirectoryForP1 = new File(getFile("P1","bin"));
  205. initialiseProject("P1");
  206. alter("P1","inc3"); // need this change in here so 'inc4' can be applied without making
  207. // it a structural change
  208. build("P1"); // full build
  209. AjState ajs = IncrementalStateManager.findStateManagingOutputLocation(binDirectoryForP1);
  210. assertTrue("There should be state for project P1",ajs!=null);
  211. assertTrue("Should be no struc changes as its a full build: "+
  212. ajs.getNumberOfStructuralChangesSinceLastFullBuild(),
  213. ajs.getNumberOfStructuralChangesSinceLastFullBuild()==0);
  214. alter("P1","inc4"); // changes body of main() method but does *not* change the structure of C.java
  215. build("P1");
  216. checkWasntFullBuild();
  217. ajs = IncrementalStateManager.findStateManagingOutputLocation(new File(getFile("P1","bin")));
  218. assertTrue("There should be state for project P1",ajs!=null);
  219. checkWasntFullBuild();
  220. assertTrue("Shouldn't be any structural changes but there were "+
  221. ajs.getNumberOfStructuralChangesSinceLastFullBuild(),
  222. ajs.getNumberOfStructuralChangesSinceLastFullBuild()==0);
  223. }
  224. /**
  225. * The C.java file modified in this test has an inner class - this means the inner class
  226. * has a this$0 field and <init>(C) ctor to watch out for when checking for structural changes
  227. *
  228. */
  229. public void testStateManagement3() {
  230. File binDirForInterproject1 = new File(getFile("interprojectdeps1","bin"));
  231. initialiseProject("interprojectdeps1");
  232. build("interprojectdeps1"); // full build
  233. AjState ajs = IncrementalStateManager.findStateManagingOutputLocation(binDirForInterproject1);
  234. assertTrue("There should be state for project P1",ajs!=null);
  235. assertTrue("Should be no struc changes as its a full build: "+
  236. ajs.getNumberOfStructuralChangesSinceLastFullBuild(),
  237. ajs.getNumberOfStructuralChangesSinceLastFullBuild()==0);
  238. alter("interprojectdeps1","inc1"); // adds a space to C.java
  239. build("interprojectdeps1");
  240. checkWasntFullBuild();
  241. ajs = IncrementalStateManager.findStateManagingOutputLocation(new File(getFile("interprojectdeps1","bin")));
  242. assertTrue("There should be state for project interprojectdeps1",ajs!=null);
  243. checkWasntFullBuild();
  244. assertTrue("Shouldn't be any structural changes but there were "+
  245. ajs.getNumberOfStructuralChangesSinceLastFullBuild(),
  246. ajs.getNumberOfStructuralChangesSinceLastFullBuild()==0);
  247. }
  248. /**
  249. * The C.java file modified in this test has an inner class - which has two ctors - this checks
  250. * how they are mangled with an instance of C.
  251. *
  252. */
  253. public void testStateManagement4() {
  254. File binDirForInterproject2 = new File(getFile("interprojectdeps2","bin"));
  255. initialiseProject("interprojectdeps2");
  256. build("interprojectdeps2"); // full build
  257. AjState ajs = IncrementalStateManager.findStateManagingOutputLocation(binDirForInterproject2);
  258. assertTrue("There should be state for project interprojectdeps2",ajs!=null);
  259. assertTrue("Should be no struc changes as its a full build: "+
  260. ajs.getNumberOfStructuralChangesSinceLastFullBuild(),
  261. ajs.getNumberOfStructuralChangesSinceLastFullBuild()==0);
  262. alter("interprojectdeps2","inc1"); // minor change to C.java
  263. build("interprojectdeps2");
  264. checkWasntFullBuild();
  265. ajs = IncrementalStateManager.findStateManagingOutputLocation(new File(getFile("interprojectdeps2","bin")));
  266. assertTrue("There should be state for project interprojectdeps1",ajs!=null);
  267. checkWasntFullBuild();
  268. assertTrue("Shouldn't be any structural changes but there were "+
  269. ajs.getNumberOfStructuralChangesSinceLastFullBuild(),
  270. ajs.getNumberOfStructuralChangesSinceLastFullBuild()==0);
  271. }
  272. /**
  273. * The C.java file modified in this test has an inner class - it has two ctors but
  274. * also a reference to C.this in it - which will give rise to an accessor being
  275. * created in C
  276. *
  277. */
  278. public void testStateManagement5() {
  279. File binDirForInterproject3 = new File(getFile("interprojectdeps3","bin"));
  280. initialiseProject("interprojectdeps3");
  281. build("interprojectdeps3"); // full build
  282. AjState ajs = IncrementalStateManager.findStateManagingOutputLocation(binDirForInterproject3);
  283. assertTrue("There should be state for project interprojectdeps3",ajs!=null);
  284. assertTrue("Should be no struc changes as its a full build: "+
  285. ajs.getNumberOfStructuralChangesSinceLastFullBuild(),
  286. ajs.getNumberOfStructuralChangesSinceLastFullBuild()==0);
  287. alter("interprojectdeps3","inc1"); // minor change to C.java
  288. build("interprojectdeps3");
  289. checkWasntFullBuild();
  290. ajs = IncrementalStateManager.findStateManagingOutputLocation(new File(getFile("interprojectdeps3","bin")));
  291. assertTrue("There should be state for project interprojectdeps1",ajs!=null);
  292. checkWasntFullBuild();
  293. assertTrue("Shouldn't be any structural changes but there were "+
  294. ajs.getNumberOfStructuralChangesSinceLastFullBuild(),
  295. ajs.getNumberOfStructuralChangesSinceLastFullBuild()==0);
  296. }
  297. /**
  298. * Now the most complex test. Create a dependancy between two projects. Building
  299. * one may affect whether the other does an incremental or full build. The
  300. * structural information recorded in the state object should be getting used
  301. * to control whether a full build is necessary...
  302. */
  303. public void testBuildingDependantProjects() {
  304. initialiseProject("P1");
  305. initialiseProject("P2");
  306. configureNewProjectDependency("P2","P1");
  307. build("P1");
  308. build("P2"); // now everything is consistent and compiled
  309. alter("P1","inc1"); // adds a second class
  310. build("P1");
  311. build("P2"); // although a second class was added - P2 can't be using it, so we don't full build here :)
  312. checkWasntFullBuild();
  313. alter("P1","inc3"); // structurally changes one of the classes
  314. build("P1");
  315. build("P2"); // build notices the structural change
  316. checkWasFullBuild();
  317. alter("P1","inc4");
  318. build("P1");
  319. build("P2"); // build sees a change but works out its not structural
  320. checkWasntFullBuild();
  321. }
  322. public void testPr85132() {
  323. initialiseProject("PR85132");
  324. build("PR85132");
  325. alter("PR85132","inc1");
  326. build("PR85132");
  327. }
  328. // parameterization of generic aspects
  329. public void testPr125405() {
  330. initialiseProject("PR125405");
  331. build("PR125405");
  332. checkCompileWeaveCount(1,1);
  333. alter("PR125405","inc1");
  334. build("PR125405");
  335. // "only abstract aspects can have type parameters"
  336. checkForError("only abstract aspects can have type parameters");
  337. alter("PR125405","inc2");
  338. build("PR125405");
  339. checkCompileWeaveCount(1,1);
  340. assertTrue("Should be no errors, but got "+MyTaskListManager.getErrorMessages(),MyTaskListManager.getErrorMessages().size()==0);
  341. }
  342. public void testPr128618() {
  343. initialiseProject("PR128618_1");
  344. initialiseProject("PR128618_2");
  345. configureNewProjectDependency("PR128618_2","PR128618_1");
  346. assertTrue("there should be no warning messages before we start",
  347. MyTaskListManager.getWarningMessages().isEmpty());
  348. build("PR128618_1");
  349. build("PR128618_2");
  350. List warnings = MyTaskListManager.getWarningMessages();
  351. assertTrue("Should be one warning, but there are #"+warnings.size(),warnings.size()==1);
  352. IMessage msg = (IMessage)(MyTaskListManager.getWarningMessages().get(0));
  353. assertEquals("warning should be against the FFDC.aj resource","FFDC.aj",msg.getSourceLocation().getSourceFile().getName());
  354. alter("PR128618_2","inc1");
  355. build("PR128618_2");
  356. checkWasntFullBuild();
  357. IMessage msg2 = (IMessage)(MyTaskListManager.getWarningMessages().get(0));
  358. assertEquals("warning should be against the FFDC.aj resource","FFDC.aj",msg2.getSourceLocation().getSourceFile().getName());
  359. assertFalse("a new warning message should have been generated", msg.equals(msg2));
  360. }
  361. public void testPr92837() {
  362. initialiseProject("PR92837");
  363. build("PR92837");
  364. alter("PR92837","inc1");
  365. build("PR92837");
  366. }
  367. public void testPr119570() {
  368. initialiseProject("PR119570");
  369. build("PR119570");
  370. assertTrue("Should be no errors, but got "+MyTaskListManager.getErrorMessages(),MyTaskListManager.getErrorMessages().size()==0);
  371. }
  372. public void testPr119570_2() {
  373. initialiseProject("PR119570_2");
  374. build("PR119570_2");
  375. List l = MyTaskListManager.getWarningMessages();
  376. assertTrue("Should be no warnings, but got "+l,l.size()==0);
  377. }
  378. // If you fiddle with the compiler options - you must manually reset the options at the end of the test
  379. public void testPr117209() {
  380. try {
  381. initialiseProject("pr117209");
  382. configureNonStandardCompileOptions("-proceedOnError");
  383. build("pr117209");
  384. checkCompileWeaveCount(6,6);
  385. } finally {
  386. MyBuildOptionsAdapter.reset();
  387. }
  388. }
  389. public void testPr114875() {
  390. initialiseProject("pr114875");
  391. build("pr114875");
  392. alter("pr114875","inc1");
  393. build("pr114875");
  394. checkWasFullBuild();
  395. alter("pr114875","inc2");
  396. build("pr114875");
  397. checkWasFullBuild(); // back to the source for an aspect change
  398. }
  399. public void testPr117882() {
  400. // AjdeInteractionTestbed.VERBOSE=true;
  401. // AjdeInteractionTestbed.configureBuildStructureModel(true);
  402. initialiseProject("PR117882");
  403. build("PR117882");
  404. checkWasFullBuild();
  405. alter("PR117882","inc1");
  406. build("PR117882");
  407. checkWasFullBuild(); // back to the source for an aspect
  408. // AjdeInteractionTestbed.VERBOSE=false;
  409. // AjdeInteractionTestbed.configureBuildStructureModel(false);
  410. }
  411. public void testPr117882_2() {
  412. // AjdeInteractionTestbed.VERBOSE=true;
  413. // AjdeInteractionTestbed.configureBuildStructureModel(true);
  414. initialiseProject("PR117882_2");
  415. build("PR117882_2");
  416. checkWasFullBuild();
  417. alter("PR117882_2","inc1");
  418. build("PR117882_2");
  419. checkWasFullBuild(); // back to the source...
  420. //checkCompileWeaveCount(1,4);
  421. //fullBuild("PR117882_2");
  422. //checkWasFullBuild();
  423. // AjdeInteractionTestbed.VERBOSE=false;
  424. // AjdeInteractionTestbed.configureBuildStructureModel(false);
  425. }
  426. public void testPr115251() {
  427. //AjdeInteractionTestbed.VERBOSE=true;
  428. initialiseProject("PR115251");
  429. build("PR115251");
  430. checkWasFullBuild();
  431. alter("PR115251","inc1");
  432. build("PR115251");
  433. checkWasFullBuild(); // back to the source
  434. }
  435. // public void testPr124399() {
  436. // AjdeInteractionTestbed.VERBOSE=true;
  437. // configureBuildStructureModel(true);
  438. // initialiseProject("PR124399");
  439. // build("PR124399");
  440. // checkWasFullBuild();
  441. // alter("PR124399","inc1");
  442. // build("PR124399");
  443. // checkWasntFullBuild();
  444. // }
  445. public void testPr121384() {
  446. // AjdeInteractionTestbed.VERBOSE=true;
  447. // AsmManager.setReporting("c:/foo.txt",true,true,true,false);
  448. MyBuildOptionsAdapter.setNonStandardOptions("-showWeaveInfo");
  449. configureBuildStructureModel(true);
  450. initialiseProject("pr121384");
  451. build("pr121384");
  452. checkWasFullBuild();
  453. alter("pr121384","inc1");
  454. build("pr121384");
  455. checkWasntFullBuild();
  456. }
  457. /* public void testPr111779() {
  458. super.VERBOSE=true;
  459. initialiseProject("PR111779");
  460. build("PR111779");
  461. alter("PR111779","inc1");
  462. build("PR111779");
  463. }
  464. */
  465. public void testPr93310_1() {
  466. initialiseProject("PR93310_1");
  467. build("PR93310_1");
  468. checkWasFullBuild();
  469. String fileC2 = getWorkingDir().getAbsolutePath() + File.separatorChar + "PR93310_1" + File.separatorChar + "src" + File.separatorChar + "pack" + File.separatorChar + "C2.java";
  470. (new File(fileC2)).delete();
  471. alter("PR93310_1","inc1");
  472. build("PR93310_1");
  473. checkWasFullBuild();
  474. int l = AjdeInteractionTestbed.MyStateListener.detectedDeletions.size();
  475. assertTrue("Expected one deleted file to be noticed, but detected: "+l,l==1);
  476. String name = (String)AjdeInteractionTestbed.MyStateListener.detectedDeletions.get(0);
  477. assertTrue("Should end with C2.java but is "+name,name.endsWith("C2.java"));
  478. }
  479. public void testPr93310_2() {
  480. initialiseProject("PR93310_2");
  481. build("PR93310_2");
  482. checkWasFullBuild();
  483. String fileC2 = getWorkingDir().getAbsolutePath() + File.separatorChar + "PR93310_2" + File.separatorChar + "src" + File.separatorChar + "pack" + File.separatorChar + "C2.java";
  484. (new File(fileC2)).delete();
  485. alter("PR93310_2","inc1");
  486. build("PR93310_2");
  487. checkWasFullBuild();
  488. int l = AjdeInteractionTestbed.MyStateListener.detectedDeletions.size();
  489. assertTrue("Expected one deleted file to be noticed, but detected: "+l,l==1);
  490. String name = (String)AjdeInteractionTestbed.MyStateListener.detectedDeletions.get(0);
  491. assertTrue("Should end with C2.java but is "+name,name.endsWith("C2.java"));
  492. }
  493. // Stage1: Compile two files, pack.A and pack.A1 - A1 sets a protected field in A.
  494. // Stage2: make the field private in class A > gives compile error
  495. // Stage3: Add a new aspect whilst there is a compile error !
  496. public void testPr113531() {
  497. initialiseProject("PR113531");
  498. build("PR113531");
  499. assertFalse("build should have compiled ok",
  500. MyTaskListManager.hasErrorMessages());
  501. alter("PR113531","inc1");
  502. build("PR113531");
  503. assertEquals("error message should be 'foo cannot be resolved' ",
  504. "foo cannot be resolved",
  505. ((IMessage)MyTaskListManager.getErrorMessages().get(0))
  506. .getMessage());
  507. alter("PR113531","inc2");
  508. build("PR113531");
  509. assertTrue("There should be no exceptions handled:\n"+MyErrorHandler.getErrorMessages(),
  510. MyErrorHandler.getErrorMessages().isEmpty());
  511. assertEquals("error message should be 'foo cannot be resolved' ",
  512. "foo cannot be resolved",
  513. ((IMessage)MyTaskListManager.getErrorMessages().get(0))
  514. .getMessage());
  515. }
  516. // Stage 1: Compile the 4 files, pack.A2 extends pack.A1 (aspects) where
  517. // A2 uses a protected field in A1 and pack.C2 extends pack.C1 (classes)
  518. // where C2 uses a protected field in C1
  519. // Stage 2: make the field private in class C1 ==> compile errors in C2
  520. // Stage 3: make the field private in aspect A1 whilst there's the compile
  521. // error.
  522. // There shouldn't be a BCExcpetion saying can't find delegate for pack.C2
  523. public void testPr119882() {
  524. initialiseProject("PR119882");
  525. build("PR119882");
  526. assertFalse("build should have compiled ok",MyTaskListManager.hasErrorMessages());
  527. alter("PR119882","inc1");
  528. build("PR119882");
  529. //fullBuild("PR119882");
  530. List errors = MyTaskListManager.getErrorMessages();
  531. assertTrue("Should be at least one error, but got none",errors.size()==1);
  532. assertEquals("error message should be 'i cannot be resolved' ",
  533. "i cannot be resolved",
  534. ((IMessage)errors.get(0))
  535. .getMessage());
  536. alter("PR119882","inc2");
  537. build("PR119882");
  538. assertTrue("There should be no exceptions handled:\n"+MyErrorHandler.getErrorMessages(),
  539. MyErrorHandler.getErrorMessages().isEmpty());
  540. assertEquals("error message should be 'i cannot be resolved' ",
  541. "i cannot be resolved",
  542. ((IMessage)errors.get(0))
  543. .getMessage());
  544. }
  545. public void testPr112736() {
  546. // AjdeInteractionTestbed.VERBOSE = true;
  547. initialiseProject("PR112736");
  548. build("PR112736");
  549. checkWasFullBuild();
  550. String fileC2 = getWorkingDir().getAbsolutePath() + File.separatorChar + "PR112736" + File.separatorChar + "src" + File.separatorChar + "pack" + File.separatorChar + "A.java";
  551. (new File(fileC2)).delete();
  552. alter("PR112736","inc1");
  553. build("PR112736");
  554. checkWasFullBuild();
  555. }
  556. /**
  557. * We have problems with multiple rewrites of a pointcut across incremental builds.
  558. */
  559. public void testPr113257() {
  560. initialiseProject("PR113257");
  561. build("PR113257");
  562. alter("PR113257","inc1");
  563. build("PR113257");
  564. checkWasFullBuild(); // back to the source
  565. alter("PR113257","inc1");
  566. build("PR113257");
  567. }
  568. public void testPr123612() {
  569. initialiseProject("PR123612");
  570. build("PR123612");
  571. alter("PR123612","inc1");
  572. build("PR123612");
  573. checkWasFullBuild(); // back to the source
  574. }
  575. public void testPr128655() {
  576. configureNonStandardCompileOptions("-showWeaveInfo");
  577. initialiseProject("pr128655");
  578. build("pr128655");
  579. List firstBuildMessages = MyTaskListManager.getWeavingMessages();
  580. assertTrue("Should be at least one message about the dec @type, but there were none",firstBuildMessages.size()>0);
  581. alter("pr128655","inc1");
  582. build("pr128655");
  583. checkWasntFullBuild(); // back to the source
  584. List secondBuildMessages = MyTaskListManager.getWeavingMessages();
  585. // check they are the same
  586. for (int i = 0; i < firstBuildMessages.size(); i++) {
  587. IMessage m1 = (IMessage)firstBuildMessages.get(i);
  588. IMessage m2 = (IMessage)secondBuildMessages.get(i);
  589. if (!m1.toString().equals(m2.toString())) {
  590. System.err.println("Message during first build was: "+m1);
  591. System.err.println("Message during second build was: "+m1);
  592. fail("The two messages should be the same, but are not: \n"+m1+"!="+m2);
  593. }
  594. }
  595. }
  596. // Similar to above, but now the annotation is in the default package
  597. public void testPr128655_2() {
  598. configureNonStandardCompileOptions("-showWeaveInfo");
  599. initialiseProject("pr128655_2");
  600. build("pr128655_2");
  601. List firstBuildMessages = MyTaskListManager.getWeavingMessages();
  602. assertTrue("Should be at least one message about the dec @type, but there were none",firstBuildMessages.size()>0);
  603. alter("pr128655_2","inc1");
  604. build("pr128655_2");
  605. checkWasntFullBuild(); // back to the source
  606. List secondBuildMessages = MyTaskListManager.getWeavingMessages();
  607. // check they are the same
  608. for (int i = 0; i < firstBuildMessages.size(); i++) {
  609. IMessage m1 = (IMessage)firstBuildMessages.get(i);
  610. IMessage m2 = (IMessage)secondBuildMessages.get(i);
  611. if (!m1.toString().equals(m2.toString())) {
  612. System.err.println("Message during first build was: "+m1);
  613. System.err.println("Message during second build was: "+m1);
  614. fail("The two messages should be the same, but are not: \n"+m1+"!="+m2);
  615. }
  616. }
  617. }
  618. // test for comment #31 - NPE
  619. public void testPr129163() {
  620. configureBuildStructureModel(true);
  621. initialiseProject("PR129613");
  622. build("PR129613");
  623. alter("PR129613","inc1");
  624. build("PR129613");
  625. assertTrue("There should be no exceptions handled:\n"+MyErrorHandler.getErrorMessages(),
  626. MyErrorHandler.getErrorMessages().isEmpty());
  627. assertEquals("warning message should be 'no match for this type name: File [Xlint:invalidAbsoluteTypeName]' ",
  628. "no match for this type name: File [Xlint:invalidAbsoluteTypeName]",
  629. ((IMessage)MyTaskListManager.getWarningMessages().get(0))
  630. .getMessage());
  631. configureBuildStructureModel(false);
  632. }
  633. // test for comment #0 - adding a comment to a class file shouldn't
  634. // cause us to go back to source and recompile everything. To force this
  635. // to behave like AJDT we need to include the aspect in 'inc1' so that
  636. // when AjState looks at its timestamp it thinks the aspect has been modified.
  637. // The logic within CrosscuttingMembers should then work out correctly
  638. // that there haven't really been any changes within the aspect and so
  639. // we shouldn't go back to source.
  640. public void testPr129163_2() {
  641. // want to behave like AJDT
  642. configureBuildStructureModel(true);
  643. initialiseProject("pr129163_2");
  644. build("pr129163_2");
  645. checkWasFullBuild();
  646. alter("pr129163_2","inc1");
  647. build("pr129163_2");
  648. checkWasntFullBuild(); // shouldn't be a full build because the
  649. // aspect hasn't changed
  650. configureBuildStructureModel(false);
  651. }
  652. // test for comment #6 - simulates AJDT core builder test testBug99133a -
  653. // changing the contents of a method within a class shouldn't force a
  654. // full build of a dependant project. To force this to behave like AJDT
  655. // 'inc1' of the dependant project should just be a copy of 'base' so that
  656. // AjState thinks somethings changed within the dependant project and
  657. // we do a build. Similarly, 'inc1' of the project depended on should
  658. // include the aspect even though nothing's changed within it. This causes
  659. // AjState to think that the aspect has changed. Together its then up to
  660. // logic within CrosscuttingMembers and various equals methods to decide
  661. // correctly that we don't have to go back to source.
  662. public void testPr129163_3() {
  663. configureBuildStructureModel(true);
  664. initialiseProject("PR129163_4");
  665. build("PR129163_4");
  666. checkWasFullBuild(); // should be a full build because initializing project
  667. initialiseProject("PR129163_3");
  668. configureNewProjectDependency("PR129163_3","PR129163_4");
  669. build("PR129163_3");
  670. checkWasFullBuild(); // should be a full build because initializing project
  671. alter("PR129163_4","inc1");
  672. build("PR129163_4");
  673. checkWasntFullBuild(); // should be an incremental build because although
  674. // "inc1" includes the aspect A1.aj, it actually hasn't
  675. // changed so we shouldn't go back to source
  676. alter("PR129163_3","inc1");
  677. build("PR129163_3");
  678. checkWasntFullBuild(); // should be an incremental build because nothing has
  679. // changed within the class and no aspects have changed
  680. // within the running of the test
  681. configureBuildStructureModel(false);
  682. }
  683. public void testPr131505() {
  684. configureNonStandardCompileOptions("-outxml");
  685. initialiseProject("PR131505");
  686. build("PR131505");
  687. checkWasFullBuild();
  688. // aop.xml file shouldn't contain any aspects
  689. checkXMLAspectCount("PR131505","",0);
  690. // add a new aspect A which should be included in the aop.xml file
  691. alter("PR131505","inc1");
  692. build("PR131505");
  693. checkWasFullBuild();
  694. checkXMLAspectCount("PR131505","",1);
  695. checkXMLAspectCount("PR131505","A",1);
  696. // make changes to the class file which shouldn't affect the contents
  697. // of the aop.xml file
  698. alter("PR131505","inc2");
  699. build("PR131505");
  700. checkWasntFullBuild();
  701. checkXMLAspectCount("PR131505","",1);
  702. checkXMLAspectCount("PR131505","A",1);
  703. // add another new aspect A1 which should also be included in the aop.xml file
  704. // ...there should be no duplicate entries in the file
  705. alter("PR131505","inc3");
  706. build("PR131505");
  707. checkWasFullBuild();
  708. checkXMLAspectCount("PR131505","",2);
  709. checkXMLAspectCount("PR131505","A1",1);
  710. checkXMLAspectCount("PR131505","A",1);
  711. // delete aspect A1 which meanss that aop.xml file should only contain A
  712. File a1 = new File(getWorkingDir().getAbsolutePath()
  713. + File.separatorChar + "PR131505" + File.separatorChar + "A1.aj");
  714. a1.delete();
  715. build("PR131505");
  716. checkWasFullBuild();
  717. checkXMLAspectCount("PR131505","",1);
  718. checkXMLAspectCount("PR131505","A1",0);
  719. checkXMLAspectCount("PR131505","A",1);
  720. // add another aspect called A which is in a different package, both A
  721. // and pkg.A should be included in the aop.xml file
  722. alter("PR131505","inc4");
  723. build("PR131505");
  724. checkWasFullBuild();
  725. checkXMLAspectCount("PR131505","",2);
  726. checkXMLAspectCount("PR131505","A",1);
  727. checkXMLAspectCount("PR131505","pkg.A",1);
  728. }
  729. public void testPr133532() {
  730. initialiseProject("PR133532");
  731. build("PR133532");
  732. alter("PR133532","inc1");
  733. build("PR133532");
  734. alter("PR133532","inc2");
  735. build("PR133532");
  736. assertTrue("There should be no errors reported:\n"+MyTaskListManager.getErrorMessages(),
  737. MyTaskListManager.getErrorMessages().isEmpty());
  738. }
  739. public void testPr133532_2() {
  740. initialiseProject("pr133532_2");
  741. build("pr133532_2");
  742. alter("pr133532_2","inc2");
  743. build("pr133532_2");
  744. assertTrue("There should be no errors reported:\n"+MyTaskListManager.getErrorMessages(),
  745. MyTaskListManager.getErrorMessages().isEmpty());
  746. String decisions = AjdeInteractionTestbed.MyStateListener.getDecisions();
  747. String expect="Need to recompile 'A.aj'";
  748. assertTrue("Couldn't find build decision: '"+expect+"' in the list of decisions made:\n"+decisions,
  749. decisions.indexOf(expect)!=-1);
  750. }
  751. public void testPr134541() {
  752. initialiseProject("PR134541");
  753. build("PR134541");
  754. assertEquals("[Xlint:adviceDidNotMatch] should be associated with line 5",5,
  755. ((IMessage)MyTaskListManager.getWarningMessages().get(0)).getSourceLocation().getLine());
  756. alter("PR134541","inc1");
  757. build("PR134541");
  758. checkWasntFullBuild(); // we've only added a white space therefore we
  759. // shouldn't be doing a full build
  760. assertEquals("[Xlint:adviceDidNotMatch] should now be associated with line 7",7,
  761. ((IMessage)MyTaskListManager.getWarningMessages().get(0)).getSourceLocation().getLine());
  762. }
  763. // other possible tests:
  764. // - memory usage (freemem calls?)
  765. // - relationship map
  766. // ---------------------------------------------------------------------------------------------------
  767. /**
  768. * Check we compiled/wove the right number of files, passing '-1' indicates you don't care about
  769. * that number.
  770. */
  771. private void checkCompileWeaveCount(int expCompile,int expWoven) {
  772. if (expCompile!=-1 && getCompiledFiles().size()!=expCompile)
  773. fail("Expected compilation of "+expCompile+" files but compiled "+getCompiledFiles().size()+
  774. "\n"+printCompiledAndWovenFiles());
  775. if (expWoven!=-1 && getWovenClasses().size()!=expWoven)
  776. fail("Expected weaving of "+expWoven+" files but wove "+getWovenClasses().size()+
  777. "\n"+printCompiledAndWovenFiles());
  778. }
  779. private void checkWasntFullBuild() {
  780. assertTrue("Shouldn't have been a full (batch) build",!wasFullBuild());
  781. }
  782. private void checkWasFullBuild() {
  783. assertTrue("Should have been a full (batch) build",wasFullBuild());
  784. }
  785. private void checkForNode(String packageName,String typeName,boolean shouldBeFound) {
  786. IProgramElement ipe = AsmManager.getDefault().getHierarchy().findElementForType(packageName,typeName);
  787. if (shouldBeFound) {
  788. if (ipe==null) printModel();
  789. assertTrue("Should have been able to find '"+packageName+"."+typeName+"' in the asm",ipe!=null);
  790. } else {
  791. if (ipe!=null) printModel();
  792. assertTrue("Should have NOT been able to find '"+packageName+"."+typeName+"' in the asm",ipe==null);
  793. }
  794. }
  795. private void printModel() {
  796. try {
  797. AsmManager.dumptree(AsmManager.getDefault().getHierarchy().getRoot(),0);
  798. } catch (IOException e) {
  799. e.printStackTrace();
  800. }
  801. }
  802. public void build(String projectName) {
  803. constructUpToDateLstFile(projectName,"build.lst");
  804. build(projectName,"build.lst");
  805. if (AjdeInteractionTestbed.VERBOSE) printBuildReport();
  806. }
  807. public void fullBuild(String projectName) {
  808. constructUpToDateLstFile(projectName,"build.lst");
  809. fullBuild(projectName,"build.lst");
  810. if (AjdeInteractionTestbed.VERBOSE) printBuildReport();
  811. }
  812. private void constructUpToDateLstFile(String pname,String configname) {
  813. File projectBase = new File(sandboxDir,pname);
  814. File toConstruct = new File(projectBase,configname);
  815. List filesForCompilation = new ArrayList();
  816. collectUpFiles(projectBase,projectBase,filesForCompilation);
  817. try {
  818. FileOutputStream fos = new FileOutputStream(toConstruct);
  819. DataOutputStream dos = new DataOutputStream(fos);
  820. for (Iterator iter = filesForCompilation.iterator(); iter.hasNext();) {
  821. String file = (String) iter.next();
  822. dos.writeBytes(file+"\n");
  823. }
  824. dos.close();
  825. } catch (IOException ioe) {
  826. ioe.printStackTrace();
  827. }
  828. }
  829. public void checkForError(String anError) {
  830. List messages = MyTaskListManager.getErrorMessages();
  831. for (Iterator iter = messages.iterator(); iter.hasNext();) {
  832. IMessage element = (IMessage) iter.next();
  833. if (element.getMessage().indexOf(anError)!=-1) return;
  834. }
  835. fail("Didn't find the error message:\n'"+anError+"'.\nErrors that occurred:\n"+MyTaskListManager.getErrorMessages());
  836. }
  837. private void collectUpFiles(File location,File base,List collectionPoint) {
  838. String contents[] = location.list();
  839. if (contents==null) return;
  840. for (int i = 0; i < contents.length; i++) {
  841. String string = contents[i];
  842. File f = new File(location,string);
  843. if (f.isDirectory()) {
  844. collectUpFiles(f,base,collectionPoint);
  845. } else if (f.isFile() && (f.getName().endsWith(".aj") || f.getName().endsWith(".java"))) {
  846. String fileFound;
  847. try {
  848. fileFound = f.getCanonicalPath();
  849. String toRemove = base.getCanonicalPath();
  850. if (!fileFound.startsWith(toRemove)) throw new RuntimeException("eh? "+fileFound+" "+toRemove);
  851. collectionPoint.add(fileFound.substring(toRemove.length()+1));//+1 captures extra separator
  852. } catch (IOException e) {
  853. e.printStackTrace();
  854. }
  855. }
  856. }
  857. }
  858. /**
  859. * Fill in the working directory with the project base files,
  860. * from the 'base' folder.
  861. */
  862. protected void initialiseProject(String p) {
  863. File projectSrc=new File(testdataSrcDir+File.separatorChar+p+File.separatorChar+"base");
  864. File destination=new File(getWorkingDir(),p);
  865. if (!destination.exists()) {destination.mkdir();}
  866. copy(projectSrc,destination);//,false);
  867. }
  868. /*
  869. * Applies an overlay onto the project being tested - copying
  870. * the contents of the specified overlay directory.
  871. */
  872. private void alter(String projectName,String overlayDirectory) {
  873. File projectSrc =new File(testdataSrcDir+File.separatorChar+projectName+
  874. File.separatorChar+overlayDirectory);
  875. File destination=new File(getWorkingDir(),projectName);
  876. copy(projectSrc,destination);
  877. }
  878. /**
  879. * Copy the contents of some directory to another location - the
  880. * copy is recursive.
  881. */
  882. private void copy(File from, File to) {
  883. String contents[] = from.list();
  884. if (contents==null) return;
  885. for (int i = 0; i < contents.length; i++) {
  886. String string = contents[i];
  887. File f = new File(from,string);
  888. File t = new File(to,string);
  889. if (f.isDirectory() && !f.getName().startsWith("inc")) {
  890. t.mkdir();
  891. copy(f,t);
  892. } else if (f.isFile()) {
  893. StringBuffer sb = new StringBuffer();
  894. //if (VERBOSE) System.err.println("Copying "+f+" to "+t);
  895. FileUtil.copyFile(f,t,sb);
  896. if (sb.length()!=0) { System.err.println(sb.toString());}
  897. }
  898. }
  899. }
  900. private static void log(String msg) {
  901. if (VERBOSE) System.out.println(msg);
  902. }
  903. /**
  904. * Count the number of times a specified aspectName appears in the default
  905. * aop.xml file and compare with the expected number of occurrences. If just
  906. * want to count the number of aspects mentioned within the file then
  907. * pass "" for the aspectName, otherwise, specify the name of the
  908. * aspect interested in.
  909. */
  910. private void checkXMLAspectCount(String projectName, String aspectName, int expectedOccurrences) {
  911. int aspectCount = 0;
  912. File aopXML = new File(getWorkingDir().getAbsolutePath()
  913. + File.separatorChar + projectName + File.separatorChar
  914. + "bin" + File.separatorChar + "META-INF" + File.separatorChar + "aop.xml");
  915. if (!aopXML.exists()) {
  916. fail("Expected file " + aopXML.getAbsolutePath() + " to exist but it doesn't");
  917. }
  918. try {
  919. BufferedReader reader = new BufferedReader(new FileReader(aopXML));
  920. String line = reader.readLine();
  921. while (line != null) {
  922. if (aspectName.equals("") && line.indexOf("aspect name=\"") != -1) {
  923. aspectCount++;
  924. } else if (line.indexOf("aspect name=\""+aspectName+"\"") != -1) {
  925. aspectCount++;
  926. }
  927. line = reader.readLine();
  928. }
  929. reader.close();
  930. } catch (IOException ie) {
  931. ie.printStackTrace();
  932. }
  933. if (aspectCount != expectedOccurrences) {
  934. fail("Expected aspect " + aspectName + " to appear " + expectedOccurrences + " times" +
  935. " in the aop.xml file but found " + aspectCount + " occurrences");
  936. }
  937. }
  938. }