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.

AjctestsAdapter.java 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. /* *******************************************************************
  2. * Copyright (c) 2003 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://www.eclipse.org/legal/epl-v10.html
  8. *
  9. * Contributors:
  10. * Wes Isberg initial implementation
  11. * ******************************************************************/
  12. package org.aspectj.testing.drivers;
  13. import java.io.File;
  14. import java.util.Arrays;
  15. import java.util.Collections;
  16. import java.util.HashMap;
  17. import java.util.Map;
  18. import org.aspectj.ajdt.internal.core.builder.AjState;
  19. import org.aspectj.bridge.IMessage;
  20. import org.aspectj.bridge.IMessageHolder;
  21. import org.aspectj.bridge.MessageHandler;
  22. import org.aspectj.bridge.MessageUtil;
  23. import org.aspectj.testing.harness.bridge.AjcTest;
  24. import org.aspectj.testing.harness.bridge.AjcTest.Spec;
  25. import org.aspectj.testing.harness.bridge.RunSpecIterator;
  26. import org.aspectj.testing.harness.bridge.Sandbox;
  27. import org.aspectj.testing.harness.bridge.Validator;
  28. import org.aspectj.testing.run.IRunIterator;
  29. import org.aspectj.testing.run.RunStatus;
  30. import org.aspectj.testing.run.Runner;
  31. import junit.framework.Test;
  32. import junit.framework.TestCase;
  33. import junit.framework.TestResult;
  34. import junit.framework.TestSuite;
  35. /*
  36. * Adapt Harness tests to JUnit driver. This renders suite files as TestSuite
  37. * and AjcTest as TestCase. When run, aborts are reported as error and fails as
  38. * failures, with all messages stuffed into the one JUnit exception message.
  39. * Test options are supported, but no harness options. The TestSuite
  40. * implementation prevents us from re-running tests. In the Eclipse JUnit test
  41. * runner, the tests display hierarchically and with annotations and with
  42. * messages. You can stop the tests, but not traverse to the source or re-run
  43. * the test.
  44. */
  45. public class AjctestsAdapter extends TestSuite {
  46. public static final String VERBOSE_NAME = AjctestsAdapter.class.getName()
  47. + ".VERBOSE";
  48. private static final boolean VERBOSE = HarnessJUnitUtil
  49. .readBooleanSystemProperty(VERBOSE_NAME);
  50. /**
  51. * Factory to make and populate suite without options.
  52. *
  53. * @param suitePath
  54. * the String path to a harness suite file
  55. * @return AjctestJUnitSuite populated with tests
  56. */
  57. public static AjctestsAdapter make(String suitePath) {
  58. return make(suitePath, null);
  59. }
  60. /**
  61. * Factory to make and populate suite
  62. *
  63. * @param suitePath
  64. * the String path to a harness suite file
  65. * @param options
  66. * the String[] options to use when creating tests
  67. * @return AjctestJUnitSuite populated with tests
  68. */
  69. public static AjctestsAdapter make(String suitePath, String[] options) {
  70. AjctestsAdapter result = new AjctestsAdapter(suitePath, options);
  71. AjcTest.Spec[] tests = AjcTest.Suite.getTests(result.getSpec());
  72. if (VERBOSE) {
  73. log("loading " + tests.length + " tests in " + suitePath);
  74. }
  75. for (Spec ajcTest : tests) {
  76. result.addTest(new AjcTestSpecAsTest(ajcTest, result));
  77. }
  78. return result;
  79. }
  80. private static void log(String message) {
  81. System.err.println(message);
  82. System.err.flush();
  83. }
  84. private final String suitePath;
  85. private final String[] options;
  86. private AjcTest.Suite.Spec spec;
  87. private Runner runner;
  88. private Validator validator;
  89. private IMessageHolder holder;
  90. private Sandbox sandbox;
  91. private File suiteDir;
  92. private String name;
  93. private AjctestsAdapter(String suitePath, String[] options) {
  94. this.suitePath = suitePath;
  95. String[] opts = new String[0];
  96. if (!HarnessJUnitUtil.isEmpty(options)) {
  97. opts = new String[options.length];
  98. System.arraycopy(options, 0, opts, 0, opts.length);
  99. }
  100. this.options = opts;
  101. }
  102. @Override
  103. public void addTest(Test test) {
  104. if (!(test instanceof AjcTestSpecAsTest)) {
  105. String m = "expecting AjcTestSpecAsTest, got "
  106. + (null == test ? "null test" : test.getClass().getName()
  107. + ": " + test);
  108. throw new IllegalArgumentException(m);
  109. }
  110. super.addTest(test);
  111. }
  112. @SuppressWarnings("rawtypes")
  113. @Override
  114. public void addTestSuite(Class testClass) {
  115. throw new Error("unimplemented");
  116. }
  117. @Override
  118. public String getName() {
  119. if (null == name) {
  120. name = HarnessJUnitUtil.cleanTestName(suitePath
  121. + Arrays.asList(options));
  122. }
  123. return name;
  124. }
  125. /**
  126. * Callback from test to run it using suite-wide holder, etc. The caller is
  127. * responsible for calling result.startTest(test) and result.endTest(test);
  128. *
  129. * @param test
  130. * the AjcTestSpecAsTest to run
  131. * @param result
  132. * the TestResult for any result messages (may be null)
  133. */
  134. protected void runTest(AjcTestSpecAsTest test, TestResult result) {
  135. final Runner runner = getRunner();
  136. final Sandbox sandbox = getSandbox();
  137. final Validator validator = getValidator();
  138. int numIncomplete = 0;
  139. final RunStatus status = new RunStatus(new MessageHandler(), runner);
  140. status.setIdentifier(test.toString());
  141. try {
  142. IMessageHolder holder = getHolder();
  143. holder.clearMessages();
  144. IRunIterator steps = test.spec.makeRunIterator(sandbox, validator);
  145. if (0 < holder.numMessages(IMessage.ERROR, true)) {
  146. MessageUtil.handleAll(status, holder, IMessage.INFO, true,
  147. false);
  148. } else {
  149. runner.runIterator(steps, status, null);
  150. }
  151. if (steps instanceof RunSpecIterator) {
  152. numIncomplete = ((RunSpecIterator) steps).getNumIncomplete();
  153. }
  154. } finally {
  155. try {
  156. // reportResult handles null TestResult
  157. HarnessJUnitUtil
  158. .reportResult(null, status, test, numIncomplete);
  159. } finally {
  160. validator.deleteTempFiles(true);
  161. }
  162. }
  163. }
  164. private File getSuiteDir() {
  165. if (null == suiteDir) {
  166. File file = new File(suitePath);
  167. file = file.getParentFile();
  168. if (null == file) {
  169. file = new File(".");
  170. }
  171. suiteDir = file;
  172. }
  173. return suiteDir;
  174. }
  175. private Validator getValidator() {
  176. if (null == validator) {
  177. validator = new Validator(getHolder());
  178. // XXX lock if keepTemp?
  179. }
  180. return validator;
  181. }
  182. private Runner getRunner() {
  183. if (null == runner) {
  184. runner = new Runner();
  185. }
  186. return runner;
  187. }
  188. private IMessageHolder getHolder() {
  189. if (null == holder) {
  190. holder = new MessageHandler();
  191. }
  192. return holder;
  193. }
  194. private AjcTest.Suite.Spec getSpec() {
  195. if (null == spec) {
  196. IMessageHolder holder = getHolder();
  197. spec = HarnessJUnitUtil.getSuiteSpec(suitePath, options,
  198. getHolder());
  199. if (VERBOSE && holder.hasAnyMessage(null, true)) {
  200. MessageUtil.print(System.err, holder, "skip ",
  201. MessageUtil.MESSAGE_MOST);
  202. }
  203. holder.clearMessages();
  204. }
  205. return spec;
  206. }
  207. private Sandbox getSandbox() {
  208. if (null == sandbox) {
  209. sandbox = new Sandbox(spec.getSuiteDirFile(), getValidator());
  210. }
  211. return sandbox;
  212. }
  213. /**
  214. * Wrap AjcTest.Spec for lookup by description
  215. *
  216. * @author wes
  217. */
  218. public static class SpecTests {
  219. private static final HashMap<String,SpecTests> TESTS = new HashMap<>();
  220. // private static void putSpecTestsFor(String id, SpecTests tests) {
  221. // TESTS.put(id, tests);
  222. // }
  223. private static SpecTests getSpecTestsFor(String id) {
  224. SpecTests result = TESTS.get(id);
  225. if (null == result) {
  226. throw new Error("no tests found for " + id);
  227. }
  228. return result;
  229. }
  230. // ------------------------------------
  231. final AjctestsAdapter mAjctestsAdapter;
  232. private final Map<String,AjcTest.Spec> mDescriptionToAjcTestSpec;
  233. // ------------------------------------
  234. private SpecTests(AjctestsAdapter ajctestsAdapter, AjcTest.Spec[] tests) {
  235. mAjctestsAdapter = ajctestsAdapter;
  236. Map<String,AjcTest.Spec> map = new HashMap<>();
  237. for (Spec test : tests) {
  238. map.put(test.getDescription(), test);
  239. }
  240. mDescriptionToAjcTestSpec = Collections.unmodifiableMap(map);
  241. }
  242. /**
  243. * @param description
  244. * the String description of the test
  245. * @throws IllegalArgumentException
  246. * if testName is not found
  247. */
  248. protected void runTest(String description) {
  249. AjcTest.Spec spec = getSpec(description);
  250. AjctestsAdapter.AjcTestSpecAsTest ajcTestAsSpec = new AjctestsAdapter.AjcTestSpecAsTest(
  251. spec, mAjctestsAdapter);
  252. // runTest handles null TestResult
  253. mAjctestsAdapter.runTest(ajcTestAsSpec, null);
  254. }
  255. /**
  256. * @param description
  257. * the String description of the test
  258. * @throws IllegalArgumentException
  259. * if testName is not found
  260. */
  261. private AjcTest.Spec getSpec(String description) {
  262. AjcTest.Spec spec = mDescriptionToAjcTestSpec
  263. .get(description);
  264. if (null == spec) {
  265. throw new IllegalArgumentException("no test for " + description);
  266. }
  267. return spec;
  268. }
  269. /**
  270. * makeUsingTestClass(..) extends this to create TestCase with
  271. * test_{name} for each test case.
  272. */
  273. public static class TestClass extends TestCase {
  274. public TestClass() {
  275. }
  276. private SpecTests mTests;
  277. /**
  278. * Called by code generated in makeUsingTestClass(..)
  279. *
  280. * @param description
  281. * the String identifier of the test stored in SpecTests
  282. * mTests.
  283. * @throws Error
  284. * on first and later uses if getTestsFor() returns
  285. * null.
  286. */
  287. public final void runTest(String description) {
  288. if (null == mTests) {
  289. String classname = getClass().getName();
  290. mTests = getSpecTestsFor(classname);
  291. }
  292. mTests.runTest(description);
  293. }
  294. }
  295. }
  296. /** Wrap AjcTest.Spec as a TestCase. Run by delegation to suite */
  297. private static class AjcTestSpecAsTest extends TestCase implements
  298. HarnessJUnitUtil.IHasAjcSpec {
  299. // this could implement Test, but Ant batchtest fails to pull name
  300. final String name;
  301. final AjcTest.Spec spec;
  302. AjctestsAdapter suite;
  303. AjcTestSpecAsTest(AjcTest.Spec spec, AjctestsAdapter suite) {
  304. super(HarnessJUnitUtil.cleanTestName(spec.getDescription()));
  305. this.name = HarnessJUnitUtil.cleanTestName(spec.getDescription());
  306. this.suite = suite;
  307. this.spec = spec;
  308. spec.setSuiteDir(suite.getSuiteDir());
  309. }
  310. @Override
  311. public int countTestCases() {
  312. return 1;
  313. }
  314. @Override
  315. public AjcTest.Spec getAjcTestSpec() {
  316. return spec;
  317. }
  318. @Override
  319. public void run(TestResult result) {
  320. if (null == suite) {
  321. throw new Error("need to re-init");
  322. }
  323. try {
  324. AjState.FORCE_INCREMENTAL_DURING_TESTING = true;
  325. result.startTest(this);
  326. suite.runTest(this, result);
  327. } finally {
  328. result.endTest(this);
  329. suite = null;
  330. AjState.FORCE_INCREMENTAL_DURING_TESTING = false;
  331. }
  332. }
  333. @Override
  334. public String getName() {
  335. return name;
  336. }
  337. @Override
  338. public String toString() {
  339. return name;
  340. }
  341. }
  342. }