269 lines
11 KiB
PowerShell
269 lines
11 KiB
PowerShell
# Copyright (c) Microsoft Corporation.
|
|
# Licensed under the MIT License.
|
|
|
|
Describe 'Breakpoint SDK Unit Tests' -Tags 'CI' {
|
|
|
|
BeforeAll {
|
|
# Start a job; this will create a runspace in which we can manage breakpoints
|
|
$job = Start-Job -Scriptblock {
|
|
Set-PSBreakpoint -Command Start-Sleep
|
|
1..240 | ForEach-Object {
|
|
Start-Sleep -Milliseconds 250
|
|
$_
|
|
Write-Error 'boo'
|
|
Write-Verbose 'Verbose' -Verbose
|
|
$DebugPreference = 'Continue'
|
|
Write-Debug 'Debug'
|
|
Write-Warning 'Warning'
|
|
}
|
|
}
|
|
|
|
# Wait for the child job that gets created to hit the breakpoint. This is the
|
|
# only safe way to know that the job has actually entered a running state and
|
|
# that the remote runspace is listening for requests.
|
|
Wait-UntilTrue { $job.ChildJobs.Count -gt 0 -and $job.ChildJobs[0].State -eq 'AtBreakpoint' } -TimeoutInMilliseconds 60000 -IntervalInMilliseconds 250
|
|
|
|
# Get the runspace for the running job
|
|
$jobRunspace = $job.ChildJobs[0].Runspace
|
|
}
|
|
|
|
AfterAll {
|
|
# Remove the running job forcibly (whether it has finished or not)
|
|
Remove-Job -Job $job -Force
|
|
}
|
|
|
|
Context 'Managing breakpoints in the host runspace via the SDK' {
|
|
|
|
AfterAll {
|
|
foreach ($bp in $Host.Runspace.Debugger.GetBreakpoints()) {
|
|
$Host.Runspace.Debugger.RemoveBreakpoint($bp) | Should -BeTrue
|
|
}
|
|
}
|
|
|
|
It 'Can set command breakpoints' {
|
|
$Host.Runspace.Debugger.SetCommandBreakpoint('Test-ThisCommandDoesNotExist', $null, $null) | Should -BeOfType System.Management.Automation.CommandBreakpoint
|
|
}
|
|
|
|
It 'Can set variable breakpoints' {
|
|
$Host.Runspace.Debugger.SetVariableBreakpoint('DebugPreference', 'ReadWrite', { continue }, $null) | Should -BeOfType System.Management.Automation.VariableBreakpoint
|
|
}
|
|
|
|
It 'Can set line breakpoints' {
|
|
$Host.Runspace.Debugger.SetLineBreakpoint($PSCommandPath, 1, 1, { continue }) | Should -BeOfType System.Management.Automation.LineBreakpoint
|
|
}
|
|
|
|
It 'Can get breakpoints' {
|
|
$Host.Runspace.Debugger.GetBreakpoints() | Should -HaveCount 3
|
|
}
|
|
|
|
It 'Can disable breakpoints' {
|
|
foreach ($bp in $Host.Runspace.Debugger.GetBreakpoints()) {
|
|
$bp = $Host.Runspace.Debugger.DisableBreakpoint($bp)
|
|
$bp.Enabled | Should -BeFalse
|
|
}
|
|
}
|
|
|
|
It 'Can enable breakpoints' {
|
|
foreach ($bp in $Host.Runspace.Debugger.GetBreakpoints()) {
|
|
$bp = $Host.Runspace.Debugger.EnableBreakpoint($bp)
|
|
$bp.Enabled | Should -BeTrue
|
|
}
|
|
}
|
|
|
|
It 'Can remove breakpoints' {
|
|
foreach ($bp in $Host.Runspace.Debugger.GetBreakpoints()) {
|
|
$Host.Runspace.Debugger.RemoveBreakpoint($bp) | Should -BeTrue
|
|
}
|
|
}
|
|
|
|
It 'Returns an empty collection when there are no breakpoints' {
|
|
$Host.Runspace.Debugger.GetBreakpoints() | Should -HaveCount 0
|
|
}
|
|
|
|
It 'Can set multiple breakpoints' {
|
|
$breakpoints = [System.Collections.Generic.List[System.Management.Automation.Breakpoint]] @(
|
|
[System.Management.Automation.LineBreakpoint]::new("/Path/to/foo.ps1", 1)
|
|
[System.Management.Automation.LineBreakpoint]::new("/Path/to/foo.ps1", 2)
|
|
[System.Management.Automation.LineBreakpoint]::new("/Path/to/foo.ps1", 3)
|
|
)
|
|
|
|
$Host.Runspace.Debugger.SetBreakpoints($breakpoints)
|
|
$Host.Runspace.Debugger.GetBreakpoints() | Should -HaveCount 3
|
|
}
|
|
}
|
|
|
|
Context 'Managing breakpoints in a remote runspace via the SDK' {
|
|
|
|
AfterAll {
|
|
foreach ($bp in $jobRunspace.Debugger.GetBreakpoints()) {
|
|
$jobRunspace.Debugger.RemoveBreakpoint($bp) | Should -BeTrue
|
|
}
|
|
}
|
|
|
|
It 'Can set command breakpoints' {
|
|
$jobRunspace.Debugger.SetCommandBreakpoint('Write-Verbose', { break }, $null) | Should -BeOfType System.Management.Automation.CommandBreakpoint
|
|
}
|
|
|
|
It 'Can set variable breakpoints' {
|
|
$jobRunspace.Debugger.SetVariableBreakpoint('DebugPreference', 'ReadWrite', { break }, $null) | Should -BeOfType System.Management.Automation.VariableBreakpoint
|
|
}
|
|
|
|
It 'Can set line breakpoints' {
|
|
$jobRunspace.Debugger.SetLineBreakpoint($PSCommandPath, 1, 1, { break }) | Should -BeOfType System.Management.Automation.LineBreakpoint
|
|
}
|
|
|
|
It 'Can get breakpoints' {
|
|
# This is 4, not 3, because we set a breakpoint in our job script
|
|
$jobRunspace.Debugger.GetBreakpoints() | Should -HaveCount 4
|
|
}
|
|
|
|
It 'Can disable breakpoints' {
|
|
foreach ($bp in $jobRunspace.Debugger.GetBreakpoints()) {
|
|
$bp = $jobRunspace.Debugger.DisableBreakpoint($bp)
|
|
$bp.Enabled | Should -BeFalse
|
|
}
|
|
}
|
|
|
|
It 'Can enable breakpoints' {
|
|
foreach ($bp in $jobRunspace.Debugger.GetBreakpoints()) {
|
|
$bp = $jobRunspace.Debugger.EnableBreakpoint($bp)
|
|
$bp.Enabled | Should -BeTrue
|
|
}
|
|
}
|
|
|
|
It 'Doesn''t manipulate any breakpoints in the default runspace' {
|
|
# Issue https://github.com/PowerShell/PowerShell/issues/10167 fix:
|
|
# Ensure that breakpoints were not created in the default runspace.
|
|
# Prior to this issue being fixed, breakpoints with the same id
|
|
# would be created or updated in the default runspace.
|
|
$Host.Runspace.Debugger.GetBreakpoints() | Should -BeNullOrEmpty
|
|
}
|
|
|
|
It 'Can remove breakpoints' {
|
|
foreach ($bp in $jobRunspace.Debugger.GetBreakpoints()) {
|
|
$jobRunspace.Debugger.RemoveBreakpoint($bp) | Should -BeTrue
|
|
}
|
|
}
|
|
|
|
It 'Returns an empty collection when there are no breakpoints' {
|
|
$jobRunspace.Debugger.GetBreakpoints() | Should -HaveCount 0
|
|
}
|
|
|
|
It 'Can set multiple breakpoints' {
|
|
$breakpoints = [System.Collections.Generic.List[System.Management.Automation.Breakpoint]] @(
|
|
[System.Management.Automation.LineBreakpoint]::new("/Path/to/foo.ps1", 1)
|
|
[System.Management.Automation.LineBreakpoint]::new("/Path/to/foo.ps1", 2)
|
|
[System.Management.Automation.LineBreakpoint]::new("/Path/to/foo.ps1", 3)
|
|
)
|
|
|
|
$jobRunspace.Debugger.SetBreakpoints($breakpoints)
|
|
$jobRunspace.Debugger.GetBreakpoints() | Should -HaveCount 3
|
|
}
|
|
}
|
|
|
|
Context 'Handling empty collections and errors while managing breakpoints in the host runspace via the SDK' {
|
|
|
|
BeforeAll {
|
|
$bp = [System.Management.Automation.CommandBreakpoint]::new($TestDrive, $null, 'Test-ThisCommandDoesNotExist')
|
|
}
|
|
|
|
It 'Returns false when trying to disable a breakpoint that does not exist' {
|
|
$Host.Runspace.Debugger.DisableBreakpoint($bp) | Should -Be $null
|
|
}
|
|
|
|
It 'Returns false when trying to enable a breakpoint that does not exist' {
|
|
$Host.Runspace.Debugger.EnableBreakpoint($bp) | Should -Be $null
|
|
}
|
|
|
|
It 'Returns false when trying to remove a breakpoint that does not exist' {
|
|
$Host.Runspace.Debugger.RemoveBreakpoint($bp) | Should -BeFalse
|
|
}
|
|
}
|
|
|
|
Context 'Handling errors while managing breakpoints in a remote runspace via the SDK' {
|
|
|
|
BeforeAll {
|
|
$bp = $jobRunspace.Debugger.SetCommandBreakpoint('Test-ThisCommandDoesNotExist', $null, $null)
|
|
$jobRunspace.Debugger.RemoveBreakpoint($bp) > $null
|
|
}
|
|
|
|
It 'Returns false when trying to disable a breakpoint that does not exist' {
|
|
$jobRunspace.Debugger.DisableBreakpoint($bp) | Should -Be $null
|
|
}
|
|
|
|
It 'Returns false when trying to enable a breakpoint that does not exist' {
|
|
$jobRunspace.Debugger.EnableBreakpoint($bp) | Should -Be $null
|
|
}
|
|
|
|
It 'Returns false when trying to remove a breakpoint that does not exist' {
|
|
$jobRunspace.Debugger.RemoveBreakpoint($bp) | Should -BeFalse
|
|
}
|
|
}
|
|
|
|
Context 'Manage breakpoints in another runspace' {
|
|
BeforeAll {
|
|
$runspace = [runspacefactory]::CreateRunspace()
|
|
$runspace.Open()
|
|
}
|
|
|
|
AfterAll {
|
|
$runspace.Close()
|
|
$runspace.Dispose()
|
|
}
|
|
|
|
It 'Can set command breakpoints' {
|
|
$Host.Runspace.Debugger.SetCommandBreakpoint('Test-ThisCommandDoesNotExist', $null, $null, $runspace.Id) | Should -BeOfType System.Management.Automation.CommandBreakpoint
|
|
}
|
|
|
|
It 'Can set variable breakpoints' {
|
|
$Host.Runspace.Debugger.SetVariableBreakpoint('DebugPreference', 'ReadWrite', { continue }, $null, $runspace.Id) | Should -BeOfType System.Management.Automation.VariableBreakpoint
|
|
}
|
|
|
|
It 'Can set line breakpoints' {
|
|
$Host.Runspace.Debugger.SetLineBreakpoint($PSCommandPath, 1, 1, { continue }, $runspace.Id) | Should -BeOfType System.Management.Automation.LineBreakpoint
|
|
}
|
|
|
|
It 'Can get breakpoints' {
|
|
$Host.Runspace.Debugger.GetBreakpoints($runspace.Id) | Should -HaveCount 3
|
|
}
|
|
|
|
It 'Can disable breakpoints' {
|
|
foreach ($bp in $Host.Runspace.Debugger.GetBreakpoints($runspace.Id)) {
|
|
$bp = $Host.Runspace.Debugger.DisableBreakpoint($bp, $runspace.Id)
|
|
$bp.Enabled | Should -BeFalse
|
|
}
|
|
}
|
|
|
|
It 'Can enable breakpoints' {
|
|
foreach ($bp in $Host.Runspace.Debugger.GetBreakpoints($runspace.Id)) {
|
|
$bp = $Host.Runspace.Debugger.EnableBreakpoint($bp, $runspace.Id)
|
|
$bp.Enabled | Should -BeTrue
|
|
}
|
|
}
|
|
|
|
It 'Doesn''t manipulate any breakpoints in the default runspace' {
|
|
$Host.Runspace.Debugger.GetBreakpoints() | Should -BeNullOrEmpty
|
|
}
|
|
|
|
It 'Can remove breakpoints' {
|
|
foreach ($bp in $Host.Runspace.Debugger.GetBreakpoints($runspace.Id)) {
|
|
$Host.Runspace.Debugger.RemoveBreakpoint($bp, $runspace.Id) | Should -BeTrue
|
|
}
|
|
}
|
|
|
|
It 'Returns an empty collection when there are no breakpoints' {
|
|
$Host.Runspace.Debugger.GetBreakpoints($runspace.Id) | Should -HaveCount 0
|
|
}
|
|
|
|
It 'Can set multiple breakpoints' {
|
|
$breakpoints = [System.Collections.Generic.List[System.Management.Automation.Breakpoint]] @(
|
|
[System.Management.Automation.LineBreakpoint]::new("/Path/to/foo.ps1", 1)
|
|
[System.Management.Automation.LineBreakpoint]::new("/Path/to/foo.ps1", 2)
|
|
[System.Management.Automation.LineBreakpoint]::new("/Path/to/foo.ps1", 3)
|
|
)
|
|
|
|
$Host.Runspace.Debugger.SetBreakpoints($breakpoints, $runspace.Id)
|
|
$Host.Runspace.Debugger.GetBreakpoints($runspace.Id) | Should -HaveCount 3
|
|
}
|
|
}
|
|
}
|