github.com/qri-io/qri@v0.10.1-0.20220104210721-c771715036cb/automation/spec/run.go (about) 1 package spec 2 3 import ( 4 "context" 5 "errors" 6 "testing" 7 "time" 8 9 "github.com/google/go-cmp/cmp" 10 "github.com/qri-io/qri/automation/run" 11 "github.com/qri-io/qri/automation/workflow" 12 "github.com/qri-io/qri/base/params" 13 ) 14 15 // AssertRunStore confirms the expected behavior of a run.Store interface 16 func AssertRunStore(t *testing.T, store run.Store) { 17 ctx := context.Background() 18 assertCreatePut(ctx, t, store) 19 20 wid := workflow.ID("test id") 21 expectedRuns := [3]*run.State{} 22 now := time.Now() 23 for i := 2; i >= 0; i-- { 24 r := &run.State{WorkflowID: wid} 25 st := now.Add(time.Duration(0-i) * time.Hour) 26 et := st.Add(time.Minute) 27 r.StartTime = &st 28 r.StopTime = &et 29 if i == 0 { 30 r.Status = run.RSWaiting 31 } 32 expectedRun, err := store.Create(ctx, r) 33 if err != nil { 34 t.Fatalf("store.Put unexpected error: %s", err) 35 } 36 expectedRuns[i] = expectedRun 37 } 38 39 if _, err := store.Get(ctx, "bad run id"); !errors.Is(err, run.ErrNotFound) { 40 t.Fatalf("store.Get should emit a run.ErrNotFound error if given an unknown run ID") 41 } 42 for i := 0; i < 3; i++ { 43 got, err := store.Get(ctx, expectedRuns[i].ID) 44 if err != nil { 45 t.Fatalf("store.Get unexpected error: %s", err) 46 } 47 48 if diff := cmp.Diff(expectedRuns[i], got); diff != "" { 49 t.Errorf("store.Get i=%d mismatch (-want +got):\n%s", i, diff) 50 } 51 } 52 53 badWID := workflow.ID("bad id") 54 if _, err := store.Count(ctx, badWID); !errors.Is(err, run.ErrUnknownWorkflowID) { 55 t.Fatalf("store.Count should emit a run.ErrUnknownWorkflowID error when given a workflow ID not associated with any runs in the Store") 56 } 57 58 gotCount, err := store.Count(ctx, wid) 59 if err != nil { 60 t.Fatalf("store.Count unexpected error: %s", err) 61 } 62 if gotCount != 3 { 63 t.Errorf("store.Count count mismatch, expected 3, got %d", gotCount) 64 } 65 66 if _, err := store.List(ctx, badWID, params.ListAll); !errors.Is(err, run.ErrUnknownWorkflowID) { 67 t.Fatalf("store.List should emit a run.ErrUnknownWorkflowID error when given a workflow ID not associated with any runs in the Store") 68 } 69 gotRuns, err := store.List(ctx, wid, params.ListAll) 70 if err != nil { 71 t.Fatalf("store.List unexpected error: %s", err) 72 } 73 if diff := cmp.Diff(expectedRuns[:], gotRuns); diff != "" { 74 t.Errorf("store.List mismatch (-want +got):\n%s", diff) 75 } 76 77 if _, err := store.GetLatest(ctx, badWID); !errors.Is(err, run.ErrUnknownWorkflowID) { 78 t.Fatalf("store.GetLatest should emit a run.ErrUnknownWorkflowID error when given a workflow ID not associated with any runs in the Store") 79 } 80 got, err := store.GetLatest(ctx, wid) 81 if err != nil { 82 t.Fatalf("store.GetLatest unexpected error: %s", err) 83 } 84 if diff := cmp.Diff(expectedRuns[0], got); diff != "" { 85 t.Errorf("store.GetLatest mismatch (-want +got): \n%s", diff) 86 } 87 88 if _, err := store.GetStatus(ctx, badWID); !errors.Is(err, run.ErrUnknownWorkflowID) { 89 t.Fatalf("store.GetStatus should emit a run.ErrUnknownWorkflowID error when given a workflow ID not associated with any runs in the Store") 90 } 91 gotStatus, err := store.GetStatus(ctx, wid) 92 if err != nil { 93 t.Fatalf("store.GetStatus unexpected error: %s", err) 94 } 95 if gotStatus != run.RSWaiting { 96 t.Errorf("store.GetStatus mismatch: expected %q, got %q", run.RSWaiting, gotStatus) 97 } 98 99 gotRuns, err = store.ListByStatus(ctx, "", run.RSWaiting, params.ListAll) 100 if err != nil { 101 t.Fatalf("store.ListByStatus unexpected error: %s", err) 102 } 103 104 if diff := cmp.Diff(expectedRuns[:1], gotRuns); diff != "" { 105 t.Errorf("store.ListByStatus mismatch (-want +got): \n%s", diff) 106 } 107 } 108 109 // assertCreatePut confirms the expected behavior of the run.Store's Put method 110 func assertCreatePut(ctx context.Context, t *testing.T, store run.Store) { 111 if _, err := store.Create(ctx, nil); err == nil { 112 t.Fatal("store.Create should error when passed nil") 113 } 114 expected := &run.State{} 115 if _, err := store.Create(ctx, expected); !errors.Is(err, run.ErrNoWorkflowID) { 116 t.Fatal("store.Create is expected to emit a run.ErrNoWorkflowID error if you try to create a run.State wit no workflow.ID") 117 } 118 119 wid := workflow.ID("assert test id") 120 expected.WorkflowID = wid 121 122 got, err := store.Create(ctx, expected) 123 if err != nil { 124 t.Fatalf("store.Create unexpected error: %s", err) 125 } 126 if got.ID == "" { 127 t.Fatal("store.Create is expected to fill the run.ID field if given a run.State with an empty ID") 128 } 129 if _, err := store.Create(ctx, got); err == nil { 130 t.Fatal("store.Create is expected to error if trying to create a run State with a run ID that already exists in the store") 131 } 132 133 got, err = store.Create(ctx, expected) 134 if err != nil { 135 t.Fatalf("store.Create should be able to add multiple entries for a single workflow.ID. Unexpected error %s", err) 136 } 137 138 if _, err := store.Put(ctx, nil); err == nil { 139 t.Fatal("store.Put should error when passed nil") 140 } 141 142 if _, err := store.Put(ctx, &run.State{}); err == nil { 143 t.Fatal("store.Put should error when passed a State with no run ID") 144 } 145 if _, err := store.Put(ctx, &run.State{ID: "test_id"}); err == nil { 146 t.Fatal("store.Put should error if you try to add a run.State with no workflow.ID") 147 } 148 if _, err := store.Put(ctx, &run.State{ID: "test_id", WorkflowID: "test workflow ID"}); err == nil { 149 t.Fatal("store.Put should error when passed a new State") 150 } 151 runID := got.ID 152 expected.ID = runID 153 expected.Status = run.RSRunning 154 got, err = store.Put(ctx, expected) 155 if err != nil { 156 t.Fatalf("store.Put unexpected error: %s", err) 157 } 158 if diff := cmp.Diff(expected, got); diff != "" { 159 t.Errorf("run.State mismatch (-want +got):\n%s", diff) 160 } 161 162 if _, err := store.Put(ctx, expected); err != nil { 163 t.Fatalf("store.Put should be able to update the same run multiple times. Unexpected error: %s", err) 164 } 165 166 expected.ID = runID 167 expected.WorkflowID = workflow.ID("new id") 168 if _, err = store.Put(ctx, expected); err == nil { 169 t.Fatal("store.Put should error if the WorkflowID of the given run.State does not match the WorkflowID of the run.State stored") 170 } 171 count, err := store.Count(ctx, got.WorkflowID) 172 if err != nil { 173 t.Fatalf("store.Count unexpected error %s", err) 174 } 175 if count != 2 { 176 t.Fatalf("store.Create/store.Put error: creating a new run should increment the run count, updating a run using run.Put should NOT increment the run count. Expected count of %d, got %d", 2, count) 177 } 178 }