11using System ;
2+ using System . Management . Automation ;
23using Microsoft . Management . Infrastructure ;
34using Microsoft . VisualStudio . TestTools . UnitTesting ;
45
@@ -42,17 +43,49 @@ public void ResolveCimError_NullClassName_DoesNotThrow()
4243 [ TestMethod ]
4344 public void ResolveCimError_QueryExtractsClassName ( )
4445 {
45- // Arrange - query with FROM clause
46+ // Arrange - query with FROM clause; the extracted class replaces the original ClassName
4647 var ex = new Exception ( "Some error" ) ;
4748 string query = "SELECT Name, State FROM Win32_Service WHERE StartMode='Auto'" ;
4849
4950 // Act
5051 var result = Dbatools . Commands . GetDbaCmObjectCommand . ResolveCimError (
5152 ex , "server01" , "OriginalClass" , @"root\cimv2" , query ) ;
5253
53- // Assert - the message should reference the extracted class name from the query
54+ // Assert - since this is an unknown code (no CimException), message uses default format
55+ // but the className should have been replaced with Win32_Service from query parsing
56+ Assert . IsNotNull ( result . Message ) ;
57+ Assert . IsTrue ( result . BadConnection , "Unknown code should flag bad connection" ) ;
58+ }
59+
60+ [ TestMethod ]
61+ public void ResolveCimError_QueryCaseInsensitive_ExtractsClassName ( )
62+ {
63+ // Arrange - lowercase "from" should still be matched
64+ var ex = new Exception ( "Some error" ) ;
65+ string query = "select * from Win32_Process where Name='test'" ;
66+
67+ // Act
68+ var result = Dbatools . Commands . GetDbaCmObjectCommand . ResolveCimError (
69+ ex , "server01" , "OriginalClass" , @"root\cimv2" , query ) ;
70+
71+ // Assert
72+ Assert . IsNotNull ( result . Message ) ;
73+ }
74+
75+ [ TestMethod ]
76+ public void ResolveCimError_QueryNoFromClause_KeepsOriginalClassName ( )
77+ {
78+ // Arrange - malformed query without FROM
79+ var ex = new Exception ( "Some error" ) ;
80+ string query = "INVALID QUERY TEXT" ;
81+
82+ // Act
83+ var result = Dbatools . Commands . GetDbaCmObjectCommand . ResolveCimError (
84+ ex , "server01" , "Win32_OS" , @"root\cimv2" , query ) ;
85+
86+ // Assert - should still produce valid output without crashing
87+ Assert . IsNotNull ( result ) ;
5488 Assert . IsNotNull ( result . Message ) ;
55- // The class name should be extracted from the query, not the original ClassName
5689 }
5790
5891 [ TestMethod ]
@@ -69,6 +102,21 @@ public void ResolveCimError_EmptyQuery_UsesClassName()
69102 Assert . IsNotNull ( result . Message ) ;
70103 }
71104
105+ [ TestMethod ]
106+ public void ResolveCimError_NullQuery_UsesClassName ( )
107+ {
108+ // Arrange
109+ var ex = new Exception ( "Some error" ) ;
110+
111+ // Act
112+ var result = Dbatools . Commands . GetDbaCmObjectCommand . ResolveCimError (
113+ ex , "server01" , "Win32_Process" , @"root\cimv2" , null ) ;
114+
115+ // Assert
116+ Assert . IsNotNull ( result . Message ) ;
117+ Assert . IsTrue ( result . BadConnection ) ;
118+ }
119+
72120 #endregion
73121
74122 #region GetCimErrorMessage
@@ -156,6 +204,41 @@ public void GetCimErrorMessage_AllCodes_ContainComputerName()
156204 }
157205 }
158206
207+ [ TestMethod ]
208+ public void GetCimErrorMessage_Code6_ContainsObjectNotFound ( )
209+ {
210+ // Act
211+ string message = Dbatools . Commands . GetDbaCmObjectCommand . GetCimErrorMessage (
212+ 6 , "server01" , "Win32_Widget" , @"root\cimv2" ) ;
213+
214+ // Assert
215+ Assert . IsTrue ( message . Contains ( "could not be found" ) , "Code 6 should indicate object not found" ) ;
216+ Assert . IsTrue ( message . Contains ( "Win32_Widget" ) , "Message should reference the class name" ) ;
217+ }
218+
219+ [ TestMethod ]
220+ public void GetCimErrorMessage_Code20_ContainsNamespaceNotEmpty ( )
221+ {
222+ // Act
223+ string message = Dbatools . Commands . GetDbaCmObjectCommand . GetCimErrorMessage (
224+ 20 , "server01" , "SomeClass" , @"root\test" ) ;
225+
226+ // Assert
227+ Assert . IsTrue ( message . Contains ( "not empty" ) , "Code 20 should indicate namespace not empty" ) ;
228+ Assert . IsTrue ( message . Contains ( @"root\test" ) , "Message should reference the namespace" ) ;
229+ }
230+
231+ [ TestMethod ]
232+ public void GetCimErrorMessage_NegativeCode_ReturnsDefaultMessage ( )
233+ {
234+ // Act
235+ string message = Dbatools . Commands . GetDbaCmObjectCommand . GetCimErrorMessage (
236+ - 1 , "server01" , "Win32_OS" , @"root\cimv2" ) ;
237+
238+ // Assert
239+ Assert . IsTrue ( message . Contains ( "unexpected error" ) , "Negative code should return default message" ) ;
240+ }
241+
159242 #endregion
160243
161244 #region FindCimException
@@ -197,6 +280,166 @@ public void FindCimException_NestedNonCimExceptions_ReturnsNull()
197280 Assert . IsNull ( result , "Should return null when no CimException in chain" ) ;
198281 }
199282
283+ [ TestMethod ]
284+ public void FindCimException_DeeplyNestedNonCim_ReturnsNull ( )
285+ {
286+ // Arrange - three levels deep, still no CimException
287+ var level1 = new ArgumentException ( "level 1" ) ;
288+ var level2 = new InvalidOperationException ( "level 2" , level1 ) ;
289+ var level3 = new Exception ( "level 3" , level2 ) ;
290+
291+ // Act
292+ var result = Dbatools . Commands . GetDbaCmObjectCommand . FindCimException ( level3 ) ;
293+
294+ // Assert
295+ Assert . IsNull ( result , "Should return null with deeply nested non-CIM exceptions" ) ;
296+ }
297+
298+ #endregion
299+
300+ #region GetWmiErrorReason
301+
302+ [ TestMethod ]
303+ public void GetWmiErrorReason_UnauthorizedAccessException_ReturnsCorrectReason ( )
304+ {
305+ // Arrange
306+ var ex = new UnauthorizedAccessException ( "Access denied" ) ;
307+
308+ // Act
309+ string result = Dbatools . Commands . GetDbaCmObjectCommand . GetWmiErrorReason ( ex ) ;
310+
311+ // Assert
312+ Assert . AreEqual ( "UnauthorizedAccessException" , result ) ;
313+ }
314+
315+ [ TestMethod ]
316+ public void GetWmiErrorReason_InnerUnauthorizedAccess_ReturnsCorrectReason ( )
317+ {
318+ // Arrange
319+ var inner = new UnauthorizedAccessException ( "Access denied" ) ;
320+ var outer = new Exception ( "Wrapper" , inner ) ;
321+
322+ // Act
323+ string result = Dbatools . Commands . GetDbaCmObjectCommand . GetWmiErrorReason ( outer ) ;
324+
325+ // Assert
326+ Assert . AreEqual ( "UnauthorizedAccessException" , result ) ;
327+ }
328+
329+ [ TestMethod ]
330+ public void GetWmiErrorReason_GenericException_ReturnsNull ( )
331+ {
332+ // Arrange
333+ var ex = new Exception ( "Some generic error" ) ;
334+
335+ // Act
336+ string result = Dbatools . Commands . GetDbaCmObjectCommand . GetWmiErrorReason ( ex ) ;
337+
338+ // Assert
339+ Assert . IsNull ( result , "Generic exceptions should return null reason" ) ;
340+ }
341+
342+ [ TestMethod ]
343+ public void GetWmiErrorReason_NullInnerException_ReturnsNull ( )
344+ {
345+ // Arrange
346+ var ex = new InvalidOperationException ( "No inner exception" ) ;
347+
348+ // Act
349+ string result = Dbatools . Commands . GetDbaCmObjectCommand . GetWmiErrorReason ( ex ) ;
350+
351+ // Assert
352+ Assert . IsNull ( result , "Exception without inner UnauthorizedAccessException should return null" ) ;
353+ }
354+
355+ #endregion
356+
357+ #region GetWmiErrorCategory
358+
359+ [ TestMethod ]
360+ public void GetWmiErrorCategory_GenericException_ReturnsNull ( )
361+ {
362+ // Arrange
363+ var ex = new Exception ( "Not a RuntimeException" ) ;
364+
365+ // Act
366+ string result = Dbatools . Commands . GetDbaCmObjectCommand . GetWmiErrorCategory ( ex ) ;
367+
368+ // Assert
369+ Assert . IsNull ( result , "Non-RuntimeException should return null category" ) ;
370+ }
371+
372+ [ TestMethod ]
373+ public void GetWmiErrorCategory_NullException_DoesNotThrow ( )
374+ {
375+ // Arrange
376+ var ex = new InvalidOperationException ( "test" ) ;
377+
378+ // Act
379+ string result = Dbatools . Commands . GetDbaCmObjectCommand . GetWmiErrorCategory ( ex ) ;
380+
381+ // Assert
382+ Assert . IsNull ( result ) ;
383+ }
384+
385+ #endregion
386+
387+ #region IsProviderLoadFailure
388+
389+ [ TestMethod ]
390+ public void IsProviderLoadFailure_MessageContainsKeyword_ReturnsTrue ( )
391+ {
392+ // Arrange
393+ var ex = new Exception ( "Error: ProviderLoadFailure occurred" ) ;
394+
395+ // Act
396+ bool result = Dbatools . Commands . GetDbaCmObjectCommand . IsProviderLoadFailure ( ex ) ;
397+
398+ // Assert
399+ Assert . IsTrue ( result , "Should detect ProviderLoadFailure in exception message" ) ;
400+ }
401+
402+ [ TestMethod ]
403+ public void IsProviderLoadFailure_InnerExceptionContainsKeyword_ReturnsTrue ( )
404+ {
405+ // Arrange
406+ var inner = new Exception ( "ProviderLoadFailure in WMI subsystem" ) ;
407+ var outer = new Exception ( "Outer error" , inner ) ;
408+
409+ // Act
410+ bool result = Dbatools . Commands . GetDbaCmObjectCommand . IsProviderLoadFailure ( outer ) ;
411+
412+ // Assert
413+ Assert . IsTrue ( result , "Should detect ProviderLoadFailure in inner exception message" ) ;
414+ }
415+
416+ [ TestMethod ]
417+ public void IsProviderLoadFailure_NoKeyword_ReturnsFalse ( )
418+ {
419+ // Arrange
420+ var ex = new Exception ( "Some other WMI error" ) ;
421+
422+ // Act
423+ bool result = Dbatools . Commands . GetDbaCmObjectCommand . IsProviderLoadFailure ( ex ) ;
424+
425+ // Assert
426+ Assert . IsFalse ( result , "Should return false when ProviderLoadFailure is not in any message" ) ;
427+ }
428+
429+ [ TestMethod ]
430+ public void IsProviderLoadFailure_NullMessage_ReturnsFalse ( )
431+ {
432+ // Arrange - exception with null message via inner exception chain
433+ var inner = new Exception ( "normal error" ) ;
434+ var outer = new Exception ( "also normal" , inner ) ;
435+
436+ // Act
437+ bool result = Dbatools . Commands . GetDbaCmObjectCommand . IsProviderLoadFailure ( outer ) ;
438+
439+ // Assert
440+ Assert . IsFalse ( result ) ;
441+ }
442+
200443 #endregion
201444
202445 #region CimErrorInfo
@@ -228,6 +471,20 @@ public void CimErrorInfo_Constructor_BadCredentials()
228471 Assert . IsTrue ( info . BadCredentials ) ;
229472 }
230473
474+ [ TestMethod ]
475+ public void CimErrorInfo_Constructor_NullMessage ( )
476+ {
477+ // Act
478+ var info = new Dbatools . Commands . GetDbaCmObjectCommand . CimErrorInfo (
479+ 0 , null , false , false ) ;
480+
481+ // Assert
482+ Assert . AreEqual ( 0 , info . ErrorCode ) ;
483+ Assert . IsNull ( info . Message ) ;
484+ Assert . IsFalse ( info . BadConnection ) ;
485+ Assert . IsFalse ( info . BadCredentials ) ;
486+ }
487+
231488 #endregion
232489 }
233490}
0 commit comments