1 /*
   2  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /*
  25  * @test
  26  * @summary Verify correctnes of the random generator from Utility.java
  27  * @library /testlibrary
  28  * @build com.oracle.java.testlibrary.*
  29  * @run driver RandomGeneratorTest SAME_SEED
  30  * @run driver RandomGeneratorTest NO_SEED
  31  * @run driver RandomGeneratorTest DIFFERENT_SEED
  32  */
  33 
  34 import com.oracle.java.testlibrary.ProcessTools;
  35 import com.oracle.java.testlibrary.Utils;
  36 import java.util.ArrayList;
  37 import java.util.List;
  38 import java.util.Random;
  39 
  40 /**
  41  * The test verifies correctness of work {@link com.oracle.java.testlibrary.Utils#getRandomInstance()}.
  42  * Test works in three modes: same seed provided, no seed provided and
  43  * different seed provided. In the first case the test expects that all random numbers
  44  * will be repeated in all next iterations. For other two modes test expects that
  45  * randomly generated numbers differ from original.
  46  */
  47 public class RandomGeneratorTest {
  48     private static final String SEED_VM_OPTION = "-D" + Utils.SEED_PROPERTY_NAME + "=";
  49 
  50     public static void main( String[] args) throws Throwable {
  51         if (args.length == 0) {
  52             throw new Error("TESTBUG: No test mode provided.");
  53         }
  54         SeedOption seedOpt = SeedOption.valueOf(args[0]);
  55         List<String> jvmArgs = new ArrayList<String>();
  56         String optStr = seedOpt.getSeedOption();
  57         if (optStr != null) {
  58             jvmArgs.add(optStr);
  59         }
  60         jvmArgs.add(RandomRunner.class.getName());
  61         String[] cmdLineArgs = jvmArgs.toArray(new String[jvmArgs.size()]);
  62         String etalon = ProcessTools.executeTestJvm(cmdLineArgs).getOutput().trim();
  63         seedOpt.verify(etalon, cmdLineArgs);
  64     }
  65 
  66     /**
  67      * The utility enum helps to generate an appropriate string that should be passed
  68      * to the command line depends on the testing mode. It is also responsible for the result
  69      * validation.
  70      */
  71     private enum SeedOption {
  72         SAME_SEED {
  73             @Override
  74             public String getSeedOption() {
  75                 return SEED_VM_OPTION + Utils.SEED;
  76             }
  77 
  78             @Override
  79             protected boolean isOutputExpected(String orig, String output) {
  80                 return output.equals(orig);
  81             }
  82         },
  83         DIFFERENT_SEED {
  84             @Override
  85             public String getSeedOption() {
  86                 return SEED_VM_OPTION + Utils.getRandomInstance().nextLong();
  87             }
  88 
  89             @Override
  90             public void verify(String orig, String[] cmdLine) {
  91                 cmdLine[0] = getSeedOption();
  92                 super.verify(orig, cmdLine);
  93             }
  94         },
  95         NO_SEED {
  96             @Override
  97             public String getSeedOption() {
  98                 return null;
  99             }
 100         };
 101 
 102         /**
 103          * Generates a string to be added as a command line argument.
 104          * It contains "-D" prefix, system property name, '=' sign
 105          * and seed value.
 106          * @return command line argument
 107          */
 108         public abstract String getSeedOption();
 109 
 110         protected boolean isOutputExpected(String orig, String output) {
 111             return !output.equals(orig);
 112         }
 113 
 114         /**
 115          * Verifies that the original output meets expectations
 116          * depending on the test mode. It compares the output of second execution
 117          * to original one.
 118          * @param orig original output
 119          * @param cmdLine command line arguments
 120          * @throws Throwable - Throws an exception in case test failure.
 121          */
 122         public void verify(String orig, String[] cmdLine) {
 123             String lastLineOrig = getLastLine(orig);
 124             String lastLine;
 125             try {
 126                 lastLine = getLastLine(ProcessTools.executeTestJvm(cmdLine).getOutput().trim());
 127             } catch (Throwable t) {
 128                 throw new Error("TESTBUG: Unexpedted exception during jvm execution.", t);
 129             }
 130             if (!isOutputExpected(lastLineOrig, lastLine)) {
 131                     throw new AssertionError("Unexpected random number sequence for mode: " + this.name());
 132             }
 133         }
 134 
 135         private static String getLastLine(String output) {
 136             return output.substring(output.lastIndexOf(Utils.NEW_LINE)).trim();
 137         }
 138     }
 139 
 140     /**
 141      * The helper class generates several random numbers
 142      * and prints them out.
 143      */
 144     public static class RandomRunner {
 145         private static final int COUNT = 10;
 146         public static void main(String[] args) {
 147             StringBuilder sb = new StringBuilder();
 148             Random rng = Utils.getRandomInstance();
 149             for (int i = 0; i < COUNT; i++) {
 150                 sb.append(rng.nextLong()).append(' ');
 151             }
 152             System.out.println(sb.toString());
 153         }
 154     }
 155 }