Skip to content
This repository was archived by the owner on Nov 27, 2023. It is now read-only.

Commit 3ad1e69

Browse files
authored
Merge pull request #198 from docker/windows_e2e
Windows e2e tests
2 parents 93623dc + 93984f8 commit 3ad1e69

File tree

10 files changed

+229
-89
lines changed

10 files changed

+229
-89
lines changed

.gitattributes

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
core.autocrlf false
2+
*.golden text eol=lf

.github/workflows/ci.yml

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121
- name: Run golangci-lint
2222
run: |
2323
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b . v1.27.0
24-
./golangci-lint run
24+
./golangci-lint run --timeout 10m0s
2525
2626
build:
2727
name: Build
@@ -62,3 +62,34 @@ jobs:
6262

6363
- name: E2E Test
6464
run: make e2e-local
65+
66+
windows-build:
67+
name: Windows Build
68+
runs-on: windows-latest
69+
env:
70+
GO111MODULE: "on"
71+
steps:
72+
- name: Set up Go 1.14
73+
uses: actions/setup-go@v1
74+
with:
75+
go-version: 1.14
76+
id: go
77+
78+
- name: Checkout code into the Go module directory
79+
uses: actions/checkout@v2
80+
81+
- uses: actions/cache@v1
82+
with:
83+
path: ~/go/pkg/mod
84+
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
85+
restore-keys: |
86+
${{ runner.os }}-go-
87+
88+
- name: Test
89+
run: make -f builder.Makefile test
90+
91+
- name: Build
92+
run: make -f builder.Makefile cli
93+
94+
- name: E2E Test
95+
run: make e2e-win-ci

Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,10 @@ cli: ## Compile the cli
3737
--output ./bin
3838

3939
e2e-local: ## Run End to end local tests
40-
go test -v ./tests/e2e ./moby/e2e
40+
go test -v ./tests/e2e ./tests/skip-win-ci-e2e ./moby/e2e
41+
42+
e2e-win-ci: ## Run End to end local tests on windows CI, no docker for linux containers available ATM
43+
go test -v ./tests/e2e
4144

4245
e2e-aci: ## Run End to end ACI tests (requires azure login)
4346
go test -v ./tests/aci-e2e

azure/convert/volume.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package convert
33
import (
44
"fmt"
55
"net/url"
6-
"path/filepath"
76
"strings"
87

98
"github.com/pkg/errors"
@@ -113,7 +112,8 @@ func (v *volumeInput) parse(name string, s string) error {
113112
v.name = name
114113
v.target = volumeURL.Path
115114
if v.target == "" {
116-
v.target = filepath.Join("/run/volumes/", v.share)
115+
// Do not use filepath.Join, on Windows it will replace / by \
116+
v.target = "/run/volumes/" + v.share
117117
}
118118
return nil
119119
}

tests/e2e/e2e_test.go

Lines changed: 4 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -28,13 +28,8 @@
2828
package main
2929

3030
import (
31-
"fmt"
32-
"io/ioutil"
33-
"log"
3431
"os"
35-
"os/exec"
3632
"path/filepath"
37-
"strings"
3833
"testing"
3934
"time"
4035

@@ -65,7 +60,7 @@ func (s *E2eSuite) TestContextDefault() {
6560
output := s.NewDockerCommand("context", "show").ExecOrDie()
6661
Expect(output).To(ContainSubstring("default"))
6762
output = s.NewCommand("docker", "context", "ls").ExecOrDie()
68-
golden.Assert(s.T(), output, "ls-out-default.golden")
63+
golden.Assert(s.T(), output, GoldenFile("ls-out-default"))
6964
})
7065
}
7166

@@ -106,7 +101,7 @@ func (s *E2eSuite) TestSetupError() {
106101
It("should display an error if cannot shell out to docker-classic", func() {
107102
err := os.Setenv("PATH", s.BinDir)
108103
Expect(err).To(BeNil())
109-
err = os.Remove(filepath.Join(s.BinDir, "docker-classic"))
104+
err = os.Remove(filepath.Join(s.BinDir, DockerClassicExecutable()))
110105
Expect(err).To(BeNil())
111106
output, err := s.NewDockerCommand("ps").Exec()
112107
Expect(output).To(ContainSubstring("docker-classic"))
@@ -115,37 +110,6 @@ func (s *E2eSuite) TestSetupError() {
115110
})
116111
}
117112

118-
func (s *E2eSuite) TestKillChildOnCancel() {
119-
It("should kill docker-classic if parent command is cancelled", func() {
120-
out := s.ListProcessesCommand().ExecOrDie()
121-
Expect(out).NotTo(ContainSubstring("docker-classic"))
122-
123-
dir := s.ConfigDir
124-
Expect(ioutil.WriteFile(filepath.Join(dir, "Dockerfile"), []byte(`FROM alpine:3.10
125-
RUN sleep 100`), 0644)).To(Succeed())
126-
shutdown := make(chan time.Time)
127-
errs := make(chan error)
128-
ctx := s.NewDockerCommand("build", "--no-cache", "-t", "test-sleep-image", ".").WithinDirectory(dir).WithTimeout(shutdown)
129-
go func() {
130-
_, err := ctx.Exec()
131-
errs <- err
132-
}()
133-
err := WaitFor(time.Second, 10*time.Second, errs, func() bool {
134-
out := s.ListProcessesCommand().ExecOrDie()
135-
return strings.Contains(out, "docker-classic")
136-
})
137-
Expect(err).NotTo(HaveOccurred())
138-
log.Println("Killing docker process")
139-
140-
close(shutdown)
141-
err = WaitFor(time.Second, 12*time.Second, nil, func() bool {
142-
out := s.ListProcessesCommand().ExecOrDie()
143-
return !strings.Contains(out, "docker-classic")
144-
})
145-
Expect(err).NotTo(HaveOccurred())
146-
})
147-
}
148-
149113
func (s *E2eSuite) TestLegacy() {
150114
It("should list all legacy commands", func() {
151115
output := s.NewDockerCommand("--help").ExecOrDie()
@@ -159,7 +123,7 @@ func (s *E2eSuite) TestLegacy() {
159123

160124
It("should run local container in less than 10 secs", func() {
161125
s.NewDockerCommand("pull", "hello-world").ExecOrDie()
162-
output := s.NewDockerCommand("run", "--rm", "hello-world").WithTimeout(time.NewTimer(10 * time.Second).C).ExecOrDie()
126+
output := s.NewDockerCommand("run", "--rm", "hello-world").WithTimeout(time.NewTimer(20 * time.Second).C).ExecOrDie()
163127
Expect(output).To(ContainSubstring("Hello from Docker!"))
164128
})
165129
}
@@ -187,7 +151,7 @@ func (s *E2eSuite) TestMockBackend() {
187151
currentContext := s.NewDockerCommand("context", "use", "test-example").ExecOrDie()
188152
Expect(currentContext).To(ContainSubstring("test-example"))
189153
output := s.NewDockerCommand("context", "ls").ExecOrDie()
190-
golden.Assert(s.T(), output, "ls-out-test-example.golden")
154+
golden.Assert(s.T(), output, GoldenFile("ls-out-test-example"))
191155
output = s.NewDockerCommand("context", "show").ExecOrDie()
192156
Expect(output).To(ContainSubstring("test-example"))
193157
})
@@ -222,40 +186,6 @@ func (s *E2eSuite) TestMockBackend() {
222186
})
223187
}
224188

225-
func (s *E2eSuite) TestAPIServer() {
226-
_, err := exec.LookPath("yarn")
227-
if err != nil || os.Getenv("SKIP_NODE") != "" {
228-
s.T().Skip("skipping, yarn not installed")
229-
}
230-
It("can run 'serve' command", func() {
231-
cName := "test-example"
232-
s.NewDockerCommand("context", "create", cName, "example").ExecOrDie()
233-
234-
sPath := fmt.Sprintf("unix:///%s/docker.sock", s.ConfigDir)
235-
server, err := serveAPI(s.ConfigDir, sPath)
236-
Expect(err).To(BeNil())
237-
defer killProcess(server)
238-
239-
s.NewCommand("yarn", "install").WithinDirectory("../node-client").ExecOrDie()
240-
output := s.NewCommand("yarn", "run", "start", cName, sPath).WithinDirectory("../node-client").ExecOrDie()
241-
Expect(output).To(ContainSubstring("nginx"))
242-
})
243-
}
244-
245189
func TestE2e(t *testing.T) {
246190
suite.Run(t, new(E2eSuite))
247191
}
248-
249-
func killProcess(process *os.Process) {
250-
err := process.Kill()
251-
Expect(err).To(BeNil())
252-
}
253-
254-
func serveAPI(configDir string, address string) (*os.Process, error) {
255-
cmd := exec.Command("../../bin/docker", "--config", configDir, "serve", "--address", address)
256-
err := cmd.Start()
257-
if err != nil {
258-
return nil, err
259-
}
260-
return cmd.Process, nil
261-
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
NAME TYPE DESCRIPTION DOCKER ENPOINT KUBERNETES ENDPOINT ORCHESTRATOR
2+
default * docker Current DOCKER_HOST based configuration npipe:////./pipe/docker_engine swarm
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
NAME TYPE DESCRIPTION DOCKER ENPOINT KUBERNETES ENDPOINT ORCHESTRATOR
2+
default docker Current DOCKER_HOST based configuration npipe:////./pipe/docker_engine swarm
3+
test-example * example

tests/framework/helper.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
package framework
2929

3030
import (
31+
"runtime"
3132
"strings"
3233

3334
"github.com/robpike/filter"
@@ -48,6 +49,19 @@ func Columns(line string) []string {
4849
return filter.Choose(strings.Split(line, " "), nonEmptyString).([]string)
4950
}
5051

52+
// GoldenFile golden file specific to platform
53+
func GoldenFile(name string) string {
54+
if IsWindows() {
55+
return name + "-windows.golden"
56+
}
57+
return name + ".golden"
58+
}
59+
60+
// IsWindows windows or other GOOS
61+
func IsWindows() bool {
62+
return runtime.GOOS == "windows"
63+
}
64+
5165
// It runs func
5266
func It(description string, test func()) {
5367
test()

tests/framework/suite.go

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ import (
3333
"os"
3434
"os/exec"
3535
"path/filepath"
36-
"runtime"
3736
"time"
3837

3938
"github.com/onsi/gomega"
@@ -56,13 +55,14 @@ func (s *Suite) SetupSuite() {
5655
log.Error(message)
5756
cp := filepath.Join(s.ConfigDir, "config.json")
5857
d, _ := ioutil.ReadFile(cp)
58+
fmt.Printf("Bin dir:%s\n", s.BinDir)
5959
fmt.Printf("Contents of %s:\n%s\n\nContents of config dir:\n", cp, string(d))
6060
for _, p := range dirContents(s.ConfigDir) {
6161
fmt.Println(p)
6262
}
6363
s.T().Fail()
6464
})
65-
s.linkClassicDocker()
65+
s.copyExecutablesInBinDir()
6666
}
6767

6868
// TearDownSuite is run after all tests
@@ -79,22 +79,42 @@ func dirContents(dir string) []string {
7979
return res
8080
}
8181

82-
func (s *Suite) linkClassicDocker() {
83-
p, err := exec.LookPath("docker-classic")
82+
func (s *Suite) copyExecutablesInBinDir() {
83+
p, err := exec.LookPath(DockerClassicExecutable())
8484
if err != nil {
85-
p, err = exec.LookPath("docker")
85+
p, err = exec.LookPath(dockerExecutable())
8686
}
8787
gomega.Expect(err).To(gomega.BeNil())
88-
err = os.Symlink(p, filepath.Join(s.BinDir, "docker-classic"))
88+
err = copyFile(p, filepath.Join(s.BinDir, DockerClassicExecutable()))
8989
gomega.Expect(err).To(gomega.BeNil())
90-
dockerPath, err := filepath.Abs("../../bin/docker")
90+
dockerPath, err := filepath.Abs("../../bin/" + dockerExecutable())
9191
gomega.Expect(err).To(gomega.BeNil())
92-
err = os.Symlink(dockerPath, filepath.Join(s.BinDir, "docker"))
92+
err = copyFile(dockerPath, filepath.Join(s.BinDir, dockerExecutable()))
9393
gomega.Expect(err).To(gomega.BeNil())
94-
err = os.Setenv("PATH", fmt.Sprintf("%s:%s", s.BinDir, os.Getenv("PATH")))
94+
err = os.Setenv("PATH", concatenatePath(s.BinDir))
9595
gomega.Expect(err).To(gomega.BeNil())
9696
}
9797

98+
func concatenatePath(path string) string {
99+
if IsWindows() {
100+
return fmt.Sprintf("%s;%s", path, os.Getenv("PATH"))
101+
}
102+
return fmt.Sprintf("%s:%s", path, os.Getenv("PATH"))
103+
}
104+
105+
func copyFile(sourceFile string, destinationFile string) error {
106+
input, err := ioutil.ReadFile(sourceFile)
107+
if err != nil {
108+
return err
109+
}
110+
111+
err = ioutil.WriteFile(destinationFile, input, 0777)
112+
if err != nil {
113+
return err
114+
}
115+
return nil
116+
}
117+
98118
// BeforeTest is run before each test
99119
func (s *Suite) BeforeTest(suite, test string) {
100120
d, _ := ioutil.TempDir("", "")
@@ -109,7 +129,7 @@ func (s *Suite) AfterTest(suite, test string) {
109129

110130
// ListProcessesCommand creates a command to list processes, "tasklist" on windows, "ps" otherwise.
111131
func (s *Suite) ListProcessesCommand() *CmdContext {
112-
if runtime.GOOS == "windows" {
132+
if IsWindows() {
113133
return s.NewCommand("tasklist")
114134
}
115135
return s.NewCommand("ps")
@@ -125,12 +145,20 @@ func (s *Suite) NewCommand(command string, args ...string) *CmdContext {
125145
}
126146

127147
func dockerExecutable() string {
128-
if runtime.GOOS == "windows" {
148+
if IsWindows() {
129149
return "docker.exe"
130150
}
131151
return "docker"
132152
}
133153

154+
// DockerClassicExecutable binary name based on platform
155+
func DockerClassicExecutable() string {
156+
if IsWindows() {
157+
return "docker-classic.exe"
158+
}
159+
return "docker-classic"
160+
}
161+
134162
// NewDockerCommand creates a docker builder.
135163
func (s *Suite) NewDockerCommand(args ...string) *CmdContext {
136164
return s.NewCommand(dockerExecutable(), args...)

0 commit comments

Comments
 (0)