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  }