DscModuleV2Tests.cs (26178B)
1 // ----------------------------------------------------------------------------- 2 // <copyright file="DscModuleV2Tests.cs" company="Microsoft Corporation"> 3 // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 4 // </copyright> 5 // ----------------------------------------------------------------------------- 6 7 namespace Microsoft.Management.Configuration.UnitTests.Tests 8 { 9 using System; 10 using System.IO; 11 using System.Management.Automation; 12 using Microsoft.Management.Configuration.Processor.Exceptions; 13 using Microsoft.Management.Configuration.Processor.PowerShell.DscModules; 14 using Microsoft.Management.Configuration.Processor.PowerShell.Helpers; 15 using Microsoft.Management.Configuration.UnitTests.Fixtures; 16 using Microsoft.Management.Configuration.UnitTests.Helpers; 17 using Microsoft.PowerShell.Commands; 18 using Windows.Foundation.Collections; 19 using Xunit; 20 using Xunit.Abstractions; 21 using static Microsoft.Management.Configuration.UnitTests.Helpers.PowerShellTestsConstants; 22 23 /// <summary> 24 /// Tests DscModuleV2 with really simple resources. 25 /// </summary> 26 [Collection("UnitTestCollection")] 27 [InProc] 28 public class DscModuleV2Tests 29 { 30 private readonly UnitTestFixture fixture; 31 private readonly ITestOutputHelper log; 32 33 /// <summary> 34 /// Initializes a new instance of the <see cref="DscModuleV2Tests"/> class. 35 /// </summary> 36 /// <param name="fixture">Fixture.</param> 37 /// <param name="log">log.</param> 38 public DscModuleV2Tests(UnitTestFixture fixture, ITestOutputHelper log) 39 { 40 this.fixture = fixture; 41 this.log = log; 42 } 43 44 /// <summary> 45 /// Tests GetAllDscResources. 46 /// </summary> 47 [Fact] 48 public void GetAllDscResources_Test() 49 { 50 var testEnvironment = this.fixture.PrepareTestProcessorEnvironment(); 51 52 var dscModule = new DscModuleV2(); 53 using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); 54 var resources = dscModule.GetAllDscResources(pwsh); 55 56 Assert.True(resources.Count > 0); 57 Assert.Contains(resources, r => r.Name == TestModule.SimpleFileResourceName); 58 } 59 60 /// <summary> 61 /// Tests GetDscResourcesInModule. 62 /// </summary> 63 /// <param name="module">Module.</param> 64 /// <param name="expectedResources">Expected DSC resources.</param> 65 [Theory] 66 [InlineData(TestModule.SimpleTestResourceModuleName, 5)] 67 [InlineData("MyReallyFakeModule", 0)] 68 public void GetDscResourcesInModule_Test(string module, int expectedResources) 69 { 70 var testEnvironment = this.fixture.PrepareTestProcessorEnvironment(); 71 72 var dscModule = new DscModuleV2(); 73 using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); 74 var resources = dscModule.GetDscResourcesInModule( 75 pwsh, 76 PowerShellHelpers.CreateModuleSpecification(module)); 77 Assert.Equal(expectedResources, resources.Count); 78 } 79 80 /// <summary> 81 /// Tests GetDscResourcesInModule with versions. 82 /// </summary> 83 [Fact] 84 public void GetDscResourcesInModule_VersionTest() 85 { 86 string newVersion = "1.0.0.0"; 87 var testEnvironment = this.fixture.PrepareTestProcessorEnvironment(); 88 89 // Get duplicated resources by creating a new directory and copy our modules. 90 // Change version and add them to the PSModulePath. 91 using var tmpDir = new TempDirectory(); 92 tmpDir.CopyDirectory(this.fixture.TestModulesPath); 93 var manifestFile = Path.Combine( 94 tmpDir.FullDirectoryPath, 95 TestModule.SimpleTestResourceModuleName, 96 TestModule.SimpleTestResourceManifestFileName); 97 File.WriteAllText( 98 manifestFile, 99 File.ReadAllText(manifestFile).Replace("0.0.0.1", newVersion)); 100 testEnvironment.AppendPSModulePath(tmpDir.FullDirectoryPath); 101 102 var dscModule = new DscModuleV2(); 103 104 // This doesn't work on v2 105 ////var allResources = dscModule.GetDscResourcesInModule( 106 //// testEnvironment.Runspace, 107 //// PowerShellHelpers.CreateModuleSpecification(TestModule.SimpleTestResourceModuleName)); 108 ////Assert.Equal(8, allResources.Count); 109 { 110 using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); 111 var ogResources = dscModule.GetDscResourcesInModule( 112 pwsh, 113 PowerShellHelpers.CreateModuleSpecification( 114 TestModule.SimpleTestResourceModuleName, 115 version: TestModule.SimpleTestResourceVersion)); 116 Assert.Equal(5, ogResources.Count); 117 } 118 119 { 120 using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); 121 var newVersionResources = dscModule.GetDscResourcesInModule( 122 pwsh, 123 PowerShellHelpers.CreateModuleSpecification( 124 TestModule.SimpleTestResourceModuleName, 125 version: newVersion)); 126 Assert.Equal(5, newVersionResources.Count); 127 } 128 129 { 130 using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); 131 var badVersionResources = dscModule.GetDscResourcesInModule( 132 pwsh, 133 PowerShellHelpers.CreateModuleSpecification( 134 TestModule.SimpleTestResourceModuleName, 135 version: "1.2.3.4")); 136 Assert.Equal(0, badVersionResources.Count); 137 } 138 } 139 140 /// <summary> 141 /// Tests GetDscResource. Should return a resource. 142 /// </summary> 143 [Fact] 144 public void GetDscResource_ResourceExists() 145 { 146 var testEnvironment = this.fixture.PrepareTestProcessorEnvironment(); 147 148 var dscModule = new DscModuleV2(); 149 using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); 150 var resource = dscModule.GetDscResource( 151 pwsh, 152 TestModule.SimpleTestResourceName, 153 PowerShellHelpers.CreateModuleSpecification(TestModule.SimpleTestResourceModuleName)); 154 155 Assert.NotNull(resource); 156 } 157 158 /// <summary> 159 /// Test GetDscResource for a resource that doesn't exist. 160 /// </summary> 161 [Fact] 162 public void GetDscResource_ResourceDoesntExist() 163 { 164 var testEnvironment = this.fixture.PrepareTestProcessorEnvironment(); 165 166 var dscModule = new DscModuleV2(); 167 using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); 168 var resource = dscModule.GetDscResource( 169 pwsh, 170 "FakeResourceName", 171 PowerShellHelpers.CreateModuleSpecification( 172 TestModule.SimpleTestResourceModuleName)); 173 Assert.Null(resource); 174 } 175 176 /// <summary> 177 /// Test GetDscResource when the same module is in different paths. 178 /// </summary> 179 [Fact] 180 public void GetDscResource_Conflict() 181 { 182 var testEnvironment = this.fixture.PrepareTestProcessorEnvironment(); 183 184 // Get duplicated resources by creating a new directory and copy our modules. 185 // Then add it to the PSModulePath. 186 using var tmpDir = new TempDirectory(); 187 tmpDir.CopyDirectory(this.fixture.TestModulesPath); 188 testEnvironment.AppendPSModulePath(tmpDir.FullDirectoryPath); 189 190 var dscModule = new DscModuleV2(); 191 using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); 192 Assert.Throws<GetDscResourceModuleConflict>( 193 () => dscModule.GetDscResource( 194 pwsh, 195 TestModule.SimpleTestResourceName, 196 PowerShellHelpers.CreateModuleSpecification( 197 TestModule.SimpleTestResourceModuleName))); 198 } 199 200 /// <summary> 201 /// Tests GetDscResource when there are multiple versions of a resource. 202 /// </summary> 203 [Fact] 204 public void GetDscResource_DiffVersions() 205 { 206 string newVersion = "2.0.0.0"; 207 var testEnvironment = this.fixture.PrepareTestProcessorEnvironment(); 208 209 // Get duplicated resources by creating a new directory and copy our modules. 210 // Change version and add them to the PSModulePath. 211 using var tmpDir = new TempDirectory(); 212 tmpDir.CopyDirectory(this.fixture.TestModulesPath); 213 var manifestFile = Path.Combine( 214 tmpDir.FullDirectoryPath, 215 TestModule.SimpleTestResourceModuleName, 216 TestModule.SimpleTestResourceManifestFileName); 217 File.WriteAllText( 218 manifestFile, 219 File.ReadAllText(manifestFile).Replace("0.0.0.1", newVersion)); 220 testEnvironment.AppendPSModulePath(tmpDir.FullDirectoryPath); 221 222 var dscModule = new DscModuleV2(); 223 224 // specific version. 225 { 226 using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); 227 var resource = dscModule.GetDscResource( 228 pwsh, 229 TestModule.SimpleTestResourceName, 230 PowerShellHelpers.CreateModuleSpecification( 231 TestModule.SimpleTestResourceModuleName, 232 TestModule.SimpleTestResourceVersion)); 233 Assert.NotNull(resource); 234 } 235 236 { 237 using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); 238 var dsc = dscModule.GetDscResource( 239 pwsh, 240 TestModule.SimpleTestResourceName, 241 PowerShellHelpers.CreateModuleSpecification( 242 TestModule.SimpleTestResourceModuleName, 243 version: newVersion)); 244 245 Assert.NotNull(dsc); 246 Assert.NotNull(dsc.Version); 247 Assert.Equal(newVersion, dsc.Version.ToString()); 248 } 249 } 250 251 /// <summary> 252 /// Calls Invoke-DscResource Get. 253 /// </summary> 254 [Fact] 255 public void InvokeGetResource_Test() 256 { 257 var testEnvironment = this.fixture.PrepareTestProcessorEnvironment(); 258 259 var dscModule = new DscModuleV2(); 260 using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); 261 var getResult = dscModule.InvokeGetResource( 262 pwsh, 263 new ValueSet(), 264 TestModule.SimpleTestResourceName, 265 PowerShellHelpers.CreateModuleSpecification( 266 TestModule.SimpleTestResourceModuleName)); 267 268 Assert.True(getResult.ContainsKey("key")); 269 Assert.True(getResult.TryGetValue("key", out object keyValue)); 270 Assert.Equal("SimpleTestResourceKey", keyValue as string); 271 } 272 273 /// <summary> 274 /// Calls Invoke-DscResource Get. Resource Get throws. 275 /// </summary> 276 [Fact] 277 public void InvokeGetResource_ResourceThrows() 278 { 279 var testEnvironment = this.fixture.PrepareTestProcessorEnvironment(); 280 281 var dscModule = new DscModuleV2(); 282 283 using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); 284 var exception = Assert.Throws<InvokeDscResourceException>(() => 285 dscModule.InvokeGetResource( 286 pwsh, 287 new ValueSet(), 288 TestModule.SimpleTestResourceThrowsName, 289 PowerShellHelpers.CreateModuleSpecification( 290 TestModule.SimpleTestResourceModuleName))); 291 292 Assert.IsType<RuntimeException>(exception.InnerException); 293 } 294 295 /// <summary> 296 /// Calls Invoke-DscResource Get. Resource writes error. 297 /// </summary> 298 [Fact(Skip = "Not supported in PSDesiredStateConfiguration 2.0.7")] 299 public void InvokeGetResource_ResourceError() 300 { 301 var testEnvironment = this.fixture.PrepareTestProcessorEnvironment(); 302 303 var dscModule = new DscModuleV2(); 304 using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); 305 Assert.Throws<WriteErrorException>(() => 306 dscModule.InvokeGetResource( 307 pwsh, 308 new ValueSet(), 309 TestModule.SimpleTestResourceErrorName, 310 PowerShellHelpers.CreateModuleSpecification( 311 TestModule.SimpleTestResourceModuleName))); 312 } 313 314 /// <summary> 315 /// Calls Invoke-DscResource Get. Resource does not exist. 316 /// </summary> 317 [Fact] 318 public void InvokeGetResource_ResourceDoesntExist() 319 { 320 var testEnvironment = this.fixture.PrepareTestProcessorEnvironment(); 321 322 var dscModule = new DscModuleV2(); 323 using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); 324 var exception = Assert.Throws<InvokeDscResourceException>( 325 () => dscModule.InvokeGetResource( 326 pwsh, 327 new ValueSet(), 328 "FakeResourceName", 329 PowerShellHelpers.CreateModuleSpecification( 330 TestModule.SimpleTestResourceModuleName))); 331 332 Assert.IsType<RuntimeException>(exception.InnerException); 333 } 334 335 /// <summary> 336 /// Calls Invoke-DscResource Test. 337 /// </summary> 338 /// <param name="value">Setting value.</param> 339 /// <param name="expectedResult">Expected result.</param> 340 [Theory] 341 [InlineData("4815162342", true)] 342 [InlineData("notalostreference", false)] 343 public void InvokeTestResource_Test(string value, bool expectedResult) 344 { 345 var testEnvironment = this.fixture.PrepareTestProcessorEnvironment(); 346 347 var dscModule = new DscModuleV2(); 348 349 var settings = new ValueSet() 350 { 351 { "secretCode", value }, 352 }; 353 354 using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); 355 var testResult = dscModule.InvokeTestResource( 356 pwsh, 357 settings, 358 TestModule.SimpleTestResourceName, 359 PowerShellHelpers.CreateModuleSpecification( 360 TestModule.SimpleTestResourceModuleName)); 361 362 Assert.Equal(expectedResult, testResult); 363 } 364 365 /// <summary> 366 /// Calls Invoke-DscResource Test. Resource throws. 367 /// </summary> 368 [Fact] 369 public void InvokeTestResource_Throws() 370 { 371 var testEnvironment = this.fixture.PrepareTestProcessorEnvironment(); 372 373 var dscModule = new DscModuleV2(); 374 using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); 375 var exception = Assert.Throws<InvokeDscResourceException>(() => 376 dscModule.InvokeTestResource( 377 pwsh, 378 new ValueSet(), 379 TestModule.SimpleTestResourceThrowsName, 380 PowerShellHelpers.CreateModuleSpecification( 381 TestModule.SimpleTestResourceModuleName))); 382 383 Assert.IsType<RuntimeException>(exception.InnerException); 384 } 385 386 /// <summary> 387 /// Calls Invoke-DscResource Test. Resource writes error. 388 /// </summary> 389 [Fact(Skip = "Not supported in PSDesiredStateConfiguration 2.0.7")] 390 public void InvokeTestResource_ResourceError() 391 { 392 var testEnvironment = this.fixture.PrepareTestProcessorEnvironment(); 393 394 var dscModule = new DscModuleV2(); 395 using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); 396 Assert.Throws<WriteErrorException>(() => 397 dscModule.InvokeTestResource( 398 pwsh, 399 new ValueSet(), 400 TestModule.SimpleTestResourceErrorName, 401 PowerShellHelpers.CreateModuleSpecification( 402 TestModule.SimpleTestResourceModuleName))); 403 } 404 405 /// <summary> 406 /// Calls Invoke-DscResource Test. Resource does not exist. 407 /// </summary> 408 [Fact] 409 public void InvokeTestResource_ResourceDoesntExist() 410 { 411 var testEnvironment = this.fixture.PrepareTestProcessorEnvironment(); 412 413 var dscModule = new DscModuleV2(); 414 using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); 415 var exception = Assert.Throws<InvokeDscResourceException>(() => 416 _ = dscModule.InvokeTestResource( 417 pwsh, 418 new ValueSet(), 419 "FakeResourceName", 420 PowerShellHelpers.CreateModuleSpecification( 421 TestModule.SimpleTestResourceModuleName))); 422 423 Assert.IsType<RuntimeException>(exception.InnerException); 424 } 425 426 /// <summary> 427 /// Calls Invoke-DscResource Set. 428 /// </summary> 429 /// <param name="value">Setting value.</param> 430 /// <param name="rebootRequired">Expected reboot required.</param> 431 [Fact] 432 public void InvokeSetResource_Test() 433 { 434 var testEnvironment = this.fixture.PrepareTestProcessorEnvironment(); 435 436 var dscModule = new DscModuleV2(); 437 438 var settings = new ValueSet() 439 { 440 { "secretCode", "4815162342" }, 441 }; 442 443 using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); 444 var testResult = dscModule.InvokeSetResource( 445 pwsh, 446 settings, 447 TestModule.SimpleTestResourceName, 448 PowerShellHelpers.CreateModuleSpecification( 449 TestModule.SimpleTestResourceModuleName)); 450 451 // TODO: Verify reboot required when is supported for class resources. 452 ////Assert.Equal(rebootRequired, testResult); 453 } 454 455 /// <summary> 456 /// Calls Invoke-DscResource Set. Resource throws. 457 /// </summary> 458 [Fact] 459 public void InvokeSetResource_Throws() 460 { 461 var testEnvironment = this.fixture.PrepareTestProcessorEnvironment(); 462 463 var dscModule = new DscModuleV2(); 464 using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); 465 var exception = Assert.Throws<InvokeDscResourceException>(() => 466 dscModule.InvokeSetResource( 467 pwsh, 468 new ValueSet(), 469 TestModule.SimpleTestResourceThrowsName, 470 PowerShellHelpers.CreateModuleSpecification( 471 TestModule.SimpleTestResourceModuleName))); 472 473 Assert.IsType<RuntimeException>(exception.InnerException); 474 } 475 476 /// <summary> 477 /// Calls Invoke-DscResource Set. Resource writes error. 478 /// </summary> 479 [Fact(Skip = "Not supported in PSDesiredStateConfiguration 2.0.7")] 480 public void InvokeSetResource_ResourceError() 481 { 482 var testEnvironment = this.fixture.PrepareTestProcessorEnvironment(); 483 484 var dscModule = new DscModuleV2(); 485 using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); 486 Assert.Throws<WriteErrorException>(() => 487 dscModule.InvokeSetResource( 488 pwsh, 489 new ValueSet(), 490 TestModule.SimpleTestResourceErrorName, 491 PowerShellHelpers.CreateModuleSpecification( 492 TestModule.SimpleTestResourceModuleName))); 493 } 494 495 /// <summary> 496 /// Calls Invoke-DscResource Set. Resource does not exist. 497 /// </summary> 498 [Fact] 499 public void InvokeSetResource_ResourceDoesntExist() 500 { 501 var testEnvironment = this.fixture.PrepareTestProcessorEnvironment(); 502 503 var dscModule = new DscModuleV2(); 504 using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); 505 var exception = Assert.Throws<InvokeDscResourceException>(() => 506 dscModule.InvokeSetResource( 507 pwsh, 508 new ValueSet(), 509 "FakeResourceName", 510 PowerShellHelpers.CreateModuleSpecification( 511 TestModule.SimpleTestResourceModuleName))); 512 513 Assert.IsType<RuntimeException>(exception.InnerException); 514 } 515 516 /// <summary> 517 /// Test calling Invoke-DscResource when a resource has multiple versions. 518 /// </summary> 519 [Fact] 520 public void InvokeResource_MultipleVersions() 521 { 522 string newVersion = "0.0.2.0"; 523 var testEnvironment = this.fixture.PrepareTestProcessorEnvironment(); 524 525 // Get duplicated resources by creating a new directory and copy our modules. 526 // Change version and add them to the PSModulePath. 527 using var tmpDir = new TempDirectory(); 528 tmpDir.CopyDirectory(this.fixture.TestModulesPath); 529 var manifestFile = Path.Combine( 530 tmpDir.FullDirectoryPath, 531 TestModule.SimpleTestResourceModuleName, 532 TestModule.SimpleTestResourceManifestFileName); 533 File.WriteAllText( 534 manifestFile, 535 File.ReadAllText(manifestFile).Replace("0.0.0.1", newVersion)); 536 testEnvironment.AppendPSModulePath(tmpDir.FullDirectoryPath); 537 538 var dscModule = new DscModuleV2(); 539 { 540 using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); 541 dscModule.InvokeSetResource( 542 pwsh, 543 new ValueSet(), 544 TestModule.SimpleTestResourceName, 545 PowerShellHelpers.CreateModuleSpecification( 546 TestModule.SimpleTestResourceModuleName, 547 TestModule.SimpleTestResourceVersion)); 548 } 549 550 { 551 using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); 552 dscModule.InvokeSetResource( 553 pwsh, 554 new ValueSet(), 555 TestModule.SimpleTestResourceName, 556 PowerShellHelpers.CreateModuleSpecification( 557 TestModule.SimpleTestResourceModuleName, 558 version: newVersion)); 559 } 560 } 561 562 /// <summary> 563 /// Calls Invoke-DscResource invalid arguments. 564 /// </summary> 565 [Fact] 566 public void InvokeSetResource_InvalidArguments() 567 { 568 var testEnvironment = this.fixture.PrepareTestProcessorEnvironment(); 569 570 var dscModule = new DscModuleV2(); 571 572 var settings = new ValueSet() 573 { 574 { "Fake", "please dont add it" }, 575 }; 576 577 using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); 578 var e = Assert.Throws<InvokeDscResourceException>(() => dscModule.InvokeSetResource( 579 pwsh, 580 settings, 581 TestModule.SimpleTestResourceName, 582 PowerShellHelpers.CreateModuleSpecification( 583 TestModule.SimpleTestResourceModuleName))); 584 585 Assert.Contains("The property 'Fake' cannot be found on this object.", e.Message); 586 Assert.Equal(ConfigurationUnitResultSource.ConfigurationSet, e.ResultSource); 587 } 588 589 /// <summary> 590 /// Tests GetDscResourcesInModule with versions. 591 /// </summary> 592 [Fact] 593 public void InvokeSetResource_ModulePathSpaces() 594 { 595 // Copy test module to a directory with spaces. 596 using var tmpDir = new TempDirectory(directoryName: Path.Combine(Guid.NewGuid().ToString(), "Path With Spaces")); 597 tmpDir.CopyDirectory(this.fixture.TestModulesPath); 598 var manifestFile = Path.Combine( 599 tmpDir.FullDirectoryPath, 600 TestModule.SimpleTestResourceModuleName, 601 TestModule.SimpleTestResourceManifestFileName); 602 603 var testEnvironment = this.fixture.PrepareTestProcessorEnvironment(); 604 testEnvironment.CleanupPSModulePath(this.fixture.TestModulesPath); 605 testEnvironment.AppendPSModulePath(tmpDir.FullDirectoryPath); 606 607 var dscModule = new DscModuleV2(); 608 609 var settings = new ValueSet() 610 { 611 { "secretCode", "4815162342" }, 612 }; 613 614 using PowerShell pwsh = PowerShell.Create(testEnvironment.Runspace); 615 var testResult = dscModule.InvokeSetResource( 616 pwsh, 617 settings, 618 TestModule.SimpleTestResourceName, 619 PowerShellHelpers.CreateModuleSpecification( 620 TestModule.SimpleTestResourceModuleName)); 621 } 622 } 623 }