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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  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 org.aspectj.tools.ajc.AjcTestCase;
  14. import org.apache.tools.ant.Project;
  15. import org.apache.tools.ant.ProjectHelper;
  16. import org.apache.tools.ant.DefaultLogger;
  17. import org.apache.tools.ant.BuildException;
  18. import org.apache.tools.ant.BuildEvent;
  19. import org.apache.tools.ant.Target;
  20. import org.apache.tools.ant.taskdefs.Java;
  21. import org.apache.tools.ant.types.Path;
  22. import java.io.File;
  23. import java.util.StringTokenizer;
  24. /**
  25. * Element that allow to run an abritrary Ant target in a sandbox.
  26. * <p/>
  27. * Such a spec is used in a "<ajc-test><ant file="myAnt.xml" [target="..."] [verbose="true"]/> XML element.
  28. * The "target" is optional. If not set, default myAnt.xml target is used.
  29. * The "file" file is looked up from the <ajc-test dir="..."/> attribute.
  30. * If "verbose" is set to "true", the ant -v output is piped, else nothing is reported except errors.
  31. * <p/>
  32. * The called Ant target benefits from 2 implicit variables:
  33. * "${aj.sandbox}" points to the test current sandbox folder.
  34. * "aj.path" is an Ant refid on the classpath formed with the sandbox folder + ltw + the AjcTestCase classpath
  35. * (ie usually aspectjrt, junit, and testing infra)
  36. * <p/>
  37. * Element "<stdout><line text="..">" and "<stderr><line text="..">" can be used. For now a full match
  38. * is performed on the output of the runned target only (not the whole Ant invocation). This is experimental
  39. * and advised to use a "<junit>" task instead or a "<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. private final static String DEFAULT_LTW_CLASSPATH_ENTRIES =
  46. ".." + File.separator + "asm/bin"
  47. + File.pathSeparator + ".." + File.separator + "bridge/bin"
  48. + File.pathSeparator + ".." + File.separator + "loadtime/bin"
  49. + File.pathSeparator + ".." + File.separator + "loadtime5/bin"
  50. + File.pathSeparator + ".." + File.separator + "weaver/bin"
  51. + File.pathSeparator + ".." + File.separator + "lib/bcel/bcel.jar"
  52. + File.pathSeparator + ".." + File.separator + "lib/asm/asm-aj.jar";
  53. private boolean m_verbose = false;
  54. private AjcTest m_ajcTest;
  55. private OutputSpec m_stdErrSpec;
  56. private OutputSpec m_stdOutSpec;
  57. private String m_antFile;
  58. private String m_antTarget;
  59. public void execute(AjcTestCase inTestCase) {
  60. final String failMessage = "test \"" + m_ajcTest.getTitle() + "\" failed: ";
  61. File buildFile = new File(m_ajcTest.getDir() + File.separatorChar + m_antFile);
  62. if (!buildFile.exists()) {
  63. AjcTestCase.fail(failMessage + "no such Ant file " + buildFile.getAbsolutePath());
  64. }
  65. Project p = new Project();
  66. final StringBuffer stdout = new StringBuffer();
  67. final StringBuffer stderr = new StringBuffer();
  68. final StringBuffer verboseLog = new StringBuffer();
  69. try {
  70. // read the Ant file
  71. p.init();
  72. p.setUserProperty("ant.file", buildFile.getAbsolutePath());
  73. // setup aj.sandbox
  74. p.setUserProperty("aj.sandbox", inTestCase.getSandboxDirectory().getAbsolutePath());
  75. // setup aj.dir "modules" folder
  76. p.setUserProperty("aj.root", new File("..").getAbsolutePath());
  77. // create the test implicit path aj.path that contains the sandbox + regular test infra path
  78. Path path = new Path(p, inTestCase.getSandboxDirectory().getAbsolutePath());
  79. populatePath(path, DEFAULT_LTW_CLASSPATH_ENTRIES);
  80. populatePath(path, AjcTestCase.DEFAULT_CLASSPATH_ENTRIES);
  81. p.addReference("aj.path", path);
  82. ProjectHelper helper = ProjectHelper.getProjectHelper();
  83. helper.parse(p, buildFile);
  84. // use default target if no target specified
  85. if (m_antTarget == null) {
  86. m_antTarget = p.getDefaultTarget();
  87. }
  88. // make sure we listen for failure
  89. DefaultLogger consoleLogger = new DefaultLogger() {
  90. public void buildFinished(BuildEvent event) {
  91. super.buildFinished(event);
  92. if (event.getException() != null) {
  93. StringBuffer message = new StringBuffer();
  94. message.append(event.getException().toString()).append("\n");
  95. message.append(verboseLog);
  96. message.append(stdout);
  97. message.append(stderr);
  98. // AjcTestCase.fail(failMessage + "failure " + event.getException());
  99. AjcTestCase.fail(message.toString());
  100. }
  101. }
  102. public void targetFinished(BuildEvent event) {
  103. super.targetFinished(event);
  104. if (event.getException() != null) {
  105. AjcTestCase.fail(failMessage + "failure in '" + event.getTarget() + "' " + event.getException());
  106. }
  107. }
  108. public void messageLogged(BuildEvent event) {
  109. super.messageLogged(event);
  110. Target target = event.getTarget();
  111. if (target != null && m_antTarget.equals(target.getName()) && event.getSource() instanceof Java)
  112. switch(event.getPriority()) {
  113. case Project.MSG_INFO:
  114. stdout.append(event.getMessage()).append('\n');
  115. break;
  116. case Project.MSG_WARN:
  117. stderr.append(event.getMessage()).append('\n');
  118. break;
  119. case Project.MSG_VERBOSE:
  120. verboseLog.append(event.getMessage()).append('\n');
  121. break;
  122. }
  123. }
  124. };
  125. consoleLogger.setErrorPrintStream(System.err);
  126. consoleLogger.setOutputPrintStream(System.out);
  127. consoleLogger.setMessageOutputLevel(m_verbose?Project.MSG_VERBOSE:Project.MSG_ERR);
  128. p.addBuildListener(consoleLogger);
  129. } catch (Throwable t) {
  130. AjcTestCase.fail(failMessage + "invalid Ant script :" + t.toString());
  131. }
  132. try {
  133. p.fireBuildStarted();
  134. p.executeTarget(m_antTarget);
  135. p.fireBuildFinished(null);
  136. } catch (BuildException e) {
  137. p.fireBuildFinished(e);
  138. } catch (Throwable t) {
  139. AjcTestCase.fail(failMessage + "error when invoking target :" + t.toString());
  140. }
  141. /* See if stdout/stderr matches test specification */
  142. if (m_stdOutSpec != null) {
  143. m_stdOutSpec.matchAgainst(stdout.toString());
  144. }
  145. if (m_stdErrSpec != null) {
  146. m_stdErrSpec.matchAgainst(stderr.toString());
  147. }
  148. }
  149. public void addStdErrSpec(OutputSpec spec) {
  150. if (m_stdErrSpec!=null)
  151. throw new UnsupportedOperationException("only one 'stderr' allowed in 'ant'");
  152. m_stdErrSpec = spec;
  153. }
  154. public void addStdOutSpec(OutputSpec spec) {
  155. if (m_stdOutSpec!=null)
  156. throw new UnsupportedOperationException("only one 'stdout' allowed in 'ant'");
  157. m_stdOutSpec = spec;
  158. }
  159. public void setVerbose(String verbose) {
  160. if (verbose != null && "true".equalsIgnoreCase(verbose)) {
  161. m_verbose = true;
  162. }
  163. }
  164. public void setFile(String file) {
  165. m_antFile = file;
  166. }
  167. public void setTarget(String target) {
  168. m_antTarget = target;
  169. }
  170. public void addExpectedMessage(ExpectedMessageSpec message) {
  171. throw new UnsupportedOperationException("don't use 'message' in 'ant' specs.");
  172. }
  173. public void setBaseDir(String dir) {
  174. ;
  175. }
  176. public void setTest(AjcTest test) {
  177. m_ajcTest = test;
  178. }
  179. private static void populatePath(Path path, String pathEntries) {
  180. StringTokenizer st = new StringTokenizer(pathEntries, File.pathSeparator);
  181. while (st.hasMoreTokens()) {
  182. path.setPath(new File(st.nextToken()).getAbsolutePath());
  183. }
  184. }
  185. }