Fix build break in test

integration_test runs manually and breakage wasn't detected. Added test to
kokoro to ensure breakages are detected in the future.

PiperOrigin-RevId: 207772835
Change-Id: Iada81b579b558477d4db3516b38366ef6a2e933d
This commit is contained in:
Fabricio Voznika
2018-08-07 13:48:35 -07:00
committed by Shentubot
parent c036da5dff
commit cb23232c37
7 changed files with 155 additions and 95 deletions
+6 -2
View File
@@ -44,10 +44,14 @@ bazel test --test_output=errors //...
exit_code=${?}
if [[ ${exit_code} -eq 0 ]]; then
# These names are used to exclude tests not supported in certain
# configuration, e.g. save/restore not supported with hostnet.
declare -a variations=("" "-kvm" "-hostnet" "-overlay")
for v in "${variations[@]}"; do
# image_test is tagged manual
bazel test --test_output=errors --test_env=RUNSC_RUNTIME=${runtime}${v} //runsc/test/image:image_test
# Run runsc tests with docker that are tagged manual.
bazel test --test_output=errors --test_env=RUNSC_RUNTIME=${runtime}${v} \
//runsc/test/image:image_test \
//runsc/test/integration:integration_test
exit_code=${?}
if [[ ${exit_code} -ne 0 ]]; then
break
+20 -20
View File
@@ -39,8 +39,8 @@ import (
func TestHelloWorld(t *testing.T) {
d := testutil.MakeDocker("hello-test")
if out, err := d.Run("hello-world"); err != nil {
t.Fatalf("docker run failed: %v\nout: %s", err, out)
if _, err := d.Run("hello-world"); err != nil {
t.Fatalf("docker run failed: %v", err)
}
defer d.CleanUp()
@@ -82,8 +82,8 @@ func testHTTPServer(port int) error {
}
func TestHttpd(t *testing.T) {
if out, err := testutil.Pull("httpd"); err != nil {
t.Fatalf("docker pull failed: %v\nout: %s", err, out)
if err := testutil.Pull("httpd"); err != nil {
t.Fatalf("docker pull failed: %v", err)
}
d := testutil.MakeDocker("http-test")
@@ -93,8 +93,8 @@ func TestHttpd(t *testing.T) {
}
// Start the container.
if out, err := d.Run("-p", "80", "-v", testutil.MountArg(dir, "/usr/local/apache2/htdocs:ro"), "httpd"); err != nil {
t.Fatalf("docker run failed: %v\nout: %s", err, out)
if _, err := d.Run("-p", "80", "-v", testutil.MountArg(dir, "/usr/local/apache2/htdocs:ro"), "httpd"); err != nil {
t.Fatalf("docker run failed: %v", err)
}
defer d.CleanUp()
@@ -105,8 +105,8 @@ func TestHttpd(t *testing.T) {
}
// Wait until it's up and running.
if err := d.WaitForHTTP(port, 5*time.Second); err != nil {
t.Fatalf("docker.WaitForHTTP() timeout: %v", err)
if err := testutil.WaitForHTTP(port, 5*time.Second); err != nil {
t.Fatalf("WaitForHTTP() timeout: %v", err)
}
if err := testHTTPServer(port); err != nil {
@@ -115,8 +115,8 @@ func TestHttpd(t *testing.T) {
}
func TestNginx(t *testing.T) {
if out, err := testutil.Pull("nginx"); err != nil {
t.Fatalf("docker pull failed: %v\nout: %s", err, out)
if err := testutil.Pull("nginx"); err != nil {
t.Fatalf("docker pull failed: %v", err)
}
d := testutil.MakeDocker("net-test")
@@ -126,8 +126,8 @@ func TestNginx(t *testing.T) {
}
// Start the container.
if out, err := d.Run("-p", "80", "-v", testutil.MountArg(dir, "/usr/share/nginx/html:ro"), "nginx"); err != nil {
t.Fatalf("docker run failed: %v\nout: %s", err, out)
if _, err := d.Run("-p", "80", "-v", testutil.MountArg(dir, "/usr/share/nginx/html:ro"), "nginx"); err != nil {
t.Fatalf("docker run failed: %v", err)
}
defer d.CleanUp()
@@ -138,8 +138,8 @@ func TestNginx(t *testing.T) {
}
// Wait until it's up and running.
if err := d.WaitForHTTP(port, 5*time.Second); err != nil {
t.Fatalf("docker.WaitForHTTP() timeout: %v", err)
if err := testutil.WaitForHTTP(port, 5*time.Second); err != nil {
t.Fatalf("WaitForHTTP() timeout: %v", err)
}
if err := testHTTPServer(port); err != nil {
@@ -148,14 +148,14 @@ func TestNginx(t *testing.T) {
}
func TestMysql(t *testing.T) {
if out, err := testutil.Pull("mysql"); err != nil {
t.Fatalf("docker pull failed: %v\nout: %s", err, out)
if err := testutil.Pull("mysql"); err != nil {
t.Fatalf("docker pull failed: %v", err)
}
d := testutil.MakeDocker("mysql-test")
// Start the container.
if out, err := d.Run("-e", "MYSQL_ROOT_PASSWORD=foobar123", "mysql"); err != nil {
t.Fatalf("docker run failed: %v\nout: %s", err, out)
if _, err := d.Run("-e", "MYSQL_ROOT_PASSWORD=foobar123", "mysql"); err != nil {
t.Fatalf("docker run failed: %v", err)
}
defer d.CleanUp()
@@ -178,8 +178,8 @@ func TestMysql(t *testing.T) {
"mysql",
"mysql", "-hmysql", "-uroot", "-pfoobar123", "-v", "-e", "source /sql/mysql.sql",
}
if out, err := client.Run(args...); err != nil {
t.Fatalf("docker run failed: %v\nout: %s", err, out)
if _, err := client.Run(args...); err != nil {
t.Fatalf("docker run failed: %v", err)
}
defer client.CleanUp()
+6 -6
View File
@@ -24,12 +24,12 @@ import (
)
func TestPythonHello(t *testing.T) {
if out, err := testutil.Pull("google/python-hello"); err != nil {
t.Fatalf("docker pull failed: %v\nout: %s", err, out)
if err := testutil.Pull("google/python-hello"); err != nil {
t.Fatalf("docker pull failed: %v", err)
}
d := testutil.MakeDocker("python-hello-test")
if out, err := d.Run("-p", "8080", "google/python-hello"); err != nil {
t.Fatalf("docker run failed: %v\nout: %s", err, out)
if _, err := d.Run("-p", "8080", "google/python-hello"); err != nil {
t.Fatalf("docker run failed: %v", err)
}
defer d.CleanUp()
@@ -40,8 +40,8 @@ func TestPythonHello(t *testing.T) {
}
// Wait until it's up and running.
if err := d.WaitForHTTP(port, 10*time.Second); err != nil {
t.Fatalf("docker.WaitForHTTP() timeout: %v", err)
if err := testutil.WaitForHTTP(port, 10*time.Second); err != nil {
t.Fatalf("WaitForHTTP() timeout: %v", err)
}
// Ensure that content is being served.
+6 -6
View File
@@ -24,12 +24,12 @@ import (
)
func TestTomcat(t *testing.T) {
if out, err := testutil.Pull("tomcat:8.0"); err != nil {
t.Fatalf("docker pull failed: %v\nout: %s", err, out)
if err := testutil.Pull("tomcat:8.0"); err != nil {
t.Fatalf("docker pull failed: %v", err)
}
d := testutil.MakeDocker("tomcat-test")
if out, err := d.Run("-p", "8080", "tomcat:8.0"); err != nil {
t.Fatalf("docker run failed: %v\nout: %s", err, out)
if _, err := d.Run("-p", "8080", "tomcat:8.0"); err != nil {
t.Fatalf("docker run failed: %v", err)
}
defer d.CleanUp()
@@ -40,8 +40,8 @@ func TestTomcat(t *testing.T) {
}
// Wait until it's up and running.
if err := d.WaitForHTTP(port, 10*time.Second); err != nil {
t.Fatalf("docker.WaitForHTTP() timeout: %v", err)
if err := testutil.WaitForHTTP(port, 10*time.Second); err != nil {
t.Fatalf("WaitForHTTP() timeout: %v", err)
}
// Ensure that content is being served.
+48 -40
View File
@@ -37,11 +37,9 @@ import (
"gvisor.googlesource.com/gvisor/runsc/test/testutil"
)
// This container is a docker image for the Flask microframework hello world application.
const container = "python-hello-test"
// httpRequestSucceeds sends a request to a given url and checks that the status is OK.
func httpRequestSucceeds(client http.Client, url string) error {
func httpRequestSucceeds(client http.Client, server string, port int) error {
url := fmt.Sprintf("http://%s:%d", server, port)
// Ensure that content is being served.
resp, err := client.Get(url)
if err != nil {
@@ -55,33 +53,50 @@ func httpRequestSucceeds(client http.Client, url string) error {
// TestLifeCycle tests a basic Create/Start/Stop docker container life cycle.
func TestLifeCycle(t *testing.T) {
d := testutil.MakeDocker(container)
// Test docker create.
if out, err := d.Do("create", "--runtime", d.Runtime, "--name", d.Name, "-p", "8080", "google/python-hello"); err != nil {
t.Fatalf("docker create failed: %v\nout: %s", err, out)
if err := testutil.Pull("nginx"); err != nil {
t.Fatalf("docker pull failed: %v", err)
}
// Test docker start.
if out, err := d.Do("start", d.Name); err != nil {
d := testutil.MakeDocker("lifecycle-test")
if err := d.Create("-p", "80", "nginx"); err != nil {
t.Fatalf("docker create failed: %v", err)
}
if err := d.Start(); err != nil {
d.CleanUp()
t.Fatalf("docker start failed: %v\nout: %s", err, out)
t.Fatalf("docker start failed: %v", err)
}
// Test docker stop.
if out, err := d.Do("stop", d.Name); err != nil {
// Test that container is working
port, err := d.FindPort(80)
if err != nil {
t.Fatalf("docker.FindPort(80) failed: %v", err)
}
if err := testutil.WaitForHTTP(port, 5*time.Second); err != nil {
t.Fatalf("WaitForHTTP() timeout: %v", err)
}
client := http.Client{Timeout: time.Duration(2 * time.Second)}
if err := httpRequestSucceeds(client, "localhost", port); err != nil {
t.Errorf("http request failed: %v", err)
}
if err := d.Stop(); err != nil {
d.CleanUp()
t.Fatalf("docker stop failed: %v\nout: %s", err, out)
t.Fatalf("docker stop failed: %v", err)
}
// Test removing the container.
if out, err := d.Do("rm", d.Name); err != nil {
t.Fatalf("docker rm failed: %v\nout: %s", err, out)
if err := d.Remove(); err != nil {
t.Fatalf("docker rm failed: %v", err)
}
}
func TestPauseResume(t *testing.T) {
d := testutil.MakeDocker(container)
if !testutil.IsPauseResumeSupported() {
t.Log("Pause/resume is not supported, skipping test.")
return
}
if err := testutil.Pull("google/python-hello"); err != nil {
t.Fatalf("docker pull failed: %v", err)
}
d := testutil.MakeDocker("pause-resume-test")
if out, err := d.Run("-p", "8080", "google/python-hello"); err != nil {
t.Fatalf("docker run failed: %v\nout: %s", err, out)
}
@@ -94,28 +109,22 @@ func TestPauseResume(t *testing.T) {
}
// Wait until it's up and running.
if err := d.WaitForHTTP(port, 5*time.Second); err != nil {
t.Fatalf("docker.WaitForHTTP() timeout: %v", err)
if err := testutil.WaitForHTTP(port, 20*time.Second); err != nil {
t.Fatalf("WaitForHTTP() timeout: %v", err)
}
timeout := time.Duration(2 * time.Second)
client := http.Client{
Timeout: timeout,
}
url := fmt.Sprintf("http://localhost:%d", port)
// Check that container is working.
if err := httpRequestSucceeds(client, url); err != nil {
client := http.Client{Timeout: time.Duration(2 * time.Second)}
if err := httpRequestSucceeds(client, "localhost", port); err != nil {
t.Errorf("http request failed: %v", err)
}
// Pause container.
if out, err := d.Do("pause", d.Name); err != nil {
t.Fatalf("docker pause failed: %v\nout: %s", err, out)
if err := d.Pause(); err != nil {
t.Fatalf("docker pause failed: %v", err)
}
// Check if container is paused.
switch _, err := client.Get(url); v := err.(type) {
switch _, err := client.Get(fmt.Sprintf("http://localhost:%d", port)); v := err.(type) {
case nil:
t.Errorf("http req expected to fail but it succeeded")
case net.Error:
@@ -126,18 +135,17 @@ func TestPauseResume(t *testing.T) {
t.Errorf("http req got unexpected error %v", v)
}
// Resume container.
if out, err := d.Do("unpause", d.Name); err != nil {
t.Fatalf("docker unpause failed: %v\nout: %s", err, out)
if err := d.Unpause(); err != nil {
t.Fatalf("docker unpause failed: %v", err)
}
// Wait until it's up and running.
if err := d.WaitForHTTP(port, 5*time.Second); err != nil {
t.Fatalf("docker.WaitForHTTP() timeout: %v", err)
if err := testutil.WaitForHTTP(port, 20*time.Second); err != nil {
t.Fatalf("WaitForHTTP() timeout: %v", err)
}
// Check if container is working again.
if err := httpRequestSucceeds(client, url); err != nil {
if err := httpRequestSucceeds(client, "localhost", port); err != nil {
t.Errorf("http request failed: %v", err)
}
}
+59 -21
View File
@@ -19,7 +19,6 @@ import (
"io/ioutil"
"log"
"math/rand"
"net/http"
"os"
"os/exec"
"path"
@@ -41,6 +40,12 @@ func runtime() string {
return r
}
// IsPauseResumeSupported returns true if Pause/Resume is supported by runtime.
func IsPauseResumeSupported() bool {
// Native host network stack can't be saved.
return !strings.Contains(runtime(), "hostnet")
}
// EnsureSupportedDockerVersion checks if correct docker is installed.
func EnsureSupportedDockerVersion() {
cmd := exec.Command("docker", "version")
@@ -100,7 +105,7 @@ func do(args ...string) (string, error) {
cmd := exec.Command("docker", args...)
out, err := cmd.CombinedOutput()
if err != nil {
return "", fmt.Errorf("error executing docker %s: %v", args, err)
return "", fmt.Errorf("error executing docker %s: %v\nout: %s", args, err, out)
}
return string(out), nil
}
@@ -108,8 +113,9 @@ func do(args ...string) (string, error) {
// Pull pulls a docker image. This is used in tests to isolate the
// time to pull the image off the network from the time to actually
// start the container, to avoid timeouts over slow networks.
func Pull(image string) (string, error) {
return do("pull", image)
func Pull(image string) error {
_, err := do("pull", image)
return err
}
// Docker contains the name and the runtime of a docker container.
@@ -125,6 +131,30 @@ func MakeDocker(namePrefix string) Docker {
return Docker{Name: namePrefix + suffix, Runtime: runtime()}
}
// Create calls 'docker create' with the arguments provided.
func (d *Docker) Create(args ...string) error {
a := []string{"create", "--runtime", d.Runtime, "--name", d.Name}
a = append(a, args...)
_, err := do(a...)
return err
}
// Start calls 'docker start'.
func (d *Docker) Start() error {
if _, err := do("start", d.Name); err != nil {
return fmt.Errorf("error starting container %q: %v", d.Name, err)
}
return nil
}
// Stop calls 'docker stop'.
func (d *Docker) Stop() error {
if _, err := do("stop", d.Name); err != nil {
return fmt.Errorf("error stopping container %q: %v", d.Name, err)
}
return nil
}
// Run calls 'docker run' with the arguments provided.
func (d *Docker) Run(args ...string) (string, error) {
a := []string{"run", "--runtime", d.Runtime, "--name", d.Name, "-d"}
@@ -132,15 +162,36 @@ func (d *Docker) Run(args ...string) (string, error) {
return do(a...)
}
// Pause calls 'docker pause'.
func (d *Docker) Pause() error {
if _, err := do("pause", d.Name); err != nil {
return fmt.Errorf("error pausing container %q: %v", d.Name, err)
}
return nil
}
// Unpause calls 'docker pause'.
func (d *Docker) Unpause() error {
if _, err := do("unpause", d.Name); err != nil {
return fmt.Errorf("error unpausing container %q: %v", d.Name, err)
}
return nil
}
// Remove calls 'docker rm'.
func (d *Docker) Remove() error {
if _, err := do("rm", d.Name); err != nil {
return fmt.Errorf("error deleting container %q: %v", d.Name, err)
}
return nil
}
// CleanUp kills and deletes the container.
func (d *Docker) CleanUp() error {
if _, err := do("kill", d.Name); err != nil {
return fmt.Errorf("error killing container %q: %v", d.Name, err)
}
if _, err := do("rm", d.Name); err != nil {
return fmt.Errorf("error deleting container %q: %v", d.Name, err)
}
return nil
return d.Remove()
}
// FindPort returns the host port that is mapped to 'sandboxPort'. This calls
@@ -177,16 +228,3 @@ func (d *Docker) WaitForOutput(pattern string, timeout time.Duration) error {
}
return fmt.Errorf("timeout waiting for output %q: %s", re.String(), out)
}
// WaitForHTTP tries GET requests on a port until the call succeeds or a timeout.
func (d *Docker) WaitForHTTP(port int, timeout time.Duration) error {
for exp := time.Now().Add(timeout); time.Now().Before(exp); {
url := fmt.Sprintf("http://localhost:%d/", port)
if _, err := http.Get(url); err == nil {
// Success!
return nil
}
time.Sleep(100 * time.Millisecond)
}
return fmt.Errorf("timeout waiting for HTTP server on port %d", port)
}
+10
View File
@@ -21,6 +21,7 @@ import (
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
"path/filepath"
"time"
@@ -182,3 +183,12 @@ func Poll(cb func() error, timeout time.Duration) error {
b := backoff.WithContext(backoff.NewConstantBackOff(100*time.Millisecond), ctx)
return backoff.Retry(cb, b)
}
// WaitForHTTP tries GET requests on a port until the call succeeds or timeout.
func WaitForHTTP(port int, timeout time.Duration) error {
cb := func() error {
_, err := http.Get(fmt.Sprintf("http://localhost:%d/", port))
return err
}
return Poll(cb, timeout)
}