influxdb/task/backend/middleware/check_middleware_test.go

326 lines
9.2 KiB
Go
Raw Normal View History

package middleware_test
import (
"context"
"fmt"
"testing"
"time"
"github.com/influxdata/influxdb/v2"
"github.com/influxdata/influxdb/v2/mock"
"github.com/influxdata/influxdb/v2/notification/check"
"github.com/influxdata/influxdb/v2/notification/rule"
"github.com/influxdata/influxdb/v2/task/backend/middleware"
)
type pipingCoordinator struct {
err error
taskCreatedPipe chan *influxdb.Task
taskUpdatedPipe chan *influxdb.Task
taskDeletedPipe chan influxdb.ID
}
func (p *pipingCoordinator) taskCreatedChan() <-chan *influxdb.Task {
if p.taskCreatedPipe == nil {
p.taskCreatedPipe = make(chan *influxdb.Task, 1)
}
return p.taskCreatedPipe
}
func (p *pipingCoordinator) taskUpdatedChan() <-chan *influxdb.Task {
if p.taskUpdatedPipe == nil {
p.taskUpdatedPipe = make(chan *influxdb.Task, 1)
}
return p.taskUpdatedPipe
}
func (p *pipingCoordinator) taskDeletedChan() <-chan influxdb.ID {
if p.taskDeletedPipe == nil {
p.taskDeletedPipe = make(chan influxdb.ID, 1)
}
return p.taskDeletedPipe
}
func (p *pipingCoordinator) TaskCreated(_ context.Context, t *influxdb.Task) error {
if p.taskCreatedPipe != nil {
p.taskCreatedPipe <- t
}
return p.err
}
func (p *pipingCoordinator) TaskUpdated(_ context.Context, from, to *influxdb.Task) error {
if p.taskUpdatedPipe != nil {
p.taskUpdatedPipe <- to
}
return p.err
}
func (p *pipingCoordinator) TaskDeleted(_ context.Context, id influxdb.ID) error {
if p.taskDeletedPipe != nil {
p.taskDeletedPipe <- id
}
return p.err
}
func (p *pipingCoordinator) RunCancelled(ctx context.Context, runID influxdb.ID) error {
return p.err
}
func (p *pipingCoordinator) RunRetried(ctx context.Context, task *influxdb.Task, run *influxdb.Run) error {
return p.err
}
func (p *pipingCoordinator) RunForced(ctx context.Context, task *influxdb.Task, run *influxdb.Run) error {
return p.err
}
type mockedSvc struct {
taskSvc *mock.TaskService
checkSvc *mock.CheckService
notificationSvc *mock.NotificationRuleStore
pipingCoordinator *pipingCoordinator
}
func newMockServices() mockedSvc {
return mockedSvc{
taskSvc: &mock.TaskService{
FindTaskByIDFn: func(_ context.Context, id influxdb.ID) (*influxdb.Task, error) { return &influxdb.Task{ID: id}, nil },
CreateTaskFn: func(context.Context, influxdb.TaskCreate) (*influxdb.Task, error) { return &influxdb.Task{ID: 1}, nil },
UpdateTaskFn: func(_ context.Context, id influxdb.ID, _ influxdb.TaskUpdate) (*influxdb.Task, error) {
return &influxdb.Task{ID: id}, nil
},
DeleteTaskFn: func(context.Context, influxdb.ID) error { return nil },
},
checkSvc: &mock.CheckService{
FindCheckByIDFn: func(_ context.Context, id influxdb.ID) (influxdb.Check, error) {
c := &check.Deadman{}
c.SetID(id)
return c, nil
},
2019-09-18 20:19:51 +00:00
CreateCheckFn: func(context.Context, influxdb.CheckCreate, influxdb.ID) error { return nil },
UpdateCheckFn: func(_ context.Context, _ influxdb.ID, c influxdb.CheckCreate) (influxdb.Check, error) { return c, nil },
PatchCheckFn: func(_ context.Context, id influxdb.ID, _ influxdb.CheckUpdate) (influxdb.Check, error) {
c := &check.Deadman{}
c.SetID(id)
return c, nil
},
DeleteCheckFn: func(context.Context, influxdb.ID) error { return nil },
},
notificationSvc: &mock.NotificationRuleStore{
FindNotificationRuleByIDF: func(_ context.Context, id influxdb.ID) (influxdb.NotificationRule, error) {
c := &rule.HTTP{}
c.SetID(id)
return c, nil
},
2019-09-18 20:19:51 +00:00
CreateNotificationRuleF: func(context.Context, influxdb.NotificationRuleCreate, influxdb.ID) error { return nil },
UpdateNotificationRuleF: func(_ context.Context, _ influxdb.ID, c influxdb.NotificationRuleCreate, _ influxdb.ID) (influxdb.NotificationRule, error) {
return c, nil
},
PatchNotificationRuleF: func(_ context.Context, id influxdb.ID, _ influxdb.NotificationRuleUpdate) (influxdb.NotificationRule, error) {
c := &rule.HTTP{}
c.SetID(id)
return c, nil
},
DeleteNotificationRuleF: func(context.Context, influxdb.ID) error { return nil },
},
pipingCoordinator: &pipingCoordinator{},
}
}
func newCheckSvcStack() (mockedSvc, *middleware.CoordinatingCheckService) {
msvcs := newMockServices()
return msvcs, middleware.NewCheckService(msvcs.checkSvc, msvcs.taskSvc, msvcs.pipingCoordinator)
}
func TestCheckCreate(t *testing.T) {
mocks, checkService := newCheckSvcStack()
ch := mocks.pipingCoordinator.taskCreatedChan()
check := &check.Deadman{}
check.SetTaskID(4)
2019-09-18 20:19:51 +00:00
cc := influxdb.CheckCreate{
Check: check,
Status: influxdb.Active,
}
err := checkService.CreateCheck(context.Background(), cc, 1)
if err != nil {
t.Fatal(err)
}
select {
case task := <-ch:
if task.ID != check.GetTaskID() {
t.Fatalf("task sent to coordinator doesn't match expected")
}
default:
t.Fatal("didn't receive task")
}
mocks.pipingCoordinator.err = fmt.Errorf("bad")
mocks.checkSvc.DeleteCheckFn = func(context.Context, influxdb.ID) error { return fmt.Errorf("AARGH") }
2019-09-18 20:19:51 +00:00
err = checkService.CreateCheck(context.Background(), cc, 1)
if err.Error() != "schedule task failed: bad\n\tcleanup also failed: AARGH" {
t.Fatal(err)
}
}
func TestCheckUpdateFromInactive(t *testing.T) {
mocks, checkService := newCheckSvcStack()
latest := time.Now().UTC()
checkService.Now = func() time.Time {
return latest
}
ch := mocks.pipingCoordinator.taskUpdatedChan()
2019-09-18 20:19:51 +00:00
mocks.checkSvc.UpdateCheckFn = func(_ context.Context, _ influxdb.ID, c influxdb.CheckCreate) (influxdb.Check, error) {
c.SetTaskID(10)
c.SetUpdatedAt(latest.Add(-20 * time.Hour))
return c, nil
}
mocks.checkSvc.PatchCheckFn = func(_ context.Context, _ influxdb.ID, c influxdb.CheckUpdate) (influxdb.Check, error) {
ic := &check.Deadman{}
ic.SetTaskID(10)
ic.SetUpdatedAt(latest.Add(-20 * time.Hour))
return ic, nil
}
mocks.checkSvc.FindCheckByIDFn = func(_ context.Context, id influxdb.ID) (influxdb.Check, error) {
c := &check.Deadman{}
c.SetID(id)
c.SetTaskID(1)
return c, nil
}
mocks.taskSvc.FindTaskByIDFn = func(_ context.Context, id influxdb.ID) (*influxdb.Task, error) {
if id == 1 {
return &influxdb.Task{ID: id, Status: string(influxdb.TaskInactive)}, nil
} else if id == 10 {
return &influxdb.Task{ID: id, Status: string(influxdb.TaskActive)}, nil
}
return &influxdb.Task{ID: id}, nil
}
deadman := &check.Deadman{}
deadman.SetTaskID(10)
2019-09-18 20:19:51 +00:00
cc := influxdb.CheckCreate{
Check: deadman,
Status: influxdb.Active,
}
thecheck, err := checkService.UpdateCheck(context.Background(), 1, cc)
if err != nil {
t.Fatal(err)
}
select {
case task := <-ch:
if task.ID != thecheck.GetTaskID() {
t.Fatalf("task sent to coordinator doesn't match expected")
}
if task.LatestCompleted != latest {
t.Fatalf("update returned incorrect LatestCompleted, expected %s got %s, or ", latest.Format(time.RFC3339), task.LatestCompleted)
}
default:
t.Fatal("didn't receive task")
}
action := influxdb.Active
thecheck, err = checkService.PatchCheck(context.Background(), 1, influxdb.CheckUpdate{Status: &action})
if err != nil {
t.Fatal(err)
}
select {
case task := <-ch:
if task.ID != thecheck.GetTaskID() {
t.Fatalf("task sent to coordinator doesn't match expected")
}
if task.LatestCompleted != latest {
t.Fatalf("update returned incorrect LatestCompleted, expected %s got %s, or ", latest.Format(time.RFC3339), task.LatestCompleted)
}
default:
t.Fatal("didn't receive task")
}
}
func TestCheckUpdate(t *testing.T) {
mocks, checkService := newCheckSvcStack()
ch := mocks.pipingCoordinator.taskUpdatedChan()
2019-09-18 20:19:51 +00:00
mocks.checkSvc.UpdateCheckFn = func(_ context.Context, _ influxdb.ID, c influxdb.CheckCreate) (influxdb.Check, error) {
c.SetTaskID(10)
return c, nil
}
deadman := &check.Deadman{}
deadman.SetTaskID(4)
2019-09-18 20:19:51 +00:00
cc := influxdb.CheckCreate{
Check: deadman,
Status: influxdb.Active,
}
check, err := checkService.UpdateCheck(context.Background(), 1, cc)
if err != nil {
t.Fatal(err)
}
select {
case task := <-ch:
if task.ID != check.GetTaskID() {
t.Fatalf("task sent to coordinator doesn't match expected")
}
default:
t.Fatal("didn't receive task")
}
}
func TestCheckPatch(t *testing.T) {
mocks, checkService := newCheckSvcStack()
ch := mocks.pipingCoordinator.taskUpdatedChan()
deadman := &check.Deadman{}
deadman.SetTaskID(4)
mocks.checkSvc.PatchCheckFn = func(context.Context, influxdb.ID, influxdb.CheckUpdate) (influxdb.Check, error) {
return deadman, nil
}
check, err := checkService.PatchCheck(context.Background(), 1, influxdb.CheckUpdate{})
if err != nil {
t.Fatal(err)
}
select {
case task := <-ch:
if task.ID != check.GetTaskID() {
t.Fatalf("task sent to coordinator doesn't match expected")
}
default:
t.Fatal("didn't receive task")
}
}
func TestCheckDelete(t *testing.T) {
mocks, checkService := newCheckSvcStack()
ch := mocks.pipingCoordinator.taskDeletedChan()
mocks.checkSvc.FindCheckByIDFn = func(_ context.Context, id influxdb.ID) (influxdb.Check, error) {
c := &check.Deadman{}
c.SetID(id)
c.SetTaskID(21)
return c, nil
}
err := checkService.DeleteCheck(context.Background(), 1)
if err != nil {
t.Fatal(err)
}
select {
case id := <-ch:
if id != influxdb.ID(21) {
t.Fatalf("task sent to coordinator doesn't match expected")
}
default:
t.Fatal("didn't receive task")
}
}