public async Task BreakContinue() { const string code = @"x <- 0 browser() while (x >= 0) { x <- x + 1 } browser()"; var tracer = await _session.TraceExecutionAsync(); using (var sf = new SourceFile(code)) { await sf.Source(_session); await _session.NextPromptShouldBeBrowseAsync(); await tracer.ContinueAsync(); await Task.Delay(100); await tracer.BreakAsync(); await _session.NextPromptShouldBeBrowseAsync(); var frame = (await _session.TracebackAsync()).Single(); frame.FileName.Should().Be(sf.FilePath); frame.LineNumber.Should().BeInRange(3, 5); await _session.ExecuteAsync("x <- -42"); await tracer.ContinueAsync(); await _session.NextPromptShouldBeBrowseAsync(); await _session.ShouldHaveTracebackAsync(new TracebackBuilder { { sf, 6 } }); } }
public async Task Promise() { const string code = @"f <- function(p) { browser() force(p) browser() } f(1 + 2)"; var tracer = await _session.TraceExecutionAsync(); using (var sf = new SourceFile(code)) { await tracer.EnableBreakpointsAsync(true); await sf.Source(_session); await _session.NextPromptShouldBeBrowseAsync(); var stackFrames = (await _session.TracebackAsync()).ToArray(); stackFrames.Should().NotBeEmpty(); var frame = stackFrames.Last(); var children = await frame.DescribeChildrenAsync(REvaluationResultProperties.None, RValueRepresentations.Deparse()); children.Should().ContainSingle(er => er.Name == "p") .Which.Should().BeAssignableTo<IRPromiseInfo>() .Which.Code.Should().Be("1 + 2"); await tracer.ContinueAsync(); await _session.NextPromptShouldBeBrowseAsync(); children = await frame.DescribeChildrenAsync(REvaluationResultProperties.None, RValueRepresentations.Deparse()); children.Should().ContainSingle(er => er.Name == "p") .Which.Should().BeAssignableTo<IRValueInfo>() .Which.Representation.Should().Be("3"); } }
public async Task AddRemoveBreakpoint() { const string code = @"x <- 1 y <- 2 z <- 3"; var tracer = await _session.TraceExecutionAsync(); using (var sf = new SourceFile(code)) { var bp1Loc = new RSourceLocation(sf.FilePath, 1); var bp1 = await tracer.CreateBreakpointAsync(bp1Loc); bp1.Location.Should().Be(bp1Loc); bp1.Tracer.Should().Be(tracer); tracer.Breakpoints.Count.Should().Be(1); var bp2Loc = new RSourceLocation(sf.FilePath, 3); var bp2 = await tracer.CreateBreakpointAsync(bp2Loc); bp2.Location.Should().Be(bp2Loc); bp2.Tracer.Should().Be(tracer); tracer.Breakpoints.Count.Should().Be(2); await bp1.DeleteAsync(); tracer.Breakpoints.Count.Should().Be(1); tracer.Breakpoints.First().Should().BeSameAs(bp2); } }
public async Task SourceRScriptTest(bool echo, string encoding) { await _workflow.RSessions.TrySwitchBrokerAsync(nameof(RInteractiveWorkflowCommandTest)); await _workflow.RSession.EnsureHostStartedAsync(new RHostStartupInfo { Name = _testMethod.Name, RHostCommandLineArguments = _settings.LastActiveConnection.RCommandLineArguments, CranMirrorName = _settings.CranMirror, CodePage = _settings.RCodePage }, null, 50000); var session = _workflow.RSession; await session.ExecuteAsync("sourced <- FALSE"); var tracker = Substitute.For<IActiveWpfTextViewTracker>(); tracker.GetLastActiveTextView(RContentTypeDefinition.ContentType).Returns((IWpfTextView)null); var command = new SourceRScriptCommand(_workflow, tracker, echo); command.Should().BeSupported() .And.BeInvisibleAndDisabled(); using (await _workflow.GetOrCreateVisualComponentAsync()) { const string code = "sourced <- TRUE"; var textBuffer = new TextBufferMock(code, RContentTypeDefinition.ContentType); var textView = new WpfTextViewMock(textBuffer); tracker.GetLastActiveTextView(RContentTypeDefinition.ContentType).Returns(textView); tracker.LastActiveTextView.Returns(textView); command.Should().BeSupported() .And.BeVisibleAndDisabled(); using (var sf = new SourceFile(code)) { var document = new TextDocumentMock(textBuffer, sf.FilePath) { Encoding = Encoding.GetEncoding(encoding) }; textBuffer.Properties[typeof(ITextDocument)] = document; command.Should().BeSupported() .And.BeVisibleAndEnabled(); var mutatedTask = EventTaskSources.IRSession.Mutated.Create(session); await command.InvokeAsync().Should().BeCompletedAsync(); await mutatedTask.Should().BeCompletedAsync(); (await session.EvaluateAsync<bool>("sourced", REvaluationKind.Normal)).Should().BeTrue(); } } }
public async Task SetAndHitToplevelBreakpoint() { const string code = @"x <- 1 y <- 2 z <- 3"; var tracer = await _session.TraceExecutionAsync(); using (var sf = new SourceFile(code)) { await tracer.EnableBreakpointsAsync(true); var bp = await tracer.CreateBreakpointAsync(new RSourceLocation(sf.FilePath, 2)); var bpHit = new BreakpointHitDetector(bp); await sf.Source(_session); await bpHit.ShouldBeHitAtNextPromptAsync(); } }
public async Task CallStack() { var tracer = await _session.TraceExecutionAsync(); const string code1 = @"f <- function(n) { if (n > 0) { g(n - 1) } else { return() } }"; const string code2 = @"g <- function(n) { if (n > 0) { f(n - 1) } else { return() } }"; using (var sf1 = new SourceFile(code1)) using (var sf2 = new SourceFile(code2)) { await tracer.EnableBreakpointsAsync(true); await sf1.Source(_session); await sf2.Source(_session); var bp = await tracer.CreateBreakpointAsync(sf1, 5); var bpHit = new BreakpointHitDetector(bp); using (var inter = await _session.BeginInteractionAsync()) { await inter.RespondAsync("f(4)\n"); } await bpHit.ShouldBeHitAtNextPromptAsync(); await _session.ShouldHaveTracebackAsync(new TracebackBuilder { { null, null, "f(4)", "<environment: R_GlobalEnv>" }, { sf1, 3, "g(n - 1)", null }, { sf2, 3, "f(n - 1)", null }, { sf1, 3, "g(n - 1)", null }, { sf2, 3, "f(n - 1)", null }, { sf1, 5, TracebackBuilder.Any, null } }); } }
public async Task InteractDuringBrowse() { var tracer = await _session.TraceExecutionAsync(); using (var sf = new SourceFile("x <- 'old'; browser()")) { var browse = new TaskCompletionSource<bool>(); tracer.Browse += (s, e) => { browse.TrySetResult(true); }; await sf.Source(_session); await browse.Task; using (var inter = await _session.BeginInteractionAsync()) { await inter.RespondAsync("x <- 'new'\n"); } var x = await _session.EvaluateAsync<string>("x", REvaluationKind.Normal); x.Should().Be("new"); } }
public async Task SetBreakpointOnNull() { const string code = @"f <- function() { NULL }"; var tracer = await _session.TraceExecutionAsync(); using (var sf = new SourceFile(code)) { var bp = await tracer.CreateBreakpointAsync(new RSourceLocation(sf.FilePath, 2)); tracer.Breakpoints.Count.Should().Be(1); await sf.Source(_session); (await _session.EvaluateAsync<bool>("is.function(f)", REvaluationKind.Normal)).Should().BeTrue(); } }
public async Task StepOutToFunction() { const string code = @"f <- function() { 1 } g <- function() { f() 1 } g()"; var tracer = await _session.TraceExecutionAsync(); using (var sf = new SourceFile(code)) { await tracer.EnableBreakpointsAsync(true); var bp = await tracer.CreateBreakpointAsync(sf, 2); var bpHit = new BreakpointHitDetector(bp); await sf.Source(_session); await bpHit.ShouldBeHitAtNextPromptAsync(); await _session.ShouldHaveTracebackAsync(new TracebackBuilder { { sf, 8, "g()" }, { sf, 5, "f()" }, { bp.Location }, }); (await tracer.StepOutAsync()).Should().Be(true); await _session.ShouldHaveTracebackAsync(new TracebackBuilder { { sf, 8, "g()" }, { sf, 6, TracebackBuilder.Any }, }); } }
public async Task MultilinePromise() { const string code = @"f <- function(p, d) { force(d) browser() } x <- quote({{{}}}) eval(substitute(f(P, x), list(P = x)))"; var tracer = await _session.TraceExecutionAsync(); using (var sf = new SourceFile(code)) { await tracer.EnableBreakpointsAsync(true); await sf.Source(_session); await _session.NextPromptShouldBeBrowseAsync(); var stackFrames = (await _session.TracebackAsync()).ToArray(); stackFrames.Should().NotBeEmpty(); var children = (await stackFrames.Last().DescribeChildrenAsync(REvaluationResultProperties.None, RValueRepresentations.Deparse())); var d = children.Should().ContainSingle(er => er.Name == "d") .Which.Should().BeAssignableTo<IRValueInfo>() .Which; children.Should().ContainSingle(er => er.Name == "p") .Which.Should().BeAssignableTo<IRPromiseInfo>() .Which.Code.Should().Be(d.Representation); } }
public async Task EnvironmentIndependentResult() { const string code = @"(function(p) { v <- 42 makeActiveBinding('a', function() 42, environment()) browser() })(42)"; var tracer = await _session.TraceExecutionAsync(); using (var sf = new SourceFile(code)) { await tracer.EnableBreakpointsAsync(true); await sf.Source(_session); await _session.NextPromptShouldBeBrowseAsync(); var stackFrames = (await _session.TracebackAsync()).ToArray(); stackFrames.Should().NotBeEmpty(); var env = stackFrames.Last(); var children = (await env.DescribeChildrenAsync(ExpressionProperty | ComputedValueProperty, RValueRepresentations.Deparse())); var v = children.Should().ContainSingle(er => er.Name == "v") .Which.Should().BeAssignableTo<IRValueInfo>() .Which; var p = children.Should().ContainSingle(er => er.Name == "p") .Which.Should().BeAssignableTo<IRPromiseInfo>() .Which; var a = children.Should().ContainSingle(er => er.Name == "a") .Which.Should().BeAssignableTo<IRActiveBindingInfo>() .Which; var e = (await env.TryEvaluateAndDescribeAsync("non_existing_variable", None, null)) .Should().BeAssignableTo<IRErrorInfo>() .Which; var iv = v.ToEnvironmentIndependentResult().Should().BeAssignableTo<IRValueInfo>().Which; (await _session.EvaluateAndDescribeAsync(iv.Expression, ExpressionProperty, RValueRepresentations.Deparse())) .Should().BeAssignableTo<IRValueInfo>().Which.Representation.Should().Be(v.Representation); // When a promise expression is evaluated directly, rather than via children, the promise is forced // and becomes a value. To have something to compare it against, evaluate the original promise in // its original environment as well. var pv = await v.GetValueAsync(ExpressionProperty, RValueRepresentations.Deparse()); var ipv = p.ToEnvironmentIndependentResult().Should().BeAssignableTo<IRPromiseInfo>().Which; (await _session.EvaluateAndDescribeAsync(ipv.Expression, ExpressionProperty, RValueRepresentations.Deparse())) .Should().BeAssignableTo<IRValueInfo>() .Which.Representation.Should().Be(pv.Representation); // When an active binding expression is evaluated directly, rather than via children, its active // binding nature is not discoverable, and it produces a value result. var iav = a.ToEnvironmentIndependentResult().Should().BeAssignableTo<IRActiveBindingInfo>().Which; (await _session.EvaluateAndDescribeAsync(iav.Expression, ExpressionProperty | ComputedValueProperty, RValueRepresentations.Deparse())) .Should().BeAssignableTo<IRValueInfo>().Which.Representation.Should().Be(a.ComputedValue.Representation); var ie = e.ToEnvironmentIndependentResult().Should().BeAssignableTo<IRErrorInfo>().Which; (await _session.TryEvaluateAndDescribeAsync(ie.Expression, ExpressionProperty, RValueRepresentations.Deparse())) .Should().BeAssignableTo<IRErrorInfo>(); } }
public static Task<IRBreakpoint> CreateBreakpointAsync(this IRExecutionTracer tracer, SourceFile sf, int lineNumber) { return tracer.CreateBreakpointAsync(new RSourceLocation(sf.FilePath, lineNumber)); }
public async Task ActiveBindingEvaluate() { const string code = @"makeActiveBinding('x', function() 42, environment()) browser(); "; var tracer = await _session.TraceExecutionAsync(); using (var sf = new SourceFile(code)) { await tracer.EnableBreakpointsAsync(true); await sf.Source(_session); await _session.NextPromptShouldBeBrowseAsync(); var stackFrames = (await _session.TracebackAsync()).ToArray(); stackFrames.Should().NotBeEmpty(); var children = await stackFrames.Last().DescribeChildrenAsync(ComputedValueProperty, RValueRepresentations.Deparse()); children.Should().ContainSingle(er => er.Name == "x") .Which.Should().BeAssignableTo<IRActiveBindingInfo>() .Which.ComputedValue.Representation.Should().Be("42"); } }
public static Task <IRBreakpoint> CreateBreakpointAsync(this IRExecutionTracer tracer, SourceFile sf, int lineNumber) { return(tracer.CreateBreakpointAsync(new RSourceLocation(sf.FilePath, lineNumber))); }
public async Task SetBreakpointWhileRunning() { const string code = @"browser() f <- function() { NULL } while (TRUE) f()"; var tracer = await _session.TraceExecutionAsync(); using (var sf = new SourceFile(code)) { await tracer.EnableBreakpointsAsync(true); await sf.Source(_session); await _session.NextPromptShouldBeBrowseAsync(); await tracer.ContinueAsync(); await Task.Delay(100); var bp = await tracer.CreateBreakpointAsync(sf, 3); await _session.NextPromptShouldBeBrowseAsync(); await _session.ShouldBeAtAsync(bp.Location); } }
public async Task BreakpointsInDifferentFiles() { var tracer = await _session.TraceExecutionAsync(); using (var sf1 = new SourceFile("1")) using (var sf2 = new SourceFile($"eval(parse({sf1.FilePath.ToRStringLiteral()}))")) { await tracer.EnableBreakpointsAsync(true); var bp1Loc = new RSourceLocation(sf1.FilePath, 1); var bp1 = await tracer.CreateBreakpointAsync(bp1Loc); bp1.Location.Should().Be(bp1Loc); var bp2Loc = new RSourceLocation(sf2.FilePath, 1); var bp2 = await tracer.CreateBreakpointAsync(bp2Loc); bp2.Location.Should().Be(bp2Loc); tracer.Breakpoints.Should().HaveCount(2); var bp1Hit = new BreakpointHitDetector(bp1); var bp2Hit = new BreakpointHitDetector(bp2); await sf2.Source(_session); await bp2Hit.ShouldBeHitAtNextPromptAsync(); bp1Hit.WasHit.Should().BeFalse(); bp2Hit.Reset(); await tracer.ContinueAsync(); await bp1Hit.ShouldBeHitAtNextPromptAsync(); bp2Hit.WasHit.Should().BeFalse(); } }
public async Task RemovedBreakpointNotHit() { const string code = @"f <- function() { 0 }"; var tracer = await _session.TraceExecutionAsync(); using (var sf = new SourceFile(code)) { await tracer.EnableBreakpointsAsync(true); await sf.Source(_session); var bp = await tracer.CreateBreakpointAsync(new RSourceLocation(sf.FilePath, 2)); var bpHit = new BreakpointHitDetector(bp); using (var inter = await _session.BeginInteractionAsync()) { await inter.RespondAsync("f()\n"); } await bpHit.ShouldBeHitAtNextPromptAsync(); await bp.DeleteAsync(); await tracer.ContinueAsync(); using (var inter = await _session.BeginInteractionAsync()) { await inter.RespondAsync("f()\n"); } using (var inter = await _session.BeginInteractionAsync()) { inter.Contexts.IsBrowser().Should().BeFalse(); } } }
public async Task EnvironmentNames() { const string code = @"f <- function() eval(quote(browser()), .GlobalEnv) g <- function(f) eval(as.call(list(f)), getNamespace('utils')) h <- function() eval(as.call(list(g, f)), as.environment('package:utils')) h()"; var tracer = await _session.TraceExecutionAsync(); using (var sf = new SourceFile(code)) { await sf.Source(_session); await _session.NextPromptShouldBeBrowseAsync(); var funcFrame = Substitute.For<IRStackFrame>(); funcFrame.IsGlobal.Returns(false); funcFrame.EnvironmentName.Returns((string)null); var globalEnv = Substitute.For<IRStackFrame>(); globalEnv.IsGlobal.Returns(true); globalEnv.EnvironmentName.Returns("<environment: R_GlobalEnv>"); var packageUtils = Substitute.For<IRStackFrame>(); packageUtils.IsGlobal.Returns(false); packageUtils.EnvironmentName.Returns("<environment: package:utils>"); var namespaceUtils = Substitute.For<IRStackFrame>(); namespaceUtils.IsGlobal.Returns(false); namespaceUtils.EnvironmentName.Returns("<environment: namespace:utils>"); var expectedFrames = new[] { globalEnv, funcFrame, // h funcFrame, // eval packageUtils, funcFrame, // g funcFrame, // eval namespaceUtils, funcFrame, // f funcFrame, // eval globalEnv }; var actualFrames = await _session.TracebackAsync(); actualFrames.ShouldAllBeEquivalentTo(expectedFrames, options => options .Including(frame => frame.IsGlobal) .Including(frame => frame.EnvironmentName) .WithStrictOrdering()); } }
public async Task HideSourceFrames(bool debug) { var tracer = await _session.TraceExecutionAsync(); using (var sf = new SourceFile("0")) { await tracer.EnableBreakpointsAsync(true); var bp = await tracer.CreateBreakpointAsync(sf, 1); var bpHit = new BreakpointHitDetector(bp); await sf.Source(_session, debug); await bpHit.ShouldBeHitAtNextPromptAsync(); var frame = (await _session.TracebackAsync()).Single(); frame.IsGlobal.Should().BeTrue(); } }
public async Task SetAndHitBreakpointInsideUnloadedFunction() { const string code = @"f <- function() { 0 } f()"; var tracer = await _session.TraceExecutionAsync(); using (var sf = new SourceFile(code)) { await tracer.EnableBreakpointsAsync(true); var bp = await tracer.CreateBreakpointAsync(new RSourceLocation(sf.FilePath, 2)); var bpHit = new BreakpointHitDetector(bp); await sf.Source(_session); await bpHit.ShouldBeHitAtNextPromptAsync(); } }
public async Task StepOutFromGlobal() { const string code = @"x <- 1 y <- 2"; var tracer = await _session.TraceExecutionAsync(); using (var sf = new SourceFile(code)) { await tracer.EnableBreakpointsAsync(true); var bp1 = await tracer.CreateBreakpointAsync(sf, 1); var bp2 = await tracer.CreateBreakpointAsync(sf, 2); var bp1Hit = new BreakpointHitDetector(bp1); await sf.Source(_session); await bp1Hit.ShouldBeHitAtNextPromptAsync(); await _session.ShouldHaveTracebackAsync(new TracebackBuilder { { bp1.Location } }); (await tracer.StepOutAsync()).Should().Be(false); await _session.ShouldHaveTracebackAsync(new TracebackBuilder { { bp2.Location } }); } }
public async Task OverlappingBreakpoints() { const string code = @"f <- function() { 1 }"; var tracer = await _session.TraceExecutionAsync(); using (var sf = new SourceFile(code)) { await tracer.EnableBreakpointsAsync(true); await sf.Source(_session); var bp1 = await tracer.CreateBreakpointAsync(sf, 1); var bp2 = await tracer.CreateBreakpointAsync(sf, 1); bp1.Should().BeSameAs(bp2); tracer.Breakpoints.Should().HaveCount(1); var bp1Hit = new BreakpointHitDetector(bp1); var bp2Hit = new BreakpointHitDetector(bp2); using (var inter = await _session.BeginInteractionAsync()) { await inter.RespondAsync("f()\n"); } await bp1Hit.ShouldBeHitAtNextPromptAsync(); bp2Hit.WasHit.Should().BeTrue(); await bp1.DeleteAsync(); tracer.Breakpoints.Should().HaveCount(1); tracer.Breakpoints.Should().Contain(bp2); await tracer.ContinueAsync(); using (var inter = await _session.BeginInteractionAsync()) { await inter.RespondAsync("f()\n"); } await bp2Hit.ShouldBeHitAtNextPromptAsync(); await bp2.DeleteAsync(); tracer.Breakpoints.Should().BeEmpty(); await tracer.ContinueAsync(); using (var inter = await _session.BeginInteractionAsync()) { await inter.RespondAsync("f()\n"); } using (var inter = await _session.BeginInteractionAsync()) { inter.Contexts.IsBrowser().Should().BeFalse(); } } }
public async Task StepOntoBreakpoint() { const string code = @"x <- 1 y <- 2"; var tracer = await _session.TraceExecutionAsync(); using (var sf = new SourceFile(code)) { await tracer.EnableBreakpointsAsync(true); var bp1 = await tracer.CreateBreakpointAsync(sf, 1); var bp2 = await tracer.CreateBreakpointAsync(sf, 2); var bp1Hit = new BreakpointHitDetector(bp1); var bp2Hit = new BreakpointHitDetector(bp2); await sf.Source(_session); await bp1Hit.ShouldBeHitAtNextPromptAsync(); (await tracer.StepOverAsync()).Should().Be(false); await bp2Hit.ShouldBeHitAtNextPromptAsync(); } }
public async Task RemoveBreakpointWhileRunning() { const string code = @"browser() f <- function() { NULL browser() } b <- FALSE; while (TRUE) if (b) f()"; var tracer = await _session.TraceExecutionAsync(); using (var sf = new SourceFile(code)) { await tracer.EnableBreakpointsAsync(true); await sf.Source(_session); await _session.NextPromptShouldBeBrowseAsync(); var bp = await tracer.CreateBreakpointAsync(sf, 3); int hitCount = 0; bp.BreakpointHit += delegate { ++hitCount; }; await tracer.ContinueAsync(); await Task.Delay(100); await bp.DeleteAsync(); await _session.ExecuteAsync("b <- TRUE"); await _session.NextPromptShouldBeBrowseAsync(); await _session.ShouldBeAtAsync(sf.FilePath, 4); hitCount.Should().Be(0); } }
public async Task StepOver() { const string code = @"f <- function(x) { x + 1 } x <- f(1) print(x)"; var tracer = await _session.TraceExecutionAsync(); using (var sf = new SourceFile(code)) { await tracer.EnableBreakpointsAsync(true); var bp = await tracer.CreateBreakpointAsync(sf, 4); var bpHit = new BreakpointHitDetector(bp); await sf.Source(_session); await bpHit.ShouldBeHitAtNextPromptAsync(); await _session.ShouldHaveTracebackAsync(new TracebackBuilder { { bp.Location } }); (await tracer.StepOverAsync()).Should().Be(true); await _session.ShouldHaveTracebackAsync(new TracebackBuilder { { bp.Location, +1 } }); } }
public async Task FrameChildren() { var tracer = await _session.TraceExecutionAsync(); _session.IsHostRunning.Should().BeTrue(because: "Host is not running."); using (var sf = new SourceFile("x <- 1; y <- 2; browser()")) { await sf.Source(_session); await _session.NextPromptShouldBeBrowseAsync(); var frame = (await _session.TracebackAsync()).Last(); var frameChildren = await frame.DescribeChildrenAsync(REvaluationResultProperties.None, null); var frameEnv = await frame.DescribeEnvironmentAsync(); var frameEnvChildren = await frameEnv.DescribeChildrenAsync(REvaluationResultProperties.None, null); frameEnv.Length.Should().Be(2); frameChildren.Should().HaveCount(2); frameChildren.Should().Contain(info => info.Name == "x"); frameChildren.Should().Contain(info => info.Name == "y"); frameChildren.ShouldAllBeEquivalentTo(frameEnvChildren, options => options.WithStrictOrdering()); } }