go.temporal.io/server@v1.23.0/common/persistence/operation_mode_validator_test.go (about)

     1  // The MIT License
     2  //
     3  // Copyright (c) 2020 Temporal Technologies Inc.  All rights reserved.
     4  //
     5  // Copyright (c) 2020 Uber Technologies, Inc.
     6  //
     7  // Permission is hereby granted, free of charge, to any person obtaining a copy
     8  // of this software and associated documentation files (the "Software"), to deal
     9  // in the Software without restriction, including without limitation the rights
    10  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    11  // copies of the Software, and to permit persons to whom the Software is
    12  // furnished to do so, subject to the following conditions:
    13  //
    14  // The above copyright notice and this permission notice shall be included in
    15  // all copies or substantial portions of the Software.
    16  //
    17  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    18  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    19  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    20  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    21  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    22  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    23  // THE SOFTWARE.
    24  
    25  package persistence
    26  
    27  import (
    28  	"fmt"
    29  	"testing"
    30  
    31  	"github.com/stretchr/testify/suite"
    32  
    33  	enumsspb "go.temporal.io/server/api/enums/v1"
    34  	persistencespb "go.temporal.io/server/api/persistence/v1"
    35  )
    36  
    37  type (
    38  	validateOperationWorkflowModeStateSuite struct {
    39  		suite.Suite
    40  	}
    41  )
    42  
    43  func TestValidateOperationWorkflowModeStateSuite(t *testing.T) {
    44  	s := new(validateOperationWorkflowModeStateSuite)
    45  	suite.Run(t, s)
    46  }
    47  
    48  func (s *validateOperationWorkflowModeStateSuite) SetupSuite() {
    49  }
    50  
    51  func (s *validateOperationWorkflowModeStateSuite) TearDownSuite() {
    52  
    53  }
    54  
    55  func (s *validateOperationWorkflowModeStateSuite) SetupTest() {
    56  
    57  }
    58  
    59  func (s *validateOperationWorkflowModeStateSuite) TearDownTest() {
    60  
    61  }
    62  
    63  func (s *validateOperationWorkflowModeStateSuite) TestCreateMode_UpdateCurrent() {
    64  
    65  	stateToError := map[enumsspb.WorkflowExecutionState]bool{
    66  		enumsspb.WORKFLOW_EXECUTION_STATE_CREATED:   false,
    67  		enumsspb.WORKFLOW_EXECUTION_STATE_RUNNING:   false,
    68  		enumsspb.WORKFLOW_EXECUTION_STATE_COMPLETED: false,
    69  		enumsspb.WORKFLOW_EXECUTION_STATE_ZOMBIE:    true,
    70  	}
    71  
    72  	creatModes := []CreateWorkflowMode{
    73  		CreateWorkflowModeBrandNew,
    74  		CreateWorkflowModeUpdateCurrent,
    75  	}
    76  
    77  	for state, expectError := range stateToError {
    78  		testSnapshot := s.newTestWorkflowSnapshot(state)
    79  		for _, createMode := range creatModes {
    80  			err := ValidateCreateWorkflowModeState(createMode, testSnapshot)
    81  			if !expectError {
    82  				s.NoError(err, err)
    83  			} else {
    84  				s.Error(err, err)
    85  			}
    86  		}
    87  	}
    88  }
    89  
    90  func (s *validateOperationWorkflowModeStateSuite) TestCreateMode_BypassCurrent() {
    91  
    92  	stateToError := map[enumsspb.WorkflowExecutionState]bool{
    93  		enumsspb.WORKFLOW_EXECUTION_STATE_CREATED:   true,
    94  		enumsspb.WORKFLOW_EXECUTION_STATE_RUNNING:   true,
    95  		enumsspb.WORKFLOW_EXECUTION_STATE_COMPLETED: false,
    96  		enumsspb.WORKFLOW_EXECUTION_STATE_ZOMBIE:    false,
    97  	}
    98  
    99  	for state, expectError := range stateToError {
   100  		testSnapshot := s.newTestWorkflowSnapshot(state)
   101  		err := ValidateCreateWorkflowModeState(CreateWorkflowModeBypassCurrent, testSnapshot)
   102  		if !expectError {
   103  			s.NoError(err, err)
   104  		} else {
   105  			s.Error(err, err)
   106  		}
   107  	}
   108  }
   109  
   110  func (s *validateOperationWorkflowModeStateSuite) TestUpdateMode_UpdateCurrent() {
   111  
   112  	// only current workflow
   113  	stateToError := map[enumsspb.WorkflowExecutionState]bool{
   114  		enumsspb.WORKFLOW_EXECUTION_STATE_CREATED:   false,
   115  		enumsspb.WORKFLOW_EXECUTION_STATE_RUNNING:   false,
   116  		enumsspb.WORKFLOW_EXECUTION_STATE_COMPLETED: false,
   117  		enumsspb.WORKFLOW_EXECUTION_STATE_ZOMBIE:    true,
   118  	}
   119  	for state, expectError := range stateToError {
   120  		testCurrentMutation := s.newTestWorkflowMutation(state)
   121  		err := ValidateUpdateWorkflowModeState(
   122  			UpdateWorkflowModeUpdateCurrent,
   123  			testCurrentMutation,
   124  			nil,
   125  		)
   126  		if !expectError {
   127  			s.NoError(err, err)
   128  		} else {
   129  			s.Error(err, err)
   130  		}
   131  	}
   132  
   133  	// current workflow & new workflow
   134  	currentStateToError := map[enumsspb.WorkflowExecutionState]bool{
   135  		enumsspb.WORKFLOW_EXECUTION_STATE_CREATED:   true,
   136  		enumsspb.WORKFLOW_EXECUTION_STATE_RUNNING:   true,
   137  		enumsspb.WORKFLOW_EXECUTION_STATE_COMPLETED: false,
   138  		enumsspb.WORKFLOW_EXECUTION_STATE_ZOMBIE:    false,
   139  	}
   140  	newStateToError := map[enumsspb.WorkflowExecutionState]bool{
   141  		enumsspb.WORKFLOW_EXECUTION_STATE_CREATED:   false,
   142  		enumsspb.WORKFLOW_EXECUTION_STATE_RUNNING:   false,
   143  		enumsspb.WORKFLOW_EXECUTION_STATE_COMPLETED: false,
   144  		enumsspb.WORKFLOW_EXECUTION_STATE_ZOMBIE:    true,
   145  	}
   146  	for currentState, currentExpectError := range currentStateToError {
   147  		for newState, newExpectError := range newStateToError {
   148  			testCurrentMutation := s.newTestWorkflowMutation(currentState)
   149  			testNewSnapshot := s.newTestWorkflowSnapshot(newState)
   150  			err := ValidateUpdateWorkflowModeState(
   151  				UpdateWorkflowModeUpdateCurrent,
   152  				testCurrentMutation,
   153  				&testNewSnapshot,
   154  			)
   155  			if currentExpectError || newExpectError {
   156  				s.Error(err, err)
   157  			} else {
   158  				s.NoError(err, err)
   159  			}
   160  		}
   161  	}
   162  }
   163  
   164  func (s *validateOperationWorkflowModeStateSuite) TestUpdateMode_BypassCurrent() {
   165  
   166  	// only current workflow
   167  	stateToError := map[enumsspb.WorkflowExecutionState]bool{
   168  		enumsspb.WORKFLOW_EXECUTION_STATE_CREATED:   true,
   169  		enumsspb.WORKFLOW_EXECUTION_STATE_RUNNING:   true,
   170  		enumsspb.WORKFLOW_EXECUTION_STATE_COMPLETED: false,
   171  		enumsspb.WORKFLOW_EXECUTION_STATE_ZOMBIE:    false,
   172  	}
   173  	for state, expectError := range stateToError {
   174  		testMutation := s.newTestWorkflowMutation(state)
   175  		err := ValidateUpdateWorkflowModeState(
   176  			UpdateWorkflowModeBypassCurrent,
   177  			testMutation,
   178  			nil,
   179  		)
   180  		if !expectError {
   181  			s.NoError(err, err)
   182  		} else {
   183  			s.Error(err, err)
   184  		}
   185  	}
   186  
   187  	// current workflow & new workflow
   188  	currentStateToError := map[enumsspb.WorkflowExecutionState]bool{
   189  		enumsspb.WORKFLOW_EXECUTION_STATE_CREATED:   true,
   190  		enumsspb.WORKFLOW_EXECUTION_STATE_RUNNING:   true,
   191  		enumsspb.WORKFLOW_EXECUTION_STATE_COMPLETED: false,
   192  		enumsspb.WORKFLOW_EXECUTION_STATE_ZOMBIE:    false,
   193  	}
   194  	newStateToError := map[enumsspb.WorkflowExecutionState]bool{
   195  		enumsspb.WORKFLOW_EXECUTION_STATE_CREATED:   true,
   196  		enumsspb.WORKFLOW_EXECUTION_STATE_RUNNING:   true,
   197  		enumsspb.WORKFLOW_EXECUTION_STATE_COMPLETED: false,
   198  		enumsspb.WORKFLOW_EXECUTION_STATE_ZOMBIE:    false,
   199  	}
   200  	for currentState, currentExpectError := range currentStateToError {
   201  		for newState, newExpectError := range newStateToError {
   202  			testCurrentMutation := s.newTestWorkflowMutation(currentState)
   203  			testNewSnapshot := s.newTestWorkflowSnapshot(newState)
   204  			err := ValidateUpdateWorkflowModeState(
   205  				UpdateWorkflowModeBypassCurrent,
   206  				testCurrentMutation,
   207  				&testNewSnapshot,
   208  			)
   209  			if currentExpectError || newExpectError {
   210  				s.Error(err, err)
   211  			} else {
   212  				s.NoError(err, err)
   213  			}
   214  		}
   215  	}
   216  }
   217  
   218  func (s *validateOperationWorkflowModeStateSuite) TestConflictResolveMode_UpdateCurrent() {
   219  
   220  	// only reset workflow
   221  	stateToError := map[enumsspb.WorkflowExecutionState]bool{
   222  		enumsspb.WORKFLOW_EXECUTION_STATE_CREATED:   false,
   223  		enumsspb.WORKFLOW_EXECUTION_STATE_RUNNING:   false,
   224  		enumsspb.WORKFLOW_EXECUTION_STATE_COMPLETED: false,
   225  		enumsspb.WORKFLOW_EXECUTION_STATE_ZOMBIE:    true,
   226  	}
   227  	for state, expectError := range stateToError {
   228  		testSnapshot := s.newTestWorkflowSnapshot(state)
   229  		err := ValidateConflictResolveWorkflowModeState(
   230  			ConflictResolveWorkflowModeUpdateCurrent,
   231  			testSnapshot,
   232  			nil,
   233  			nil,
   234  		)
   235  		if !expectError {
   236  			s.NoError(err, err)
   237  		} else {
   238  			s.Error(err, err)
   239  		}
   240  	}
   241  
   242  	// reset workflow & new workflow
   243  	resetStateToError := map[enumsspb.WorkflowExecutionState]bool{
   244  		enumsspb.WORKFLOW_EXECUTION_STATE_CREATED:   true,
   245  		enumsspb.WORKFLOW_EXECUTION_STATE_RUNNING:   true,
   246  		enumsspb.WORKFLOW_EXECUTION_STATE_COMPLETED: false,
   247  		enumsspb.WORKFLOW_EXECUTION_STATE_ZOMBIE:    true,
   248  	}
   249  	newStateToError := map[enumsspb.WorkflowExecutionState]bool{
   250  		enumsspb.WORKFLOW_EXECUTION_STATE_CREATED:   false,
   251  		enumsspb.WORKFLOW_EXECUTION_STATE_RUNNING:   false,
   252  		enumsspb.WORKFLOW_EXECUTION_STATE_COMPLETED: false,
   253  		enumsspb.WORKFLOW_EXECUTION_STATE_ZOMBIE:    true,
   254  	}
   255  	for resetState, resetExpectError := range resetStateToError {
   256  		for newState, newExpectError := range newStateToError {
   257  			testResetSnapshot := s.newTestWorkflowSnapshot(resetState)
   258  			testNewSnapshot := s.newTestWorkflowSnapshot(newState)
   259  			err := ValidateConflictResolveWorkflowModeState(
   260  				ConflictResolveWorkflowModeUpdateCurrent,
   261  				testResetSnapshot,
   262  				&testNewSnapshot,
   263  				nil,
   264  			)
   265  			if resetExpectError || newExpectError {
   266  				s.Error(err, err)
   267  			} else {
   268  				s.NoError(err, err)
   269  			}
   270  		}
   271  	}
   272  
   273  	// reset workflow & current workflow
   274  	resetStateToError = map[enumsspb.WorkflowExecutionState]bool{
   275  		enumsspb.WORKFLOW_EXECUTION_STATE_CREATED:   false,
   276  		enumsspb.WORKFLOW_EXECUTION_STATE_RUNNING:   false,
   277  		enumsspb.WORKFLOW_EXECUTION_STATE_COMPLETED: false,
   278  		enumsspb.WORKFLOW_EXECUTION_STATE_ZOMBIE:    true,
   279  	}
   280  	currentStateToError := map[enumsspb.WorkflowExecutionState]bool{
   281  		enumsspb.WORKFLOW_EXECUTION_STATE_CREATED:   true,
   282  		enumsspb.WORKFLOW_EXECUTION_STATE_RUNNING:   true,
   283  		enumsspb.WORKFLOW_EXECUTION_STATE_COMPLETED: false,
   284  		enumsspb.WORKFLOW_EXECUTION_STATE_ZOMBIE:    false,
   285  	}
   286  	for resetState, resetExpectError := range resetStateToError {
   287  		for currentState, currentExpectError := range currentStateToError {
   288  			testResetSnapshot := s.newTestWorkflowSnapshot(resetState)
   289  			testCurrentSnapshot := s.newTestWorkflowMutation(currentState)
   290  			err := ValidateConflictResolveWorkflowModeState(
   291  				ConflictResolveWorkflowModeUpdateCurrent,
   292  				testResetSnapshot,
   293  				nil,
   294  				&testCurrentSnapshot,
   295  			)
   296  			if resetExpectError || currentExpectError {
   297  				s.Error(err, err)
   298  			} else {
   299  				s.NoError(err, err)
   300  			}
   301  		}
   302  	}
   303  
   304  	// reset workflow & new workflow & current workflow
   305  	resetStateToError = map[enumsspb.WorkflowExecutionState]bool{
   306  		enumsspb.WORKFLOW_EXECUTION_STATE_CREATED:   true,
   307  		enumsspb.WORKFLOW_EXECUTION_STATE_RUNNING:   true,
   308  		enumsspb.WORKFLOW_EXECUTION_STATE_COMPLETED: false,
   309  		enumsspb.WORKFLOW_EXECUTION_STATE_ZOMBIE:    true,
   310  	}
   311  	newStateToError = map[enumsspb.WorkflowExecutionState]bool{
   312  		enumsspb.WORKFLOW_EXECUTION_STATE_CREATED:   false,
   313  		enumsspb.WORKFLOW_EXECUTION_STATE_RUNNING:   false,
   314  		enumsspb.WORKFLOW_EXECUTION_STATE_COMPLETED: false,
   315  		enumsspb.WORKFLOW_EXECUTION_STATE_ZOMBIE:    true,
   316  	}
   317  	currentStateToError = map[enumsspb.WorkflowExecutionState]bool{
   318  		enumsspb.WORKFLOW_EXECUTION_STATE_CREATED:   true,
   319  		enumsspb.WORKFLOW_EXECUTION_STATE_RUNNING:   true,
   320  		enumsspb.WORKFLOW_EXECUTION_STATE_COMPLETED: false,
   321  		enumsspb.WORKFLOW_EXECUTION_STATE_ZOMBIE:    false,
   322  	}
   323  	for resetState, resetExpectError := range resetStateToError {
   324  		for newState, newExpectError := range newStateToError {
   325  			for currentState, currentExpectError := range currentStateToError {
   326  				testResetSnapshot := s.newTestWorkflowSnapshot(resetState)
   327  				testNewSnapshot := s.newTestWorkflowSnapshot(newState)
   328  				testCurrentSnapshot := s.newTestWorkflowMutation(currentState)
   329  				err := ValidateConflictResolveWorkflowModeState(
   330  					ConflictResolveWorkflowModeUpdateCurrent,
   331  					testResetSnapshot,
   332  					&testNewSnapshot,
   333  					&testCurrentSnapshot,
   334  				)
   335  				if resetExpectError || newExpectError || currentExpectError {
   336  					s.Error(err, err)
   337  				} else {
   338  					s.NoError(err, err)
   339  				}
   340  			}
   341  		}
   342  	}
   343  }
   344  
   345  func (s *validateOperationWorkflowModeStateSuite) TestConflictResolveMode_BypassCurrent() {
   346  
   347  	// only reset workflow
   348  	stateToError := map[enumsspb.WorkflowExecutionState]bool{
   349  		enumsspb.WORKFLOW_EXECUTION_STATE_CREATED:   true,
   350  		enumsspb.WORKFLOW_EXECUTION_STATE_RUNNING:   true,
   351  		enumsspb.WORKFLOW_EXECUTION_STATE_COMPLETED: false,
   352  		enumsspb.WORKFLOW_EXECUTION_STATE_ZOMBIE:    false,
   353  	}
   354  	for state, expectError := range stateToError {
   355  		testSnapshot := s.newTestWorkflowSnapshot(state)
   356  		err := ValidateConflictResolveWorkflowModeState(
   357  			ConflictResolveWorkflowModeBypassCurrent,
   358  			testSnapshot,
   359  			nil,
   360  			nil,
   361  		)
   362  		if !expectError {
   363  			s.NoError(err, err)
   364  		} else {
   365  			s.Error(err, err)
   366  		}
   367  	}
   368  
   369  	// reset workflow & new workflow
   370  	resetStateToError := map[enumsspb.WorkflowExecutionState]bool{
   371  		enumsspb.WORKFLOW_EXECUTION_STATE_CREATED:   true,
   372  		enumsspb.WORKFLOW_EXECUTION_STATE_RUNNING:   true,
   373  		enumsspb.WORKFLOW_EXECUTION_STATE_COMPLETED: false,
   374  		enumsspb.WORKFLOW_EXECUTION_STATE_ZOMBIE:    true,
   375  	}
   376  	newStateToError := map[enumsspb.WorkflowExecutionState]bool{
   377  		enumsspb.WORKFLOW_EXECUTION_STATE_CREATED:   true,
   378  		enumsspb.WORKFLOW_EXECUTION_STATE_RUNNING:   true,
   379  		enumsspb.WORKFLOW_EXECUTION_STATE_COMPLETED: true,
   380  		enumsspb.WORKFLOW_EXECUTION_STATE_ZOMBIE:    false,
   381  	}
   382  	for resetState, resetExpectError := range resetStateToError {
   383  		for newState, newExpectError := range newStateToError {
   384  			testResetSnapshot := s.newTestWorkflowSnapshot(resetState)
   385  			testNewSnapshot := s.newTestWorkflowSnapshot(newState)
   386  			err := ValidateConflictResolveWorkflowModeState(
   387  				ConflictResolveWorkflowModeBypassCurrent,
   388  				testResetSnapshot,
   389  				&testNewSnapshot,
   390  				nil,
   391  			)
   392  			if resetExpectError || newExpectError {
   393  				if err == nil {
   394  					fmt.Print("##")
   395  				}
   396  				s.Error(err, err)
   397  			} else {
   398  				s.NoError(err, err)
   399  			}
   400  		}
   401  	}
   402  }
   403  
   404  func (s *validateOperationWorkflowModeStateSuite) newTestWorkflowSnapshot(
   405  	state enumsspb.WorkflowExecutionState,
   406  ) WorkflowSnapshot {
   407  	return WorkflowSnapshot{
   408  		ExecutionInfo:  &persistencespb.WorkflowExecutionInfo{},
   409  		ExecutionState: &persistencespb.WorkflowExecutionState{State: state},
   410  	}
   411  }
   412  
   413  func (s *validateOperationWorkflowModeStateSuite) newTestWorkflowMutation(
   414  	state enumsspb.WorkflowExecutionState,
   415  ) WorkflowMutation {
   416  	return WorkflowMutation{
   417  		ExecutionInfo:  &persistencespb.WorkflowExecutionInfo{},
   418  		ExecutionState: &persistencespb.WorkflowExecutionState{State: state},
   419  	}
   420  }