From e2f5d72301cfb3a9df33fe4b4394a2e9d844fe1c Mon Sep 17 00:00:00 2001 From: Lucas Clemente Date: Sun, 5 Jun 2016 14:44:54 +0200 Subject: [PATCH] add an integration test using a dockered chrome via selenium this commit also moves the {Before,After}Suite functions from the integration_test.go file into the integrationtests_suite_test.go file, and adds the docker-specific hooks. ref #162 --- .travis.yml | 5 + integrationtests/chrome_test.go | 16 ++ integrationtests/integration_test.go | 75 +--------- .../integrationtests_suite_test.go | 139 ++++++++++++++++++ 4 files changed, 168 insertions(+), 67 deletions(-) create mode 100644 integrationtests/chrome_test.go diff --git a/.travis.yml b/.travis.yml index 6763b8fd..135f7251 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,10 @@ +sudo: required + language: go +services: + - docker + go: - 1.6 - 1.7beta1 diff --git a/integrationtests/chrome_test.go b/integrationtests/chrome_test.go new file mode 100644 index 00000000..2e9ed087 --- /dev/null +++ b/integrationtests/chrome_test.go @@ -0,0 +1,16 @@ +package integrationtests + +import ( + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("Chrome tests", func() { + It("loads a simple hello world page using quic", func() { + err := wd.Get("https://quic.clemente.io/hello") + Expect(err).NotTo(HaveOccurred()) + source, err := wd.PageSource() + Expect(err).NotTo(HaveOccurred()) + Expect(source).To(ContainSubstring("Hello, World!\n")) + }) +}) diff --git a/integrationtests/integration_test.go b/integrationtests/integration_test.go index 2596ebe4..6a8c1d70 100644 --- a/integrationtests/integration_test.go +++ b/integrationtests/integration_test.go @@ -2,20 +2,14 @@ package integrationtests import ( "bytes" - "crypto/rand" "fmt" - "io" - "net" - "net/http" "os" "os/exec" "runtime" "strconv" "sync" - "github.com/lucas-clemente/quic-go/h2quic" "github.com/lucas-clemente/quic-go/protocol" - "github.com/lucas-clemente/quic-go/testdata" _ "github.com/lucas-clemente/quic-clients" // download clients @@ -26,65 +20,12 @@ import ( ) var _ = Describe("Integration tests", func() { - const dataLen = 50 * 1024 - const host = "127.0.0.1" - - var ( - server *h2quic.Server - clientPath string - data []byte - port string + clientPath := fmt.Sprintf( + "%s/src/github.com/lucas-clemente/quic-clients/client-%s-debug", + os.Getenv("GOPATH"), + runtime.GOOS, ) - http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) { - _, err := io.WriteString(w, "Hello, World!\n") - Expect(err).NotTo(HaveOccurred()) - }) - - http.HandleFunc("/data", func(w http.ResponseWriter, r *http.Request) { - _, err := w.Write(data) - Expect(err).NotTo(HaveOccurred()) - }) - - http.HandleFunc("/echo", func(w http.ResponseWriter, r *http.Request) { - _, err := io.Copy(w, r.Body) - Expect(err).NotTo(HaveOccurred()) - }) - - BeforeSuite(func() { - data = make([]byte, dataLen) - _, err := rand.Read(data) - Expect(err).NotTo(HaveOccurred()) - - clientPath = fmt.Sprintf( - "%s/src/github.com/lucas-clemente/quic-clients/client-%s-debug", - os.Getenv("GOPATH"), - runtime.GOOS, - ) - - server = &h2quic.Server{ - Server: &http.Server{ - TLSConfig: testdata.GetTLSConfig(), - }, - } - - addr, err := net.ResolveUDPAddr("udp", host+":0") - Expect(err).NotTo(HaveOccurred()) - conn, err := net.ListenUDP("udp", addr) - Expect(err).NotTo(HaveOccurred()) - port = strconv.Itoa(conn.LocalAddr().(*net.UDPAddr).Port) - - go func() { - defer GinkgoRecover() - server.Serve(conn) - }() - }) - - AfterSuite(func() { - err := server.Close() - Expect(err).NotTo(HaveOccurred()) - }) - for i := range protocol.SupportedVersions { version := protocol.SupportedVersions[i] @@ -93,7 +34,7 @@ var _ = Describe("Integration tests", func() { command := exec.Command( clientPath, "--quic-version="+strconv.Itoa(int(version)), - "--host="+host, + "--host=127.0.0.1", "--port="+port, "https://quic.clemente.io/hello", ) @@ -108,7 +49,7 @@ var _ = Describe("Integration tests", func() { command := exec.Command( clientPath, "--quic-version="+strconv.Itoa(int(version)), - "--host="+host, + "--host=127.0.0.1", "--port="+port, "--body=foo", "https://quic.clemente.io/echo", @@ -124,7 +65,7 @@ var _ = Describe("Integration tests", func() { command := exec.Command( clientPath, "--quic-version="+strconv.Itoa(int(version)), - "--host="+host, + "--host=127.0.0.1", "--port="+port, "https://quic.clemente.io/data", ) @@ -145,7 +86,7 @@ var _ = Describe("Integration tests", func() { command := exec.Command( clientPath, "--quic-version="+strconv.Itoa(int(version)), - "--host="+host, + "--host=127.0.0.1", "--port="+port, "https://quic.clemente.io/data", ) diff --git a/integrationtests/integrationtests_suite_test.go b/integrationtests/integrationtests_suite_test.go index 71306d8e..fe882235 100644 --- a/integrationtests/integrationtests_suite_test.go +++ b/integrationtests/integrationtests_suite_test.go @@ -1,13 +1,152 @@ package integrationtests import ( + "crypto/rand" + "fmt" + "io" + "net" + "net/http" + "os/exec" + "strconv" + "time" + + "github.com/lucas-clemente/quic-go/h2quic" + "github.com/lucas-clemente/quic-go/testdata" + "github.com/tebeka/selenium" + . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + "github.com/onsi/gomega/gbytes" + "github.com/onsi/gomega/gexec" "testing" ) +const ( + dataLen = 50 * 1024 +) + +var ( + server *h2quic.Server + data []byte + port string + + docker *gexec.Session + wd selenium.WebDriver +) + func TestIntegration(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "Integration Tests Suite") } + +var _ = BeforeSuite(func() { + setupHTTPHandlers() + setupQuicServer() + setupSelenium() +}) + +var _ = AfterSuite(func() { + err := server.Close() + Expect(err).NotTo(HaveOccurred()) + + docker.Interrupt().Wait(1) +}) + +func setupHTTPHandlers() { + data = make([]byte, dataLen) + _, err := rand.Read(data) + Expect(err).NotTo(HaveOccurred()) + + http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) { + _, err := io.WriteString(w, "Hello, World!\n") + Expect(err).NotTo(HaveOccurred()) + }) + + http.HandleFunc("/data", func(w http.ResponseWriter, r *http.Request) { + _, err := w.Write(data) + Expect(err).NotTo(HaveOccurred()) + }) + + http.HandleFunc("/echo", func(w http.ResponseWriter, r *http.Request) { + _, err := io.Copy(w, r.Body) + Expect(err).NotTo(HaveOccurred()) + }) +} + +func setupQuicServer() { + server = &h2quic.Server{ + Server: &http.Server{ + TLSConfig: testdata.GetTLSConfig(), + }, + } + + addr, err := net.ResolveUDPAddr("udp", "0.0.0.0:0") + Expect(err).NotTo(HaveOccurred()) + conn, err := net.ListenUDP("udp", addr) + Expect(err).NotTo(HaveOccurred()) + port = strconv.Itoa(conn.LocalAddr().(*net.UDPAddr).Port) + + go func() { + defer GinkgoRecover() + server.Serve(conn) + }() +} + +func setupSelenium() { + var err error + pullCmd := exec.Command("docker", "pull", "selenium/standalone-chrome:latest") + pull, err := gexec.Start(pullCmd, GinkgoWriter, GinkgoWriter) + Expect(err).NotTo(HaveOccurred()) + // Assuming a download at 10 Mbit/s + Eventually(pull, 10*time.Minute).Should(gexec.Exit(0)) + + dockerCmd := exec.Command( + "docker", + "run", + "-i", + "--rm", + "-p=4444:4444", + "-p=5900:5900", + "selenium/standalone-chrome:latest", + ) + docker, err = gexec.Start(dockerCmd, GinkgoWriter, GinkgoWriter) + Expect(err).NotTo(HaveOccurred()) + Eventually(docker.Out, 5).Should(gbytes.Say("Selenium Server is up and running")) + + caps := selenium.Capabilities{ + "browserName": "chrome", + "chromeOptions": map[string]interface{}{ + "args": []string{ + "--enable-quic", + "--no-proxy-server", + "--origin-to-force-quic-on=quic.clemente.io:443", + fmt.Sprintf(`--host-resolver-rules=MAP quic.clemente.io:443 %s:%s`, GetLocalIP(), port), + }, + }, + } + wd, err = selenium.NewRemote(caps, "http://localhost:4444/wd/hub") + Expect(err).NotTo(HaveOccurred()) +} + +func GetLocalIP() string { + // First, try finding interface docker0 + i, err := net.InterfaceByName("docker0") + if err == nil { + var addrs []net.Addr + addrs, err = i.Addrs() + Expect(err).NotTo(HaveOccurred()) + return addrs[0].(*net.IPNet).IP.String() + } + + addrs, err := net.InterfaceAddrs() + Expect(err).NotTo(HaveOccurred()) + for _, address := range addrs { + if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() { + if ipnet.IP.To4() != nil { + return ipnet.IP.String() + } + } + } + panic("no addr") +}