mirror of
https://github.com/grafana/grafana.git
synced 2025-02-20 11:48:34 -06:00
119 lines
2.7 KiB
Go
119 lines
2.7 KiB
Go
|
package schedule
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"math/rand"
|
||
|
"runtime"
|
||
|
"sync"
|
||
|
"testing"
|
||
|
"time"
|
||
|
|
||
|
"github.com/stretchr/testify/require"
|
||
|
)
|
||
|
|
||
|
func TestSchedule_alertRuleInfo(t *testing.T) {
|
||
|
t.Run("when rule evaluation is not stopped", func(t *testing.T) {
|
||
|
t.Run("Update should send to updateCh", func(t *testing.T) {
|
||
|
r := newAlertRuleInfo(context.Background())
|
||
|
resultCh := make(chan bool)
|
||
|
go func() {
|
||
|
resultCh <- r.update()
|
||
|
}()
|
||
|
select {
|
||
|
case <-r.updateCh:
|
||
|
require.True(t, <-resultCh)
|
||
|
case <-time.After(5 * time.Second):
|
||
|
t.Fatal("No message was received on update channel")
|
||
|
}
|
||
|
})
|
||
|
t.Run("eval should send to evalCh", func(t *testing.T) {
|
||
|
r := newAlertRuleInfo(context.Background())
|
||
|
expected := time.Now()
|
||
|
resultCh := make(chan bool)
|
||
|
version := rand.Int63()
|
||
|
go func() {
|
||
|
resultCh <- r.eval(expected, version)
|
||
|
}()
|
||
|
select {
|
||
|
case ctx := <-r.evalCh:
|
||
|
require.Equal(t, version, ctx.version)
|
||
|
require.Equal(t, expected, ctx.scheduledAt)
|
||
|
require.True(t, <-resultCh)
|
||
|
case <-time.After(5 * time.Second):
|
||
|
t.Fatal("No message was received on eval channel")
|
||
|
}
|
||
|
})
|
||
|
t.Run("eval should exit when context is cancelled", func(t *testing.T) {
|
||
|
r := newAlertRuleInfo(context.Background())
|
||
|
resultCh := make(chan bool)
|
||
|
go func() {
|
||
|
resultCh <- r.eval(time.Now(), rand.Int63())
|
||
|
}()
|
||
|
runtime.Gosched()
|
||
|
r.stop()
|
||
|
select {
|
||
|
case result := <-resultCh:
|
||
|
require.False(t, result)
|
||
|
case <-time.After(5 * time.Second):
|
||
|
t.Fatal("No message was received on eval channel")
|
||
|
}
|
||
|
})
|
||
|
})
|
||
|
t.Run("when rule evaluation is stopped", func(t *testing.T) {
|
||
|
t.Run("Update should do nothing", func(t *testing.T) {
|
||
|
r := newAlertRuleInfo(context.Background())
|
||
|
r.stop()
|
||
|
require.False(t, r.update())
|
||
|
})
|
||
|
t.Run("eval should do nothing", func(t *testing.T) {
|
||
|
r := newAlertRuleInfo(context.Background())
|
||
|
r.stop()
|
||
|
require.False(t, r.eval(time.Now(), rand.Int63()))
|
||
|
})
|
||
|
t.Run("stop should do nothing", func(t *testing.T) {
|
||
|
r := newAlertRuleInfo(context.Background())
|
||
|
r.stop()
|
||
|
r.stop()
|
||
|
})
|
||
|
})
|
||
|
t.Run("should be thread-safe", func(t *testing.T) {
|
||
|
r := newAlertRuleInfo(context.Background())
|
||
|
wg := sync.WaitGroup{}
|
||
|
go func() {
|
||
|
for {
|
||
|
select {
|
||
|
case <-r.evalCh:
|
||
|
time.Sleep(time.Microsecond)
|
||
|
case <-r.updateCh:
|
||
|
time.Sleep(time.Microsecond)
|
||
|
case <-r.ctx.Done():
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
}()
|
||
|
|
||
|
for i := 0; i < 10; i++ {
|
||
|
wg.Add(1)
|
||
|
go func() {
|
||
|
for i := 0; i < 20; i++ {
|
||
|
max := 3
|
||
|
if i <= 10 {
|
||
|
max = 2
|
||
|
}
|
||
|
switch rand.Intn(max) + 1 {
|
||
|
case 1:
|
||
|
r.update()
|
||
|
case 2:
|
||
|
r.eval(time.Now(), rand.Int63())
|
||
|
case 3:
|
||
|
r.stop()
|
||
|
}
|
||
|
}
|
||
|
wg.Done()
|
||
|
}()
|
||
|
}
|
||
|
|
||
|
wg.Wait()
|
||
|
})
|
||
|
}
|