diff --git a/PSSwagger/PSSwagger.Constants.ps1 b/PSSwagger/PSSwagger.Constants.ps1 index 1a4094e..d0cca21 100644 --- a/PSSwagger/PSSwagger.Constants.ps1 +++ b/PSSwagger/PSSwagger.Constants.ps1 @@ -51,7 +51,9 @@ else { `$ClrPath = Join-Path -Path `$PSScriptRoot -ChildPath 'ref' | Join-Path -ChildPath `$clr $DynamicAssemblyGenerationCode `$allDllsPath = Join-Path -Path `$ClrPath -ChildPath '*.dll' -Get-ChildItem -Path `$allDllsPath -File | ForEach-Object { Add-Type -Path `$_.FullName -ErrorAction SilentlyContinue } +if (Test-Path -Path `$ClrPath -PathType Container) { + Get-ChildItem -Path `$allDllsPath -File | ForEach-Object { Add-Type -Path `$_.FullName -ErrorAction SilentlyContinue } +} . (Join-Path -Path `$PSScriptRoot -ChildPath 'New-ServiceClient.ps1') . (Join-Path -Path `$PSScriptRoot -ChildPath 'GeneratedHelpers.ps1') @@ -247,7 +249,21 @@ $getTaskResultBlock = @' if(`$taskResult.IsFaulted) { Write-Verbose -Message 'Operation failed.' - Throw "`$(`$taskResult.Exception.InnerExceptions | Out-String)" + if (`$taskResult.Exception) + { + if ((Get-Member -InputObject `$taskResult.Exception -Name 'InnerExceptions') -and `$taskResult.Exception.InnerExceptions) + { + foreach (`$ex in `$taskResult.Exception.InnerExceptions) + { + Write-Error -Exception `$ex + } + } elseif ((Get-Member -InputObject `$taskResult.Exception -Name 'InnerException') -and `$taskResult.Exception.InnerException) + { + Write-Error -Exception `$taskResult.Exception.InnerException + } else { + Write-Error -Exception `$taskResult.Exception + } + } } elseif (`$taskResult.IsCanceled) { diff --git a/PSSwagger/PSSwagger.psm1 b/PSSwagger/PSSwagger.psm1 index 81bdc62..fbe9cfd 100644 --- a/PSSwagger/PSSwagger.psm1 +++ b/PSSwagger/PSSwagger.psm1 @@ -779,6 +779,7 @@ function ConvertTo-CsharpCode $tempCodeGenSettingsPath = '' # Latest AutoRest inconsistently appends 'Client' to the specified infoName to generated the client name. # We need to override the client name to ensure that generated PowerShell cmdlets work fine. + # Note: -ClientName doesn't seem to work for legacy invocation $ClientName = $info['ClientTypeName'] try { if ($info.ContainsKey('CodeGenFileRequired') -and $info.CodeGenFileRequired) { @@ -833,7 +834,6 @@ function ConvertTo-CsharpCode Write-Verbose -Message $LocalizedData.InvokingAutoRestWithParams Write-Verbose -Message $($autoRestParams | Out-String) - $autorestMessages = & AutoRest $autoRestParams if ($autorestMessages) { Write-Verbose -Message $($autorestMessages | Out-String) @@ -925,7 +925,9 @@ function ConvertTo-CsharpCode $dependencies = Get-PSSwaggerExternalDependencies -Azure:$codeCreatedByAzureGenerator -Framework 'netstandard1' $microsoftRestClientRuntimeAzureRequiredVersion = if ($dependencies.ContainsKey('Microsoft.Rest.ClientRuntime.Azure')) { $dependencies['Microsoft.Rest.ClientRuntime.Azure'].RequiredVersion } else { '' } + # In some cases, PSCore doesn't inherit this process's PSModulePath $command = @" + `$env:PSModulePath = `"$env:PSModulePath`"; `$AddPSSwaggerClientType_params = @{ OutputAssemblyName = '$outAssembly' ClrPath = '$clrPath' @@ -936,6 +938,7 @@ function ConvertTo-CsharpCode CodeCreatedByAzureGenerator = `$$codeCreatedByAzureGenerator BootstrapConsent = `$$UserConsent } + `$env:PSModulePath += ';$env:PSModulePath' PSSwaggerUtility\Add-PSSwaggerClientType @AddPSSwaggerClientType_params "@ $success = & "$PowerShellCorePath" -command "& {$command}" diff --git a/Tests/PSSwaggerScenario.Tests.ps1 b/Tests/PSSwaggerScenario.Tests.ps1 index 41b5d6e..c993cef 100644 --- a/Tests/PSSwaggerScenario.Tests.ps1 +++ b/Tests/PSSwaggerScenario.Tests.ps1 @@ -512,7 +512,7 @@ Describe "Composite Swagger Tests" -Tag @('Composite','ScenarioTest') { Import-Module $PsSwaggerPath -Force if((Get-Variable -Name PSEdition -ErrorAction Ignore) -and ('Core' -eq $PSEdition)) { - & "powershell.exe" -command "& {`$env:PSModulePath=`$env:PSModulePath_Backup; + & "$env:SystemRoot\System32\WindowsPowerShell\v1.0\powershell.exe" -command "& {`$env:PSModulePath=`$env:PSModulePath_Backup; Import-Module (Join-Path `"$PsSwaggerPath`" `"PSSwagger.psd1`") -Force -ArgumentList `$true; New-PSSwaggerModule -SpecificationPath $SwaggerSpecPath -Name $ModuleName -UseAzureCsharpGenerator -Path $Path -NoAssembly -Verbose -ConfirmBootstrap; }" @@ -521,6 +521,11 @@ Describe "Composite Swagger Tests" -Tag @('Composite','ScenarioTest') { } $ModulePath = Join-Path -Path $Path -ChildPath $ModuleName + # Destroy the full and core CLR requirements so that AzureRM modules aren't required + # For now, composite swagger specs don't work without the -UseAzureCsharpGenerator flag because of AutoRest naming inconsistency + "" | Out-File -FilePath (Join-Path -Path $ModulePath -ChildPath "0.0.1" | Join-Path -ChildPath "Test-CoreRequirements.ps1") + "" | Out-File -FilePath (Join-Path -Path $ModulePath -ChildPath "0.0.1" | Join-Path -ChildPath "Test-FullRequirements.ps1") + Get-Module -ListAvailable -Name $ModulePath | Should BeOfType 'System.Management.Automation.PSModuleInfo' # Import generated module @@ -807,7 +812,7 @@ Describe "Header scenario tests" -Tag @('Header','ScenarioTest') { $GeneratedModuleVersionPath = Join-Path -Path $GeneratedModuleBase -ChildPath $ModuleVersion $Header = '__Custom_HEADER_Content__' if((Get-Variable -Name PSEdition -ErrorAction Ignore) -and ('Core' -eq $PSEdition)) { - & "powershell.exe" -command "& {`$env:PSModulePath=`$env:PSModulePath_Backup; + & "$env:SystemRoot\System32\WindowsPowerShell\v1.0\PowerShell.exe" -command "& {`$env:PSModulePath=`$env:PSModulePath_Backup; Import-Module '$PsSwaggerPath' -Force -ArgumentList `$true; New-PSSwaggerModule -SpecificationPath '$SwaggerSpecPath' -Name $ModuleName -Version '$ModuleVersion' -UseAzureCsharpGenerator -Path '$GeneratedPath' -NoAssembly -Verbose -ConfirmBootstrap -Header '$Header'; }" @@ -828,7 +833,7 @@ Describe "Header scenario tests" -Tag @('Header','ScenarioTest') { $ModuleVersion = '2.2.2.2' $GeneratedModuleVersionPath = Join-Path -Path $GeneratedModuleBase -ChildPath $ModuleVersion if((Get-Variable -Name PSEdition -ErrorAction Ignore) -and ('Core' -eq $PSEdition)) { - & "powershell.exe" -command "& {`$env:PSModulePath=`$env:PSModulePath_Backup; + & "$env:SystemRoot\System32\WindowsPowerShell\v1.0\PowerShell.exe" -command "& {`$env:PSModulePath=`$env:PSModulePath_Backup; Import-Module '$PsSwaggerPath' -Force -ArgumentList `$true; New-PSSwaggerModule -SpecificationPath '$SwaggerSpecPath' -Name $ModuleName -Version '$ModuleVersion' -UseAzureCsharpGenerator -Path '$GeneratedPath' -NoAssembly -Verbose -ConfirmBootstrap; }" @@ -973,7 +978,7 @@ Describe "Pre-compiled SDK Assmebly scenario tests" -Tag @('SDKAssembly','Scenar Verbose = $true } Invoke-NewPSSwaggerModuleCommand -NewPSSwaggerModuleParameters $NewPSSwaggerModule_params -ErrorVariable 'ev' -ErrorAction 'SilentlyContinue' - $ev.FullyQualifiedErrorId | Should Be 'AssemblyNotFound,New-PSSwaggerModule' + (Remove-TestErrorId -FullyQualifiedErrorId $ev.FullyQualifiedErrorId) | Should Be 'AssemblyNotFound,New-PSSwaggerModule' } It 'Should fail when client type name is not found in pre-compiled SDK assembly scenario' { @@ -999,7 +1004,7 @@ Describe "Pre-compiled SDK Assmebly scenario tests" -Tag @('SDKAssembly','Scenar Verbose = $true } Invoke-NewPSSwaggerModuleCommand -NewPSSwaggerModuleParameters $NewPSSwaggerModule_params -ErrorVariable 'ev' -ErrorAction 'SilentlyContinue' - $ev.FullyQualifiedErrorId | Should Be 'UnableToExtractDetailsFromSdkAssembly,Update-PathFunctionDetails' + (Remove-TestErrorId -FullyQualifiedErrorId $ev.FullyQualifiedErrorId) | Should Be 'UnableToExtractDetailsFromSdkAssembly,Update-PathFunctionDetails' } It 'Should fail when incorrect namespace in client type name is specified in pre-compiled SDK assembly scenario' { @@ -1025,7 +1030,7 @@ Describe "Pre-compiled SDK Assmebly scenario tests" -Tag @('SDKAssembly','Scenar Verbose = $true } Invoke-NewPSSwaggerModuleCommand -NewPSSwaggerModuleParameters $NewPSSwaggerModule_params -ErrorVariable 'ev' -ErrorAction 'SilentlyContinue' - $ev.FullyQualifiedErrorId | Should Be 'UnableToExtractDetailsFromSdkAssembly,Update-PathFunctionDetails' + (Remove-TestErrorId -FullyQualifiedErrorId $ev.FullyQualifiedErrorId) | Should Be 'UnableToExtractDetailsFromSdkAssembly,Update-PathFunctionDetails' } It 'Should fail when incorrect client type name is specified in pre-compiled SDK assembly scenario' { @@ -1051,6 +1056,6 @@ Describe "Pre-compiled SDK Assmebly scenario tests" -Tag @('SDKAssembly','Scenar Verbose = $true } Invoke-NewPSSwaggerModuleCommand -NewPSSwaggerModuleParameters $NewPSSwaggerModule_params -ErrorVariable 'ev' -ErrorAction 'SilentlyContinue' - $ev.FullyQualifiedErrorId | Should Be 'UnableToExtractDetailsFromSdkAssembly,Update-PathFunctionDetails' + (Remove-TestErrorId -FullyQualifiedErrorId $ev.FullyQualifiedErrorId) | Should Be 'UnableToExtractDetailsFromSdkAssembly,Update-PathFunctionDetails' } } diff --git a/Tests/TestUtilities.psm1 b/Tests/TestUtilities.psm1 index c681dd1..d9d2781 100644 --- a/Tests/TestUtilities.psm1 +++ b/Tests/TestUtilities.psm1 @@ -93,16 +93,76 @@ function Invoke-NewPSSwaggerModuleCommand { elseif ($_.Value -ne $false) { $ParametersString += " -$($_.Name) '$($_.Value)'" } - } - & "powershell.exe" -command "& { + } + # For now this hides Exception and ErrorObject + $command = "& { `$env:PSModulePath=`$env:PSModulePath_Backup; - New-PSSwaggerModule $ParametersString + New-PSSwaggerModule $ParametersString -ErrorVariable evtemp + foreach (`$ev in `$evtemp) { + `$returnEv = `$false + `$evEncoded = 'ErrorVariable: ' + if (`$ev.FullyQualifiedErrorId) { + `$evEncoded += 'ErrorId=' + `$evEncoded += `$ev.FullyQualifiedErrorId + `$evEncoded += ';' + `$returnEv = `$true + } + + if (`$ev.CategoryInfo) { + `$evEncoded += 'ErrorCategory=' + `$evEncoded += `$ev.CategoryInfo.Category + `$evEncoded += ';' + `$returnEv = `$true + } + + if (`$returnEv) { + `$evEncoded + } + } }" + $result = & "$env:SystemRoot\System32\WindowsPowerShell\v1.0\PowerShell.exe" -command $command + if ($PSBoundParameters.ContainsKey("ErrorVariable")) { + foreach ($resultLine in $result) { + if ($resultLine.StartsWith("ErrorVariable: ")) { + $errorVariableInfoTokenPairs = $resultLine.Substring(15).Split(';') + $errorId = '' + $errorCategory = '' + for ($i = 0; $i -lt $errorVariableInfoTokenPairs.Length; $i++) { + $errorVariableInfoTokens = $errorVariableInfoTokenPairs[$i].Split('=') + if ($errorVariableInfoTokens[0] -eq 'ErrorId') { + $errorId = $errorVariableInfoTokens[1] + } elseif ($errorVariableInfoTokens[0] -eq 'ErrorCategory') { + $errorCategory = $errorVariableInfoTokens[1] + } + } + + Write-Error -Message 'New-PSSwaggerModule remote error' -ErrorId $errorId -Category $errorCategory + } + } + } + $result } else { New-PSSwaggerModule @NewPSSwaggerModuleParameters } } + +function Remove-TestErrorId { + [CmdletBinding()] + param( + [string]$FullyQualifiedErrorId + ) + + $errorIds = $FullyQualifiedErrorId.Split(',') + $NewFullyQualifiedErrorId = '' + for ($i = 0; $i -lt $errorIds.Length; $i++) { + if ($errorIds[$i] -ne 'Invoke-NewPSSwaggerModuleCommand') { + $NewFullyQualifiedErrorId += "$($errorIds[$i])," + } + } + + return $NewFullyQualifiedErrorId.Substring(0, $NewFullyQualifiedErrorId.Length - 1) +} function Initialize-Test { [CmdletBinding()] param( @@ -132,9 +192,8 @@ function Initialize-Test { # Module generation part needs to happen in full powershell Write-Verbose "Generating module" if((Get-Variable -Name PSEdition -ErrorAction Ignore) -and ('Core' -eq $PSEdition)) { - & "powershell.exe" -command "& {`$env:PSModulePath=`$env:PSModulePath_Backup; + & "$env:SystemRoot\System32\WindowsPowerShell\v1.0\PowerShell.exe" -command "& {`$env:PSModulePath=`$env:PSModulePath_Backup; Import-Module (Join-Path `"$PsSwaggerPath`" `"PSSwagger.psd1`") -Force; - Import-Module (Join-Path `"$PsSwaggerPath`" `"PSSwaggerUtility`") -Force; Initialize-PSSwaggerDependencies -AllFrameworks -AcceptBootstrap -Azure:`$$UseAzureCSharpGenerator; New-PSSwaggerModule -SpecificationPath (Join-Path -Path `"$testCaseDataLocation`" -ChildPath $TestSpecFileName) -Path "$generatedModulesPath" -Name $GeneratedModuleName -Verbose -NoAssembly -UseAzureCSharpGenerator:`$$UseAzureCSharpGenerator -ConfirmBootstrap; }" diff --git a/Tests/run-tests.ps1 b/Tests/run-tests.ps1 index 097d03c..6440b44 100644 --- a/Tests/run-tests.ps1 +++ b/Tests/run-tests.ps1 @@ -135,6 +135,10 @@ if (-not $azureRmProfile) { } $powershellFolder = $null +$srcPath = Join-Path -Path $PSScriptRoot -ChildPath .. | Join-Path -ChildPath PSSwagger +$srcPath += [System.IO.Path]::DirectorySeparatorChar +$modulePath = Join-Path -Path $PSScriptRoot -ChildPath .. +$modulePath += [System.IO.Path]::DirectorySeparatorChar if ("netstandard1.7" -eq $TestFramework) { # beta > alpha $powershellCore = Get-Package -Name PowerShell* -ProviderName msi | Sort-Object -Property Name -Descending | Select-Object -First 1 -ErrorAction Ignore @@ -143,7 +147,7 @@ if ("netstandard1.7" -eq $TestFramework) { } $psVersion = $powershellCore.Name.Substring(11) $powershellFolder = "$Env:ProgramFiles\PowerShell\$($psVersion)" - $executeTestsCommand += ";`$env:PSModulePath_Backup=`"$env:PSModulePath`"" + $executeTestsCommand += ";`$env:PSModulePath_Backup=`"$srcPath;$modulePath;$env:PSModulePath`"" } if ($EnableTracing) { @@ -154,7 +158,7 @@ $srcPath = Join-Path -Path $PSScriptRoot -ChildPath .. | Join-Path -ChildPath PS $srcPath += [System.IO.Path]::DirectorySeparatorChar $executeTestsCommand += @" ;`$verbosepreference=`'continue`'; - `$env:PSModulePath=`"$srcPath;`$env:PSModulePath`"; + `$env:PSModulePath=`"$srcPath;$modulePath;`$env:PSModulePath`"; Invoke-Pester -Script `'$PSScriptRoot`' -ExcludeTag KnownIssue -OutputFormat NUnitXml -OutputFile ScenarioTestResults.xml -Verbose; "@ # Set up Pester params