From 9ecbc52379b579fc526507e098826f3e64188b43 Mon Sep 17 00:00:00 2001 From: Ruben Guerrero Date: Mon, 18 Sep 2023 11:44:46 -0700 Subject: [PATCH] Make DSC resource name check case insentive (#3632) Make resource name check case insensitive. Add tests Address #3628 --- .github/actions/spelling/expect.txt | 1 + .../ConfigureCommand.cs | 17 +++++ .../Configuration/ResourceCaseInsensitive.yml | 9 +++ .../Helpers/ConfigurationUnitAndResource.cs | 2 +- .../Tests/ConfigurationSetProcessorTests.cs | 66 +++++++++++++++++++ .../Microsoft.WinGet.Configuration.Tests.ps1 | 49 +++++++++++--- 6 files changed, 134 insertions(+), 10 deletions(-) create mode 100644 src/AppInstallerCLIE2ETests/TestData/Configuration/ResourceCaseInsensitive.yml diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt index 7017582937..e96d89bc3c 100644 --- a/.github/actions/spelling/expect.txt +++ b/.github/actions/spelling/expect.txt @@ -122,6 +122,7 @@ ecfrbrowse ECustom EFGH EFile +efileresource endregion ENDSESSION EPester diff --git a/src/AppInstallerCLIE2ETests/ConfigureCommand.cs b/src/AppInstallerCLIE2ETests/ConfigureCommand.cs index 5b4fa2cc55..7153e511fb 100644 --- a/src/AppInstallerCLIE2ETests/ConfigureCommand.cs +++ b/src/AppInstallerCLIE2ETests/ConfigureCommand.cs @@ -154,6 +154,23 @@ public void ConfigServerUnexpectedExit() FileAssert.DoesNotExist(targetFilePath); } + /// + /// Resource name case insensitive test. + /// + [Test] + public void ResourceCaseInsensitive() + { + TestCommon.EnsureModuleState(Constants.SimpleTestModuleName, present: false); + + var result = TestCommon.RunAICLICommand(CommandAndAgreementsAndVerbose, TestCommon.GetTestDataFile("Configuration\\ResourceCaseInsensitive.yml")); + Assert.AreEqual(0, result.ExitCode); + + // The configuration creates a file next to itself with the given contents + string targetFilePath = TestCommon.GetTestDataFile("Configuration\\ResourceCaseInsensitive.txt"); + FileAssert.Exists(targetFilePath); + Assert.AreEqual("Contents!", System.IO.File.ReadAllText(targetFilePath)); + } + private void DeleteTxtFiles() { // Delete all .txt files in the test directory; they are placed there by the tests diff --git a/src/AppInstallerCLIE2ETests/TestData/Configuration/ResourceCaseInsensitive.yml b/src/AppInstallerCLIE2ETests/TestData/Configuration/ResourceCaseInsensitive.yml new file mode 100644 index 0000000000..32cec1bade --- /dev/null +++ b/src/AppInstallerCLIE2ETests/TestData/Configuration/ResourceCaseInsensitive.yml @@ -0,0 +1,9 @@ +properties: + configurationVersion: 0.2 + resources: + - resource: xE2ETestResource/e2efileresource + directives: + repository: AppInstallerCLIE2ETestsRepo + settings: + Path: ${WinGetConfigRoot}\ResourceCaseInsensitive.txt + Content: Contents! diff --git a/src/Microsoft.Management.Configuration.Processor/Helpers/ConfigurationUnitAndResource.cs b/src/Microsoft.Management.Configuration.Processor/Helpers/ConfigurationUnitAndResource.cs index 25d311fa5d..c690e7ddae 100644 --- a/src/Microsoft.Management.Configuration.Processor/Helpers/ConfigurationUnitAndResource.cs +++ b/src/Microsoft.Management.Configuration.Processor/Helpers/ConfigurationUnitAndResource.cs @@ -29,7 +29,7 @@ public ConfigurationUnitAndResource( ConfigurationUnitInternal configurationUnitInternal, DscResourceInfoInternal dscResourceInfoInternal) { - if (configurationUnitInternal.Unit.Type != dscResourceInfoInternal.Name) + if (!configurationUnitInternal.Unit.Type.Equals(dscResourceInfoInternal.Name, StringComparison.OrdinalIgnoreCase)) { throw new ArgumentException(); } diff --git a/src/Microsoft.Management.Configuration.UnitTests/Tests/ConfigurationSetProcessorTests.cs b/src/Microsoft.Management.Configuration.UnitTests/Tests/ConfigurationSetProcessorTests.cs index f4b30655bc..c2f62d4192 100644 --- a/src/Microsoft.Management.Configuration.UnitTests/Tests/ConfigurationSetProcessorTests.cs +++ b/src/Microsoft.Management.Configuration.UnitTests/Tests/ConfigurationSetProcessorTests.cs @@ -78,6 +78,72 @@ public void CreateUnitProcessor_ResourceExists() processorEnvMock.Verify(); } + /// + /// Test CreateUnitProcessor case insensitive. + /// + [Fact] + public void CreateUnitProcessor_CaseInsensitive() + { + string resourceName = "name"; + string moduleName = "xModuleName"; + Version version = new Version("1.0"); + + var processorEnvMock = new Mock(); + processorEnvMock.Setup( + m => m.GetDscResource(It.Is(c => c.Unit.Type.Equals("Name", StringComparison.OrdinalIgnoreCase)))) + .Returns(new DscResourceInfoInternal("Name", moduleName, version)) + .Verifiable(); + + var configurationSetProcessor = new ConfigurationSetProcessor( + processorEnvMock.Object, + new ConfigurationSet()); + + var unit = new ConfigurationUnit + { + Type = resourceName, + }; + unit.Metadata.Add("module", moduleName); + unit.Metadata.Add("version", version.ToString()); + + var unitProcessor = configurationSetProcessor.CreateUnitProcessor(unit); + Assert.NotNull(unitProcessor); + Assert.Equal(unit.Type, unitProcessor.Unit.Type); + + processorEnvMock.Verify(); + } + + /// + /// Test CreateUnitProcessor case insensitive. + /// + [Fact] + public void CreateUnitProcessor_ResourceNameMismatch() + { + string resourceName = "name"; + string moduleName = "xModuleName"; + Version version = new Version("1.0"); + + var processorEnvMock = new Mock(); + processorEnvMock.Setup( + m => m.GetDscResource(It.Is(c => c.Unit.Type == resourceName))) + .Returns(new DscResourceInfoInternal("OtherName", moduleName, version)) + .Verifiable(); + + var configurationSetProcessor = new ConfigurationSetProcessor( + processorEnvMock.Object, + new ConfigurationSet()); + + var unit = new ConfigurationUnit + { + Type = resourceName, + }; + unit.Metadata.Add("module", moduleName); + unit.Metadata.Add("version", version.ToString()); + + Assert.Throws(() => configurationSetProcessor.CreateUnitProcessor(unit)); + + processorEnvMock.Verify(); + } + /// /// Test CreateUnitProcessor with no version directive. /// diff --git a/src/PowerShell/tests/Microsoft.WinGet.Configuration.Tests.ps1 b/src/PowerShell/tests/Microsoft.WinGet.Configuration.Tests.ps1 index b7f3358366..5f5e6be27c 100644 --- a/src/PowerShell/tests/Microsoft.WinGet.Configuration.Tests.ps1 +++ b/src/PowerShell/tests/Microsoft.WinGet.Configuration.Tests.ps1 @@ -338,7 +338,7 @@ Describe 'Get configuration' { Describe 'Invoke-WinGetConfiguration' { - BeforeAll { + BeforeEach { DeleteConfigTxtFiles } @@ -430,7 +430,6 @@ Describe 'Invoke-WinGetConfiguration' { } It 'Piped' { - DeleteConfigTxtFiles $testFile = GetConfigTestDataFile "Configure_TestRepo.yml" $result = Get-WinGetConfiguration -File $testFile | Invoke-WinGetConfiguration -AcceptConfigurationAgreements $result | Should -Not -BeNullOrEmpty @@ -445,7 +444,6 @@ Describe 'Invoke-WinGetConfiguration' { } It 'Positional' { - DeleteConfigTxtFiles $testFile = GetConfigTestDataFile "Configure_TestRepo.yml" $set = Get-WinGetConfiguration $testFile $set | Should -Not -BeNullOrEmpty @@ -498,11 +496,28 @@ Describe 'Invoke-WinGetConfiguration' { $expectedFile = Join-Path $(GetConfigTestDataPath) "DependentResources_Failure.txt" Test-Path $expectedFile | Should -Be $false } + + It 'ResourceCaseInsensitive' { + $testFile = GetConfigTestDataFile "ResourceCaseInsensitive.yml" + $set = Get-WinGetConfiguration -File $testFile + $set | Should -Not -BeNullOrEmpty + + $result = Invoke-WinGetConfiguration -AcceptConfigurationAgreements -Set $set + $result | Should -Not -BeNullOrEmpty + $result.ResultCode | Should -Be 0 + $result.UnitResults.Count | Should -Be 1 + $result.UnitResults[0].State | Should -Be "Completed" + $result.UnitResults[0].ResultCode | Should -Be 0 + + $expectedFile = Join-Path $(GetConfigTestDataPath) "ResourceCaseInsensitive.txt" + Test-Path $expectedFile | Should -Be $true + Get-Content $expectedFile -Raw | Should -Be "Contents!" + } } Describe 'Start|Complete-WinGetConfiguration' { - BeforeAll { + BeforeEach { DeleteConfigTxtFiles } @@ -525,7 +540,6 @@ Describe 'Start|Complete-WinGetConfiguration' { } It 'From TestRepo' { - DeleteConfigTxtFiles $testFile = GetConfigTestDataFile "Configure_TestRepo.yml" $set = Get-WinGetConfiguration -File $testFile $set | Should -Not -BeNullOrEmpty @@ -680,11 +694,31 @@ Describe 'Start|Complete-WinGetConfiguration' { $expectedFile = Join-Path $(GetConfigTestDataPath) "DependentResources_Failure.txt" Test-Path $expectedFile | Should -Be $false } + + It 'ResourceCaseInsensitive' { + $testFile = GetConfigTestDataFile "ResourceCaseInsensitive.yml" + $set = Get-WinGetConfiguration -File $testFile + $set | Should -Not -BeNullOrEmpty + + $job = Start-WinGetConfiguration -AcceptConfigurationAgreements -Set $set + $job | Should -Not -BeNullOrEmpty + + $result = Complete-WinGetConfiguration -ConfigurationJob $job + $result | Should -Not -BeNullOrEmpty + $result.ResultCode | Should -Be 0 + $result.UnitResults.Count | Should -Be 1 + $result.UnitResults[0].State | Should -Be "Completed" + $result.UnitResults[0].ResultCode | Should -Be 0 + + $expectedFile = Join-Path $(GetConfigTestDataPath) "ResourceCaseInsensitive.txt" + Test-Path $expectedFile | Should -Be $true + Get-Content $expectedFile -Raw | Should -Be "Contents!" + } } Describe 'Test-WinGetConfiguration' { - BeforeAll { + BeforeEach { DeleteConfigTxtFiles } @@ -702,7 +736,6 @@ Describe 'Test-WinGetConfiguration' { } It 'Positive' { - DeleteConfigTxtFiles $testFile = GetConfigTestDataFile "Configure_TestRepo.yml" $set = Get-WinGetConfiguration -File $testFile $set | Should -Not -BeNullOrEmpty @@ -719,7 +752,6 @@ Describe 'Test-WinGetConfiguration' { } It 'Piped' { - DeleteConfigTxtFiles $testFile = GetConfigTestDataFile "Configure_TestRepo.yml" $result = Get-WinGetConfiguration -File $testFile | Test-WinGetConfiguration -AcceptConfigurationAgreements $result | Should -Not -BeNullOrEmpty @@ -730,7 +762,6 @@ Describe 'Test-WinGetConfiguration' { } It 'Positional' { - DeleteConfigTxtFiles $testFile = GetConfigTestDataFile "Configure_TestRepo.yml" $set = Get-WinGetConfiguration $testFile $set | Should -Not -BeNullOrEmpty