test: improve TestAgent

* don't use retry to try restarting the agent
  this caused some issues when the startup would fail in
  a separate go routine

* clear out the data directory on every retry since the ports
  are stored in the raft data files

* set a unique id for every agent to allow for tracking of
  concurrent output
This commit is contained in:
Frank Schroeder 2017-05-23 16:03:52 +02:00
parent 2b627b95dd
commit 828f40054a
No known key found for this signature in database
GPG Key ID: 4D65C6EAEC87DECD
1 changed files with 56 additions and 37 deletions

View File

@ -9,6 +9,8 @@ import (
"net/http/httptest" "net/http/httptest"
"os" "os"
"path/filepath" "path/filepath"
"runtime"
"strconv"
"strings" "strings"
"time" "time"
@ -97,6 +99,9 @@ func (a *TestAgent) Start() *TestAgent {
if a.Config == nil { if a.Config == nil {
a.Config = TestConfig() a.Config = TestConfig()
} }
if a.Config.DNSRecursor != "" {
a.Config.DNSRecursors = append(a.Config.DNSRecursors, a.Config.DNSRecursor)
}
if a.Config.DataDir == "" { if a.Config.DataDir == "" {
name := "agent" name := "agent"
if a.Name != "" { if a.Name != "" {
@ -110,9 +115,18 @@ func (a *TestAgent) Start() *TestAgent {
a.DataDir = d a.DataDir = d
a.Config.DataDir = d a.Config.DataDir = d
} }
if a.Config.DNSRecursor != "" { id := UniqueID()
a.Config.DNSRecursors = append(a.Config.DNSRecursors, a.Config.DNSRecursor) for i := 10; i >= 0; i-- {
pickRandomPorts(a.Config)
// ports are baked into the data files so we need to clear out the
// data dir on every retry
os.RemoveAll(a.Config.DataDir)
if err := os.MkdirAll(a.Config.DataDir, 0755); err != nil {
panic(fmt.Sprintf("Error creating dir %s: %s", a.Config.DataDir, err))
} }
// write the keyring
if a.Key != "" { if a.Key != "" {
writeKey := func(key, filename string) { writeKey := func(key, filename string) {
path := filepath.Join(a.Config.DataDir, filename) path := filepath.Join(a.Config.DataDir, filename)
@ -128,28 +142,25 @@ func (a *TestAgent) Start() *TestAgent {
if err != nil { if err != nil {
panic(fmt.Sprintf("Error creating agent: %s", err)) panic(fmt.Sprintf("Error creating agent: %s", err))
} }
agent.id = id
agent.LogOutput = a.LogOutput
agent.LogWriter = a.LogWriter
// we need the err var in the next exit condition
if err := agent.Start(); err == nil {
a.Agent = agent a.Agent = agent
a.Agent.LogOutput = a.LogOutput break
a.Agent.LogWriter = a.LogWriter } else if i == 0 {
tenTimes := &retry.Counter{Count: 10, Wait: 100 * time.Millisecond} fmt.Println(id, a.Name, "Error starting agent:", err)
retry.RunWith(tenTimes, &panicFailer{}, func(r *retry.R) { runtime.Goexit()
err := a.Agent.Start() } else {
if err == nil { agent.Shutdown()
return fmt.Println(id, a.Name, "retrying")
} }
// retry with different ports on port conflict
if strings.Contains(err.Error(), "bind: address already in use") {
a.Agent.Shutdown()
pickRandomPorts(a.Config)
r.Fatal("port conflict")
} }
// do not retry on other failures
panic(fmt.Sprintf("Error starting agent: %s", err))
})
a.Agent.StartSync() a.Agent.StartSync()
var out structs.IndexedNodes var out structs.IndexedNodes
retry.Run(&panicFailer{}, func(r *retry.R) { retry.Run(&panicFailer{}, func(r *retry.R) {
if len(a.httpServers) == 0 { if len(a.httpServers) == 0 {
@ -223,6 +234,14 @@ func (a *TestAgent) consulConfig() *consul.Config {
return c return c
} }
func UniqueID() string {
id := strconv.FormatUint(rand.Uint64(), 36)
for len(id) < 16 {
id += " "
}
return id
}
// pickRandomPorts selects random ports from fixed size random blocks of // pickRandomPorts selects random ports from fixed size random blocks of
// ports. This does not eliminate the chance for port conflict but // ports. This does not eliminate the chance for port conflict but
// reduces it significanltly with little overhead. Furthermore, asking // reduces it significanltly with little overhead. Furthermore, asking
@ -241,6 +260,7 @@ func pickRandomPorts(c *Config) {
c.Ports.SerfLan = port + 4 c.Ports.SerfLan = port + 4
c.Ports.SerfWan = port + 5 c.Ports.SerfWan = port + 5
c.Ports.Server = port + 6 c.Ports.Server = port + 6
//c.ConsulConfig.Memberlist.
} }
// BoolTrue and BoolFalse exist to create a *bool value. // BoolTrue and BoolFalse exist to create a *bool value.
@ -256,7 +276,6 @@ func TestConfig() *Config {
} }
cfg := DefaultConfig() cfg := DefaultConfig()
pickRandomPorts(cfg)
cfg.Version = version.Version cfg.Version = version.Version
cfg.VersionPrerelease = "c.d" cfg.VersionPrerelease = "c.d"