Skip to content

Commit 8c7f703

Browse files
TravisEz13daxian-dbw
authored andcommitted
Add tests to do basic verification of docker images (PowerShell#4244)
1 parent 3b3b3d1 commit 8c7f703

3 files changed

Lines changed: 321 additions & 0 deletions

File tree

docker/tests/README.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Docker tests
2+
3+
## Windows and Linux containers
4+
5+
The tests must be run separately on the Windows and Linux docker daemons. You can use the Linux docker daemon on Windows, but that will only test Linux containers not Windows Containers.
6+
7+
## To building and basic behavior of the containers
8+
9+
```PowerShell
10+
Invoke-Pester
11+
```
12+
13+
Note: be sure to do this using both the Windows and Linux docker daemon, as the windows.
14+
15+
## To test the productions containers
16+
17+
```PowerShell
18+
Invoke-Pester -Tag Behavior
19+
```
20+
21+
## To test only building the containers
22+
23+
```PowerShell
24+
Invoke-Pester -Tag Build
25+
```

docker/tests/container.tests.ps1

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
Import-module -Name "$PSScriptRoot\containerTestCommon.psm1" -Force
2+
$script:linuxContainerTests = Get-LinuxContainer
3+
$script:windowsContainerTests = Get-WindowsContainer
4+
$script:skipLinux = Test-SkipLinux
5+
$script:skipWindows = Test-SkipWindows
6+
7+
Describe "Build Linux Containers" -Tags 'Build', 'Linux' {
8+
BeforeAll {
9+
Set-RepoName 'pscontainertest'
10+
}
11+
12+
it "$(Get-RepoName):<Name> builds from '<path>'" -TestCases $script:linuxContainerTests -Skip:$script:skipLinux {
13+
param(
14+
[Parameter(Mandatory=$true)]
15+
[string]
16+
$name,
17+
18+
[Parameter(Mandatory=$true)]
19+
[string]
20+
$path
21+
)
22+
{ Invoke-Docker -Command build -Params '--pull', '--quiet', '-t', "$(Get-RepoName):${Name}", $path -SuppressHostOutput} | should not throw
23+
}
24+
}
25+
26+
Describe "Build Windows Containers" -Tags 'Build', 'Windows' {
27+
BeforeAll {
28+
Set-RepoName 'pscontainertest'
29+
}
30+
31+
it "$(Get-RepoName):<Name> builds from '<path>'" -TestCases $script:windowsContainerTests -skip:$script:skipWindows {
32+
param(
33+
[Parameter(Mandatory=$true)]
34+
[string]
35+
$name,
36+
37+
[Parameter(Mandatory=$true)]
38+
[string]
39+
$path
40+
)
41+
42+
{ Invoke-Docker -Command build -Params @(
43+
'--pull'
44+
'--quiet'
45+
'-t'
46+
"$(Get-RepoName):${Name}"
47+
$path
48+
) -SuppressHostOutput} | should not throw
49+
}
50+
}
51+
52+
Describe "Linux Containers run PowerShell" -Tags 'Behavior', 'Linux' {
53+
BeforeAll{
54+
$testContext = Get-TestContext -type Linux
55+
}
56+
AfterAll{
57+
# prune unused volumes
58+
$null=Invoke-Docker -Command 'volume', 'prune' -Params '--force' -SuppressHostOutput
59+
}
60+
BeforeEach
61+
{
62+
Remove-Item $testContext.resolvedXmlPath -ErrorAction SilentlyContinue
63+
Remove-Item $testContext.resolvedLogPath -ErrorAction SilentlyContinue
64+
}
65+
66+
it "Get PSVersion table from $(Get-RepoName):<Name>" -TestCases $script:linuxContainerTests -Skip:$script:skipLinux {
67+
param(
68+
[Parameter(Mandatory=$true)]
69+
[string]
70+
$name,
71+
72+
[Parameter(Mandatory=$true)]
73+
[string]
74+
$path
75+
)
76+
77+
Get-ContainerPowerShellVersion -TestContext $testContext -Name $Name -RepoName (Get-RepoName) | should be '6.0.0-beta'
78+
}
79+
}
80+
81+
Describe "Windows Containers run PowerShell" -Tags 'Behavior', 'Windows' {
82+
BeforeAll{
83+
$testContext = Get-TestContext -type Windows
84+
}
85+
BeforeEach
86+
{
87+
Remove-Item $testContext.resolvedXmlPath -ErrorAction SilentlyContinue
88+
Remove-Item $testContext.resolvedLogPath -ErrorAction SilentlyContinue
89+
}
90+
91+
it "Get PSVersion table from $(Get-RepoName):<Name>" -TestCases $script:windowsContainerTests -skip:$script:skipWindows {
92+
param(
93+
[Parameter(Mandatory=$true)]
94+
[string]
95+
$name,
96+
97+
[Parameter(Mandatory=$true)]
98+
[string]
99+
$path
100+
)
101+
102+
Get-ContainerPowerShellVersion -TestContext $testContext -Name $Name -RepoName (Get-RepoName) | should be '6.0.0-beta'
103+
}
104+
}
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
$script:forcePull = $true
2+
# Get docker Engine OS
3+
function Get-DockerEngineOs
4+
{
5+
docker info --format '{{ .OperatingSystem }}'
6+
}
7+
8+
# Call Docker with appropriate result checksfunction Invoke-Docker
9+
function Invoke-Docker
10+
{
11+
param(
12+
[Parameter(Mandatory=$true)]
13+
[string[]]
14+
$Command,
15+
[ValidateSet("error","warning",'ignore')]
16+
$FailureAction = 'error',
17+
18+
[Parameter(Mandatory=$true)]
19+
[string[]]
20+
$Params,
21+
22+
[switch]
23+
$PassThru,
24+
[switch]
25+
$SuppressHostOutput
26+
)
27+
28+
$ErrorActionPreference = 'Continue'
29+
30+
# Log how we are running docker for troubleshooting issues
31+
Write-Verbose "Running docker $command $params" -Verbose
32+
if($SuppressHostOutput.IsPresent)
33+
{
34+
$result = docker $command $params 2>&1
35+
}
36+
else
37+
{
38+
&'docker' $command $params 2>&1 | Tee-Object -Variable result -ErrorAction SilentlyContinue | Out-String -Stream -ErrorAction SilentlyContinue | Write-Host -ErrorAction SilentlyContinue
39+
}
40+
41+
$dockerExitCode = $LASTEXITCODE
42+
if($PassThru.IsPresent)
43+
{
44+
Write-Verbose "passing through docker result$($result.length)..." -Verbose
45+
return $result
46+
}
47+
elseif($dockerExitCode -ne 0 -and $FailureAction -eq 'error')
48+
{
49+
Write-Error "docker $command failed with: $result" -ErrorAction Stop
50+
return $false
51+
}
52+
elseif($dockerExitCode -ne 0 -and $FailureAction -eq 'warning')
53+
{
54+
Write-Warning "docker $command failed with: $result"
55+
return $false
56+
}
57+
elseif($dockerExitCode -ne 0)
58+
{
59+
return $false
60+
}
61+
62+
return $true
63+
}
64+
65+
# Return a list of Linux Container Test Cases
66+
function Get-LinuxContainer
67+
{
68+
foreach($os in 'centos7','opensuse42.1','ubuntu14.04','ubuntu16.04')
69+
{
70+
Write-Output @{
71+
Name = $os
72+
Path = "$psscriptroot/../release/$os"
73+
}
74+
}
75+
76+
}
77+
78+
# Return a list of Windows Container Test Cases
79+
function Get-WindowsContainer
80+
{
81+
foreach($os in 'windowsservercore','nanoserver')
82+
{
83+
Write-Output @{
84+
Name = $os
85+
Path = "$psscriptroot/../release/$os"
86+
}
87+
}
88+
}
89+
90+
91+
$script:repoName = 'microsoft/powershell'
92+
function Get-RepoName
93+
{
94+
return $script:repoName
95+
}
96+
97+
function Set-RepoName
98+
{
99+
param([string]$RepoName)
100+
101+
$script:repoName = $RepoName
102+
$script:forcePull = $false
103+
}
104+
105+
function Test-SkipWindows
106+
{
107+
[bool] $canRunWindows = (Get-DockerEngineOs) -like 'Windows*'
108+
return ($IsLinux -or $IsOSX -or !$canRunWindows)
109+
}
110+
111+
function Test-SkipLinux
112+
{
113+
return !((Get-DockerEngineOs) -like 'Alpine Linux*')
114+
}
115+
116+
function Get-TestContext
117+
{
118+
param(
119+
[ValidateSet('Linux','Windows','macOS')]
120+
[string]$Type
121+
)
122+
123+
$resultFileName = 'results.xml'
124+
$logFileName = 'results.log'
125+
$containerTestDrive = '/test'
126+
127+
# Return a windows context if the Context in Windows *AND*
128+
# the current system is windows, otherwise Join-path will fail.
129+
if($Type -eq 'Windows' -and $IsWindows)
130+
{
131+
$ContainerTestDrive = 'C:\test'
132+
}
133+
$resolvedTestDrive = (Resolve-Path "Testdrive:\").providerPath
134+
135+
return @{
136+
ResolvedTestDrive = $resolvedTestDrive
137+
ResolvedXmlPath = Join-Path $resolvedTestDrive -ChildPath $resultFileName
138+
ResolvedLogPath = Join-Path $resolvedTestDrive -ChildPath $logFileName
139+
ContainerTestDrive = $ContainerTestDrive
140+
ContainerXmlPath = Join-Path $containerTestDrive -ChildPath $resultFileName
141+
ContainerLogPath = Join-Path $containerTestDrive -ChildPath $logFileName
142+
Type = $Type
143+
ForcePull = $script:forcePull
144+
}
145+
}
146+
147+
function Get-ContainerPowerShellVersion
148+
{
149+
param(
150+
[HashTable] $TestContext,
151+
[string] $RepoName,
152+
[string] $Name
153+
)
154+
155+
$imageTag = "${script:repoName}:${Name}"
156+
157+
if($TestContext.ForcePull)
158+
{
159+
$null=Invoke-Docker -Command 'image', 'pull' -Params $imageTag -SuppressHostOutput
160+
}
161+
162+
$runParams = @()
163+
$localVolumeName = $testContext.resolvedTestDrive
164+
$runParams += '--rm'
165+
if($TestContext.Type -ne 'Windows' -and $isWindows)
166+
{
167+
# use a container volume on windows because host volumes are not automatic
168+
$volumeName = "test-volume-" + (Get-Random -Minimum 100 -Maximum 999)
169+
170+
# using alpine because it's tiny
171+
$null=Invoke-Docker -Command create -Params '-v', '/test', '--name', $volumeName, 'alpine' -SuppressHostOutput
172+
$runParams += '--volumes-from'
173+
$runParams += $volumeName
174+
}
175+
else {
176+
$runParams += '-v'
177+
$runParams += "${localVolumeName}:$($testContext.containerTestDrive)"
178+
}
179+
180+
$runParams += $imageTag
181+
$runParams += 'powershell'
182+
$runParams += '-c'
183+
$runParams += ('$PSVersionTable.PSVersion.ToString() | out-string | out-file -encoding ascii -FilePath '+$testContext.containerLogPath)
184+
185+
$null = Invoke-Docker -Command run -Params $runParams -SuppressHostOutput
186+
if($TestContext.Type -ne 'Windows' -and $isWindows)
187+
{
188+
$null = Invoke-Docker -Command cp -Params "${volumeName}:$($testContext.containerLogPath)", $TestContext.ResolvedLogPath
189+
$null = Invoke-Docker -Command container, rm -Params $volumeName, '--force' -SuppressHostOutput
190+
}
191+
return (Get-Content -Encoding Ascii $testContext.resolvedLogPath)[0]
192+
}

0 commit comments

Comments
 (0)