Merge pull request #537 from lucas-clemente/wip-no-docker

Replace docker with a directly launched Chrome for integration tests
This commit is contained in:
Lucas Clemente
2017-07-07 12:18:25 +02:00
committed by GitHub
9 changed files with 242 additions and 395 deletions

View File

@@ -1,4 +1,4 @@
sudo: required
dist: trusty
addons:
hosts:
@@ -6,9 +6,6 @@ addons:
language: go
services:
- docker
go:
- 1.7.x
- 1.8.x
@@ -30,6 +27,8 @@ before_install:
- go get github.com/onsi/gomega
- export GOARCH=$TRAVIS_GOARCH
- go env # for debugging
- "export DISPLAY=:99.0"
- "Xvfb $DISPLAY &"
script:
- .travis/script.sh

View File

@@ -9,5 +9,5 @@ fi
if [ ${TESTMODE} == "integration" ]; then
ginkgo --randomizeAllSpecs --randomizeSuites --trace --progress -focus "Benchmark"
ginkgo -r --randomizeAllSpecs --randomizeSuites --trace --progress integrationtests
ginkgo -v -r --randomizeAllSpecs --randomizeSuites --trace --progress integrationtests
fi

View File

@@ -11,4 +11,5 @@
- Remove the `tls.Config` from the `quic.Config`. The `tls.Config` must now be passed to the `Dial` and `Listen` functions as a separate parameter. See the [Godoc](https://godoc.org/github.com/lucas-clemente/quic-go) for details.
- Changed the log level environment variable to only accept strings ("DEBUG", "INFO", "ERROR"), see [the wiki](https://github.com/lucas-clemente/quic-go/wiki/Logging) for more details.
- Rename the `h2quic.QuicRoundTripper` to `h2quic.RoundTripper`
- Changed `h2quic.Server.Serve()` to accept a `net.PacketConn`
- Various bugfixes

View File

@@ -69,11 +69,11 @@ func (s *Server) ListenAndServeTLS(certFile, keyFile string) error {
}
// Serve an existing UDP connection.
func (s *Server) Serve(conn *net.UDPConn) error {
func (s *Server) Serve(conn net.PacketConn) error {
return s.serveImpl(s.TLSConfig, conn)
}
func (s *Server) serveImpl(tlsConfig *tls.Config, conn *net.UDPConn) error {
func (s *Server) serveImpl(tlsConfig *tls.Config, conn net.PacketConn) error {
if s.Server == nil {
return errors.New("use of h2quic.Server without http.Server")
}

View File

@@ -2,234 +2,142 @@ package integrationtests
import (
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
"path/filepath"
"strconv"
"github.com/tebeka/selenium"
"os/exec"
"runtime"
"strings"
"time"
"github.com/lucas-clemente/quic-go/internal/utils"
"github.com/lucas-clemente/quic-go/protocol"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/onsi/gomega/gexec"
)
const nImgs = 200
const imgSize = 40
const (
nChromeRetries = 8
)
func init() {
http.HandleFunc("/tile", func(w http.ResponseWriter, r *http.Request) {
// Small 40x40 png
w.Write([]byte{
0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a, 0x00, 0x00, 0x00, 0x0d,
0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x28,
0x01, 0x03, 0x00, 0x00, 0x00, 0xb6, 0x30, 0x2a, 0x2e, 0x00, 0x00, 0x00,
0x03, 0x50, 0x4c, 0x54, 0x45, 0x5a, 0xc3, 0x5a, 0xad, 0x38, 0xaa, 0xdb,
0x00, 0x00, 0x00, 0x0b, 0x49, 0x44, 0x41, 0x54, 0x78, 0x01, 0x63, 0x18,
0x61, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x01, 0xe2, 0xb8, 0x75, 0x22, 0x00,
0x00, 0x00, 0x00, 0x49, 0x45, 0x4e, 0x44, 0xae, 0x42, 0x60, 0x82,
})
})
func getChromePath() string {
if runtime.GOOS == "darwin" {
return "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"
}
return "google-chrome"
}
http.HandleFunc("/tiles", func(w http.ResponseWriter, r *http.Request) {
io.WriteString(w, "<html><body>")
for i := 0; i < nImgs; i++ {
fmt.Fprintf(w, `<img src="/tile?cachebust=%d">`, i)
func chromeTest(version protocol.VersionNumber, url string, blockUntilDone func()) {
// Chrome sometimes starts but doesn't send any HTTP requests for no apparent reason.
// Retry starting it a couple of times.
for i := 0; i < nChromeRetries; i++ {
if chromeTestImpl(version, url, blockUntilDone) {
return
}
io.WriteString(w, "</body></html>")
})
}
Fail("Chrome didn't hit the testing endpoints")
}
func chromeTestImpl(version protocol.VersionNumber, url string, blockUntilDone func()) bool {
userDataDir, err := ioutil.TempDir("", "quic-go-test-chrome-dir")
Expect(err).NotTo(HaveOccurred())
defer os.RemoveAll(userDataDir)
path := getChromePath()
args := []string{
"--disable-gpu",
"--no-first-run=true",
"--no-default-browser-check=true",
"--user-data-dir=" + userDataDir,
"--enable-quic=true",
"--no-proxy-server=true",
"--origin-to-force-quic-on=quic.clemente.io:443",
fmt.Sprintf(`--host-resolver-rules=MAP quic.clemente.io:443 localhost:%s`, port),
fmt.Sprintf("--quic-version=QUIC_VERSION_%d", version),
url,
}
utils.Infof("Running chrome: %s '%s'", getChromePath(), strings.Join(args, "' '"))
command := exec.Command(path, args...)
session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())
defer session.Kill()
const pollInterval = 100 * time.Millisecond
const pollDuration = 10 * time.Second
for i := 0; i < int(pollDuration/pollInterval); i++ {
time.Sleep(pollInterval)
if testEndpointCalled {
break
}
}
if !testEndpointCalled {
return false
}
blockUntilDone()
return true
}
var _ = Describe("Chrome tests", func() {
// test disabled since it doesn't work with the configurable QUIC version in the server
PIt("does not work with mismatching versions", func() {
versionForUs := protocol.SupportedVersions[0]
versionForChrome := protocol.SupportedVersions[1]
supportedVersionsBefore := protocol.SupportedVersions
protocol.SupportedVersions = []protocol.VersionNumber{versionForUs}
wd := getWebdriverForVersion(versionForChrome)
defer func() {
protocol.SupportedVersions = supportedVersionsBefore
wd.Close()
}()
err := wd.Get("https://quic.clemente.io/hello")
Expect(err).NotTo(HaveOccurred())
source, err := wd.PageSource()
Expect(err).NotTo(HaveOccurred())
Expect(source).ToNot(ContainSubstring("Hello, World!\n"))
})
for i := range protocol.SupportedVersions {
version := protocol.SupportedVersions[i]
Context(fmt.Sprintf("with quic version %d", version), func() {
var (
wd selenium.WebDriver
supportedVersionsBefore []protocol.VersionNumber
)
supportedVersionsBefore := protocol.SupportedVersions
BeforeEach(func() {
if version == protocol.Version37 {
Skip("Skipping Chrome test with QUIC version 37")
}
supportedVersionsBefore = protocol.SupportedVersions
protocol.SupportedVersions = []protocol.VersionNumber{version}
})
JustBeforeEach(func() {
wd = getWebdriverForVersion(version)
})
AfterEach(func() {
wd.Close()
protocol.SupportedVersions = supportedVersionsBefore
})
It("loads a simple hello world page using quic", func(done Done) {
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"))
close(done)
}, 5)
It("loads a large number of files", func(done Done) {
err := wd.Get("https://quic.clemente.io/tiles")
Expect(err).NotTo(HaveOccurred())
Eventually(func() error {
imgs, err := wd.FindElements("tag name", "img")
if err != nil {
return err
}
if len(imgs) != nImgs {
return fmt.Errorf("expected number of images to be %d, got %d", nImgs, len(imgs))
}
for i, img := range imgs {
size, err := img.Size()
if err != nil {
return err
}
if size.Height != imgSize || size.Width != imgSize {
return fmt.Errorf("image %d did not have expected size", i)
}
}
return nil
}, 5).ShouldNot(HaveOccurred())
close(done)
}, 20)
It("downloads a small file", func() {
dataMan.GenerateData(dataLen)
err := wd.Get("https://quic.clemente.io/data")
Expect(err).NotTo(HaveOccurred())
Eventually(func() int { return getDownloadSize("data") }, 30, 0.1).Should(Equal(dataLen))
Expect(getDownloadMD5("data")).To(Equal(dataMan.GetMD5()))
}, 60)
chromeTest(
version,
fmt.Sprintf("https://quic.clemente.io/downloadtest?num=1&len=%d", dataLen),
waitForDone,
)
})
It("downloads a large file", func() {
dataMan.GenerateData(dataLongLen)
err := wd.Get("https://quic.clemente.io/data")
Expect(err).NotTo(HaveOccurred())
Eventually(func() int { return getDownloadSize("data") }, 90, 0.5).Should(Equal(dataLongLen))
Expect(getDownloadMD5("data")).To(Equal(dataMan.GetMD5()))
}, 100)
chromeTest(
version,
fmt.Sprintf("https://quic.clemente.io/downloadtest?num=1&len=%d", dataLongLen),
waitForDone,
)
})
It("loads a large number of files", func() {
chromeTest(
version,
"https://quic.clemente.io/downloadtest?num=4&len=100",
waitForDone,
)
})
It("uploads a small file", func() {
dataMan.GenerateData(dataLen)
data := dataMan.GetData()
dir, err := ioutil.TempDir("", "quic-upload-src")
Expect(err).ToNot(HaveOccurred())
defer os.RemoveAll(dir)
tmpfn := filepath.Join(dir, "data.dat")
err = ioutil.WriteFile(tmpfn, data, 0777)
Expect(err).ToNot(HaveOccurred())
copyFileToDocker(tmpfn)
err = wd.Get("https://quic.clemente.io/uploadform?num=1")
Expect(err).NotTo(HaveOccurred())
elem, err := wd.FindElement(selenium.ByCSSSelector, "#upload_0")
Expect(err).ToNot(HaveOccurred())
err = elem.SendKeys("/home/seluser/data.dat")
Expect(err).ToNot(HaveOccurred())
Eventually(func() error { return elem.Submit() }, 30, 0.1).ShouldNot(HaveOccurred())
file := filepath.Join(uploadDir, "data.dat")
Expect(getFileSize(file)).To(Equal(dataLen))
Expect(getFileMD5(file)).To(Equal(dataMan.GetMD5()))
chromeTest(
version,
fmt.Sprintf("https://quic.clemente.io/uploadtest?num=1&len=%d", dataLen),
waitForNUploaded(1),
)
})
It("uploads a large file", func() {
dataMan.GenerateData(dataLongLen)
data := dataMan.GetData()
dir, err := ioutil.TempDir("", "quic-upload-src")
Expect(err).ToNot(HaveOccurred())
defer os.RemoveAll(dir)
tmpfn := filepath.Join(dir, "data.dat")
err = ioutil.WriteFile(tmpfn, data, 0777)
Expect(err).ToNot(HaveOccurred())
copyFileToDocker(tmpfn)
err = wd.Get("https://quic.clemente.io/uploadform?num=1")
Expect(err).NotTo(HaveOccurred())
elem, err := wd.FindElement(selenium.ByCSSSelector, "#upload_0")
Expect(err).ToNot(HaveOccurred())
err = elem.SendKeys("/home/seluser/data.dat")
Expect(err).ToNot(HaveOccurred())
Eventually(func() error { return elem.Submit() }, 90, 0.5).ShouldNot(HaveOccurred())
file := filepath.Join(uploadDir, "data.dat")
Expect(getFileSize(file)).To(Equal(dataLongLen))
Expect(getFileMD5(file)).To(Equal(dataMan.GetMD5()))
chromeTest(
version,
fmt.Sprintf("https://quic.clemente.io/uploadtest?num=1&len=%d", dataLongLen),
waitForNUploaded(1),
)
})
// this test takes a long time because it copies every file into the docker container one by one
// unfortunately, docker doesn't support copying multiple files at once
// see https://github.com/docker/docker/issues/7710
It("uploads many small files", func() {
num := protocol.MaxStreamsPerConnection + 20
dir, err := ioutil.TempDir("", "quic-upload-src")
Expect(err).ToNot(HaveOccurred())
defer os.RemoveAll(dir)
var md5s [][]byte
for i := 0; i < num; i++ {
dataMan.GenerateData(dataLen)
data := dataMan.GetData()
md5s = append(md5s, dataMan.GetMD5())
tmpfn := filepath.Join(dir, "data_"+strconv.Itoa(i)+".dat")
err = ioutil.WriteFile(tmpfn, data, 0777)
Expect(err).ToNot(HaveOccurred())
copyFileToDocker(tmpfn)
}
err = wd.Get("https://quic.clemente.io/uploadform?num=" + strconv.Itoa(num))
Expect(err).NotTo(HaveOccurred())
for i := 0; i < num; i++ {
var elem selenium.WebElement
elem, err = wd.FindElement(selenium.ByCSSSelector, "#upload_"+strconv.Itoa(i))
Expect(err).ToNot(HaveOccurred())
err = elem.SendKeys("/home/seluser/data_" + strconv.Itoa(i) + ".dat")
Expect(err).ToNot(HaveOccurred())
}
elem, err := wd.FindElement(selenium.ByCSSSelector, "#form")
Expect(err).ToNot(HaveOccurred())
Eventually(func() error { return elem.Submit() }, 30, 0.1).ShouldNot(HaveOccurred())
for i := 0; i < num; i++ {
file := filepath.Join(uploadDir, "data_"+strconv.Itoa(i)+".dat")
Expect(getFileSize(file)).To(Equal(dataLen))
Expect(getFileMD5(file)).To(Equal(md5s[i]))
}
chromeTest(
version,
fmt.Sprintf("https://quic.clemente.io/uploadtest?num=%d&len=%d", num, dataLen),
waitForNUploaded(num),
)
})
})
}

View File

@@ -38,7 +38,7 @@ var _ = Describe("Drop Proxy", func() {
"https://quic.clemente.io/data",
)
session, err := Start(command, GinkgoWriter, GinkgoWriter)
session, err := Start(command, nil, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())
defer session.Kill()
Eventually(session, 20).Should(Exit(0))

View File

@@ -34,7 +34,7 @@ var _ = Describe("Integration tests", func() {
"--port="+port,
"https://quic.clemente.io/hello",
)
session, err := Start(command, GinkgoWriter, GinkgoWriter)
session, err := Start(command, nil, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())
defer session.Kill()
Eventually(session, 5).Should(Exit(0))
@@ -51,7 +51,7 @@ var _ = Describe("Integration tests", func() {
"--body=foo",
"https://quic.clemente.io/echo",
)
session, err := Start(command, GinkgoWriter, GinkgoWriter)
session, err := Start(command, nil, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())
defer session.Kill()
Eventually(session, 5).Should(Exit(0))

View File

@@ -2,35 +2,27 @@ package integrationtests
import (
"bytes"
"crypto/md5"
"encoding/hex"
"flag"
"fmt"
"io"
"io/ioutil"
"log"
"mime/multipart"
"net"
"net/http"
"os"
"os/exec"
"path"
"path/filepath"
"runtime"
"strings"
"sync/atomic"
"strconv"
"time"
"github.com/lucas-clemente/quic-go/h2quic"
"github.com/lucas-clemente/quic-go/internal/utils"
"github.com/lucas-clemente/quic-go/protocol"
"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"
)
@@ -41,17 +33,17 @@ const (
)
var (
server *h2quic.Server
dataMan dataManager
port string
uploadDir string
clientPath string // path of the quic_client
serverPath string // path of the quic_server
server *h2quic.Server
dataMan dataManager
port string
clientPath string
serverPath string
nFilesUploaded int32
testEndpointCalled bool
doneCalled bool
logFileName string // the log file set in the ginkgo flags
logFile *os.File
docker *gexec.Session
)
func TestIntegration(t *testing.T) {
@@ -59,14 +51,7 @@ func TestIntegration(t *testing.T) {
RunSpecs(t, "Integration Tests Suite")
}
var _ = BeforeSuite(func() {
setupHTTPHandlers()
setupSelenium()
})
var _ = AfterSuite(func() {
stopSelenium()
}, 10)
var _ = BeforeSuite(setupHTTPHandlers)
// read the logfile command line flag
// to set call ginkgo -- -logfile=log.txt
@@ -77,14 +62,6 @@ func init() {
var _ = BeforeEach(func() {
// set custom time format for logs
utils.SetLogTimeFormat("15:04:05.000")
// create a new uploadDir for every test
var err error
uploadDir, err = ioutil.TempDir("", "quic-upload-dest")
Expect(err).ToNot(HaveOccurred())
err = os.MkdirAll(uploadDir, os.ModeDir|0777)
Expect(err).ToNot(HaveOccurred())
_, thisfile, _, ok := runtime.Caller(0)
if !ok {
Fail("Failed to get current path")
@@ -93,6 +70,7 @@ var _ = BeforeEach(func() {
serverPath = filepath.Join(thisfile, fmt.Sprintf("../../../quic-clients/server-%s-debug", runtime.GOOS))
if len(logFileName) > 0 {
var err error
logFile, err = os.Create("./log.txt")
Expect(err).ToNot(HaveOccurred())
log.SetOutput(logFile)
@@ -105,18 +83,13 @@ var _ = JustBeforeEach(startQuicServer)
var _ = AfterEach(func() {
stopQuicServer()
// remove uploadDir
if len(uploadDir) < 20 {
panic("uploadDir too short")
}
os.RemoveAll(uploadDir)
// remove downloaded file in docker container
removeDownload("data")
if len(logFileName) > 0 {
_ = logFile.Close()
}
nFilesUploaded = 0
doneCalled = false
testEndpointCalled = false
})
func setupHTTPHandlers() {
@@ -136,6 +109,16 @@ func setupHTTPHandlers() {
Expect(err).NotTo(HaveOccurred())
})
http.HandleFunc("/prdata", func(w http.ResponseWriter, r *http.Request) {
defer GinkgoRecover()
sl := r.URL.Query().Get("len")
l, err := strconv.Atoi(sl)
Expect(err).NotTo(HaveOccurred())
data := generatePRData(l)
_, err = w.Write(data)
Expect(err).NotTo(HaveOccurred())
})
http.HandleFunc("/echo", func(w http.ResponseWriter, r *http.Request) {
defer GinkgoRecover()
body, err := ioutil.ReadAll(r.Body)
@@ -144,46 +127,45 @@ func setupHTTPHandlers() {
Expect(err).NotTo(HaveOccurred())
})
// requires the num GET parameter, e.g. /uploadform?num=2
// will create num input fields for uploading files
http.HandleFunc("/uploadform", func(w http.ResponseWriter, r *http.Request) {
// Requires the len & num GET parameters, e.g. /uploadtest?len=100&num=1
http.HandleFunc("/uploadtest", func(w http.ResponseWriter, r *http.Request) {
defer GinkgoRecover()
num, err := strconv.Atoi(r.URL.Query().Get("num"))
Expect(err).ToNot(HaveOccurred())
response := "<html><body>\n<form id='form' action='https://quic.clemente.io/uploadhandler' method='post' enctype='multipart/form-data'>"
for i := 0; i < num; i++ {
response += "<input type='file' id='upload_" + strconv.Itoa(i) + "' name='uploadfile_" + strconv.Itoa(i) + "' />"
}
response += "</form><body></html>"
_, err = io.WriteString(w, response)
response := uploadHTML
response = strings.Replace(response, "LENGTH", r.URL.Query().Get("len"), -1)
response = strings.Replace(response, "NUM", r.URL.Query().Get("num"), -1)
_, err := io.WriteString(w, response)
Expect(err).NotTo(HaveOccurred())
testEndpointCalled = true
})
// Requires the len & num GET parameters, e.g. /downloadtest?len=100&num=1
http.HandleFunc("/downloadtest", func(w http.ResponseWriter, r *http.Request) {
defer GinkgoRecover()
response := downloadHTML
response = strings.Replace(response, "LENGTH", r.URL.Query().Get("len"), -1)
response = strings.Replace(response, "NUM", r.URL.Query().Get("num"), -1)
_, err := io.WriteString(w, response)
Expect(err).NotTo(HaveOccurred())
testEndpointCalled = true
})
http.HandleFunc("/uploadhandler", func(w http.ResponseWriter, r *http.Request) {
defer GinkgoRecover()
err := r.ParseMultipartForm(100 * (1 << 20)) // max. 100 MB
Expect(err).ToNot(HaveOccurred())
count := 0
for {
var file multipart.File
var handler *multipart.FileHeader
file, handler, err = r.FormFile("uploadfile_" + strconv.Itoa(count))
if err != nil {
break
}
count++
f, err2 := os.OpenFile(path.Join(uploadDir, handler.Filename), os.O_WRONLY|os.O_CREATE, 0666)
Expect(err2).ToNot(HaveOccurred())
io.Copy(f, file)
f.Close()
file.Close()
}
Expect(count).ToNot(BeZero()) // there have been at least one uploaded file in this request
_, err = io.WriteString(w, "")
l, err := strconv.Atoi(r.URL.Query().Get("len"))
Expect(err).NotTo(HaveOccurred())
defer r.Body.Close()
actual, err := ioutil.ReadAll(r.Body)
Expect(err).NotTo(HaveOccurred())
Expect(bytes.Equal(actual, generatePRData(l))).To(BeTrue())
atomic.AddInt32(&nFilesUploaded, 1)
})
http.HandleFunc("/done", func(w http.ResponseWriter, r *http.Request) {
doneCalled = true
})
}
@@ -210,137 +192,94 @@ func stopQuicServer() {
Expect(server.Close()).NotTo(HaveOccurred())
}
func setupSelenium() {
var err error
pullCmd := exec.Command("docker", "pull", "lclemente/standalone-chrome:dev")
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",
"--name", "quic-test-selenium",
"lclemente/standalone-chrome:dev",
)
docker, err = gexec.Start(dockerCmd, GinkgoWriter, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())
Eventually(docker.Out, 10).Should(gbytes.Say("Selenium Server is up and running"))
func waitForDone() {
Eventually(func() bool { return doneCalled }, 60).Should(BeTrue())
}
func stopSelenium() {
docker.Interrupt().Wait(10)
}
func getWebdriverForVersion(version protocol.VersionNumber) selenium.WebDriver {
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),
fmt.Sprintf(`--quic-version=QUIC_VERSION_%d`, version),
},
},
func waitForNUploaded(expected int) func() {
return func() {
Eventually(func() int32 {
return atomic.LoadInt32(&nFilesUploaded)
}, 60).Should(BeEquivalentTo(expected))
}
wd, err := selenium.NewRemote(caps, "http://localhost:4444/wd/hub")
Expect(err).NotTo(HaveOccurred())
return wd
}
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()
}
const commonJS = `
var buf = new ArrayBuffer(LENGTH);
var prng = new Uint8Array(buf);
var seed = 1;
for (var i = 0; i < LENGTH; i++) {
// https://en.wikipedia.org/wiki/Lehmer_random_number_generator
seed = seed * 48271 % 2147483647;
prng[i] = seed;
}
`
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()
}
const uploadHTML = `
<html>
<body>
<script>
console.log("Running DL test...");
` + commonJS + `
for (var i = 0; i < NUM; i++) {
var req = new XMLHttpRequest();
req.open("POST", "/uploadhandler?len=" + LENGTH, true);
req.send(buf);
}
</script>
</body>
</html>
`
const downloadHTML = `
<html>
<body>
<script>
console.log("Running DL test...");
` + commonJS + `
function verify(data) {
if (data.length !== LENGTH) return false;
for (var i = 0; i < LENGTH; i++) {
if (data[i] !== prng[i]) return false;
}
return true;
}
panic("no addr")
}
func removeDownload(filename string) {
cmd := exec.Command("docker", "exec", "-i", "quic-test-selenium", "rm", "-f", "/home/seluser/Downloads/"+filename)
session, err := gexec.Start(cmd, GinkgoWriter, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())
Eventually(session, 5).Should(gexec.Exit(0))
}
// getDownloadSize gets the file size of a file in the /home/seluser/Downloads folder in the docker container
func getDownloadSize(filename string) int {
var out bytes.Buffer
cmd := exec.Command("docker", "exec", "-i", "quic-test-selenium", "stat", "--printf=%s", "/home/seluser/Downloads/"+filename)
session, err := gexec.Start(cmd, &out, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())
Eventually(session, 5).Should(gexec.Exit())
if session.ExitCode() != 0 {
return 0
var nOK = 0;
for (var i = 0; i < NUM; i++) {
let req = new XMLHttpRequest();
req.responseType = "arraybuffer";
req.open("POST", "/prdata?len=" + LENGTH, true);
req.onreadystatechange = function () {
if (req.readyState === XMLHttpRequest.DONE && req.status === 200) {
if (verify(new Uint8Array(req.response))) {
nOK++;
if (nOK === NUM) {
console.log("Done :)");
var reqDone = new XMLHttpRequest();
reqDone.open("GET", "/done");
reqDone.send();
}
}
}
};
req.send();
}
Expect(out.Bytes()).ToNot(BeEmpty())
size, err := strconv.Atoi(string(out.Bytes()))
Expect(err).NotTo(HaveOccurred())
return size
}
</script>
</body>
</html>
`
// getFileSize gets the file size of a file on the local file system
func getFileSize(filename string) int {
file, err := os.Open(filename)
Expect(err).ToNot(HaveOccurred())
fi, err := file.Stat()
Expect(err).ToNot(HaveOccurred())
return int(fi.Size())
}
// getDownloadMD5 gets the md5 sum file of a file in the /home/seluser/Downloads folder in the docker container
func getDownloadMD5(filename string) []byte {
var out bytes.Buffer
cmd := exec.Command("docker", "exec", "-i", "quic-test-selenium", "md5sum", "/home/seluser/Downloads/"+filename)
session, err := gexec.Start(cmd, &out, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())
Eventually(session, 5).Should(gexec.Exit())
if session.ExitCode() != 0 {
return nil
// Same as in the JS code, see
// https://en.wikipedia.org/wiki/Lehmer_random_number_generator
func generatePRData(l int) []byte {
res := make([]byte, l)
seed := uint64(1)
for i := 0; i < l; i++ {
seed = seed * 48271 % 2147483647
res[i] = byte(seed)
}
Expect(out.Bytes()).ToNot(BeEmpty())
res, err := hex.DecodeString(string(out.Bytes()[0:32]))
Expect(err).NotTo(HaveOccurred())
return res
}
// getFileMD5 gets the md5 sum of a file on the local file system
func getFileMD5(filepath string) []byte {
var result []byte
file, err := os.Open(filepath)
Expect(err).ToNot(HaveOccurred())
defer file.Close()
hash := md5.New()
_, err = io.Copy(hash, file)
Expect(err).ToNot(HaveOccurred())
return hash.Sum(result)
}
// copyFileToDocker copies a file from the local file system into the /home/seluser/ directory in the docker container
func copyFileToDocker(filepath string) {
cmd := exec.Command("docker", "cp", filepath, "quic-test-selenium:/home/seluser/")
session, err := gexec.Start(cmd, GinkgoWriter, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())
Eventually(session, 5).Should(gexec.Exit(0))
}

View File

@@ -86,7 +86,7 @@ var _ = Describe("Server tests", func() {
"--certificate_file="+filepath.Join(tmpDir, "cert.pem"),
"--port="+serverPort,
)
session, err = Start(command, GinkgoWriter, GinkgoWriter)
session, err = Start(command, nil, GinkgoWriter)
Expect(err).NotTo(HaveOccurred())
}()
}