private async Task RunEnvironmentTestAsync(string expression, Action <IReadOnlyList <REnvironment> > assert)
        {
            var sessionProvider    = VsAppShell.Current.ExportProvider.GetExportedValue <IRSessionProvider>();
            var environmentChanged = new CountdownEvent(3);
            IReadOnlyList <REnvironment> environments = null;

            using (var rHostScript = new RHostScript(sessionProvider, null)) {
                using (var environmentProvider = new REnvironmentProvider(rHostScript.Session)) {
                    environmentProvider.EnvironmentChanged += (sender, e) => {
                        environments = e.Environments;
                        environmentChanged.Signal();
                    };
                    using (var interaction = await rHostScript.Session.BeginInteractionAsync(false)) {
                        await interaction.RespondAsync(expression + Environment.NewLine);
                    }

                    bool timedout = true;
                    if (System.Diagnostics.Debugger.IsAttached)
                    {
                        environmentChanged.Wait();
                    }
                    else
                    {
                        timedout = environmentChanged.Wait(TimeSpan.FromSeconds(10));
                    }
                    timedout.Should().BeTrue();

                    assert(environments);
                }
            }
        }
Exemple #2
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);
        }