@@ -84,6 +84,171 @@ Describe "Trace-Command" -tags "CI" {
8484 }
8585 }
8686
87+ Context " MethodInvocation traces" {
88+
89+ BeforeAll {
90+ $filePath = Join-Path $TestDrive ' testtracefile.txt'
91+
92+ class MyClass {
93+ MyClass() {}
94+ MyClass([int ]$arg ) {}
95+
96+ [void ]Method() { return }
97+ [void ]Method([string ]$arg ) { return }
98+ [void ]Method([int ]$arg ) { return }
99+
100+ [string ]ReturnMethod() { return " foo" }
101+
102+ static [void ]StaticMethod() { return }
103+ static [void ]StaticMethod([string ]$arg ) { return }
104+ }
105+
106+ # C# classes support more features than pwsh classes
107+ Add-Type - TypeDefinition @'
108+ namespace TraceCommandTests;
109+
110+ public sealed class OverloadTests
111+ {
112+ public int PropertySetter { get; set; }
113+
114+ public OverloadTests() {}
115+ public OverloadTests(int value)
116+ {
117+ PropertySetter = value;
118+ }
119+
120+ public void GenericMethod<T>()
121+ {}
122+
123+ public T GenericMethodWithArg<T>(T obj) => obj;
124+
125+ public void MethodWithDefault(string arg1, int optional = 1)
126+ {}
127+
128+ public void MethodWithOut(out int val)
129+ {
130+ val = 1;
131+ }
132+
133+ public void MethodWithRef(ref int val)
134+ {
135+ val = 1;
136+ }
137+ }
138+ '@
139+ }
140+
141+ AfterEach {
142+ Remove-Item $filePath - Force - ErrorAction SilentlyContinue
143+ }
144+
145+ It " Traces instance method" {
146+ $myClass = [MyClass ]::new()
147+ Trace-Command - Name MethodInvocation - Expression {
148+ $myClass.Method (1 )
149+ } - FilePath $filePath
150+ Get-Content $filePath | Should - BeLike " *Invoking method: void Method(int arg)"
151+ }
152+
153+ It " Traces static method" {
154+ Trace-Command - Name MethodInvocation - Expression {
155+ [MyClass ]::StaticMethod(1 )
156+ } - FilePath $filePath
157+ Get-Content $filePath | Should - BeLike " *Invoking method: static void StaticMethod(string arg)"
158+ }
159+
160+ It " Traces method with return type" {
161+ $myClass = [MyClass ]::new()
162+ Trace-Command - Name MethodInvocation - Expression {
163+ $myClass.ReturnMethod ()
164+ } - FilePath $filePath
165+ Get-Content $filePath | Should - BeLike " *Invoking method: string ReturnMethod()"
166+ }
167+
168+ It " Traces constructor" {
169+ Trace-Command - Name MethodInvocation - Expression {
170+ [TraceCommandTests.OverloadTests ]::new(" 1234" )
171+ } - FilePath $filePath
172+ Get-Content $filePath | Should - BeLike " *Invoking method: TraceCommandTests.OverloadTests new(int value)"
173+ }
174+
175+ It " Traces Property setter invoked as a method" {
176+ $obj = [TraceCommandTests.OverloadTests ]::new()
177+ Trace-Command - Name MethodInvocation - Expression {
178+ $obj.set_PropertySetter (1234 )
179+ } - FilePath $filePath
180+ Get-Content $filePath | Should - BeLike " *Invoking method: void set_PropertySetter(int value)"
181+ }
182+
183+ It " Traces generic method" {
184+ $obj = [TraceCommandTests.OverloadTests ]::new()
185+ Trace-Command - Name MethodInvocation - Expression {
186+ $obj.GenericMethod [int ]()
187+ } - FilePath $filePath
188+ Get-Content $filePath | Should - BeLike " *Invoking method: void GenericMethod`` [int`` ]()"
189+ }
190+
191+ It " Traces generic method with argument" {
192+ $obj = [TraceCommandTests.OverloadTests ]::new()
193+ Trace-Command - Name MethodInvocation - Expression {
194+ $obj.GenericMethodWithArg (" foo" )
195+ } - FilePath $filePath
196+ Get-Content $filePath | Should - BeLike " *Invoking method: string GenericMethodWithArg`` [string`` ](string obj)"
197+ }
198+
199+ It " Traces .NET call with default value" {
200+ $obj = [TraceCommandTests.OverloadTests ]::new()
201+ Trace-Command - Name MethodInvocation - Expression {
202+ $obj.MethodWithDefault (" foo" )
203+ } - FilePath $filePath
204+ Get-Content $filePath | Should - BeLike " *Invoking method: void MethodWithDefault(string arg1, int optional = 1)"
205+ }
206+
207+ It " Traces method with ref argument" {
208+ $obj = [TraceCommandTests.OverloadTests ]::new()
209+ $v = 1
210+
211+ Trace-Command - Name MethodInvocation - Expression {
212+ $obj.MethodWithRef ([ref ]$v )
213+ } - FilePath $filePath
214+ # [ref] goes through the binder so will trigger the first trace
215+ Get-Content $filePath | Select-Object - Skip 1 | Should - BeLike " *Invoking method: void MethodWithRef(`` [ref`` ] int val)"
216+ }
217+
218+ It " Traces method with out argument" {
219+ $obj = [TraceCommandTests.OverloadTests ]::new()
220+ $v = 1
221+
222+ Trace-Command - Name MethodInvocation - Expression {
223+ $obj.MethodWithOut ([ref ]$v )
224+ } - FilePath $filePath
225+ # [ref] goes through the binder so will trigger the first trace
226+ Get-Content $filePath | Select-Object - Skip 1 | Should - BeLike " *Invoking method: void MethodWithOut(`` [ref`` ] int val)"
227+ }
228+
229+ It " Traces a binding error" {
230+ Trace-Command - Name MethodInvocation - Expression {
231+ # try/catch is used as error formatter will hit the trace as well
232+ try {
233+ [System.Runtime.InteropServices.Marshal ]::SizeOf([int ])
234+ }
235+ catch {
236+ # Satisfy codefactor
237+ $_ | Out-Null
238+ }
239+ } - FilePath $filePath
240+ # type fqn is used, the wildcard avoids hardcoding that
241+ Get-Content $filePath | Should - BeLike " *Invoking method: static int SizeOf`` [System.RuntimeType, *`` ](System.RuntimeType, * structure)"
242+ }
243+
244+ It " Traces LINQ call" {
245+ Trace-Command - Name MethodInvocation - Expression {
246+ [System.Linq.Enumerable ]::Union([int []]@ (1 , 2 ), [int []]@ (3 , 4 ))
247+ } - FilePath $filePath
248+ Get-Content $filePath | Should - BeLike " *Invoking method: static System.Collections.Generic.IEnumerable`` [int`` ] Union`` [int`` ](System.Collections.Generic.IEnumerable`` [int`` ] first, System.Collections.Generic.IEnumerable`` [int`` ] second)"
249+ }
250+ }
251+
87252 Context " Trace-Command tests for code coverage" {
88253
89254 BeforeAll {
0 commit comments