Skip to content

Commit a3fbde3

Browse files
committed
Enable PsesInternalHostTests (previously PowerShellContextTests)
1 parent b8480d6 commit a3fbde3

File tree

3 files changed

+163
-185
lines changed

3 files changed

+163
-185
lines changed

src/PowerShellEditorServices/Services/PowerShell/Host/PsesInternalHost.cs

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -216,12 +216,7 @@ public async Task<bool> TryStartAsync(HostStartOptions startOptions, Cancellatio
216216

217217
if (startOptions.LoadProfiles)
218218
{
219-
await ExecuteDelegateAsync(
220-
"LoadProfiles",
221-
new PowerShellExecutionOptions { MustRunInForeground = true, ThrowOnError = false },
222-
(pwsh, _) => pwsh.LoadProfiles(_hostInfo.ProfilePaths),
223-
cancellationToken).ConfigureAwait(false);
224-
219+
await LoadHostProfilesAsync(cancellationToken).ConfigureAwait(false);
225220
_logger.LogInformation("Profiles loaded");
226221
}
227222

@@ -391,6 +386,15 @@ public void InvokePSDelegate(string representation, ExecutionOptions executionOp
391386
task.ExecuteAndGetResult(cancellationToken);
392387
}
393388

389+
internal Task LoadHostProfilesAsync(CancellationToken cancellationToken)
390+
{
391+
return ExecuteDelegateAsync(
392+
"LoadProfiles",
393+
new PowerShellExecutionOptions { MustRunInForeground = true, ThrowOnError = false },
394+
(pwsh, _) => pwsh.LoadProfiles(_hostInfo.ProfilePaths),
395+
cancellationToken);
396+
}
397+
394398
public Task SetInitialWorkingDirectoryAsync(string path, CancellationToken cancellationToken)
395399
{
396400
InitialWorkingDirectory = path;
@@ -919,7 +923,7 @@ private Task PopOrReinitializeRunspaceAsync()
919923
CancellationToken.None);
920924
}
921925

922-
private bool TryLoadPSReadLine(PowerShell pwsh, EngineIntrinsics engineIntrinsics, out IReadLine psrlReadLine)
926+
internal bool TryLoadPSReadLine(PowerShell pwsh, EngineIntrinsics engineIntrinsics, out IReadLine psrlReadLine)
923927
{
924928
psrlReadLine = null;
925929
try

test/PowerShellEditorServices.Test/Session/PowerShellContextTests.cs

Lines changed: 0 additions & 178 deletions
This file was deleted.
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
// Copyright (c) Microsoft Corporation.
2+
// Licensed under the MIT License.
3+
4+
using System;
5+
using System.Collections.Generic;
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
using Microsoft.Extensions.Logging.Abstractions;
9+
using Microsoft.PowerShell.EditorServices.Services.PowerShell.Host;
10+
using Microsoft.PowerShell.EditorServices.Services.PowerShell.Console;
11+
using Xunit;
12+
13+
namespace Microsoft.PowerShell.EditorServices.Test.Console
14+
{
15+
using System.Management.Automation;
16+
using System.Management.Automation.Runspaces;
17+
18+
[Trait("Category", "PsesInternalHost")]
19+
public class PsesInternalHostTests : IDisposable
20+
{
21+
private readonly PsesInternalHost psesHost;
22+
23+
public PsesInternalHostTests()
24+
{
25+
psesHost = PsesHostFactory.Create(NullLoggerFactory.Instance);
26+
}
27+
28+
public void Dispose()
29+
{
30+
psesHost.StopAsync().Wait();
31+
GC.SuppressFinalize(this);
32+
}
33+
34+
[Fact]
35+
public async Task CanExecutePSCommand()
36+
{
37+
Assert.True(psesHost.IsRunning);
38+
var command = new PSCommand().AddScript("$a = \"foo\"; $a");
39+
var task = psesHost.ExecutePSCommandAsync<string>(command, CancellationToken.None);
40+
var result = await task.ConfigureAwait(true);
41+
Assert.Equal("foo", result[0]);
42+
}
43+
44+
[Fact]
45+
public async Task CanQueueParallelPSCommands()
46+
{
47+
// Concurrently initiate 4 requests in the session.
48+
Task taskOne = psesHost.ExecutePSCommandAsync(
49+
new PSCommand().AddScript("$x = 100"),
50+
CancellationToken.None);
51+
52+
Task taskTwo = psesHost.ExecutePSCommandAsync(
53+
new PSCommand().AddScript("$x += 200"),
54+
CancellationToken.None);
55+
56+
Task taskThree = psesHost.ExecutePSCommandAsync(
57+
new PSCommand().AddScript("$x = $x / 100"),
58+
CancellationToken.None);
59+
60+
Task<IReadOnlyList<int>> resultTask = psesHost.ExecutePSCommandAsync<int>(
61+
new PSCommand().AddScript("$x"),
62+
CancellationToken.None);
63+
64+
// Wait for all of the executes to complete.
65+
await Task.WhenAll(taskOne, taskTwo, taskThree, resultTask).ConfigureAwait(true);
66+
67+
// Sanity checks
68+
Assert.Equal(RunspaceState.Opened, psesHost.Runspace.RunspaceStateInfo.State);
69+
70+
// 100 + 200 = 300, then divided by 100 is 3. We are ensuring that
71+
// the commands were executed in the sequence they were called.
72+
Assert.Equal(3, (await resultTask.ConfigureAwait(true))[0]);
73+
}
74+
75+
[Fact]
76+
public async Task CanCancelExecutionWithToken()
77+
{
78+
_ = await Assert.ThrowsAsync<TaskCanceledException>(() =>
79+
{
80+
return psesHost.ExecutePSCommandAsync(
81+
new PSCommand().AddScript("Start-Sleep 10"),
82+
new CancellationTokenSource(1000).Token);
83+
}).ConfigureAwait(true);
84+
}
85+
86+
[Fact]
87+
public async Task CanCancelExecutionWithMethod()
88+
{
89+
var executeTask = psesHost.ExecutePSCommandAsync(
90+
new PSCommand().AddScript("Start-Sleep 10"),
91+
CancellationToken.None);
92+
93+
// Wait until our task has started.
94+
Thread.Sleep(2000);
95+
psesHost.CancelCurrentTask();
96+
_ = await Assert.ThrowsAsync<TaskCanceledException>(() => executeTask).ConfigureAwait(true);
97+
Assert.True(executeTask.IsCanceled);
98+
}
99+
100+
[Fact]
101+
public async Task CanResolveAndLoadProfilesForHostId()
102+
{
103+
string[] expectedProfilePaths =
104+
new string[]
105+
{
106+
PsesHostFactory.TestProfilePaths.AllUsersAllHosts,
107+
PsesHostFactory.TestProfilePaths.AllUsersCurrentHost,
108+
PsesHostFactory.TestProfilePaths.CurrentUserAllHosts,
109+
PsesHostFactory.TestProfilePaths.CurrentUserCurrentHost
110+
};
111+
112+
// Load the profiles for the test host name
113+
await psesHost.LoadHostProfilesAsync(CancellationToken.None).ConfigureAwait(true);
114+
115+
// Ensure that all the paths are set in the correct variables
116+
// and that the current user's host profile got loaded
117+
PSCommand psCommand = new PSCommand().AddScript(
118+
"\"$($profile.AllUsersAllHosts) " +
119+
"$($profile.AllUsersCurrentHost) " +
120+
"$($profile.CurrentUserAllHosts) " +
121+
"$($profile.CurrentUserCurrentHost) " +
122+
"$(Assert-ProfileLoaded)\"");
123+
124+
var result = await psesHost.ExecutePSCommandAsync<string>(psCommand, CancellationToken.None).ConfigureAwait(true);
125+
126+
string expectedString =
127+
string.Format(
128+
"{0} True",
129+
string.Join(
130+
" ",
131+
expectedProfilePaths));
132+
133+
Assert.Equal(expectedString, result[0], ignoreCase: true);
134+
}
135+
136+
[Fact]
137+
public async Task CanLoadPSReadLine()
138+
{
139+
// NOTE: This is slightly more complicated than one would expect because we explicitly
140+
// need it to run on the pipeline thread otherwise Windows complains about the the
141+
// thread's appartment state not matching.
142+
Assert.True(await psesHost.ExecuteDelegateAsync(
143+
nameof(psesHost.TryLoadPSReadLine),
144+
executionOptions: null,
145+
(pwsh, _) => psesHost.TryLoadPSReadLine(
146+
pwsh,
147+
(EngineIntrinsics)pwsh.Runspace.SessionStateProxy.GetVariable("ExecutionContext"),
148+
out IReadLine readLine),
149+
CancellationToken.None).ConfigureAwait(true));
150+
}
151+
}
152+
}

0 commit comments

Comments
 (0)