remove most unnecessary sleeps from tests

This commit is contained in:
Naitik Shah 2013-08-19 22:51:32 -07:00
parent 2024e37361
commit a4481adb67
2 changed files with 61 additions and 50 deletions

View File

@ -8,6 +8,7 @@ import (
"github.com/daaku/go.freeport" "github.com/daaku/go.freeport"
"github.com/daaku/go.tool" "github.com/daaku/go.tool"
"io/ioutil" "io/ioutil"
"net"
"net/http" "net/http"
"os" "os"
"os/exec" "os/exec"
@ -18,15 +19,6 @@ import (
"time" "time"
) )
const (
// The amount of time we give a process to become ready.
processWait = time.Second * 2
// The amount of time for the long HTTP request. This should be
// bigger than the value above.
slowHttpWait = time.Second * 4
)
// Debug logging. // Debug logging.
var debugLog = flag.Bool("debug", false, "enable debug logging") var debugLog = flag.Bool("debug", false, "enable debug logging")
@ -44,14 +36,16 @@ type response struct {
// State for the test run. // State for the test run.
type harness struct { type harness struct {
T *testing.T // The test instance. T *testing.T // The test instance.
ImportPath string // The import path for the server command. ImportPath string // The import path for the server command.
ExeName string // The temp binary from the build. ExeName string // The temp binary from the build.
Addr []string // The addresses for the http servers. Addr []string // The addresses for the http servers.
Process []*os.Process // The server commands, oldest to newest. Process []*os.Process // The server commands, oldest to newest.
ProcessMutex sync.Mutex // The mutex to guard Process manipulation. ProcessMutex sync.Mutex // The mutex to guard Process manipulation.
RequestWaitGroup sync.WaitGroup // The wait group for the HTTP requests. RequestWaitGroup sync.WaitGroup // The wait group for the HTTP requests.
newProcess chan bool // A bool is sent on restart. newProcess chan bool // A bool is sent on restart.
requestCount int
requestCountMutex sync.Mutex
} }
// Find 3 free ports and setup addresses. // Find 3 free ports and setup addresses.
@ -99,9 +93,6 @@ func (h *harness) Build() {
// Start a fresh server and wait for pid updates on restart. // Start a fresh server and wait for pid updates on restart.
func (h *harness) Start() { func (h *harness) Start() {
if h.newProcess == nil {
h.newProcess = make(chan bool)
}
cmd := exec.Command(h.ExeName, h.Args()...) cmd := exec.Command(h.ExeName, h.Args()...)
stderr, err := cmd.StderrPipe() stderr, err := cmd.StderrPipe()
go func() { go func() {
@ -133,11 +124,7 @@ func (h *harness) Start() {
if err != nil { if err != nil {
h.T.Fatalf("Failed to start command: %s", err) h.T.Fatalf("Failed to start command: %s", err)
} }
h.ProcessMutex.Lock()
h.Process = append(h.Process, cmd.Process)
h.ProcessMutex.Unlock()
<-h.newProcess <-h.newProcess
time.Sleep(processWait)
} }
// Restart the most recent server. // Restart the most recent server.
@ -147,7 +134,6 @@ func (h *harness) Restart() {
h.T.Fatalf("Failed to send SIGUSR2 and restart process: %s", err) h.T.Fatalf("Failed to send SIGUSR2 and restart process: %s", err)
} }
<-h.newProcess <-h.newProcess
time.Sleep(processWait)
} }
// Graceful termination of the most recent server. // Graceful termination of the most recent server.
@ -177,17 +163,34 @@ func (h *harness) RemoveExe() {
} }
} }
// Get the global request count.
func (h *harness) RequestCount() int {
h.requestCountMutex.Lock()
defer h.requestCountMutex.Unlock()
c := h.requestCount
h.requestCount++
return c
}
// Helper for sending a single request. // Helper for sending a single request.
func (h *harness) SendOne(duration time.Duration, addr string, pid int) { func (h *harness) SendOne(dialgroup *sync.WaitGroup, duration time.Duration, addr string, pid int) {
debug("Send One pid=%d duration=%s", pid, duration) count := h.RequestCount()
debug("Send %02d pid=%d duration=%s", count, pid, duration)
client := &http.Client{ client := &http.Client{
Transport: &http.Transport{DisableKeepAlives: true}, Transport: &http.Transport{
DisableKeepAlives: true,
Dial: func(network, addr string) (net.Conn, error) {
defer dialgroup.Done()
return net.Dial(network, addr)
},
},
} }
url := fmt.Sprintf("http://%s/sleep/?duration=%s", addr, duration.String()) url := fmt.Sprintf("http://%s/sleep/?duration=%s", addr, duration.String())
r, err := client.Get(url) r, err := client.Get(url)
if err != nil { if err != nil {
h.T.Fatalf("Failed request to %s: %s", url, err) h.T.Fatalf("Failed request to %s: %s", url, err)
} }
debug("Body %02d pid=%d duration=%s", count, pid, duration)
defer r.Body.Close() defer r.Body.Close()
res := &response{} res := &response{}
err = json.NewDecoder(r.Body).Decode(res) err = json.NewDecoder(r.Body).Decode(res)
@ -197,19 +200,22 @@ func (h *harness) SendOne(duration time.Duration, addr string, pid int) {
if pid != res.Pid { if pid != res.Pid {
h.T.Fatalf("Didn't get expected pid %d instead got %d", pid, res.Pid) h.T.Fatalf("Didn't get expected pid %d instead got %d", pid, res.Pid)
} }
debug("Request Done pid=%d duration=%s", pid, duration) debug("Done %02d pid=%d duration=%s", count, pid, duration)
h.RequestWaitGroup.Done() h.RequestWaitGroup.Done()
} }
// Send test HTTP request. // Send test HTTP request.
func (h *harness) SendRequest() { func (h *harness) SendRequest() {
pid := h.MostRecentProcess().Pid pid := h.MostRecentProcess().Pid
var dialgroup sync.WaitGroup
for _, addr := range h.Addr { for _, addr := range h.Addr {
debug("Added 2 Requests") debug("Added 2 Requests")
h.RequestWaitGroup.Add(2) h.RequestWaitGroup.Add(2)
go h.SendOne(time.Second*0, addr, pid) dialgroup.Add(2)
go h.SendOne(slowHttpWait, addr, pid) go h.SendOne(&dialgroup, time.Second*0, addr, pid)
go h.SendOne(&dialgroup, time.Second*2, addr, pid)
} }
dialgroup.Wait()
} }
// Wait for everything. // Wait for everything.
@ -223,6 +229,7 @@ func TestComplex(t *testing.T) {
h := &harness{ h := &harness{
ImportPath: "github.com/daaku/go.grace/gracehttp/testserver", ImportPath: "github.com/daaku/go.grace/gracehttp/testserver",
T: t, T: t,
newProcess: make(chan bool),
} }
debug("Building") debug("Building")
h.Build() h.Build()
@ -230,24 +237,18 @@ func TestComplex(t *testing.T) {
h.Start() h.Start()
debug("Send Request 1") debug("Send Request 1")
h.SendRequest() h.SendRequest()
debug("Sleeping 1")
time.Sleep(processWait)
debug("Restart 1") debug("Restart 1")
h.Restart() h.Restart()
debug("Send Request 2") debug("Send Request 2")
h.SendRequest() h.SendRequest()
debug("Sleeping 2")
time.Sleep(processWait)
debug("Restart 2") debug("Restart 2")
h.Restart() h.Restart()
debug("Send Request 3") debug("Send Request 3")
h.SendRequest() h.SendRequest()
debug("Sleeping 3")
time.Sleep(processWait)
debug("Stopping")
h.Stop()
debug("Waiting") debug("Waiting")
h.Wait() h.Wait()
debug("Stopping")
h.Stop()
debug("Removing Executable") debug("Removing Executable")
h.RemoveExe() h.RemoveExe()
} }

View File

@ -20,19 +20,11 @@ var (
address0 = flag.String("a0", ":48567", "Zero address to bind to.") address0 = flag.String("a0", ":48567", "Zero address to bind to.")
address1 = flag.String("a1", ":48568", "First address to bind to.") address1 = flag.String("a1", ":48568", "First address to bind to.")
address2 = flag.String("a2", ":48569", "Second address to bind to.") address2 = flag.String("a2", ":48569", "Second address to bind to.")
finished = make(chan bool)
) )
func main() { func serve() {
flag.Parse() err := gracehttp.Serve(
err := flag.Set("gracehttp.log", "false")
if err != nil {
log.Fatalf("Error setting gracehttp.log: %s", err)
}
err = json.NewEncoder(os.Stderr).Encode(&response{Pid: os.Getpid()})
if err != nil {
log.Fatalf("Error writing startup json: %s", err)
}
err = gracehttp.Serve(
&http.Server{Addr: *address0, Handler: newHandler()}, &http.Server{Addr: *address0, Handler: newHandler()},
&http.Server{Addr: *address1, Handler: newHandler()}, &http.Server{Addr: *address1, Handler: newHandler()},
&http.Server{Addr: *address2, Handler: newHandler()}, &http.Server{Addr: *address2, Handler: newHandler()},
@ -40,6 +32,24 @@ func main() {
if err != nil { if err != nil {
log.Fatalf("Error in gracehttp.Serve: %s", err) log.Fatalf("Error in gracehttp.Serve: %s", err)
} }
finished <- true
}
func main() {
flag.Parse()
err := flag.Set("gracehttp.log", "false")
if err != nil {
log.Fatalf("Error setting gracehttp.log: %s", err)
}
go serve()
time.Sleep(time.Second * 2) // BUG
err = json.NewEncoder(os.Stderr).Encode(&response{Pid: os.Getpid()})
if err != nil {
log.Fatalf("Error writing startup json: %s", err)
}
<-finished
} }
func newHandler() http.Handler { func newHandler() http.Handler {