Skip to content

Commit b24f531

Browse files
author
Adrian Cole
committed
Runs e2e directly instead of via ginkgo
Signed-off-by: Adrian Cole <[email protected]>
1 parent 19e7d9f commit b24f531

16 files changed

+591
-756
lines changed

.github/workflows/commit.yaml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ on:
1818

1919
jobs:
2020
bin:
21-
name: "Build `getenvoy` and `e2e` binaries for use in e2e tests"
21+
name: "Build the `getenvoy` binary for use in e2e tests"
2222
runs-on: ubuntu-latest
2323
timeout-minutes: 15 # instead of 360 by default
2424
steps:
@@ -33,10 +33,10 @@ jobs:
3333
- name: "Init on first use"
3434
run: make init
3535

36-
- name: "Build `getenvoy` and `e2e` binaries"
36+
- name: "Build the `getenvoy` binary"
3737
run: make bin
3838

39-
- name: "Share `getenvoy` and `e2e` binaries with the downstream jobs"
39+
- name: "Share the `getenvoy` binary with the downstream jobs"
4040
uses: actions/upload-artifact@v2
4141
with:
4242
name: bin
@@ -52,7 +52,7 @@ jobs:
5252
- name: "Checkout"
5353
uses: actions/checkout@v2
5454

55-
- name: "Re-use `getenvoy` and `e2e` binaries pre-built by the upstream job"
55+
- name: "Re-use the `getenvoy` binary pre-built by the upstream job"
5656
uses: actions/download-artifact@v2
5757
with:
5858
name: bin
@@ -61,7 +61,7 @@ jobs:
6161
- name: "Build language-specific Docker build images"
6262
run: make builders
6363

64-
- name: "Run e2e tests using `getenvoy` and `e2e` binaries built by the upstream job"
64+
- name: "Run e2e tests using the `getenvoy` binary built by the upstream job"
6565
run: ./ci/e2e/linux/run_tests.sh
6666

6767
e2e_macos:
@@ -74,7 +74,7 @@ jobs:
7474
- name: "Checkout"
7575
uses: actions/checkout@v2
7676

77-
- name: "Re-use `getenvoy` and `e2e` binaries pre-built by the upstream job"
77+
- name: "Re-use the `getenvoy` binary pre-built by the upstream job"
7878
uses: actions/download-artifact@v2
7979
with:
8080
name: bin
@@ -92,5 +92,5 @@ jobs:
9292
run: make builders
9393
timeout-minutes: 10 # fail fast if MacOS runner becomes to slow
9494

95-
- name: "Run e2e tests using `getenvoy` and `e2e` binaries built by the upstream job"
95+
- name: "Run e2e tests using the `getenvoy` binary built by the upstream job"
9696
run: ./ci/e2e/macos/run_tests.sh

.github/workflows/release.yaml

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -71,33 +71,11 @@ jobs:
7171
- name: "Push extension builder images"
7272
run: make builders.push BUILDERS_TAG=${{ env.RELEASE_VERSION }}
7373

74-
e2e_bin:
75-
name: "Build `e2e` binaries for use in e2e tests"
76-
runs-on: ubuntu-latest
77-
steps:
78-
- name: "Checkout"
79-
uses: actions/checkout@v2
80-
81-
- name: "Install Go"
82-
uses: actions/setup-go@v2
83-
with:
84-
go-version: '1.16.2'
85-
86-
- name: "Build `e2e` binaries"
87-
run: make build/bin/linux/amd64/e2e build/bin/darwin/amd64/e2e
88-
89-
- name: "Share `e2e` binaries with the downstream jobs"
90-
uses: actions/upload-artifact@v2
91-
with:
92-
name: bin
93-
path: build/bin
94-
9574
e2e_linux:
9675
name: "Run e2e tests on Linux"
9776
needs:
9877
- getenvoy
9978
- builders
100-
- e2e_bin
10179
runs-on: ubuntu-latest
10280
timeout-minutes: 30 # instead of 360 by default
10381
steps:
@@ -138,7 +116,6 @@ jobs:
138116
needs:
139117
- getenvoy
140118
- builders
141-
- e2e_bin
142119
runs-on: macos-latest
143120
timeout-minutes: 90 # instead of 360 by default
144121
steps:

Makefile

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ COVERAGE_PKG_LIST ?= $(shell go list ./pkg/... | grep -v -e github.com/tetratela
5353
GO_COVERAGE_OPTS ?= -covermode=atomic -coverpkg=./...
5454
GO_COVERAGE_EXTRA_OPTS ?=
5555

56-
E2E_OPTS ?= -ginkgo.v
56+
E2E_PKG_LIST ?= ./test/e2e/...
57+
E2E_OPTS ?= -test.parallel 1 -test.failfast
5758
E2E_EXTRA_OPTS ?=
5859

5960
GOOSES := linux darwin
@@ -68,15 +69,6 @@ $(call GETENVOY_OUT_PATH,$(1),$(2)): generate
6869
endef
6970
$(foreach os,$(GOOSES),$(foreach arch,$(GOARCHS),$(eval $(call GEN_GETENVOY_BUILD_TARGET,$(os),$(arch)))))
7071

71-
E2E_OUT_PATH = $(BIN_DIR)/$(1)/$(2)/e2e
72-
73-
define GEN_E2E_BUILD_TARGET
74-
.PHONY: $(call E2E_OUT_PATH,$(1),$(2))
75-
$(call E2E_OUT_PATH,$(1),$(2)):
76-
CGO_ENABLED=0 GOOS=$(1) GOARCH=$(2) go test -c -o $(call E2E_OUT_PATH,$(1),$(2)) ./test/e2e
77-
endef
78-
$(foreach os,$(GOOSES),$(foreach arch,$(GOARCHS),$(eval $(call GEN_E2E_BUILD_TARGET,$(os),$(arch)))))
79-
8072
.PHONY: init
8173
init: generate
8274

@@ -109,9 +101,9 @@ test.ci: generate
109101
go test $(GO_TEST_OPTS) $(GO_TEST_EXTRA_OPTS) $(TEST_PKG_LIST)
110102

111103
.PHONY: e2e
112-
e2e: $(call GETENVOY_OUT_PATH,$(GOOS),$(GOARCH)) $(call E2E_OUT_PATH,$(GOOS),$(GOARCH))
104+
e2e: $(call GETENVOY_OUT_PATH,$(GOOS),$(GOARCH))
113105
docker-compose up -d
114-
E2E_GETENVOY_BINARY=$(PWD)/$(call GETENVOY_OUT_PATH,$(GOOS),$(GOARCH)) $(call E2E_OUT_PATH,$(GOOS),$(GOARCH)) $(GO_TEST_OPTS) $(GO_TEST_EXTRA_OPTS) $(E2E_OPTS) $(E2E_EXTRA_OPTS)
106+
E2E_GETENVOY_BINARY=$(PWD)/$(call GETENVOY_OUT_PATH,$(GOOS),$(GOARCH)) go test github.com/tetratelabs/getenvoy/test/e2e $(E2E_OPTS) $(E2E_EXTRA_OPTS) $(E2E_PKG_LIST)
115107

116108
.PHONY: bin
117109
bin: $(foreach os,$(GOOSES), bin/$(os))
@@ -124,7 +116,7 @@ $(foreach os,$(GOOSES),$(eval $(call GEN_BIN_GOOS_TARGET,$(os))))
124116

125117
define GEN_BIN_GOOS_GOARCH_TARGET
126118
.PHONY: bin/$(1)/$(2)
127-
bin/$(1)/$(2): $(call GETENVOY_OUT_PATH,$(1),$(2)) $(call E2E_OUT_PATH,$(1),$(2))
119+
bin/$(1)/$(2): $(call GETENVOY_OUT_PATH,$(1),$(2))
128120
endef
129121
$(foreach os,$(GOOSES),$(foreach arch,$(GOARCHS),$(eval $(call GEN_BIN_GOOS_GOARCH_TARGET,$(os),$(arch)))))
130122

ci/e2e/linux/run_tests.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,5 @@ docker-compose up -d
3838
# run e2e tests on a `getenvoy` binary built by the upstream job
3939
export E2E_GETENVOY_BINARY="${WORKSPACE_DIR}/build/bin/linux/amd64/getenvoy"
4040

41-
# run e2e tests with '-ginkgo.v' flag to be able to see the progress
42-
${WORKSPACE_DIR}/build/bin/linux/amd64/e2e -ginkgo.v
41+
# run e2e tests with '-v' flag to be able to see the progress
42+
go test github.com/tetratelabs/getenvoy/test/e2e -test.parallel 1 -test.failfast -v ./test/e2e/...

ci/e2e/macos/run_tests.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,4 +41,4 @@ docker-compose up -d
4141
export E2E_GETENVOY_BINARY="${WORKSPACE_DIR}/build/bin/darwin/amd64/getenvoy"
4242

4343
# run e2e tests with '-ginkgo.v' flag to be able to see the progress
44-
${WORKSPACE_DIR}/build/bin/darwin/amd64/e2e -ginkgo.v
44+
go test github.com/tetratelabs/getenvoy/test/e2e -test.parallel 1 -test.failfast -v ./test/e2e/...

test/e2e/e2e_suite_test.go

Lines changed: 0 additions & 67 deletions
This file was deleted.

test/e2e/e2e_test.go

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
// Copyright 2021 Tetrate
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package e2e_test
16+
17+
import (
18+
"io/ioutil"
19+
"os"
20+
"path/filepath"
21+
"regexp"
22+
"testing"
23+
24+
"github.com/stretchr/testify/require"
25+
"github.com/tetratelabs/log"
26+
27+
"github.com/tetratelabs/getenvoy/pkg/extension/workspace/config/extension"
28+
e2e "github.com/tetratelabs/getenvoy/test/e2e/util"
29+
)
30+
31+
var (
32+
// GetEnvoy is a convenient alias.
33+
GetEnvoy = e2e.GetEnvoy
34+
)
35+
36+
// stripAnsiEscapeRegexp is a regular expression to clean ANSI Control sequences
37+
// feat https://stackoverflow.com/questions/14693701/how-can-i-remove-the-ansi-escape-sequences-from-a-string-in-python#33925425
38+
var stripAnsiEscapeRegexp = regexp.MustCompile(`(\x9B|\x1B\[)[0-?]*[ -/]*[@-~]`)
39+
40+
func requireEnvoyBinaryPath(t *testing.T) {
41+
path, err := e2e.Env.GetEnvoyBinary()
42+
require.NoError(t, err, `error reading path to getenvoy binary`)
43+
e2e.GetEnvoyBinaryPath = path
44+
}
45+
46+
// requireNewTempDir creates a new directory. The function returned cleans it up.
47+
func requireNewTempDir(t *testing.T) (string, func()) {
48+
d, err := ioutil.TempDir("", "")
49+
if err != nil {
50+
require.NoError(t, err, `ioutil.TempDir("", "") erred`)
51+
}
52+
dir := requireAbsDir(t, d)
53+
return dir, func() {
54+
e := os.RemoveAll(dir)
55+
require.NoError(t, e, `error removing directory: %v`, dir)
56+
}
57+
}
58+
59+
// RequireChDir will os.Chdir into the indicated dir, panicing on any problem.
60+
// The function returned reverts to the original.
61+
func requireChDir(t *testing.T, d string) func() {
62+
// Save previous working directory to that it can be reverted later.
63+
previous, err := os.Getwd()
64+
require.NoError(t, err, `error determining current directory`)
65+
66+
// Now, actually change to the directory.
67+
err = os.Chdir(d)
68+
require.NoError(t, err, `error changing to directory: %v`, d)
69+
return func() {
70+
e := os.Chdir(previous)
71+
require.NoError(t, e, `error changing to directory: %v`, previous)
72+
}
73+
}
74+
75+
// requireAbsDir runs filepath.Abs and ensures there are no errors and the input is a directory.
76+
func requireAbsDir(t *testing.T, d string) string {
77+
dir, err := filepath.Abs(d)
78+
require.NoError(t, err, `error determining absolute directory: %v`, d)
79+
require.DirExists(t, dir, `directory doesn't exist': %v`, dir)
80+
dir, err = filepath.EvalSymlinks(dir)
81+
require.NoError(t, err, `filepath.EvalSymlinks(%s) erred`, dir)
82+
require.NotEmpty(t, dir, `filepath.EvalSymlinks(%s) returned ""`)
83+
return dir
84+
}
85+
86+
// Command gives us an interface needed for testing GetEnvoy
87+
type Command interface {
88+
Exec() (string, string, error)
89+
}
90+
91+
// requireExecNoStdout invokes the command and returns its stderr if successful and stdout is empty.
92+
func requireExecNoStdout(t *testing.T, cmd Command) string {
93+
stdout, stderr := requireExec(t, cmd)
94+
require.Empty(t, stdout, `expected no stdout running [%v]`, cmd)
95+
require.NotEmpty(t, stderr, `expected stderr running [%v]`, cmd)
96+
return stderr
97+
}
98+
99+
// requireExecNoStderr invokes the command and returns its stdout if successful and stderr is empty.
100+
func requireExecNoStderr(t *testing.T, cmd Command) string {
101+
stdout, stderr := requireExec(t, cmd)
102+
require.NotEmpty(t, stdout, `expected stdout running [%v]`, cmd)
103+
require.Empty(t, stderr, `expected no stderr running [%v]`, cmd)
104+
return stdout
105+
}
106+
107+
// requireExec invokes the command and returns its (stdout, stderr) if successful.
108+
func requireExec(t *testing.T, cmd Command) (string, string) {
109+
log.Infof(`running [%v]`, cmd)
110+
stdout, stderr, err := cmd.Exec()
111+
112+
require.NoError(t, err, `error running [%v]`, cmd)
113+
return stdout, stderr
114+
}
115+
116+
// requireExtensionInit is useful for tests that depend on "getenvoy extension init" as a prerequisite.
117+
func requireExtensionInit(t *testing.T, workDir string, category extension.Category, language extension.Language, name string) {
118+
cmd := GetEnvoy("extension init").
119+
Arg(workDir).
120+
Arg("--category").Arg(string(category)).
121+
Arg("--language").Arg(string(language)).
122+
Arg("--name").Arg(name)
123+
// stderr returned is not tested because doing so is redundant to TestGetEnvoyExtensionInit.
124+
_ = requireExecNoStdout(t, cmd)
125+
}
126+
127+
// extensionWasmPath returns the language-specific location of the extension.wasm.
128+
func extensionWasmPath(language extension.Language) string {
129+
switch language {
130+
case extension.LanguageRust:
131+
return filepath.Join("target", "getenvoy", "extension.wasm")
132+
case extension.LanguageTinyGo:
133+
return filepath.Join("build", "extension.wasm")
134+
}
135+
panic("unsupported language " + language)
136+
}
137+
138+
// requireExtensionInit is useful for tests that depend on "getenvoy extension build" as a prerequisite.
139+
// The result of calling this is the bytes representing the built wasm
140+
func requireExtensionBuild(t *testing.T, language extension.Language, workDir string) []byte {
141+
cmd := GetEnvoy("extension build").Args(e2e.Env.GetBuiltinContainerOptions()...)
142+
// stderr returned is not tested because doing so is redundant to TestGetEnvoyExtensionInit.
143+
_ = requireExecNoStderr(t, cmd)
144+
145+
extensionWasmFile := filepath.Join(workDir, extensionWasmPath(language))
146+
require.FileExists(t, extensionWasmFile, `extension wasm file %s missing after running [%v]`, extensionWasmFile, cmd)
147+
148+
wasmBytes, err := ioutil.ReadFile(extensionWasmFile)
149+
require.NoError(t, err, `error reading %s after running [%v]: %s`, extensionWasmFile, cmd)
150+
require.NotEmpty(t, wasmBytes, `%s empty after running [%v]`, extensionWasmFile, cmd)
151+
return wasmBytes
152+
}
153+
154+
// requireExtensionClean is useful for tests that depend on "getenvoy extension clean" on completion.
155+
// (stdout, stderr) returned are not tested because they can both be empty.
156+
func requireExtensionClean(t *testing.T, workDir string) {
157+
err := os.Chdir(workDir)
158+
require.NoError(t, err, `error changing to directory: %v`, workDir)
159+
160+
cmd := GetEnvoy("extension clean")
161+
_, _ = requireExec(t, cmd)
162+
}

0 commit comments

Comments
 (0)