PageRenderTime 49ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 1ms

/TestTools/src/org/testng/TestNGCommandLineArgs.java

http://ravi-project-iptest.googlecode.com/
Java | 753 lines | 442 code | 66 blank | 245 comment | 136 complexity | bfcf0eed65590101c27b840a9aadbb25 MD5 | raw file
  1. package org.testng;
  2. import java.io.BufferedReader;
  3. import java.io.FileReader;
  4. import java.io.IOException;
  5. import java.util.ArrayList;
  6. import java.util.Arrays;
  7. import java.util.HashMap;
  8. import java.util.List;
  9. import java.util.Map;
  10. import java.util.StringTokenizer;
  11. import org.testng.internal.AnnotationTypeEnum;
  12. import org.testng.internal.ClassHelper;
  13. import org.testng.internal.Utils;
  14. import org.testng.internal.version.VersionInfo;
  15. import org.testng.log4testng.Logger;
  16. /**
  17. * TestNG/RemoteTestNG command line arguments parser.
  18. *
  19. * @author Cedric Beust
  20. * @author <a href = "mailto:the_mindstorm&#64;evolva.ro">Alexandru Popescu</a>
  21. */
  22. public final class TestNGCommandLineArgs {
  23. /** This class's log4testng Logger. */
  24. private static final Logger LOGGER = Logger.getLogger(TestNGCommandLineArgs.class);
  25. public static final String SHOW_TESTNG_STACK_FRAMES = "testng.show.stack.frames";
  26. public static final String TEST_CLASSPATH = "testng.test.classpath";
  27. // These next two are used by the Eclipse plug-in
  28. public static final String PORT_COMMAND_OPT = "-port";
  29. public static final String HOST_COMMAND_OPT = "-host";
  30. /** The logging level option. */
  31. public static final String LOG = "-log";
  32. /** @deprecated replaced by DEFAULT_ANNOTATIONS_COMMAND_OPT. */
  33. public static final String TARGET_COMMAND_OPT = "-target";
  34. /** The default annotations option (useful in TestNG 15 only). */
  35. public static final String ANNOTATIONS_COMMAND_OPT = "-annotations";
  36. /** The test report output directory option. */
  37. public static final String OUTDIR_COMMAND_OPT = "-d";
  38. public static final String EXCLUDED_GROUPS_COMMAND_OPT = "-excludegroups";
  39. public static final String GROUPS_COMMAND_OPT = "-groups";
  40. public static final String JUNIT_DEF_OPT = "-junit";
  41. public static final String LISTENER_COMMAND_OPT = "-listener";
  42. public static final String MASTER_OPT = "-master";
  43. public static final String OBJECT_FACTORY_COMMAND_OPT = "-objectfactory";
  44. /**
  45. * Used to pass a reporter configuration in the form
  46. * <code>-reporter <reporter_name_or_class>:option=value[,option=value]</code>
  47. */
  48. public static final String REPORTER = "-reporter";
  49. /**
  50. * Used as map key for the complete list of report listeners provided with the above argument
  51. */
  52. public static final String REPORTERS_LIST = "-reporterslist";
  53. public static final String PARALLEL_MODE = "-parallel";
  54. public static final String SKIP_FAILED_INVOCATION_COUNT_OPT = "-skipfailedinvocationcounts";
  55. public static final String SLAVE_OPT = "-slave";
  56. /** The source directory option (when using JavaDoc type annotations). */
  57. public static final String SRC_COMMAND_OPT = "-sourcedir";
  58. public static final String SUITE_NAME_OPT = "-suitename";
  59. /** The list of test classes option. */
  60. public static final String TESTCLASS_COMMAND_OPT = "-testclass";
  61. public static final String TESTJAR_COMMAND_OPT = "-testjar";
  62. public static final String TEST_NAME_OPT = "-testname";
  63. public static final String TESTRUNNER_FACTORY_COMMAND_OPT = "-testrunfactory";
  64. public static final String THREAD_COUNT = "-threadcount";
  65. public static final String USE_DEFAULT_LISTENERS = "-usedefaultlisteners";
  66. public static final String SUITE_DEF_OPT = "testng.suite.definitions";
  67. /**
  68. * When given a file name to form a class name, the file name is parsed and divided
  69. * into segments. For example, "c:/java/classes/com/foo/A.class" would be divided
  70. * into 6 segments {"C:" "java", "classes", "com", "foo", "A"}. The first segment
  71. * actually making up the class name is [3]. This value is saved in m_lastGoodRootIndex
  72. * so that when we parse the next file name, we will try 3 right away. If 3 fails we
  73. * will take the long approach. This is just a optimization cache value.
  74. */
  75. private static int m_lastGoodRootIndex = -1;
  76. /**
  77. * Hide the constructor for utility class.
  78. */
  79. private TestNGCommandLineArgs() {
  80. // Hide constructor for utility class
  81. }
  82. /**
  83. * Parses the command line options and returns a map from option string to parsed values.
  84. * For example, if argv contains {..., "-sourcedir", "src/main", "-target", ...} then
  85. * the map would contain an entry in which the key would be the "-sourcedir" String and
  86. * the value would be the "src/main" String.
  87. *
  88. * @param originalArgv the command line options.
  89. * @return the parsed parameters as a map from option string to parsed values.
  90. */
  91. public static Map parseCommandLine(final String[] originalArgv) {
  92. for (int i = 0; i < originalArgv.length; ++i) {
  93. LOGGER.debug("originalArgv[" + i + "] = \"" + originalArgv[i] + "\"");
  94. }
  95. // TODO CQ In this method, is this OK to simply ignore invalid parameters?
  96. LOGGER.debug("TestNG version: \"" + (VersionInfo.IS_JDK14 ? "14" : "15") + "\"");
  97. Map<String, Object> arguments = new HashMap<String, Object>();
  98. String[] argv = expandArgv(originalArgv);
  99. for (int i = 0; i < argv.length; i++) {
  100. if (OUTDIR_COMMAND_OPT.equalsIgnoreCase(argv[i])) {
  101. if ((i + 1) < argv.length) {
  102. arguments.put(OUTDIR_COMMAND_OPT, argv[i + 1].trim());
  103. }
  104. else {
  105. LOGGER.error("WARNING: missing output directory after -d. ignored");
  106. }
  107. i++;
  108. }
  109. else if (GROUPS_COMMAND_OPT.equalsIgnoreCase(argv[i])
  110. || EXCLUDED_GROUPS_COMMAND_OPT.equalsIgnoreCase(argv[i])) {
  111. if ((i + 1) < argv.length) {
  112. String option = null;
  113. if (argv[i + 1].startsWith("\"")) {
  114. if (argv[i + 1].endsWith("\"")) {
  115. option = argv[i + 1].substring(1, argv[i + 1].length() - 1);
  116. }
  117. else {
  118. LOGGER.error("WARNING: groups option is not well quoted:" + argv[i + 1]);
  119. option = argv[i + 1].substring(1);
  120. }
  121. }
  122. else {
  123. option = argv[i + 1];
  124. }
  125. String opt = GROUPS_COMMAND_OPT.equalsIgnoreCase(argv[i])
  126. ? GROUPS_COMMAND_OPT : EXCLUDED_GROUPS_COMMAND_OPT;
  127. arguments.put(opt, option);
  128. }
  129. else {
  130. LOGGER.error("WARNING: missing groups parameter after -groups. ignored");
  131. }
  132. i++;
  133. }
  134. else if (LOG.equalsIgnoreCase(argv[i])) {
  135. if ((i + 1) < argv.length) {
  136. arguments.put(LOG, Integer.valueOf(argv[i + 1].trim()));
  137. }
  138. else {
  139. LOGGER.error("WARNING: missing log level after -log. ignored");
  140. }
  141. i++;
  142. }
  143. else if (JUNIT_DEF_OPT.equalsIgnoreCase(argv[i])) {
  144. arguments.put(JUNIT_DEF_OPT, Boolean.TRUE);
  145. }
  146. else if (TARGET_COMMAND_OPT.equalsIgnoreCase(argv[i])) {
  147. if ((i + 1) < argv.length) {
  148. arguments.put(ANNOTATIONS_COMMAND_OPT, AnnotationTypeEnum.valueOf(argv[i + 1]));
  149. LOGGER.warn("The usage of " + TARGET_COMMAND_OPT + " has been deprecated. Please use " + ANNOTATIONS_COMMAND_OPT + " instead.");
  150. ++i;
  151. }
  152. }
  153. else if (ANNOTATIONS_COMMAND_OPT.equalsIgnoreCase(argv[i])) {
  154. if ((i + 1) < argv.length) {
  155. arguments.put(ANNOTATIONS_COMMAND_OPT, AnnotationTypeEnum.valueOf(argv[i + 1]));
  156. ++i;
  157. }
  158. }
  159. else if (TESTRUNNER_FACTORY_COMMAND_OPT.equalsIgnoreCase(argv[i])) {
  160. if ((i + 1) < argv.length) {
  161. arguments.put(TESTRUNNER_FACTORY_COMMAND_OPT, fileToClass(argv[++i]));
  162. }
  163. else {
  164. LOGGER.error("WARNING: missing ITestRunnerFactory class or file argument after "
  165. + TESTRUNNER_FACTORY_COMMAND_OPT);
  166. }
  167. }
  168. else if (OBJECT_FACTORY_COMMAND_OPT.equalsIgnoreCase(argv[i])) {
  169. if ((i + 1) < argv.length) {
  170. Class<?> cls = fileToClass(argv[++i]);
  171. arguments.put(OBJECT_FACTORY_COMMAND_OPT, cls);
  172. }
  173. else {
  174. LOGGER.error("WARNING: missing IObjectFactory class/file list argument after "
  175. + OBJECT_FACTORY_COMMAND_OPT);
  176. }
  177. }
  178. else if (LISTENER_COMMAND_OPT.equalsIgnoreCase(argv[i])) {
  179. if ((i + 1) < argv.length) {
  180. String strClass = argv[++i];
  181. String sep = ";";
  182. if (strClass.indexOf(",") >= 0) {
  183. sep = ",";
  184. }
  185. String[] strs = Utils.split(strClass, sep);
  186. List<Class<?>> classes = new ArrayList<Class<?>>();
  187. for (String cls : strs) {
  188. classes.add(fileToClass(cls));
  189. }
  190. arguments.put(LISTENER_COMMAND_OPT, classes);
  191. }
  192. else {
  193. LOGGER.error("WARNING: missing ITestListener class/file list argument after "
  194. + LISTENER_COMMAND_OPT);
  195. }
  196. }
  197. else if (TESTCLASS_COMMAND_OPT.equalsIgnoreCase(argv[i])) {
  198. if ((i + 1) < argv.length) {
  199. while ((i + 1) < argv.length) {
  200. String nextArg = argv[i + 1].trim();
  201. if (!nextArg.toLowerCase().endsWith(".xml") && !nextArg.startsWith("-")) {
  202. // Assume it's a class name
  203. List<Class<?>> l = (List<Class<?>>) arguments.get(TESTCLASS_COMMAND_OPT);
  204. if (null == l) {
  205. l = new ArrayList<Class<?>>();
  206. arguments.put(TESTCLASS_COMMAND_OPT, l);
  207. }
  208. Class<?> cls = fileToClass(nextArg);
  209. if (null != cls) {
  210. l.add(cls);
  211. }
  212. i++;
  213. } // if
  214. else {
  215. break;
  216. }
  217. }
  218. }
  219. else {
  220. TestNG.exitWithError("-testclass must be followed by a classname");
  221. }
  222. }
  223. else if (TESTJAR_COMMAND_OPT.equalsIgnoreCase(argv[i])) {
  224. if ((i + 1) < argv.length) {
  225. arguments.put(TESTJAR_COMMAND_OPT, argv[i + 1].trim());
  226. }
  227. else {
  228. TestNG.exitWithError("-testjar must be followed by a valid jar");
  229. }
  230. i++;
  231. }
  232. else if (SRC_COMMAND_OPT.equalsIgnoreCase(argv[i])) {
  233. if ((i + 1) < argv.length) {
  234. arguments.put(SRC_COMMAND_OPT, argv[i + 1].trim());
  235. }
  236. else {
  237. TestNG.exitWithError(SRC_COMMAND_OPT + " must be followed by a directory path");
  238. }
  239. i++;
  240. }
  241. else if (HOST_COMMAND_OPT.equals(argv[i])) {
  242. String hostAddress = "127.0.0.1";
  243. if ((i + 1) < argv.length) {
  244. hostAddress = argv[i + 1].trim();
  245. i++;
  246. }
  247. else {
  248. LOGGER.warn("WARNING: "
  249. + HOST_COMMAND_OPT
  250. + " option should be followed by the host address. "
  251. + "Using default localhost.");
  252. }
  253. arguments.put(HOST_COMMAND_OPT, hostAddress);
  254. }
  255. else if (PORT_COMMAND_OPT.equals(argv[i])) {
  256. String portNumber = null;
  257. if ((i + 1) < argv.length) {
  258. portNumber = argv[i + 1].trim();
  259. }
  260. else {
  261. TestNG.exitWithError(
  262. PORT_COMMAND_OPT + " option should be followed by a valid port number.");
  263. }
  264. arguments.put(PORT_COMMAND_OPT, portNumber);
  265. i++;
  266. }
  267. else if (SLAVE_OPT.equals(argv[i])) {
  268. String propertiesFile = null;
  269. if ((i + 1) < argv.length) {
  270. propertiesFile = argv[i + 1].trim();
  271. }
  272. else {
  273. TestNG.exitWithError(SLAVE_OPT + " option should be followed by a valid file path.");
  274. }
  275. arguments.put(SLAVE_OPT, propertiesFile);
  276. i++;
  277. }
  278. else if (MASTER_OPT.equals(argv[i])) {
  279. String propertiesFile = null;
  280. if ((i + 1) < argv.length) {
  281. propertiesFile = argv[i + 1].trim();
  282. }
  283. else {
  284. TestNG.exitWithError(MASTER_OPT + " option should be followed by a valid file path.");
  285. }
  286. arguments.put(MASTER_OPT, propertiesFile);
  287. i++;
  288. }
  289. else if (PARALLEL_MODE.equalsIgnoreCase(argv[i])) {
  290. if ((i + 1) < argv.length) {
  291. arguments.put(PARALLEL_MODE, argv[i + 1]);
  292. i++;
  293. }
  294. }
  295. else if (THREAD_COUNT.equalsIgnoreCase(argv[i])) {
  296. if ((i + 1) < argv.length) {
  297. arguments.put(THREAD_COUNT, argv[i + 1]);
  298. i++;
  299. }
  300. }
  301. else if (USE_DEFAULT_LISTENERS.equalsIgnoreCase(argv[i])) {
  302. if ((i + 1) < argv.length) {
  303. arguments.put(USE_DEFAULT_LISTENERS, argv[i + 1]);
  304. i++;
  305. }
  306. }
  307. else if (SUITE_NAME_OPT.equalsIgnoreCase(argv[i])) {
  308. if ((i + 1) < argv.length) {
  309. arguments.put(SUITE_NAME_OPT, trim(argv[i + 1]));
  310. i++;
  311. }
  312. }
  313. else if (TEST_NAME_OPT.equalsIgnoreCase(argv[i])) {
  314. if ((i + 1) < argv.length) {
  315. arguments.put(TEST_NAME_OPT, trim(argv[i + 1]));
  316. i++;
  317. }
  318. }
  319. else if (REPORTER.equalsIgnoreCase(argv[i])) {
  320. if ((i + 1) < argv.length) {
  321. ReporterConfig reporterConfig = ReporterConfig.deserialize(trim(argv[i + 1]));
  322. if (arguments.get(REPORTERS_LIST) == null) {
  323. arguments.put(REPORTERS_LIST, new ArrayList<ReporterConfig>());
  324. }
  325. ((List<ReporterConfig>)arguments.get(REPORTERS_LIST)).add(reporterConfig);
  326. i++;
  327. }
  328. }
  329. else if (SKIP_FAILED_INVOCATION_COUNT_OPT.equalsIgnoreCase(argv[i])) {
  330. arguments.put(SKIP_FAILED_INVOCATION_COUNT_OPT, Boolean.TRUE);
  331. }
  332. //
  333. // Unknown option
  334. //
  335. else if (argv[i].startsWith("-")) {
  336. TestNG.exitWithError("Unknown option: " + argv[i]);
  337. }
  338. //
  339. // The XML files
  340. //
  341. // Read parameters just once, to get all xml files
  342. else if( arguments.get(SUITE_DEF_OPT) == null ){
  343. List<String> suiteDefs = new ArrayList<String>();
  344. // Iterates over all declared XML file params
  345. for (int k = i; k < argv.length; k++) {
  346. String file = argv[k].trim();
  347. if (file.toLowerCase().endsWith(".xml")) {
  348. suiteDefs.add(file);
  349. }
  350. }
  351. arguments.put(SUITE_DEF_OPT, suiteDefs);
  352. }
  353. }
  354. for (Map.Entry entry : arguments.entrySet()) {
  355. LOGGER.debug("parseCommandLine argument: \""
  356. + entry.getKey() + "\" = \"" + entry.getValue() + "\"");
  357. }
  358. return arguments;
  359. }
  360. /**
  361. * @param string
  362. * @return
  363. */
  364. private static String trim(String string) {
  365. String trimSpaces=string.trim();
  366. if (trimSpaces.startsWith("\"")) {
  367. if (trimSpaces.endsWith("\"")) {
  368. return trimSpaces.substring(1, trimSpaces.length() - 1);
  369. } else {
  370. return trimSpaces.substring(1);
  371. }
  372. } else {
  373. return trimSpaces;
  374. }
  375. }
  376. /**
  377. * Expand the command line parameters to take @ parameters into account.
  378. * When @ is encountered, the content of the file that follows is inserted
  379. * in the command line
  380. * @param originalArgv the original command line parameters
  381. * @return the new and enriched command line parameters
  382. */
  383. private static String[] expandArgv(String[] originalArgv) {
  384. List<String> vResult = new ArrayList<String>();
  385. for (String arg : originalArgv) {
  386. if (arg.startsWith("@")) {
  387. String fileName = arg.substring(1);
  388. vResult.addAll(readFile(fileName));
  389. }
  390. else {
  391. vResult.add(arg);
  392. }
  393. }
  394. return vResult.toArray(new String[vResult.size()]);
  395. }
  396. // /**
  397. // * Break a line of parameters into individual parameters as the command line parsing
  398. // * would do. The line is assumed to contain only un-escaped double quotes. For example
  399. // * the following Java string:
  400. // * " a \"command\"\"line\" \"with quotes\" a command line\" with quotes \"here there"
  401. // * would yield the following 7 tokens:
  402. // * a,commandline,with quotes,a,command,line with quotes here,there
  403. // * @param line the command line parameter to be parsed
  404. // * @return the list of individual command line tokens
  405. // */
  406. // private static List<String> parseArgs(String line) {
  407. // LOGGER.debug("parseArgs line: \"" + line + "\"");
  408. // final String SPACE = " ";
  409. // final String DOUBLE_QUOTE = "\"";
  410. //
  411. // // If line contains no double quotes, the space character is the only
  412. // // separator. Easy to do return quickly (logic is also easier to follow)
  413. // if (line.indexOf(DOUBLE_QUOTE) == -1) {
  414. // List<String> results = Arrays.asList(line.split(SPACE));
  415. // for (String result : results) {
  416. // LOGGER.debug("parseArgs result: \"" + result + "\"");
  417. // }
  418. // return results;
  419. // }
  420. //
  421. // // TODO There must be an easier way to do this with a regular expression.
  422. //
  423. // StringTokenizer st = new StringTokenizer(line, SPACE + DOUBLE_QUOTE, true);
  424. // List<String> results = new ArrayList<String>();
  425. //
  426. // /*
  427. // * isInDoubleQuote toggles from false to true when we reach a double
  428. // * quoted string and toggles back to false when we exit. We need to
  429. // * know if we are in a double quoted string to treat blanks as normal
  430. // * characters. Out of quotes blanks separate arguments.
  431. // *
  432. // * The following example shows these toggle points:
  433. // *
  434. // * " a \"command\"\"line\" \"with quotes\" a command line\" with quotes \"here there"
  435. // * T F T F T F T F
  436. // *
  437. // * If the double quotes are not evenly matched, an exception is thrown.
  438. // */
  439. // boolean isInDoubleQuote = false;
  440. //
  441. // /*
  442. // * isInArg toggles from false to true when we enter a command line argument
  443. // * and toggles back to false when we exit. The logic is that we toggle to
  444. // * true at the first non-whitespace character met. We toggle back to false
  445. // * at first whitespace character not in double quotes or at end of line.
  446. // *
  447. // * The following example shows these toggle points:
  448. // *
  449. // * " a \"command\"\"line\" \"with quotes\" a command line\" with quotes \"here there"
  450. // * TF T F T F TFT FT F
  451. // */
  452. // boolean isInArg = false;
  453. //
  454. // /* arg is a string buffer to create the argument by concatenating all tokens
  455. // * that compose it.
  456. // *
  457. // * The following example shows the token returned by the parser and the
  458. // * (spaces, double quotes, others) and resultant argument:
  459. // *
  460. // * Input (argument):
  461. // * "line\" with quotes \"here"
  462. // *
  463. // * Tokens (9):
  464. // * line,", ,with, ,quote, ,",here
  465. // */
  466. // StringBuffer arg = new StringBuffer();
  467. //
  468. // while (st.hasMoreTokens()) {
  469. // String token = st.nextToken();
  470. //
  471. // if (token.equals(SPACE)) {
  472. // if (isInArg) {
  473. // if (isInDoubleQuote) {
  474. // // Spaces within double quotes are treated as normal spaces
  475. // arg.append(SPACE);
  476. // }
  477. // else {
  478. // // First spaces outside double quotes marks the end of the argument.
  479. // isInArg = false;
  480. // results.add(arg.toString());
  481. // arg = new StringBuffer();
  482. // }
  483. // }
  484. // }
  485. // else if (token.equals(DOUBLE_QUOTE)) {
  486. // // If we encounter a double quote, we may be entering a new argument
  487. // // (isInArg is false) or continuing the current argument (isInArg is true).
  488. // isInArg = true;
  489. // isInDoubleQuote = !isInDoubleQuote;
  490. // }
  491. // else {
  492. // // We we encounter a new token, we may be entering a new argument
  493. // // (isInArg is false) or continuing the current argument (isInArg is true).
  494. // isInArg = true;
  495. // arg.append(token);
  496. // }
  497. // }
  498. //
  499. // // In some (most) cases we exit this parsing because there are no tokens left
  500. // // but we have not encountered a token to indicate that the last argument has
  501. // // completely been read. For example, if the command line ends with a whitespace
  502. // // the isInArg will toggle to false and the argument will be completely read.
  503. // if (isInArg) {
  504. // // End of last argument
  505. // results.add(arg.toString());
  506. // }
  507. //
  508. // // If we exit the parsing of the command line with an uneven number of double
  509. // // quotes, throw an exception.
  510. // if (isInDoubleQuote) {
  511. // throw new IllegalArgumentException("Unbalanced double quotes: \"" + line + "\"");
  512. // }
  513. //
  514. // for (String result : results) {
  515. // LOGGER.debug("parseArgs result: \"" + result + "\"");
  516. // }
  517. //
  518. // return results;
  519. // }
  520. /**
  521. * Reads the file specified by filename and returns the file content as a string.
  522. * End of lines are replaced by a space
  523. *
  524. * @param fileName the command line filename
  525. * @return the file content as a string.
  526. */
  527. public static List<String> readFile(String fileName) {
  528. List<String> result = new ArrayList<String>();
  529. try {
  530. BufferedReader bufRead = new BufferedReader(new FileReader(fileName));
  531. String line;
  532. // Read through file one line at time. Print line # and line
  533. while ((line = bufRead.readLine()) != null) {
  534. result.add(line);
  535. }
  536. bufRead.close();
  537. }
  538. catch (IOException e) {
  539. LOGGER.error("IO exception reading command line file", e);
  540. }
  541. return result;
  542. }
  543. /**
  544. * Returns the Class object corresponding to the given name. The name may be
  545. * of the following form:
  546. * <ul>
  547. * <li>A class name: "org.testng.TestNG"</li>
  548. * <li>A class file name: "/testng/src/org/testng/TestNG.class"</li>
  549. * <li>A class source name: "d:\testng\src\org\testng\TestNG.java"</li>
  550. * </ul>
  551. *
  552. * @param file
  553. * the class name.
  554. * @return the class corresponding to the name specified.
  555. */
  556. private static Class<?> fileToClass(String file) {
  557. Class<?> result = null;
  558. if(!file.endsWith(".class") && !file.endsWith(".java")) {
  559. // Doesn't end in .java or .class, assume it's a class name
  560. result = ClassHelper.forName(file);
  561. if (null == result) {
  562. throw new TestNGException("Cannot load class from file: " + file);
  563. }
  564. return result;
  565. }
  566. int classIndex = file.lastIndexOf(".class");
  567. if (-1 == classIndex) {
  568. classIndex = file.lastIndexOf(".java");
  569. //
  570. // if(-1 == classIndex) {
  571. // result = ClassHelper.forName(file);
  572. //
  573. // if (null == result) {
  574. // throw new TestNGException("Cannot load class from file: " + file);
  575. // }
  576. //
  577. // return result;
  578. // }
  579. //
  580. }
  581. // Transforms the file name into a class name.
  582. // Remove the ".class" or ".java" extension.
  583. String shortFileName = file.substring(0, classIndex);
  584. // Split file name into segments. For example "c:/java/classes/com/foo/A"
  585. // becomes {"c:", "java", "classes", "com", "foo", "A"}
  586. String[] segments = shortFileName.split("[/\\\\]", -1);
  587. //
  588. // Check if the last good root index works for this one. For example, if the previous
  589. // name was "c:/java/classes/com/foo/A.class" then m_lastGoodRootIndex is 3 and we
  590. // try to make a class name ignoring the first m_lastGoodRootIndex segments (3). This
  591. // will succeed rapidly if the path is the same as the one from the previous name.
  592. //
  593. if (-1 != m_lastGoodRootIndex) {
  594. // TODO use a SringBuffer here
  595. String className = segments[m_lastGoodRootIndex];
  596. for (int i = m_lastGoodRootIndex + 1; i < segments.length; i++) {
  597. className += "." + segments[i];
  598. }
  599. result = ClassHelper.forName(className);
  600. if (null != result) {
  601. return result;
  602. }
  603. }
  604. //
  605. // We haven't found a good root yet, start by resolving the class from the end segment
  606. // and work our way up. For example, if we start with "c:/java/classes/com/foo/A"
  607. // we'll start by resolving "A", then "foo.A", then "com.foo.A" until something
  608. // resolves. When it does, we remember the path we are at as "lastGoodRoodIndex".
  609. //
  610. // TODO CQ use a StringBuffer here
  611. String className = null;
  612. for (int i = segments.length - 1; i >= 0; i--) {
  613. if (null == className) {
  614. className = segments[i];
  615. }
  616. else {
  617. className = segments[i] + "." + className;
  618. }
  619. result = ClassHelper.forName(className);
  620. if (null != result) {
  621. m_lastGoodRootIndex = i;
  622. break;
  623. }
  624. }
  625. if (null == result) {
  626. throw new TestNGException("Cannot load class from file: " + file);
  627. }
  628. return result;
  629. }
  630. // private static void ppp(Object msg) {
  631. // System.out.println("[CMD]: " + msg);
  632. // }
  633. /**
  634. * Prints the usage message to System.out. This message describes all the command line
  635. * options.
  636. */
  637. public static void usage() {
  638. System.out.println("Usage:");
  639. System.out.println("[" + OUTDIR_COMMAND_OPT + " output-directory]");
  640. System.out.println("\t\tdefault output directory to : " + TestNG.DEFAULT_OUTPUTDIR);
  641. System.out.println("[" + TESTCLASS_COMMAND_OPT
  642. + " list of .class files or list of class names]");
  643. System.out.println("[" + SRC_COMMAND_OPT + " a source directory]");
  644. if (VersionInfo.IS_JDK14) {
  645. System.out.println("[" + ANNOTATIONS_COMMAND_OPT + " " + AnnotationTypeEnum.JAVADOC.getName() + "]");
  646. System.out.println("\t\tSpecifies the default annotation type to be used in suites when none is explicitly specified.");
  647. System.out.println("\t\tThis version of TestNG (14) only supports " + AnnotationTypeEnum.JAVADOC.getName() + " annotation type.");
  648. System.out.println("\t\tFor interface compatibility reasons, we allow this value to be explicitly set to " +
  649. AnnotationTypeEnum.JAVADOC.getName() + "\" ");
  650. }
  651. else {
  652. System.out.println("[" + ANNOTATIONS_COMMAND_OPT + " " + AnnotationTypeEnum.JAVADOC.getName() + " or "
  653. + AnnotationTypeEnum.JDK.getName() + "]");
  654. System.out.println("\t\tSpecifies the default annotation type to be used in suites when none is explicitly");
  655. System.out.println("\t\tspecified. This version of TestNG (15) supports both \""
  656. + AnnotationTypeEnum.JAVADOC.getName() + "\" and \"" + AnnotationTypeEnum.JDK.getName() + "\" annotation types.");
  657. }
  658. System.out.println("[" + GROUPS_COMMAND_OPT + " comma-separated list of group names to be run]");
  659. System.out.println("\t\tworks only with " + TESTCLASS_COMMAND_OPT);
  660. System.out.println("[" + EXCLUDED_GROUPS_COMMAND_OPT
  661. + " comma-separated list of group names to be excluded]");
  662. System.out.println("\t\tworks only with " + TESTCLASS_COMMAND_OPT);
  663. System.out.println("[" + TESTRUNNER_FACTORY_COMMAND_OPT
  664. + " list of .class files or list of class names implementing "
  665. + ITestRunnerFactory.class.getName()
  666. + "]");
  667. System.out.println("[" + LISTENER_COMMAND_OPT
  668. + " list of .class files or list of class names implementing "
  669. + ITestListener.class.getName()
  670. + " and/or "
  671. + ISuiteListener.class.getName()
  672. + "]");
  673. System.out.println("[" + PARALLEL_MODE
  674. + " methods|tests]");
  675. System.out.println("\t\trun tests in parallel using the specified mode");
  676. System.out.println("[" + THREAD_COUNT
  677. + " number of threads to use when running tests in parallel]");
  678. System.out.println("[" + SUITE_NAME_OPT + " name]");
  679. System.out.println("\t\tDefault name of test suite, if not specified in suite definition file or source code");
  680. System.out.println("[" + TEST_NAME_OPT + " Name]");
  681. System.out.println("\t\tDefault name of test, if not specified in suite definition file or source code");
  682. System.out.println("[" + REPORTER + " Extended configuration for custom report listener]");
  683. System.out.println("[suite definition files*]");
  684. System.out.println("");
  685. System.out.println("For details, please consult the documentation at http://testng.org.");
  686. }
  687. }