8000 Fixed Test-Modulemanifest to normalize paths correctly before validating by SteveL-MSFT · Pull Request #3097 · PowerShell/PowerShell · GitHub
[go: up one dir, main page]

Skip to content

Fixed Test-Modulemanifest to normalize paths correctly before validating #3097

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Mar 1, 2017

Conversation

SteveL-MSFT
Copy link
Member

changed hard coded Windows directory separator and resolved path so the slashes are correct
added test
addresses #2610

changed hard coded Windows directory separator and resolved path so the slashes are correct
added test
"" > testdrive:/module/foo/bar.psm1
"" > testdrive:/module/bar/foo.psm1
New-ModuleManifest -NestedModules foo\bar.psm1,bar/foo.psm1 -RootModule foo\bar.psm1 -RequiredAssemblies foo/bar.psm1,bar\foo.psm1 -Path testdrive:/module/test.psd1
Test-ModuleManifest -Path testdrive:/module/test.psd1 -ErrorAction Stop | Should BeOfType System.Management.Automation.PSModuleInfo
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you want some additional validation on the paths, maybe a Test-Path on the NestedModules, RootModule, and RequiredAssemblies.

There are other module properties that specify files, maybe you should be testing those too - TypesToProcess, FormatsToProcess, ScriptsToProcess, maybe FileList and ModuleList?

I wonder if it's a bad idea to specify RequiredAssemblies without a valid assembly - if that's not already causing problems, I can see it causing problems in the future.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The semantics of test-modulemanifest seems to only verify existence of files and not if they are valid. Rather than verify the files exist and being validated, I'm adding a negative test where test-modulemanifest should fail if any paths don't exist

CmdletProviderContext cmdContext = new CmdletProviderContext(this);
Collection<PathInfo> pathInfos = SessionState.Path.GetResolvedPSPathFromPSPath(path, cmdContext);

foreach (PathInfo pathInfo in pathInfos)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you resolve to multiple files, shouldn't that be an error instead of just ignoring it?

Copy link
Member Author
@SteveL-MSFT SteveL-MSFT Feb 7, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lzybkr Since wildcards are explicitly being checked and not allowed in the module manifest, is a Debug.Assert sufficient?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looking at other code in this file, decided to throw

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Possible downside here is I'm adding blocks that can't be hit

added negative test cases that do file path checks
Copy link
Member Author
@SteveL-MSFT SteveL-MSFT left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lzybkr are you ok with the updated changes?

New-Item -ItemType Directory -Path testdrive:/module/foo
New-Item -ItemType Directory -Path testdrive:/module/bar
"" > testdrive:/module/foo/bar.psm1
"" > testdrive:/module/bar/foo.psm1
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe better use Set-Content ? This is more clearly.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree. Fixed.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Closed.


Test-Path $testModulePath | Should Be $true

Test-ModuleManifest -Path $testModulePath -ErrorAction Stop | Should BeOfType System.Management.Automation.PSModuleInfo
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why we use -ErrorAction Stop ? It is not a "throw" test. Better -ErrorAction SilentlyContinue.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I used ErrorAction Stop here since Test-ModuleManifest writes to the error stream on manifest errors and I thought this was an easy way to ensure no errors being returned. Otherwise I think I'd have to redirect the error stream and check it and I don't think that's providing additional value. I can add a comment to clarify my intent.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clear.
Closed.


New-Item -ItemType Directory -Path testdrive:/module
New-Item -ItemType Directory -Path testdrive:/module/foo
"" > testdrive:/module/foo/bar.psm1
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The same about Set-Content

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Closed.

"RootModule"="Modules_InvalidManifest";
"ScriptsToProcess"="Modules_InvalidManifest"
}
foreach ($parameter in $parametersAndExecptions.Keys) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo "parametersAndExecptions" <- "parametersAndErrors"

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Closed.

}
catch {
$_.FullQulaifiedErrorId | Should Match "$errorId"
}
Copy link
Collaborator
@iSazonov iSazonov Feb 15, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why Should BeOfType System.Management.Automation.PSModuleInfo ? If we expect that Test-ModuleManifest raise an exception in the tests the Should BeOfType will be never run.

I suggest using the excellent function ShouldBeErrorId
(I have already prepared new PR #3161 to move existing tests to this pattern)
The new look of this test:

            { Test-ModuleManifest -Path $testModulePath -ErrorAction Stop } | ShouldBeErrorId $errorId

Only insert:

Import-Module $PSScriptRoot\..\..\Common\Test.Helpers.psm1

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool! will make this change

9E88 Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Closed.

Describe "Test-ModuleManifest tests" -tags "CI" {

AfterEach {
if (Test-Path testdrive:/module) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks as unneeded check: Remove-Item implicitly do the check.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

changed

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Closed.

@SteveL-MSFT
Copy link
Member Author

@iSazonov thanks for the feedback, I'll take care of these after I get back from vacation on 2/21

@lzybkr lzybkr self-assigned this Feb 16, 2017
@iSazonov
Copy link
Collaborator

@SteveL-MSFT I don't see new commit related with your last comments.

… readable

fixed typo in test that exposed issue in cmdlet for validating nestedmodules
@SteveL-MSFT
Copy link
Member Author

@iSazonov took longer than I expected, after I fixed the typo, I found a issue with the cmdlet

@@ -37,22 +38,17 @@ Describe "Test-ModuleManifest tests" -tags "CI" {
"ModuleList"="Modules_InvalidModuleListinModuleManifest";
"TypesToProcess"="Modules_InvalidManifest";
"FormatsToProcess"="Modules_InvalidManifest";
"RootModule"="Modules_InvalidManifest";
#"RootModule"="Modules_InvalidManifest";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe remove it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should be uncommented. Looks like the cmdlets doesn't do any validation of RootModule currently, will need to add that code.

"ScriptsToProcess"="Modules_InvalidManifest"
}
foreach ($parameter in $parametersAndExecptions.Keys) {
foreach ($parameter in $parametersAndErrors.Keys) {
Write-Warning "Testing $parameter"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what the best practice is here. When doing the test in a loop and something fails, the current error from Pester isn't sufficient to tell you where it failed. @JamesWTruher suggestions?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose we should use TestCases

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool!

}
[string]$errorId = $parametersAndErrors[$parameter] + ",Microsoft.PowerShell.Commands.TestModuleManifestCommand"

{ Test-ModuleManifest -Path $testModulePath -ErrorAction Stop } | ShouldBeErrorId $errorId
Remove-Item -Recurse -Force $testModulePath
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove? It seems AfterEach does cleanups.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is needed as I'm generating a new invalid manifest each iteration of the loop

used TestCases feature of Pester for tests
added tests for valid and invalid rootmodules
"ScriptsToProcess"="Modules_InvalidManifest"
$args = @{$parameter = "doesnotexist.psm1"}
New-ModuleManifest -Path $testModulePath @args
Test-Path $testModulePath | Should Be $true
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Below ShouldBeErrorId still catches this error. Maybe remove the line?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, this isn't needed, originally I thought to check that the manifest was actually created, but it would fail later. Will remove.

New-Item -ItemType Directory -Path testdrive:/module
$testModulePath = "testdrive:/module/test.psd1"

if ($rootModuleValue -ne $null -and $rootModuleValue -ne "")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems it is better to us to split the tests into two and remove the conditions.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Was perhaps over optimizing on code reuse. I'll split it to make it more readable.

{ Test-ModuleManifest -Path $testModulePath -ErrorAction Stop } | ShouldBeErrorId $errorId
Remove-Item -Recurse -Force $testModulePath
New-ModuleManifest -Path $testModulePath -RootModule $rootModuleValue
Test-Path $testModulePath | Should Be $true
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe remove too?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree

New-Item -ItemType Directory -Path testdrive:/module
$testModulePath = "testdrive:/module/test.psd1"

if ($rootModuleValue -ne "doesnotexist.psm1")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems it is better to us to split the tests into two and remove the conditions.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm ok with splitting

New-Item -ItemType File -Path testdrive:/module/$rootModuleValue
}
New-ModuleManifest -Path $testModulePath -RootModule $rootModuleValue
Test-Path $testModulePath | Should Be $true
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe remove too?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree

@iSazonov
Copy link
Collaborator

I see multiple New-Item but I see no reason optimize them (BeforeAll).

So the tests LGTM.

@@ -131,6 +131,22 @@ protected override void ProcessRecord()
}
}

//RootModule can be null, empty string or point to a valid .psm1, or .dll. Anything else is invalid.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cdxml and xaml modules are allowed in RootModule just as they are allowed in NestedModules.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, when comparing extensions, is ignoring the case correct for non-Windows?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This file contains OrdinalIgnoreCase 4 times. But I see lots of other files to ignore the case when dealing with paths.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, case insensitive comparisons on executable extensions could be a bigger issue than just this file.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the extension comparison issue should probably be a separate issue so we can apply same fix everywhere

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Created issue #3218

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. We don't even have the desired method. Perhaps even better, make a request in .Net.

Copy link
Member Author
@SteveL-MSFT SteveL-MSFT Feb 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In testing a fix for cdxml/XAML modules, I see that you get this error message for InvalidModuleManifest which just seems wrong:

<value>The module manifest '{0}' could not be processed because it is not a valid Windows PowerShell restricted language file. Remove the elements that are not permitted by the restricted language:

    <value>The module manifest '{0}' could not be processed because it is not a valid Windows PowerShell restricted language file. Remove the elements that are not permitted by the restricted language: {1}</value>

I'd like to change it to something like:

The module manifest '{0}' could not be processed because it is not a valid PowerShell module manifest file.  Remove the elements that are not permitted: {1}

CC @HemantMahawar

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lzybkr addressed

added tests
updated InvalidModuleManifest error message to be about module manifests
Test-ModuleManifest -Path $testModulePath -ErrorAction Stop | Should BeOfType System.Management.Automation.PSModuleInfo
}

It "module manifest containing missing files returns error" -TestCases `
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typical use of -TestCases is to introduce a variable - that is probably easier to read.

If there is a good reason to inline the argument - you should prefer parens instead of a backtick.
Extra indentation on the test cases might also make it more readable, so maybe format like:

It "should work" -TestCases (
        @{rootModuleValue = "bar.psm1"},
        @{rootModuleValue = "bar.dll"}
) {
    param($rootModuleValue)
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will change

added tests
updated InvalidModuleManifest error message to be about module manifests
changed -TestCases usage to parens than backtick for readability
@lzybkr
Copy link
Contributor
lzybkr commented Mar 1, 2017

Closing and re-opening to retry blocked CI.

@lzybkr lzybkr closed this Mar 1, 2017
@lzybkr lzybkr reopened this Mar 1, 2017
@lzybkr lzybkr merged commit 99d696f into PowerShell:master Mar 1, 2017
@SteveL-MSFT SteveL-MSFT deleted the modulemanifest branch March 21, 2017 19:53
@iSazonov iSazonov removed the Review - Needed The PR is being reviewed label Mar 27, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants
0