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 }