diff --git a/src/System.Management.Automation/engine/Modules/ModuleCmdletBase.cs b/src/System.Management.Automation/engine/Modules/ModuleCmdletBase.cs index 576a9a295a..e3c85d9d31 100644 --- a/src/System.Management.Automation/engine/Modules/ModuleCmdletBase.cs +++ b/src/System.Management.Automation/engine/Modules/ModuleCmdletBase.cs @@ -1338,6 +1338,25 @@ namespace Microsoft.PowerShell.Commands return true; } + /// + /// Helper function to generate fake PSModuleInfo objects from ModuleSpecification objects. + /// + /// Collection of ModuleSpecification objects + /// Collection of fake PSModuleInfo objects + private IEnumerable CreateFakeModuleObject(IEnumerable moduleSpecs) + { + foreach (ModuleSpecification moduleSpec in moduleSpecs) + { + var fakeModuleInfo = new PSModuleInfo(moduleSpec.Name, Context, null); + if (moduleSpec.Guid.HasValue) + { + fakeModuleInfo.SetGuid(moduleSpec.Guid.Value); + } + fakeModuleInfo.SetVersion(moduleSpec.RequiredVersion ?? moduleSpec.Version); + yield return fakeModuleInfo; + } + } + private ErrorRecord GetErrorRecordIfUnsupportedRootCdxmlAndNestedModuleScenario( Hashtable data, string moduleManifestPath, @@ -1977,16 +1996,8 @@ namespace Microsoft.PowerShell.Commands } else { - PSModuleInfo fakeRequiredModuleInfo = null; - foreach (ModuleSpecification requiredModule in requiredModules) + foreach (PSModuleInfo fakeRequiredModuleInfo in CreateFakeModuleObject(requiredModules)) { - fakeRequiredModuleInfo = new PSModuleInfo(requiredModule.Name, Context, null); - if (requiredModule.Guid.HasValue) - { - fakeRequiredModuleInfo.SetGuid(requiredModule.Guid.Value); - } - fakeRequiredModuleInfo.SetVersion(requiredModule.RequiredVersion ?? requiredModule.Version); - requiredModulesSpecifiedInModuleManifest.Add(fakeRequiredModuleInfo); } } @@ -2797,6 +2808,12 @@ namespace Microsoft.PowerShell.Commands if (!needToAnalyzeScriptModules) { + // Add nested modules to the manifestInfo when no more analysis needs to be done + foreach (PSModuleInfo fakeNestedModuleInfo in CreateFakeModuleObject(nestedModules)) + { + manifestInfo.AddNestedModule(fakeNestedModuleInfo); + } + return manifestInfo; } } @@ -3428,6 +3445,7 @@ namespace Microsoft.PowerShell.Commands updated.Add(element); } } + ss.Internal.ExportedVariables.Clear(); ss.Internal.ExportedVariables.AddRange(updated); } diff --git a/test/powershell/engine/Module/TestModuleManifest.Tests.ps1 b/test/powershell/engine/Module/TestModuleManifest.Tests.ps1 index bbd0093c6c..350d5504dc 100644 --- a/test/powershell/engine/Module/TestModuleManifest.Tests.ps1 +++ b/test/powershell/engine/Module/TestModuleManifest.Tests.ps1 @@ -2,17 +2,21 @@ # Licensed under the MIT License. Describe "Test-ModuleManifest tests" -tags "CI" { + BeforeEach { + $testModulePath = "testdrive:/module/test.psd1" + New-Item -ItemType Directory -Path testdrive:/module > $null + } + AfterEach { Remove-Item -Recurse -Force -ErrorAction SilentlyContinue testdrive:/module } It "module manifest containing paths with backslashes or forwardslashes are resolved correctly" { - New-Item -ItemType Directory -Path testdrive:/module - New-Item -ItemType Directory -Path testdrive:/module/foo - New-Item -ItemType Directory -Path testdrive:/module/bar - New-Item -ItemType File -Path testdrive:/module/foo/bar.psm1 - New-Item -ItemType File -Path testdrive:/module/bar/foo.psm1 + New-Item -ItemType Directory -Path testdrive:/module/foo > $null + New-Item -ItemType Directory -Path testdrive:/module/bar > $null + New-Item -ItemType File -Path testdrive:/module/foo/bar.psm1 > $null + New-Item -ItemType File -Path testdrive:/module/bar/foo.psm1 > $null $testModulePath = "testdrive:/module/test.psd1" $fileList = "foo\bar.psm1","bar/foo.psm1" @@ -38,10 +42,8 @@ Describe "Test-ModuleManifest tests" -tags "CI" { param ($parameter, $error) - New-Item -ItemType Directory -Path testdrive:/module - New-Item -ItemType Directory -Path testdrive:/module/foo - New-Item -ItemType File -Path testdrive:/module/foo/bar.psm1 - $testModulePath = "testdrive:/module/test.psd1" + New-Item -ItemType Directory -Path testdrive:/module/foo > $null + New-Item -ItemType File -Path testdrive:/module/foo/bar.psm1 > $null $args = @{$parameter = "doesnotexist.psm1"} New-ModuleManifest -Path $testModulePath @args @@ -57,10 +59,7 @@ Describe "Test-ModuleManifest tests" -tags "CI" { param($rootModuleValue) - New-Item -ItemType Directory -Path testdrive:/module - $testModulePath = "testdrive:/module/test.psd1" - - New-Item -ItemType File -Path testdrive:/module/$rootModuleValue + New-Item -ItemType File -Path testdrive:/module/$rootModuleValue > $null New-ModuleManifest -Path $testModulePath -RootModule $rootModuleValue $moduleManifest = Test-ModuleManifest -Path $testModulePath -ErrorAction Stop $moduleManifest | Should -BeOfType System.Management.Automation.PSModuleInfo @@ -74,10 +73,7 @@ Describe "Test-ModuleManifest tests" -tags "CI" { param($rootModuleValue, $error) - New-Item -ItemType Directory -Path testdrive:/module - $testModulePath = "testdrive:/module/test.psd1" - - New-Item -ItemType File -Path testdrive:/module/$rootModuleValue + New-Item -ItemType File -Path testdrive:/module/$rootModuleValue > $null New-ModuleManifest -Path $testModulePath -RootModule $rootModuleValue { Test-ModuleManifest -Path $testModulePath -ErrorAction Stop } | Should -Throw -ErrorId "$error,Microsoft.PowerShell.Commands.TestModuleManifestCommand" } @@ -89,9 +85,6 @@ Describe "Test-ModuleManifest tests" -tags "CI" { param($rootModuleValue) - New-Item -ItemType Directory -Path testdrive:/module - $testModulePath = "testdrive:/module/test.psd1" - New-ModuleManifest -Path $testModulePath -RootModule $rootModuleValue $moduleManifest = Test-ModuleManifest -Path $testModulePath -ErrorAction Stop $moduleManifest | Should -BeOfType System.Management.Automation.PSModuleInfo @@ -104,9 +97,7 @@ Describe "Test-ModuleManifest tests" -tags "CI" { param($rootModuleValue, $error) - $testModulePath = "testdrive:/module/test.psd1" - New-Item -ItemType Directory -Path testdrive:/module - New-Item -ItemType File -Path testdrive:/module/$rootModuleValue + New-Item -ItemType File -Path testdrive:/module/$rootModuleValue > $null New-ModuleManifest -Path $testModulePath -RootModule $rootModuleValue { Test-ModuleManifest -Path $testModulePath -ErrorAction Stop } | Should -Throw -ErrorId "$error,Microsoft.PowerShell.Commands.TestModuleManifestCommand" @@ -118,12 +109,23 @@ Describe "Test-ModuleManifest tests" -tags "CI" { param($rootModuleValue, $error) - $testModulePath = "testdrive:/module/test.psd1" - New-Item -ItemType Directory -Path testdrive:/module - New-ModuleManifest -Path $testModulePath -RootModule $rootModuleValue { Test-ModuleManifest -Path $testModulePath -ErrorAction Stop } | Should -Throw -ErrorId "$error,Microsoft.PowerShell.Commands.TestModuleManifestCommand" } + + It "module manifest containing nested module gets returned: " -TestCases ( + @{variation = "no analysis as all exported with no wildcard"; exportValue = "@()"}, + @{variation = "analysis as exported with wildcard"; exportValue = "*"} + ) { + + param($exportValue) + + New-Item -ItemType File -Path testdrive:/module/Foo.psm1 > $null + New-ModuleManifest -Path $testModulePath -NestedModules "Foo.psm1" -FunctionsToExport $exportValue -CmdletsToExport $exportValue -VariablesToExport $exportValue -AliasesToExport $exportValue + $module = Test-ModuleManifest -Path $testModulePath + $module.NestedModules | Should -HaveCount 1 + $module.NestedModules.Name | Should -BeExactly "Foo" + } } Describe "Tests for circular references in required modules" -tags "CI" { @@ -174,7 +176,7 @@ Describe "Tests for circular references in required modules" -tags "CI" { function TestImportModule([bool]$AddVersion, [bool]$AddGuid, [bool]$AddCircularReference) { $moduleRootPath = Join-Path $TestDrive 'TestModules' - New-Item $moduleRootPath -ItemType Directory -Force + New-Item $moduleRootPath -ItemType Directory -Force > $null Push-Location $moduleRootPath $moduleCount = 6 # this depth was enough to find a bug in cyclic reference detection product code; greater depth will slow tests down diff --git a/test/powershell/engine/Module/UpdateModuleManifest.Tests.ps1 b/test/powershell/engine/Module/UpdateModuleManifest.Tests.ps1 new file mode 100644 index 0000000000..0ac58a92c3 --- /dev/null +++ b/test/powershell/engine/Module/UpdateModuleManifest.Tests.ps1 @@ -0,0 +1,33 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +Describe "Update-ModuleManifest tests" -tags "CI" { + + BeforeEach { + $testModulePath = "testdrive:/module/test.psd1" + New-Item -ItemType Directory -Path testdrive:/module > $null + } + + AfterEach { + Remove-Item -Recurse -Force -ErrorAction SilentlyContinue testdrive:/module + } + + It "Update should not clear out NestedModules: " -TestCases @( + @{ variation = "export with wildcards"; exportValue = "*" }, + @{ variation = "export without wildcards"; exportValue = "@()"} + ) { + param($exportValue) + + New-Item -ItemType File -Path testdrive:/module/foo.psm1 > $null + New-ModuleManifest -Path $testModulePath -NestedModules foo.psm1 -HelpInfoUri http://foo.com -AliasesToExport $exportValue -CmdletsToExport $exportValue -FunctionsToExport $exportValue -VariablesToExport $exportValue -DscResourcesToExport $exportValue + $module = Test-ModuleManifest -Path $testModulePath + $module.HelpInfoUri | Should -BeExactly "http://foo.com/" + $module.NestedModules | Should -HaveCount 1 + $module.NestedModules.Name | Should -BeExactly foo + Update-ModuleManifest -Path $testModulePath -HelpInfoUri https://bar.org + $module = Test-ModuleManifest -Path $testModulePath + $module.HelpInfoUri | Should -BeExactly "https://bar.org/" + $module.NestedModules | Should -HaveCount 1 + $module.NestedModules.Name | Should -BeExactly foo + } +}