1 /*
   2  * Copyright (c) 2015, 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 
  25 package org.graalvm.compiler.core.test;
  26 
  27 import static org.graalvm.compiler.core.test.GraalCompilerTest.getInitialOptions;
  28 
  29 import java.lang.reflect.Method;
  30 import java.lang.reflect.Modifier;
  31 
  32 import org.graalvm.compiler.api.test.Graal;
  33 import org.graalvm.compiler.debug.DebugCloseable;
  34 import org.graalvm.compiler.debug.DebugHandlersFactory;
  35 import org.graalvm.compiler.debug.DebugContext;
  36 import org.graalvm.compiler.debug.GraalError;
  37 import org.graalvm.compiler.debug.Indent;
  38 import org.graalvm.compiler.graph.Node;
  39 import org.graalvm.compiler.java.GraphBuilderPhase;
  40 import org.graalvm.compiler.nodes.StructuredGraph;
  41 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
  42 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
  43 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
  44 import org.graalvm.compiler.options.OptionValues;
  45 import org.graalvm.compiler.phases.OptimisticOptimizations;
  46 import org.graalvm.compiler.phases.Phase;
  47 import org.graalvm.compiler.phases.PhaseSuite;
  48 import org.graalvm.compiler.phases.VerifyPhase.VerificationError;
  49 import org.graalvm.compiler.phases.tiers.HighTierContext;
  50 import org.graalvm.compiler.phases.util.Providers;
  51 import org.graalvm.compiler.runtime.RuntimeProvider;
  52 import org.junit.Test;
  53 
  54 import jdk.vm.ci.meta.MetaAccessProvider;
  55 import jdk.vm.ci.meta.ResolvedJavaMethod;
  56 
  57 public class VerifyDebugUsageTest {
  58 
  59     private static class InvalidLogUsagePhase extends Phase {
  60 
  61         @Override
  62         protected void run(StructuredGraph graph) {
  63             DebugContext debug = graph.getDebug();
  64             for (Node n : graph.getNodes()) {
  65                 debug.log("%s", n.toString());
  66             }
  67         }
  68 
  69     }
  70 
  71     private static class InvalidLogAndIndentUsagePhase extends Phase {
  72 
  73         @Override
  74         @SuppressWarnings("try")
  75         protected void run(StructuredGraph graph) {
  76             DebugContext debug = graph.getDebug();
  77             try (Indent i = debug.logAndIndent("%s", graph.toString())) {
  78                 for (Node n : graph.getNodes()) {
  79                     debug.log("%s", n);
  80                 }
  81             }
  82         }
  83 
  84     }
  85 
  86     private static class InvalidDumpUsagePhase extends Phase {
  87 
  88         @Override
  89         protected void run(StructuredGraph graph) {
  90             DebugContext debug = graph.getDebug();
  91             debug.dump(DebugContext.BASIC_LEVEL, graph, "%s", graph.toString());
  92         }
  93     }
  94 
  95     private static class InvalidDumpLevelPhase extends Phase {
  96 
  97         @Override
  98         protected void run(StructuredGraph graph) {
  99             DebugContext debug = graph.getDebug();
 100             debug.dump(DebugContext.VERY_DETAILED_LEVEL + 1, graph, "%s", graph);
 101         }
 102     }
 103 
 104     private static class NonConstantDumpLevelPhase extends Phase {
 105 
 106         @Override
 107         protected void run(StructuredGraph graph) {
 108             DebugContext debug = graph.getDebug();
 109             debug.dump(getLevel(), graph, "%s", graph);
 110         }
 111 
 112         int getLevel() {
 113             return 10;
 114         }
 115     }
 116 
 117     private static class InvalidVerifyUsagePhase extends Phase {
 118 
 119         @Override
 120         protected void run(StructuredGraph graph) {
 121             DebugContext debug = graph.getDebug();
 122             debug.verify(graph, "%s", graph.toString());
 123         }
 124 
 125     }
 126 
 127     private static class InvalidConcatLogUsagePhase extends Phase {
 128 
 129         @Override
 130         protected void run(StructuredGraph graph) {
 131             DebugContext debug = graph.getDebug();
 132             for (Node n : graph.getNodes()) {
 133                 debug.log("error " + n);
 134             }
 135         }
 136 
 137     }
 138 
 139     private static class InvalidConcatLogAndIndentUsagePhase extends Phase {
 140 
 141         @Override
 142         @SuppressWarnings("try")
 143         protected void run(StructuredGraph graph) {
 144             DebugContext debug = graph.getDebug();
 145             try (Indent i = debug.logAndIndent("error " + graph)) {
 146                 for (Node n : graph.getNodes()) {
 147                     debug.log("%s", n);
 148                 }
 149             }
 150         }
 151 
 152     }
 153 
 154     private static class InvalidConcatDumpUsagePhase extends Phase {
 155 
 156         @Override
 157         protected void run(StructuredGraph graph) {
 158             DebugContext debug = graph.getDebug();
 159             debug.dump(DebugContext.BASIC_LEVEL, graph, "error " + graph);
 160         }
 161 
 162     }
 163 
 164     private static class InvalidConcatVerifyUsagePhase extends Phase {
 165 
 166         @Override
 167         protected void run(StructuredGraph graph) {
 168             DebugContext debug = graph.getDebug();
 169             debug.verify(graph, "error " + graph);
 170         }
 171 
 172     }
 173 
 174     private static class ValidLogUsagePhase extends Phase {
 175 
 176         @Override
 177         protected void run(StructuredGraph graph) {
 178             DebugContext debug = graph.getDebug();
 179             for (Node n : graph.getNodes()) {
 180                 debug.log("%s", n);
 181             }
 182         }
 183 
 184     }
 185 
 186     private static class ValidLogAndIndentUsagePhase extends Phase {
 187 
 188         @Override
 189         @SuppressWarnings("try")
 190         protected void run(StructuredGraph graph) {
 191             DebugContext debug = graph.getDebug();
 192             try (Indent i = debug.logAndIndent("%s", graph)) {
 193                 for (Node n : graph.getNodes()) {
 194                     debug.log("%s", n);
 195                 }
 196             }
 197         }
 198 
 199     }
 200 
 201     private static class ValidDumpUsagePhase extends Phase {
 202 
 203         @Override
 204         protected void run(StructuredGraph graph) {
 205             DebugContext debug = graph.getDebug();
 206             debug.dump(DebugContext.BASIC_LEVEL, graph, "%s", graph);
 207         }
 208 
 209     }
 210 
 211     private static class ValidVerifyUsagePhase extends Phase {
 212 
 213         @Override
 214         protected void run(StructuredGraph graph) {
 215             DebugContext debug = graph.getDebug();
 216             debug.verify(graph, "%s", graph);
 217         }
 218 
 219     }
 220 
 221     private static class InvalidGraalErrorGuaranteePhase extends Phase {
 222         @Override
 223         protected void run(StructuredGraph graph) {
 224             GraalError.guarantee(graph.getNodes().count() > 0, "Graph must contain nodes %s %s %s", graph, graph, graph.toString());
 225         }
 226     }
 227 
 228     private static class ValidGraalErrorGuaranteePhase extends Phase {
 229         @Override
 230         protected void run(StructuredGraph graph) {
 231             GraalError.guarantee(graph.getNodes().count() > 0, "Graph must contain nodes %s", graph);
 232         }
 233     }
 234 
 235     public static Object sideEffect;
 236 
 237     private static class InvalidGraalErrorCtorPhase extends Phase {
 238         @Override
 239         protected void run(StructuredGraph graph) {
 240             sideEffect = new GraalError("No Error %s", graph.toString());
 241         }
 242     }
 243 
 244     private static class ValidGraalErrorCtorPhase extends Phase {
 245         @Override
 246         protected void run(StructuredGraph graph) {
 247             sideEffect = new GraalError("Error %s", graph);
 248         }
 249     }
 250 
 251     @Test(expected = VerificationError.class)
 252     public void testLogInvalid() {
 253         testDebugUsageClass(InvalidLogUsagePhase.class);
 254     }
 255 
 256     @Test(expected = VerificationError.class)
 257     public void testLogAndIndentInvalid() {
 258         testDebugUsageClass(InvalidLogAndIndentUsagePhase.class);
 259     }
 260 
 261     @Test(expected = VerificationError.class)
 262     public void testVerifyInvalid() {
 263         testDebugUsageClass(InvalidVerifyUsagePhase.class);
 264     }
 265 
 266     @Test(expected = VerificationError.class)
 267     public void testDumpInvalid() {
 268         testDebugUsageClass(InvalidDumpUsagePhase.class);
 269     }
 270 
 271     @Test(expected = VerificationError.class)
 272     public void testDumpLevelInvalid() {
 273         testDebugUsageClass(InvalidDumpLevelPhase.class);
 274     }
 275 
 276     @Test(expected = VerificationError.class)
 277     public void testDumpNonConstantLevelInvalid() {
 278         testDebugUsageClass(NonConstantDumpLevelPhase.class);
 279     }
 280 
 281     @Test(expected = VerificationError.class)
 282     public void testLogInvalidConcat() {
 283         testDebugUsageClass(InvalidConcatLogUsagePhase.class);
 284     }
 285 
 286     @Test(expected = VerificationError.class)
 287     public void testLogAndIndentInvalidConcat() {
 288         testDebugUsageClass(InvalidConcatLogAndIndentUsagePhase.class);
 289     }
 290 
 291     @Test(expected = VerificationError.class)
 292     public void testVerifyInvalidConcat() {
 293         testDebugUsageClass(InvalidConcatVerifyUsagePhase.class);
 294     }
 295 
 296     @Test(expected = VerificationError.class)
 297     public void testDumpInvalidConcat() {
 298         testDebugUsageClass(InvalidConcatDumpUsagePhase.class);
 299     }
 300 
 301     @Test
 302     public void testLogValid() {
 303         testDebugUsageClass(ValidLogUsagePhase.class);
 304     }
 305 
 306     @Test()
 307     public void testLogAndIndentValid() {
 308         testDebugUsageClass(ValidLogAndIndentUsagePhase.class);
 309     }
 310 
 311     @Test
 312     public void testVerifyValid() {
 313         testDebugUsageClass(ValidVerifyUsagePhase.class);
 314     }
 315 
 316     @Test
 317     public void testDumpValid() {
 318         testDebugUsageClass(ValidDumpUsagePhase.class);
 319     }
 320 
 321     @Test(expected = VerificationError.class)
 322     public void testGraalGuaranteeInvalid() {
 323         testDebugUsageClass(InvalidGraalErrorGuaranteePhase.class);
 324     }
 325 
 326     @Test
 327     public void testGraalGuaranteeValid() {
 328         testDebugUsageClass(ValidGraalErrorGuaranteePhase.class);
 329     }
 330 
 331     @Test(expected = VerificationError.class)
 332     public void testGraalCtorInvalid() {
 333         testDebugUsageClass(InvalidGraalErrorCtorPhase.class);
 334     }
 335 
 336     @Test
 337     public void testGraalCtorValid() {
 338         testDebugUsageClass(ValidGraalErrorCtorPhase.class);
 339     }
 340 
 341     @SuppressWarnings("try")
 342     private static void testDebugUsageClass(Class<?> c) {
 343         RuntimeProvider rt = Graal.getRequiredCapability(RuntimeProvider.class);
 344         Providers providers = rt.getHostBackend().getProviders();
 345         MetaAccessProvider metaAccess = providers.getMetaAccess();
 346         PhaseSuite<HighTierContext> graphBuilderSuite = new PhaseSuite<>();
 347         Plugins plugins = new Plugins(new InvocationPlugins());
 348         GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true).withUnresolvedIsError(true);
 349         graphBuilderSuite.appendPhase(new GraphBuilderPhase(config));
 350         HighTierContext context = new HighTierContext(providers, graphBuilderSuite, OptimisticOptimizations.NONE);
 351         OptionValues options = getInitialOptions();
 352         DebugContext debug = DebugContext.create(options, DebugHandlersFactory.LOADER);
 353         for (Method m : c.getDeclaredMethods()) {
 354             if (!Modifier.isNative(m.getModifiers()) && !Modifier.isAbstract(m.getModifiers())) {
 355                 ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m);
 356                 StructuredGraph graph = new StructuredGraph.Builder(options, debug).method(method).build();
 357                 graphBuilderSuite.apply(graph, context);
 358                 try (DebugCloseable s = debug.disableIntercept()) {
 359                     new VerifyDebugUsage().apply(graph, context);
 360                 }
 361             }
 362         }
 363     }
 364 }