ConfigurationSetProcessorTests.cs (42778B)
1 // ----------------------------------------------------------------------------- 2 // <copyright file="ConfigurationSetProcessorTests.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.Collections.Generic; 11 using System.Management.Automation; 12 using Microsoft.Management.Configuration; 13 using Microsoft.Management.Configuration.Processor.Exceptions; 14 using Microsoft.Management.Configuration.Processor.Helpers; 15 using Microsoft.Management.Configuration.Processor.PowerShell.DscResourcesInfo; 16 using Microsoft.Management.Configuration.Processor.PowerShell.Helpers; 17 using Microsoft.Management.Configuration.Processor.PowerShell.ProcessorEnvironments; 18 using Microsoft.Management.Configuration.Processor.PowerShell.Set; 19 using Microsoft.Management.Configuration.UnitTests.Fixtures; 20 using Microsoft.Management.Configuration.UnitTests.Helpers; 21 using Microsoft.PowerShell.Commands; 22 using Moq; 23 using Windows.Foundation.Collections; 24 using Windows.Security.Cryptography.Certificates; 25 using Xunit; 26 using Xunit.Abstractions; 27 28 /// <summary> 29 /// Unit tests for configuration processor tests. 30 /// </summary> 31 [Collection("UnitTestCollection")] 32 [InProc] 33 public class ConfigurationSetProcessorTests 34 { 35 private readonly UnitTestFixture fixture; 36 private readonly ITestOutputHelper log; 37 38 /// <summary> 39 /// Initializes a new instance of the <see cref="ConfigurationSetProcessorTests"/> class. 40 /// </summary> 41 /// <param name="fixture">Unit test fixture.</param> 42 /// <param name="log">Log helper.</param> 43 public ConfigurationSetProcessorTests(UnitTestFixture fixture, ITestOutputHelper log) 44 { 45 this.fixture = fixture; 46 this.log = log; 47 } 48 49 /// <summary> 50 /// Test CreateUnitProcessor. Happy path. 51 /// </summary> 52 [Fact] 53 public void CreateUnitProcessor_ResourceExists() 54 { 55 string resourceName = "xResourceName"; 56 string moduleName = "xModuleName"; 57 Version version = new Version("1.0"); 58 59 var processorEnvMock = new Mock<IProcessorEnvironment>(); 60 processorEnvMock.Setup( 61 m => m.GetDscResource(It.Is<ConfigurationUnitAndModule>(c => c.Unit.Type == resourceName))) 62 .Returns(new DscResourceInfoInternal(resourceName, moduleName, version)) 63 .Verifiable(); 64 65 var configurationSetProcessor = new PowerShellConfigurationSetProcessor( 66 processorEnvMock.Object, 67 new ConfigurationSet()); 68 69 var unit = new ConfigurationUnit 70 { 71 Type = resourceName, 72 }; 73 unit.Metadata.Add("module", moduleName); 74 unit.Metadata.Add("version", version.ToString()); 75 76 var unitProcessor = configurationSetProcessor.CreateUnitProcessor(unit); 77 Assert.NotNull(unitProcessor); 78 Assert.Equal(unit.Type, unitProcessor.Unit.Type); 79 80 processorEnvMock.Verify(); 81 } 82 83 /// <summary> 84 /// Test CreateUnitProcessor case-insensitive. 85 /// </summary> 86 [Fact] 87 public void CreateUnitProcessor_CaseInsensitive() 88 { 89 string resourceName = "name"; 90 string moduleName = "xModuleName"; 91 Version version = new Version("1.0"); 92 93 var processorEnvMock = new Mock<IProcessorEnvironment>(); 94 processorEnvMock.Setup( 95 m => m.GetDscResource(It.Is<ConfigurationUnitAndModule>(c => c.Unit.Type.Equals("Name", StringComparison.OrdinalIgnoreCase)))) 96 .Returns(new DscResourceInfoInternal("Name", moduleName, version)) 97 .Verifiable(); 98 99 var configurationSetProcessor = new PowerShellConfigurationSetProcessor( 100 processorEnvMock.Object, 101 new ConfigurationSet()); 102 103 var unit = new ConfigurationUnit 104 { 105 Type = resourceName, 106 }; 107 unit.Metadata.Add("module", moduleName); 108 unit.Metadata.Add("version", version.ToString()); 109 110 var unitProcessor = configurationSetProcessor.CreateUnitProcessor(unit); 111 Assert.NotNull(unitProcessor); 112 Assert.Equal(unit.Type, unitProcessor.Unit.Type); 113 114 processorEnvMock.Verify(); 115 } 116 117 /// <summary> 118 /// Test CreateUnitProcessor case-insensitive. 119 /// </summary> 120 [Fact] 121 public void CreateUnitProcessor_ResourceNameMismatch() 122 { 123 string resourceName = "name"; 124 string moduleName = "xModuleName"; 125 Version version = new Version("1.0"); 126 127 var processorEnvMock = new Mock<IProcessorEnvironment>(); 128 processorEnvMock.Setup( 129 m => m.GetDscResource(It.Is<ConfigurationUnitAndModule>(c => c.Unit.Type == resourceName))) 130 .Returns(new DscResourceInfoInternal("OtherName", moduleName, version)) 131 .Verifiable(); 132 133 var configurationSetProcessor = new PowerShellConfigurationSetProcessor( 134 processorEnvMock.Object, 135 new ConfigurationSet()); 136 137 var unit = new ConfigurationUnit 138 { 139 Type = resourceName, 140 }; 141 unit.Metadata.Add("module", moduleName); 142 unit.Metadata.Add("version", version.ToString()); 143 144 Assert.Throws<ArgumentException>(() => configurationSetProcessor.CreateUnitProcessor(unit)); 145 146 processorEnvMock.Verify(); 147 } 148 149 /// <summary> 150 /// Test CreateUnitProcessor with no version directive. 151 /// </summary> 152 [Fact] 153 public void CreateUnitProcessor_ResourceExists_NoVersionDirective() 154 { 155 string resourceName = "xResourceName"; 156 string moduleName = "xModuleName"; 157 Version version = new Version("1.0.0.0"); 158 159 var processorEnvMock = new Mock<IProcessorEnvironment>(); 160 processorEnvMock.Setup( 161 m => m.GetDscResource(It.Is<ConfigurationUnitAndModule>(c => c.Unit.Type == resourceName))) 162 .Returns(new DscResourceInfoInternal(resourceName, moduleName, version)) 163 .Verifiable(); 164 165 var configurationSetProcessor = new PowerShellConfigurationSetProcessor( 166 processorEnvMock.Object, 167 new ConfigurationSet()); 168 169 var unit = new ConfigurationUnit 170 { 171 Type = resourceName, 172 }; 173 unit.Metadata.Add("module", moduleName); 174 175 var unitProcessor = configurationSetProcessor.CreateUnitProcessor(unit); 176 Assert.NotNull(unitProcessor); 177 Assert.Equal(unit.Type, unitProcessor.Unit.Type); 178 179 processorEnvMock.Verify(); 180 } 181 182 /// <summary> 183 /// Test CreateUnitProcessor with no module directive. 184 /// </summary> 185 [Fact] 186 public void CreateUnitProcessor_ResourceExists_NoModuleDirective() 187 { 188 string resourceName = "xResourceName"; 189 string moduleName = "xModuleName"; 190 Version version = new Version("1.0"); 191 192 var processorEnvMock = new Mock<IProcessorEnvironment>(); 193 processorEnvMock.Setup( 194 m => m.GetDscResource(It.Is<ConfigurationUnitAndModule>(c => c.Unit.Type == resourceName))) 195 .Returns(new DscResourceInfoInternal(resourceName, moduleName, version)) 196 .Verifiable(); 197 198 var configurationSetProcessor = new PowerShellConfigurationSetProcessor( 199 processorEnvMock.Object, 200 new ConfigurationSet()); 201 202 var unit = new ConfigurationUnit 203 { 204 Type = resourceName, 205 }; 206 207 var unitProcessor = configurationSetProcessor.CreateUnitProcessor(unit); 208 Assert.NotNull(unitProcessor); 209 Assert.Equal(unit.Type, unitProcessor.Unit.Type); 210 211 processorEnvMock.Verify(); 212 } 213 214 /// <summary> 215 /// Tests Creating a unit processor by downloading the resource. 216 /// </summary> 217 [Fact] 218 public void CreateUnitProcessor_InstallResource() 219 { 220 string resourceName = "xResourceName"; 221 string moduleName = "xModuleName"; 222 Version version = new Version("1.0"); 223 224 DscResourceInfoInternal? nullResource = null; 225 DscResourceInfoInternal dscResourceInfo = new DscResourceInfoInternal(resourceName, moduleName, version); 226 var processorEnvMock = new Mock<IProcessorEnvironment>(); 227 processorEnvMock.SetupSequence( 228 m => m.GetDscResource(It.Is<ConfigurationUnitAndModule>(c => c.Unit.Type == resourceName))) 229 .Returns(nullResource) 230 .Returns(dscResourceInfo); 231 232 PSObject findDscResourceResult = new PSObject(processorEnvMock); 233 processorEnvMock.Setup( 234 m => m.FindModule(It.Is<ConfigurationUnitAndModule>(c => c.Unit.Type == resourceName))) 235 .Returns(findDscResourceResult) 236 .Verifiable(); 237 238 processorEnvMock.Setup( 239 m => m.InstallModule(findDscResourceResult)) 240 .Verifiable(); 241 242 var configurationSetProcessor = new PowerShellConfigurationSetProcessor( 243 processorEnvMock.Object, 244 new ConfigurationSet()); 245 246 var unit = new ConfigurationUnit 247 { 248 Type = resourceName, 249 }; 250 unit.Metadata.Add("module", moduleName); 251 unit.Metadata.Add("version", version.ToString()); 252 253 var unitProcessor = configurationSetProcessor.CreateUnitProcessor(unit); 254 Assert.NotNull(unitProcessor); 255 Assert.Equal(unit.Type, unitProcessor.Unit.Type); 256 257 processorEnvMock.Verify(); 258 } 259 260 /// <summary> 261 /// Tests Creating a unit processor by downloading the resource. 262 /// </summary> 263 [Fact] 264 public void CreateUnitProcessor_InstallResource_WithoutModule() 265 { 266 string resourceName = "SimpleFileResource"; 267 Version version = new Version("0.0.0.1"); 268 269 DscResourceInfoInternal? nullResource = null; 270 DscResourceInfoInternal dscResourceInfo = new DscResourceInfoInternal(resourceName, null, version); 271 var processorEnvMock = new Mock<IProcessorEnvironment>(); 272 processorEnvMock.SetupSequence( 273 m => m.GetDscResource(It.Is<ConfigurationUnitAndModule>(c => c.Unit.Type == resourceName))) 274 .Returns(nullResource) 275 .Returns(dscResourceInfo); 276 277 PSObject findDscResourceResult = this.CreateFindResourceInfo(); 278 processorEnvMock.Setup( 279 m => m.FindDscResource(It.Is<ConfigurationUnitAndModule>(c => c.Unit.Type == resourceName))) 280 .Returns(findDscResourceResult) 281 .Verifiable(); 282 283 PSObject moduleInfo = ((dynamic)findDscResourceResult).PSGetModuleInfo; 284 processorEnvMock.Setup( 285 m => m.InstallModule(moduleInfo)) 286 .Verifiable(); 287 288 var configurationSetProcessor = new PowerShellConfigurationSetProcessor( 289 processorEnvMock.Object, 290 new ConfigurationSet()); 291 292 var unit = new ConfigurationUnit 293 { 294 Type = resourceName, 295 }; 296 unit.Metadata.Add("version", version.ToString()); 297 298 var unitProcessor = configurationSetProcessor.CreateUnitProcessor(unit); 299 Assert.NotNull(unitProcessor); 300 Assert.Equal(unit.Type, unitProcessor.Unit.Type); 301 302 processorEnvMock.Verify(); 303 } 304 305 /// <summary> 306 /// Tests Creating a unit processor by downloading the resource. 307 /// </summary> 308 [Fact] 309 public void CreateUnitProcessor_InstallResource_NotFoundAfterInstall() 310 { 311 string resourceName = "xResourceName"; 312 string moduleName = "xModuleName"; 313 Version version = new Version("1.0"); 314 315 DscResourceInfoInternal? nullResource = null; 316 DscResourceInfoInternal dscResourceInfo = new DscResourceInfoInternal(resourceName, moduleName, version); 317 var processorEnvMock = new Mock<IProcessorEnvironment>(); 318 processorEnvMock.Setup( 319 m => m.GetDscResource(It.Is<ConfigurationUnitAndModule>(c => c.Unit.Type == resourceName))) 320 .Returns(nullResource); 321 322 PSObject findDscResourceResult = new PSObject(processorEnvMock); 323 processorEnvMock.Setup( 324 m => m.FindModule(It.Is<ConfigurationUnitAndModule>(c => c.Unit.Type == resourceName))) 325 .Returns(findDscResourceResult) 326 .Verifiable(); 327 328 processorEnvMock.Setup( 329 m => m.InstallModule(findDscResourceResult)) 330 .Verifiable(); 331 332 var configurationSetProcessor = new PowerShellConfigurationSetProcessor( 333 processorEnvMock.Object, 334 new ConfigurationSet()); 335 336 var unit = new ConfigurationUnit 337 { 338 Type = resourceName, 339 }; 340 unit.Metadata.Add("module", moduleName); 341 unit.Metadata.Add("version", version.ToString()); 342 343 Assert.Throws<InstallDscResourceException>( 344 () => configurationSetProcessor.CreateUnitProcessor(unit)); 345 346 processorEnvMock.Verify(); 347 } 348 349 /// <summary> 350 /// Tests Creating a unit processor by downloading the resource. 351 /// </summary> 352 [Fact] 353 public void CreateUnitProcessor_InstallResource_NotFound() 354 { 355 string resourceName = "xResourceName"; 356 string moduleName = "xModuleName"; 357 Version version = new Version("1.0"); 358 359 DscResourceInfoInternal? nullResource = null; 360 DscResourceInfoInternal dscResourceInfo = new DscResourceInfoInternal(resourceName, moduleName, version); 361 var processorEnvMock = new Mock<IProcessorEnvironment>(); 362 processorEnvMock.Setup( 363 m => m.GetDscResource(It.Is<ConfigurationUnitAndModule>(c => c.Unit.Type == resourceName))) 364 .Returns(nullResource); 365 366 PSObject? findDscResourceResult = null; 367 processorEnvMock.Setup( 368 m => m.FindModule(It.Is<ConfigurationUnitAndModule>(c => c.Unit.Type == resourceName))) 369 .Returns(findDscResourceResult) 370 .Verifiable(); 371 372 var configurationSetProcessor = new PowerShellConfigurationSetProcessor( 373 processorEnvMock.Object, 374 new ConfigurationSet()); 375 376 var unit = new ConfigurationUnit 377 { 378 Type = resourceName, 379 }; 380 unit.Metadata.Add("module", moduleName); 381 unit.Metadata.Add("version", version.ToString()); 382 383 Assert.Throws<FindDscResourceNotFoundException>( 384 () => configurationSetProcessor.CreateUnitProcessor(unit)); 385 386 processorEnvMock.Verify(); 387 } 388 389 /// <summary> 390 /// Test GetUnitProcessorDetails Local Resource not found. 391 /// </summary> 392 [Fact] 393 public void GetUnitProcessorDetails_Local_NoFound() 394 { 395 string resourceName = "xResource"; 396 DscResourceInfoInternal? nullDscInfoInternal = null; 397 398 var processorEnvMock = new Mock<IProcessorEnvironment>(); 399 processorEnvMock.Setup( 400 m => m.GetDscResource(It.Is<ConfigurationUnitAndModule>(u => u.Unit.Type == resourceName))) 401 .Returns(nullDscInfoInternal) 402 .Verifiable(); 403 404 var configurationSetProcessor = new PowerShellConfigurationSetProcessor( 405 processorEnvMock.Object, 406 new ConfigurationSet()); 407 408 var unit = new ConfigurationUnit() 409 { 410 Type = resourceName, 411 }; 412 413 var configurationUnitProcessorDetails = configurationSetProcessor.GetUnitProcessorDetails( 414 unit, 415 ConfigurationUnitDetailFlags.Local); 416 417 Assert.Null(configurationUnitProcessorDetails); 418 419 processorEnvMock.Verify(); 420 } 421 422 /// <summary> 423 /// Test GetUnitProcessorDetails Local Found. Module not installed by PowerShellGet. 424 /// </summary> 425 [Fact] 426 public void GetUnitProcessorDetails_Local_NotInstalledByPowerShellGet() 427 { 428 var unit = this.CreateConfigurationUnit(); 429 var (dscResourceInfo, psModuleInfo) = this.GetResourceAndModuleInfo(unit); 430 PSObject? nullPsModuleInfo = null; 431 432 var processorEnvMock = new Mock<IProcessorEnvironment>(); 433 processorEnvMock.Setup( 434 m => m.GetDscResource(It.Is<ConfigurationUnitAndModule>(u => u.Unit.Type == dscResourceInfo.Name))) 435 .Returns(dscResourceInfo) 436 .Verifiable(); 437 processorEnvMock.Setup( 438 m => m.GetAvailableModule(It.Is<ModuleSpecification>(s => s.Name == dscResourceInfo.ModuleName))) 439 .Returns(psModuleInfo) 440 .Verifiable(); 441 processorEnvMock.Setup( 442 m => m.GetInstalledModule(It.Is<ModuleSpecification>(s => s.Name == dscResourceInfo.ModuleName))) 443 .Returns(nullPsModuleInfo) 444 .Verifiable(); 445 processorEnvMock.Setup( 446 m => m.GetCertsOfValidSignedFiles(It.IsAny<string[]>())) 447 .Returns(new List<Certificate>()) 448 .Verifiable(); 449 450 var configurationSetProcessor = new PowerShellConfigurationSetProcessor( 451 processorEnvMock.Object, 452 new ConfigurationSet()); 453 454 var configurationUnitProcessorDetails = configurationSetProcessor.GetUnitProcessorDetails( 455 unit, 456 ConfigurationUnitDetailFlags.Local); 457 458 Assert.NotNull(configurationUnitProcessorDetails); 459 Assert.Equal(dscResourceInfo.Name, configurationUnitProcessorDetails.UnitType); 460 461 processorEnvMock.Verify(); 462 } 463 464 /// <summary> 465 /// Test GetUnitProcessorDetails locally found. Do not include Load. 466 /// </summary> 467 /// <param name="detailFlags">Detail flags.</param> 468 [Theory] 469 [InlineData(ConfigurationUnitDetailFlags.Local)] 470 [InlineData(ConfigurationUnitDetailFlags.ReadOnly)] 471 [InlineData(ConfigurationUnitDetailFlags.Download)] 472 public void GetUnitProcessorDetails_Local(object detailFlags) 473 { 474 var unit = this.CreateConfigurationUnit(); 475 var (dscResourceInfo, psModuleInfo) = this.GetResourceAndModuleInfo(unit); 476 var getModuleInfo = this.CreateGetModuleInfo(); 477 478 var processorEnvMock = new Mock<IProcessorEnvironment>(); 479 processorEnvMock.Setup( 480 m => m.GetDscResource(It.Is<ConfigurationUnitAndModule>(u => u.Unit.Type == dscResourceInfo.Name))) 481 .Returns(dscResourceInfo) 482 .Verifiable(); 483 processorEnvMock.Setup( 484 m => m.GetAvailableModule(It.Is<ModuleSpecification>(s => s.Name == dscResourceInfo.ModuleName))) 485 .Returns(psModuleInfo) 486 .Verifiable(); 487 processorEnvMock.Setup( 488 m => m.GetInstalledModule(It.Is<ModuleSpecification>(s => s.Name == dscResourceInfo.ModuleName))) 489 .Returns(getModuleInfo) 490 .Verifiable(); 491 processorEnvMock.Setup( 492 m => m.GetCertsOfValidSignedFiles(It.IsAny<string[]>())) 493 .Returns(new List<Certificate>()) 494 .Verifiable(); 495 496 var configurationSetProcessor = new PowerShellConfigurationSetProcessor( 497 processorEnvMock.Object, 498 new ConfigurationSet()); 499 500 var configurationUnitProcessorDetails = configurationSetProcessor.GetUnitProcessorDetails( 501 unit, 502 Assert.IsType<ConfigurationUnitDetailFlags>(detailFlags)); 503 504 Assert.NotNull(configurationUnitProcessorDetails); 505 Assert.Equal(dscResourceInfo.Name, configurationUnitProcessorDetails.UnitType); 506 507 processorEnvMock.Verify(); 508 processorEnvMock.Verify(m => m.FindDscResource(It.IsAny<ConfigurationUnitAndModule>()), Times.Never()); 509 processorEnvMock.Verify(m => m.ImportModule(It.IsAny<ModuleSpecification>()), Times.Never()); 510 } 511 512 /// <summary> 513 /// Test GetUnitProcessorDetails locally found and load. 514 /// </summary> 515 [Fact] 516 public void GetUnitProcessorDetails_Local_Load() 517 { 518 var unit = this.CreateConfigurationUnit(); 519 var (dscResourceInfo, psModuleInfo) = this.GetResourceAndModuleInfo(unit); 520 var getModuleInfo = this.CreateGetModuleInfo(); 521 522 var processorEnvMock = new Mock<IProcessorEnvironment>(); 523 processorEnvMock.Setup( 524 m => m.GetDscResource(It.Is<ConfigurationUnitAndModule>(u => u.Unit.Type == dscResourceInfo.Name))) 525 .Returns(dscResourceInfo) 526 .Verifiable(); 527 processorEnvMock.Setup( 528 m => m.GetAvailableModule(It.Is<ModuleSpecification>(s => s.Name == dscResourceInfo.ModuleName))) 529 .Returns(psModuleInfo) 530 .Verifiable(); 531 processorEnvMock.Setup( 532 m => m.GetInstalledModule(It.Is<ModuleSpecification>(s => s.Name == dscResourceInfo.ModuleName))) 533 .Returns(getModuleInfo) 534 .Verifiable(); 535 processorEnvMock.Setup( 536 m => m.ImportModule(It.Is<ModuleSpecification>(s => s.Name == dscResourceInfo.ModuleName))) 537 .Verifiable(); 538 processorEnvMock.Setup( 539 m => m.GetCertsOfValidSignedFiles(It.IsAny<string[]>())) 540 .Returns(new List<Certificate>()) 541 .Verifiable(); 542 543 var configurationSetProcessor = new PowerShellConfigurationSetProcessor( 544 processorEnvMock.Object, 545 new ConfigurationSet()); 546 547 var configurationUnitProcessorDetails = configurationSetProcessor.GetUnitProcessorDetails( 548 unit, 549 ConfigurationUnitDetailFlags.Load); 550 551 Assert.NotNull(configurationUnitProcessorDetails); 552 Assert.Equal(dscResourceInfo.Name, configurationUnitProcessorDetails.UnitType); 553 554 processorEnvMock.Verify(); 555 processorEnvMock.Verify(m => m.FindDscResource(It.IsAny<ConfigurationUnitAndModule>()), Times.Never()); 556 } 557 558 /// <summary> 559 /// Test GetUnitProcessorDetails Catalog Not Found. 560 /// </summary> 561 [Fact] 562 public void GetUnitProcessorDetails_Catalog_NotFound() 563 { 564 var unit = this.CreateConfigurationUnit(); 565 DscResourceInfoInternal? nullDscResourceInfo = null; 566 PSObject? nullPsModuleInfo = null; 567 568 var processorEnvMock = new Mock<IProcessorEnvironment>(); 569 processorEnvMock.Setup( 570 m => m.GetDscResource(It.Is<ConfigurationUnitAndModule>(u => u.Unit.Type == unit.Type))) 571 .Returns(nullDscResourceInfo) 572 .Verifiable(); 573 processorEnvMock.Setup( 574 m => m.FindModule(It.Is<ConfigurationUnitAndModule>(c => unit.Type == unit.Type))) 575 .Returns(nullPsModuleInfo) 576 .Verifiable(); 577 578 var configurationSetProcessor = new PowerShellConfigurationSetProcessor( 579 processorEnvMock.Object, 580 new ConfigurationSet()); 581 582 var configurationUnitProcessorDetails = configurationSetProcessor.GetUnitProcessorDetails( 583 unit, 584 ConfigurationUnitDetailFlags.ReadOnly); 585 586 Assert.Null(configurationUnitProcessorDetails); 587 588 processorEnvMock.Verify(); 589 } 590 591 /// <summary> 592 /// Test GetUnitProcessorDetails Catalog Found. 593 /// </summary> 594 [Fact] 595 public void GetUnitProcessorDetails_Catalog() 596 { 597 var unit = this.CreateConfigurationUnit(); 598 DscResourceInfoInternal? nullDscResourceInfo = null; 599 var getFindResourceInfo = this.CreateFindResourceInfo(); 600 601 var processorEnvMock = new Mock<IProcessorEnvironment>(); 602 processorEnvMock.Setup( 603 m => m.GetDscResource(It.Is<ConfigurationUnitAndModule>(u => u.Unit.Type == unit.Type))) 604 .Returns(nullDscResourceInfo) 605 .Verifiable(); 606 processorEnvMock.Setup( 607 m => m.FindModule(It.Is<ConfigurationUnitAndModule>(c => unit.Type == unit.Type))) 608 .Returns(getFindResourceInfo) 609 .Verifiable(); 610 611 var configurationSetProcessor = new PowerShellConfigurationSetProcessor( 612 processorEnvMock.Object, 613 new ConfigurationSet()); 614 615 var configurationUnitProcessorDetails = configurationSetProcessor.GetUnitProcessorDetails( 616 unit, 617 ConfigurationUnitDetailFlags.ReadOnly); 618 619 Assert.NotNull(configurationUnitProcessorDetails); 620 Assert.Equal("SimpleFileResource", configurationUnitProcessorDetails.UnitType); 621 622 processorEnvMock.Verify(); 623 } 624 625 /// <summary> 626 /// Test GetUnitProcessorDetails downloading module. 627 /// </summary> 628 [Fact] 629 public void GetUnitProcessorDetails_Download() 630 { 631 var unit = this.CreateConfigurationUnit(); 632 DscResourceInfoInternal? nullDscResourceInfo = null; 633 var (_, psModuleInfo) = this.GetResourceAndModuleInfo(unit); 634 var getFindModuleInfo = this.CreateGetModuleInfo(); 635 636 var processorEnvMock = new Mock<IProcessorEnvironment>(); 637 processorEnvMock.Setup( 638 m => m.GetDscResource(It.Is<ConfigurationUnitAndModule>(u => u.Unit.Type == unit.Type))) 639 .Returns(nullDscResourceInfo) 640 .Verifiable(); 641 processorEnvMock.Setup( 642 m => m.FindModule(It.Is<ConfigurationUnitAndModule>(c => unit.Type == unit.Type))) 643 .Returns(getFindModuleInfo) 644 .Verifiable(); 645 processorEnvMock.Setup( 646 m => m.SaveModule(getFindModuleInfo, It.IsAny<string>())) 647 .Verifiable(); 648 processorEnvMock.Setup( 649 m => m.GetAvailableModule(It.Is<string>(s => s.EndsWith("xSimpleTestResource")))) 650 .Returns(psModuleInfo) 651 .Verifiable(); 652 processorEnvMock.Setup( 653 m => m.GetCertsOfValidSignedFiles(It.IsAny<string[]>())) 654 .Returns(new List<Certificate>()) 655 .Verifiable(); 656 657 var configurationSetProcessor = new PowerShellConfigurationSetProcessor( 658 processorEnvMock.Object, 659 new ConfigurationSet()); 660 661 var configurationUnitProcessorDetails = configurationSetProcessor.GetUnitProcessorDetails( 662 unit, 663 ConfigurationUnitDetailFlags.Download); 664 665 Assert.NotNull(configurationUnitProcessorDetails); 666 Assert.Equal("SimpleFileResource", configurationUnitProcessorDetails.UnitType); 667 668 processorEnvMock.Verify(); 669 670 processorEnvMock.Verify(m => m.InstallModule(It.IsAny<PSObject>()), Times.Never()); 671 } 672 673 /// <summary> 674 /// Tests GetUnitProcessorDetails install module, but resource not found anyway. 675 /// </summary> 676 [Fact] 677 public void GetUnitProcessorDetails_Load_NotFoundAfterInstall() 678 { 679 var unit = this.CreateConfigurationUnit(); 680 DscResourceInfoInternal? nullDscResourceInfo = null; 681 var (_, psModuleInfo) = this.GetResourceAndModuleInfo(unit); 682 var getFindResourceInfo = this.CreateFindResourceInfo(); 683 684 var processorEnvMock = new Mock<IProcessorEnvironment>(); 685 processorEnvMock.Setup( 686 m => m.GetDscResource(It.Is<ConfigurationUnitAndModule>(u => u.Unit.Type == unit.Type))) 687 .Returns(nullDscResourceInfo) 688 .Verifiable(); 689 processorEnvMock.Setup( 690 m => m.FindModule(It.Is<ConfigurationUnitAndModule>(c => unit.Type == unit.Type))) 691 .Returns(getFindResourceInfo) 692 .Verifiable(); 693 processorEnvMock.Setup( 694 m => m.InstallModule(getFindResourceInfo)) 695 .Verifiable(); 696 697 var configurationSetProcessor = new PowerShellConfigurationSetProcessor( 698 processorEnvMock.Object, 699 new ConfigurationSet()); 700 701 Assert.Throws<InstallDscResourceException>(() => configurationSetProcessor.GetUnitProcessorDetails( 702 unit, 703 ConfigurationUnitDetailFlags.Load)); 704 705 processorEnvMock.Verify(); 706 processorEnvMock.Verify( 707 m => m.GetDscResource(It.Is<ConfigurationUnitAndModule>(u => u.Unit.Type == unit.Type)), 708 Times.Exactly(2)); 709 } 710 711 /// <summary> 712 /// Tests GetUnitProcessorDetails install module. 713 /// </summary> 714 [Fact] 715 public void GetUnitProcessorDetails_Load() 716 { 717 var unit = this.CreateConfigurationUnit(); 718 DscResourceInfoInternal? nullDscResourceInfo = null; 719 var (dscResourceInfo, psModuleInfo) = this.GetResourceAndModuleInfo(unit); 720 var getFindResourceInfo = this.CreateFindResourceInfo(); 721 722 var processorEnvMock = new Mock<IProcessorEnvironment>(); 723 processorEnvMock.SetupSequence( 724 m => m.GetDscResource(It.Is<ConfigurationUnitAndModule>(u => u.Unit.Type == unit.Type))) 725 .Returns(nullDscResourceInfo) 726 .Returns(dscResourceInfo); 727 processorEnvMock.Setup( 728 m => m.FindModule(It.Is<ConfigurationUnitAndModule>(c => unit.Type == unit.Type))) 729 .Returns(getFindResourceInfo) 730 .Verifiable(); 731 processorEnvMock.Setup( 732 m => m.InstallModule(getFindResourceInfo)) 733 .Verifiable(); 734 processorEnvMock.Setup( 735 m => m.GetInstalledModule(It.Is<ModuleSpecification>(s => s.Name == dscResourceInfo.ModuleName))) 736 .Returns(getFindResourceInfo) 737 .Verifiable(); 738 processorEnvMock.Setup( 739 m => m.ImportModule(It.Is<ModuleSpecification>(s => s.Name == dscResourceInfo.ModuleName))) 740 .Verifiable(); 741 742 var configurationSetProcessor = new PowerShellConfigurationSetProcessor( 743 processorEnvMock.Object, 744 new ConfigurationSet()); 745 746 var configurationUnitProcessorDetails = configurationSetProcessor.GetUnitProcessorDetails( 747 unit, 748 ConfigurationUnitDetailFlags.Load); 749 750 Assert.NotNull(configurationUnitProcessorDetails); 751 Assert.Equal(dscResourceInfo.Name, configurationUnitProcessorDetails.UnitType); 752 753 processorEnvMock.Verify(); 754 processorEnvMock.Verify( 755 m => m.GetDscResource(It.Is<ConfigurationUnitAndModule>(u => u.Unit.Type == unit.Type)), 756 Times.Exactly(2)); 757 } 758 759 /// <summary> 760 /// This tests uses SimpleTestResourceTypes Test to validate the resource got the correct types 761 /// from the processor. 762 /// </summary> 763 [Fact] 764 public void CreateUnitProcessor_TestTypes() 765 { 766 var processorEnv = this.fixture.PrepareTestProcessorEnvironment(); 767 768 var setProcessor = new PowerShellConfigurationSetProcessor(processorEnv, new ConfigurationSet()); 769 770 var unit = new ConfigurationUnit 771 { 772 Type = "SimpleTestResourceTypes", 773 Intent = ConfigurationUnitIntent.Assert, 774 }; 775 776 unit.Metadata.Add("module", "xSimpleTestResource"); 777 unit.Metadata.Add("version", "0.0.0.1"); 778 779 var hashtableProperty = new ValueSet 780 { 781 { "secretStringKey", "secretCode" }, 782 { "secretIntKey", "123456" }, 783 }; 784 785 unit.Settings.Add("boolProperty", true); 786 unit.Settings.Add("intProperty", 3); 787 unit.Settings.Add("doubleProperty", -9.876); 788 unit.Settings.Add("charProperty", 'f'); 789 unit.Settings.Add("hashtableProperty", hashtableProperty); 790 791 var unitProcessor = setProcessor.CreateUnitProcessor(unit); 792 793 unitProcessor.TestSettings(); 794 } 795 796 /// <summary> 797 /// Tests a module that requires admin is loaded from non admin. 798 /// </summary> 799 [FactSkipIfCI] 800 public void CreateUnitProcessor_ModuleRequiresAdmin() 801 { 802 var processorEnv = this.fixture.PrepareTestProcessorEnvironment(); 803 804 var setProcessor = new PowerShellConfigurationSetProcessor(processorEnv, new ConfigurationSet()); 805 806 var unit = new ConfigurationUnit 807 { 808 Type = "AdminResource", 809 Intent = ConfigurationUnitIntent.Assert, 810 }; 811 unit.Metadata.Add("module", "xAdminTestResource"); 812 unit.Metadata.Add("version", "0.0.0.1"); 813 814 unit.Settings.Add("key", "key"); 815 816 var importModuleException = Assert.Throws<ImportModuleException>(() => setProcessor.CreateUnitProcessor(unit)); 817 Assert.Equal(ErrorCodes.WinGetConfigUnitImportModuleAdmin, importModuleException.HResult); 818 } 819 820 /// <summary> 821 /// Test CreateUnitProcessor. Limit mode. 822 /// </summary> 823 [Fact] 824 public void CreateUnitProcessor_LimitMode() 825 { 826 string resourceName = "xResourceName"; 827 string moduleName = "xModuleName"; 828 Version version = new Version("1.0"); 829 830 var processorEnvMock = new Mock<IProcessorEnvironment>(); 831 processorEnvMock.Setup( 832 m => m.GetDscResource(It.Is<ConfigurationUnitAndModule>(c => c.Unit.Type == resourceName))) 833 .Returns(new DscResourceInfoInternal(resourceName, moduleName, version)) 834 .Verifiable(); 835 836 var limitSet = new ConfigurationSet(); 837 var limitUnit = new ConfigurationUnit 838 { 839 Type = resourceName, 840 Intent = ConfigurationUnitIntent.Apply, 841 }; 842 limitUnit.Metadata.Add("module", moduleName); 843 limitUnit.Metadata.Add("version", version.ToString()); 844 limitSet.Units = new List<ConfigurationUnit> { limitUnit }; 845 846 var configurationSetProcessor = new PowerShellConfigurationSetProcessor( 847 processorEnvMock.Object, 848 limitSet, 849 true); 850 851 // Calling with unit different from limit set should throw. 852 var unitDifferentContent = new ConfigurationUnit 853 { 854 Type = "differentResourceName", 855 Intent = ConfigurationUnitIntent.Apply, 856 }; 857 858 Assert.Throws<System.InvalidOperationException>(() => configurationSetProcessor.CreateUnitProcessor(unitDifferentContent)); 859 Assert.Throws<System.InvalidOperationException>(() => configurationSetProcessor.GetUnitProcessorDetails(unitDifferentContent, ConfigurationUnitDetailFlags.Load)); 860 861 // Calling with unit matching limit set. 862 var unitProcessor = configurationSetProcessor.CreateUnitProcessor(limitUnit); 863 Assert.NotNull(unitProcessor); 864 Assert.Equal(limitUnit.Type, unitProcessor.Unit.Type); 865 var processorDetails = configurationSetProcessor.GetUnitProcessorDetails(limitUnit, ConfigurationUnitDetailFlags.Load); 866 Assert.NotNull(processorDetails); 867 Assert.Equal(moduleName, processorDetails.ModuleName); 868 869 // Calling CreateProcessor again should thow. Calling GetProcessorDetails multiple times is ok. 870 Assert.Throws<System.InvalidOperationException>(() => configurationSetProcessor.CreateUnitProcessor(limitUnit)); 871 var processorDetails2 = configurationSetProcessor.GetUnitProcessorDetails(limitUnit, ConfigurationUnitDetailFlags.Load); 872 Assert.NotNull(processorDetails2); 873 Assert.Equal(moduleName, processorDetails2.ModuleName); 874 } 875 876 /// <summary> 877 /// Test CreateUnitProcessor. Limit mode. Duplicate units in limit set. 878 /// </summary> 879 [Fact] 880 public void CreateUnitProcessor_LimitMode_DuplicateUnits() 881 { 882 string resourceName = "xResourceName"; 883 string moduleName = "xModuleName"; 884 Version version = new Version("1.0"); 885 886 var processorEnvMock = new Mock<IProcessorEnvironment>(); 887 processorEnvMock.Setup( 888 m => m.GetDscResource(It.Is<ConfigurationUnitAndModule>(c => c.Unit.Type == resourceName))) 889 .Returns(new DscResourceInfoInternal(resourceName, moduleName, version)) 890 .Verifiable(); 891 892 var limitSet = new ConfigurationSet(); 893 var limitUnit = new ConfigurationUnit 894 { 895 Type = resourceName, 896 Intent = ConfigurationUnitIntent.Apply, 897 }; 898 limitUnit.Metadata.Add("module", moduleName); 899 limitUnit.Metadata.Add("version", version.ToString()); 900 limitSet.Units = new List<ConfigurationUnit> { limitUnit, limitUnit }; 901 902 var configurationSetProcessor = new PowerShellConfigurationSetProcessor( 903 processorEnvMock.Object, 904 limitSet, 905 true); 906 907 // Calling with unit different from limit set should throw. 908 var unitDifferentContent = new ConfigurationUnit 909 { 910 Type = "differentResourceName", 911 Intent = ConfigurationUnitIntent.Apply, 912 }; 913 914 Assert.Throws<System.InvalidOperationException>(() => configurationSetProcessor.CreateUnitProcessor(unitDifferentContent)); 915 916 // Calling with unit matching limit set. 917 var unitProcessor = configurationSetProcessor.CreateUnitProcessor(limitUnit); 918 Assert.NotNull(unitProcessor); 919 Assert.Equal(limitUnit.Type, unitProcessor.Unit.Type); 920 921 // Calling again should also not thow. 922 var unitProcessor2 = configurationSetProcessor.CreateUnitProcessor(limitUnit); 923 Assert.NotNull(unitProcessor2); 924 Assert.Equal(limitUnit.Type, unitProcessor2.Unit.Type); 925 926 // Calling third time should throw. 927 Assert.Throws<System.InvalidOperationException>(() => configurationSetProcessor.CreateUnitProcessor(limitUnit)); 928 } 929 930 private ConfigurationUnit CreateConfigurationUnit() 931 { 932 var unit = new ConfigurationUnit(); 933 unit.Type = "SimpleFileResource"; 934 unit.Metadata.Add("module", "xSimpleTestResource"); 935 unit.Metadata.Add("version", "0.0.0.1"); 936 937 return unit; 938 } 939 940 private (DscResourceInfoInternal dscResourceInfo, PSModuleInfo psModuleInfo) GetResourceAndModuleInfo(ConfigurationUnit unit) 941 { 942 // This is easier than trying to mock sealed class from external code... 943 var testEnv = this.fixture.PrepareTestProcessorEnvironment(true); 944 var dscResourceInfo = testEnv.GetDscResource(new ConfigurationUnitAndModule(unit, string.Empty)); 945 var psModuleInfo = testEnv.GetAvailableModule(PowerShellHelpers.CreateModuleSpecification("xSimpleTestResource", "0.0.0.1")); 946 947 if (dscResourceInfo is null || psModuleInfo is null) 948 { 949 throw new ArgumentNullException("Test processor environment not set correctly"); 950 } 951 952 return (dscResourceInfo, psModuleInfo); 953 } 954 955 private PSObject CreateGetModuleInfo() 956 { 957 return new PSObject(new 958 { 959 Repository = "PSGallery", 960 PublishedDate = new DateTime(2017, 12, 10), 961 IconUri = "https://github.com/microsoft/winget-cli", 962 Name = "xSimpleTestResource", 963 Description = "PowerShell module with DSC resources for unit tests", 964 RepositorySourceLocation = "https://github.com/microsoft/winget-cli", 965 Version = "0.0.0.1", 966 Author = "Luffytaro", 967 CompanyName = "Microsoft Corporation", 968 }); 969 } 970 971 private PSObject CreateFindResourceInfo() 972 { 973 var getModuleInfo = this.CreateGetModuleInfo(); 974 return new PSObject(new 975 { 976 Name = "SimpleFileResource", 977 ModuleName = "xSimpleTestResource", 978 Version = "0.0.0.1", 979 PSGetModuleInfo = getModuleInfo, 980 }); 981 } 982 } 983 }