diff --git a/images/win/Windows2016-Azure.json b/images/win/Windows2016-Azure.json index 05333241a..349591cd4 100644 --- a/images/win/Windows2016-Azure.json +++ b/images/win/Windows2016-Azure.json @@ -84,6 +84,11 @@ "source": "{{ template_dir }}/scripts/SoftwareReport", "destination": "{{user `image_folder`}}" }, + { + "type": "file", + "source": "{{ template_dir }}/scripts/Tests", + "destination": "{{user `image_folder`}}" + }, { "type": "windows-shell", "inline": [ @@ -839,18 +844,6 @@ "{{ template_dir }}/scripts/Installers/Validate-AliyunCli.ps1" ] }, - { - "type": "powershell", - "scripts":[ - "{{ template_dir }}/scripts/Installers/Validate-JavaTools.ps1" - ] - }, - { - "type": "powershell", - "scripts":[ - "{{ template_dir }}/scripts/Installers/Validate-Cmake.ps1" - ] - }, { "type": "powershell", "scripts":[ @@ -911,12 +904,6 @@ "{{ template_dir }}/scripts/Installers/Validate-AzureCosmosDbEmulator.ps1" ] }, - { - "type": "powershell", - "scripts":[ - "{{ template_dir }}/scripts/Installers/Validate-7zip.ps1" - ] - }, { "type": "powershell", "scripts":[ @@ -983,18 +970,6 @@ "{{ template_dir }}/scripts/Installers/Validate-KubernetesCli.ps1" ] }, - { - "type": "powershell", - "scripts":[ - "{{ template_dir }}/scripts/Installers/Validate-Kind.ps1" - ] - }, - { - "type": "powershell", - "scripts":[ - "{{ template_dir }}/scripts/Installers/Validate-MongoDB.ps1" - ] - }, { "type": "powershell", "scripts":[ @@ -1019,6 +994,12 @@ "type": "windows-restart", "restart_timeout": "10m" }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Tests/RunAll-Tests.ps1" + ] + }, { "type": "powershell", "inline": [ diff --git a/images/win/Windows2019-Azure.json b/images/win/Windows2019-Azure.json index d5bf5f739..94a9a9375 100644 --- a/images/win/Windows2019-Azure.json +++ b/images/win/Windows2019-Azure.json @@ -84,6 +84,11 @@ "source": "{{ template_dir }}/scripts/SoftwareReport", "destination": "{{user `image_folder`}}" }, + { + "type": "file", + "source": "{{ template_dir }}/scripts/Tests", + "destination": "{{user `image_folder`}}" + }, { "type": "windows-shell", "inline": [ @@ -826,18 +831,6 @@ "{{ template_dir }}/scripts/Installers/Validate-NodeLts.ps1" ] }, - { - "type": "powershell", - "scripts":[ - "{{ template_dir }}/scripts/Installers/Validate-JavaTools.ps1" - ] - }, - { - "type": "powershell", - "scripts":[ - "{{ template_dir }}/scripts/Installers/Validate-Cmake.ps1" - ] - }, { "type": "powershell", "scripts":[ @@ -899,12 +892,6 @@ ] }, { - "type": "powershell", - "scripts":[ - "{{ template_dir }}/scripts/Installers/Validate-7zip.ps1" - ] - }, - { "type": "powershell", "scripts":[ "{{ template_dir }}/scripts/Installers/Validate-Packer.ps1" @@ -976,18 +963,6 @@ "{{ template_dir }}/scripts/Installers/Validate-KubernetesCli.ps1" ] }, - { - "type": "powershell", - "scripts":[ - "{{ template_dir }}/scripts/Installers/Validate-Kind.ps1" - ] - }, - { - "type": "powershell", - "scripts":[ - "{{ template_dir }}/scripts/Installers/Validate-MongoDB.ps1" - ] - }, { "type": "powershell", "scripts":[ @@ -1024,6 +999,12 @@ "type": "windows-restart", "restart_timeout": "10m" }, + { + "type": "powershell", + "scripts":[ + "{{ template_dir }}/scripts/Tests/RunAll-Tests.ps1" + ] + }, { "type": "powershell", "inline": [ diff --git a/images/win/scripts/ImageHelpers/ImageHelpers.psm1 b/images/win/scripts/ImageHelpers/ImageHelpers.psm1 index 95a7d6c70..da1449568 100644 --- a/images/win/scripts/ImageHelpers/ImageHelpers.psm1 +++ b/images/win/scripts/ImageHelpers/ImageHelpers.psm1 @@ -4,6 +4,7 @@ param() . $PSScriptRoot\PathHelpers.ps1 . $PSScriptRoot\InstallHelpers.ps1 . $PSScriptRoot\ChocoHelpers.ps1 +. $PSScriptRoot\TestsHelpers.ps1 Export-ModuleMember -Function @( 'Test-MachinePath' @@ -28,4 +29,8 @@ Export-ModuleMember -Function @( 'Test-IsWin16' 'Choco-Install' 'Extract-7Zip' + 'Get-CommandResult' + 'Get-WhichTool' + 'Get-EnvironmentVariable' + 'Invoke-PesterTests' ) diff --git a/images/win/scripts/ImageHelpers/TestsHelpers.ps1 b/images/win/scripts/ImageHelpers/TestsHelpers.ps1 new file mode 100644 index 000000000..fdc341ccf --- /dev/null +++ b/images/win/scripts/ImageHelpers/TestsHelpers.ps1 @@ -0,0 +1,106 @@ +function Get-CommandResult { + Param ( + [Parameter(Mandatory)][string] $Command + ) + # CMD trick to suppress and show error output because some commands write to stderr (for example, "python --version") + [string[]]$output = & $env:comspec /c "$Command 2>&1" + $exitCode = $LASTEXITCODE + + return @{ + Output = $output + ExitCode = $exitCode + } +} + +# Gets path to the tool, analogue of 'which tool' +function Get-WhichTool { + Param ( + [Parameter(Mandatory)][string] $Tool + ) + return (Get-Command $Tool).Path +} + +# Gets value of environment variable by the name +function Get-EnvironmentVariable($variable) { + return [System.Environment]::GetEnvironmentVariable($variable) +} + +# Update environment variables without reboot +function Update-Environment { + $variables = [Environment]::GetEnvironmentVariables("Machine") + $variables.Keys | ForEach-Object { + $key = $_ + $value = $variables[$key] + Set-Item -Path "env:$key" -Value $value + } + # We need to refresh PATH the latest one because it could include other variables "%M2_HOME%/bin" + $env:PATH = [Environment]::GetEnvironmentVariable("PATH", "Machine") +} + +# Run Pester tests for specific tool +function Invoke-PesterTests { + Param( + [Parameter(Mandatory)][string] $TestFile, + [string] $TestName + ) + + $testPath = "C:\image\Tests\${TestFile}.Tests.ps1" + if (-not (Test-Path $testPath)) { + throw "Unable to find test file '$TestFile' on '$testPath'." + } + + $configuration = [PesterConfiguration] @{ + Run = @{ Path = $testPath; PassThru = $true } + Output = @{ Verbosity = "Detailed" } + } + if ($TestName) { + $configuration.Filter.FullName = $TestName + } + + # Update environment variables without reboot + Update-Environment + + # Switch ErrorActionPreference to Stop temporary to make sure that tests will on silent errors too + $backupErrorActionPreference = $ErrorActionPreference + $ErrorActionPreference = "Stop" + $results = Invoke-Pester -Configuration $configuration + $ErrorActionPreference = $backupErrorActionPreference + + # Fail in case if no tests are run + if (-not ($results -and ($results.FailedCount -eq 0) -and ($results.PassedCount -gt 0))) { + $results + throw "Test run has finished with errors" + } +} + +# Pester Assert to check exit code of command +function ShouldReturnZeroExitCode { + Param( + [String]$ActualValue, + [switch]$Negate, + [string] $Because + ) + + $result = Get-CommandResult $ActualValue + + [bool]$succeeded = $result.ExitCode -eq 0 + if ($Negate) { $succeeded = -not $succeeded } + + + + if (-not $succeeded) + { + $CommandResultIndent = " " * 4 + $commandOutput = ($result.Output | ForEach-Object { "${CommandResultIndent}${_}" }) -join "`n" + $failureMessage = "Command '${ActualValue}' has finished with exit code ${actualExitCode}`n${commandOutput}" + } + + return [PSCustomObject] @{ + Succeeded = $succeeded + FailureMessage = $failureMessage + } +} + +If (Get-Command -Name Add-AssertionOperator -ErrorAction SilentlyContinue) { + Add-AssertionOperator -Name ReturnZeroExitCode -InternalName ShouldReturnZeroExitCode -Test ${function:ShouldReturnZeroExitCode} +} \ No newline at end of file diff --git a/images/win/scripts/Installers/Install-7zip.ps1 b/images/win/scripts/Installers/Install-7zip.ps1 index 419c81782..9ad1e2045 100644 --- a/images/win/scripts/Installers/Install-7zip.ps1 +++ b/images/win/scripts/Installers/Install-7zip.ps1 @@ -4,3 +4,5 @@ ################################################################################ Choco-Install -PackageName 7zip.install + +Invoke-PesterTests -TestFile "Tools" -TestName "7-Zip" \ No newline at end of file diff --git a/images/win/scripts/Installers/Install-Cmake.ps1 b/images/win/scripts/Installers/Install-Cmake.ps1 index 37183d5e6..8baa82e2a 100644 --- a/images/win/scripts/Installers/Install-Cmake.ps1 +++ b/images/win/scripts/Installers/Install-Cmake.ps1 @@ -4,3 +4,5 @@ ################################################################################ Choco-Install -PackageName cmake.install -ArgumentList "--installargs",'ADD_CMAKE_TO_PATH=""System""' + +Invoke-PesterTests -TestFile "Tools" -TestName "CMake" \ No newline at end of file diff --git a/images/win/scripts/Installers/Install-JavaTools.ps1 b/images/win/scripts/Installers/Install-JavaTools.ps1 index 49b95e3af..759d132fc 100644 --- a/images/win/scripts/Installers/Install-JavaTools.ps1 +++ b/images/win/scripts/Installers/Install-JavaTools.ps1 @@ -126,3 +126,5 @@ $archivePath = Start-DownloadWithRetry -Url $uri -Name "cobertura.zip" Extract-7Zip -Path $archivePath -DestinationPath "C:\" setx COBERTURA_HOME $coberturaPath /M + +Invoke-PesterTests -TestFile "Java" \ No newline at end of file diff --git a/images/win/scripts/Installers/Install-MongoDB.ps1 b/images/win/scripts/Installers/Install-MongoDB.ps1 index 245e5b98f..177300e97 100644 --- a/images/win/scripts/Installers/Install-MongoDB.ps1 +++ b/images/win/scripts/Installers/Install-MongoDB.ps1 @@ -7,3 +7,5 @@ Choco-Install -PackageName mongodb $mongoPath = (Get-CimInstance Win32_Service -Filter "Name LIKE 'mongodb'").PathName $mongoBin = Split-Path -Path $mongoPath.split('"')[1] Add-MachinePathItem "$mongoBin" + +Invoke-PesterTests -TestFile "Databases" -TestName "MongoDB" \ No newline at end of file diff --git a/images/win/scripts/Installers/Validate-7zip.ps1 b/images/win/scripts/Installers/Validate-7zip.ps1 deleted file mode 100644 index d29d394e1..000000000 --- a/images/win/scripts/Installers/Validate-7zip.ps1 +++ /dev/null @@ -1,15 +0,0 @@ -################################################################################ -## File: Validate-7zip.ps1 -## Desc: Validate 7zip -################################################################################ - -if (Get-Command -Name '7z') -{ - Write-Host '7zip on path' -} -else -{ - Write-Host '7zip is not on path' - exit 1 -} - diff --git a/images/win/scripts/Installers/Validate-Cmake.ps1 b/images/win/scripts/Installers/Validate-Cmake.ps1 deleted file mode 100644 index df6835919..000000000 --- a/images/win/scripts/Installers/Validate-Cmake.ps1 +++ /dev/null @@ -1,16 +0,0 @@ -################################################################################ -## File: Validate-Cmake.ps1 -## Desc: Validate Cmake -################################################################################ - -if(Get-Command -Name 'cmake') -{ - Write-Host "CMake $(cmake -version) on path" -} -else -{ - Write-Host "CMake not on path" - exit 1 -} - - diff --git a/images/win/scripts/Installers/Validate-JavaTools.ps1 b/images/win/scripts/Installers/Validate-JavaTools.ps1 deleted file mode 100644 index 50513156f..000000000 --- a/images/win/scripts/Installers/Validate-JavaTools.ps1 +++ /dev/null @@ -1,79 +0,0 @@ -################################################################################ -## File: Validate-JavaTools.ps1 -## Desc: Validate various JDKs and java tools -################################################################################ - -Function Validate-JavaVersion { - param ( - [Parameter(Mandatory)] [string] $Version, - [switch] $Default - ) - - Write-Host "Checking Java $version" - - # Set Path to get Java - if (-not $Default) - { - # Take 7 & 8 for versions 1.7 and 1.8 - $versionNumber = $version.Split(".") | Select-Object -Last 1 - - $javaPath = [System.Environment]::GetEnvironmentVariable("JAVA_HOME_${versionNumber}_X64") - if ([string]::IsNullOrEmpty($javaPath)) - { - Write-Host "Environment variable 'JAVA_HOME_${versionNumber}_X64' is null" - exit 1 - } - - $javaBin = "$javaPath\bin;" - $env:Path = $javaBin + $env:Path - } - else - { - Validate-JavaVersion -Version $Version - } - - $isJavaExists = $($(& $env:comspec "/s /c java -version 2>&1") | Out-String) -match '^(?.+) version "(?.+)".*' - - if ($isJavaExists) - { - $javaVersion = $matches.version - } - else - { - Write-Host "Java $version was not found" - exit 1 - } - - $isJavaCorrect = $javaVersion.StartsWith($version) - - if($isJavaCorrect) - { - Write-Host "Java $javaVersion found" - # Reset Path to the default one in case we need to check the default Java later - $env:Path = [System.Environment]::GetEnvironmentVariable("Path","Machine") + ";" + [System.Environment]::GetEnvironmentVariable("Path","User") - } - else - { - Write-Host "Expected Java $version, but found $javaVersion" - exit 1 - } -} - -if((Get-Command -Name 'java') -and (Get-Command -Name 'mvn') -and (Get-Command -Name 'ant') -and (Get-Command -Name 'gradle')) -{ - Write-Host "Java $(java -version) on path" - Write-Host "Maven $(mvn -version) on path" - Write-Host "Ant $(ant -version) on path" - Write-Host "Gradle $(gradle -version) on path" -} -else -{ - Write-Host "one of Java,Maven,Ant,Gradle is not on path." - exit 1 -} - -Write-Host "Checking installed Java versions" -Validate-JavaVersion -Version "1.7" -Validate-JavaVersion -Version "1.8" -Default -Validate-JavaVersion -Version "11" -Validate-JavaVersion -Version "13" diff --git a/images/win/scripts/Installers/Validate-Kind.ps1 b/images/win/scripts/Installers/Validate-Kind.ps1 deleted file mode 100644 index 9147f4621..000000000 --- a/images/win/scripts/Installers/Validate-Kind.ps1 +++ /dev/null @@ -1,14 +0,0 @@ -################################################################################ -## File: Validate-Kind.ps1 -## Desc: Validate Kind. -################################################################################ - -if (Get-Command -Name 'kind') -{ - Write-Host "kind $(kind version) in path" -} -else -{ - Write-Host "kind is not in path" - exit 1 -} diff --git a/images/win/scripts/Installers/Validate-MongoDB.ps1 b/images/win/scripts/Installers/Validate-MongoDB.ps1 deleted file mode 100644 index 517f824cb..000000000 --- a/images/win/scripts/Installers/Validate-MongoDB.ps1 +++ /dev/null @@ -1,24 +0,0 @@ -################################################################################ -## File: Validate-MongoDB.ps1 -## Desc: Validate MongoDB -################################################################################ - -if (Get-Command -Name 'mongod') -{ - Write-Host 'mongod is on path' -} -else -{ - Write-Host 'mongod not on path' - exit 1 -} - -if (Get-Command -Name 'mongo') -{ - Write-Host 'mongo is on path' -} -else -{ - Write-Host 'mongo not on path' - exit 1 -} diff --git a/images/win/scripts/Installers/Windows2016/Initialize-VM.ps1 b/images/win/scripts/Installers/Windows2016/Initialize-VM.ps1 index 794c1b0f6..5afc6e61f 100644 --- a/images/win/scripts/Installers/Windows2016/Initialize-VM.ps1 +++ b/images/win/scripts/Installers/Windows2016/Initialize-VM.ps1 @@ -41,6 +41,8 @@ Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force Install-Module -Name PowerShellGet -Force Set-PSRepository -InstallationPolicy Trusted -Name PSGallery +Write-Host "Install the latest Pester version" +Install-Module Pester -Scope AllUsers -SkipPublisherCheck -Force Write-Host "Disable Antivirus" Set-MpPreference -DisableRealtimeMonitoring $true diff --git a/images/win/scripts/Installers/Windows2019/Initialize-VM.ps1 b/images/win/scripts/Installers/Windows2019/Initialize-VM.ps1 index 99c238e8c..e57ccb981 100644 --- a/images/win/scripts/Installers/Windows2019/Initialize-VM.ps1 +++ b/images/win/scripts/Installers/Windows2019/Initialize-VM.ps1 @@ -38,6 +38,8 @@ Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force Install-Module -Name PowerShellGet -Force Set-PSRepository -InstallationPolicy Trusted -Name PSGallery +Write-Host "Install the latest Pester version" +Install-Module Pester -Scope AllUsers -SkipPublisherCheck -Force Write-Host "Disable Antivirus" Set-MpPreference -DisableRealtimeMonitoring $true diff --git a/images/win/scripts/Tests/Databases.Tests.ps1 b/images/win/scripts/Tests/Databases.Tests.ps1 new file mode 100644 index 000000000..b7cda7a49 --- /dev/null +++ b/images/win/scripts/Tests/Databases.Tests.ps1 @@ -0,0 +1,8 @@ +Describe "MongoDB" { + It "" -TestCases @( + @{ ToolName = "mongo" } + @{ ToolName = "mongod" } + ) { + "$ToolName --version" | Should -ReturnZeroExitCode + } +} \ No newline at end of file diff --git a/images/win/scripts/Tests/Java.Tests.ps1 b/images/win/scripts/Tests/Java.Tests.ps1 new file mode 100644 index 000000000..04a749bd4 --- /dev/null +++ b/images/win/scripts/Tests/Java.Tests.ps1 @@ -0,0 +1,36 @@ +Describe "Java" { + It "Java is default" -TestCases @(@{ DefaultJavaVersion = 8 }) { + $actualJavaPath = Get-EnvironmentVariable "JAVA_HOME" + $expectedJavaPath = Get-EnvironmentVariable "JAVA_HOME_${DefaultJavaVersion}_X64" + + $actualJavaPath | Should -Not -BeNullOrEmpty + $expectedJavaPath | Should -Not -BeNullOrEmpty + $actualJavaPath | Should -Be $expectedJavaPath + } + + It "" -TestCases @( + @{ ToolName = "java" } + @{ ToolName = "mvn" } + @{ ToolName = "ant" } + @{ ToolName = "gradle" } + ) { + "$ToolName -version" | Should -ReturnZeroExitCode + } + + It "Java " -TestCases @( + @{ Version = "1.7" } + @{ Version = "1.8" } + @{ Version = "11" } + @{ Version = "13" } + ) { + $versionNumber = $version.Split(".") | Select-Object -Last 1 + + $javaVariableValue = Get-EnvironmentVariable "JAVA_HOME_${versionNumber}_X64" + $javaVariableValue | Should -Not -BeNullOrEmpty + $javaPath = Join-Path $javaVariableValue "bin\java" + + $result = Get-CommandResult "`"$javaPath`" -version" + $result.ExitCode | Should -Be 0 + $result.Output[0] | Should -Match ([regex]::Escape("openjdk version `"${Version}.")) + } +} \ No newline at end of file diff --git a/images/win/scripts/Tests/RunAll-Tests.ps1 b/images/win/scripts/Tests/RunAll-Tests.ps1 new file mode 100644 index 000000000..1d8e835ca --- /dev/null +++ b/images/win/scripts/Tests/RunAll-Tests.ps1 @@ -0,0 +1 @@ +Invoke-PesterTests "*" \ No newline at end of file diff --git a/images/win/scripts/Tests/Tools.Tests.ps1 b/images/win/scripts/Tests/Tools.Tests.ps1 new file mode 100644 index 000000000..6ddbcb217 --- /dev/null +++ b/images/win/scripts/Tests/Tools.Tests.ps1 @@ -0,0 +1,17 @@ +Describe "7-Zip" { + It "7z" { + "7z" | Should -ReturnZeroExitCode + } +} + +Describe "CMake" { + It "cmake" { + "cmake --version" | Should -ReturnZeroExitCode + } +} + +Describe "Kind" { + It "Kind" { + "kind version" | Should -ReturnZeroExitCode + } +} \ No newline at end of file