/** * Expects the current evaluation to be completed successfully and not be killed or to produce * further suspended events. It returns a string representation of the result value to be * asserted. If the evaluation caused any errors they are thrown as {@link AssertionError}. * Throws an {@link IllegalStateException} if the tester is already closed. * * @since 0.16 */ public String expectDone() { return (String) expectDoneImpl(false); }
/** * Get {@link com.oracle.truffle.api.source.Source Truffle Source} that corresponds to the * {@link Source Polyglot Source}. This is a bridge between the two Source implementations. * * @since 0.28 */ public static com.oracle.truffle.api.source.Source getSourceImpl(Source source) { return (com.oracle.truffle.api.source.Source) getField(source, "impl"); }
trace("sourceString = '" + sourceString + "'"); com.oracle.truffle.api.source.Source tsource = DebuggerTester.getSourceImpl(source); for (int l = 1; l < source.getLineCount(); l++) { if (!bps.containsKey(l)) { int lineResolved = source.getLineNumber(indexResolved - 1); if (TRACE) { trace("TESTING breakpoint '" + line + "' => " + lineResolved + ":"); try (DebuggerSession session = startSession()) { startEval(source); int[] resolvedIndexPtr = new int[]{0}; Breakpoint breakpoint = session.install(Breakpoint.newBuilder(tsource).lineIs(line).oneShot().resolveListener(new Breakpoint.ResolveListener() { expectSuspended((SuspendedEvent event) -> { Assert.assertEquals("Expected " + line + " => " + lineResolved, lineResolved, event.getSourceSection().getStartLine()); event.prepareContinue(); }); expectDone(); Assert.assertEquals("Expected resolved " + line + " => " + indexResolved, indexResolved, resolvedIndexPtr[0]);
private void assertBreakpoints(Source source, List<Breakpoint> breakpoints, Set<Breakpoint> breakpointsResolved, List<Breakpoint> breakpointsHit) { try (DebuggerSession session = startSession()) { for (Breakpoint breakpoint : breakpoints) { session.install(breakpoint); } startEval(source); while (breakpointsHit.size() != breakpoints.size()) { expectSuspended((SuspendedEvent event) -> { breakpointsHit.addAll(event.getBreakpoints()); event.prepareContinue(); }); } expectDone(); } Assert.assertEquals(breakpoints.size(), breakpointsResolved.size()); Assert.assertEquals(breakpoints.size(), breakpointsHit.size()); }
notifyNextAction(); Object event; try { event = takeEvent(); // waits for next event. String e = getErr(); if (!e.isEmpty()) { throw new AssertionError("Error output is not empty: " + e);
com.oracle.truffle.api.source.Source tsource = DebuggerTester.getSourceImpl(source); final List<Breakpoint> breakpoints = new ArrayList<>(); final Set<Breakpoint> breakpointsResolved = new HashSet<>(); breakpoints.add(breakpoint); assertBreakpoints(source, breakpoints, breakpointsResolved, breakpointsHit); assertBreakpoints(source, breakpoints, breakpointsResolved, breakpointsHit);
/** * Starts a new {@link Debugger#startSession(SuspendedCallback, SourceElement...) debugger * session} in the context's {@link Engine engine}. The debugger session allows to suspend the * execution on the provided source elements and to install breakpoints. If multiple sessions * are created for one {@link #startEval(Source) evaluation} then all suspended events are * delegated to this debugger tester instance. * * @param sourceElements a list of source elements * @return a new debugger session * @since 0.33 */ public DebuggerSession startSession(SourceElement... sourceElements) { return getDebugger().startSession(new SuspendedCallback() { public void onSuspend(SuspendedEvent event) { DebuggerTester.this.onSuspend(event); } }, sourceElements); }
/** * Expects the current evaluation to be killed and not be completed or to produce further * suspended events. Throws an {@link IllegalStateException} if the tester is already closed. If * the evaluation caused any errors besides the kill exception then they are thrown as * {@link AssertionError}. * * @since 0.16 */ public void expectKilled() { Throwable error = expectThrowable(); if (error instanceof PolyglotException) { Assert.assertTrue(error.getMessage(), error.getMessage().contains("KillException")); return; } throw new AssertionError("Expected killed bug got error: " + error, error); }
/** * Opens {@code declaringClass}'s package to allow a method declared in {@code accessor} to call * {@link AccessibleObject#setAccessible(boolean)} on an {@link AccessibleObject} representing a * field or method declared by {@code declaringClass}. */ private static void openForReflectionTo(Class<?> declaringClass, Class<?> accessor) { try { Method getModule = Class.class.getMethod("getModule"); Class<?> moduleClass = getModule.getReturnType(); Class<?> modulesClass = Class.forName("jdk.internal.module.Modules"); Method addOpens = maybeGetAddOpensMethod(moduleClass, modulesClass); if (addOpens != null) { Object moduleToOpen = getModule.invoke(declaringClass); Object accessorModule = getModule.invoke(accessor); if (moduleToOpen != accessorModule) { addOpens.invoke(null, moduleToOpen, declaringClass.getPackage().getName(), accessorModule); } } } catch (Exception e) { throw new AssertionError(e); } }
trace("sourceString = '" + sourceString + "'"); int column = source.getColumnNumber(bp[0] - 1); if (TRACE) { trace("TESTING BP_" + bpId + ": " + bp[0] + " (" + line + ":" + column + ") => " + bp[1] + ":"); try (DebuggerSession session = startSession()) { startEval(source); int[] resolvedIndexPtr = new int[]{0}; Breakpoint breakpoint = session.install( Breakpoint.newBuilder(DebuggerTester.getSourceImpl(source)).lineIs(line).columnIs(column).oneShot().resolveListener(new Breakpoint.ResolveListener() { @Override public void breakpointResolved(Breakpoint brkp, SourceSection section) { expectSuspended((SuspendedEvent event) -> { Assert.assertEquals("Expected " + bp[0] + " => " + bp[1] + ", resolved at " + resolvedIndexPtr[0], bp[1], event.getSourceSection().getCharIndex() + 1); event.prepareContinue(); }); expectDone(); Assert.assertEquals("Expected resolved " + bp[0] + " => " + bp[1], bp[1], resolvedIndexPtr[0]);
private void assertBreakpoints(Source source, List<Breakpoint> breakpoints, Set<Breakpoint> breakpointsResolved, List<Breakpoint> breakpointsHit) { try (DebuggerSession session = startSession(new SourceElement[0])) { for (Breakpoint breakpoint : breakpoints) { session.install(breakpoint); } startEval(source); while (breakpointsHit.size() != breakpoints.size()) { try { expectSuspended((SuspendedEvent event) -> { breakpointsHit.addAll(event.getBreakpoints()); event.prepareContinue(); }); } catch (Throwable t) { Set<Breakpoint> notHit = new HashSet<>(breakpoints); notHit.removeAll(breakpointsHit); for (Breakpoint b : notHit) { err("Not hit " + b + ": " + b.getLocationDescription()); } err("---"); for (Breakpoint b : breakpointsHit) { err("Hit " + b + ": " + b.getLocationDescription()); } throw t; } } expectDone(); } Assert.assertEquals(breakpoints.size(), breakpointsResolved.size()); Assert.assertEquals(breakpoints.size(), breakpointsHit.size()); }
notifyNextAction(); Object event; try { event = takeEvent(); String e = getErr(); if (!e.isEmpty()) { throw new AssertionError("Error output is not empty: " + e);
com.oracle.truffle.api.source.Source tsource = DebuggerTester.getSourceImpl(source); final List<Breakpoint> breakpoints = new ArrayList<>(); final Set<Breakpoint> breakpointsResolved = new HashSet<>(); breakpoints.add(breakpoint); assertBreakpoints(source, breakpoints, breakpointsResolved, breakpointsHit); assertBreakpoints(source, breakpoints, breakpointsResolved, breakpointsHit);
/** * Starts a new {@link Debugger#startSession(SuspendedCallback) debugger session} in the * context's {@link Engine engine}. The debugger session allows to suspend the execution and to * install breakpoints. If multiple sessions are created for one {@link #startEval(Source) * evaluation} then all suspended events are delegated to this debugger tester instance. * * @return a new debugger session * @since 0.16 */ public DebuggerSession startSession() { return getDebugger().startSession(new SuspendedCallback() { public void onSuspend(SuspendedEvent event) { DebuggerTester.this.onSuspend(event); } }); }
/** * Expects the current evaluation to be killed and not be completed or to produce further * suspended events. Throws an {@link IllegalStateException} if the tester is already closed. If * the evaluation caused any errors besides the kill exception then they are thrown as * {@link AssertionError}. * * @since 0.16 */ public void expectKilled() { Throwable error = expectThrowable(); if (error instanceof PolyglotException) { Assert.assertTrue(((PolyglotException) error).isCancelled()); Assert.assertTrue(error.getMessage(), error.getMessage().contains("Execution cancelled by a debugging session.")); return; } throw new AssertionError("Expected killed bug got error: " + error, error); }
/** * Opens {@code declaringClass}'s package to allow a method declared in {@code accessor} to call * {@link AccessibleObject#setAccessible(boolean)} on an {@link AccessibleObject} representing a * field or method declared by {@code declaringClass}. */ private static void openForReflectionTo(Class<?> declaringClass, Class<?> accessor) { try { Method getModule = Class.class.getMethod("getModule"); Class<?> moduleClass = getModule.getReturnType(); Class<?> modulesClass = Class.forName("jdk.internal.module.Modules"); Method addOpens = maybeGetAddOpensMethod(moduleClass, modulesClass); if (addOpens != null) { Object moduleToOpen = getModule.invoke(declaringClass); Object accessorModule = getModule.invoke(accessor); if (moduleToOpen != accessorModule) { addOpens.invoke(null, moduleToOpen, declaringClass.getPackage().getName(), accessorModule); } } } catch (Exception e) { throw new AssertionError(e); } }
trace("sourceString = '" + sourceString + "'"); int column = source.getColumnNumber(bp[0] - 1); if (TRACE) { trace("TESTING BP_" + bpId + ": " + bp[0] + " (" + line + ":" + column + ") => " + bp[1] + ":"); try (DebuggerSession session = startSession()) { startEval(source); int[] resolvedIndexPtr = new int[]{0}; Breakpoint breakpoint = session.install( Breakpoint.newBuilder(DebuggerTester.getSourceImpl(source)).lineIs(line).columnIs(column).oneShot().resolveListener(new Breakpoint.ResolveListener() { @Override public void breakpointResolved(Breakpoint brkp, SourceSection section) { expectSuspended((SuspendedEvent event) -> { Assert.assertEquals("Expected " + bp[0] + " => " + bp[1] + ", resolved at " + resolvedIndexPtr[0], bp[1], event.getSourceSection().getCharIndex() + 1); event.prepareContinue(); }); expectDone(); Assert.assertEquals("Expected resolved " + bp[0] + " => " + bp[1], bp[1], resolvedIndexPtr[0]);
notifyNextAction(); Object event; try { event = takeEvent(); String e = getErr(); if (!e.isEmpty()) { throw new AssertionError("Error output is not empty: " + e);
/** * Expects the current evaluation to be completed with an error and not be killed or to produce * further suspended events. It returns a string representation of the result value to be * asserted. If the evaluation caused any errors they are thrown as {@link AssertionError}. * Throws an {@link IllegalStateException} if the tester is already closed. * * @since 0.16 */ public Throwable expectThrowable() { return (Throwable) expectDoneImpl(true); }
/** * Starts a new {@link Debugger#startSession(SuspendedCallback) debugger session} in the * context's {@link Engine engine}. The debugger session allows to suspend the execution and to * install breakpoints. If multiple sessions are created for one {@link #startEval(Source) * evaluation} then all suspended events are delegated to this debugger tester instance. * * @return a new debugger session * @since 0.16 */ public DebuggerSession startSession() { return getDebugger().startSession(new SuspendedCallback() { public void onSuspend(SuspendedEvent event) { DebuggerTester.this.onSuspend(event); } }); }