Centralize test actions in AcceptanceTest

This commit is contained in:
Fabian Reinartz 2015-10-02 12:18:02 +02:00
parent b0989ca9f3
commit 5c4ec44962
1 changed files with 37 additions and 39 deletions

View File

@ -25,6 +25,8 @@ type AcceptanceTest struct {
ams []*Alertmanager ams []*Alertmanager
collectors []*Collector collectors []*Collector
actions map[float64][]func()
} }
type AcceptanceOpts struct { type AcceptanceOpts struct {
@ -44,8 +46,9 @@ func (opts *AcceptanceOpts) relativeTime(act time.Time) float64 {
func NewAcceptanceTest(t *testing.T, opts *AcceptanceOpts) *AcceptanceTest { func NewAcceptanceTest(t *testing.T, opts *AcceptanceOpts) *AcceptanceTest {
test := &AcceptanceTest{ test := &AcceptanceTest{
T: t, T: t,
opts: opts, opts: opts,
actions: map[float64][]func(){},
} }
opts.baseTime = time.Now() opts.baseTime = time.Now()
@ -64,13 +67,17 @@ func freeAddress() string {
return l.Addr().String() return l.Addr().String()
} }
// Do sets the given function to be executed at the given time.
func (t *AcceptanceTest) Do(at float64, f func()) {
t.actions[at] = append(t.actions[at], f)
}
// Alertmanager returns a new structure that allows starting an instance // Alertmanager returns a new structure that allows starting an instance
// of Alertmanager on a random port. // of Alertmanager on a random port.
func (t *AcceptanceTest) Alertmanager() *Alertmanager { func (t *AcceptanceTest) Alertmanager() *Alertmanager {
am := &Alertmanager{ am := &Alertmanager{
t: t.T, t: t,
opts: t.opts, opts: t.opts,
actions: map[float64][]func(){},
} }
cf, err := ioutil.TempFile("", "am_config") cf, err := ioutil.TempFile("", "am_config")
@ -131,9 +138,7 @@ func (t *AcceptanceTest) Run() {
defer am.kill() defer am.kill()
} }
for _, am := range t.ams { t.runActions()
go am.runActions()
}
var latest float64 var latest float64
for _, coll := range t.collectors { for _, coll := range t.collectors {
@ -156,18 +161,36 @@ func (t *AcceptanceTest) Run() {
} }
} }
// runActions performs the stored actions at the defined times.
func (t *AcceptanceTest) runActions() {
var wg sync.WaitGroup
for at, fs := range t.actions {
ts := t.opts.expandTime(at)
wg.Add(len(fs))
for _, f := range fs {
go func(f func()) {
time.Sleep(ts.Sub(time.Now()))
f()
wg.Done()
}(f)
}
}
wg.Wait()
}
// Alertmanager encapsulates an Alertmanager process and allows // Alertmanager encapsulates an Alertmanager process and allows
// declaring alerts being pushed to it at fixed points in time. // declaring alerts being pushed to it at fixed points in time.
type Alertmanager struct { type Alertmanager struct {
t *testing.T t *AcceptanceTest
opts *AcceptanceOpts opts *AcceptanceOpts
addr string addr string
client alertmanager.Client client alertmanager.Client
cmd *exec.Cmd cmd *exec.Cmd
confFile *os.File confFile *os.File
actions map[float64][]func()
} }
// Push declares alerts that are to be pushed to the Alertmanager // Push declares alerts that are to be pushed to the Alertmanager
@ -178,7 +201,7 @@ func (am *Alertmanager) Push(at float64, alerts ...*TestAlert) {
nas = append(nas, a.nativeAlert(am.opts)) nas = append(nas, a.nativeAlert(am.opts))
} }
am.Do(at, func() { am.t.Do(at, func() {
var buf bytes.Buffer var buf bytes.Buffer
if err := json.NewEncoder(&buf).Encode(nas); err != nil { if err := json.NewEncoder(&buf).Encode(nas); err != nil {
am.t.Error(err) am.t.Error(err)
@ -198,7 +221,7 @@ func (am *Alertmanager) Push(at float64, alerts ...*TestAlert) {
func (am *Alertmanager) SetSilence(at float64, sil *TestSilence) { func (am *Alertmanager) SetSilence(at float64, sil *TestSilence) {
silences := alertmanager.NewSilenceAPI(am.client) silences := alertmanager.NewSilenceAPI(am.client)
am.Do(at, func() { am.t.Do(at, func() {
sid, err := silences.Set(context.Background(), sil.nativeSilence(am.opts)) sid, err := silences.Set(context.Background(), sil.nativeSilence(am.opts))
if err != nil { if err != nil {
am.t.Error(err) am.t.Error(err)
@ -212,18 +235,13 @@ func (am *Alertmanager) SetSilence(at float64, sil *TestSilence) {
func (am *Alertmanager) DelSilence(at float64, sil *TestSilence) { func (am *Alertmanager) DelSilence(at float64, sil *TestSilence) {
silences := alertmanager.NewSilenceAPI(am.client) silences := alertmanager.NewSilenceAPI(am.client)
am.Do(at, func() { am.t.Do(at, func() {
if err := silences.Del(context.Background(), sil.ID); err != nil { if err := silences.Del(context.Background(), sil.ID); err != nil {
am.t.Error(err) am.t.Error(err)
} }
}) })
} }
// Do sets the given function to be executed at the given time.
func (am *Alertmanager) Do(at float64, f func()) {
am.actions[at] = append(am.actions[at], f)
}
// start the alertmanager and wait until it is ready to receive. // start the alertmanager and wait until it is ready to receive.
func (am *Alertmanager) start() { func (am *Alertmanager) start() {
if err := am.cmd.Start(); err != nil { if err := am.cmd.Start(); err != nil {
@ -233,26 +251,6 @@ func (am *Alertmanager) start() {
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
} }
// runActions performs the stored actions at the defined times.
func (am *Alertmanager) runActions() {
var wg sync.WaitGroup
for at, fs := range am.actions {
ts := am.opts.expandTime(at)
wg.Add(len(fs))
for _, f := range fs {
go func(f func()) {
time.Sleep(ts.Sub(time.Now()))
f()
wg.Done()
}(f)
}
}
wg.Wait()
}
// kill the underlying Alertmanager process and remove intermediate data. // kill the underlying Alertmanager process and remove intermediate data.
func (am *Alertmanager) kill() { func (am *Alertmanager) kill() {
am.cmd.Process.Kill() am.cmd.Process.Kill()