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 package common;
  24 
  25 import com.oracle.java.testlibrary.Platform;
  26 import com.oracle.java.testlibrary.cli.CommandLineOptionTest;
  27 import sun.hotspot.code.BlobType;
  28 
  29 import java.util.Collections;
  30 import java.util.EnumSet;
  31 import java.util.LinkedList;
  32 import java.util.List;
  33 import java.util.function.Function;
  34 
  35 /**
  36  * Code cache related command line option test case consisting of description
  37  * of code heaps used during test case run and additional options that should
  38  * be passed to JVM and runner aimed to perform actual testing based on the
  39  * description.
  40  */
  41 public class CodeCacheCLITestCase {
  42     private static final Function<CodeCacheOptions, Boolean> ONLY_SEGMENTED
  43             = options -> options.segmented;
  44     private static final Function<CodeCacheOptions, Boolean> SEGMENTED_SERVER
  45             = ONLY_SEGMENTED.andThen(isSegmented -> isSegmented
  46                     && Platform.isServer() && Platform.isTieredSupported());
  47     private static final String USE_INT_MODE = "-Xint";
  48     private static final String SEGMENTED_CODE_CACHE = "SegmentedCodeCache";
  49     private static final String TIERED_COMPILATION = "TieredCompilation";
  50     private static final String TIERED_STOP_AT = "TieredStopAtLevel";
  51 
  52     private final Description description;
  53     private final Runner runner;
  54 
  55     public CodeCacheCLITestCase(Description description, Runner runner) {
  56         this.description = description;
  57         this.runner = runner;
  58     }
  59 
  60     public final void run(CodeCacheOptions options) throws Throwable {
  61         if (description.isApplicable(options)) {
  62             runner.run(description, options);
  63         }
  64     }
  65 
  66     public enum CommonDescriptions {
  67         /**
  68          * Verifies that in interpreted mode PrintCodeCache output contains
  69          * only NonNMethod code heap.
  70          */
  71         INT_MODE(ONLY_SEGMENTED, EnumSet.of(BlobType.NonNMethod), USE_INT_MODE),
  72         /**
  73          * Verifies that with disabled SegmentedCodeCache PrintCodeCache output
  74          * contains only CodeCache's entry.
  75          */
  76         NON_SEGMENTED(options -> !options.segmented, EnumSet.of(BlobType.All),
  77                 CommandLineOptionTest.prepareBooleanFlag(SEGMENTED_CODE_CACHE,
  78                         false)),
  79         /**
  80          * Verifies that with disabled tiered compilation and enabled segmented
  81          * code cache PrintCodeCache output does not contain information about
  82          * profiled-nmethods heap and non-segmented CodeCache.
  83          */
  84         NON_TIERED(ONLY_SEGMENTED,
  85                 EnumSet.of(BlobType.NonNMethod, BlobType.MethodNonProfiled),
  86                 CommandLineOptionTest.prepareBooleanFlag(TIERED_COMPILATION,
  87                         false)),
  88         /**
  89          * Verifies that with TieredStopAtLevel=0 PrintCodeCache output will
  90          * contain information about non-nmethods and non-profiled nmethods
  91          * heaps only.
  92          */
  93         TIERED_LEVEL_0(SEGMENTED_SERVER,
  94                 EnumSet.of(BlobType.NonNMethod, BlobType.MethodNonProfiled),
  95                 CommandLineOptionTest.prepareBooleanFlag(TIERED_COMPILATION,
  96                         true),
  97                 CommandLineOptionTest.prepareNumericFlag(TIERED_STOP_AT, 0)),
  98         /**
  99          * Verifies that with TieredStopAtLevel=1 PrintCodeCache output will
 100          * contain information about non-nmethods and non-profiled nmethods
 101          * heaps only.
 102          */
 103         TIERED_LEVEL_1(SEGMENTED_SERVER,
 104                 EnumSet.of(BlobType.NonNMethod, BlobType.MethodNonProfiled),
 105                 CommandLineOptionTest.prepareBooleanFlag(TIERED_COMPILATION,
 106                         true),
 107                 CommandLineOptionTest.prepareNumericFlag(TIERED_STOP_AT, 1)),
 108         /**
 109          * Verifies that with TieredStopAtLevel=4 PrintCodeCache output will
 110          * contain information about all three code heaps.
 111          */
 112         TIERED_LEVEL_4(SEGMENTED_SERVER,
 113                 EnumSet.complementOf(EnumSet.of(BlobType.All)),
 114                 CommandLineOptionTest.prepareBooleanFlag(TIERED_COMPILATION,
 115                         true),
 116                 CommandLineOptionTest.prepareNumericFlag(TIERED_STOP_AT, 4));
 117 
 118         CommonDescriptions(Function<CodeCacheOptions, Boolean> predicate,
 119                 EnumSet<BlobType> involvedCodeHeaps,
 120                 String... additionalOptions) {
 121             this.description = new Description(predicate,
 122                     involvedCodeHeaps, additionalOptions);
 123         }
 124 
 125 
 126         public final Description description;
 127     }
 128 
 129     public static class Description {
 130         public final EnumSet<BlobType> involvedCodeHeaps;
 131         private final String[] testCaseSpecificOptions;
 132         private final Function<CodeCacheOptions, Boolean> predicate;
 133 
 134         public Description(Function<CodeCacheOptions, Boolean> predicate,
 135                 EnumSet<BlobType> involvedCodeHeaps,
 136                 String... testCaseSpecificOptions) {
 137             this.involvedCodeHeaps = involvedCodeHeaps;
 138             this.testCaseSpecificOptions = testCaseSpecificOptions;
 139             this.predicate = predicate;
 140         }
 141 
 142         public boolean isApplicable(CodeCacheOptions options) {
 143             return predicate.apply(options);
 144         }
 145 
 146         public CodeCacheOptions expectedValues(CodeCacheOptions options) {
 147             return options.mapOptions(involvedCodeHeaps);
 148         }
 149 
 150         public String[] getTestOptions(CodeCacheOptions codeCacheOptions,
 151                 String... additionalOptions) {
 152             List<String> options = new LinkedList<>();
 153             Collections.addAll(options, testCaseSpecificOptions);
 154             Collections.addAll(options, additionalOptions);
 155             return codeCacheOptions.prepareOptions(
 156                     options.toArray(new String[options.size()]));
 157         }
 158     }
 159 
 160     public static interface Runner {
 161         public void run(Description testCaseDescription,
 162                 CodeCacheOptions options) throws Throwable;
 163     }
 164 }
 165