1 /*
   2  * Copyright (c) 2007, 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 package vm.oom;
  24 
  25 import nsk.share.TestFailure;
  26 import nsk.share.test.*;
  27 import nsk.share.gc.*;
  28 import java.util.List;
  29 import java.util.ArrayList;
  30 import vm.share.stack.StackUtils;
  31 
  32 public abstract class OOMTraceTest extends GCTestBase {
  33     protected abstract OutOfMemoryError createOOM();
  34     private List<StackTraceElement> expectedTrace = new ArrayList<StackTraceElement>();
  35     private boolean expectOOM = true;
  36     private Stresser stresser;
  37 
  38     protected void initExpectedTrace() {
  39         addExpectedTraceElement(OOMTraceTest.class.getName(), "run", false);
  40         addExpectedTraceElement(OOMTraceTest.class.getName(), "run1", false);
  41         addExpectedTraceElement(null, "createOOM", false);
  42     }
  43 
  44     protected void addExpectedTraceElement(String className, String methodName, boolean nativeMethod) {
  45         StackUtils.addExpectedTraceElement(expectedTrace, className, methodName, nativeMethod);
  46     }
  47 
  48     /**
  49      * Verify that all elements from expectedTrace occur somewhere
  50      * in the stack trace.
  51      */
  52     protected void checkExpectedTraceElements(StackTraceElement[] elements) {
  53         try {
  54             if (expectedTrace.size() == 0)
  55                 return;
  56             log.info("Expected part of stack trace:");
  57             StackUtils.printStackTrace(log, expectedTrace);
  58             int i = StackUtils.findMatch(elements, expectedTrace.get(expectedTrace.size() - 1));
  59             if (i == -1)
  60                 throw new TestFailure("Expected element not found: " + StackUtils.strStackTraceElement(expectedTrace.get(0)));
  61             log.info("Found first expected element at index " + i);
  62             StackUtils.checkMatches(elements, expectedTrace, i);
  63         } catch (TestFailure e) {
  64             throw e;
  65         }
  66     }
  67 
  68     protected boolean isAlwaysOOM() {
  69         return expectOOM;
  70     }
  71 
  72     protected void dontExpectOOM() {
  73         expectOOM = false;
  74     }
  75 
  76     protected boolean continueExecution() {
  77         return stresser.continueExecution();
  78     }
  79 
  80     protected void checkOOM(OutOfMemoryError oom) {
  81         log.info("Checking stack trace.");
  82         StackTraceElement[] elements = oom.getStackTrace();
  83         log.info("Actual stack trace:");
  84         StackUtils.printStackTrace(log, elements);
  85         checkExpectedTraceElements(elements);
  86         checkStackTraceElements(elements);
  87     }
  88 
  89     protected void checkStackTraceElements(StackTraceElement[] elements) {
  90         if (elements == null)
  91             throw new TestFailure("OutOfMemoryError has null stack trace");
  92         if (elements.length == 0)
  93             throw new TestFailure("OutOfMemoryError has stack trace of length 0");
  94         if (elements.length == 1)
  95             throw new TestFailure("OutOfMemoryError has stack trace of length 1");
  96     }
  97 
  98     public void run1() {
  99         OutOfMemoryError oom = createOOM();
 100         if (oom == null) {
 101             if (isAlwaysOOM())
 102                 throw new TestFailure("No OOM is obtained.");
 103             else {
 104                 log.info("OOM is not obtained, skipping");
 105                 return;
 106             }
 107         }
 108         log.info("OutOfMemoryError is obtained:");
 109         log.info(oom);
 110         checkOOM(oom);
 111         log.info("Verification of OOM passed");
 112     }
 113 
 114     public void run() {
 115         initExpectedTrace();
 116 
 117         stresser = new Stresser(runParams.getStressOptions());
 118         stresser.start(runParams.getIterations());
 119 
 120         while (stresser.iteration()) {
 121             run1();
 122         }
 123 
 124         stresser.finish();
 125 
 126         log.info("TEST PASSED");
 127     }
 128 }