summaryrefslogtreecommitdiffstats
path: root/Godeps/_workspace/src/github.com/braintree/manners/server_test.go
diff options
context:
space:
mode:
author=Corey Hulen <corey@hulen.com>2015-11-23 15:53:48 -0800
committer=Corey Hulen <corey@hulen.com>2015-11-23 15:53:48 -0800
commit4f4cd5e63573da4d6edcc7d4213afaca67c19f88 (patch)
treecefbc7af53629d97644ca2f6b2369e9d879f0101 /Godeps/_workspace/src/github.com/braintree/manners/server_test.go
parentf8a3c9a14edca6df0647d89cf225f2470cbe025c (diff)
downloadchat-4f4cd5e63573da4d6edcc7d4213afaca67c19f88.tar.gz
chat-4f4cd5e63573da4d6edcc7d4213afaca67c19f88.tar.bz2
chat-4f4cd5e63573da4d6edcc7d4213afaca67c19f88.zip
upgrading libs
Diffstat (limited to 'Godeps/_workspace/src/github.com/braintree/manners/server_test.go')
-rw-r--r--Godeps/_workspace/src/github.com/braintree/manners/server_test.go273
1 files changed, 228 insertions, 45 deletions
diff --git a/Godeps/_workspace/src/github.com/braintree/manners/server_test.go b/Godeps/_workspace/src/github.com/braintree/manners/server_test.go
index 0da015566..e73613aa8 100644
--- a/Godeps/_workspace/src/github.com/braintree/manners/server_test.go
+++ b/Godeps/_workspace/src/github.com/braintree/manners/server_test.go
@@ -1,71 +1,254 @@
package manners
import (
+ helpers "github.com/mattermost/platform/Godeps/_workspace/src/github.com/braintree/manners/test_helpers"
+ "net"
"net/http"
"testing"
+ "time"
)
-// Tests that the server allows in-flight requests to complete before shutting
-// down.
+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) {
- ready := make(chan bool)
- done := make(chan bool)
+ server := newServer()
+ wg := helpers.NewWaitGroup()
+ server.wg = wg
+ statechanged := make(chan http.ConnState)
+ listener, exitchan := startServer(t, server, statechanged)
- exited := false
+ client := newClient(listener.Addr(), false)
+ client.Run()
- handler := newBlockingHandler(ready, done)
- server := NewServer()
+ // wait for client to connect, but don't let it send the request yet
+ 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")
- go func() {
- err := server.ListenAndServe(":7000", handler)
- if err != nil {
- t.Error(err)
- }
+ server.Close()
+
+ waiting := <-wg.WaitCalled
+ if waiting < 1 {
+ t.Errorf("Expected the waitgroup to equal 1 at shutdown; actually %d", waiting)
+ }
+
+ // allow the client to finish sending the request and make sure the server exits after
+ // (client will be in connected but idle state at that point)
+ client.sendrequest <- true
+ close(client.sendrequest)
+ if err := <-exitchan; err != nil {
+ t.Error("Unexpected error during shutdown", err)
+ }
+}
+
+// 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.wg = wg
+ statechanged := make(chan http.ConnState)
+ listener, exitchan := startServer(t, server, statechanged)
+
+ client1 := newClient(listener.Addr(), false)
+ client1.Run()
+
+ // wait for client1 to connect
+ 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")
+
+ // start the shutdown; once it hits waitgroup.Wait()
+ // the listener should of been closed, though client1 is still connected
+ if server.Close() != true {
+ t.Fatal("first call to Close returned false")
+ }
+ if server.Close() != false {
+ t.Fatal("second call to Close returned true")
+ }
+
+ waiting := <-wg.WaitCalled
+ if waiting != 1 {
+ t.Errorf("Waitcount should be one, got %d", waiting)
+ }
+
+ // should get connection refused at this point
+ client2 := newClient(listener.Addr(), false)
+ client2.Run()
+
+ if err := <-client2.connected; err == nil {
+ t.Fatal("client2 connected when it should of received connection refused")
+ }
+
+ // let client1 finish so the server can exit
+ close(client1.sendrequest) // don't bother sending an actual request
+
+ <-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)
- exited = true
- }()
+ client := newClient(listener.Addr(), false)
+ client.Run()
+ <-client.connected
+ client.sendrequest <- true
+ <-client.response
- go func() {
- _, err := http.Get("http://localhost:7000")
- if err != nil {
- t.Error(err)
+ server.Close()
+ if err := <-srvClosedCh; err != nil {
+ t.Error("Unexpected error during shutdown", err)
+ }
+
+ // When
+ client.sendrequest <- true
+ rr := <-client.response
+
+ // Then
+ if rr.body != nil || rr.err != nil {
+ t.Errorf("Request should be rejected, body=%v, err=%v", rr.body, rr.err)
+ }
+}
+
+func waitForState(t *testing.T, waiter chan http.ConnState, state http.ConnState, errmsg string) {
+ for {
+ select {
+ case ns := <-waiter:
+ if ns == state {
+ return
+ }
+ case <-time.After(time.Second):
+ t.Fatal(errmsg)
}
- }()
+ }
+}
- // This will block until the server is inside the handler function.
- <-ready
+// 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()
+ statechanged := make(chan http.ConnState)
+ server.wg = wg
+ listener, exitchan := startServer(t, server, statechanged)
- server.Shutdown <- true
- <-done
+ client := newClient(listener.Addr(), false)
+ client.Run()
+
+ // wait for client to connect, but don't let it send the request
+ if err := <-client.connected; err != nil {
+ t.Fatal("Client failed to connect to server", err)
+ }
+
+ for i := 0; i < 2; i++ {
+ client.sendrequest <- true
+ waitForState(t, statechanged, http.StateActive, "Client failed to reach active state")
+ <-client.response
+ waitForState(t, statechanged, http.StateIdle, "Client failed to reach idle state")
+ }
+
+ // client is now in an idle state
+
+ server.Close()
+ waiting := <-wg.WaitCalled
+ if waiting != 0 {
+ t.Errorf("Waitcount should be zero, got %d", waiting)
+ }
- if exited {
- t.Fatal("The request did not complete before server exited")
- } else {
- // The handler is being allowed to run to completion; test passes.
+ if err := <-exitchan; err != nil {
+ t.Error("Unexpected error during shutdown", err)
}
}
-// Tests that the server begins to shut down when told to and does not accept
-// new requests
-func TestShutdown(t *testing.T) {
- handler := newTestHandler()
- server := NewServer()
- exited := make(chan bool)
-
- go func() {
- err := server.ListenAndServe(":7100", handler)
- if err != nil {
- t.Error(err)
+// Test state transitions from new->active->-idle->closed using an actual
+// network connection and make sure the waitgroup count is correct at the end.
+func TestStateTransitionActiveIdleClosed(t *testing.T) {
+ var (
+ listener net.Listener
+ exitchan chan error
+ )
+
+ keyFile, err1 := helpers.NewTempFile(helpers.Key)
+ certFile, err2 := helpers.NewTempFile(helpers.Cert)
+ defer keyFile.Unlink()
+ defer certFile.Unlink()
+
+ if err1 != nil || err2 != nil {
+ t.Fatal("Failed to create temporary files", err1, err2)
+ }
+
+ for _, withTLS := range []bool{false, true} {
+ server := newServer()
+ wg := helpers.NewWaitGroup()
+ statechanged := make(chan http.ConnState)
+ server.wg = wg
+ if withTLS {
+ listener, exitchan = startTLSServer(t, server, certFile.Name(), keyFile.Name(), statechanged)
+ } else {
+ listener, exitchan = startServer(t, server, statechanged)
}
- exited <- true
- }()
- server.Shutdown <- true
+ client := newClient(listener.Addr(), withTLS)
+ client.Run()
+
+ // wait for client to connect, but don't let it send the request
+ if err := <-client.connected; err != nil {
+ t.Fatal("Client failed to connect to server", err)
+ }
- <-exited
- _, err := http.Get("http://localhost:7100")
+ client.sendrequest <- true
+ waitForState(t, statechanged, http.StateActive, "Client failed to reach active state")
- if err == nil {
- t.Fatal("Did not receive an error when trying to connect to server.")
+ rr := <-client.response
+ if rr.err != nil {
+ t.Fatalf("tls=%t unexpected error from client %s", withTLS, rr.err)
+ }
+
+ waitForState(t, statechanged, http.StateIdle, "Client failed to reach idle state")
+
+ // client is now in an idle state
+ close(client.sendrequest)
+ <-client.closed
+ waitForState(t, statechanged, http.StateClosed, "Client failed to reach closed state")
+
+ server.Close()
+ waiting := <-wg.WaitCalled
+ if waiting != 0 {
+ t.Errorf("Waitcount should be zero, got %d", waiting)
+ }
+
+ if err := <-exitchan; err != nil {
+ t.Error("Unexpected error during shutdown", err)
+ }
}
}