Depenancy upgrades and movign to dep. (#8630)
Этот коммит содержится в:
коммит произвёл
Joram Wilander
родитель
bf24f51c4e
Коммит
6e2cb00008
5
vendor/github.com/tylerb/graceful/README.md
сгенерированный
поставляемый
5
vendor/github.com/tylerb/graceful/README.md
сгенерированный
поставляемый
@@ -3,11 +3,6 @@ graceful [](htt
|
||||
|
||||
Graceful is a Go 1.3+ package enabling graceful shutdown of http.Handler servers.
|
||||
|
||||
## Using Go 1.8?
|
||||
|
||||
If you are using Go 1.8, you may not need to use this library! Consider using `http.Server`'s built-in [Shutdown()](https://golang.org/pkg/net/http/#Server.Shutdown)
|
||||
method for graceful shutdowns.
|
||||
|
||||
## Installation
|
||||
|
||||
To install, simply execute:
|
||||
|
||||
692
vendor/github.com/tylerb/graceful/graceful_test.go
сгенерированный
поставляемый
692
vendor/github.com/tylerb/graceful/graceful_test.go
сгенерированный
поставляемый
@@ -1,692 +0,0 @@
|
||||
package graceful
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"reflect"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
// The tests will run a test server on this port.
|
||||
port = 9654
|
||||
concurrentRequestN = 8
|
||||
killTime = 500 * time.Millisecond
|
||||
timeoutTime = 1000 * time.Millisecond
|
||||
waitTime = 100 * time.Millisecond
|
||||
)
|
||||
|
||||
func runQuery(t *testing.T, expected int, shouldErr bool, wg *sync.WaitGroup, once *sync.Once) {
|
||||
defer wg.Done()
|
||||
client := http.Client{}
|
||||
r, err := client.Get(fmt.Sprintf("http://localhost:%d", port))
|
||||
if shouldErr && err == nil {
|
||||
once.Do(func() {
|
||||
t.Error("Expected an error but none was encountered.")
|
||||
})
|
||||
} else if shouldErr && err != nil {
|
||||
if checkErr(t, err, once) {
|
||||
return
|
||||
}
|
||||
}
|
||||
if r != nil && r.StatusCode != expected {
|
||||
once.Do(func() {
|
||||
t.Errorf("Incorrect status code on response. Expected %d. Got %d", expected, r.StatusCode)
|
||||
})
|
||||
} else if r == nil {
|
||||
once.Do(func() {
|
||||
t.Error("No response when a response was expected.")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func checkErr(t *testing.T, err error, once *sync.Once) bool {
|
||||
if err.(*url.Error).Err == io.EOF {
|
||||
return true
|
||||
}
|
||||
var errno syscall.Errno
|
||||
switch oe := err.(*url.Error).Err.(type) {
|
||||
case *net.OpError:
|
||||
switch e := oe.Err.(type) {
|
||||
case syscall.Errno:
|
||||
errno = e
|
||||
case *os.SyscallError:
|
||||
errno = e.Err.(syscall.Errno)
|
||||
}
|
||||
if errno == syscall.ECONNREFUSED {
|
||||
return true
|
||||
} else if err != nil {
|
||||
once.Do(func() {
|
||||
t.Error("Error on Get:", err)
|
||||
})
|
||||
}
|
||||
default:
|
||||
if strings.Contains(err.Error(), "transport closed before response was received") {
|
||||
return true
|
||||
}
|
||||
if strings.Contains(err.Error(), "server closed connection") {
|
||||
return true
|
||||
}
|
||||
fmt.Printf("unknown err: %s, %#v\n", err, err)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func createListener(sleep time.Duration) (*http.Server, net.Listener, error) {
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) {
|
||||
time.Sleep(sleep)
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
})
|
||||
|
||||
server := &http.Server{Addr: fmt.Sprintf(":%d", port), Handler: mux}
|
||||
l, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
|
||||
return server, l, err
|
||||
}
|
||||
|
||||
func launchTestQueries(t *testing.T, wg *sync.WaitGroup, c chan os.Signal) {
|
||||
defer wg.Done()
|
||||
var once sync.Once
|
||||
|
||||
for i := 0; i < concurrentRequestN; i++ {
|
||||
wg.Add(1)
|
||||
go runQuery(t, http.StatusOK, false, wg, &once)
|
||||
}
|
||||
|
||||
time.Sleep(waitTime)
|
||||
c <- os.Interrupt
|
||||
time.Sleep(waitTime)
|
||||
|
||||
for i := 0; i < concurrentRequestN; i++ {
|
||||
wg.Add(1)
|
||||
go runQuery(t, 0, true, wg, &once)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGracefulRun(t *testing.T) {
|
||||
var wg sync.WaitGroup
|
||||
defer wg.Wait()
|
||||
|
||||
c := make(chan os.Signal, 1)
|
||||
server, l, err := createListener(killTime / 2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
srv := &Server{Timeout: killTime, Server: server, interrupt: c}
|
||||
srv.Serve(l)
|
||||
}()
|
||||
|
||||
wg.Add(1)
|
||||
go launchTestQueries(t, &wg, c)
|
||||
}
|
||||
|
||||
func TestGracefulRunLimitKeepAliveListener(t *testing.T) {
|
||||
var wg sync.WaitGroup
|
||||
defer wg.Wait()
|
||||
|
||||
c := make(chan os.Signal, 1)
|
||||
server, l, err := createListener(killTime / 2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
srv := &Server{
|
||||
Timeout: killTime,
|
||||
ListenLimit: concurrentRequestN,
|
||||
TCPKeepAlive: 1 * time.Second,
|
||||
Server: server,
|
||||
interrupt: c,
|
||||
}
|
||||
srv.Serve(l)
|
||||
}()
|
||||
|
||||
wg.Add(1)
|
||||
go launchTestQueries(t, &wg, c)
|
||||
}
|
||||
|
||||
func TestGracefulRunTimesOut(t *testing.T) {
|
||||
var wg sync.WaitGroup
|
||||
defer wg.Wait()
|
||||
|
||||
c := make(chan os.Signal, 1)
|
||||
server, l, err := createListener(killTime * 10)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
srv := &Server{Timeout: killTime, Server: server, interrupt: c}
|
||||
srv.Serve(l)
|
||||
}()
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
var once sync.Once
|
||||
|
||||
for i := 0; i < concurrentRequestN; i++ {
|
||||
wg.Add(1)
|
||||
go runQuery(t, 0, true, &wg, &once)
|
||||
}
|
||||
|
||||
time.Sleep(waitTime)
|
||||
c <- os.Interrupt
|
||||
time.Sleep(waitTime)
|
||||
|
||||
for i := 0; i < concurrentRequestN; i++ {
|
||||
wg.Add(1)
|
||||
go runQuery(t, 0, true, &wg, &once)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func TestGracefulRunDoesntTimeOut(t *testing.T) {
|
||||
var wg sync.WaitGroup
|
||||
defer wg.Wait()
|
||||
|
||||
c := make(chan os.Signal, 1)
|
||||
server, l, err := createListener(killTime * 2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
srv := &Server{Timeout: 0, Server: server, interrupt: c}
|
||||
srv.Serve(l)
|
||||
}()
|
||||
|
||||
wg.Add(1)
|
||||
go launchTestQueries(t, &wg, c)
|
||||
}
|
||||
|
||||
func TestGracefulRunDoesntTimeOutAfterConnectionCreated(t *testing.T) {
|
||||
var wg sync.WaitGroup
|
||||
defer wg.Wait()
|
||||
|
||||
c := make(chan os.Signal, 1)
|
||||
server, l, err := createListener(killTime)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
srv := &Server{Timeout: 0, Server: server, interrupt: c}
|
||||
srv.Serve(l)
|
||||
}()
|
||||
time.Sleep(waitTime)
|
||||
|
||||
// Make a sample first request. The connection will be left idle.
|
||||
resp, err := http.Get(fmt.Sprintf("http://localhost:%d", port))
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("first request failed: %v", err))
|
||||
}
|
||||
resp.Body.Close()
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
|
||||
// With idle connections improperly handled, the server doesn't wait for this
|
||||
// to complete and the request fails. It should be allowed to complete successfully.
|
||||
_, err := http.Get(fmt.Sprintf("http://localhost:%d", port))
|
||||
if err != nil {
|
||||
t.Errorf("Get failed: %v", err)
|
||||
}
|
||||
}()
|
||||
|
||||
// Ensure the request goes out
|
||||
time.Sleep(waitTime)
|
||||
c <- os.Interrupt
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func TestGracefulRunNoRequests(t *testing.T) {
|
||||
var wg sync.WaitGroup
|
||||
defer wg.Wait()
|
||||
|
||||
c := make(chan os.Signal, 1)
|
||||
server, l, err := createListener(killTime * 2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
srv := &Server{Timeout: 0, Server: server, interrupt: c}
|
||||
srv.Serve(l)
|
||||
}()
|
||||
|
||||
c <- os.Interrupt
|
||||
}
|
||||
|
||||
func TestGracefulForwardsConnState(t *testing.T) {
|
||||
var stateLock sync.Mutex
|
||||
states := make(map[http.ConnState]int)
|
||||
connState := func(conn net.Conn, state http.ConnState) {
|
||||
stateLock.Lock()
|
||||
states[state]++
|
||||
stateLock.Unlock()
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
defer wg.Wait()
|
||||
|
||||
expected := map[http.ConnState]int{
|
||||
http.StateNew: concurrentRequestN,
|
||||
http.StateActive: concurrentRequestN,
|
||||
http.StateClosed: concurrentRequestN,
|
||||
}
|
||||
|
||||
c := make(chan os.Signal, 1)
|
||||
server, l, err := createListener(killTime / 2)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
srv := &Server{
|
||||
ConnState: connState,
|
||||
Timeout: killTime,
|
||||
Server: server,
|
||||
interrupt: c,
|
||||
}
|
||||
srv.Serve(l)
|
||||
}()
|
||||
|
||||
wg.Add(1)
|
||||
go launchTestQueries(t, &wg, c)
|
||||
wg.Wait()
|
||||
|
||||
stateLock.Lock()
|
||||
if !reflect.DeepEqual(states, expected) {
|
||||
t.Errorf("Incorrect connection state tracking.\n actual: %v\nexpected: %v\n", states, expected)
|
||||
}
|
||||
stateLock.Unlock()
|
||||
}
|
||||
|
||||
func TestGracefulExplicitStop(t *testing.T) {
|
||||
server, l, err := createListener(1 * time.Millisecond)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
srv := &Server{Timeout: killTime, Server: server}
|
||||
|
||||
go func() {
|
||||
go srv.Serve(l)
|
||||
time.Sleep(waitTime)
|
||||
srv.Stop(killTime)
|
||||
}()
|
||||
|
||||
// block on the stopChan until the server has shut down
|
||||
select {
|
||||
case <-srv.StopChan():
|
||||
case <-time.After(timeoutTime):
|
||||
t.Fatal("Timed out while waiting for explicit stop to complete")
|
||||
}
|
||||
}
|
||||
|
||||
func TestGracefulExplicitStopOverride(t *testing.T) {
|
||||
server, l, err := createListener(1 * time.Millisecond)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
srv := &Server{Timeout: killTime, Server: server}
|
||||
|
||||
go func() {
|
||||
go srv.Serve(l)
|
||||
time.Sleep(waitTime)
|
||||
srv.Stop(killTime / 2)
|
||||
}()
|
||||
|
||||
// block on the stopChan until the server has shut down
|
||||
select {
|
||||
case <-srv.StopChan():
|
||||
case <-time.After(killTime):
|
||||
t.Fatal("Timed out while waiting for explicit stop to complete")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBeforeShutdownAndShutdownInitiatedCallbacks(t *testing.T) {
|
||||
var wg sync.WaitGroup
|
||||
defer wg.Wait()
|
||||
|
||||
server, l, err := createListener(1 * time.Millisecond)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
beforeShutdownCalled := make(chan struct{})
|
||||
cb1 := func() bool { close(beforeShutdownCalled); return true }
|
||||
shutdownInitiatedCalled := make(chan struct{})
|
||||
cb2 := func() { close(shutdownInitiatedCalled) }
|
||||
|
||||
wg.Add(2)
|
||||
srv := &Server{Server: server, BeforeShutdown: cb1, ShutdownInitiated: cb2}
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
srv.Serve(l)
|
||||
}()
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
time.Sleep(waitTime)
|
||||
srv.Stop(killTime)
|
||||
}()
|
||||
|
||||
beforeShutdown := false
|
||||
shutdownInitiated := false
|
||||
for i := 0; i < 2; i++ {
|
||||
select {
|
||||
case <-beforeShutdownCalled:
|
||||
beforeShutdownCalled = nil
|
||||
beforeShutdown = true
|
||||
case <-shutdownInitiatedCalled:
|
||||
shutdownInitiatedCalled = nil
|
||||
shutdownInitiated = true
|
||||
case <-time.After(killTime):
|
||||
t.Fatal("Timed out while waiting for ShutdownInitiated callback to be called")
|
||||
}
|
||||
}
|
||||
|
||||
if !beforeShutdown {
|
||||
t.Fatal("beforeShutdown should be true")
|
||||
}
|
||||
if !shutdownInitiated {
|
||||
t.Fatal("shutdownInitiated should be true")
|
||||
}
|
||||
}
|
||||
|
||||
func TestBeforeShutdownCanceled(t *testing.T) {
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
|
||||
server, l, err := createListener(1 * time.Millisecond)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
beforeShutdownCalled := make(chan struct{})
|
||||
cb1 := func() bool { close(beforeShutdownCalled); return false }
|
||||
shutdownInitiatedCalled := make(chan struct{})
|
||||
cb2 := func() { close(shutdownInitiatedCalled) }
|
||||
|
||||
srv := &Server{Server: server, BeforeShutdown: cb1, ShutdownInitiated: cb2}
|
||||
go func() {
|
||||
srv.Serve(l)
|
||||
wg.Done()
|
||||
}()
|
||||
go func() {
|
||||
time.Sleep(waitTime)
|
||||
srv.Stop(killTime)
|
||||
}()
|
||||
|
||||
beforeShutdown := false
|
||||
shutdownInitiated := false
|
||||
timeouted := false
|
||||
|
||||
for i := 0; i < 2; i++ {
|
||||
select {
|
||||
case <-beforeShutdownCalled:
|
||||
beforeShutdownCalled = nil
|
||||
beforeShutdown = true
|
||||
case <-shutdownInitiatedCalled:
|
||||
shutdownInitiatedCalled = nil
|
||||
shutdownInitiated = true
|
||||
case <-time.After(killTime):
|
||||
timeouted = true
|
||||
}
|
||||
}
|
||||
|
||||
if !beforeShutdown {
|
||||
t.Fatal("beforeShutdown should be true")
|
||||
}
|
||||
if !timeouted {
|
||||
t.Fatal("timeouted should be true")
|
||||
}
|
||||
if shutdownInitiated {
|
||||
t.Fatal("shutdownInitiated shouldn't be true")
|
||||
}
|
||||
|
||||
srv.BeforeShutdown = func() bool { return true }
|
||||
srv.Stop(killTime)
|
||||
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func hijackingListener(srv *Server) (*http.Server, net.Listener, error) {
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) {
|
||||
conn, bufrw, err := rw.(http.Hijacker).Hijack()
|
||||
if err != nil {
|
||||
http.Error(rw, "webserver doesn't support hijacking", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
defer conn.Close()
|
||||
|
||||
bufrw.WriteString("HTTP/1.1 200 OK\r\n\r\n")
|
||||
bufrw.Flush()
|
||||
})
|
||||
|
||||
server := &http.Server{Addr: fmt.Sprintf(":%d", port), Handler: mux}
|
||||
l, err := net.Listen("tcp", fmt.Sprintf(":%d", port))
|
||||
return server, l, err
|
||||
}
|
||||
|
||||
func TestNotifyClosed(t *testing.T) {
|
||||
var wg sync.WaitGroup
|
||||
defer wg.Wait()
|
||||
|
||||
c := make(chan os.Signal, 1)
|
||||
srv := &Server{Timeout: killTime, interrupt: c}
|
||||
server, l, err := hijackingListener(srv)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
srv.Server = server
|
||||
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
srv.Serve(l)
|
||||
}()
|
||||
|
||||
var once sync.Once
|
||||
for i := 0; i < concurrentRequestN; i++ {
|
||||
wg.Add(1)
|
||||
runQuery(t, http.StatusOK, false, &wg, &once)
|
||||
}
|
||||
|
||||
srv.Stop(0)
|
||||
|
||||
// block on the stopChan until the server has shut down
|
||||
select {
|
||||
case <-srv.StopChan():
|
||||
case <-time.After(timeoutTime):
|
||||
t.Fatal("Timed out while waiting for explicit stop to complete")
|
||||
}
|
||||
|
||||
if len(srv.connections) > 0 {
|
||||
t.Fatal("hijacked connections should not be managed")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestStopDeadlock(t *testing.T) {
|
||||
var wg sync.WaitGroup
|
||||
defer wg.Wait()
|
||||
|
||||
c := make(chan struct{})
|
||||
server, l, err := createListener(1 * time.Millisecond)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
srv := &Server{Server: server, NoSignalHandling: true}
|
||||
|
||||
wg.Add(2)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
time.Sleep(waitTime)
|
||||
srv.Serve(l)
|
||||
}()
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
srv.Stop(0)
|
||||
close(c)
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-c:
|
||||
l.Close()
|
||||
case <-time.After(timeoutTime):
|
||||
t.Fatal("Timed out while waiting for explicit stop to complete")
|
||||
}
|
||||
}
|
||||
|
||||
// Run with --race
|
||||
func TestStopRace(t *testing.T) {
|
||||
server, l, err := createListener(1 * time.Millisecond)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
srv := &Server{Timeout: killTime, Server: server}
|
||||
|
||||
go func() {
|
||||
go srv.Serve(l)
|
||||
srv.Stop(killTime)
|
||||
}()
|
||||
srv.Stop(0)
|
||||
select {
|
||||
case <-srv.StopChan():
|
||||
case <-time.After(timeoutTime):
|
||||
t.Fatal("Timed out while waiting for explicit stop to complete")
|
||||
}
|
||||
}
|
||||
|
||||
func TestInterruptLog(t *testing.T) {
|
||||
c := make(chan os.Signal, 1)
|
||||
|
||||
server, l, err := createListener(killTime * 10)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var buf bytes.Buffer
|
||||
var tbuf bytes.Buffer
|
||||
logger := log.New(&buf, "", 0)
|
||||
expected := log.New(&tbuf, "", 0)
|
||||
|
||||
srv := &Server{Timeout: killTime, Server: server, Logger: logger, interrupt: c}
|
||||
go func() { srv.Serve(l) }()
|
||||
|
||||
stop := srv.StopChan()
|
||||
c <- os.Interrupt
|
||||
expected.Print("shutdown initiated")
|
||||
|
||||
<-stop
|
||||
|
||||
if buf.String() != tbuf.String() {
|
||||
t.Fatal("shutdown log incorrect - got '" + buf.String() + "'")
|
||||
}
|
||||
}
|
||||
|
||||
func TestMultiInterrupts(t *testing.T) {
|
||||
c := make(chan os.Signal, 1)
|
||||
|
||||
server, l, err := createListener(killTime * 10)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
var bu bytes.Buffer
|
||||
buf := SyncBuffer{&wg, &bu}
|
||||
var tbuf bytes.Buffer
|
||||
logger := log.New(&buf, "", 0)
|
||||
expected := log.New(&tbuf, "", 0)
|
||||
|
||||
srv := &Server{Timeout: killTime, Server: server, Logger: logger, interrupt: c}
|
||||
go func() { srv.Serve(l) }()
|
||||
|
||||
stop := srv.StopChan()
|
||||
buf.Add(1 + 10) // Expecting 11 log calls
|
||||
c <- os.Interrupt
|
||||
expected.Printf("shutdown initiated")
|
||||
for i := 0; i < 10; i++ {
|
||||
c <- os.Interrupt
|
||||
expected.Printf("already shutting down")
|
||||
}
|
||||
|
||||
<-stop
|
||||
|
||||
wg.Wait()
|
||||
bb, bt := buf.Bytes(), tbuf.Bytes()
|
||||
for i, b := range bb {
|
||||
if b != bt[i] {
|
||||
t.Fatal(fmt.Sprintf("shutdown log incorrect - got '%s', expected '%s'", buf.String(), tbuf.String()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestLogFunc(t *testing.T) {
|
||||
c := make(chan os.Signal, 1)
|
||||
|
||||
server, l, err := createListener(killTime * 10)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var called bool
|
||||
srv := &Server{Timeout: killTime, Server: server,
|
||||
LogFunc: func(format string, args ...interface{}) {
|
||||
called = true
|
||||
}, interrupt: c}
|
||||
stop := srv.StopChan()
|
||||
go func() { srv.Serve(l) }()
|
||||
c <- os.Interrupt
|
||||
<-stop
|
||||
|
||||
if called != true {
|
||||
t.Fatal("Expected LogFunc to be called.")
|
||||
}
|
||||
}
|
||||
|
||||
// SyncBuffer calls Done on the embedded wait group after each call to Write.
|
||||
type SyncBuffer struct {
|
||||
*sync.WaitGroup
|
||||
*bytes.Buffer
|
||||
}
|
||||
|
||||
func (buf *SyncBuffer) Write(b []byte) (int, error) {
|
||||
defer buf.Done()
|
||||
return buf.Buffer.Write(b)
|
||||
}
|
||||
125
vendor/github.com/tylerb/graceful/http2_test.go
сгенерированный
поставляемый
125
vendor/github.com/tylerb/graceful/http2_test.go
сгенерированный
поставляемый
@@ -1,125 +0,0 @@
|
||||
// +build go1.6
|
||||
|
||||
package graceful
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/http2"
|
||||
)
|
||||
|
||||
func createServer() *http.Server {
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) {
|
||||
rw.WriteHeader(http.StatusOK)
|
||||
})
|
||||
|
||||
server := &http.Server{Addr: fmt.Sprintf(":%d", port), Handler: mux}
|
||||
|
||||
return server
|
||||
}
|
||||
|
||||
func checkIfConnectionToServerIsHTTP2(t *testing.T, wg *sync.WaitGroup, c chan os.Signal) {
|
||||
|
||||
defer wg.Done()
|
||||
|
||||
tr := &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
}
|
||||
|
||||
err := http2.ConfigureTransport(tr)
|
||||
|
||||
if err != nil {
|
||||
t.Fatal("Unable to upgrade client transport to HTTP/2")
|
||||
}
|
||||
|
||||
client := http.Client{Transport: tr}
|
||||
r, err := client.Get(fmt.Sprintf("https://localhost:%d", port))
|
||||
|
||||
c <- os.Interrupt
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Error encountered while connecting to test server: %s", err)
|
||||
}
|
||||
|
||||
if !r.ProtoAtLeast(2, 0) {
|
||||
t.Fatalf("Expected HTTP/2 connection to server, but connection was using %s", r.Proto)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHTTP2ListenAndServeTLS(t *testing.T) {
|
||||
|
||||
c := make(chan os.Signal, 1)
|
||||
|
||||
var wg sync.WaitGroup
|
||||
wg.Add(1)
|
||||
|
||||
server := createServer()
|
||||
|
||||
var srv *Server
|
||||
go func() {
|
||||
// set timeout of 0 to test idle connection closing
|
||||
srv = &Server{Timeout: 0, TCPKeepAlive: 1 * time.Minute, Server: server, interrupt: c}
|
||||
srv.ListenAndServeTLS("test-fixtures/cert.crt", "test-fixtures/key.pem")
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
time.Sleep(waitTime) // Wait for the server to start
|
||||
|
||||
wg.Add(1)
|
||||
go checkIfConnectionToServerIsHTTP2(t, &wg, c)
|
||||
wg.Wait()
|
||||
|
||||
c <- os.Interrupt // kill the server to close idle connections
|
||||
|
||||
// block on the stopChan until the server has shut down
|
||||
select {
|
||||
case <-srv.StopChan():
|
||||
case <-time.After(killTime * 2):
|
||||
t.Fatal("Timed out while waiting for explicit stop to complete")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestHTTP2ListenAndServeTLSConfig(t *testing.T) {
|
||||
|
||||
c := make(chan os.Signal, 1)
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
||||
wg.Add(1)
|
||||
|
||||
server2 := createServer()
|
||||
|
||||
go func() {
|
||||
srv := &Server{Timeout: killTime, TCPKeepAlive: 1 * time.Minute, Server: server2, interrupt: c}
|
||||
|
||||
cert, err := tls.LoadX509KeyPair("test-fixtures/cert.crt", "test-fixtures/key.pem")
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Unexpected error: %s", err)
|
||||
}
|
||||
|
||||
tlsConf := &tls.Config{
|
||||
Certificates: []tls.Certificate{cert},
|
||||
NextProtos: []string{"h2"}, // We need to explicitly enable http/2 in Go 1.7+
|
||||
}
|
||||
|
||||
tlsConf.BuildNameToCertificate()
|
||||
|
||||
srv.ListenAndServeTLSConfig(tlsConf)
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
time.Sleep(waitTime) // Wait for the server to start
|
||||
|
||||
wg.Add(1)
|
||||
go checkIfConnectionToServerIsHTTP2(t, &wg, c)
|
||||
wg.Wait()
|
||||
}
|
||||
43
vendor/github.com/tylerb/graceful/test-fixtures/cert.crt
сгенерированный
поставляемый
43
vendor/github.com/tylerb/graceful/test-fixtures/cert.crt
сгенерированный
поставляемый
@@ -1,43 +0,0 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDhTCCAm2gAwIBAgIUDvdWhjUd/JS+E5bxZlmCM+giGHMwDQYJKoZIhvcNAQEL
|
||||
BQAwHzEdMBsGA1UEAxMUVGVzdCBJbnRlcm1lZGlhdGUgQ0EwHhcNMTYwNjAyMDMy
|
||||
MjA0WhcNMTkwNjAyMDMyMjM0WjAUMRIwEAYDVQQDEwlsb2NhbGhvc3QwggEiMA0G
|
||||
CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDDoyMTUK2OSp+XhKRXB/+uO6YAJE/W
|
||||
2rzqARahWT6boHZMDhHXRtdwYxWwiUqoxlEeBrEerQ2qPFAqlWkDw8zliE/DWgXg
|
||||
BiW+Vq5DAn3F1jZ5WskLWr1iP48oK4/l+BXEsDd44MHZFoSZiWlr2Fi4iaIHJE7+
|
||||
LGBqPVQXwBYTyc7Jvi3HY8I4/waaAwXoSo8vDPjRiMCD2wlg24Rimocf4goa/2Xs
|
||||
Z0NU76Uf2jPdsZ5MujjKRqwHDEAjiBq0aPvm6igkNGAGoZ6QYEptO+J4t1oFrbdP
|
||||
gYRlpqCa3ekr9gc+wg5AO/V9x8/cypbQ8tpwFwvvSYg2TJaUMZ5abc+HAgMBAAGj
|
||||
gcMwgcAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMB0GA1UdDgQWBBQC
|
||||
R0Y69NLOfFCLRiB5N3uoacILXTAfBgNVHSMEGDAWgBRm0fFHSXtDCVHC8UW7/obv
|
||||
DLp9tTBJBggrBgEFBQcBAQQ9MDswOQYIKwYBBQUHMAKGLWh0dHA6Ly9sb2NhbGhv
|
||||
c3Qvc2VsZi1pc3N1ZWQtaW50ZXJtZWRpYXRlLmNydDAUBgNVHREEDTALgglsb2Nh
|
||||
bGhvc3QwDQYJKoZIhvcNAQELBQADggEBALAf/nowwB0NJ7lGGaoVKhmMHxBEQkd1
|
||||
K/jBAlJg9Kgmg1IJJ7zLE3SeYF8tGTNYATd4RLmqo1GakrMDaKWNXd74v3p/tWmb
|
||||
4vqCh6WzFPHU1dpxDKtbbmaLt9Ije7s6DuQAz9bBXM0mN0vy5F0dORpx/j0h3u1B
|
||||
j7B5O8kLejPY2w/8pd+QECCb1Q5A6Xx1EEsJpzTlGXO0SBla/oCg+nvirsBGVpWr
|
||||
bGskAIwG9wNKuGfg4m5u1bL87iX80NemeLtWRWVM+Ry/RhfOokH59/EIFRAXeRz6
|
||||
gXjIWa0vcXnhW1MOvbD1GFYhO6AJAnDwWes48WfBHysOhq0RycdpGw0=
|
||||
-----END CERTIFICATE-----
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIDjTCCAnWgAwIBAgIUMzpit8+j2dWxdk1PdMqGWYalZyIwDQYJKoZIhvcNAQEL
|
||||
BQAwFzEVMBMGA1UEAxMMVGVzdCBSb290IENBMB4XDTE2MDUyOTEwNDYwMFoXDTMx
|
||||
MDUyNjEwNDYzMFowHzEdMBsGA1UEAxMUVGVzdCBJbnRlcm1lZGlhdGUgQ0EwggEi
|
||||
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDs6kY6mHJWzupq5dsSavPZHuv6
|
||||
0E9PczHbujWLuzv7+qbwzcAgfRvaeR0xgvf7q9pjMgJ7/kNANgneWGpwciLgHtiJ
|
||||
rSHii3RZfWlK4gdbCXya9EmHj8zO+9xGBHM0FrqfqA+IA70SimFcwGPrGHyERsdX
|
||||
+mqO64Z95yI5uJpoS8OBAUPU8i6xvNLZGmgUEF3CRhDDTYVGcTEtKAPcnnBuZzZU
|
||||
Ds+DrHf/MC7HHK0/l0auuRz3p+/GFNePGePG+FFbInS/vwHwrkMW2tzBKG41K+gD
|
||||
GfkTjVU8xBSiMYOiEja6YcJ4GuzEPcmu5LS+6BkLlsIbazDW5IM8p+7+8RKjAgMB
|
||||
AAGjgcgwgcUwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O
|
||||
BBYEFGbR8UdJe0MJUcLxRbv+hu8Mun21MB8GA1UdIwQYMBaAFKmz0h3CW1HBO9uz
|
||||
uCzg+MNPGZtkMEEGCCsGAQUFBwEBBDUwMzAxBggrBgEFBQcwAoYlaHR0cDovL2xv
|
||||
Y2FsaG9zdC9zZWxmLWlzc3VlZC1yb290LmNydDAfBgNVHREEGDAWghRUZXN0IElu
|
||||
dGVybWVkaWF0ZSBDQTANBgkqhkiG9w0BAQsFAAOCAQEAaYVGqHbaE0c9F/kyIMgu
|
||||
S3HuNn4pBh2EwGcKIlPkDe43hqXjhS/+itmWk75rQz+Rw+acevGoxbpDR38abTIS
|
||||
RJd9L/3MA644z8F82er3pNjKqvS/vTre/wsvGYwmEM+GrgJw3HUcisc93qLgaWH2
|
||||
kjky208k9kOuzJDiY45eu9TfSSmjSHSMCtxk8p5wYKDcfVz+uqlBhVEiHGjQIc2E
|
||||
66SituusiwgQv/mdtEW7y48EvMGdzxPfLFcvj06B3vTsZaaYyB6GyKwMcaPFvHRr
|
||||
V0yYaKRZgAh4X6LHlgPJqvIv3gjMdJR55durAO7tI9Pos0o5Lv5WJgi0g0KvMsco
|
||||
qQ==
|
||||
-----END CERTIFICATE-----
|
||||
27
vendor/github.com/tylerb/graceful/test-fixtures/key.pem
сгенерированный
поставляемый
27
vendor/github.com/tylerb/graceful/test-fixtures/key.pem
сгенерированный
поставляемый
@@ -1,27 +0,0 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpQIBAAKCAQEAw6MjE1Ctjkqfl4SkVwf/rjumACRP1tq86gEWoVk+m6B2TA4R
|
||||
10bXcGMVsIlKqMZRHgaxHq0NqjxQKpVpA8PM5YhPw1oF4AYlvlauQwJ9xdY2eVrJ
|
||||
C1q9Yj+PKCuP5fgVxLA3eODB2RaEmYlpa9hYuImiByRO/ixgaj1UF8AWE8nOyb4t
|
||||
x2PCOP8GmgMF6EqPLwz40YjAg9sJYNuEYpqHH+IKGv9l7GdDVO+lH9oz3bGeTLo4
|
||||
ykasBwxAI4gatGj75uooJDRgBqGekGBKbTvieLdaBa23T4GEZaagmt3pK/YHPsIO
|
||||
QDv1fcfP3MqW0PLacBcL70mINkyWlDGeWm3PhwIDAQABAoIBAQC87HWa2XZAyt+D
|
||||
OpxZT2ghoYiU6nwPR/zXHWX1OnGzaCnVGGEyOz8hUQ5JBMwMYDdFf8DbltJzavsf
|
||||
pFldQWBE6HXeeLjjtgwM2zg9jdJXkp3YY0tyo5XvouFkMW0s735WCrYHDUUllxFG
|
||||
E+SyOKK00nSd4PpHiiMxdTgYF286exwOpzjhcJfAkn7oBNeOGc5VLOvcvakrSrdq
|
||||
OYBAJ25HSVFnSQbeAAsCzBEBZC0WLyB1BQGcidbtEn8sxyGnV8HWjbXY+MJQWHg+
|
||||
q2iK+uvO4wtrE/WC6p4Ty44Myh+AB79s35HWKYd4okwKkpI1QdD543TIiZnkNEVI
|
||||
aS/uH13BAoGBAP/psBxKzIft59hw+U9NscH6N9/ze8iAtOtqsWdER/qXCrlUn8+j
|
||||
F/xquJR6gDj5GwGBt07asEuoG8CKJMQI0c3AeHF7XBcmUunBStktb9O97Zsp6bNJ
|
||||
olsrWlM4yvVuCVizEwIYjHrMBOS3YIPErM1LmAyDHmzx3+yz+3+WxRQLAoGBAMO0
|
||||
MaJDPisMC05pvieHRb91HlsiSrASeMkw1FmHI0b/gcC88mEnuXIze1ySoF6FE7B7
|
||||
xaEm6Lf5Snl0JgXPDSj6ukd51NdaU2VmpKvDOrvQ5QQE9mXaDkXv/i2B0YkCh+Hy
|
||||
bkziW1IKnWT2PTRAAEIJQ22oK51MdQnvCdmtsIP1AoGBAKnMiEl9Z9AZDmgSLZls
|
||||
17D5MPGrQEp8+43oMOVv7MJcTYVCnPbMJDIbLXV3AnTK9Bw/0TzE5YyNcjyCbHqV
|
||||
z39RYZkKXMQPbZwj4GHRQA2iS3FUkfeft9X+IeRuHlxSMmlkCAyv9SXVELog4i0L
|
||||
5gwhSDWlGh73LbiEgy7Y/tKZAoGBALTiMhYGDMoA4dpiBi3G7AKgH6SgN2QyTo22
|
||||
oi71pveSZb1dZrHB47fYOadApxV17tLqM6pVqjeRJPLJFfO8gi9kPxSdWMqLZBWP
|
||||
H5jaY8kAtQxYAd32A8dEoSwylxcJzcpbJvPNLBbSVNPifIN0vEhNA5OxIk7LQkoi
|
||||
NHqL/WCZAoGAPf3kb9Gw/NkBq4Cn86pQfP/xE0h7zcoNmFtLbdKIjId+DDDOPOeX
|
||||
9tm33fZzw0SG4KlRQlsqgzFvm8aDD8rpW17341Z/rWlLo8uHNdRkMvbSabc34vPv
|
||||
4lrs0rHSYW06MlqkJBNVraySRz7hmU4+n7YMvNI0Due9mVGmE1NU/vI=
|
||||
-----END RSA PRIVATE KEY-----
|
||||
40
vendor/github.com/tylerb/graceful/tests/main.go
сгенерированный
поставляемый
40
vendor/github.com/tylerb/graceful/tests/main.go
сгенерированный
поставляемый
@@ -1,40 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/urfave/negroni"
|
||||
"gopkg.in/tylerb/graceful.v1"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
||||
wg.Add(3)
|
||||
go func() {
|
||||
n := negroni.New()
|
||||
fmt.Println("Launching server on :3000")
|
||||
graceful.Run(":3000", 0, n)
|
||||
fmt.Println("Terminated server on :3000")
|
||||
wg.Done()
|
||||
}()
|
||||
go func() {
|
||||
n := negroni.New()
|
||||
fmt.Println("Launching server on :3001")
|
||||
graceful.Run(":3001", 0, n)
|
||||
fmt.Println("Terminated server on :3001")
|
||||
wg.Done()
|
||||
}()
|
||||
go func() {
|
||||
n := negroni.New()
|
||||
fmt.Println("Launching server on :3002")
|
||||
graceful.Run(":3002", 0, n)
|
||||
fmt.Println("Terminated server on :3002")
|
||||
wg.Done()
|
||||
}()
|
||||
fmt.Println("Press ctrl+c. All servers should terminate.")
|
||||
wg.Wait()
|
||||
|
||||
}
|
||||
Ссылка в новой задаче
Block a user