@@ -32,6 +32,16 @@ public class DebugServiceTests : IDisposable
32
32
private AsyncQueue < SessionStateChangedEventArgs > sessionStateQueue =
33
33
new AsyncQueue < SessionStateChangedEventArgs > ( ) ;
34
34
35
+ private ScriptFile GetDebugScript ( string fileName )
36
+ {
37
+ return this . workspace . GetFile (
38
+ TestUtilities . NormalizePath ( Path . Combine (
39
+ Path . GetDirectoryName ( typeof ( DebugServiceTests ) . Assembly . Location ) ,
40
+ "../../../../PowerShellEditorServices.Test.Shared/Debugging" ,
41
+ fileName
42
+ ) ) ) ;
43
+ }
44
+
35
45
public DebugServiceTests ( )
36
46
{
37
47
var logger = NullLogger . Instance ;
@@ -41,18 +51,9 @@ public DebugServiceTests()
41
51
42
52
this . workspace = new WorkspaceService ( NullLoggerFactory . Instance ) ;
43
53
44
- // Load the test debug file
45
- this . debugScriptFile =
46
- this . workspace . GetFile (
47
- TestUtilities . NormalizePath ( Path . Combine (
48
- Path . GetDirectoryName ( typeof ( DebugServiceTests ) . Assembly . Location ) ,
49
- "../../../../PowerShellEditorServices.Test.Shared/Debugging/VariableTest.ps1" ) ) ) ;
50
-
51
- this . variableScriptFile =
52
- this . workspace . GetFile (
53
- TestUtilities . NormalizePath ( Path . Combine (
54
- Path . GetDirectoryName ( typeof ( DebugServiceTests ) . Assembly . Location ) ,
55
- "../../../../PowerShellEditorServices.Test.Shared/Debugging/VariableTest.ps1" ) ) ) ;
54
+ // Load the test debug files
55
+ this . debugScriptFile = GetDebugScript ( "DebugTest.ps1" ) ;
56
+ this . variableScriptFile = GetDebugScript ( "VariableTest.ps1" ) ;
56
57
57
58
this . debugService = new DebugService (
58
59
this . powerShellContext ,
@@ -65,13 +66,6 @@ public DebugServiceTests()
65
66
66
67
this . debugService . DebuggerStopped += debugService_DebuggerStopped ;
67
68
this . debugService . BreakpointUpdated += debugService_BreakpointUpdated ;
68
-
69
- // Load the test debug file
70
- this . debugScriptFile =
71
- this . workspace . GetFile (
72
- TestUtilities . NormalizePath ( Path . Combine (
73
- Path . GetDirectoryName ( typeof ( DebugServiceTests ) . Assembly . Location ) ,
74
- "../../../../PowerShellEditorServices.Test.Shared/Debugging/DebugTest.ps1" ) ) ) ;
75
69
}
76
70
77
71
async void powerShellContext_SessionStateChanged ( object sender , SessionStateChangedEventArgs e )
@@ -123,11 +117,7 @@ public async Task DebuggerAcceptsScriptArgs(string[] args)
123
117
// The path is intentionally odd (some escaped chars but not all) because we are testing
124
118
// the internal path escaping mechanism - it should escape certains chars ([, ] and space) but
125
119
// it should not escape already escaped chars.
126
- ScriptFile debugWithParamsFile =
127
- this . workspace . GetFile (
128
- TestUtilities . NormalizePath ( Path . Combine (
129
- Path . GetDirectoryName ( typeof ( DebugServiceTests ) . Assembly . Location ) ,
130
- "../../../../PowerShellEditorServices.Test.Shared/Debugging/Debug W&ith Params [Test].ps1" ) ) ) ;
120
+ ScriptFile debugWithParamsFile = GetDebugScript ( "Debug W&ith Params [Test].ps1" ) ;
131
121
132
122
await this . debugService . SetLineBreakpointsAsync (
133
123
debugWithParamsFile ,
@@ -889,7 +879,7 @@ await this.debugService.SetLineBreakpointsAsync(
889
879
890
880
var nullStringVar = variables . FirstOrDefault ( v => v . Name == "$nullString" ) ;
891
881
Assert . NotNull ( nullStringVar ) ;
892
- Assert . True ( "[NullString]" . Equals ( nullStringVar . ValueString ) ) ;
882
+ Assert . Equal ( "[NullString]" , nullStringVar . ValueString ) ;
893
883
Assert . True ( nullStringVar . IsExpandable ) ;
894
884
895
885
// Abort script execution early and wait for completion
@@ -973,6 +963,7 @@ await this.debugService.SetLineBreakpointsAsync(
973
963
974
964
// Verifies fix for issue #86, $proc = Get-Process foo displays just the ETS property set
975
965
// and not all process properties.
966
+ [ Trait ( "Category" , "DebugService" ) ]
976
967
[ Fact ]
977
968
public async Task DebuggerVariableProcessObjDisplaysCorrectly ( )
978
969
{
@@ -1005,6 +996,55 @@ await this.debugService.SetLineBreakpointsAsync(
1005
996
await executeTask . ConfigureAwait ( false ) ;
1006
997
}
1007
998
999
+ // This is a regression test for a bug where user code causes a new synchronization context
1000
+ // to be created, breaking the extension. It's most evident when debugging PowerShell
1001
+ // scripts that use System.Windows.Forms. It required fixing both Editor Services and
1002
+ // OmniSharp.
1003
+ //
1004
+ // This test depends on PowerShell being able to load System.Windows.Forms, which only works
1005
+ // reliably with Windows PowerShell. It works with PowerShell Core in the real-world;
1006
+ // however, our host executable is xUnit, not PowerShell. So by restricting to Windows
1007
+ // PowerShell, we avoid all issues with our test project (and the xUnit executable) not
1008
+ // having System.Windows.Forms deployed, and can instead rely on the Windows Global Assembly
1009
+ // Cache (GAC) to find it.
1010
+ [ Trait ( "Category" , "DebugService" ) ]
1011
+ [ SkippableFact ]
1012
+ public async Task DebuggerStepsPastSystemWindowsForms ( )
1013
+ {
1014
+ Skip . If ( ! VersionUtils . IsPS5 ) ;
1015
+
1016
+ ScriptFile formsFile = GetDebugScript ( "FormsTest.ps1" ) ;
1017
+
1018
+ await debugService . SetCommandBreakpointsAsync (
1019
+ new [ ] { CommandBreakpointDetails . Create ( "Write-Host" ) } ) . ConfigureAwait ( false ) ;
1020
+
1021
+ Task executeTask = powerShellContext . ExecuteScriptWithArgsAsync ( formsFile . FilePath ) ;
1022
+
1023
+ // Wait for function breakpoint to hit
1024
+ await AssertDebuggerStopped ( formsFile . FilePath , 5 ) . ConfigureAwait ( false ) ;
1025
+
1026
+ StackFrameDetails [ ] stackFrames = debugService . GetStackFrames ( ) ;
1027
+ VariableDetailsBase [ ] variables =
1028
+ debugService . GetVariables ( stackFrames [ 0 ] . LocalVariables . Id ) ;
1029
+
1030
+ // Verify $before, $form, and $after vars exist
1031
+ var before = variables . FirstOrDefault ( v => v . Name == "$before" ) ;
1032
+ Assert . NotNull ( before ) ;
1033
+ Assert . Equal ( "\" before\" " , before . ValueString ) ;
1034
+
1035
+ var form = variables . FirstOrDefault ( v => v . Name == "$form" ) ;
1036
+ Assert . NotNull ( form ) ;
1037
+ Assert . StartsWith ( "System.Windows.Forms.Form" , form . ValueString ) ;
1038
+
1039
+ var after = variables . FirstOrDefault ( v => v . Name == "$after" ) ;
1040
+ Assert . NotNull ( after ) ;
1041
+ Assert . Equal ( "\" after\" " , after . ValueString ) ;
1042
+
1043
+ // Abort script execution early and wait for completion
1044
+ debugService . Abort ( ) ;
1045
+ await executeTask . ConfigureAwait ( false ) ;
1046
+ }
1047
+
1008
1048
public async Task AssertDebuggerPaused ( )
1009
1049
{
1010
1050
DebuggerStoppedEventArgs eventArgs =
0 commit comments