2018-07-26 20:27:35 +00:00
|
|
|
package storetest
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
"reflect"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/influxdata/platform"
|
|
|
|
"github.com/influxdata/platform/task/backend"
|
|
|
|
)
|
|
|
|
|
|
|
|
type CreateRunStoreFunc func(*testing.T) (backend.LogWriter, backend.LogReader)
|
|
|
|
type DestroyRunStoreFunc func(*testing.T, backend.LogWriter, backend.LogReader)
|
|
|
|
|
|
|
|
func NewRunStoreTest(name string, crf CreateRunStoreFunc, drf DestroyRunStoreFunc) func(*testing.T) {
|
|
|
|
return func(t *testing.T) {
|
|
|
|
t.Run(name, func(t *testing.T) {
|
2018-09-06 21:55:55 +00:00
|
|
|
t.Run("UpdateRunState", func(t *testing.T) {
|
2018-07-26 20:27:35 +00:00
|
|
|
updateRunState(t, crf, drf)
|
|
|
|
})
|
|
|
|
t.Run("RunLog", func(t *testing.T) {
|
|
|
|
runLogTest(t, crf, drf)
|
|
|
|
})
|
|
|
|
t.Run("ListRuns", func(t *testing.T) {
|
|
|
|
listRunsTest(t, crf, drf)
|
|
|
|
})
|
|
|
|
t.Run("FindRunByID", func(t *testing.T) {
|
|
|
|
findRunByIDTest(t, crf, drf)
|
|
|
|
})
|
|
|
|
t.Run("ListLogs", func(t *testing.T) {
|
|
|
|
listLogsTest(t, crf, drf)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func updateRunState(t *testing.T, crf CreateRunStoreFunc, drf DestroyRunStoreFunc) {
|
|
|
|
writer, reader := crf(t)
|
|
|
|
defer drf(t, writer, reader)
|
|
|
|
|
2018-08-01 15:51:10 +00:00
|
|
|
task := &backend.StoreTask{
|
2018-08-01 16:43:31 +00:00
|
|
|
ID: platform.ID([]byte("ab01ab01ab01ab01")),
|
|
|
|
Org: platform.ID([]byte("ab01ab01ab01ab05")),
|
2018-08-01 15:51:10 +00:00
|
|
|
}
|
2018-08-30 00:08:50 +00:00
|
|
|
scheduledFor := time.Unix(1, 0).UTC()
|
2018-07-26 20:27:35 +00:00
|
|
|
run := platform.Run{
|
2018-08-14 18:25:19 +00:00
|
|
|
ID: platform.ID([]byte("run")),
|
2018-08-30 00:08:50 +00:00
|
|
|
TaskID: task.ID,
|
2018-09-06 21:55:55 +00:00
|
|
|
Status: "started",
|
2018-08-14 18:25:19 +00:00
|
|
|
ScheduledFor: scheduledFor.Format(time.RFC3339),
|
2018-07-26 20:27:35 +00:00
|
|
|
}
|
2018-09-06 21:55:55 +00:00
|
|
|
rlb := backend.RunLogBase{
|
|
|
|
Task: task,
|
|
|
|
RunID: run.ID,
|
|
|
|
RunScheduledFor: 1,
|
2018-07-26 20:27:35 +00:00
|
|
|
}
|
|
|
|
|
2018-08-30 00:08:50 +00:00
|
|
|
startAt := time.Unix(2, 0).UTC()
|
2018-09-06 21:55:55 +00:00
|
|
|
if err := writer.UpdateRunState(context.Background(), rlb, startAt, backend.RunStarted); err != nil {
|
2018-07-26 20:27:35 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2018-08-14 18:25:19 +00:00
|
|
|
run.StartedAt = startAt.Format(time.RFC3339Nano)
|
2018-07-26 20:27:35 +00:00
|
|
|
run.Status = "started"
|
|
|
|
|
2018-09-06 21:55:55 +00:00
|
|
|
returnedRun, err := reader.FindRunByID(context.Background(), task.Org, task.ID, run.ID)
|
2018-07-26 20:27:35 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(run, *returnedRun) {
|
|
|
|
t.Fatalf("expected: %+v, got: %+v", run, returnedRun)
|
|
|
|
}
|
|
|
|
|
2018-08-30 00:08:50 +00:00
|
|
|
endAt := time.Unix(3, 0).UTC()
|
2018-09-06 21:55:55 +00:00
|
|
|
if err := writer.UpdateRunState(context.Background(), rlb, endAt, backend.RunSuccess); err != nil {
|
2018-07-26 20:27:35 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2018-08-14 18:25:19 +00:00
|
|
|
run.FinishedAt = endAt.Format(time.RFC3339Nano)
|
2018-07-26 20:27:35 +00:00
|
|
|
run.Status = "success"
|
|
|
|
|
2018-08-23 18:30:59 +00:00
|
|
|
returnedRun, err = reader.FindRunByID(context.Background(), task.Org, task.ID, run.ID)
|
2018-07-26 20:27:35 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(run, *returnedRun) {
|
|
|
|
t.Fatalf("expected: %+v, got: %+v", run, returnedRun)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func runLogTest(t *testing.T, crf CreateRunStoreFunc, drf DestroyRunStoreFunc) {
|
|
|
|
writer, reader := crf(t)
|
|
|
|
defer drf(t, writer, reader)
|
|
|
|
|
2018-08-01 15:51:10 +00:00
|
|
|
task := &backend.StoreTask{
|
2018-08-01 16:43:31 +00:00
|
|
|
ID: platform.ID([]byte("ab01ab01ab01ab01")),
|
|
|
|
Org: platform.ID([]byte("ab01ab01ab01ab05")),
|
2018-08-01 15:51:10 +00:00
|
|
|
}
|
|
|
|
|
2018-09-06 21:55:55 +00:00
|
|
|
sf := time.Now().UTC()
|
|
|
|
sa := sf.Add(time.Second)
|
2018-07-26 20:27:35 +00:00
|
|
|
run := platform.Run{
|
2018-08-14 18:25:19 +00:00
|
|
|
ID: platform.ID([]byte("run")),
|
2018-08-30 00:08:50 +00:00
|
|
|
TaskID: task.ID,
|
2018-09-06 21:55:55 +00:00
|
|
|
Status: "started",
|
|
|
|
ScheduledFor: sf.Format(time.RFC3339),
|
|
|
|
StartedAt: sa.Format(time.RFC3339),
|
|
|
|
}
|
|
|
|
rlb := backend.RunLogBase{
|
|
|
|
Task: task,
|
|
|
|
RunID: run.ID,
|
|
|
|
RunScheduledFor: sf.Unix(),
|
2018-07-26 20:27:35 +00:00
|
|
|
}
|
|
|
|
|
2018-08-30 00:08:50 +00:00
|
|
|
logTime := time.Now().UTC()
|
2018-07-26 20:27:35 +00:00
|
|
|
|
2018-09-06 21:55:55 +00:00
|
|
|
if err := writer.AddRunLog(context.Background(), rlb, logTime, "bad"); err == nil {
|
2018-07-26 20:27:35 +00:00
|
|
|
t.Fatal("shouldn't be able to log against non existing run")
|
|
|
|
}
|
|
|
|
|
2018-09-06 21:55:55 +00:00
|
|
|
err := writer.UpdateRunState(context.Background(), rlb, sa, backend.RunStarted)
|
2018-07-26 20:27:35 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2018-09-06 21:55:55 +00:00
|
|
|
if err := writer.AddRunLog(context.Background(), rlb, logTime, "first"); err != nil {
|
2018-07-26 20:27:35 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2018-09-06 21:55:55 +00:00
|
|
|
if err := writer.AddRunLog(context.Background(), rlb, logTime, "second"); err != nil {
|
2018-07-26 20:27:35 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2018-09-06 21:55:55 +00:00
|
|
|
if err := writer.AddRunLog(context.Background(), rlb, logTime, "third"); err != nil {
|
2018-07-26 20:27:35 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2018-08-30 00:08:50 +00:00
|
|
|
fmtLogTime := logTime.UTC().Format(time.RFC3339)
|
2018-07-26 20:27:35 +00:00
|
|
|
run.Log = platform.Log(fmt.Sprintf("%s: first\n%s: second\n%s: third", fmtLogTime, fmtLogTime, fmtLogTime))
|
2018-08-23 18:30:59 +00:00
|
|
|
returnedRun, err := reader.FindRunByID(context.Background(), task.Org, task.ID, run.ID)
|
2018-07-26 20:27:35 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(run, *returnedRun) {
|
|
|
|
t.Fatalf("expected: %+v, got: %+v", run, returnedRun)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func listRunsTest(t *testing.T, crf CreateRunStoreFunc, drf DestroyRunStoreFunc) {
|
|
|
|
writer, reader := crf(t)
|
|
|
|
defer drf(t, writer, reader)
|
|
|
|
|
2018-08-01 15:51:10 +00:00
|
|
|
task := &backend.StoreTask{
|
2018-08-01 16:43:31 +00:00
|
|
|
ID: platform.ID([]byte("ab01ab01ab01ab01")),
|
|
|
|
Org: platform.ID([]byte("ab01ab01ab01ab05")),
|
2018-08-01 15:51:10 +00:00
|
|
|
}
|
2018-07-26 20:27:35 +00:00
|
|
|
|
2018-08-01 15:51:10 +00:00
|
|
|
if _, err := reader.ListRuns(context.Background(), platform.RunFilter{Task: &task.ID}); err == nil {
|
2018-07-26 20:27:35 +00:00
|
|
|
t.Fatal("failed to error on bad id")
|
|
|
|
}
|
|
|
|
|
|
|
|
runs := make([]platform.Run, 200)
|
|
|
|
for i := 0; i < len(runs); i++ {
|
2018-08-30 00:08:50 +00:00
|
|
|
scheduledFor := time.Unix(int64(i), 0).UTC()
|
2018-07-26 20:27:35 +00:00
|
|
|
runs[i] = platform.Run{
|
2018-08-14 18:25:19 +00:00
|
|
|
ID: platform.ID([]byte(fmt.Sprintf("run%d", i))),
|
2018-09-06 21:55:55 +00:00
|
|
|
Status: "started",
|
2018-08-14 18:25:19 +00:00
|
|
|
ScheduledFor: scheduledFor.Format(time.RFC3339),
|
2018-07-26 20:27:35 +00:00
|
|
|
}
|
2018-09-06 21:55:55 +00:00
|
|
|
rlb := backend.RunLogBase{
|
|
|
|
Task: task,
|
|
|
|
RunID: runs[i].ID,
|
|
|
|
RunScheduledFor: scheduledFor.Unix(),
|
|
|
|
}
|
2018-07-26 20:27:35 +00:00
|
|
|
|
2018-09-06 21:55:55 +00:00
|
|
|
err := writer.UpdateRunState(context.Background(), rlb, scheduledFor.Add(time.Second), backend.RunStarted)
|
2018-07-26 20:27:35 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_, err := reader.ListRuns(context.Background(), platform.RunFilter{})
|
|
|
|
if err == nil {
|
|
|
|
t.Fatal("failed to error without any filter")
|
|
|
|
}
|
|
|
|
|
|
|
|
listRuns, err := reader.ListRuns(context.Background(), platform.RunFilter{
|
2018-08-01 15:51:10 +00:00
|
|
|
Task: &task.ID,
|
2018-07-26 20:27:35 +00:00
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(listRuns) != len(runs) {
|
|
|
|
t.Fatalf("retrieved: %d, expected: %d", len(listRuns), len(runs))
|
|
|
|
}
|
|
|
|
|
|
|
|
listRuns, err = reader.ListRuns(context.Background(), platform.RunFilter{
|
2018-08-01 15:51:10 +00:00
|
|
|
Task: &task.ID,
|
2018-07-26 20:27:35 +00:00
|
|
|
After: &runs[20].ID,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(listRuns) != len(runs)-20 {
|
|
|
|
t.Fatalf("retrieved: %d, expected: %d", len(listRuns), len(runs)-20)
|
|
|
|
}
|
|
|
|
|
|
|
|
listRuns, err = reader.ListRuns(context.Background(), platform.RunFilter{
|
2018-08-01 15:51:10 +00:00
|
|
|
Task: &task.ID,
|
2018-07-26 20:27:35 +00:00
|
|
|
Limit: 30,
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(listRuns) != 30 {
|
|
|
|
t.Fatalf("retrieved: %d, expected: %d", len(listRuns), 30)
|
|
|
|
}
|
|
|
|
|
2018-08-14 18:25:19 +00:00
|
|
|
scheduledFor, _ := time.Parse(time.RFC3339, runs[34].ScheduledFor)
|
2018-07-26 20:27:35 +00:00
|
|
|
listRuns, err = reader.ListRuns(context.Background(), platform.RunFilter{
|
2018-08-01 15:51:10 +00:00
|
|
|
Task: &task.ID,
|
2018-08-30 00:08:50 +00:00
|
|
|
AfterTime: scheduledFor.Add(-time.Second).Format(time.RFC3339),
|
2018-07-26 20:27:35 +00:00
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(listRuns) != len(runs)-34 {
|
|
|
|
t.Fatalf("retrieved: %d, expected: %d", len(listRuns), len(runs)-34)
|
|
|
|
}
|
|
|
|
|
2018-08-14 18:25:19 +00:00
|
|
|
scheduledFor, _ = time.Parse(time.RFC3339, runs[34].ScheduledFor)
|
2018-07-26 20:27:35 +00:00
|
|
|
listRuns, err = reader.ListRuns(context.Background(), platform.RunFilter{
|
2018-08-01 15:51:10 +00:00
|
|
|
Task: &task.ID,
|
2018-08-14 18:25:19 +00:00
|
|
|
BeforeTime: scheduledFor.Add(time.Nanosecond).Format(time.RFC3339),
|
2018-07-26 20:27:35 +00:00
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(listRuns) != 35 {
|
|
|
|
t.Fatalf("retrieved: %d, expected: %d", len(listRuns), 34)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func findRunByIDTest(t *testing.T, crf CreateRunStoreFunc, drf DestroyRunStoreFunc) {
|
|
|
|
writer, reader := crf(t)
|
|
|
|
defer drf(t, writer, reader)
|
|
|
|
|
2018-08-23 18:30:59 +00:00
|
|
|
if _, err := reader.FindRunByID(context.Background(), platform.ID([]byte("fat")), platform.ID([]byte("ugly")), platform.ID([]byte("bad"))); err == nil {
|
2018-07-26 20:27:35 +00:00
|
|
|
t.Fatal("failed to error with bad id")
|
|
|
|
}
|
|
|
|
|
2018-08-01 15:51:10 +00:00
|
|
|
task := &backend.StoreTask{
|
2018-08-01 16:43:31 +00:00
|
|
|
ID: platform.ID([]byte("ab01ab01ab01ab01")),
|
|
|
|
Org: platform.ID([]byte("ab01ab01ab01ab05")),
|
2018-08-01 15:51:10 +00:00
|
|
|
}
|
2018-09-06 21:55:55 +00:00
|
|
|
sf := time.Now().UTC()
|
|
|
|
sa := sf.Add(time.Second)
|
|
|
|
|
2018-07-26 20:27:35 +00:00
|
|
|
run := platform.Run{
|
2018-08-14 18:25:19 +00:00
|
|
|
ID: platform.ID([]byte("run")),
|
2018-08-30 00:08:50 +00:00
|
|
|
TaskID: task.ID,
|
2018-09-06 21:55:55 +00:00
|
|
|
Status: "started",
|
|
|
|
ScheduledFor: sf.Format(time.RFC3339),
|
|
|
|
StartedAt: sa.Format(time.RFC3339),
|
|
|
|
}
|
|
|
|
rlb := backend.RunLogBase{
|
|
|
|
Task: task,
|
|
|
|
RunID: run.ID,
|
|
|
|
RunScheduledFor: sf.Unix(),
|
2018-07-26 20:27:35 +00:00
|
|
|
}
|
|
|
|
|
2018-09-06 21:55:55 +00:00
|
|
|
if err := writer.UpdateRunState(context.Background(), rlb, sa, backend.RunStarted); err != nil {
|
2018-07-26 20:27:35 +00:00
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2018-08-23 18:30:59 +00:00
|
|
|
returnedRun, err := reader.FindRunByID(context.Background(), task.Org, task.ID, run.ID)
|
2018-07-26 20:27:35 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !reflect.DeepEqual(run, *returnedRun) {
|
|
|
|
t.Fatalf("expected:\n%#v, got: \n%#v", run, *returnedRun)
|
|
|
|
}
|
|
|
|
|
|
|
|
returnedRun.Log = "cows"
|
|
|
|
|
2018-08-23 18:30:59 +00:00
|
|
|
rr2, err := reader.FindRunByID(context.Background(), task.Org, task.ID, run.ID)
|
2018-07-26 20:27:35 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if reflect.DeepEqual(returnedRun, rr2) {
|
|
|
|
t.Fatalf("updateing returned run modified RunStore data")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func listLogsTest(t *testing.T, crf CreateRunStoreFunc, drf DestroyRunStoreFunc) {
|
|
|
|
writer, reader := crf(t)
|
|
|
|
defer drf(t, writer, reader)
|
|
|
|
|
2018-08-01 15:51:10 +00:00
|
|
|
task := &backend.StoreTask{
|
2018-08-01 16:43:31 +00:00
|
|
|
ID: platform.ID([]byte("ab01ab01ab01ab01")),
|
|
|
|
Org: platform.ID([]byte("ab01ab01ab01ab05")),
|
2018-08-01 15:51:10 +00:00
|
|
|
}
|
2018-07-26 20:27:35 +00:00
|
|
|
|
|
|
|
if _, err := reader.ListLogs(context.Background(), platform.LogFilter{}); err == nil {
|
|
|
|
t.Fatal("failed to error with no filter")
|
|
|
|
}
|
2018-08-01 15:51:10 +00:00
|
|
|
if _, err := reader.ListLogs(context.Background(), platform.LogFilter{Run: &task.ID}); err == nil {
|
2018-07-26 20:27:35 +00:00
|
|
|
t.Fatal("failed to error with no filter")
|
|
|
|
}
|
|
|
|
|
|
|
|
runs := make([]platform.Run, 20)
|
|
|
|
for i := 0; i < len(runs); i++ {
|
2018-09-06 21:55:55 +00:00
|
|
|
sf := time.Unix(int64(i), 0)
|
2018-07-26 20:27:35 +00:00
|
|
|
runs[i] = platform.Run{
|
2018-08-14 18:25:19 +00:00
|
|
|
ID: platform.ID([]byte(fmt.Sprintf("run%d", i))),
|
|
|
|
Status: "started",
|
2018-09-06 21:55:55 +00:00
|
|
|
ScheduledFor: sf.UTC().Format(time.RFC3339),
|
|
|
|
}
|
|
|
|
rlb := backend.RunLogBase{
|
|
|
|
Task: task,
|
|
|
|
RunID: runs[i].ID,
|
|
|
|
RunScheduledFor: sf.Unix(),
|
2018-07-26 20:27:35 +00:00
|
|
|
}
|
|
|
|
|
2018-09-06 21:55:55 +00:00
|
|
|
err := writer.UpdateRunState(context.Background(), rlb, time.Now(), backend.RunStarted)
|
2018-07-26 20:27:35 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2018-09-06 21:55:55 +00:00
|
|
|
writer.AddRunLog(context.Background(), rlb, time.Unix(int64(i), 0), fmt.Sprintf("log%d", i))
|
2018-07-26 20:27:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
logs, err := reader.ListLogs(context.Background(), platform.LogFilter{Run: &runs[4].ID})
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
fmtTimelog := time.Unix(int64(4), 0).Format(time.RFC3339)
|
|
|
|
if fmtTimelog+": log4" != string(logs[0]) {
|
|
|
|
t.Fatalf("expected: %+v, got: %+v", fmtTimelog+": log4", string(logs[0]))
|
|
|
|
}
|
|
|
|
|
2018-08-01 15:51:10 +00:00
|
|
|
logs, err = reader.ListLogs(context.Background(), platform.LogFilter{Task: &task.ID})
|
2018-07-26 20:27:35 +00:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(logs) != len(runs) {
|
|
|
|
t.Fatal("not all logs retrieved")
|
|
|
|
}
|
|
|
|
}
|