Skip to content

Commit a2eda58

Browse files
committed
Add Tests (Pretty sure there's a race condition)
1 parent 84b55f8 commit a2eda58

File tree

1 file changed

+93
-1
lines changed

1 file changed

+93
-1
lines changed

test/PowerShellEditorServices.Test.E2E/DebugAdapterProtocolMessageTests.cs

+93-1
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@
1111
using Microsoft.Extensions.Logging;
1212
using Microsoft.Extensions.Logging.Debug;
1313
using OmniSharp.Extensions.DebugAdapter.Client;
14+
using OmniSharp.Extensions.DebugAdapter.Protocol.Events;
1415
using OmniSharp.Extensions.DebugAdapter.Protocol.Models;
1516
using OmniSharp.Extensions.DebugAdapter.Protocol.Requests;
17+
using OmniSharp.Extensions.JsonRpc.Server;
1618
using Xunit;
1719
using Xunit.Abstractions;
1820

@@ -28,8 +30,14 @@ public class DebugAdapterProtocolMessageTests : IAsyncLifetime, IDisposable
2830
private DebugAdapterClient PsesDebugAdapterClient;
2931
private PsesStdioProcess _psesProcess;
3032

33+
/// <summary>
34+
/// Completes when the debug adapter is started.
35+
/// </summary>
3136
public TaskCompletionSource<object> Started { get; } = new TaskCompletionSource<object>();
32-
37+
/// <summary>
38+
/// Completes when the first breakpoint is reached.
39+
/// </summary>
40+
public TaskCompletionSource<StoppedEvent> Stopped { get; } = new TaskCompletionSource<StoppedEvent>();
3341
public DebugAdapterProtocolMessageTests(ITestOutputHelper output) => _output = output;
3442

3543
public async Task InitializeAsync()
@@ -65,6 +73,13 @@ public async Task InitializeAsync()
6573
Started.SetResult(true);
6674
return Task.CompletedTask;
6775
})
76+
// We use this to create a task we can await to test debugging after a breakpoint has been received.
77+
.OnNotification<StoppedEvent>(null, (stoppedEvent, _) =>
78+
{
79+
Console.WriteLine("StoppedEvent received");
80+
Stopped.SetResult(stoppedEvent);
81+
return Task.CompletedTask;
82+
})
6883
// The OnInitialized delegate gets run when we first receive the _Initialize_ response:
6984
// https://microsoft.github.io/debug-adapter-protocol/specification#Requests_Initialize
7085
.OnInitialized((_, _, _, _) =>
@@ -263,6 +278,83 @@ public async Task CanSetBreakpointsAsync()
263278
(i) => Assert.Equal("after breakpoint", i));
264279
}
265280

281+
[SkippableFact]
282+
public async Task FailsIfStacktraceRequestedWhenNotPaused()
283+
{
284+
Skip.If(PsesStdioProcess.RunningInConstrainedLanguageMode,
285+
"Breakpoints can't be set in Constrained Language Mode.");
286+
string filePath = NewTestFile(GenerateScriptFromLoggingStatements(
287+
"labelTestBreakpoint"
288+
));
289+
// Set a breakpoint
290+
await PsesDebugAdapterClient.SetBreakpoints(
291+
new SetBreakpointsArguments
292+
{
293+
Source = new Source { Name = Path.GetFileName(filePath), Path = filePath },
294+
Breakpoints = new SourceBreakpoint[] { new SourceBreakpoint { Line = 1 } },
295+
SourceModified = false,
296+
}
297+
);
298+
299+
// Signal to start the script
300+
await PsesDebugAdapterClient.RequestConfigurationDone(new ConfigurationDoneArguments());
301+
await PsesDebugAdapterClient.LaunchScript(filePath, Started);
302+
303+
304+
// Get the stacktrace for the breakpoint
305+
await Assert.ThrowsAsync<JsonRpcException>(() => PsesDebugAdapterClient.RequestStackTrace(
306+
new StackTraceArguments { }
307+
));
308+
}
309+
310+
[SkippableFact]
311+
public async Task SendsInitialLabelBreakpointForPerformanceReasons()
312+
{
313+
Skip.If(PsesStdioProcess.RunningInConstrainedLanguageMode,
314+
"Breakpoints can't be set in Constrained Language Mode.");
315+
string filePath = NewTestFile(GenerateScriptFromLoggingStatements(
316+
"before breakpoint",
317+
"at breakpoint",
318+
"after breakpoint"
319+
));
320+
321+
//TODO: This is technically wrong per the spec, configDone should be completed BEFORE launching, but this is how the vscode client does it today and we really need to fix that.
322+
await PsesDebugAdapterClient.LaunchScript(filePath, Started);
323+
324+
// {"command":"setBreakpoints","arguments":{"source":{"name":"dfsdfg.ps1","path":"/Users/tyleonha/Code/PowerShell/Misc/foo/dfsdfg.ps1"},"lines":[2],"breakpoints":[{"line":2}],"sourceModified":false},"type":"request","seq":3}
325+
SetBreakpointsResponse setBreakpointsResponse = await PsesDebugAdapterClient.SetBreakpoints(new SetBreakpointsArguments
326+
{
327+
Source = new Source { Name = Path.GetFileName(filePath), Path = filePath },
328+
Breakpoints = new SourceBreakpoint[] { new SourceBreakpoint { Line = 2 } },
329+
SourceModified = false,
330+
});
331+
332+
Breakpoint breakpoint = setBreakpointsResponse.Breakpoints.First();
333+
Assert.True(breakpoint.Verified);
334+
Assert.Equal(filePath, breakpoint.Source.Path, ignoreCase: s_isWindows);
335+
Assert.Equal(2, breakpoint.Line);
336+
337+
ConfigurationDoneResponse configDoneResponse = await PsesDebugAdapterClient.RequestConfigurationDone(new ConfigurationDoneArguments());
338+
339+
// FIXME: I think there is a race condition here. If you remove this, the following line Stack Trace fails because the breakpoint hasn't been hit yet. I think the whole getLog process just works long enough for ConfigurationDone to complete and for the breakpoint to be hit.
340+
341+
// I've tried to do this properly by waiting for a StoppedEvent, but that doesn't seem to work, I'm probably just not wiring it up right in the handler.
342+
Assert.NotNull(configDoneResponse);
343+
Assert.Collection(await GetLog(),
344+
(i) => Assert.Equal("before breakpoint", i));
345+
File.Delete(s_testOutputPath);
346+
347+
// Get the stacktrace for the breakpoint
348+
StackTraceResponse stackTraceResponse = await PsesDebugAdapterClient.RequestStackTrace(
349+
new StackTraceArguments { ThreadId = 1 }
350+
);
351+
StackFrame firstFrame = stackTraceResponse.StackFrames.First();
352+
Assert.Equal(
353+
firstFrame.PresentationHint,
354+
StackFramePresentationHint.Label
355+
);
356+
}
357+
266358
// This is a regression test for a bug where user code causes a new synchronization context
267359
// to be created, breaking the extension. It's most evident when debugging PowerShell
268360
// scripts that use System.Windows.Forms. It required fixing both Editor Services and

0 commit comments

Comments
 (0)