Skip to content

Commit e325feb

Browse files
authored
Merge pull request #2 from imdj360/comprehensive-auto-instrument-test
Comprehensive auto instrument test
2 parents a50bf3a + d9d428a commit e325feb

6 files changed

Lines changed: 319 additions & 20 deletions

File tree

TestData/Integration/xslt/compiled/sample-inline-cs-auto-instrument.xslt

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,49 @@ using System;
99
using System.Globalization;
1010
1111
public class MathHelper {
12+
// Private fields
13+
private int counter = 0;
14+
private string prefix = "Result: ";
15+
private double multiplier = 2.5;
16+
private int[] cachedValues = new int[] { 10, 20, 30, 40, 50 };
17+
18+
// Methods using private variables
19+
public int IncrementCounter() {
20+
counter++;
21+
return counter;
22+
}
23+
24+
public int GetCounterValue() {
25+
return counter;
26+
}
27+
28+
public string GetPrefixedMessage(string message) {
29+
string result = prefix + message;
30+
return result;
31+
}
32+
33+
public double ApplyMultiplier(double value) {
34+
double result = value * multiplier;
35+
return result;
36+
}
37+
38+
public int GetCachedValue(int index) {
39+
if (index >= 0 && index < cachedValues.Length) {
40+
int value = cachedValues[index];
41+
return value;
42+
}
43+
return -1;
44+
}
45+
46+
public int SumCachedValues() {
47+
int sum = 0;
48+
for (int i = 0; i < cachedValues.Length; i++) {
49+
sum += cachedValues[i];
50+
}
51+
return sum;
52+
}
53+
54+
// Integer operations
1255
public int Add(int a, int b) {
1356
return a + b;
1457
}
@@ -21,6 +64,142 @@ public class MathHelper {
2164
public string FormatNumber(int num) {
2265
return num.ToString("N0", CultureInfo.InvariantCulture);
2366
}
67+
68+
// Double operations
69+
public double AddDouble(double a, double b) {
70+
double result = a + b;
71+
return result;
72+
}
73+
74+
public double DivideDouble(double a, double b) {
75+
if (b == 0) return 0;
76+
return a / b;
77+
}
78+
79+
public string FormatDouble(double num) {
80+
return num.ToString("F2", CultureInfo.InvariantCulture);
81+
}
82+
83+
// Decimal operations
84+
public decimal AddDecimal(decimal a, decimal b) {
85+
decimal result = a + b;
86+
return result;
87+
}
88+
89+
public decimal MultiplyDecimal(decimal a, decimal b) {
90+
return a * b;
91+
}
92+
93+
public string FormatCurrency(decimal amount) {
94+
return amount.ToString("C2", CultureInfo.InvariantCulture);
95+
}
96+
97+
// DateTime operations
98+
public string GetCurrentDate() {
99+
DateTime now = DateTime.Now;
100+
return now.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture);
101+
}
102+
103+
public string FormatDate(int year, int month, int day) {
104+
DateTime date = new DateTime(year, month, day);
105+
return date.ToString("MMMM dd, yyyy", CultureInfo.InvariantCulture);
106+
}
107+
108+
public int GetDaysDifference(int year1, int month1, int day1, int year2, int month2, int day2) {
109+
DateTime date1 = new DateTime(year1, month1, day1);
110+
DateTime date2 = new DateTime(year2, month2, day2);
111+
TimeSpan diff = date2 - date1;
112+
return diff.Days;
113+
}
114+
115+
// String operations
116+
public string ConcatStrings(string a, string b) {
117+
string result = a + " " + b;
118+
return result;
119+
}
120+
121+
public string ToUpperCase(string text) {
122+
return text.ToUpper();
123+
}
124+
125+
public string ReverseString(string text) {
126+
char[] charArray = text.ToCharArray();
127+
Array.Reverse(charArray);
128+
return new string(charArray);
129+
}
130+
131+
public int GetStringLength(string text) {
132+
return text.Length;
133+
}
134+
135+
// Array operations
136+
public int SumArray(int count) {
137+
int[] numbers = new int[count];
138+
for (int i = 0; i < count; i++) {
139+
numbers[i] = i + 1;
140+
}
141+
142+
int sum = 0;
143+
for (int i = 0; i < numbers.Length; i++) {
144+
sum += numbers[i];
145+
}
146+
return sum;
147+
}
148+
149+
public string JoinStringArray() {
150+
string[] words = new string[] { "XSLT", "Debugger", "Test" };
151+
string result = "";
152+
for (int i = 0; i < words.Length; i++) {
153+
if (i > 0) result += " ";
154+
result += words[i];
155+
}
156+
return result;
157+
}
158+
159+
public double AverageDoubles(int count) {
160+
double[] values = new double[count];
161+
for (int i = 0; i < count; i++) {
162+
values[i] = (i + 1) * 1.5;
163+
}
164+
165+
double sum = 0;
166+
for (int i = 0; i < values.Length; i++) {
167+
sum += values[i];
168+
}
169+
double average = sum / values.Length;
170+
return average;
171+
}
172+
173+
public int FindMaxInArray(int size) {
174+
int[] numbers = new int[size];
175+
for (int i = 0; i < size; i++) {
176+
numbers[i] = (i * 7) % 100;
177+
}
178+
179+
int max = numbers[0];
180+
for (int i = 1; i < numbers.Length; i++) {
181+
if (numbers[i] > max) {
182+
max = numbers[i];
183+
}
184+
}
185+
return max;
186+
}
187+
188+
public string ReverseArray(int count) {
189+
int[] numbers = new int[count];
190+
for (int i = 0; i < count; i++) {
191+
numbers[i] = i + 1;
192+
}
193+
194+
Array.Reverse(numbers);
195+
196+
string result = "";
197+
for (int i = 0; i < numbers.Length; i++) {
198+
if (i > 0) result += ",";
199+
result += numbers[i].ToString();
200+
}
201+
return result;
202+
}
24203
}
25204
]]>
26205
</msxsl:script>
@@ -32,9 +211,49 @@ public class MathHelper {
32211
</head>
33212
<body>
34213
<h1>C# Method Auto-Instrumentation Test</h1>
214+
215+
<h2>Private Field Access</h2>
216+
<p>Increment counter (1st call): <xsl:value-of select="user:IncrementCounter()"/></p>
217+
<p>Increment counter (2nd call): <xsl:value-of select="user:IncrementCounter()"/></p>
218+
<p>Increment counter (3rd call): <xsl:value-of select="user:IncrementCounter()"/></p>
219+
<p>Get counter value: <xsl:value-of select="user:GetCounterValue()"/></p>
220+
<p>Prefixed message: <xsl:value-of select="user:GetPrefixedMessage('Hello')"/></p>
221+
<p>Apply multiplier to 10: <xsl:value-of select="user:ApplyMultiplier(10)"/></p>
222+
<p>Cached value at index 2: <xsl:value-of select="user:GetCachedValue(2)"/></p>
223+
<p>Sum of cached values: <xsl:value-of select="user:SumCachedValues()"/></p>
224+
225+
<h2>Integer Operations</h2>
35226
<p>Add 5 + 3 = <xsl:value-of select="user:Add(5, 3)"/></p>
36227
<p>Multiply 4 * 7 = <xsl:value-of select="user:Multiply(4, 7)"/></p>
37228
<p>Formatted: <xsl:value-of select="user:FormatNumber(1000000)"/></p>
229+
230+
<h2>Double Operations</h2>
231+
<p>Add 3.14 + 2.86 = <xsl:value-of select="user:AddDouble(3.14, 2.86)"/></p>
232+
<p>Divide 10.5 / 2.5 = <xsl:value-of select="user:DivideDouble(10.5, 2.5)"/></p>
233+
<p>Formatted Double: <xsl:value-of select="user:FormatDouble(123.456)"/></p>
234+
235+
<h2>Decimal Operations</h2>
236+
<p>Add Decimal 10.50 + 20.75 = <xsl:value-of select="user:AddDecimal(10.50, 20.75)"/></p>
237+
<p>Multiply Decimal 5.5 * 2 = <xsl:value-of select="user:MultiplyDecimal(5.5, 2)"/></p>
238+
<p>Currency: <xsl:value-of select="user:FormatCurrency(1234.56)"/></p>
239+
240+
<h2>DateTime Operations</h2>
241+
<p>Current Date: <xsl:value-of select="user:GetCurrentDate()"/></p>
242+
<p>Formatted Date: <xsl:value-of select="user:FormatDate(2025, 11, 1)"/></p>
243+
<p>Days between 2025-01-01 and 2025-12-31: <xsl:value-of select="user:GetDaysDifference(2025, 1, 1, 2025, 12, 31)"/></p>
244+
245+
<h2>String Operations</h2>
246+
<p>Concat: <xsl:value-of select="user:ConcatStrings('Hello', 'World')"/></p>
247+
<p>Uppercase: <xsl:value-of select="user:ToUpperCase('xslt debugger')"/></p>
248+
<p>Reverse: <xsl:value-of select="user:ReverseString('XSLT')"/></p>
249+
<p>Length of 'Testing': <xsl:value-of select="user:GetStringLength('Testing')"/></p>
250+
251+
<h2>Array Operations</h2>
252+
<p>Sum of array [1,2,3,4,5]: <xsl:value-of select="user:SumArray(5)"/></p>
253+
<p>Join string array: <xsl:value-of select="user:JoinStringArray()"/></p>
254+
<p>Average of doubles [1.5, 3.0, 4.5, 6.0]: <xsl:value-of select="user:AverageDoubles(4)"/></p>
255+
<p>Max in array (size 10): <xsl:value-of select="user:FindMaxInArray(10)"/></p>
256+
<p>Reverse array [1,2,3,4,5,6]: <xsl:value-of select="user:ReverseArray(6)"/></p>
38257
</body>
39258
</html>
40259
</xsl:template>

XsltDebugger.ConsoleTest/ProgramUsingEngineType.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ static async Task Main(string[] args)
7070
}
7171

7272
// Enable debugging with log level
73-
XsltEngineManager.SetDebugFlags(debug: true, LogLevel.TraceAll);
74-
Console.WriteLine(" >> Debugging ENABLED (TraceAll)\n");
73+
XsltEngineManager.SetDebugFlags(debug: true, LogLevel.Log);
74+
Console.WriteLine(" >> Debugging ENABLED (Log)\n");
7575

7676
// Set breakpoint - detect which file and set appropriate line
7777
var fullStylesheetPath = Path.GetFullPath(stylesheetPath);

XsltDebugger.DebugAdapter/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ The debug adapter implements the Debug Adapter Protocol (DAP) to enable debuggin
1919
- **`Program.cs`**: Entry point for the debug adapter
2020
- **`XsltDebugSession.cs`**: Main DAP session handler
2121
- **`CompiledEngine.cs`**: XSLT 1.0 engine with inline C# support
22-
- **`SaxonEngine.cs`**: XSLT 2.0/3.0 engine using Saxon .NET
22+
- **`SaxonEngine.cs`**: XSLT 1.0/2.0/3.0 engine using Saxon .NET
2323
- **`XsltInstrumenter.cs`**: Injects debugging hooks into XSLT stylesheets
2424

2525
### Features
@@ -31,7 +31,7 @@ The debug adapter implements the Debug Adapter Protocol (DAP) to enable debuggin
3131
- **Inline C# Scripting**: Compile and execute inline C# code in XSLT via `msxsl:script`
3232
- **Multiple Engines**:
3333
- Compiled engine for XSLT 1.0 with inline C# support
34-
- Saxon .NET engine for XSLT 2.0/3.0 support
34+
- Saxon .NET engine for XSLT 1.0/2.0/3.0 support
3535
- **Instrumentation**: Dynamic XSLT modification for debug hooks
3636

3737
## Building
@@ -73,7 +73,7 @@ dotnet test ../XsltDebugger.Tests/XsltDebugger.Tests.csproj
7373
## Dependencies
7474

7575
- **Microsoft.CSharp**: For Roslyn C# compilation (inline scripts)
76-
- **SaxonHE10Net31Api**: Saxon .NET XSLT 2.0/3.0 processor (community IKVM build)
76+
- **SaxonHE10Net31Api**: Saxon .NET XSLT 1.0/2.0/3.0 processor (community IKVM build)
7777
- **System.Xml**: For XSLT 1.0 processing
7878

7979
## Protocol Support

XsltDebugger.Tests/CompiledEngineIntegrationTests.cs

Lines changed: 79 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -229,27 +229,95 @@ void OnOutput(string message)
229229
snapshot = outputLog.ToList();
230230
}
231231

232-
// Verify instrumentation occurred
233-
snapshot.Should().Contain(message => message.Contains("Instrumented 3 inline C# method(s)", StringComparison.OrdinalIgnoreCase),
234-
"should report instrumenting 3 C# methods");
235-
236-
// Verify Add method logging
232+
// Verify instrumentation occurred for all methods
233+
snapshot.Should().Contain(message => message.Contains("Instrumented ", StringComparison.Ordinal) && message.Contains(" inline C# method(s)", StringComparison.Ordinal),
234+
"should report instrumenting multiple C# methods");
235+
236+
// Verify private field access methods
237+
snapshot.Should().Contain(message => message.Contains("[inline] [IncrementCounter:", StringComparison.Ordinal),
238+
"should log IncrementCounter method");
239+
snapshot.Should().Contain(message => message.Contains("[inline] [GetCounterValue:", StringComparison.Ordinal),
240+
"should log GetCounterValue method");
241+
snapshot.Should().Contain(message => message.Contains("[inline] [GetPrefixedMessage:", StringComparison.Ordinal) && message.Contains("args = { message = Hello }"),
242+
"should log GetPrefixedMessage method with args");
243+
snapshot.Should().Contain(message => message.Contains("[inline] [ApplyMultiplier:", StringComparison.Ordinal),
244+
"should log ApplyMultiplier method");
245+
snapshot.Should().Contain(message => message.Contains("[inline] [GetCachedValue:", StringComparison.Ordinal) && message.Contains("args = { index = 2 }"),
246+
"should log GetCachedValue method with index parameter");
247+
snapshot.Should().Contain(message => message.Contains("[inline] [SumCachedValues:", StringComparison.Ordinal),
248+
"should log SumCachedValues method");
249+
250+
// Verify integer operations
237251
snapshot.Should().Contain(message => message.Contains("[inline] [Add:", StringComparison.Ordinal) && message.Contains("args = { a = 5, b = 3 }"),
238252
"should log Add method entry with parameters");
239253
snapshot.Should().Contain(message => message.Contains("[inline] [Add:", StringComparison.Ordinal) && message.Contains("return = 8"),
240254
"should log Add method return value");
241-
242-
// Verify Multiply method logging
243255
snapshot.Should().Contain(message => message.Contains("[inline] [Multiply:", StringComparison.Ordinal) && message.Contains("args = { a = 4, b = 7 }"),
244256
"should log Multiply method entry with parameters");
245257
snapshot.Should().Contain(message => message.Contains("[inline] [Multiply:", StringComparison.Ordinal) && message.Contains("return = 28"),
246258
"should log Multiply method return value");
247-
248-
// Verify FormatNumber method logging
249259
snapshot.Should().Contain(message => message.Contains("[inline] [FormatNumber:", StringComparison.Ordinal) && message.Contains("args = { num = 1000000 }"),
250260
"should log FormatNumber method entry with parameters");
251-
snapshot.Should().Contain(message => message.Contains("[inline] [FormatNumber:", StringComparison.Ordinal) && message.Contains("return = 1,000,000"),
252-
"should log FormatNumber method return value");
261+
262+
// Verify double operations
263+
snapshot.Should().Contain(message => message.Contains("[inline] [AddDouble:", StringComparison.Ordinal) && message.Contains("args = { a = 3.14, b = 2.86 }"),
264+
"should log AddDouble method with double parameters");
265+
snapshot.Should().Contain(message => message.Contains("[inline] [DivideDouble:", StringComparison.Ordinal) && message.Contains("args = { a = 10.5, b = 2.5 }"),
266+
"should log DivideDouble method with double parameters");
267+
snapshot.Should().Contain(message => message.Contains("[inline] [FormatDouble:", StringComparison.Ordinal) && message.Contains("args = { num = 123.456 }"),
268+
"should log FormatDouble method");
269+
270+
// Verify decimal operations
271+
snapshot.Should().Contain(message => message.Contains("[inline] [AddDecimal:", StringComparison.Ordinal),
272+
"should log AddDecimal method");
273+
snapshot.Should().Contain(message => message.Contains("[inline] [MultiplyDecimal:", StringComparison.Ordinal),
274+
"should log MultiplyDecimal method");
275+
snapshot.Should().Contain(message => message.Contains("[inline] [FormatCurrency:", StringComparison.Ordinal),
276+
"should log FormatCurrency method");
277+
278+
// Verify DateTime operations
279+
snapshot.Should().Contain(message => message.Contains("[inline] [GetCurrentDate:", StringComparison.Ordinal),
280+
"should log GetCurrentDate method");
281+
snapshot.Should().Contain(message => message.Contains("[inline] [FormatDate:", StringComparison.Ordinal) && message.Contains("args = { year = 2025, month = 11, day = 1 }"),
282+
"should log FormatDate method with parameters");
283+
snapshot.Should().Contain(message => message.Contains("[inline] [GetDaysDifference:", StringComparison.Ordinal),
284+
"should log GetDaysDifference method");
285+
286+
// Verify string operations
287+
snapshot.Should().Contain(message => message.Contains("[inline] [ConcatStrings:", StringComparison.Ordinal) && message.Contains("args = { a = Hello, b = World }"),
288+
"should log ConcatStrings method with string parameters");
289+
snapshot.Should().Contain(message => message.Contains("[inline] [ToUpperCase:", StringComparison.Ordinal) && message.Contains("args = { text = xslt debugger }"),
290+
"should log ToUpperCase method");
291+
snapshot.Should().Contain(message => message.Contains("[inline] [ReverseString:", StringComparison.Ordinal) && message.Contains("args = { text = XSLT }"),
292+
"should log ReverseString method");
293+
snapshot.Should().Contain(message => message.Contains("[inline] [GetStringLength:", StringComparison.Ordinal) && message.Contains("args = { text = Testing }"),
294+
"should log GetStringLength method");
295+
296+
// Verify array operations
297+
snapshot.Should().Contain(message => message.Contains("[inline] [SumArray:", StringComparison.Ordinal) && message.Contains("args = { count = 5 }"),
298+
"should log SumArray method");
299+
snapshot.Should().Contain(message => message.Contains("[inline] [JoinStringArray:", StringComparison.Ordinal),
300+
"should log JoinStringArray method");
301+
snapshot.Should().Contain(message => message.Contains("[inline] [AverageDoubles:", StringComparison.Ordinal) && message.Contains("args = { count = 4 }"),
302+
"should log AverageDoubles method");
303+
snapshot.Should().Contain(message => message.Contains("[inline] [FindMaxInArray:", StringComparison.Ordinal) && message.Contains("args = { size = 10 }"),
304+
"should log FindMaxInArray method");
305+
snapshot.Should().Contain(message => message.Contains("[inline] [ReverseArray:", StringComparison.Ordinal) && message.Contains("args = { count = 6 }"),
306+
"should log ReverseArray method");
307+
308+
// Verify output file was created
309+
var stylesheetDir = Path.GetDirectoryName(fullStylesheetPath) ?? throw new InvalidOperationException("Unable to determine stylesheet directory.");
310+
var outDir = Path.Combine(stylesheetDir, "out");
311+
var outFile = Path.Combine(outDir, $"{Path.GetFileNameWithoutExtension(fullStylesheetPath)}.out.xml");
312+
313+
File.Exists(outFile).Should().BeTrue("compiled engine should write transformation results to disk");
314+
var output = await File.ReadAllTextAsync(outFile);
315+
output.Should().Contain("Auto-Instrumentation Test");
316+
output.Should().Contain("Result: Hello");
317+
output.Should().Contain("25");
318+
output.Should().Contain("XSLT DEBUGGER");
319+
320+
TryDeleteOutput(outFile, outDir);
253321
}
254322
finally
255323
{

0 commit comments

Comments
 (0)