summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/braintree/manners
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/braintree/manners')
-rw-r--r--vendor/github.com/braintree/manners/README.md4
-rw-r--r--vendor/github.com/braintree/manners/helpers_test.go141
-rw-r--r--vendor/github.com/braintree/manners/interfaces.go7
-rw-r--r--vendor/github.com/braintree/manners/server.go141
-rw-r--r--vendor/github.com/braintree/manners/server_test.go153
-rw-r--r--vendor/github.com/braintree/manners/static.go14
-rw-r--r--vendor/github.com/braintree/manners/test_helpers/certs.go29
-rw-r--r--vendor/github.com/braintree/manners/test_helpers/conn.go13
-rw-r--r--vendor/github.com/braintree/manners/test_helpers/listener.go34
-rw-r--r--vendor/github.com/braintree/manners/test_helpers/temp_file.go27
-rw-r--r--vendor/github.com/braintree/manners/test_helpers/wait_group.go33
-rw-r--r--vendor/github.com/braintree/manners/transition_test.go9
12 files changed, 224 insertions, 381 deletions
diff --git a/vendor/github.com/braintree/manners/README.md b/vendor/github.com/braintree/manners/README.md
index 09f6f9693..78e0fc01a 100644
--- a/vendor/github.com/braintree/manners/README.md
+++ b/vendor/github.com/braintree/manners/README.md
@@ -23,10 +23,6 @@ Manners ensures that all requests are served by incrementing a WaitGroup when a
If your request handler spawns Goroutines that are not guaranteed to finish with the request, you can ensure they are also completed with the `StartRoutine` and `FinishRoutine` functions on the server.
-### Known Issues
-
-Manners does not correctly shut down long-lived keepalive connections when issued a shutdown command. Clients on an idle keepalive connection may see a connection reset error rather than a close. See https://github.com/braintree/manners/issues/13 for details.
-
### Compatability
Manners 0.3.0 and above uses standard library functionality introduced in Go 1.3.
diff --git a/vendor/github.com/braintree/manners/helpers_test.go b/vendor/github.com/braintree/manners/helpers_test.go
index 3c11a081d..ba1422cb4 100644
--- a/vendor/github.com/braintree/manners/helpers_test.go
+++ b/vendor/github.com/braintree/manners/helpers_test.go
@@ -3,27 +3,30 @@ package manners
import (
"bufio"
"crypto/tls"
+ "errors"
"io/ioutil"
"net"
"net/http"
+ "os"
+ "sync"
"testing"
)
+func newServer() *GracefulServer {
+ return NewWithServer(new(http.Server))
+}
+
// a simple step-controllable http client
type client struct {
tls bool
addr net.Addr
connected chan error
sendrequest chan bool
- response chan *rawResponse
+ idle chan error
+ idlerelease chan bool
closed chan bool
}
-type rawResponse struct {
- body []string
- err error
-}
-
func (c *client) Run() {
go func() {
var err error
@@ -39,21 +42,19 @@ func (c *client) Run() {
for <-c.sendrequest {
_, err = conn.Write([]byte("GET / HTTP/1.1\nHost: localhost:8000\n\n"))
if err != nil {
- c.response <- &rawResponse{err: err}
+ c.idle <- err
}
// Read response; no content
scanner := bufio.NewScanner(conn)
- var lines []string
for scanner.Scan() {
// our null handler doesn't send a body, so we know the request is
// done when we reach the blank line after the headers
- line := scanner.Text()
- if line == "" {
+ if scanner.Text() == "" {
break
}
- lines = append(lines, line)
}
- c.response <- &rawResponse{lines, scanner.Err()}
+ c.idle <- scanner.Err()
+ <-c.idlerelease
}
conn.Close()
ioutil.ReadAll(conn)
@@ -67,7 +68,8 @@ func newClient(addr net.Addr, tls bool) *client {
tls: tls,
connected: make(chan error),
sendrequest: make(chan bool),
- response: make(chan *rawResponse),
+ idle: make(chan error),
+ idlerelease: make(chan bool),
closed: make(chan bool),
}
}
@@ -86,6 +88,7 @@ func startGenericServer(t *testing.T, server *GracefulServer, statechanged chan
}
}
+ //server.up = make(chan chan bool))
server.up = make(chan net.Listener)
exitchan := make(chan error)
@@ -117,3 +120,115 @@ func startTLSServer(t *testing.T, server *GracefulServer, certFile, keyFile stri
return startGenericServer(t, server, statechanged, runner)
}
+
+type tempFile struct {
+ *os.File
+}
+
+func newTempFile(content []byte) (*tempFile, error) {
+ f, err := ioutil.TempFile("", "graceful-test")
+ if err != nil {
+ return nil, err
+ }
+
+ f.Write(content)
+ return &tempFile{f}, nil
+}
+
+func (tf *tempFile) Unlink() {
+ if tf.File != nil {
+ os.Remove(tf.Name())
+ tf.File = nil
+ }
+}
+
+type testWg struct {
+ sync.Mutex
+ count int
+ waitCalled chan int
+}
+
+func newTestWg() *testWg {
+ return &testWg{
+ waitCalled: make(chan int, 1),
+ }
+}
+
+func (wg *testWg) Add(delta int) {
+ wg.Lock()
+ wg.count++
+ wg.Unlock()
+}
+
+func (wg *testWg) Done() {
+ wg.Lock()
+ wg.count--
+ wg.Unlock()
+}
+
+func (wg *testWg) Wait() {
+ wg.Lock()
+ wg.waitCalled <- wg.count
+ wg.Unlock()
+}
+
+type fakeConn struct {
+ net.Conn
+ closeCalled bool
+}
+
+func (c *fakeConn) Close() error {
+ c.closeCalled = true
+ return nil
+}
+
+type fakeListener struct {
+ acceptRelease chan bool
+ closeCalled chan bool
+}
+
+func newFakeListener() *fakeListener { return &fakeListener{make(chan bool, 1), make(chan bool, 1)} }
+
+func (l *fakeListener) Addr() net.Addr {
+ addr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:8080")
+ return addr
+}
+
+func (l *fakeListener) Close() error {
+ l.closeCalled <- true
+ l.acceptRelease <- true
+ return nil
+}
+
+func (l *fakeListener) Accept() (net.Conn, error) {
+ <-l.acceptRelease
+ return nil, errors.New("connection closed")
+}
+
+// localhostCert is a PEM-encoded TLS cert with SAN IPs
+// "127.0.0.1" and "[::1]", expiring at the last second of 2049 (the end
+// of ASN.1 time).
+// generated from src/pkg/crypto/tls:
+// go run generate_cert.go --rsa-bits 512 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
+var (
+ localhostCert = []byte(`-----BEGIN CERTIFICATE-----
+MIIBdzCCASOgAwIBAgIBADALBgkqhkiG9w0BAQUwEjEQMA4GA1UEChMHQWNtZSBD
+bzAeFw03MDAxMDEwMDAwMDBaFw00OTEyMzEyMzU5NTlaMBIxEDAOBgNVBAoTB0Fj
+bWUgQ28wWjALBgkqhkiG9w0BAQEDSwAwSAJBAN55NcYKZeInyTuhcCwFMhDHCmwa
+IUSdtXdcbItRB/yfXGBhiex00IaLXQnSU+QZPRZWYqeTEbFSgihqi1PUDy8CAwEA
+AaNoMGYwDgYDVR0PAQH/BAQDAgCkMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8GA1Ud
+EwEB/wQFMAMBAf8wLgYDVR0RBCcwJYILZXhhbXBsZS5jb22HBH8AAAGHEAAAAAAA
+AAAAAAAAAAAAAAEwCwYJKoZIhvcNAQEFA0EAAoQn/ytgqpiLcZu9XKbCJsJcvkgk
+Se6AbGXgSlq+ZCEVo0qIwSgeBqmsJxUu7NCSOwVJLYNEBO2DtIxoYVk+MA==
+-----END CERTIFICATE-----`)
+
+ localhostKey = []byte(`-----BEGIN RSA PRIVATE KEY-----
+MIIBPAIBAAJBAN55NcYKZeInyTuhcCwFMhDHCmwaIUSdtXdcbItRB/yfXGBhiex0
+0IaLXQnSU+QZPRZWYqeTEbFSgihqi1PUDy8CAwEAAQJBAQdUx66rfh8sYsgfdcvV
+NoafYpnEcB5s4m/vSVe6SU7dCK6eYec9f9wpT353ljhDUHq3EbmE4foNzJngh35d
+AekCIQDhRQG5Li0Wj8TM4obOnnXUXf1jRv0UkzE9AHWLG5q3AwIhAPzSjpYUDjVW
+MCUXgckTpKCuGwbJk7424Nb8bLzf3kllAiA5mUBgjfr/WtFSJdWcPQ4Zt9KTMNKD
+EUO0ukpTwEIl6wIhAMbGqZK3zAAFdq8DD2jPx+UJXnh0rnOkZBzDtJ6/iN69AiEA
+1Aq8MJgTaYsDQWyU/hDq5YkDJc9e9DSCvUIzqxQWMQE=
+-----END RSA PRIVATE KEY-----`)
+)
diff --git a/vendor/github.com/braintree/manners/interfaces.go b/vendor/github.com/braintree/manners/interfaces.go
deleted file mode 100644
index fd0732857..000000000
--- a/vendor/github.com/braintree/manners/interfaces.go
+++ /dev/null
@@ -1,7 +0,0 @@
-package manners
-
-type waitGroup interface {
- Add(int)
- Done()
- Wait()
-}
diff --git a/vendor/github.com/braintree/manners/server.go b/vendor/github.com/braintree/manners/server.go
index dfd3b873b..d51d99b81 100644
--- a/vendor/github.com/braintree/manners/server.go
+++ b/vendor/github.com/braintree/manners/server.go
@@ -60,32 +60,29 @@ import (
type GracefulServer struct {
*http.Server
- shutdown chan bool
- shutdownFinished chan bool
- wg waitGroup
- routinesCount int
+ shutdown chan bool
+ wg waitGroup
- lcsmu sync.RWMutex
- connections map[net.Conn]bool
+ lcsmu sync.RWMutex
+ lastConnState map[net.Conn]http.ConnState
up chan net.Listener // Only used by test code.
}
-// NewServer creates a new GracefulServer.
-func NewServer() *GracefulServer {
- return NewWithServer(new(http.Server))
+type waitGroup interface {
+ Add(int)
+ Done()
+ Wait()
}
// NewWithServer wraps an existing http.Server object and returns a
// GracefulServer that supports all of the original Server operations.
func NewWithServer(s *http.Server) *GracefulServer {
return &GracefulServer{
- Server: s,
- shutdown: make(chan bool),
- shutdownFinished: make(chan bool, 1),
- wg: new(sync.WaitGroup),
- routinesCount: 0,
- connections: make(map[net.Conn]bool),
+ Server: s,
+ shutdown: make(chan bool),
+ wg: new(sync.WaitGroup),
+ lastConnState: make(map[net.Conn]http.ConnState),
}
}
@@ -95,14 +92,6 @@ func (s *GracefulServer) Close() bool {
return <-s.shutdown
}
-// BlockingClose is similar to Close, except that it blocks until the last
-// connection has been closed.
-func (s *GracefulServer) BlockingClose() bool {
- result := s.Close()
- <-s.shutdownFinished
- return result
-}
-
// ListenAndServe provides a graceful equivalent of net/http.Serve.ListenAndServe.
func (s *GracefulServer) ListenAndServe() error {
addr := s.Addr
@@ -149,64 +138,56 @@ func (s *GracefulServer) ListenAndServeTLS(certFile, keyFile string) error {
// Serve provides a graceful equivalent net/http.Server.Serve.
func (s *GracefulServer) Serve(listener net.Listener) error {
- // Wrap the server HTTP handler into graceful one, that will close kept
- // alive connections if a new request is received after shutdown.
- gracefulHandler := newGracefulHandler(s.Server.Handler)
- s.Server.Handler = gracefulHandler
-
- // Start a goroutine that waits for a shutdown signal and will stop the
- // listener when it receives the signal. That in turn will result in
- // unblocking of the http.Serve call.
+ var closing int32
+
go func() {
s.shutdown <- true
close(s.shutdown)
- gracefulHandler.Close()
+ atomic.StoreInt32(&closing, 1)
s.Server.SetKeepAlivesEnabled(false)
listener.Close()
}()
originalConnState := s.Server.ConnState
-
- // s.ConnState is invoked by the net/http.Server every time a connection
- // changes state. It keeps track of each connection's state over time,
- // enabling manners to handle persisted connections correctly.
s.ConnState = func(conn net.Conn, newState http.ConnState) {
s.lcsmu.RLock()
- protected := s.connections[conn]
+ lastConnState := s.lastConnState[conn]
s.lcsmu.RUnlock()
switch newState {
-
case http.StateNew:
// New connection -> StateNew
- protected = true
s.StartRoutine()
case http.StateActive:
// (StateNew, StateIdle) -> StateActive
- if gracefulHandler.IsClosed() {
- conn.Close()
- break
+ if lastConnState == http.StateIdle {
+ // The connection transitioned from idle back to active
+ s.StartRoutine()
}
- if !protected {
- protected = true
- s.StartRoutine()
+ case http.StateIdle:
+ // StateActive -> StateIdle
+ // Immediately close newly idle connections; if not they may make
+ // one more request before SetKeepAliveEnabled(false) takes effect.
+ if atomic.LoadInt32(&closing) == 1 {
+ conn.Close()
}
+ s.FinishRoutine()
- default:
- // (StateNew, StateActive) -> (StateIdle, StateClosed, StateHiJacked)
- if protected {
+ case http.StateClosed, http.StateHijacked:
+ // (StateNew, StateActive, StateIdle) -> (StateClosed, StateHiJacked)
+ // If the connection was idle we do not need to decrement the counter.
+ if lastConnState != http.StateIdle {
s.FinishRoutine()
- protected = false
}
}
s.lcsmu.Lock()
if newState == http.StateClosed || newState == http.StateHijacked {
- delete(s.connections, conn)
+ delete(s.lastConnState, conn)
} else {
- s.connections[conn] = protected
+ s.lastConnState[conn] = newState
}
s.lcsmu.Unlock()
@@ -220,16 +201,15 @@ func (s *GracefulServer) Serve(listener net.Listener) error {
if s.up != nil {
s.up <- listener
}
-
err := s.Server.Serve(listener)
- // An error returned on shutdown is not worth reporting.
- if err != nil && gracefulHandler.IsClosed() {
- err = nil
+
+ // This block is reached when the server has received a shut down command
+ // or a real error happened.
+ if err == nil || atomic.LoadInt32(&closing) == 1 {
+ s.wg.Wait()
+ return nil
}
- // Wait for pending requests to complete regardless the Serve result.
- s.wg.Wait()
- s.shutdownFinished <- true
return err
}
@@ -237,56 +217,11 @@ func (s *GracefulServer) Serve(listener net.Listener) error {
// starts more goroutines and these goroutines are not guaranteed to finish
// before the request.
func (s *GracefulServer) StartRoutine() {
- s.lcsmu.Lock()
- defer s.lcsmu.Unlock()
s.wg.Add(1)
- s.routinesCount++
}
// FinishRoutine decrements the server's WaitGroup. Use this to complement
// StartRoutine().
func (s *GracefulServer) FinishRoutine() {
- s.lcsmu.Lock()
- defer s.lcsmu.Unlock()
s.wg.Done()
- s.routinesCount--
-}
-
-// RoutinesCount returns the number of currently running routines
-func (s *GracefulServer) RoutinesCount() int {
- s.lcsmu.RLock()
- defer s.lcsmu.RUnlock()
- return s.routinesCount
-}
-
-// gracefulHandler is used by GracefulServer to prevent calling ServeHTTP on
-// to be closed kept-alive connections during the server shutdown.
-type gracefulHandler struct {
- closed int32 // accessed atomically.
- wrapped http.Handler
-}
-
-func newGracefulHandler(wrapped http.Handler) *gracefulHandler {
- return &gracefulHandler{
- wrapped: wrapped,
- }
-}
-
-func (gh *gracefulHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
- if atomic.LoadInt32(&gh.closed) == 0 {
- gh.wrapped.ServeHTTP(w, r)
- return
- }
- r.Body.Close()
- // Server is shutting down at this moment, and the connection that this
- // handler is being called on is about to be closed. So we do not need to
- // actually execute the handler logic.
-}
-
-func (gh *gracefulHandler) Close() {
- atomic.StoreInt32(&gh.closed, 1)
-}
-
-func (gh *gracefulHandler) IsClosed() bool {
- return atomic.LoadInt32(&gh.closed) == 1
}
diff --git a/vendor/github.com/braintree/manners/server_test.go b/vendor/github.com/braintree/manners/server_test.go
index 994284216..108863040 100644
--- a/vendor/github.com/braintree/manners/server_test.go
+++ b/vendor/github.com/braintree/manners/server_test.go
@@ -5,34 +5,13 @@ import (
"net/http"
"testing"
"time"
-
- helpers "github.com/braintree/manners/test_helpers"
)
-type httpInterface interface {
- ListenAndServe() error
- ListenAndServeTLS(certFile, keyFile string) error
- Serve(listener net.Listener) error
-}
-
-// Test that the method signatures of the methods we override from net/http/Server match those of the original.
-func TestInterface(t *testing.T) {
- var original, ours interface{}
- original = &http.Server{}
- ours = &GracefulServer{}
- if _, ok := original.(httpInterface); !ok {
- t.Errorf("httpInterface definition does not match the canonical server!")
- }
- if _, ok := ours.(httpInterface); !ok {
- t.Errorf("GracefulServer does not implement httpInterface")
- }
-}
-
// Tests that the server allows in-flight requests to complete
// before shutting down.
func TestGracefulness(t *testing.T) {
- server := NewServer()
- wg := helpers.NewWaitGroup()
+ server := newServer()
+ wg := newTestWg()
server.wg = wg
statechanged := make(chan http.ConnState)
listener, exitchan := startServer(t, server, statechanged)
@@ -44,13 +23,14 @@ func TestGracefulness(t *testing.T) {
if err := <-client.connected; err != nil {
t.Fatal("Client failed to connect to server", err)
}
- // Even though the client is connected, the server ConnState handler may
- // not know about that yet. So wait until it is called.
- waitForState(t, statechanged, http.StateNew, "Request not received")
+ // avoid a race between the client connection and the server accept
+ if state := <-statechanged; state != http.StateNew {
+ t.Fatal("Unexpected state", state)
+ }
server.Close()
- waiting := <-wg.WaitCalled
+ waiting := <-wg.waitCalled
if waiting < 1 {
t.Errorf("Expected the waitgroup to equal 1 at shutdown; actually %d", waiting)
}
@@ -64,23 +44,11 @@ func TestGracefulness(t *testing.T) {
}
}
-// Tests that starting the server and closing in 2 new, separate goroutines doesnot
-// get flagged by the race detector (need to run 'go test' w/the -race flag)
-func TestRacyClose(t *testing.T) {
- go func() {
- ListenAndServe(":9000", nil)
- }()
-
- go func() {
- Close()
- }()
-}
-
// Tests that the server begins to shut down when told to and does not accept
// new requests once shutdown has begun
func TestShutdown(t *testing.T) {
- server := NewServer()
- wg := helpers.NewWaitGroup()
+ server := newServer()
+ wg := newTestWg()
server.wg = wg
statechanged := make(chan http.ConnState)
listener, exitchan := startServer(t, server, statechanged)
@@ -92,9 +60,10 @@ func TestShutdown(t *testing.T) {
if err := <-client1.connected; err != nil {
t.Fatal("Client failed to connect to server", err)
}
- // Even though the client is connected, the server ConnState handler may
- // not know about that yet. So wait until it is called.
- waitForState(t, statechanged, http.StateNew, "Request not received")
+ // avoid a race between the client connection and the server accept
+ if state := <-statechanged; state != http.StateNew {
+ t.Fatal("Unexpected state", state)
+ }
// start the shutdown; once it hits waitgroup.Wait()
// the listener should of been closed, though client1 is still connected
@@ -105,7 +74,7 @@ func TestShutdown(t *testing.T) {
t.Fatal("second call to Close returned true")
}
- waiting := <-wg.WaitCalled
+ waiting := <-wg.waitCalled
if waiting != 1 {
t.Errorf("Waitcount should be one, got %d", waiting)
}
@@ -124,32 +93,36 @@ func TestShutdown(t *testing.T) {
<-exitchan
}
-// If a request is sent to a closed server via a kept alive connection then
-// the server closes the connection upon receiving the request.
-func TestRequestAfterClose(t *testing.T) {
- // Given
- server := NewServer()
- srvStateChangedCh := make(chan http.ConnState, 100)
- listener, srvClosedCh := startServer(t, server, srvStateChangedCh)
+// Test that a connection is closed upon reaching an idle state if and only if the server
+// is shutting down.
+func TestCloseOnIdle(t *testing.T) {
+ server := newServer()
+ wg := newTestWg()
+ server.wg = wg
+ fl := newFakeListener()
+ runner := func() error {
+ return server.Serve(fl)
+ }
- client := newClient(listener.Addr(), false)
- client.Run()
- <-client.connected
- client.sendrequest <- true
- <-client.response
+ startGenericServer(t, server, nil, runner)
- server.Close()
- if err := <-srvClosedCh; err != nil {
- t.Error("Unexpected error during shutdown", err)
+ // Change to idle state while server is not closing; Close should not be called
+ conn := &fakeConn{}
+ server.ConnState(conn, http.StateIdle)
+ if conn.closeCalled {
+ t.Error("Close was called unexpected")
}
- // When
- client.sendrequest <- true
- rr := <-client.response
+ server.Close()
- // Then
- if rr.body != nil || rr.err != nil {
- t.Errorf("Request should be rejected, body=%v, err=%v", rr.body, rr.err)
+ // wait until the server calls Close() on the listener
+ // by that point the atomic closing variable will have been updated, avoiding a race.
+ <-fl.closeCalled
+
+ conn = &fakeConn{}
+ server.ConnState(conn, http.StateIdle)
+ if !conn.closeCalled {
+ t.Error("Close was not called")
}
}
@@ -169,8 +142,8 @@ func waitForState(t *testing.T, waiter chan http.ConnState, state http.ConnState
// Test that a request moving from active->idle->active using an actual
// network connection still results in a corect shutdown
func TestStateTransitionActiveIdleActive(t *testing.T) {
- server := NewServer()
- wg := helpers.NewWaitGroup()
+ server := newServer()
+ wg := newTestWg()
statechanged := make(chan http.ConnState)
server.wg = wg
listener, exitchan := startServer(t, server, statechanged)
@@ -186,14 +159,15 @@ func TestStateTransitionActiveIdleActive(t *testing.T) {
for i := 0; i < 2; i++ {
client.sendrequest <- true
waitForState(t, statechanged, http.StateActive, "Client failed to reach active state")
- <-client.response
+ <-client.idle
+ client.idlerelease <- true
waitForState(t, statechanged, http.StateIdle, "Client failed to reach idle state")
}
// client is now in an idle state
server.Close()
- waiting := <-wg.WaitCalled
+ waiting := <-wg.waitCalled
if waiting != 0 {
t.Errorf("Waitcount should be zero, got %d", waiting)
}
@@ -211,8 +185,8 @@ func TestStateTransitionActiveIdleClosed(t *testing.T) {
exitchan chan error
)
- keyFile, err1 := helpers.NewTempFile(helpers.Key)
- certFile, err2 := helpers.NewTempFile(helpers.Cert)
+ keyFile, err1 := newTempFile(localhostKey)
+ certFile, err2 := newTempFile(localhostCert)
defer keyFile.Unlink()
defer certFile.Unlink()
@@ -221,8 +195,8 @@ func TestStateTransitionActiveIdleClosed(t *testing.T) {
}
for _, withTLS := range []bool{false, true} {
- server := NewServer()
- wg := helpers.NewWaitGroup()
+ server := newServer()
+ wg := newTestWg()
statechanged := make(chan http.ConnState)
server.wg = wg
if withTLS {
@@ -242,11 +216,12 @@ func TestStateTransitionActiveIdleClosed(t *testing.T) {
client.sendrequest <- true
waitForState(t, statechanged, http.StateActive, "Client failed to reach active state")
- rr := <-client.response
- if rr.err != nil {
- t.Fatalf("tls=%t unexpected error from client %s", withTLS, rr.err)
+ err := <-client.idle
+ if err != nil {
+ t.Fatalf("tls=%t unexpected error from client %s", withTLS, err)
}
+ client.idlerelease <- true
waitForState(t, statechanged, http.StateIdle, "Client failed to reach idle state")
// client is now in an idle state
@@ -255,7 +230,7 @@ func TestStateTransitionActiveIdleClosed(t *testing.T) {
waitForState(t, statechanged, http.StateClosed, "Client failed to reach closed state")
server.Close()
- waiting := <-wg.WaitCalled
+ waiting := <-wg.waitCalled
if waiting != 0 {
t.Errorf("Waitcount should be zero, got %d", waiting)
}
@@ -265,25 +240,3 @@ func TestStateTransitionActiveIdleClosed(t *testing.T) {
}
}
}
-
-func TestRoutinesCount(t *testing.T) {
- var count int
- server := NewServer()
-
- count = server.RoutinesCount()
- if count != 0 {
- t.Errorf("Expected the routines count to equal 0; actually %d", count)
- }
-
- server.StartRoutine()
- count = server.RoutinesCount()
- if count != 1 {
- t.Errorf("Expected the routines count to equal 1; actually %d", count)
- }
-
- server.FinishRoutine()
- count = server.RoutinesCount()
- if count != 0 {
- t.Errorf("Expected the routines count to equal 0; actually %d", count)
- }
-}
diff --git a/vendor/github.com/braintree/manners/static.go b/vendor/github.com/braintree/manners/static.go
index b53950675..2a74b094b 100644
--- a/vendor/github.com/braintree/manners/static.go
+++ b/vendor/github.com/braintree/manners/static.go
@@ -3,23 +3,14 @@ package manners
import (
"net"
"net/http"
- "sync"
)
-var (
- defaultServer *GracefulServer
- defaultServerLock = &sync.Mutex{}
-)
-
-func init() {
- defaultServerLock.Lock()
-}
+var defaultServer *GracefulServer
// ListenAndServe provides a graceful version of the function provided by the
// net/http package. Call Close() to stop the server.
func ListenAndServe(addr string, handler http.Handler) error {
defaultServer = NewWithServer(&http.Server{Addr: addr, Handler: handler})
- defaultServerLock.Unlock()
return defaultServer.ListenAndServe()
}
@@ -27,7 +18,6 @@ func ListenAndServe(addr string, handler http.Handler) error {
// net/http package. Call Close() to stop the server.
func ListenAndServeTLS(addr string, certFile string, keyFile string, handler http.Handler) error {
defaultServer = NewWithServer(&http.Server{Addr: addr, Handler: handler})
- defaultServerLock.Unlock()
return defaultServer.ListenAndServeTLS(certFile, keyFile)
}
@@ -35,13 +25,11 @@ func ListenAndServeTLS(addr string, certFile string, keyFile string, handler htt
// package. Call Close() to stop the server.
func Serve(l net.Listener, handler http.Handler) error {
defaultServer = NewWithServer(&http.Server{Handler: handler})
- defaultServerLock.Unlock()
return defaultServer.Serve(l)
}
// Shuts down the default server used by ListenAndServe, ListenAndServeTLS and
// Serve. It returns true if it's the first time Close is called.
func Close() bool {
- defaultServerLock.Lock()
return defaultServer.Close()
}
diff --git a/vendor/github.com/braintree/manners/test_helpers/certs.go b/vendor/github.com/braintree/manners/test_helpers/certs.go
deleted file mode 100644
index ede248b3d..000000000
--- a/vendor/github.com/braintree/manners/test_helpers/certs.go
+++ /dev/null
@@ -1,29 +0,0 @@
-package test_helpers
-
-// A PEM-encoded TLS cert with SAN IPs "127.0.0.1" and "[::1]", expiring at the
-// last second of 2049 (the end of ASN.1 time).
-
-// generated from src/pkg/crypto/tls:
-// go run generate_cert.go --rsa-bits 512 --host 127.0.0.1,::1,example.com --ca --start-date "Jan 1 00:00:00 1970" --duration=1000000h
-var (
- Cert = []byte(`-----BEGIN CERTIFICATE-----
-MIIBdzCCASOgAwIBAgIBADALBgkqhkiG9w0BAQUwEjEQMA4GA1UEChMHQWNtZSBD
-bzAeFw03MDAxMDEwMDAwMDBaFw00OTEyMzEyMzU5NTlaMBIxEDAOBgNVBAoTB0Fj
-bWUgQ28wWjALBgkqhkiG9w0BAQEDSwAwSAJBAN55NcYKZeInyTuhcCwFMhDHCmwa
-IUSdtXdcbItRB/yfXGBhiex00IaLXQnSU+QZPRZWYqeTEbFSgihqi1PUDy8CAwEA
-AaNoMGYwDgYDVR0PAQH/BAQDAgCkMBMGA1UdJQQMMAoGCCsGAQUFBwMBMA8GA1Ud
-EwEB/wQFMAMBAf8wLgYDVR0RBCcwJYILZXhhbXBsZS5jb22HBH8AAAGHEAAAAAAA
-AAAAAAAAAAAAAAEwCwYJKoZIhvcNAQEFA0EAAoQn/ytgqpiLcZu9XKbCJsJcvkgk
-Se6AbGXgSlq+ZCEVo0qIwSgeBqmsJxUu7NCSOwVJLYNEBO2DtIxoYVk+MA==
------END CERTIFICATE-----`)
-
- Key = []byte(`-----BEGIN RSA PRIVATE KEY-----
-MIIBPAIBAAJBAN55NcYKZeInyTuhcCwFMhDHCmwaIUSdtXdcbItRB/yfXGBhiex0
-0IaLXQnSU+QZPRZWYqeTEbFSgihqi1PUDy8CAwEAAQJBAQdUx66rfh8sYsgfdcvV
-NoafYpnEcB5s4m/vSVe6SU7dCK6eYec9f9wpT353ljhDUHq3EbmE4foNzJngh35d
-AekCIQDhRQG5Li0Wj8TM4obOnnXUXf1jRv0UkzE9AHWLG5q3AwIhAPzSjpYUDjVW
-MCUXgckTpKCuGwbJk7424Nb8bLzf3kllAiA5mUBgjfr/WtFSJdWcPQ4Zt9KTMNKD
-EUO0ukpTwEIl6wIhAMbGqZK3zAAFdq8DD2jPx+UJXnh0rnOkZBzDtJ6/iN69AiEA
-1Aq8MJgTaYsDQWyU/hDq5YkDJc9e9DSCvUIzqxQWMQE=
------END RSA PRIVATE KEY-----`)
-)
diff --git a/vendor/github.com/braintree/manners/test_helpers/conn.go b/vendor/github.com/braintree/manners/test_helpers/conn.go
deleted file mode 100644
index 8c610f58e..000000000
--- a/vendor/github.com/braintree/manners/test_helpers/conn.go
+++ /dev/null
@@ -1,13 +0,0 @@
-package test_helpers
-
-import "net"
-
-type Conn struct {
- net.Conn
- CloseCalled bool
-}
-
-func (c *Conn) Close() error {
- c.CloseCalled = true
- return nil
-}
diff --git a/vendor/github.com/braintree/manners/test_helpers/listener.go b/vendor/github.com/braintree/manners/test_helpers/listener.go
deleted file mode 100644
index e3af35a6e..000000000
--- a/vendor/github.com/braintree/manners/test_helpers/listener.go
+++ /dev/null
@@ -1,34 +0,0 @@
-package test_helpers
-
-import (
- "errors"
- "net"
-)
-
-type Listener struct {
- AcceptRelease chan bool
- CloseCalled chan bool
-}
-
-func NewListener() *Listener {
- return &Listener{
- make(chan bool, 1),
- make(chan bool, 1),
- }
-}
-
-func (l *Listener) Addr() net.Addr {
- addr, _ := net.ResolveTCPAddr("tcp", "127.0.0.1:8080")
- return addr
-}
-
-func (l *Listener) Close() error {
- l.CloseCalled <- true
- l.AcceptRelease <- true
- return nil
-}
-
-func (l *Listener) Accept() (net.Conn, error) {
- <-l.AcceptRelease
- return nil, errors.New("connection closed")
-}
diff --git a/vendor/github.com/braintree/manners/test_helpers/temp_file.go b/vendor/github.com/braintree/manners/test_helpers/temp_file.go
deleted file mode 100644
index c4aa263a0..000000000
--- a/vendor/github.com/braintree/manners/test_helpers/temp_file.go
+++ /dev/null
@@ -1,27 +0,0 @@
-package test_helpers
-
-import (
- "io/ioutil"
- "os"
-)
-
-type TempFile struct {
- *os.File
-}
-
-func NewTempFile(content []byte) (*TempFile, error) {
- f, err := ioutil.TempFile("", "graceful-test")
- if err != nil {
- return nil, err
- }
-
- f.Write(content)
- return &TempFile{f}, nil
-}
-
-func (tf *TempFile) Unlink() {
- if tf.File != nil {
- os.Remove(tf.Name())
- tf.File = nil
- }
-}
diff --git a/vendor/github.com/braintree/manners/test_helpers/wait_group.go b/vendor/github.com/braintree/manners/test_helpers/wait_group.go
deleted file mode 100644
index 1df590db7..000000000
--- a/vendor/github.com/braintree/manners/test_helpers/wait_group.go
+++ /dev/null
@@ -1,33 +0,0 @@
-package test_helpers
-
-import "sync"
-
-type WaitGroup struct {
- sync.Mutex
- Count int
- WaitCalled chan int
-}
-
-func NewWaitGroup() *WaitGroup {
- return &WaitGroup{
- WaitCalled: make(chan int, 1),
- }
-}
-
-func (wg *WaitGroup) Add(delta int) {
- wg.Lock()
- wg.Count++
- wg.Unlock()
-}
-
-func (wg *WaitGroup) Done() {
- wg.Lock()
- wg.Count--
- wg.Unlock()
-}
-
-func (wg *WaitGroup) Wait() {
- wg.Lock()
- wg.WaitCalled <- wg.Count
- wg.Unlock()
-}
diff --git a/vendor/github.com/braintree/manners/transition_test.go b/vendor/github.com/braintree/manners/transition_test.go
index 5d398514e..ffa06d3eb 100644
--- a/vendor/github.com/braintree/manners/transition_test.go
+++ b/vendor/github.com/braintree/manners/transition_test.go
@@ -1,7 +1,6 @@
package manners
import (
- helpers "github.com/braintree/manners/test_helpers"
"net/http"
"strings"
"testing"
@@ -31,18 +30,18 @@ type transitionTest struct {
}
func testStateTransition(t *testing.T, test transitionTest) {
- server := NewServer()
- wg := helpers.NewWaitGroup()
+ server := newServer()
+ wg := newTestWg()
server.wg = wg
startServer(t, server, nil)
- conn := &helpers.Conn{}
+ conn := &fakeConn{}
for _, newState := range test.states {
server.ConnState(conn, newState)
}
server.Close()
- waiting := <-wg.WaitCalled
+ waiting := <-wg.waitCalled
if waiting != test.expectedWgCount {
names := make([]string, len(test.states))
for i, s := range test.states {