1 /*
2  * Copyright (c) 2015, 2017, 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 test.java.lang.invoke.lib;
25 
26 // Android-added: import of Function for filterException
27 import java.util.function.Function;
28 
29 /**
30  * Helper class used to catch and process VirtualMachineError with message "Out
31  * of space in CodeCache". Some JSR292 tests run out of code cache size, so code
32  * cache overflows and VME is thrown. This VME is considered as non-critical in
33  * some JSR292 tests, so it should be processed to prevent test failure.
34  */
35 public class CodeCacheOverflowProcessor {
36 
37     /**
38      * Checks if an instance of Throwable is caused by VirtualMachineError with
39      * message "Out of space in CodeCache". May be used as filter in method
40      * {@code jdk.testlibrary.Utils.filterException}.
41      *
42      * @param t - Throwable to check.
43      * @return true if Throwable is caused by VME, false otherwise.
44      */
isThrowableCausedByVME(Throwable t)45     public static Boolean isThrowableCausedByVME(Throwable t) {
46         Throwable causeOfT = t;
47         do {
48             if (causeOfT instanceof VirtualMachineError
49                     && causeOfT.getMessage().matches(".*[Oo]ut of space"
50                             + " in CodeCache.*")) {
51                 return true;
52             }
53             causeOfT = causeOfT != null ? causeOfT.getCause() : null;
54         } while (causeOfT != null && causeOfT != t);
55         return false;
56     }
57 
58     /**
59      * Checks if the given test throws an exception caused by
60      * VirtualMachineError with message "Out of space in CodeCache", and, if VME
61      * takes place, processes it so that no exception is thrown, and prints its
62      * stack trace. If test throws exception not caused by VME, this method just
63      * re-throws this exception.
64      *
65      * @param test - test to check for and process VirtualMachineError.
66      * @return - an exception caused by VME or null
67      *           if test has thrown no exception.
68      * @throws Throwable - if test has thrown an exception
69      *                     that is not caused by VME.
70      */
runMHTest(ThrowingRunnable test)71     public static Throwable runMHTest(ThrowingRunnable test) throws Throwable {
72         Throwable t = filterException(test::run,
73                 CodeCacheOverflowProcessor::isThrowableCausedByVME);
74         if (t != null) {
75             System.err.printf("%nNon-critical exception caught becuse of"
76                     + " code cache size is not enough to run all test cases.%n%n");
77         }
78         return t;
79     }
80 
81     // BEGIN Android-changed: these interfaces methods taken from jdk.testlibrary
82     /**
83      * Interface same as java.lang.Runnable but with
84      * method {@code run()} able to throw any Throwable.
85      */
86     public static interface ThrowingRunnable {
run()87         void run() throws Throwable;
88     }
89 
90     /**
91      * Filters out an exception that may be thrown by the given
92      * test according to the given filter.
93      *
94      * @param test - method that is invoked and checked for exception.
95      * @param filter - function that checks if the thrown exception matches
96      *                 criteria given in the filter's implementation.
97      * @return - exception that matches the filter if it has been thrown or
98      *           {@code null} otherwise.
99      * @throws Throwable - if test has thrown an exception that does not
100      *                     match the filter.
101      */
filterException(ThrowingRunnable test, Function<Throwable, Boolean> filter)102     public static Throwable filterException(ThrowingRunnable test,
103                                             Function<Throwable, Boolean> filter) throws Throwable {
104         try {
105             test.run();
106         } catch (Throwable t) {
107             if (filter.apply(t)) {
108                 return t;
109             } else {
110                 throw t;
111             }
112         }
113         return null;
114     }
115     // END Android-changed: these interfaces methods taken from jdk.testlibrary
116 }
117