mirror of
https://github.com/golang/go
synced 2024-11-21 22:04:39 -07:00
httptest: introduce TempServer, clean up tests
This also breaks fs_test into two parts as the range tests test http's private httpRange and I had to change the fs_test package from "http" to "http_test" to use httptest which otherwise has a cyclic depedency back on http. Aside: we should start exposing the Range stuff in the future. R=rsc CC=golang-dev https://golang.org/cl/4261047
This commit is contained in:
parent
5f54c807f1
commit
f88abdad0f
@ -2,89 +2,22 @@
|
|||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package http
|
package http_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
. "http"
|
||||||
|
"http/httptest"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ParseRangeTests = []struct {
|
|
||||||
s string
|
|
||||||
length int64
|
|
||||||
r []httpRange
|
|
||||||
}{
|
|
||||||
{"", 0, nil},
|
|
||||||
{"foo", 0, nil},
|
|
||||||
{"bytes=", 0, nil},
|
|
||||||
{"bytes=5-4", 10, nil},
|
|
||||||
{"bytes=0-2,5-4", 10, nil},
|
|
||||||
{"bytes=0-9", 10, []httpRange{{0, 10}}},
|
|
||||||
{"bytes=0-", 10, []httpRange{{0, 10}}},
|
|
||||||
{"bytes=5-", 10, []httpRange{{5, 5}}},
|
|
||||||
{"bytes=0-20", 10, []httpRange{{0, 10}}},
|
|
||||||
{"bytes=15-,0-5", 10, nil},
|
|
||||||
{"bytes=-5", 10, []httpRange{{5, 5}}},
|
|
||||||
{"bytes=-15", 10, []httpRange{{0, 10}}},
|
|
||||||
{"bytes=0-499", 10000, []httpRange{{0, 500}}},
|
|
||||||
{"bytes=500-999", 10000, []httpRange{{500, 500}}},
|
|
||||||
{"bytes=-500", 10000, []httpRange{{9500, 500}}},
|
|
||||||
{"bytes=9500-", 10000, []httpRange{{9500, 500}}},
|
|
||||||
{"bytes=0-0,-1", 10000, []httpRange{{0, 1}, {9999, 1}}},
|
|
||||||
{"bytes=500-600,601-999", 10000, []httpRange{{500, 101}, {601, 399}}},
|
|
||||||
{"bytes=500-700,601-999", 10000, []httpRange{{500, 201}, {601, 399}}},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParseRange(t *testing.T) {
|
|
||||||
for _, test := range ParseRangeTests {
|
|
||||||
r := test.r
|
|
||||||
ranges, err := parseRange(test.s, test.length)
|
|
||||||
if err != nil && r != nil {
|
|
||||||
t.Errorf("parseRange(%q) returned error %q", test.s, err)
|
|
||||||
}
|
|
||||||
if len(ranges) != len(r) {
|
|
||||||
t.Errorf("len(parseRange(%q)) = %d, want %d", test.s, len(ranges), len(r))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for i := range r {
|
|
||||||
if ranges[i].start != r[i].start {
|
|
||||||
t.Errorf("parseRange(%q)[%d].start = %d, want %d", test.s, i, ranges[i].start, r[i].start)
|
|
||||||
}
|
|
||||||
if ranges[i].length != r[i].length {
|
|
||||||
t.Errorf("parseRange(%q)[%d].length = %d, want %d", test.s, i, ranges[i].length, r[i].length)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
testFile = "testdata/file"
|
testFile = "testdata/file"
|
||||||
testFileLength = 11
|
testFileLength = 11
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
serverOnce sync.Once
|
|
||||||
serverAddr string
|
|
||||||
)
|
|
||||||
|
|
||||||
func startServer(t *testing.T) {
|
|
||||||
serverOnce.Do(func() {
|
|
||||||
HandleFunc("/ServeFile", func(w ResponseWriter, r *Request) {
|
|
||||||
ServeFile(w, r, "testdata/file")
|
|
||||||
})
|
|
||||||
l, err := net.Listen("tcp", "127.0.0.1:0")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal("listen:", err)
|
|
||||||
}
|
|
||||||
serverAddr = l.Addr().String()
|
|
||||||
go Serve(l, nil)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
var ServeFileRangeTests = []struct {
|
var ServeFileRangeTests = []struct {
|
||||||
start, end int
|
start, end int
|
||||||
r string
|
r string
|
||||||
@ -99,7 +32,11 @@ var ServeFileRangeTests = []struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func TestServeFile(t *testing.T) {
|
func TestServeFile(t *testing.T) {
|
||||||
startServer(t)
|
ts := httptest.NewServer(HandlerFunc(func(w ResponseWriter, r *Request) {
|
||||||
|
ServeFile(w, r, "testdata/file")
|
||||||
|
}))
|
||||||
|
defer ts.Close()
|
||||||
|
|
||||||
var err os.Error
|
var err os.Error
|
||||||
|
|
||||||
file, err := ioutil.ReadFile(testFile)
|
file, err := ioutil.ReadFile(testFile)
|
||||||
@ -110,7 +47,7 @@ func TestServeFile(t *testing.T) {
|
|||||||
// set up the Request (re-used for all tests)
|
// set up the Request (re-used for all tests)
|
||||||
var req Request
|
var req Request
|
||||||
req.Header = make(Header)
|
req.Header = make(Header)
|
||||||
if req.URL, err = ParseURL("http://" + serverAddr + "/ServeFile"); err != nil {
|
if req.URL, err = ParseURL(ts.URL); err != nil {
|
||||||
t.Fatal("ParseURL:", err)
|
t.Fatal("ParseURL:", err)
|
||||||
}
|
}
|
||||||
req.Method = "GET"
|
req.Method = "GET"
|
||||||
@ -149,7 +86,7 @@ func TestServeFile(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getBody(t *testing.T, req Request) (*Response, []byte) {
|
func getBody(t *testing.T, req Request) (*Response, []byte) {
|
||||||
r, err := send(&req, DefaultTransport)
|
r, err := DefaultClient.Do(&req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(req.URL.String(), "send:", err)
|
t.Fatal(req.URL.String(), "send:", err)
|
||||||
}
|
}
|
||||||
|
@ -7,5 +7,6 @@ include ../../../Make.inc
|
|||||||
TARG=http/httptest
|
TARG=http/httptest
|
||||||
GOFILES=\
|
GOFILES=\
|
||||||
recorder.go\
|
recorder.go\
|
||||||
|
server.go\
|
||||||
|
|
||||||
include ../../../Make.pkg
|
include ../../../Make.pkg
|
||||||
|
42
src/pkg/http/httptest/server.go
Normal file
42
src/pkg/http/httptest/server.go
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Implementation of TempServer
|
||||||
|
|
||||||
|
package httptest
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"http"
|
||||||
|
"net"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A Server is an HTTP server listening on a system-chosen port on the
|
||||||
|
// local loopback interface, for use in end-to-end HTTP tests.
|
||||||
|
type Server struct {
|
||||||
|
URL string // base URL of form http://ipaddr:port with no trailing slash
|
||||||
|
Listener net.Listener
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewServer starts and returns a new Server.
|
||||||
|
// The caller should call Close when finished, to shut it down.
|
||||||
|
func NewServer(handler http.Handler) *Server {
|
||||||
|
ts := new(Server)
|
||||||
|
l, err := net.Listen("tcp", "127.0.0.1:0")
|
||||||
|
if err != nil {
|
||||||
|
if l, err = net.Listen("tcp6", "[::1]:0"); err != nil {
|
||||||
|
panic(fmt.Sprintf("httptest: failed to listen on a port: %v", err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ts.Listener = l
|
||||||
|
ts.URL = "http://" + l.Addr().String()
|
||||||
|
server := &http.Server{Handler: handler}
|
||||||
|
go server.Serve(l)
|
||||||
|
return ts
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close shuts down the temporary server.
|
||||||
|
func (s *Server) Close() {
|
||||||
|
s.Listener.Close()
|
||||||
|
}
|
57
src/pkg/http/range_test.go
Normal file
57
src/pkg/http/range_test.go
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
// Copyright 2011 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package http
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
var ParseRangeTests = []struct {
|
||||||
|
s string
|
||||||
|
length int64
|
||||||
|
r []httpRange
|
||||||
|
}{
|
||||||
|
{"", 0, nil},
|
||||||
|
{"foo", 0, nil},
|
||||||
|
{"bytes=", 0, nil},
|
||||||
|
{"bytes=5-4", 10, nil},
|
||||||
|
{"bytes=0-2,5-4", 10, nil},
|
||||||
|
{"bytes=0-9", 10, []httpRange{{0, 10}}},
|
||||||
|
{"bytes=0-", 10, []httpRange{{0, 10}}},
|
||||||
|
{"bytes=5-", 10, []httpRange{{5, 5}}},
|
||||||
|
{"bytes=0-20", 10, []httpRange{{0, 10}}},
|
||||||
|
{"bytes=15-,0-5", 10, nil},
|
||||||
|
{"bytes=-5", 10, []httpRange{{5, 5}}},
|
||||||
|
{"bytes=-15", 10, []httpRange{{0, 10}}},
|
||||||
|
{"bytes=0-499", 10000, []httpRange{{0, 500}}},
|
||||||
|
{"bytes=500-999", 10000, []httpRange{{500, 500}}},
|
||||||
|
{"bytes=-500", 10000, []httpRange{{9500, 500}}},
|
||||||
|
{"bytes=9500-", 10000, []httpRange{{9500, 500}}},
|
||||||
|
{"bytes=0-0,-1", 10000, []httpRange{{0, 1}, {9999, 1}}},
|
||||||
|
{"bytes=500-600,601-999", 10000, []httpRange{{500, 101}, {601, 399}}},
|
||||||
|
{"bytes=500-700,601-999", 10000, []httpRange{{500, 201}, {601, 399}}},
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseRange(t *testing.T) {
|
||||||
|
for _, test := range ParseRangeTests {
|
||||||
|
r := test.r
|
||||||
|
ranges, err := parseRange(test.s, test.length)
|
||||||
|
if err != nil && r != nil {
|
||||||
|
t.Errorf("parseRange(%q) returned error %q", test.s, err)
|
||||||
|
}
|
||||||
|
if len(ranges) != len(r) {
|
||||||
|
t.Errorf("len(parseRange(%q)) = %d, want %d", test.s, len(ranges), len(r))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for i := range r {
|
||||||
|
if ranges[i].start != r[i].start {
|
||||||
|
t.Errorf("parseRange(%q)[%d].start = %d, want %d", test.s, i, ranges[i].start, r[i].start)
|
||||||
|
}
|
||||||
|
if ranges[i].length != r[i].length {
|
||||||
|
t.Errorf("parseRange(%q)[%d].length = %d, want %d", test.s, i, ranges[i].length, r[i].length)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -171,13 +171,10 @@ func TestHostHandlers(t *testing.T) {
|
|||||||
for _, h := range handlers {
|
for _, h := range handlers {
|
||||||
Handle(h.pattern, stringHandler(h.msg))
|
Handle(h.pattern, stringHandler(h.msg))
|
||||||
}
|
}
|
||||||
l, err := net.Listen("tcp", "127.0.0.1:0") // any port
|
ts := httptest.NewServer(nil)
|
||||||
if err != nil {
|
defer ts.Close()
|
||||||
t.Fatal(err)
|
|
||||||
}
|
conn, err := net.Dial("tcp", "", ts.Listener.Addr().String())
|
||||||
defer l.Close()
|
|
||||||
go Serve(l, nil)
|
|
||||||
conn, err := net.Dial("tcp", "", l.Addr().String())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
@ -296,13 +293,6 @@ func TestServerTimeouts(t *testing.T) {
|
|||||||
|
|
||||||
// TestIdentityResponse verifies that a handler can unset
|
// TestIdentityResponse verifies that a handler can unset
|
||||||
func TestIdentityResponse(t *testing.T) {
|
func TestIdentityResponse(t *testing.T) {
|
||||||
l, err := net.Listen("tcp", "127.0.0.1:0")
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("failed to listen on a port: %v", err)
|
|
||||||
}
|
|
||||||
defer l.Close()
|
|
||||||
urlBase := "http://" + l.Addr().String() + "/"
|
|
||||||
|
|
||||||
handler := HandlerFunc(func(rw ResponseWriter, req *Request) {
|
handler := HandlerFunc(func(rw ResponseWriter, req *Request) {
|
||||||
rw.SetHeader("Content-Length", "3")
|
rw.SetHeader("Content-Length", "3")
|
||||||
rw.SetHeader("Transfer-Encoding", req.FormValue("te"))
|
rw.SetHeader("Transfer-Encoding", req.FormValue("te"))
|
||||||
@ -320,15 +310,15 @@ func TestIdentityResponse(t *testing.T) {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
server := &Server{Handler: handler}
|
ts := httptest.NewServer(handler)
|
||||||
go server.Serve(l)
|
defer ts.Close()
|
||||||
|
|
||||||
// Note: this relies on the assumption (which is true) that
|
// Note: this relies on the assumption (which is true) that
|
||||||
// Get sends HTTP/1.1 or greater requests. Otherwise the
|
// Get sends HTTP/1.1 or greater requests. Otherwise the
|
||||||
// server wouldn't have the choice to send back chunked
|
// server wouldn't have the choice to send back chunked
|
||||||
// responses.
|
// responses.
|
||||||
for _, te := range []string{"", "identity"} {
|
for _, te := range []string{"", "identity"} {
|
||||||
url := urlBase + "?te=" + te
|
url := ts.URL + "/?te=" + te
|
||||||
res, _, err := Get(url)
|
res, _, err := Get(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error with Get of %s: %v", url, err)
|
t.Fatalf("error with Get of %s: %v", url, err)
|
||||||
@ -346,15 +336,15 @@ func TestIdentityResponse(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Verify that ErrContentLength is returned
|
// Verify that ErrContentLength is returned
|
||||||
url := urlBase + "?overwrite=1"
|
url := ts.URL + "/?overwrite=1"
|
||||||
_, _, err = Get(url)
|
_, _, err := Get(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error with Get of %s: %v", url, err)
|
t.Fatalf("error with Get of %s: %v", url, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that the connection is closed when the declared Content-Length
|
// Verify that the connection is closed when the declared Content-Length
|
||||||
// is larger than what the handler wrote.
|
// is larger than what the handler wrote.
|
||||||
conn, err := net.Dial("tcp", "", l.Addr().String())
|
conn, err := net.Dial("tcp", "", ts.Listener.Addr().String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("error dialing: %v", err)
|
t.Fatalf("error dialing: %v", err)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user