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

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. }