1 /*
   2  * Copyright (c) 2015, 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  * @bug 8135068
  27  * @summary Tests CompilerCommand's method matcher
  28  * @modules java.base/jdk.internal.misc
  29  * @library /testlibrary /test/lib ../share /
  30  * @build compiler.compilercontrol.matcher.MethodMatcherTest
  31  * @run driver ClassFileInstaller sun.hotspot.WhiteBox
  32  *                                sun.hotspot.WhiteBox$WhiteBoxPermission
  33  * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
  34  *           -XX:+WhiteBoxAPI compiler.compilercontrol.matcher.MethodMatcherTest
  35  */
  36 
  37 package compiler.compilercontrol.matcher;
  38 
  39 import jdk.test.lib.Pair;
  40 import compiler.compilercontrol.share.method.MethodDescriptor;
  41 import compiler.compilercontrol.share.method.MethodGenerator;
  42 import pool.PoolHelper;
  43 import sun.hotspot.WhiteBox;
  44 
  45 import java.lang.reflect.Executable;
  46 import java.util.ArrayList;
  47 import java.util.List;
  48 import java.util.concurrent.Callable;
  49 import java.util.regex.Matcher;
  50 import java.util.regex.Pattern;
  51 
  52 public class MethodMatcherTest {
  53     private static final WhiteBox WB = WhiteBox.getWhiteBox();
  54     private static final PoolHelper POOL = new PoolHelper();
  55     private static final List<Pair<Executable, Callable<?>>> METHODS =
  56             POOL.getAllMethods();
  57     private static final int AMOUNT = Integer.parseInt(System
  58             .getProperty("test.amount", "25"));
  59 
  60     public static void main(String[] args) {
  61         MethodGenerator gen = new MethodGenerator();
  62         List<Pair<Executable, Callable<?>>> testMethods =
  63                 POOL.getAllMethods(PoolHelper.METHOD_FILTER);
  64         for (Pair<Executable, Callable<?>> pair : testMethods) {
  65             for (int i = 0; i < AMOUNT; i++) {
  66                 MethodDescriptor md = gen.generateRandomDescriptor(pair.first);
  67                 check(md);
  68             }
  69         }
  70     }
  71 
  72     /**
  73      * Check method matcher with given test case
  74      *
  75      * @param methodDescriptor method descriptor to check matcher's pattern
  76      */
  77     private static void check(MethodDescriptor methodDescriptor) {
  78         System.out.println("Test case: " + methodDescriptor.getString());
  79         System.out.println("Regex: " + methodDescriptor.getRegexp());
  80         Pattern pattern = Pattern.compile(methodDescriptor.getRegexp());
  81         boolean isValidDesc = methodDescriptor.isValid();
  82         List<MethodDescriptor> failList = new ArrayList<>();
  83         // walk through all methods in pool to check match with test pattern
  84         for (Pair<Executable, Callable<?>> pair : METHODS) {
  85             MethodDescriptor m = MethodGenerator.commandDescriptor(pair.first);
  86             Matcher matcher = pattern.matcher(m.getCanonicalString());
  87             // get expected result
  88             MatcherResult expected;
  89             if (isValidDesc) {
  90                 expected = matcher.matches() ?
  91                         MatcherResult.MATCH : MatcherResult.NO_MATCH;
  92             } else {
  93                 expected = MatcherResult.PARSING_FAILURE;
  94             }
  95             // get MethodMatcher's result
  96             MatcherResult matchResult = MatcherResult.fromCode(WB.matchesMethod(
  97                     pair.first, methodDescriptor.getString()));
  98             // compare
  99             if (matchResult != expected) {
 100                 System.out.printf("- Method: %s%n-- FAILED: result: %s, " +
 101                                 "but expected: %s%n", m.getCanonicalString(),
 102                         matchResult, expected);
 103                 failList.add(m);
 104             }
 105         }
 106         int size = failList.size();
 107         if (size != 0) {
 108             System.err.println("FAILED test case: " + methodDescriptor
 109                     .getString());
 110             if (size == METHODS.size()) {
 111                 System.err.println("-- All methods failed to match");
 112             } else {
 113                 for (MethodDescriptor md : failList) {
 114                     System.err.println("-- FAILED match: " + md.getString());
 115                 }
 116             }
 117             throw new AssertionError("FAIL: " + methodDescriptor.getString());
 118         }
 119         System.out.println("--PASSED");
 120     }
 121 
 122     /**
 123      * Represents MethodMatcher's matching result
 124      */
 125     public enum MatcherResult {
 126         PARSING_FAILURE(-1, "Parsing failed"),
 127         NO_MATCH(0, "No match"),
 128         MATCH(1, "Match");
 129 
 130         public final int code;
 131         private final String message;
 132 
 133         private MatcherResult(int code, String message) {
 134             this.code = code;
 135             this.message = message;
 136         }
 137 
 138         public static MatcherResult fromCode(int code) {
 139             switch (code) {
 140                 case -1: return PARSING_FAILURE;
 141                 case  0: return NO_MATCH;
 142                 case  1: return MATCH;
 143                 default:
 144                     throw new IllegalArgumentException("MATCHER FAILURE:"
 145                             + "Wrong code: " + code);
 146             }
 147         }
 148 
 149         @Override
 150         public String toString() {
 151             return message;
 152         }
 153     }
 154 }