Skip to content

Debugger crashing unexpectedly on Pester tests #66

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
AndrewGaspar opened this issue Jan 2, 2016 · 14 comments
Closed

Debugger crashing unexpectedly on Pester tests #66

AndrewGaspar opened this issue Jan 2, 2016 · 14 comments
Assignees
Labels
Issue-Bug A bug to squash.
Milestone

Comments

@AndrewGaspar
Copy link

I've got a pester test that I'm trying to debug in VS Code. To invoke the test, I have a script pester.ps1 registered to a debug configuration in .vscode\launch.json. This script is simple:

.vscode\pester.ps1:

Invoke-Pester -Path (Join-Path $PSScriptRoot "..")

My pester code looks like this:
tests\MyModule.Tests.ps1

using module ..\MyModule

Describe "Tests for MyModule" {
  Context "MyModule foo config tests" {
    It "should do bar" {
      # ..
    }

    It "should handle baz" {
      # ..
    }
  }
}

Watching the Debug Console, the Describe and Context portion are logged before the debugger crashes. If I put a breakpoint on the Context line, however, it crashes before breaking, only printing the Describe line. If I put a breakpoint on the Describe line, it successfully breaks into the debugger at that line.

@daviwil daviwil added the Issue-Bug A bug to squash. label Jan 2, 2016
@daviwil
Copy link
Contributor

daviwil commented Jan 2, 2016

Haven't seen this issue before, I'll take a look. Thanks Andrew!

@daviwil daviwil added this to the 0.4.0 milestone Jan 2, 2016
@rkeithhill
Copy link
Contributor

@daviwil Spent a little time looking at this and I'm a bit perplexed. PowerShell is telling me (via Get-PSCallStack) that there are 13 stack frames. However when we ask for the variables for the 4th stack frame (index 3) it errors out. I observe the very same behavior from ISE (just using the commands directly):

·3> Get-PSCallStack

Command            Arguments                                                                                                           
-------            ---------                                                                                                           
Get-It             {}                                                                                                                  
<ScriptBlock>      {}                                                                                                                  
Invoke-Test        {Name=should do bar, ScriptBlock=...                                                                                
ItImpl             {Pester=@{AfterAll=System.Object[]; AfterEach=System.Object[]; BeforeAll=System.Object[]; BeforeEach=System.Objec...
It                 {name=should do bar, test=...                                                                                       
<ScriptBlock>      {}                                                                                                                  
Context            {Name=MyModule foo config tests, Fixture=...                                                                        
<ScriptBlock>      {}                                                                                                                  
Describe           {Name=Tests for MyModule, Fixture=...                                                                               
MyModule.Tests.ps1 {}                                                                                                                  
<ScriptBlock>      {Path=C:\Users\Keith\PowerShellSupport\VSCodePesterCrash\Tests\MyModule.Tests.ps1, Arguments=, Parameters=System....
Invoke-Pester      {Script=C:\Users\Keith\PowerShellSupport\VSCodePesterCrash\.vscode\.., Verbose=True}                                
pester.ps1         {}                                                                                                                  



·4> get-variable -Scope 3
get-variable : The scope number '3' exceeds the number of active scopes.
Parameter name: scopeID
Actual value was 3.
At line:1 char:1
+ get-variable -Scope 3
+ ~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Get-Variable], PSArgumentOutOfRangeException
    + FullyQualifiedErrorId : ArgumentOutOfRange,Microsoft.PowerShell.Commands.GetVariableCommand

Any idea what's up with that? Get-PSCallStack and Get-Variable -Scope don't seem to be in agreement over the number of stack frames. I guess we can add code to detect the error from Get-Variable but then do we pitch the stack frames we don't have variables for?

Here's a repro ZIP -
VSCodePesterCrash.zip

@daviwil
Copy link
Contributor

daviwil commented Jan 4, 2016

Hmmm, I'll ask someone about this, haven't seen that before.

@daviwil
Copy link
Contributor

daviwil commented Jan 4, 2016

Ok, it looks like Get-Variable -Scope uses scopes that don't map directly to call stack frames. The appropriate way to get the variables for a call stack frame is to call the GetFrameVariables method on each PSCallStack variable you get from Get-PSCallStack. Jason implied that there may be some bug with this pre-v5, so we may need to keep an eye on that.

@rkeithhill
Copy link
Contributor

@daviwil Thanks. I'll look at this tonight.

@rkeithhill rkeithhill self-assigned this Jan 4, 2016
@rkeithhill
Copy link
Contributor

Hmm, GetFrameVariables() seems broken to me. Here's a small program I'm debugging in ISE with breakpoint set on the return $true:

$scriptVar = 'scriptVar'

function Test-Scope ($p1) {
    $foo = 42
    return $true
}

Test-Scope bar

After the breakpoint is hit in the debugger, here is the output I get querying Get-Variable vs GetFrameVariables():

·30> $cs = Get-PSCallStack

·31> $cs[0].GetFrameVariables()

Key               Value                                     
---               -----                                     
args              System.Management.Automation.LocalVariable
input             System.Management.Automation.LocalVariable
PSBoundParameters System.Management.Automation.LocalVariable
MyInvocation      System.Management.Automation.LocalVariable
PSScriptRoot      System.Management.Automation.LocalVariable
PSCommandPath     System.Management.Automation.LocalVariable



·32> Get-Variable -Scope 0

Name                           Value                                                                                                   
----                           -----                                                                                                   
?                              True                                                                                                    
args                           {}                                                                                                      
ConsoleFileName                                                                                                                        
cs                             {at Test-Scope, C:\Users\Keith\PowerShellSupport\VariableScopes.ps1: line 5, at <ScriptBlock>, C:\Use...
ExecutionContext               System.Management.Automation.EngineIntrinsics                                                           
false                          False                                                                                                   
**foo**                          **42**
HOME                           C:\Users\Keith                                                                                          
Host                           System.Management.Automation.Internal.Host.InternalHost                                                 
input                          System.Collections.ArrayList+ArrayListEnumeratorSimple                                                  
MaximumAliasCount              4096                                                                                                    
MaximumDriveCount              4096                                                                                                    
MaximumErrorCount              256                                                                                                     
MaximumFunctionCount           4096                                                                                                    
MaximumVariableCount           4096                                                                                                    
MyInvocation                   System.Management.Automation.InvocationInfo                                                             
null                                                                                                                                   
**p1**                           **bar**
PID                            14376                                                                                                   
PSBoundParameters              {}                                                                                                      
PSCommandPath                                                                                                                          
PSCulture                      en-US                                                                                                   
PSDebugContext                 System.Management.Automation.PSDebugContext                                                             
PSHOME                         C:\Windows\System32\WindowsPowerShell\v1.0                                                              
PSScriptRoot                                                                                                                           
PSUICulture                    en-US                                                                                                   
PSVersionTable                 {PSVersion, PSCompatibleVersions, BuildVersion, CLRVersion...}                                          
ShellId                        Microsoft.PowerShell                                                                                    
true                           True                                                                                                    



·33> $cs[1].GetFrameVariables()

Key               Value                                     
---               -----                                     
args              System.Management.Automation.LocalVariable
input             System.Management.Automation.LocalVariable
PSBoundParameters System.Management.Automation.LocalVariable
MyInvocation      System.Management.Automation.LocalVariable
PSScriptRoot      System.Management.Automation.LocalVariable
PSCommandPath     System.Management.Automation.LocalVariable



·34> Get-Variable -Scope 1

Name                           Value                                                                                                   
----                           -----                                                                                                   
$                              )                                                                                                       
?                              True                                                                                                    
^                              $cs                                                                                                     
args                           {}                                                                                                      
ConfirmPreference              High                                                                                                    
ConsoleFileName                                                                                                                        
DebugPreference                SilentlyContinue                                                                                        
Error                          {The scope number '3' exceeds the number of active scopes....                                           
ErrorActionPreference          Continue                                                                                                
ErrorView                      NormalView                                                                                              
ExecutionContext               System.Management.Automation.EngineIntrinsics                                                           
false                          False                                                                                                   
FormatEnumerationLimit         4                                                                                                       
HOME                           C:\Users\Keith                                                                                          
Host                           System.Management.Automation.Internal.Host.InternalHost                                                 
InformationPreference          SilentlyContinue                                                                                        
input                          System.Collections.ArrayList+ArrayListEnumeratorSimple                                                  
MaximumAliasCount              4096                                                                                                    
MaximumDriveCount              4096                                                                                                    
MaximumErrorCount              256                                                                                                     
MaximumFunctionCount           4096                                                                                                    
MaximumHistoryCount            4096                                                                                                    
MaximumVariableCount           4096                                                                                                    
MyInvocation                   System.Management.Automation.InvocationInfo                                                             
NestedPromptLevel              1                                                                                                       
null                                                                                                                                   
OutputEncoding                 System.Text.SBCSCodePageEncoding                                                                        
PID                            14376                                                                                                   
profile                        C:\Users\Keith\Documents\WindowsPowerShell\Microsoft.PowerShellISE_profile.ps1                          
ProgressPreference             Continue                                                                                                
PSBoundParameters              {}                                                                                                      
PSCommandPath                  C:\Users\Keith\PowerShellSupport\VSCodePesterCrash\.vscode\pester.ps1                                   
PSCulture                      en-US                                                                                                   
PSDefaultParameterValues       {}                                                                                                      
PSEmailServer                                                                                                                          
PSHOME                         C:\Windows\System32\WindowsPowerShell\v1.0                                                              
psISE                          Microsoft.PowerShell.Host.ISE.ObjectModelRoot                                                           
PSScriptRoot                   C:\Users\Keith\PowerShellSupport\VSCodePesterCrash\.vscode                                              
PSSessionApplicationName       wsman                                                                                                   
PSSessionConfigurationName     http://schemas.microsoft.com/powershell/Microsoft.PowerShell                                            
PSSessionOption                System.Management.Automation.Remoting.PSSessionOption                                                   
PSUICulture                    en-US                                                                                                   
psUnsupportedConsoleApplica... {wmic, wmic.exe, cmd, cmd.exe...}                                                                       
PSVersionTable                 {PSVersion, PSCompatibleVersions, BuildVersion, CLRVersion...}                                          
PWD                            C:\WINDOWS\system32                                                                                     
**scriptVar**                    **scriptVar**
ShellId                        Microsoft.PowerShell                                                                                    
StackTrace                        at System.Management.Automation.SessionStateInternal.GetScopeByID(Int32 scopeID)...                  
true                           True                                                                                                    
VerbosePreference              SilentlyContinue                                                                                        
WarningPreference              Continue                                                                                                
WhatIfPreference               False                                                                                                   

The results of calling GetFrameVariables() contains none of the user defined variables. What am I missing here?

@daviwil
Copy link
Contributor

daviwil commented Jan 5, 2016

Hey @lzybkr, could you help us understand the use of GetFrameVariables vs Get-Variable -Scope here? Looks like GetFrameVariables doesn't immediately return the user defined variables in the scope. Is there another way to get those in this case?

@lzybkr
Copy link
Member

lzybkr commented Jan 6, 2016

GetFrameVariables was added for debuggers, but it does look useless in V5. I recall it working better in V3, but there were issues with it.

Get-Variable is the alternative, there is no other api or cmdlet that provides the promise of GetFrameVariables.

The primary issue is dot sourcing. When you dot source, you introduce a new frame, but not a new scope. A secondary issue is that some variables are preserved when you dot source, e.g.

PS>  $a = $_ = 'global'; . { "a: $a _: $_"; $a = $_ = 'dot source' }; "a: $a _: $_"
a: global _: global
a: dot source _: global

Get-Variable doesn't handle this correctly, and GetFrameVariables did, or at least was meant to. Bottom line, I need to fix GetFrameVariables, but you'll need to use Get-Variable until then, and w/ older versions of PS.

@daviwil
Copy link
Contributor

daviwil commented Jan 6, 2016

Thanks for the clarification! We'll continue using Get-Variable and try find a graceful way to handle the gotchas until a fix for GetFrameVariables appears in a later version of PowerShell.

Having the ability to easily see the user-defined variables for each call stack frame is really helpful so I think using Get-Variable is fine for now even if there are some cases in which it doesn't work. We just need to make sure we're showing things as accurately possible or not at all in those cases if accuracy can't be guaranteed.

@rkeithhill
Copy link
Contributor

Do we have a property somewhere that we can query from C# for which version of PowerShell the debug host is currently using? I see the code for this eventually needing this sort of check. Or would this be a compile-time #if check? I'm a bit fuzzy on how the support for v3 and v4 works.

@daviwil
Copy link
Contributor

daviwil commented Jan 7, 2016

Yep, PowerShellContext.PowerShellVersion will give you that.

@rkeithhill
Copy link
Contributor

OK fixing this but the fix is in the PowerShellEditorServices repo. Just realized that so my commit reference to issue 66 is for the wrong repo.

@daviwil
Copy link
Contributor

daviwil commented Jan 8, 2016

Keith submitted a fix for this here:

PowerShell/PowerShellEditorServices@b1e0e2d

This should work fine for you in the 0.4.0 release :)

@daviwil daviwil closed this as completed Jan 8, 2016
@AndrewGaspar
Copy link
Author

Thanks, guys!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Issue-Bug A bug to squash.
Projects
None yet
Development

No branches or pull requests

4 participants