Skip to content

Instantly share code, notes, and snippets.

@pawelniewie
Created July 22, 2015 14:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pawelniewie/118c2b5c54cc19502ccd to your computer and use it in GitHub Desktop.
Save pawelniewie/118c2b5c54cc19502ccd to your computer and use it in GitHub Desktop.
package main
import (
"os/exec"
"os/user"
"testing"
"net/http"
"io/ioutil"
"fmt"
"github.com/stretchr/testify/assert"
"syscall"
"strings"
"runtime"
"time"
. "gopkg.in/check.v1"
)
func Test(t *testing.T) { TestingT(t) }
type DockerSuite struct {
containerIp string
cID string
}
var _ = Suite(&DockerSuite{})
func (s *DockerSuite) SetUpSuite(t *C) {
s.containerIp = "127.0.0.1"
if runtime.GOOS == "darwin" {
out, _, err := runCommandWithOutput("boot2docker", "ip")
if err != nil {
t.Fatalf("You don't have boot2docker installed, it is required on Mac OS X")
} else {
s.containerIp = strings.TrimSpace(out)
}
} else if (runtime.GOOS == "linux") {
out, _, _ := runCommandWithOutput("id")
if !strings.Contains(out, "(docker)") {
usr, _ := user.Current()
t.Fatalf("You don't have a permission to control docker, to fix this run (or ask your administrator):\n\nsudo usermod -aG docker %s\nexec su -l %s\n", usr.Username, usr.Username)
}
}
cID, _, err := runCommandWithOutput("docker", "run", "-d", "-p", "19090:80", "nginx")
if err != nil {
t.Fatalf("Failed to start container: %s", cID)
} else {
s.cID = strings.TrimSpace(cID)
t.Log("Started container: " + s.cID)
}
}
func (s *DockerSuite) TearDownSuite(t *C) {
if s.cID == "" {
t.Log("Seems like the container didn't start")
return
}
_, _, err := runCommandWithOutput("docker", "stop", s.cID)
if err != nil {
t.Fatalf("Failed to stop container: %s", s.cID)
} else {
t.Log("Stopped container " + s.cID)
}
_, _, err = runCommandWithOutput("docker", "rm", s.cID)
if err != nil {
t.Fatalf("Failed to remove container: %s", s.cID)
} else {
t.Log("Removed container " + s.cID)
}
}
type httpHandler func() (response *http.Response, err error)
func httpPoller(t *C, handler httpHandler, timeout time.Duration) (httpBody []byte, lastError error) {
finishAt := time.Now().Add(timeout)
for {
if (time.Now().After(finishAt)) {
return
}
response, err := handler()
if err == nil {
defer response.Body.Close()
contents, err := ioutil.ReadAll(response.Body)
if err != nil {
lastError = err
} else {
httpBody = contents
lastError = nil
return
}
} else {
lastError = err
}
time.Sleep(150 * time.Nanosecond)
}
}
func (s *DockerSuite) TestNginx(t *C) {
timeout := 30 * time.Second
httpBody, lastError := httpPoller(t, func() (response *http.Response, err error) {
response, err = http.Get(fmt.Sprintf("http://%s:19090/", s.containerIp))
return
}, timeout);
if httpBody != nil {
assert.Contains(t, string(httpBody), "Welcome to nginx!", "HTML response does not contain welcome message")
} else {
t.Fatalf("Container didn't start in: %s, last error was: %s", timeout, lastError)
}
}
func processExitCode(err error) (exitCode int) {
if err != nil {
var exiterr error
if exitCode, exiterr = getExitCode(err); exiterr != nil {
// TODO: Fix this so we check the error's text.
// we've failed to retrieve exit code, so we set it to 127
exitCode = 127
}
}
return
}
func getExitCode(err error) (int, error) {
exitCode := 0
if exiterr, ok := err.(*exec.ExitError); ok {
if procExit := exiterr.Sys().(syscall.WaitStatus); ok {
return procExit.ExitStatus(), nil
}
}
return exitCode, fmt.Errorf("failed to get exit code")
}
func runCommandWithOutput(name string, arg ...string) (output string, exitCode int, err error) {
exitCode = 0
cmd := exec.Command(name, arg...)
out, err := cmd.CombinedOutput()
exitCode = processExitCode(err)
output = string(out)
return
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment