Skip to content

Commit 9897621

Browse files
feat(migration): Convert Get-DbatoolsError to C# binary cmdlet
- All parameters preserved (First, Last, Skip, All) - All code paths implemented (paging, filtering by FullyQualifiedErrorId) - Build passes (645 tests, 0 failures) - C# unit tests written and passing (20 new tests) - Pester integration tests pass (5/5, baseline maintained) - Feature parity verified (100%) - PS1 retired, cmdlet exported from dbatools.library Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent fd4e39c commit 9897621

4 files changed

Lines changed: 572 additions & 1 deletion

File tree

dbatools.library.psd1

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
'Get-DbatoolsChangeLog',
4848
'Get-DbatoolsConfig',
4949
'Get-DbatoolsConfigValue',
50+
'Get-DbatoolsError',
5051
'Invoke-DbaQuery',
5152
'Join-DbaPath',
5253
'New-DbaAzAccessToken',

docs/plan/TRACKER-MIGRATE-CONFIG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
| 1 | Get-DbatoolsChangeLog | DONE | GetDbatoolsChangeLogCommand.cs | OK | 100% | 1/1 | Read-only, no deps |
1111
| 2 | Get-DbatoolsConfig | DONE | GetDbatoolsConfigCommand.cs | OK | 100% | 7/7 | Read-only, no deps |
1212
| 3 | Get-DbatoolsConfigValue | DONE | GetDbatoolsConfigValueCommand.cs | OK | 100% | 1/1 | Read-only, no deps |
13-
| 4 | Get-DbatoolsError | PENDING | | | | | Read-only, no deps |
13+
| 4 | Get-DbatoolsError | DONE | GetDbatoolsErrorCommand.cs | OK | 100% | 5/5 | Read-only, no deps |
1414
| 5 | Get-DbatoolsLog | PENDING | | | | | Read-only, no deps |
1515
| 6 | Get-DbatoolsPath | PENDING | | | | | Read-only, no deps |
1616
| 7 | New-DbatoolsSupportPackage | PENDING | | | | | ShouldProcess required |
Lines changed: 350 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,350 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using System.Management.Automation;
5+
using Microsoft.VisualStudio.TestTools.UnitTesting;
6+
7+
namespace Dataplat.Dbatools.Tests.Commands
8+
{
9+
[TestClass]
10+
public class GetDbatoolsErrorCommandTests
11+
{
12+
#region SelectedProperties
13+
[TestMethod]
14+
public void SelectedProperties_ContainsExpectedProperties()
15+
{
16+
// Arrange
17+
string[] expected = new string[]
18+
{
19+
"CategoryInfo",
20+
"ErrorDetails",
21+
"Exception",
22+
"FullyQualifiedErrorId",
23+
"InvocationInfo",
24+
"PipelineIterationInfo",
25+
"PSMessageDetails",
26+
"ScriptStackTrace",
27+
"TargetObject"
28+
};
29+
30+
// Act
31+
string[] actual = Dataplat.Dbatools.Commands.GetDbatoolsErrorCommand.SelectedProperties;
32+
33+
// Assert
34+
Assert.AreEqual(expected.Length, actual.Length, "Property count mismatch");
35+
for (int i = 0; i < expected.Length; i++)
36+
{
37+
Assert.AreEqual(expected[i], actual[i], String.Format("Property at index {0} mismatch", i));
38+
}
39+
}
40+
41+
[TestMethod]
42+
public void SelectedProperties_HasNineProperties()
43+
{
44+
// Act
45+
string[] props = Dataplat.Dbatools.Commands.GetDbatoolsErrorCommand.SelectedProperties;
46+
47+
// Assert
48+
Assert.AreEqual(9, props.Length);
49+
}
50+
#endregion
51+
52+
#region FilterDbatoolsErrors
53+
[TestMethod]
54+
public void FilterDbatoolsErrors_NullInput_ReturnsEmptyList()
55+
{
56+
// Act
57+
List<PSObject> result = Dataplat.Dbatools.Commands.GetDbatoolsErrorCommand.FilterDbatoolsErrors(null);
58+
59+
// Assert
60+
Assert.IsNotNull(result);
61+
Assert.AreEqual(0, result.Count);
62+
}
63+
64+
[TestMethod]
65+
public void FilterDbatoolsErrors_EmptyCollection_ReturnsEmptyList()
66+
{
67+
// Arrange
68+
ArrayList errors = new ArrayList();
69+
70+
// Act
71+
List<PSObject> result = Dataplat.Dbatools.Commands.GetDbatoolsErrorCommand.FilterDbatoolsErrors(errors);
72+
73+
// Assert
74+
Assert.AreEqual(0, result.Count);
75+
}
76+
77+
[TestMethod]
78+
public void FilterDbatoolsErrors_MatchesDbatoolsErrors()
79+
{
80+
// Arrange
81+
ArrayList errors = new ArrayList();
82+
ErrorRecord dbatoolsError = new ErrorRecord(
83+
new Exception("test error"),
84+
"dbatools_Get-DbaDatabase",
85+
ErrorCategory.ConnectionError,
86+
null
87+
);
88+
errors.Add(dbatoolsError);
89+
90+
// Act
91+
List<PSObject> result = Dataplat.Dbatools.Commands.GetDbatoolsErrorCommand.FilterDbatoolsErrors(errors);
92+
93+
// Assert
94+
Assert.AreEqual(1, result.Count);
95+
Assert.AreEqual("dbatools_Get-DbaDatabase", result[0].Properties["FullyQualifiedErrorId"].Value);
96+
}
97+
98+
[TestMethod]
99+
public void FilterDbatoolsErrors_ExcludesNonDbatoolsErrors()
100+
{
101+
// Arrange
102+
ArrayList errors = new ArrayList();
103+
ErrorRecord otherError = new ErrorRecord(
104+
new Exception("other error"),
105+
"SomeOtherModule_DoStuff",
106+
ErrorCategory.InvalidOperation,
107+
null
108+
);
109+
errors.Add(otherError);
110+
111+
// Act
112+
List<PSObject> result = Dataplat.Dbatools.Commands.GetDbatoolsErrorCommand.FilterDbatoolsErrors(errors);
113+
114+
// Assert
115+
Assert.AreEqual(0, result.Count);
116+
}
117+
118+
[TestMethod]
119+
public void FilterDbatoolsErrors_CaseInsensitiveMatch()
120+
{
121+
// Arrange
122+
ArrayList errors = new ArrayList();
123+
ErrorRecord upperCase = new ErrorRecord(
124+
new Exception("test"),
125+
"DBATOOLS_SomeCmd",
126+
ErrorCategory.NotSpecified,
127+
null
128+
);
129+
errors.Add(upperCase);
130+
131+
// Act
132+
List<PSObject> result = Dataplat.Dbatools.Commands.GetDbatoolsErrorCommand.FilterDbatoolsErrors(errors);
133+
134+
// Assert
135+
Assert.AreEqual(1, result.Count, "Should match dbatools case-insensitively");
136+
}
137+
138+
[TestMethod]
139+
public void FilterDbatoolsErrors_SkipsNullItems()
140+
{
141+
// Arrange
142+
ArrayList errors = new ArrayList();
143+
errors.Add(null);
144+
ErrorRecord dbatoolsError = new ErrorRecord(
145+
new Exception("test"),
146+
"dbatools_Test",
147+
ErrorCategory.NotSpecified,
148+
null
149+
);
150+
errors.Add(dbatoolsError);
151+
152+
// Act
153+
List<PSObject> result = Dataplat.Dbatools.Commands.GetDbatoolsErrorCommand.FilterDbatoolsErrors(errors);
154+
155+
// Assert
156+
Assert.AreEqual(1, result.Count);
157+
}
158+
159+
[TestMethod]
160+
public void FilterDbatoolsErrors_OutputHasExpectedProperties()
161+
{
162+
// Arrange
163+
ArrayList errors = new ArrayList();
164+
Exception ex = new Exception("test exception");
165+
ErrorRecord record = new ErrorRecord(
166+
ex,
167+
"dbatools_Get-DbaDatabase",
168+
ErrorCategory.ConnectionError,
169+
"sql01"
170+
);
171+
errors.Add(record);
172+
173+
// Act
174+
List<PSObject> result = Dataplat.Dbatools.Commands.GetDbatoolsErrorCommand.FilterDbatoolsErrors(errors);
175+
176+
// Assert
177+
Assert.AreEqual(1, result.Count);
178+
PSObject obj = result[0];
179+
Assert.IsNotNull(obj.Properties["CategoryInfo"]);
180+
Assert.IsNotNull(obj.Properties["Exception"]);
181+
Assert.IsNotNull(obj.Properties["FullyQualifiedErrorId"]);
182+
Assert.IsNotNull(obj.Properties["ScriptStackTrace"]);
183+
Assert.IsNotNull(obj.Properties["TargetObject"]);
184+
Assert.AreEqual("sql01", obj.Properties["TargetObject"].Value);
185+
Assert.AreEqual(ex, obj.Properties["Exception"].Value);
186+
}
187+
188+
[TestMethod]
189+
public void FilterDbatoolsErrors_MixedErrors_ReturnsOnlyDbatools()
190+
{
191+
// Arrange
192+
ArrayList errors = new ArrayList();
193+
errors.Add(new ErrorRecord(new Exception("e1"), "dbatools_Cmd1", ErrorCategory.NotSpecified, null));
194+
errors.Add(new ErrorRecord(new Exception("e2"), "OtherModule_Cmd", ErrorCategory.NotSpecified, null));
195+
errors.Add(new ErrorRecord(new Exception("e3"), "dbatools_Cmd2", ErrorCategory.NotSpecified, null));
196+
197+
// Act
198+
List<PSObject> result = Dataplat.Dbatools.Commands.GetDbatoolsErrorCommand.FilterDbatoolsErrors(errors);
199+
200+
// Assert
201+
Assert.AreEqual(2, result.Count);
202+
}
203+
#endregion
204+
205+
#region ApplyPaging
206+
[TestMethod]
207+
public void ApplyPaging_NullInput_ReturnsEmptyList()
208+
{
209+
// Act
210+
List<PSObject> result = Dataplat.Dbatools.Commands.GetDbatoolsErrorCommand.ApplyPaging(null, 1, 0, 0);
211+
212+
// Assert
213+
Assert.AreEqual(0, result.Count);
214+
}
215+
216+
[TestMethod]
217+
public void ApplyPaging_EmptyInput_ReturnsEmptyList()
218+
{
219+
// Act
220+
List<PSObject> result = Dataplat.Dbatools.Commands.GetDbatoolsErrorCommand.ApplyPaging(new List<PSObject>(), 1, 0, 0);
221+
222+
// Assert
223+
Assert.AreEqual(0, result.Count);
224+
}
225+
226+
[TestMethod]
227+
public void ApplyPaging_FirstOne_ReturnsFirstItem()
228+
{
229+
// Arrange
230+
List<PSObject> items = CreateTestItems(5);
231+
232+
// Act
233+
List<PSObject> result = Dataplat.Dbatools.Commands.GetDbatoolsErrorCommand.ApplyPaging(items, 1, 0, 0);
234+
235+
// Assert
236+
Assert.AreEqual(1, result.Count);
237+
Assert.AreEqual("item0", result[0].Properties["Name"].Value);
238+
}
239+
240+
[TestMethod]
241+
public void ApplyPaging_FirstThree_ReturnsFirstThreeItems()
242+
{
243+
// Arrange
244+
List<PSObject> items = CreateTestItems(5);
245+
246+
// Act
247+
List<PSObject> result = Dataplat.Dbatools.Commands.GetDbatoolsErrorCommand.ApplyPaging(items, 3, 0, 0);
248+
249+
// Assert
250+
Assert.AreEqual(3, result.Count);
251+
Assert.AreEqual("item0", result[0].Properties["Name"].Value);
252+
Assert.AreEqual("item2", result[2].Properties["Name"].Value);
253+
}
254+
255+
[TestMethod]
256+
public void ApplyPaging_LastOne_ReturnsLastItem()
257+
{
258+
// Arrange
259+
List<PSObject> items = CreateTestItems(5);
260+
261+
// Act
262+
List<PSObject> result = Dataplat.Dbatools.Commands.GetDbatoolsErrorCommand.ApplyPaging(items, 0, 1, 0);
263+
264+
// Assert
265+
Assert.AreEqual(1, result.Count);
266+
Assert.AreEqual("item4", result[0].Properties["Name"].Value);
267+
}
268+
269+
[TestMethod]
270+
public void ApplyPaging_SkipTwo_SkipsFirstTwo()
271+
{
272+
// Arrange
273+
List<PSObject> items = CreateTestItems(5);
274+
275+
// Act
276+
List<PSObject> result = Dataplat.Dbatools.Commands.GetDbatoolsErrorCommand.ApplyPaging(items, 0, 0, 2);
277+
278+
// Assert
279+
Assert.AreEqual(3, result.Count);
280+
Assert.AreEqual("item2", result[0].Properties["Name"].Value);
281+
}
282+
283+
[TestMethod]
284+
public void ApplyPaging_SkipExceedsCount_ReturnsEmptyList()
285+
{
286+
// Arrange
287+
List<PSObject> items = CreateTestItems(3);
288+
289+
// Act
290+
List<PSObject> result = Dataplat.Dbatools.Commands.GetDbatoolsErrorCommand.ApplyPaging(items, 0, 0, 10);
291+
292+
// Assert
293+
Assert.AreEqual(0, result.Count);
294+
}
295+
296+
[TestMethod]
297+
public void ApplyPaging_SkipAndFirst_CombinesCorrectly()
298+
{
299+
// Arrange: 5 items (item0..item4), skip 1, first 2 => item1, item2
300+
List<PSObject> items = CreateTestItems(5);
301+
302+
// Act
303+
List<PSObject> result = Dataplat.Dbatools.Commands.GetDbatoolsErrorCommand.ApplyPaging(items, 2, 0, 1);
304+
305+
// Assert
306+
Assert.AreEqual(2, result.Count);
307+
Assert.AreEqual("item1", result[0].Properties["Name"].Value);
308+
Assert.AreEqual("item2", result[1].Properties["Name"].Value);
309+
}
310+
311+
[TestMethod]
312+
public void ApplyPaging_FirstLargerThanCount_ReturnsAll()
313+
{
314+
// Arrange
315+
List<PSObject> items = CreateTestItems(3);
316+
317+
// Act
318+
List<PSObject> result = Dataplat.Dbatools.Commands.GetDbatoolsErrorCommand.ApplyPaging(items, 10, 0, 0);
319+
320+
// Assert
321+
Assert.AreEqual(3, result.Count);
322+
}
323+
324+
[TestMethod]
325+
public void ApplyPaging_ZeroFirstAndLast_ReturnsAll()
326+
{
327+
// Arrange
328+
List<PSObject> items = CreateTestItems(4);
329+
330+
// Act
331+
List<PSObject> result = Dataplat.Dbatools.Commands.GetDbatoolsErrorCommand.ApplyPaging(items, 0, 0, 0);
332+
333+
// Assert
334+
Assert.AreEqual(4, result.Count);
335+
}
336+
337+
private static List<PSObject> CreateTestItems(int count)
338+
{
339+
List<PSObject> items = new List<PSObject>();
340+
for (int i = 0; i < count; i++)
341+
{
342+
PSObject obj = new PSObject();
343+
obj.Properties.Add(new PSNoteProperty("Name", String.Format("item{0}", i)));
344+
items.Add(obj);
345+
}
346+
return items;
347+
}
348+
#endregion
349+
}
350+
}

0 commit comments

Comments
 (0)