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.

AntSpec.java 11KB

15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  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. * Alexandre Vasseur initial implementation
  11. *******************************************************************************/
  12. package org.aspectj.testing;
  13. import java.io.BufferedReader;
  14. import java.io.File;
  15. import java.io.FileReader;
  16. import java.util.StringTokenizer;
  17. import org.apache.tools.ant.BuildEvent;
  18. import org.apache.tools.ant.BuildException;
  19. import org.apache.tools.ant.DefaultLogger;
  20. import org.apache.tools.ant.Project;
  21. import org.apache.tools.ant.ProjectHelper;
  22. import org.apache.tools.ant.Target;
  23. import org.apache.tools.ant.taskdefs.Java;
  24. import org.apache.tools.ant.types.Path;
  25. import org.aspectj.tools.ajc.AjcTestCase;
  26. /**
  27. * Element that allow to run an abritrary Ant target in a sandbox.
  28. * <p/>
  29. * Such a spec is used in a "<ajc-test><ant file="myAnt.xml" [target="..."] [verbose="true"]/> XML element. The "target" is
  30. * optional. If not set, default myAnt.xml target is used. The "file" file is looked up from the <ajc-test dir="..."/> attribute. If
  31. * "verbose" is set to "true", the ant -v output is piped, else nothing is reported except errors.
  32. * <p/>
  33. * The called Ant target benefits from 2 implicit variables: "${aj.sandbox}" points to the test current sandbox folder. "aj.path" is
  34. * an Ant refid on the classpath formed with the sandbox folder + ltw + the AjcTestCase classpath (ie usually aspectjrt, junit, and
  35. * testing infra)
  36. * <p/>
  37. * Element "<stdout><line text="..">" and "<stderr><line text="..">" can be used. For now a full match is performed on the output of
  38. * the runned target only (not the whole Ant invocation). This is experimental and advised to use a "<junit>" task instead or a
  39. * "<java>" whose main that throws some exception upon failure.
  40. *
  41. *
  42. * @author <a href="mailto:alex AT gnilux DOT com">Alexandre Vasseur</a>
  43. */
  44. public class AntSpec implements ITestStep {
  45. public static final String outputFolders(String... modules) {
  46. StringBuilder s = new StringBuilder();
  47. for (String module: modules) {
  48. s.append(File.pathSeparator + ".." +File.separator + module + File.separator + "target" + File.separator + "classes");
  49. }
  50. return s.toString();
  51. }
  52. // ALSO SEE AJC
  53. private final static String DEFAULT_LTW_CLASSPATH_ENTRIES =
  54. outputFolders("asm", "bridge", "loadtime", "weaver", "org.aspectj.matcher", "bcel-builder");
  55. // private final static String DEFAULT_LTW_CLASSPATH_ENTRIES = ".." + File.separator + "asm/bin" + File.pathSeparator + ".."
  56. // + File.separator + "bridge/bin" + File.pathSeparator + ".." + File.separator + "loadtime/bin" + File.pathSeparator
  57. // + ".." + File.separator + "loadtime5/bin" + File.pathSeparator + ".." + File.separator + "weaver/bin"
  58. // + File.pathSeparator + ".." + File.separator + "org.aspectj.matcher/bin" + File.pathSeparator + ".." + File.separator
  59. // + "lib/bcel/bcel.jar" + File.pathSeparator + ".." + File.separator + "lib/bcel/bcel-verifier.jar";;
  60. private boolean m_verbose = false;
  61. private AjcTest m_ajcTest;
  62. private OutputSpec m_stdErrSpec;
  63. private OutputSpec m_stdOutSpec;
  64. private String m_antFile;
  65. private String m_antTarget;
  66. public void execute(final AjcTestCase inTestCase) {
  67. final String failMessage = "test \"" + m_ajcTest.getTitle() + "\" failed: ";
  68. File buildFile = new File(m_ajcTest.getDir() + File.separatorChar + m_antFile);
  69. if (!buildFile.exists()) {
  70. AjcTestCase.fail(failMessage + "no such Ant file " + buildFile.getAbsolutePath());
  71. }
  72. Project p = new Project();
  73. final StringBuffer stdout = new StringBuffer();
  74. final StringBuffer stderr = new StringBuffer();
  75. final StringBuffer verboseLog = new StringBuffer();
  76. try {
  77. // read the Ant file
  78. p.init();
  79. p.setUserProperty("ant.file", buildFile.getAbsolutePath());
  80. // setup aj.sandbox
  81. p.setUserProperty("aj.sandbox", inTestCase.getSandboxDirectory().getAbsolutePath());
  82. // setup aj.dir "modules" folder
  83. p.setUserProperty("aj.root", new File("..").getAbsolutePath());
  84. // create the test implicit path aj.path that contains the sandbox + regular test infra path
  85. Path path = new Path(p, inTestCase.getSandboxDirectory().getAbsolutePath());
  86. populatePath(path, DEFAULT_LTW_CLASSPATH_ENTRIES);
  87. populatePath(path, AjcTestCase.DEFAULT_CLASSPATH_ENTRIES);
  88. p.addReference("aj.path", path);
  89. p.setBasedir(buildFile.getAbsoluteFile().getParent());
  90. ProjectHelper helper = ProjectHelper.getProjectHelper();
  91. helper.parse(p, buildFile);
  92. // use default target if no target specified
  93. if (m_antTarget == null) {
  94. m_antTarget = p.getDefaultTarget();
  95. }
  96. // make sure we listen for failure
  97. DefaultLogger consoleLogger = new DefaultLogger() {
  98. public void buildFinished(BuildEvent event) {
  99. super.buildFinished(event);
  100. if (event.getException() != null) {
  101. try {
  102. File antout = new File(inTestCase.getSandboxDirectory().getAbsolutePath(), "antout");
  103. if (antout.exists()) {
  104. stdout.append("Forked java command stdout:\n");
  105. System.out.println("Forked java command stdout:");
  106. FileReader fr = new FileReader(antout);
  107. BufferedReader br = new BufferedReader(fr);
  108. String line = br.readLine();
  109. while (line != null) {
  110. stdout.append(line).append("\n");
  111. System.out.println(stdout);
  112. line = br.readLine();
  113. }
  114. fr.close();
  115. }
  116. File anterr = new File(inTestCase.getSandboxDirectory().getAbsolutePath(), "anterr");
  117. if (anterr.exists()) {
  118. stdout.append("Forked java command stderr:\n");
  119. System.out.println("Forked java command stderr:");
  120. FileReader fr = new FileReader(anterr);
  121. BufferedReader br = new BufferedReader(fr);
  122. String line = br.readLine();
  123. while (line != null) {
  124. stdout.append(line).append("\n");
  125. System.out.println(stdout);
  126. line = br.readLine();
  127. }
  128. fr.close();
  129. }
  130. } catch (Exception e) {
  131. System.out.println("Exception whilst loading forked java task output " + e.getMessage() + "\n");
  132. e.printStackTrace();
  133. stdout.append("Exception whilst loading forked java task output " + e.getMessage() + "\n");
  134. }
  135. StringBuffer message = new StringBuffer();
  136. message.append(event.getException().toString()).append("\n");
  137. message.append(verboseLog);
  138. message.append(stdout);
  139. message.append(stderr);
  140. // AjcTestCase.fail(failMessage + "failure " + event.getException());
  141. AjcTestCase.fail(message.toString());
  142. }
  143. }
  144. public void targetFinished(BuildEvent event) {
  145. super.targetFinished(event);
  146. if (event.getException() != null) {
  147. AjcTestCase.fail(failMessage + "failure in '" + event.getTarget() + "' " + event.getException());
  148. }
  149. }
  150. public void messageLogged(BuildEvent event) {
  151. super.messageLogged(event);
  152. Target target = event.getTarget();
  153. if (target != null && m_antTarget.equals(target.getName()) && event.getSource() instanceof Java)
  154. switch (event.getPriority()) {
  155. case Project.MSG_INFO:
  156. stdout.append(event.getMessage()).append('\n');
  157. break;
  158. case Project.MSG_WARN:
  159. stderr.append(event.getMessage()).append('\n');
  160. break;
  161. case Project.MSG_VERBOSE:
  162. verboseLog.append(event.getMessage()).append('\n');
  163. break;
  164. }
  165. }
  166. };
  167. consoleLogger.setErrorPrintStream(System.err);
  168. consoleLogger.setOutputPrintStream(System.out);
  169. consoleLogger.setMessageOutputLevel(m_verbose ? Project.MSG_VERBOSE : Project.MSG_ERR);
  170. p.addBuildListener(consoleLogger);
  171. } catch (Throwable t) {
  172. AjcTestCase.fail(failMessage + "invalid Ant script :" + t.toString());
  173. }
  174. try {
  175. p.setProperty("verbose", "true");
  176. p.fireBuildStarted();
  177. p.executeTarget(m_antTarget);
  178. p.fireBuildFinished(null);
  179. } catch (BuildException e) {
  180. p.fireBuildFinished(e);
  181. } catch (Throwable t) {
  182. AjcTestCase.fail(failMessage + "error when invoking target :" + t.toString());
  183. }
  184. /* See if stdout/stderr matches test specification */
  185. if (m_stdOutSpec != null) {
  186. m_stdOutSpec.matchAgainst(stdout.toString());
  187. }
  188. if (m_stdErrSpec != null) {
  189. String stderr2 = stderr.toString();
  190. // Working around this rediculous message that still comes out of Java7 builds:
  191. if (stderr2.indexOf("Class JavaLaunchHelper is implemented in both")!=-1 && stderr2.indexOf('\n')!=-1) {
  192. stderr2 = stderr2.replaceAll("objc\\[[0-9]*\\]: Class JavaLaunchHelper is implemented in both [^\n]*\n","");
  193. }
  194. // JDK 11 is complaining about illegal reflective calls - temporary measure ignore these - does that get all tests passing and this is the last problem?
  195. if (stderr2.indexOf("WARNING: Illegal reflective access using Lookup on org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor") != -1) {
  196. // WARNING: An illegal reflective access operation has occurred
  197. // WARNING: Illegal reflective access using Lookup on org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor (file:/Users/aclement/gits/org.aspectj/loadtime/bin/) to class java.lang.ClassLoader
  198. // WARNING: Please consider reporting this to the maintainers of org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor
  199. // WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
  200. // WARNING: All illegal access operations will be denied in a future release
  201. stderr2 = stderr2.replaceAll("WARNING: An illegal reflective access operation has occurred\n","");
  202. stderr2 = stderr2.replaceAll("WARNING: Illegal reflective access using Lookup on org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor[^\n]*\n","");
  203. stderr2 = stderr2.replaceAll("WARNING: Please consider reporting this to the maintainers of org.aspectj.weaver.loadtime.ClassLoaderWeavingAdaptor\n","");
  204. stderr2 = stderr2.replaceAll("WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations\n","");
  205. stderr2 = stderr2.replaceAll("WARNING: All illegal access operations will be denied in a future release\n","");
  206. }
  207. m_stdErrSpec.matchAgainst(stderr2);
  208. }
  209. }
  210. public void addStdErrSpec(OutputSpec spec) {
  211. if (m_stdErrSpec != null)
  212. throw new UnsupportedOperationException("only one 'stderr' allowed in 'ant'");
  213. m_stdErrSpec = spec;
  214. }
  215. public void addStdOutSpec(OutputSpec spec) {
  216. if (m_stdOutSpec != null)
  217. throw new UnsupportedOperationException("only one 'stdout' allowed in 'ant'");
  218. m_stdOutSpec = spec;
  219. }
  220. public void setVerbose(String verbose) {
  221. if (verbose != null && "true".equalsIgnoreCase(verbose)) {
  222. m_verbose = true;
  223. }
  224. }
  225. public void setFile(String file) {
  226. m_antFile = file;
  227. }
  228. public void setTarget(String target) {
  229. m_antTarget = target;
  230. }
  231. public void addExpectedMessage(ExpectedMessageSpec message) {
  232. throw new UnsupportedOperationException("don't use 'message' in 'ant' specs.");
  233. }
  234. public void setBaseDir(String dir) {
  235. ;
  236. }
  237. public void setTest(AjcTest test) {
  238. m_ajcTest = test;
  239. }
  240. private static void populatePath(Path path, String pathEntries) {
  241. StringTokenizer st = new StringTokenizer(pathEntries, File.pathSeparator);
  242. while (st.hasMoreTokens()) {
  243. path.setPath(new File(st.nextToken()).getAbsolutePath());
  244. }
  245. }
  246. }