github.com/filecoin-project/bacalhau@v0.3.23-0.20230228154132-45c989550ace/pkg/compute/store/inmemory/store_test.go (about) 1 package inmemory 2 3 import ( 4 "context" 5 "testing" 6 7 "github.com/filecoin-project/bacalhau/pkg/compute/store" 8 "github.com/filecoin-project/bacalhau/pkg/model" 9 "github.com/google/uuid" 10 "github.com/stretchr/testify/suite" 11 ) 12 13 type Suite struct { 14 suite.Suite 15 executionStore store.ExecutionStore 16 execution store.Execution 17 } 18 19 func (s *Suite) SetupTest() { 20 s.executionStore = NewStore() 21 s.execution = newExecution() 22 } 23 24 func TestSuite(t *testing.T) { 25 suite.Run(t, new(Suite)) 26 } 27 28 func (s *Suite) TestCreateExecution() { 29 err := s.executionStore.CreateExecution(context.Background(), s.execution) 30 s.NoError(err) 31 32 // verify the execution was created 33 readExecution, err := s.executionStore.GetExecution(context.Background(), s.execution.ID) 34 s.NoError(err) 35 s.Equal(s.execution, readExecution) 36 37 // verify a history entry was created 38 history, err := s.executionStore.GetExecutionHistory(context.Background(), s.execution.ID) 39 s.NoError(err) 40 s.Len(history, 1) 41 s.verifyHistory(history[0], readExecution, store.ExecutionStateUndefined, newExecutionComment) 42 } 43 44 func (s *Suite) TestCreateExecution_AlreadyExists() { 45 err := s.executionStore.CreateExecution(context.Background(), s.execution) 46 s.NoError(err) 47 48 err = s.executionStore.CreateExecution(context.Background(), s.execution) 49 s.Error(err) 50 } 51 52 func (s *Suite) TestCreateExecution_InvalidState() { 53 s.execution.State = store.ExecutionStateBidAccepted 54 err := s.executionStore.CreateExecution(context.Background(), s.execution) 55 s.Error(err) 56 } 57 58 func (s *Suite) TestGetExecution_DoesntExist() { 59 _, err := s.executionStore.GetExecution(context.Background(), uuid.NewString()) 60 s.ErrorAs(err, &store.ErrExecutionNotFound{}) 61 } 62 63 func (s *Suite) TestGetExecutions() { 64 ctx := context.Background() 65 err := s.executionStore.CreateExecution(ctx, s.execution) 66 s.NoError(err) 67 68 readExecutions, err := s.executionStore.GetExecutions(ctx, s.execution.Shard.ID()) 69 s.NoError(err) 70 s.Len(readExecutions, 1) 71 s.Equal(s.execution, readExecutions[0]) 72 73 // Create another execution for the same shard 74 anotherExecution := newExecution() 75 anotherExecution.Shard = s.execution.Shard 76 err = s.executionStore.CreateExecution(ctx, anotherExecution) 77 s.NoError(err) 78 79 readExecutions, err = s.executionStore.GetExecutions(ctx, s.execution.Shard.ID()) 80 s.NoError(err) 81 s.Len(readExecutions, 2) 82 s.Equal(s.execution, readExecutions[0]) 83 s.Equal(anotherExecution, readExecutions[1]) 84 } 85 86 func (s *Suite) TestGetExecutions_DoesntExist() { 87 _, err := s.executionStore.GetExecutions(context.Background(), uuid.NewString()) 88 s.ErrorAs(err, &store.ErrExecutionsNotFoundForShard{}) 89 } 90 91 func (s *Suite) TestUpdateExecution() { 92 ctx := context.Background() 93 err := s.executionStore.CreateExecution(ctx, s.execution) 94 s.NoError(err) 95 96 // update with no conditions 97 request := store.UpdateExecutionStateRequest{ 98 ExecutionID: s.execution.ID, 99 NewState: store.ExecutionStatePublishing, 100 Comment: "Hello There!", 101 } 102 err = s.executionStore.UpdateExecutionState(ctx, request) 103 s.NoError(err) 104 105 // verify the update happened as expected 106 readExecution, err := s.executionStore.GetExecution(ctx, s.execution.ID) 107 s.NoError(err) 108 s.Equal(request.NewState, readExecution.State) 109 s.Equal(s.execution.Version+1, readExecution.Version) 110 111 // verify a new history entry was created 112 history, err := s.executionStore.GetExecutionHistory(ctx, s.execution.ID) 113 s.NoError(err) 114 s.Len(history, 2) 115 s.verifyHistory(history[1], readExecution, s.execution.State, request.Comment) 116 } 117 118 func (s *Suite) TestUpdateExecution_ConditionsPass() { 119 ctx := context.Background() 120 err := s.executionStore.CreateExecution(ctx, s.execution) 121 s.NoError(err) 122 123 // update with no conditions 124 request := store.UpdateExecutionStateRequest{ 125 ExecutionID: s.execution.ID, 126 ExpectedState: s.execution.State, 127 ExpectedVersion: s.execution.Version, 128 NewState: store.ExecutionStatePublishing, 129 Comment: "Hello There!", 130 } 131 err = s.executionStore.UpdateExecutionState(ctx, request) 132 s.NoError(err) 133 134 // verify the update happened as expected 135 readExecution, err := s.executionStore.GetExecution(ctx, s.execution.ID) 136 s.NoError(err) 137 s.Equal(request.NewState, readExecution.State) 138 s.Equal(s.execution.Version+1, readExecution.Version) 139 } 140 141 func (s *Suite) TestUpdateExecution_ConditionsStateFail() { 142 ctx := context.Background() 143 err := s.executionStore.CreateExecution(ctx, s.execution) 144 s.NoError(err) 145 146 // update with no conditions 147 request := store.UpdateExecutionStateRequest{ 148 ExecutionID: s.execution.ID, 149 ExpectedState: store.ExecutionStateBidAccepted, 150 NewState: store.ExecutionStatePublishing, 151 } 152 err = s.executionStore.UpdateExecutionState(ctx, request) 153 s.ErrorAs(err, &store.ErrInvalidExecutionState{}) 154 } 155 156 func (s *Suite) TestUpdateExecution_ConditionsVersionFail() { 157 ctx := context.Background() 158 err := s.executionStore.CreateExecution(ctx, s.execution) 159 s.NoError(err) 160 161 // update with no conditions 162 request := store.UpdateExecutionStateRequest{ 163 ExecutionID: s.execution.ID, 164 ExpectedVersion: s.execution.Version + 99, 165 NewState: store.ExecutionStatePublishing, 166 } 167 err = s.executionStore.UpdateExecutionState(ctx, request) 168 s.ErrorAs(err, &store.ErrInvalidExecutionVersion{}) 169 } 170 171 func (s *Suite) TestDeleteExecution() { 172 err := s.executionStore.CreateExecution(context.Background(), s.execution) 173 s.NoError(err) 174 175 err = s.executionStore.DeleteExecution(context.Background(), s.execution.ID) 176 s.NoError(err) 177 178 _, err = s.executionStore.GetExecution(context.Background(), s.execution.ID) 179 s.ErrorAs(err, &store.ErrExecutionNotFound{}) 180 181 _, err = s.executionStore.GetExecutions(context.Background(), s.execution.Shard.ID()) 182 s.ErrorAs(err, &store.ErrExecutionsNotFoundForShard{}) 183 } 184 185 func (s *Suite) TestDeleteExecution_MultiEntries() { 186 ctx := context.Background() 187 err := s.executionStore.CreateExecution(ctx, s.execution) 188 s.NoError(err) 189 190 // second execution with same shardID 191 secondExecution := newExecution() 192 secondExecution.Shard = s.execution.Shard 193 err = s.executionStore.CreateExecution(ctx, secondExecution) 194 195 // third execution with different shardID 196 thirdExecution := newExecution() 197 err = s.executionStore.CreateExecution(ctx, thirdExecution) 198 s.NoError(err) 199 200 // validate pre-state 201 firstShardExecutions, err := s.executionStore.GetExecutions(ctx, s.execution.Shard.ID()) 202 s.NoError(err) 203 s.Len(firstShardExecutions, 2) 204 205 secondShardExecutions, err := s.executionStore.GetExecutions(ctx, thirdExecution.Shard.ID()) 206 s.NoError(err) 207 s.Len(secondShardExecutions, 1) 208 209 // delete first execution 210 err = s.executionStore.DeleteExecution(ctx, s.execution.ID) 211 s.NoError(err) 212 _, err = s.executionStore.GetExecution(ctx, s.execution.ID) 213 s.ErrorAs(err, &store.ErrExecutionNotFound{}) 214 executions, err := s.executionStore.GetExecutions(ctx, s.execution.Shard.ID()) 215 s.NoError(err) 216 s.Len(executions, 1) 217 218 // delete second execution 219 err = s.executionStore.DeleteExecution(ctx, secondExecution.ID) 220 s.NoError(err) 221 _, err = s.executionStore.GetExecution(ctx, secondExecution.ID) 222 s.ErrorAs(err, &store.ErrExecutionNotFound{}) 223 executions, err = s.executionStore.GetExecutions(ctx, secondExecution.Shard.ID()) 224 s.ErrorAs(err, &store.ErrExecutionsNotFoundForShard{}) 225 226 // delete third execution 227 err = s.executionStore.DeleteExecution(ctx, thirdExecution.ID) 228 s.NoError(err) 229 _, err = s.executionStore.GetExecution(ctx, thirdExecution.ID) 230 s.ErrorAs(err, &store.ErrExecutionNotFound{}) 231 _, err = s.executionStore.GetExecutions(ctx, thirdExecution.Shard.ID()) 232 s.ErrorAs(err, &store.ErrExecutionsNotFoundForShard{}) 233 } 234 235 func (s *Suite) TestDeleteExecution_DoesntExist() { 236 err := s.executionStore.DeleteExecution(context.Background(), uuid.NewString()) 237 s.NoError(err) 238 } 239 240 func (s *Suite) TestGetExecutionHistory_DoesntExist() { 241 _, err := s.executionStore.GetExecutionHistory(context.Background(), uuid.NewString()) 242 s.ErrorAs(err, &store.ErrExecutionHistoryNotFound{}) 243 } 244 245 func newExecution() store.Execution { 246 return *store.NewExecution( 247 uuid.NewString(), 248 model.JobShard{ 249 Job: &model.Job{ 250 Metadata: model.Metadata{ 251 ID: uuid.NewString(), 252 }, 253 }, 254 Index: 1, 255 }, 256 "nodeID-1", 257 model.ResourceUsageData{ 258 CPU: 1, 259 Memory: 2, 260 }) 261 } 262 263 func (s *Suite) verifyHistory(history store.ExecutionHistory, newExecution store.Execution, previousState store.ExecutionState, comment string) { 264 s.Equal(previousState, history.PreviousState) 265 s.Equal(newExecution.ID, history.ExecutionID) 266 s.Equal(newExecution.State, history.NewState) 267 s.Equal(newExecution.Version, history.NewVersion) 268 s.Equal(newExecution.UpdateTime, history.Time) 269 s.Equal(comment, history.Comment) 270 }