test/hotspot/jtreg/vmTestbase/vm/runtime/defmeth/StressTest.java
changeset 50243 4fac3c99487d
equal deleted inserted replaced
50242:9a87afc49148 50243:4fac3c99487d
       
     1 /*
       
     2  * Copyright (c) 2013, 2018, 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 package vm.runtime.defmeth;
       
    25 
       
    26 import java.util.ArrayList;
       
    27 import java.util.Arrays;
       
    28 import java.util.List;
       
    29 import java.util.Random;
       
    30 import nsk.share.TestFailure;
       
    31 import nsk.share.test.StressOptions;
       
    32 import nsk.share.test.Stresser;
       
    33 import vm.runtime.defmeth.shared.Constants;
       
    34 import vm.runtime.defmeth.shared.DefMethTest;
       
    35 import vm.runtime.defmeth.shared.ExecutionMode;
       
    36 import vm.runtime.defmeth.shared.builder.TestBuilder;
       
    37 import vm.share.options.Option;
       
    38 import vm.share.options.OptionSupport;
       
    39 import vm.share.options.Options;
       
    40 import static jdk.internal.org.objectweb.asm.Opcodes.*;
       
    41 
       
    42 /*
       
    43  * Stress test for default methods implementation.
       
    44  *
       
    45  * Stress scenario is the following:
       
    46  *   - in multiple threads ...
       
    47  *   - ... continuously run random tests ...
       
    48  *   - ... in random configuration ...
       
    49  *   - ... until predefined period of time is over...
       
    50  *   - ... or any failures occured.
       
    51  */
       
    52 public class StressTest implements Runnable {
       
    53     @Options
       
    54     private StressOptions opts = new StressOptions();
       
    55 
       
    56     @Option(name="seed", default_value="0", description="force deterministic behavior")
       
    57     private int seed;
       
    58 
       
    59     @Option(name="redefine", default_value="false", description="use scenarios w/ class redefinition")
       
    60     private boolean doRedefine;
       
    61 
       
    62     @Option(name="ver", default_value="49", description="minimum class file version to be used in the tests")
       
    63     private int minMajorVer;
       
    64 
       
    65     @Option(name="ignoreTestFailures", default_value="false", description="ignore failures of the executed tests")
       
    66     private boolean ignoreTestFailures;
       
    67 
       
    68     class Worker extends Thread {
       
    69         private final Random rand;
       
    70 
       
    71         private volatile DefMethTest failedTest;
       
    72         private Throwable reason;
       
    73         private volatile long executedTests = 0;
       
    74 
       
    75         public Worker(String id, int seed) {
       
    76             setName(id);
       
    77             this.rand = new Random(seed);
       
    78         }
       
    79 
       
    80         @Override
       
    81         public void run() {
       
    82             while (!Thread.interrupted()) {
       
    83                 int idx = rand.nextInt(testlist.size());
       
    84                 DefMethTest test = testlist.get(idx);
       
    85                 try {
       
    86                     test.run();
       
    87                     executedTests++;
       
    88                     if (test.isFailed()) {
       
    89                         throw new TestFailure(test.toString());
       
    90                     }
       
    91                 } catch (Throwable e) {
       
    92                     if (!ignoreTestFailures) {
       
    93                         failedTest = test;
       
    94                         reason = e;
       
    95                         break;
       
    96                     }
       
    97                 }
       
    98             }
       
    99         }
       
   100 
       
   101         public boolean isFailed() { return failedTest != null; }
       
   102         public Throwable getReason() { return reason; }
       
   103         public DefMethTest getFailedTest() { return failedTest; }
       
   104         public long getExecutedTests() { return executedTests; }
       
   105     }
       
   106 
       
   107     private List<DefMethTest> testlist;
       
   108 
       
   109     private Worker[] workers;
       
   110 
       
   111     Stresser stresser;
       
   112 
       
   113     public static void main(String[] args) {
       
   114         StressTest test = new StressTest();
       
   115         OptionSupport.setupAndRun(test, args);
       
   116     }
       
   117 
       
   118     @Override
       
   119     public void run() {
       
   120         configureTests();
       
   121         startWorkers();
       
   122 
       
   123         stresser = new Stresser(opts);
       
   124         try {
       
   125             stresser.start(0);
       
   126             while (workersAlive() && stresser.continueExecution()) {
       
   127                 printStats();
       
   128 
       
   129                 try {
       
   130                     Thread.sleep(1000);
       
   131                 } catch (InterruptedException ex) {}
       
   132             }
       
   133         } finally {
       
   134             interruptWorkers();
       
   135             joinWorkers();
       
   136 
       
   137             stresser.finish();
       
   138         }
       
   139     }
       
   140 
       
   141     private void configureTests() {
       
   142         int[] majorVerValues = new int[52 - minMajorVer + 1];
       
   143         for (int i = 0; i< majorVerValues.length; i++) {
       
   144             majorVerValues[i] = minMajorVer + i;
       
   145         }
       
   146 
       
   147         int[] flagsValues = new int[] {
       
   148             0,
       
   149             ACC_STRICT,
       
   150             ACC_SYNCHRONIZED,
       
   151             ACC_STRICT | ACC_SYNCHRONIZED
       
   152         };
       
   153 
       
   154         boolean[] doRedefineValues;
       
   155         if (doRedefine) {
       
   156             doRedefineValues = new boolean[] { true, false};
       
   157         } else {
       
   158             doRedefineValues = new boolean[] { false };
       
   159         }
       
   160 
       
   161         // Upper limit for test count
       
   162         int testCount = DefMethTest.getTests().size() * majorVerValues.length
       
   163                         * flagsValues.length * doRedefineValues.length;
       
   164 
       
   165         testlist = new ArrayList<>(testCount);
       
   166 
       
   167         // Enumerate all tests in all possible modes
       
   168         for (Class<? extends DefMethTest> testClass : DefMethTest.getTests()) {
       
   169             for (ExecutionMode mode : ExecutionMode.values()) {
       
   170                 // Skip REDEFINITION execmode, the top README file indicates that it isn't a
       
   171                 // valid execution mode and there's also no code supporting this in the test generator.
       
   172                 if ("REDEFINITION".equals(mode.toString())) {
       
   173                     continue;
       
   174                 }
       
   175 
       
   176                 for (int majorVer : majorVerValues) {
       
   177                     for (int flags : flagsValues ) {
       
   178                         for (boolean redefine : doRedefineValues) {
       
   179                             // RedefineTest isn't applicable to reflection-based execution scenario (REDEFINE & INVOKE_WITH_ARGS)
       
   180                             if (testClass == RedefineTest.class && mode.isReflectionBased()) {
       
   181                                 continue;
       
   182                             }
       
   183 
       
   184                             // Only run the RedefineTest tests when redefining
       
   185                             if (!redefine && testClass == RedefineTest.class) {
       
   186                                 continue;
       
   187                             }
       
   188 
       
   189                             try {
       
   190                                 DefMethTest test = testClass.newInstance();
       
   191 
       
   192                                 OptionSupport.setup(test, new String[] {
       
   193                                         "-execMode", mode.toString(),
       
   194                                         "-ver", Integer.toString(majorVer),
       
   195                                         "-flags", Integer.toString(flags),
       
   196                                         "-redefine", Boolean.toString(redefine),
       
   197                                         "-ignoreCrashes",
       
   198                                         "-ignoreKnownFailures",
       
   199                                         "-silent",
       
   200                                         "-failfast"});
       
   201 
       
   202                                 testlist.add(test);
       
   203                             } catch (InstantiationException | IllegalAccessException ex) {
       
   204                                 throw new TestFailure(ex);
       
   205                             }
       
   206                         }
       
   207                     }
       
   208                 }
       
   209             }
       
   210         }
       
   211 
       
   212         System.out.printf("Testlist size: %d\n", testlist.size());
       
   213     }
       
   214 
       
   215     private void startWorkers() {
       
   216         Random rand;
       
   217         if (seed == 0) {
       
   218             seed = (new Random()).nextInt();
       
   219         }
       
   220 
       
   221         System.out.printf("Seed: %d\n", seed);
       
   222         rand = new Random(seed);
       
   223 
       
   224         //Workaround for the deadlock caused by
       
   225         // JDK-7122142: "(ann) Race condition between isAnnotationPresent and getAnnotations"
       
   226         try {
       
   227             // Do a warm-up cycle
       
   228             for (Class<? extends DefMethTest> testClass : DefMethTest.getTests()) {
       
   229                 DefMethTest test = testClass.newInstance();
       
   230 
       
   231                 OptionSupport.setupAndRun(test,
       
   232                         new String[] { "-silent", "-ignoreKnownFailures"});
       
   233             }
       
   234         } catch(InstantiationException | IllegalAccessException e) {
       
   235             throw new RuntimeException(e);
       
   236         }
       
   237 
       
   238         int threadsCount = opts.getThreadsFactor();
       
   239         if (threadsCount == 1) {
       
   240             threadsCount = 5;
       
   241         }
       
   242 
       
   243         workers = new Worker[threadsCount];
       
   244 
       
   245         System.out.printf("Spawning %d workers...\n", workers.length);
       
   246 
       
   247         for (int i = 0; i < workers.length; i++) {
       
   248             workers[i] = new Worker(
       
   249                     String.format("Worker #%d/%d", i+1, workers.length),
       
   250                     rand.nextInt());
       
   251         }
       
   252 
       
   253         for (Worker worker : workers) {
       
   254             worker.start();
       
   255         }
       
   256     }
       
   257 
       
   258     private void interruptWorkers() {
       
   259         for (Worker worker : workers) {
       
   260             worker.interrupt();
       
   261         }
       
   262     }
       
   263 
       
   264     private void joinWorkers() {
       
   265         boolean isFailed = false;
       
   266 
       
   267         for (Worker worker : workers) {
       
   268             while (worker.isAlive()) {
       
   269                 try {
       
   270                     worker.join();
       
   271                 } catch (InterruptedException e) {}
       
   272             }
       
   273 
       
   274             System.out.printf("%s: %s (executed: %d)\n",
       
   275                     worker.getName(),
       
   276                     worker.isFailed() ? "FAILED: " + worker.getFailedTest() : "PASSED",
       
   277                     worker.getExecutedTests());
       
   278 
       
   279             if (worker.isFailed()) {
       
   280                 if (Constants.PRINT_STACK_TRACE) {
       
   281                     worker.getReason().printStackTrace();
       
   282                 }
       
   283 
       
   284                 isFailed = true;
       
   285             }
       
   286         }
       
   287 
       
   288         if (isFailed) {
       
   289             throw new TestFailure("Some of the worker threads failed.");
       
   290         }
       
   291     }
       
   292 
       
   293     private boolean workersAlive() {
       
   294         for (Worker worker : workers) {
       
   295             if (!worker.isAlive()) {
       
   296                 return false;
       
   297             }
       
   298         }
       
   299 
       
   300         return true;
       
   301     }
       
   302 
       
   303     private void printStats() {
       
   304         long[] counts = new long[workers.length];
       
   305         for (int i = 0; i < counts.length; i++) {
       
   306             counts[i] = workers[i].executedTests;
       
   307         }
       
   308 
       
   309         StringBuilder msg = new StringBuilder();
       
   310         msg.append(stresser.getTimeLeft() / 1000).append("s left: ");
       
   311         msg.append(Arrays.toString(counts));
       
   312 
       
   313         System.out.println(msg);
       
   314     }
       
   315 }