Beispiel #1
0
        public static async Task NextPromptShouldBeBrowseAsync(this IRSession session)
        {
            var tracer = await session.TraceExecutionAsync();

            // Grab the next available prompt, and verify that it's Browse>
            using (var inter = await session.BeginInteractionAsync()) {
                inter.Contexts.IsBrowser().Should().BeTrue("Next available prompt should be a Browse> prompt");
            }

            // Now wait until session tells us that it has noticed the prompt and processed it.
            // Note that even if we register the handler after it has already noticed, but
            // before the interaction completed, it will still invoke the handler.
            var browseTask = EventTaskSources.IRExecutionTracer.Browse.Create(tracer);

            // Spin until either Browse is raised, or we see a different non-Browse prompt.
            // If the latter happens, we're not going to see Browse raised for that prompt that we've
            // seen initially, because something had interfered asynchronously, which shouldn't happen
            // in a test - and if it does, the test should be considered failed at that point, because
            // the state is indeterminate.
            while (true)
            {
                var interTask     = session.BeginInteractionAsync();
                var completedTask = await Task.WhenAny(browseTask, interTask);

                if (completedTask == browseTask)
                {
                    interTask.ContinueWith(t => t.Result.Dispose(), TaskContinuationOptions.OnlyOnRanToCompletion).DoNotWait();
                    return;
                }

                using (var inter = await interTask) {
                    inter.Contexts.IsBrowser().Should().BeTrue();
                }
            }
        }
Beispiel #2
0
        public async System.Threading.Tasks.Task ClearAllAsync()
        {
            if (_rSession == null)
            {
                return;
            }

            using (var eval = await _rSession.BeginInteractionAsync(false)) {
                await eval.ClearPlotHistoryAsync();
            }
        }
Beispiel #3
0
        public async Task InteractDuringBrowse()
        {
            using (var debugSession = new DebugSession(_session)) {
                using (var sf = new SourceFile("x <- 'old'; browser()")) {
                    var browse = new TaskCompletionSource <bool>();
                    debugSession.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");
                    }

                    REvaluationResult x;
                    using (var eval = await _session.BeginEvaluationAsync()) {
                        x = await eval.EvaluateAsync("x");
                    }

                    x.StringResult.Should().Be("new");
                }
            }
        }
Beispiel #4
0
        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");
                }

                string x;
                using (var eval = await _session.BeginEvaluationAsync()) {
                    x = await eval.EvaluateAsync <string>("x", REvaluationKind.Normal);
                }

                x.Should().Be("new");
            }
        }
Beispiel #5
0
        private async Task ExitBrowserAsync(IRSession session)
        {
            await TaskUtilities.SwitchToBackgroundThread();

            var cts = new CancellationTokenSource(1000);
            IRSessionInteraction inter;

            try {
                inter = await session.BeginInteractionAsync(true, cts.Token);
            } catch (OperationCanceledException) {
                // If we couldn't get a prompt to put "Q" into within a reasonable timeframe, just
                // abort the current interaction;
                await session.CancelAllAsync();

                return;
            }

            using (inter) {
                // Check if this is still the same prompt as the last Browse prompt that we've seen.
                // If it isn't, then session has moved on already, and there's nothing for us to exit.
                RBrowseEventArgs currentBrowseDebugEventArgs;
                lock (_browseLock) {
                    currentBrowseDebugEventArgs = _currentBrowseEventArgs;
                }

                if (currentBrowseDebugEventArgs != null && currentBrowseDebugEventArgs.Context.Contexts == inter.Contexts)
                {
                    await inter.RespondAsync("Q\n");
                }
            }
        }
Beispiel #6
0
        public RCodeBlockTest()
        {
            _shell   = TestCoreShell.CreateSubstitute();
            _session = _shell.SetupSessionSubstitute();

            _interaction = Substitute.For <IRSessionInteraction>();
            _session.BeginInteractionAsync(Arg.Any <bool>(), Arg.Any <CancellationToken>()).Returns(Task.FromResult(_interaction));
        }
Beispiel #7
0
        private async Task ExecuteAndCaptureOutputAsync(IRSession session, string expression, CancellationToken cancellationToken)
        {
            _output = new StringBuilder();
            _errors = new StringBuilder();

            using (var inter = await session.BeginInteractionAsync(isVisible: true, cancellationToken: cancellationToken)) {
                await inter.RespondAsync(expression);
            }
        }
Beispiel #8
0
        private async Task ExecuteAndCaptureOutputAsync(IRSession session, string expression, CancellationToken cancellationToken)
        {
            _output = new StringBuilder();
            _errors = new StringBuilder();

            try {
                using (var inter = await session.BeginInteractionAsync(true, cancellationToken)) {
                    await inter.RespondAsync(expression);
                }
            } catch (OperationCanceledException) { }
        }
Beispiel #9
0
        public async Task CallStack()
        {
            using (var debugSession = new DebugSession(_session)) {
                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 debugSession.EnableBreakpointsAsync(true);

                        await sf1.Source(_session);

                        await sf2.Source(_session);

                        var bp = await debugSession.CreateBreakpointAsync(sf1, 5);

                        var bpHit = new BreakpointHitDetector(bp);

                        using (var inter = await _session.BeginInteractionAsync()) {
                            await inter.RespondAsync("f(4)\n");
                        }
                        await bpHit.ShouldBeHitAtNextPromptAsync();

                        (await debugSession.GetStackFramesAsync()).Should().HaveTail(new MatchDebugStackFrames {
                            { (string)null, null, "f(4)" },
                            { sf1, 3, "g(n - 1)" },
                            { sf2, 3, "f(n - 1)" },
                            { sf1, 3, "g(n - 1)" },
                            { sf2, 3, "f(n - 1)" },
                            { sf1, 5, MatchAny <string> .Instance },
                        });
                    }
            }
        }
Beispiel #10
0
        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 }
                    });
                }
        }
Beispiel #11
0
        public async Task InitializeAsync()
        {
            await _sessionProvider.TrySwitchBrokerAsync(nameof(GridDataTest));

            await _session.StartHostAsync(new RHostStartupInfo(), new RHostClientTestApp(), 50000);

            var packages = (await _session.InstalledPackagesAsync()).Select(p => p.ToObject <RPackage>()).ToList();

            if (!packages.Any(p => p.Package.EqualsIgnoreCase("quantmod")))
            {
                using (var request = await _session.BeginInteractionAsync()) {
                    await request.InstallPackageAsync("quantmod");
                }
            }
        }
Beispiel #12
0
        public async Task <ExecutionResult> ExecuteCodeAsync(string text)
        {
            var start = 0;
            var end   = text.IndexOf('\n');

            if (end == -1)
            {
                return(ExecutionResult.Success);
            }

            try {
                using (Session.DisableMutatedOnReadConsole()) {
                    while (end != -1)
                    {
                        var line = text.Substring(start, end - start + 1);
                        start = end + 1;
                        end   = text.IndexOf('\n', start);

                        using (var request = await Session.BeginInteractionAsync()) {
                            using (_evaluatorRequest.Increment()) {
                                if (line.Length >= request.MaxLength)
                                {
                                    CurrentWindow.WriteErrorLine(string.Format(Resources.InputIsTooLong, request.MaxLength));
                                    return(ExecutionResult.Failure);
                                }

                                await request.RespondAsync(line);
                            }
                        }
                    }
                }

                return(ExecutionResult.Success);
            } catch (RHostDisconnectedException rhdex) {
                WriteError(rhdex.Message);
                return(ExecutionResult.Success);
            } catch (OperationCanceledException) {
                // Cancellation reason was already reported via RSession.Error and printed out;
                // Return success cause connection lost doesn't mean that RHost died
                return(ExecutionResult.Success);
            } catch (Exception ex) {
                await _coreShell.ShowErrorMessageAsync(ex.ToString());

                return(ExecutionResult.Failure);
            } finally {
                History.AddToHistory(text);
            }
        }
Beispiel #13
0
        public async Task <ExecutionResult> ExecuteCodeAsync(string text)
        {
            var start = 0;
            var end   = text.IndexOf('\n');

            if (end == -1)
            {
                return(ExecutionResult.Success);
            }

            try {
                Session.BeforeRequest -= SessionOnBeforeRequest;
                using (Session.DisableMutatedOnReadConsole()) {
                    while (end != -1)
                    {
                        var line = text.Substring(start, end - start + 1);
                        start = end + 1;
                        end   = text.IndexOf('\n', start);

                        using (var request = await Session.BeginInteractionAsync()) {
                            if (line.Length >= request.MaxLength)
                            {
                                CurrentWindow.WriteErrorLine(string.Format(Resources.InputIsTooLong, request.MaxLength));
                                return(ExecutionResult.Failure);
                            }

                            await request.RespondAsync(line);
                        }
                    }
                }

                return(ExecutionResult.Success);
            } catch (RException) {
                // It was already reported via RSession.Error and printed out; just return failure.
                return(ExecutionResult.Failure);
            } catch (OperationCanceledException) {
                // Cancellation reason was already reported via RSession.Error and printed out; just return failure.
                return(ExecutionResult.Failure);
            } catch (Exception ex) {
                await _coreShell.DispatchOnMainThreadAsync(() => _coreShell.ShowErrorMessage(ex.ToString()));

                return(ExecutionResult.Failure);
            } finally {
                Session.BeforeRequest += SessionOnBeforeRequest;
                History.AddToHistory(text);
            }
        }
Beispiel #14
0
 public async Task Source(IRSession session, bool debug = true)
 {
     using (IRSessionInteraction eval = await session.BeginInteractionAsync()) {
         await eval.RespondAsync($"{(debug ? "rtvs::debug_source" : "source")}({FilePath.ToRStringLiteral()})" + Environment.NewLine);
     }
 }
Beispiel #15
0
        private async Task Environments(string script, params IREnvironment[] expectedEnvs)
        {
            // Detach all packages that can be detached before doing anything else. The only two that
            // cannot be detached are .GlobalEnv, which is the first in the list, and package:base,
            // which is the last. So, just keep detaching the 2nd item until the list only has 2 left.
            await _session.ExecuteAsync("while (length(search()) > 2) detach(2)");

            // Wait for prompt to appear.
            using (var eval = await _session.BeginInteractionAsync()) { }

            var envProvider = new REnvironmentProvider(_session);
            var envTcs      = new TaskCompletionSource <IREnvironment[]>();

            envProvider.Environments.CollectionChanged += (sender, args) => {
                envTcs.TrySetResult(envProvider.Environments.ToArray());
            };

            using (var inter = await _session.BeginInteractionAsync()) {
                inter.RespondAsync(script + "\n").DoNotWait();
            }

            // Wait until we hit the Browse> prompt.
            using (var inter = await _session.BeginInteractionAsync()) {
                inter.Contexts.IsBrowser().Should().BeTrue();
            }

            var actualEnvs = await envTcs.Task;

            actualEnvs.ShouldAllBeEquivalentTo(expectedEnvs, options => options
                                               .Including(env => env.Name)
                                               .Including(env => env.Kind)
                                               .WithStrictOrdering());

            // Validating EnvironmentExpression:
            // For environments that are on the search list, we can validate it by retrieving environment by name,
            // and verifying that it is indeed the same. format() generates comparable string values - it returns strings
            // that are unique for any given environment (using its name if it has one, and its memory address otherwise).
            // For all other environments, we validate by looking at a variable named 'tag' in that environment, and
            // comparing its value to the name of the function extracted from the call (i.e. environment name).
            var expectedObjects = new List <string>();
            var actualObjects   = new List <string>();

            foreach (var env in actualEnvs)
            {
                if (env == null)
                {
                    expectedObjects.Add(null);
                    actualObjects.Add(null);
                }
                else if (env.Kind == REnvironmentKind.Function)
                {
                    int tagEnd = env.Name.IndexOf("(");
                    tagEnd.Should().BePositive();
                    string tag = env.Name.Substring(0, tagEnd);

                    expectedObjects.Add(tag);
                    actualObjects.Add(await _session.EvaluateAsync <string>(
                                          $"({env.EnvironmentExpression})$tag",
                                          REvaluationKind.Normal));
                }
                else
                {
                    expectedObjects.Add(await _session.EvaluateAsync <string>(
                                            $"format(as.environment({env.Name.ToRStringLiteral()}))",
                                            REvaluationKind.Normal));
                    actualObjects.Add(await _session.EvaluateAsync <string>(
                                          $"format({env.EnvironmentExpression})",
                                          REvaluationKind.Normal));
                }
            }

            actualObjects.Should().Equal(expectedObjects);
        }
Beispiel #16
0
        private async Task ExitBrowserAsync(IRSession session) {
            await TaskUtilities.SwitchToBackgroundThread();

            var cts = new CancellationTokenSource(1000);
            IRSessionInteraction inter;
            try {
                inter = await session.BeginInteractionAsync(true, cts.Token);
            } catch (OperationCanceledException) {
                // If we couldn't get a prompt to put "Q" into within a reasonable timeframe, just
                // abort the current interaction;
                await session.CancelAllAsync();
                return;
            }

            using (inter) {
                // Check if this is still the same prompt as the last Browse prompt that we've seen.
                // If it isn't, then session has moved on already, and there's nothing for us to exit.
                RBrowseEventArgs currentBrowseDebugEventArgs;
                lock (_browseLock) {
                    currentBrowseDebugEventArgs = _currentBrowseEventArgs;
                }

                if (currentBrowseDebugEventArgs != null && currentBrowseDebugEventArgs.Context.Contexts == inter.Contexts) {
                    await inter.RespondAsync("Q\n");
                }
            }
        }
Beispiel #17
0
 private async Task ExecuteRCode(IRSession session, string expression)
 {
     using (var interaction = await session.BeginInteractionAsync(isVisible: false)) {
         await interaction.RespondAsync(expression);
     }
 }
 private async Task ExecuteRCode(IRSession session, string expression) {
     using (var interaction = await session.BeginInteractionAsync(isVisible: false)) {
         await interaction.RespondAsync(expression).SilenceException<RException>();
     }
 }
Beispiel #19
0
        public async Task SetAndHitBreakpointInsideLoadedFunction()
        {
            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();
            }
        }
Beispiel #20
0
 public async Task Source(IRSession session) {
     using (IRSessionInteraction eval = await session.BeginInteractionAsync()) {
         await eval.RespondAsync($"rtvs::debug_source({FilePath.ToRStringLiteral()})" + Environment.NewLine);
     }
 }