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.

MoreOutputLocationManagerTests.java 16KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. /********************************************************************
  2. * Copyright (c) 2006 Contributors. All rights reserved.
  3. * This program and the accompanying materials are made available
  4. * under the terms of the Eclipse Public License v1.0
  5. * which accompanies this distribution and is available at
  6. * http://eclipse.org/legal/epl-v10.html
  7. *
  8. * Contributors: IBM Corporation - initial API and implementation
  9. * Helen Hawkins - initial version
  10. *******************************************************************/
  11. package org.aspectj.systemtest.incremental.tools;
  12. import java.io.File;
  13. import java.util.ArrayList;
  14. import java.util.Collections;
  15. import java.util.HashSet;
  16. import java.util.Iterator;
  17. import java.util.List;
  18. import java.util.Map;
  19. import java.util.Set;
  20. import org.aspectj.ajde.core.IOutputLocationManager;
  21. import org.aspectj.ajdt.internal.core.builder.AjBuildConfig;
  22. import org.aspectj.ajdt.internal.core.builder.AjState;
  23. import org.aspectj.ajdt.internal.core.builder.IncrementalStateManager;
  24. import org.aspectj.util.FileUtil;
  25. import org.aspectj.weaver.bcel.UnwovenClassFile;
  26. /**
  27. * Similar to OutputLocationManagerTests, however, tests the different scenarios when no outputDir is set but instead there is an
  28. * OutputLocationManager which returns the same output location for all files and resources.
  29. *
  30. * There are eight places where AjBuildConfig.getOutputDir() is called that are tested here:
  31. *
  32. * AjBuildManager.getOutputClassFileName(..) - testCorrectInfoWhenNoOutputPath AjBuildManager.initBcelWorld(..) -
  33. * testPathResolutionWithInpathDirAndNoOutputPath testPathResolutionWithInpathJarAndNoOutputPath AjBuildManager.writeManifest(..) -
  34. * testCopyManifest AjBuildManager.writeOutxml(..) - testOutxml - testOutXmlForAspectsWithDifferentOutputDirs
  35. * AjState.createUnwovenClassFile(..) - testPathResolutionAfterChangeInClassOnInpath AjState.deleteResources(..) -
  36. * testAjStateDeleteResources AjState.maybeDeleteResources(..) - testAjStateDeleteResourcesInInputDir
  37. * AjState.removeAllResultsOfLastBuild(..) - testAllResourcesAreDeletedCorrectlyOnPathChange
  38. * IncrementalStateManager.findStateManagingOutputLocation(..) - testFindStateManagingOutputLocation
  39. *
  40. * The other three places are not tested here because they were implemented when OutputLocationManager was introduced.
  41. *
  42. */
  43. public class MoreOutputLocationManagerTests extends AbstractMultiProjectIncrementalAjdeInteractionTestbed {
  44. private String inpathTestingDir;
  45. private String expectedOutputDir;
  46. @Override
  47. protected void setUp() throws Exception {
  48. super.setUp();
  49. initialiseProject("inpathTesting");
  50. inpathTestingDir = getWorkingDir() + File.separator + "inpathTesting";
  51. expectedOutputDir = inpathTestingDir + File.separator + "bin";
  52. configureOutputLocationManager("inpathTesting", new SingleDirOutputLocMgr(inpathTestingDir));
  53. }
  54. /**
  55. * Tests that the UnwovenClassFiles have the correct path when there is no outputDir but there is an OutputLocationManager. Is a
  56. * simple project that has no inpath setting
  57. */
  58. public void testCorrectInfoWhenNoOutputPath() {
  59. build("inpathTesting");
  60. AjState state = getState();
  61. Map<String,File> classNameToFileMap = state.getClassNameToFileMap();
  62. assertFalse("expected there to be classes ", classNameToFileMap.isEmpty());
  63. Set<Map.Entry<String,File>> entrySet = classNameToFileMap.entrySet();
  64. for (Map.Entry<String, File> entry : entrySet) {
  65. String className = entry.getKey();
  66. String fullClassName = expectedOutputDir + File.separator + className.replace('.', File.separatorChar) + ".class";
  67. File file = entry.getValue();
  68. assertEquals("expected file to have path \n" + fullClassName + ", but" + " found path \n" + file.getAbsolutePath(),
  69. fullClassName, file.getAbsolutePath());
  70. }
  71. }
  72. /**
  73. * Tests that can retieve the state that manages a given output location when there is no outputDir set
  74. */
  75. public void testFindStateManagingOutputLocation() {
  76. build("inpathTesting");
  77. AjState state = IncrementalStateManager.findStateManagingOutputLocation(new File(expectedOutputDir));
  78. assertNotNull("Expected to find a state that managed output location " + expectedOutputDir + ", but did not", state);
  79. }
  80. /**
  81. * Tests that the UnwovenClassFiles corresponding to classes on the inpath have the correct class name when there is no output
  82. * directory (ultimately tests AjBuildManager.initBcelWorld() when there is a jar on the inpath). Only does one build.
  83. */
  84. public void testPathResolutionWithInpathDirAndNoOutputPath() {
  85. String inpathDir = inpathTestingDir + File.separator + "injarBin" + File.separator + "pkg";
  86. addInpathEntry(inpathDir);
  87. build("inpathTesting");
  88. // expect to compile the aspect in 'inpathTesting' project and weave
  89. // both the aspect and the class on the inpath.
  90. checkCompileWeaveCount("inpathTesting", 1, 2);
  91. // get hold of the state for this project - expect to find one
  92. AjState state = getState();
  93. // the classes onthe inpath are recorded against the AjBuildManager
  94. // (they are deleted from the ajstate whilst cleaning up after a build)
  95. Map<String,List<UnwovenClassFile>> binarySources = state.getAjBuildManager().getBinarySourcesForThisWeave();
  96. assertFalse("expected there to be binary sources from the inpath setting but didn't find any", binarySources.isEmpty());
  97. List<UnwovenClassFile> unwovenClassFiles = binarySources.get(inpathDir + File.separator + "InpathClass.class");
  98. List<String> fileNames = new ArrayList<>();
  99. // the unwovenClassFiles should have filenames that point to the output dir
  100. // (which in this case is the sandbox dir) and not where they came from.
  101. for (UnwovenClassFile ucf: unwovenClassFiles) {
  102. if (!ucf.getFilename().contains(expectedOutputDir)) {
  103. fileNames.add(ucf.getFilename());
  104. }
  105. }
  106. assertTrue("expected to find UnwovenClassFile from directory\n" + expectedOutputDir + ", \n but found files " + fileNames,
  107. fileNames.isEmpty());
  108. }
  109. /**
  110. * Tests that the UnwovenClassFiles corresponding to classes on the inpath have the correct class name when there is no output
  111. * directory (ultimately tests AjState.createUnwovenClassFile(BinarySourceFile) and ensures the unwovenClassFile has the correct
  112. * name. Makes a change to a class file on the inpath to ensure we enter this method (there is a check that says are we the
  113. * first build))
  114. */
  115. public void testPathResolutionAfterChangeInClassOnInpath() throws Exception {
  116. String inpathDir = inpathTestingDir + File.separator + "injarBin" + File.separator + "pkg";
  117. addInpathEntry(inpathDir);
  118. build("inpathTesting");
  119. // build again so that we enter
  120. // AjState.createUnwovenClassFile(BinarySourceFile)
  121. File from = new File(testdataSrcDir + File.separatorChar + "inpathTesting" + File.separatorChar + "newInpathClass"
  122. + File.separatorChar + "InpathClass.class");
  123. File destination = new File(inpathDir + File.separatorChar + "InpathClass.class");
  124. FileUtil.copyFile(from, destination);
  125. // get hold of the state for this project - expect to find one
  126. AjState state = getState();
  127. AjBuildConfig buildConfig = state.getBuildConfig();
  128. state.prepareForNextBuild(buildConfig);
  129. Map<String, List<UnwovenClassFile>> binarySources = state.getBinaryFilesToCompile(true);
  130. assertFalse("expected there to be binary sources from the inpath setting but didn't find any", binarySources.isEmpty());
  131. List<UnwovenClassFile> unwovenClassFiles = binarySources.get(inpathDir + File.separator + "InpathClass.class");
  132. List<String> fileNames = new ArrayList<>();
  133. // the unwovenClassFiles should have filenames that point to the output dir
  134. // (which in this case is the sandbox dir) and not where they came from.
  135. for (UnwovenClassFile ucf: unwovenClassFiles) {
  136. if (!ucf.getFilename().contains(expectedOutputDir)) {
  137. fileNames.add(ucf.getFilename());
  138. }
  139. }
  140. assertTrue("expected to find UnwovenClassFile from directory\n" + expectedOutputDir + ", \n but found files " + fileNames,
  141. fileNames.isEmpty());
  142. }
  143. /**
  144. * Tests that the UnwovenClassFiles corresponding to jars on the inpath have the correct class name when there is no output path
  145. * (ultimately tests AjBuildManager.initBcelWorld() when there is a jar on the inpath). Only does one build.
  146. */
  147. public void testPathResolutionWithInpathJarAndNoOutputPath() {
  148. String inpathDir = inpathTestingDir + File.separator + "inpathJar.jar";
  149. addInpathEntry(inpathDir);
  150. build("inpathTesting");
  151. // expect to compile the aspect in 'inpathTesting' project and weave
  152. // both the aspect and the class in the jar on the inpath.
  153. checkCompileWeaveCount("inpathTesting", 1, 2);
  154. AjState state = getState();
  155. // tests AjState.createUnwovenClassFile(BinarySourceFile)
  156. Map<String,List<UnwovenClassFile>> binarySources = state.getAjBuildManager().getBinarySourcesForThisWeave();
  157. assertFalse("expected there to be binary sources from the inpath setting but didn't find any", binarySources.isEmpty());
  158. List<UnwovenClassFile> unwovenClassFiles = binarySources.get(inpathDir);
  159. List<String> fileNames = new ArrayList<>();
  160. for (UnwovenClassFile ucf: unwovenClassFiles) {
  161. if (!ucf.getFilename().contains(expectedOutputDir)) {
  162. fileNames.add(ucf.getFilename());
  163. }
  164. }
  165. assertTrue("expected to find UnwovenClassFile from directory\n" + expectedOutputDir + ", \n but found files " + fileNames,
  166. fileNames.isEmpty());
  167. }
  168. /**
  169. * A manifest file is in the jar on the inpath - check that it's copied to the correct place
  170. */
  171. public void testCopyManifest() {
  172. String inpathDir = inpathTestingDir + File.separator + "inpathJar.jar";
  173. addInpathEntry(inpathDir);
  174. build("inpathTesting");
  175. String resource = expectedOutputDir + File.separator + "META-INF" + File.separator + "MANIFEST.MF";
  176. File f = new File(resource);
  177. assertTrue("expected file " + resource + " to exist but it did not", f.exists());
  178. }
  179. /**
  180. * "resources" are contained within inpath jars - check that a text file contained within a jar is copied and then deleted
  181. * correctly. Essentially tests AjState.deleteResources().
  182. */
  183. // see 243376: for now don't do this, waste of cpu - ajdt better for handling resources - but is that true for inpath resources?
  184. // public void testAjStateDeleteResources() {
  185. // String inpathDir = inpathTestingDir + File.separator + "inpathJar.jar";
  186. // addInpathEntry(inpathDir);
  187. //
  188. // build("inpathTesting");
  189. //
  190. // AjState state = getState();
  191. //
  192. // String resource = expectedOutputDir + File.separator + "inpathResource.txt";
  193. // File f = new File(resource);
  194. // assertTrue("expected file " + resource + " to exist but it did not",f.exists());
  195. // // this call should delete the resources
  196. // state.getFilesToCompile(true);
  197. // assertFalse("did not expect the file " + resource + " to exist but it does",f.exists());
  198. // }
  199. /**
  200. * Can set to copy resources that are in inpath dirs - check that a text file contained within such a dir is copied and then
  201. * deleted correctly. Essentially tests AjState.maybeDeleteResources().
  202. */
  203. // see 243376: for now don't do this, waste of cpu - ajdt better for handling resources - but is that true for inpath resources?
  204. // public void testAjStateDeleteResourcesInInputDir() {
  205. // // temporary problem with this on linux, think it is a filesystem lastmodtime issue
  206. // if (System.getProperty("os.name","").toLowerCase().equals("linux")) return;
  207. // if (System.getProperty("os.name","").toLowerCase().indexOf("mac")!=-1) return;
  208. //
  209. // AjBuildManager.COPY_INPATH_DIR_RESOURCES = true;
  210. // try {
  211. // String inpathDir = inpathTestingDir + File.separator + "injarBin"
  212. // + File.separator + "pkg";
  213. // addInpathEntry(inpathDir);
  214. // build("inpathTesting");
  215. // AjState state = getState();
  216. // String resource = "inDirResource.txt";
  217. // assertTrue("expected state to have resource " + resource + "but it did not",
  218. // state.hasResource(resource));
  219. // // this call should delete the resources - tests AjState.deleteResources()
  220. // state.getFilesToCompile(true);
  221. // assertFalse("did not expect state to have resource " + resource +
  222. // " but found that it did", state.hasResource(resource));
  223. // } finally {
  224. // AjBuildManager.COPY_INPATH_DIR_RESOURCES = false;
  225. // }
  226. //
  227. // }
  228. /**
  229. * Changing inpath entry from a jar to a directory between builds means that AjState should realise somethings changed. This
  230. * causes all resources (Manifest and txt files) to be deleted. Also should be a full build. Essentially tests
  231. * AjState.removeAllResultsFromLastBuild().
  232. */
  233. public void testAllResourcesAreDeletedCorrectlyOnPathChange() {
  234. String inpathJar = inpathTestingDir + File.separator + "inpathJar.jar";
  235. addInpathEntry(inpathJar);
  236. build("inpathTesting");
  237. String resource = expectedOutputDir + File.separator + "inpathResource.txt";
  238. File f = new File(resource);
  239. assertTrue("expected file " + resource + " to exist but it did not", f.exists());
  240. // this should force a change and the file is deleted
  241. // tests AjState.removeAllResultsFromLastBuild()
  242. addInpathEntry(null);
  243. build("inpathTesting");
  244. assertFalse("did not expect the file " + resource + " to exist but it does", f.exists());
  245. checkWasFullBuild();
  246. }
  247. public void testOutxml() {
  248. configureNonStandardCompileOptions("inpathTesting", "-outxml");
  249. build("inpathTesting");
  250. String resource = expectedOutputDir + File.separator + "META-INF" + File.separator + "aop-ajc.xml";
  251. File f = new File(resource);
  252. assertTrue("expected file " + resource + " to exist but it did not", f.exists());
  253. }
  254. public void testAspectsRecordedOnlyOnceInState() {
  255. configureNonStandardCompileOptions("inpathTesting", "-outxml");
  256. build("inpathTesting");
  257. AjState state = getState();
  258. Map<String,char[]> m = state.getAspectNamesToFileNameMap();
  259. assertEquals("Expected only one aspect recored in the state but found " + m.size(), 1, m.size());
  260. build("inpathTesting");
  261. m = state.getAspectNamesToFileNameMap();
  262. assertEquals("Expected only one aspect recored in the state but found " + m.size(), 1, m.size());
  263. }
  264. private AjState getState() {
  265. // get hold of the state for this project - expect to find one
  266. AjState state = IncrementalStateManager.retrieveStateFor(inpathTestingDir);
  267. assertNotNull("expected to find AjState for build config " + inpathTestingDir + " but didn't", state);
  268. return state;
  269. }
  270. private void addInpathEntry(String entry) {
  271. if (entry == null) {
  272. configureInPath("inpathTesting", (Set)null);
  273. return;
  274. }
  275. File f = new File(entry);
  276. Set<File> s = new HashSet<>();
  277. s.add(f);
  278. configureInPath("inpathTesting", s);
  279. }
  280. /**
  281. * Sends all output to the same directory
  282. */
  283. private static class SingleDirOutputLocMgr implements IOutputLocationManager {
  284. private File classOutputLoc;
  285. private File resourceOutputLoc;
  286. private String testProjectOutputPath;
  287. private List<File> allOutputLocations;
  288. private File outputLoc;
  289. public SingleDirOutputLocMgr(String testProjectPath) {
  290. this.testProjectOutputPath = testProjectPath + File.separator + "bin";
  291. outputLoc = new File(testProjectOutputPath);
  292. allOutputLocations = new ArrayList<>();
  293. allOutputLocations.add(outputLoc);
  294. }
  295. @Override
  296. public File getOutputLocationForClass(File compilationUnit) {
  297. return outputLoc;
  298. }
  299. @Override
  300. public Map<File,String> getInpathMap() {
  301. return Collections.emptyMap();
  302. }
  303. @Override
  304. public File getOutputLocationForResource(File resource) {
  305. return outputLoc;
  306. }
  307. @Override
  308. public List<File> getAllOutputLocations() {
  309. return allOutputLocations;
  310. }
  311. @Override
  312. public File getDefaultOutputLocation() {
  313. return outputLoc;
  314. }
  315. @Override
  316. public void reportFileWrite(String outputfile, int filetype) {
  317. }
  318. @Override
  319. public void reportFileRemove(String outputfile, int filetype) {
  320. }
  321. @Override
  322. public String getSourceFolderForFile(File sourceFile) {
  323. return null; // no impl
  324. }
  325. @Override
  326. public int discoverChangesSince(File dir, long buildtime) {
  327. return 0; // no impl
  328. }
  329. }
  330. }