public static void main()

in src/java/org/pantsbuild/tools/junit/impl/ConsoleRunnerImpl.java [703:850]


  public static void main(String[] args) {
    /**
     * Command line option bean.
     */
    class Options {
      @Option(name = "-fail-fast", usage = "Causes the test suite run to fail fast.")
      private boolean failFast;

      @Option(name = "-output-mode", usage = "Specify what part of output should be passed " +
          "to stdout. In case of FAILURE_ONLY and parallel tests execution " +
          "output can be partial or even wrong. (default: ALL)")
      private OutputMode outputMode = OutputMode.ALL;

      @Option(name = "-xmlreport",
              usage = "Create ant compatible junit xml report files in -outdir.")
      private boolean xmlReport;

      @Option(name = "-outdir",
              usage = "Directory to output test captures too.")
      private File outdir = new File(System.getProperty("java.io.tmpdir"));

      @Option(name = "-per-test-timer",
          usage = "Show a description of each test and timer for each test class.")
      private boolean perTestTimer;

      // TODO(zundel): This argument is deprecated, remove in a future release
      @Option(name = "-default-parallel",
          usage = "DEPRECATED: use -default-concurrency instead.\n"
              + "Whether to run test classes without @TestParallel or @TestSerial in parallel.")
      private boolean defaultParallel;

      @Option(name = "-default-concurrency",
          usage = "Specify how to parallelize running tests.\n"
          + "Use -use-experimental-runner for PARALLEL_METHODS and PARALLEL_CLASSES_AND_METHODS")
      private Concurrency defaultConcurrency;

      private int parallelThreads = 0;

      @Option(name = "-parallel-threads",
          usage = "Number of threads to execute tests in parallel. Must be positive, "
              + "or 0 to set automatically.")
      public void setParallelThreads(int parallelThreads) {
        if (parallelThreads < 0) {
          throw new InvalidCmdLineArgumentException(
              "-parallel-threads", parallelThreads, "-parallel-threads cannot be negative");
        }
        this.parallelThreads = parallelThreads;
        if (parallelThreads == 0) {
          int availableProcessors = Runtime.getRuntime().availableProcessors();
          this.parallelThreads = availableProcessors;
          System.err.printf("Auto-detected %d processors, using -parallel-threads=%d\n",
              availableProcessors, this.parallelThreads);
        }
      }

      private int testShard;
      private int numTestShards;

      @Option(name = "-test-shard",
          usage = "Subset of tests to run, in the form M/N, 0 <= M < N. For example, 1/3 means "
                  + "run tests number 2, 5, 8, 11, ...")
      public void setTestShard(String shard) {
        String errorMsg = "-test-shard should be in the form M/N";
        int slashIdx = shard.indexOf('/');
        if (slashIdx < 0) {
          throw new InvalidCmdLineArgumentException("-test-shard", shard, errorMsg);
        }
        try {
          this.testShard = Integer.parseInt(shard.substring(0, slashIdx));
          this.numTestShards = Integer.parseInt(shard.substring(slashIdx + 1));
        } catch (NumberFormatException ex) {
          throw new InvalidCmdLineArgumentException("-test-shard", shard, errorMsg);
        }
        if (testShard < 0 || numTestShards <= 0 || testShard >= numTestShards) {
          throw new InvalidCmdLineArgumentException(
              "-test-shard", shard, "0 <= M < N is required in -test-shard M/N");
        }
      }

      private int numRetries;

      @Option(name = "-num-retries",
          usage = "Number of attempts to retry each failing test, 0 by default")
      public void setNumRetries(int numRetries) {
        if (numRetries < 0) {
          throw new InvalidCmdLineArgumentException(
              "-num-retries", numRetries, "-num-retries cannot be negative");
        }
        this.numRetries = numRetries;
      }

      @Argument(usage = "Names of junit test classes or test methods to run.  Names prefixed "
                        + "with @ are considered arg file paths and these will be loaded and the "
                        + "whitespace delimited arguments found inside added to the list",
                required = true,
                metaVar = "TESTS",
                handler = StringArrayOptionHandler.class)
      private String[] tests = {};

      @Option(name="-use-experimental-runner",
          usage="Use the experimental runner that has support for parallel methods")
      private boolean useExperimentalRunner = false;
    }

    Options options = new Options();
    CmdLineParser parser = new CmdLineParser(options);
    try {
      parser.parseArgument(args);
    } catch (CmdLineException | InvalidCmdLineArgumentException e) {
      parser.printUsage(System.err);
      exit(1);
    }

    options.defaultConcurrency = computeConcurrencyOption(options.defaultConcurrency,
        options.defaultParallel);

    ConsoleRunnerImpl runner =
        new ConsoleRunnerImpl(options.failFast,
            options.outputMode,
            options.xmlReport,
            options.perTestTimer,
            options.outdir,
            options.defaultConcurrency,
            options.parallelThreads,
            options.testShard,
            options.numTestShards,
            options.numRetries,
            options.useExperimentalRunner,
            // NB: Buffering helps speedup output-heavy tests.
            new PrintStream(new BufferedOutputStream(System.out), true),
            new PrintStream(new BufferedOutputStream(System.err), true));

    List<String> tests = Lists.newArrayList();
    for (String test : options.tests) {
      if (test.startsWith("@")) {
        try {
          String argFileContents = Files.toString(new File(test.substring(1)), Charsets.UTF_8);
          tests.addAll(Arrays.asList(argFileContents.split("\\s+")));
        } catch (IOException e) {
          System.err.printf("Failed to load args from arg file %s: %s\n", test, e.getMessage());
          exit(1);
        }
      } else {
        tests.add(test);
      }
    }
    runner.run(tests);
  }