View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.rng.examples.stress;
18  
19  import picocli.CommandLine;
20  import picocli.CommandLine.RunLast;
21  
22  /**
23   * Executes testing utilities for the random number generators in the Commons RNG library.
24   *
25   * <p>The principle action is testing a generator by piping the values returned by its
26   * {@link org.apache.commons.rng.UniformRandomProvider#nextInt()
27   * UniformRandomProvider.nextInt()} method to a program that reads {@code int} values from
28   * its standard input and writes an analysis report to standard output. The <a
29   * href="http://www.phy.duke.edu/~rgb/General/dieharder.php"> "Dieharder"</a> test suite
30   * is such a software.</p>
31   *
32   * <p>Example of command line, assuming that "examples-stress.jar" specifies this
33   * class as the "main" class (see {@link #main(String[]) main} method):</p>
34   *
35   * <pre>{@code $ java -jar examples-stress.jar stress /usr/bin/dieharder -a -g 200 -Y 1 -k 2}</pre>
36   *
37   * <p>Other functionality includes:</p>
38   *
39   * <ul>
40   *   <li>Listing all the available generators
41   *   <li>Collating results from known stress test applications
42   *   <li>Outputting data from a random generator
43   *   <li>Showing the platform native byte order
44   *   <li>Testing data transfer to an application sub-process via its standard input
45   * </ul>
46   */
47  public final class ExamplesStressApplication {
48      /** No public constructor. */
49      private ExamplesStressApplication() {}
50  
51      /**
52       * Run the RNG examples stress command line application.
53       *
54       * @param args Application's arguments.
55       */
56      public static void main(String[] args) {
57          // Build the command line manually so we can configure options.
58          final CommandLine cmd = new CommandLine(new ExamplesStressCommand())
59                  .addSubcommand("bridge",  new CommandLine(new BridgeTestCommand())
60                                                            .setStopAtPositional(true))
61                  .addSubcommand("endian",  new EndianessCommand())
62                  .addSubcommand("list",    new ListCommand())
63                  .addSubcommand("output",  new CommandLine(new OutputCommand())
64                                                            // Allow the input seed using hex (0x, 0X, #)
65                                                            // or octal (starting with 0)
66                                                            .registerConverter(Long.class, Long::decode))
67                  .addSubcommand("results", new ResultsCommand())
68                  .addSubcommand("stress",  new CommandLine(new StressTestCommand())
69                                                            .setStopAtPositional(true))
70                  // Call last to apply to all sub-commands
71                  .setCaseInsensitiveEnumValuesAllowed(true);
72  
73          try {
74              // Parse the command line and invokes the Callable program (RNGUtilities)
75              cmd.parseWithHandler(new RunLast(), args);
76          } catch (final CommandLine.ExecutionException ex) {
77              final Throwable cause = ex.getCause();
78              if (cause != null) {
79                  // If this was an exception generated by the application then the full
80                  // stack trace is not needed depending on log level. This limits stack
81                  // trace output to unexpected errors in the common use case.
82                  if (cause instanceof ApplicationException &&
83                          !LogUtils.isLoggable(LogUtils.LogLevel.DEBUG)) {
84                      LogUtils.error(cause.getMessage());
85                  } else {
86                      LogUtils.error(cause, cause.getMessage());
87                  }
88                  System.exit(1);
89              }
90              // No cause so re-throw. This may be a Picocli parsing error.
91              throw ex;
92          }
93      }
94  }