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 9.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  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. // ALSO SEE AJC
  46. private final static String DEFAULT_LTW_CLASSPATH_ENTRIES = ".." + File.separator + "asm/bin" + File.pathSeparator + ".."
  47. + File.separator + "bridge/bin" + File.pathSeparator + ".." + File.separator + "loadtime/bin" + File.pathSeparator
  48. + ".." + File.separator + "loadtime5/bin" + File.pathSeparator + ".." + File.separator + "weaver/bin"
  49. + File.pathSeparator + ".." + File.separator + "org.aspectj.matcher/bin" + File.pathSeparator + ".." + File.separator
  50. + "lib/bcel/bcel.jar" + File.pathSeparator + ".." + File.separator + "lib/bcel/bcel-verifier.jar";;
  51. private boolean m_verbose = false;
  52. private AjcTest m_ajcTest;
  53. private OutputSpec m_stdErrSpec;
  54. private OutputSpec m_stdOutSpec;
  55. private String m_antFile;
  56. private String m_antTarget;
  57. public void execute(final AjcTestCase inTestCase) {
  58. final String failMessage = "test \"" + m_ajcTest.getTitle() + "\" failed: ";
  59. File buildFile = new File(m_ajcTest.getDir() + File.separatorChar + m_antFile);
  60. if (!buildFile.exists()) {
  61. AjcTestCase.fail(failMessage + "no such Ant file " + buildFile.getAbsolutePath());
  62. }
  63. Project p = new Project();
  64. final StringBuffer stdout = new StringBuffer();
  65. final StringBuffer stderr = new StringBuffer();
  66. final StringBuffer verboseLog = new StringBuffer();
  67. try {
  68. // read the Ant file
  69. p.init();
  70. p.setUserProperty("ant.file", buildFile.getAbsolutePath());
  71. // setup aj.sandbox
  72. p.setUserProperty("aj.sandbox", inTestCase.getSandboxDirectory().getAbsolutePath());
  73. // setup aj.dir "modules" folder
  74. p.setUserProperty("aj.root", new File("..").getAbsolutePath());
  75. // create the test implicit path aj.path that contains the sandbox + regular test infra path
  76. Path path = new Path(p, inTestCase.getSandboxDirectory().getAbsolutePath());
  77. populatePath(path, DEFAULT_LTW_CLASSPATH_ENTRIES);
  78. populatePath(path, AjcTestCase.DEFAULT_CLASSPATH_ENTRIES);
  79. p.addReference("aj.path", path);
  80. p.setBasedir(buildFile.getAbsoluteFile().getParent());
  81. ProjectHelper helper = ProjectHelper.getProjectHelper();
  82. helper.parse(p, buildFile);
  83. // use default target if no target specified
  84. if (m_antTarget == null) {
  85. m_antTarget = p.getDefaultTarget();
  86. }
  87. // make sure we listen for failure
  88. DefaultLogger consoleLogger = new DefaultLogger() {
  89. public void buildFinished(BuildEvent event) {
  90. super.buildFinished(event);
  91. if (event.getException() != null) {
  92. try {
  93. File antout = new File(inTestCase.getSandboxDirectory().getAbsolutePath(), "antout");
  94. if (antout.exists()) {
  95. stdout.append("Forked java command stdout:\n");
  96. System.out.println("Forked java command stdout:");
  97. FileReader fr = new FileReader(antout);
  98. BufferedReader br = new BufferedReader(fr);
  99. String line = br.readLine();
  100. while (line != null) {
  101. stdout.append(line).append("\n");
  102. System.out.println(stdout);
  103. line = br.readLine();
  104. }
  105. fr.close();
  106. }
  107. File anterr = new File(inTestCase.getSandboxDirectory().getAbsolutePath(), "anterr");
  108. if (anterr.exists()) {
  109. stdout.append("Forked java command stderr:\n");
  110. System.out.println("Forked java command stderr:");
  111. FileReader fr = new FileReader(anterr);
  112. BufferedReader br = new BufferedReader(fr);
  113. String line = br.readLine();
  114. while (line != null) {
  115. stdout.append(line).append("\n");
  116. System.out.println(stdout);
  117. line = br.readLine();
  118. }
  119. fr.close();
  120. }
  121. } catch (Exception e) {
  122. System.out.println("Exception whilst loading forked java task output " + e.getMessage() + "\n");
  123. e.printStackTrace();
  124. stdout.append("Exception whilst loading forked java task output " + e.getMessage() + "\n");
  125. }
  126. StringBuffer message = new StringBuffer();
  127. message.append(event.getException().toString()).append("\n");
  128. message.append(verboseLog);
  129. message.append(stdout);
  130. message.append(stderr);
  131. // AjcTestCase.fail(failMessage + "failure " + event.getException());
  132. AjcTestCase.fail(message.toString());
  133. }
  134. }
  135. public void targetFinished(BuildEvent event) {
  136. super.targetFinished(event);
  137. if (event.getException() != null) {
  138. AjcTestCase.fail(failMessage + "failure in '" + event.getTarget() + "' " + event.getException());
  139. }
  140. }
  141. public void messageLogged(BuildEvent event) {
  142. super.messageLogged(event);
  143. Target target = event.getTarget();
  144. if (target != null && m_antTarget.equals(target.getName()) && event.getSource() instanceof Java)
  145. switch (event.getPriority()) {
  146. case Project.MSG_INFO:
  147. stdout.append(event.getMessage()).append('\n');
  148. break;
  149. case Project.MSG_WARN:
  150. stderr.append(event.getMessage()).append('\n');
  151. break;
  152. case Project.MSG_VERBOSE:
  153. verboseLog.append(event.getMessage()).append('\n');
  154. break;
  155. }
  156. }
  157. };
  158. consoleLogger.setErrorPrintStream(System.err);
  159. consoleLogger.setOutputPrintStream(System.out);
  160. consoleLogger.setMessageOutputLevel(m_verbose ? Project.MSG_VERBOSE : Project.MSG_ERR);
  161. p.addBuildListener(consoleLogger);
  162. } catch (Throwable t) {
  163. AjcTestCase.fail(failMessage + "invalid Ant script :" + t.toString());
  164. }
  165. try {
  166. p.setProperty("verbose", "true");
  167. p.fireBuildStarted();
  168. p.executeTarget(m_antTarget);
  169. p.fireBuildFinished(null);
  170. } catch (BuildException e) {
  171. p.fireBuildFinished(e);
  172. } catch (Throwable t) {
  173. AjcTestCase.fail(failMessage + "error when invoking target :" + t.toString());
  174. }
  175. /* See if stdout/stderr matches test specification */
  176. if (m_stdOutSpec != null) {
  177. m_stdOutSpec.matchAgainst(stdout.toString());
  178. }
  179. if (m_stdErrSpec != null) {
  180. String stderr2 = stderr.toString();
  181. // Working around this rediculous message that still comes out of Java7 builds:
  182. if (stderr2.indexOf("Class JavaLaunchHelper is implemented in both")!=-1 && stderr2.indexOf('\n')!=-1) {
  183. stderr2 = stderr2.replaceAll("objc\\[[0-9]*\\]: Class JavaLaunchHelper is implemented in both [^\n]*\n","");
  184. }
  185. m_stdErrSpec.matchAgainst(stderr2);
  186. }
  187. }
  188. public void addStdErrSpec(OutputSpec spec) {
  189. if (m_stdErrSpec != null)
  190. throw new UnsupportedOperationException("only one 'stderr' allowed in 'ant'");
  191. m_stdErrSpec = spec;
  192. }
  193. public void addStdOutSpec(OutputSpec spec) {
  194. if (m_stdOutSpec != null)
  195. throw new UnsupportedOperationException("only one 'stdout' allowed in 'ant'");
  196. m_stdOutSpec = spec;
  197. }
  198. public void setVerbose(String verbose) {
  199. if (verbose != null && "true".equalsIgnoreCase(verbose)) {
  200. m_verbose = true;
  201. }
  202. }
  203. public void setFile(String file) {
  204. m_antFile = file;
  205. }
  206. public void setTarget(String target) {
  207. m_antTarget = target;
  208. }
  209. public void addExpectedMessage(ExpectedMessageSpec message) {
  210. throw new UnsupportedOperationException("don't use 'message' in 'ant' specs.");
  211. }
  212. public void setBaseDir(String dir) {
  213. ;
  214. }
  215. public void setTest(AjcTest test) {
  216. m_ajcTest = test;
  217. }
  218. private static void populatePath(Path path, String pathEntries) {
  219. StringTokenizer st = new StringTokenizer(pathEntries, File.pathSeparator);
  220. while (st.hasMoreTokens()) {
  221. path.setPath(new File(st.nextToken()).getAbsolutePath());
  222. }
  223. }
  224. }