/* * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.oracle.truffle.api.instrumentation.test.examples; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.io.IOException; import java.util.concurrent.atomic.AtomicBoolean; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import com.oracle.truffle.api.instrumentation.EventContext; import com.oracle.truffle.api.instrumentation.TruffleInstrument; import com.oracle.truffle.api.instrumentation.test.AbstractInstrumentationTest; import com.oracle.truffle.api.instrumentation.test.examples.DebuggerController.Callback; import com.oracle.truffle.api.source.Source; import com.oracle.truffle.api.vm.PolyglotRuntime; import com.oracle.truffle.api.vm.PolyglotRuntime.Instrument; public final class DebuggerExampleTest extends AbstractInstrumentationTest { private DebuggerController debugger; @Before public void setupDebugger() throws IOException { // BEGIN: DebuggerExampleTest PolyglotRuntime runtime = engine.getRuntime(); Instrument instrument = runtime.getInstruments().get(DebuggerExample.ID); assert !instrument.isEnabled() : "Not enabled yet"; debugger = instrument.lookup(DebuggerController.class); assert instrument.isEnabled() : "Got enabled"; assert debugger != null : "We can control the debugger"; // END: DebuggerExampleTest assertTrue("Enabled by requesting registered services class", instrument.isEnabled()); assertNotNull("Debugger interface found", debugger); DebuggerExample itself = instrument.lookup(DebuggerExample.class); assertNull("Debugger instrument itself isn't found", itself); TruffleInstrument instr = instrument.lookup(TruffleInstrument.class); assertNull("Instrument itself isn't found", instr); assertEvalOut("", ""); // ensure debugger gets loaded } @Test public void testBreakpoint() throws IOException { final AtomicBoolean breakpointHit = new AtomicBoolean(); debugger.installBreakpoint(1, new Callback() { @Override public void halted(DebuggerController d, EventContext haltedAt) { Assert.assertEquals(1, haltedAt.getInstrumentedSourceSection().getStartLine()); breakpointHit.set(true); } }); run(lines("BLOCK(STATEMENT,", "STATEMENT,", "STATEMENT)")); Assert.assertTrue(breakpointHit.get()); } @Test @SuppressWarnings("hiding") public void testStepInto() throws IOException { Source source = lines("ROOT(", // 1 "DEFINE(foo,STATEMENT),", // 2 "DEFINE(bar", // 3 /**/",STATEMENT", // 4 /**/",STATEMENT(CALL(foo))", // 5 /**/",STATEMENT),", // 6 "STATEMENT(CALL(bar)))"); // 7 final AtomicBoolean allStepped = new AtomicBoolean(); debugger.installBreakpoint(7, new Callback() { public void halted(DebuggerController debugger, EventContext haltedAt) { assertLineAt(haltedAt, 7); debugger.stepInto(new Callback() { public void halted(DebuggerController debugger, EventContext haltedAt) { assertLineAt(haltedAt, 4); debugger.stepInto(new Callback() { public void halted(DebuggerController debugger, EventContext haltedAt) { assertLineAt(haltedAt, 5); debugger.stepInto(new Callback() { public void halted(DebuggerController debugger, EventContext haltedAt) { assertLineAt(haltedAt, 2); debugger.stepInto(new Callback() { public void halted(DebuggerController debugger, EventContext haltedAt) { assertLineAt(haltedAt, 6); debugger.stepInto(new Callback() { public void halted(DebuggerController debugger, EventContext haltedAt) { throw new AssertionError(); } }); allStepped.set(true); } }); } }); } }); } }); } }); run(source); Assert.assertTrue(allStepped.get()); } private static void assertLineAt(EventContext haltedAt, int index) { Assert.assertEquals(index, haltedAt.getInstrumentedSourceSection().getStartLine()); } @Test @SuppressWarnings("hiding") public void testStepOver() throws IOException { Source source = lines("ROOT(", // 1 "DEFINE(foo,STATEMENT),", // 2 "DEFINE(bar", // 3 /**/",STATEMENT", // 4 /**/",STATEMENT(CALL(foo))", // 5 /**/",STATEMENT),", // 6 "STATEMENT(CALL(bar)))"); // 7 final AtomicBoolean allStepped = new AtomicBoolean(); debugger.installBreakpoint(4, new Callback() { public void halted(DebuggerController debugger, EventContext haltedAt) { assertLineAt(haltedAt, 4); debugger.stepOver(new Callback() { public void halted(DebuggerController debugger, EventContext haltedAt) { assertLineAt(haltedAt, 5); debugger.stepOver(new Callback() { public void halted(DebuggerController debugger, EventContext haltedAt) { assertLineAt(haltedAt, 6); allStepped.set(true); debugger.stepOver(new Callback() { public void halted(DebuggerController debugger, EventContext haltedAt) { throw new AssertionError(); } }); } }); } }); } }); run(source); Assert.assertTrue(allStepped.get()); } @Test @SuppressWarnings("hiding") public void testStepOut() throws IOException { Source source = lines("ROOT(", // 1 "DEFINE(foo,STATEMENT),", // 2 "DEFINE(bar", // 3 /**/",STATEMENT", // 4 /**/",STATEMENT(CALL(foo))", // 5 /**/",STATEMENT),", // 6 "STATEMENT(CALL(bar)))"); // 7 final AtomicBoolean allStepped = new AtomicBoolean(); debugger.installBreakpoint(2, new Callback() { @Override public void halted(DebuggerController debugger, EventContext haltedAt) { assertLineAt(haltedAt, 2); debugger.stepOut(new Callback() { @Override public void halted(DebuggerController debugger, EventContext haltedAt) { assertLineAt(haltedAt, 6); debugger.stepOver(new Callback() { @Override public void halted(DebuggerController debugger, EventContext haltedAt) { throw new AssertionError(); } }); allStepped.set(true); } }); } }); run(source); Assert.assertTrue(allStepped.get()); } }