go.uber.org/cadence@v1.2.9/internal/workflow_replayer_test.go (about)

     1  // Copyright (c) 2017-2021 Uber Technologies Inc.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  package internal
    22  
    23  import (
    24  	"context"
    25  	"errors"
    26  	"fmt"
    27  	"testing"
    28  	"time"
    29  
    30  	"github.com/stretchr/testify/require"
    31  	"github.com/stretchr/testify/suite"
    32  	"go.uber.org/zap"
    33  
    34  	"go.uber.org/cadence/.gen/go/shared"
    35  	"go.uber.org/cadence/internal/common"
    36  )
    37  
    38  type workflowReplayerSuite struct {
    39  	*require.Assertions
    40  	suite.Suite
    41  
    42  	replayer *WorkflowReplayer
    43  	logger   *zap.Logger
    44  }
    45  
    46  var (
    47  	testTaskList = "taskList"
    48  )
    49  
    50  func TestWorkflowReplayerSuite(t *testing.T) {
    51  	s := new(workflowReplayerSuite)
    52  	suite.Run(t, s)
    53  }
    54  
    55  func (s *workflowReplayerSuite) SetupTest() {
    56  	s.Assertions = require.New(s.T())
    57  
    58  	s.logger = getTestLogger(s.T())
    59  	s.replayer = NewWorkflowReplayerWithOptions(ReplayOptions{
    60  		ContextPropagators: []ContextPropagator{
    61  			NewStringMapPropagator([]string{testHeader}),
    62  		},
    63  	})
    64  	s.replayer.RegisterWorkflow(testReplayWorkflow)
    65  	s.replayer.RegisterWorkflow(testReplayWorkflowLocalActivity)
    66  	s.replayer.RegisterWorkflow(testReplayWorkflowContextPropagator)
    67  	s.replayer.RegisterWorkflow(testReplayWorkflowFromFile)
    68  	s.replayer.RegisterWorkflow(testReplayWorkflowFromFileParent)
    69  	s.replayer.RegisterWorkflow(localActivitiesCallingOptionsWorkflow{s.T()}.Execute)
    70  }
    71  
    72  func (s *workflowReplayerSuite) TestReplayWorkflowHistory_Full() {
    73  	err := s.replayer.ReplayWorkflowHistory(s.logger, getTestReplayWorkflowFullHistory(s.T()))
    74  	s.NoError(err)
    75  }
    76  
    77  func (s *workflowReplayerSuite) TestReplayWorkflowHistory_Full_ResultMisMatch() {
    78  	fullHistory := getTestReplayWorkflowFullHistory(s.T())
    79  	completedEvent := fullHistory.Events[len(fullHistory.Events)-1]
    80  	s.Equal(shared.EventTypeWorkflowExecutionCompleted, completedEvent.GetEventType())
    81  	completedEvent.WorkflowExecutionCompletedEventAttributes.Result = []byte("some random result")
    82  
    83  	err := s.replayer.ReplayWorkflowHistory(s.logger, fullHistory)
    84  	s.Error(err)
    85  }
    86  
    87  func (s *workflowReplayerSuite) TestReplayWorkflowHistory_Full_ContinueAsNew() {
    88  	fullHistory := getTestReplayWorkflowFullHistory(s.T())
    89  	completedEventIdx := len(fullHistory.Events) - 1
    90  	s.Equal(shared.EventTypeWorkflowExecutionCompleted, fullHistory.Events[completedEventIdx].GetEventType())
    91  	fullHistory.Events[completedEventIdx] = createTestEventWorkflowExecutionContinuedAsNew(int64(completedEventIdx+1), nil)
    92  
    93  	err := s.replayer.ReplayWorkflowHistory(s.logger, fullHistory)
    94  	s.NoError(err)
    95  }
    96  
    97  func (s *workflowReplayerSuite) TestReplayWorkflowHistory_Partial_WithDecisionEvents() {
    98  	err := s.replayer.ReplayWorkflowHistory(s.logger, getTestReplayWorkflowPartialHistoryWithDecisionEvents(s.T()))
    99  	s.NoError(err)
   100  }
   101  
   102  func (s *workflowReplayerSuite) TestReplayWorkflowHistory_Partial_NoDecisionEvents() {
   103  	err := s.replayer.ReplayWorkflowHistory(s.logger, getTestReplayWorkflowPartialHistoryNoDecisionEvents(s.T()))
   104  	s.NoError(err)
   105  }
   106  
   107  func (s *workflowReplayerSuite) TestReplayWorkflowHistory_LocalActivity() {
   108  	err := s.replayer.ReplayWorkflowHistory(s.logger, getTestReplayWorkflowLocalActivityHistory(s.T()))
   109  	s.NoError(err)
   110  }
   111  
   112  func (s *workflowReplayerSuite) TestReplayWorkflowHistory_LocalActivity_Result_Mismatch() {
   113  	err := s.replayer.ReplayWorkflowHistory(s.logger, getTestReplayWorkflowLocalActivityResultMismatchHistory(s.T()))
   114  	s.Error(err)
   115  }
   116  
   117  func (s *workflowReplayerSuite) TestReplayWorkflowHistory_LocalActivity_Activity_Type_Mismatch() {
   118  	err := s.replayer.ReplayWorkflowHistory(s.logger, getTestReplayWorkflowLocalActivityTypeMismatchHistory(s.T()))
   119  	s.Error(err)
   120  }
   121  
   122  func (s *workflowReplayerSuite) TestReplayWorkflowHistory_ContextPropagator() {
   123  	err := s.replayer.ReplayWorkflowHistory(s.logger, getTestReplayWorkflowContextPropagatorHistory(s.T()))
   124  	s.NoError(err)
   125  }
   126  
   127  func (s *workflowReplayerSuite) TestReplayWorkflowHistoryFromFileLocalActivities() {
   128  	err := s.replayer.ReplayWorkflowHistoryFromJSONFile(s.logger, "testdata/localActivities.json")
   129  	s.NoError(err)
   130  }
   131  
   132  func (s *workflowReplayerSuite) TestReplayWorkflowHistoryFromFileParent() {
   133  	err := s.replayer.ReplayWorkflowHistoryFromJSONFile(s.logger, "testdata/parentWF.json")
   134  	s.NoError(err)
   135  }
   136  
   137  func (s *workflowReplayerSuite) TestReplayWorkflowHistoryFromFile() {
   138  	err := s.replayer.ReplayWorkflowHistoryFromJSONFile(s.logger, "testdata/sampleHistory.json")
   139  	s.NoError(err)
   140  }
   141  
   142  func testReplayWorkflow(ctx Context) error {
   143  	ao := ActivityOptions{
   144  		ScheduleToStartTimeout: time.Second,
   145  		StartToCloseTimeout:    time.Second,
   146  	}
   147  	ctx = WithActivityOptions(ctx, ao)
   148  	err := ExecuteActivity(ctx, "testActivity").Get(ctx, nil)
   149  	if err != nil {
   150  		GetLogger(ctx).Error("activity failed with error.", zap.Error(err))
   151  		panic("Failed workflow")
   152  	}
   153  	return err
   154  }
   155  
   156  func testReplayWorkflowLocalActivity(ctx Context) error {
   157  	ao := LocalActivityOptions{
   158  		ScheduleToCloseTimeout: time.Second,
   159  	}
   160  	ctx = WithLocalActivityOptions(ctx, ao)
   161  	err := ExecuteLocalActivity(ctx, testActivity).Get(ctx, nil)
   162  	if err != nil {
   163  		GetLogger(ctx).Error("activity failed with error.", zap.Error(err))
   164  		panic("Failed workflow")
   165  	}
   166  	return err
   167  }
   168  
   169  func testReplayWorkflowContextPropagator(ctx Context) error {
   170  	value := ctx.Value(contextKey(testHeader))
   171  	if val, ok := value.(string); ok && val != "" {
   172  		testReplayWorkflow(ctx)
   173  		return nil
   174  	}
   175  
   176  	return errors.New("context propagator is not setup correctly for workflow replayer")
   177  }
   178  
   179  func testReplayWorkflowFromFile(ctx Context) error {
   180  	ao := ActivityOptions{
   181  		ScheduleToStartTimeout: time.Minute,
   182  		StartToCloseTimeout:    time.Minute,
   183  		HeartbeatTimeout:       20 * time.Second,
   184  		WaitForCancellation:    true,
   185  	}
   186  	ctx = WithActivityOptions(ctx, ao)
   187  	err := ExecuteActivity(ctx, "testActivityMultipleArgs", 2, "test", true).Get(ctx, nil)
   188  	if err != nil {
   189  		GetLogger(ctx).Error("activity failed with error.", zap.Error(err))
   190  		panic("Failed workflow")
   191  	}
   192  	return err
   193  }
   194  
   195  func testReplayWorkflowFromFileParent(ctx Context) error {
   196  	execution := GetWorkflowInfo(ctx).WorkflowExecution
   197  	childID := fmt.Sprintf("child_workflow:%v", execution.RunID)
   198  	cwo := ChildWorkflowOptions{
   199  		WorkflowID:                   childID,
   200  		ExecutionStartToCloseTimeout: time.Minute,
   201  	}
   202  	ctx = WithChildWorkflowOptions(ctx, cwo)
   203  	var result string
   204  	cwf := ExecuteChildWorkflow(ctx, testReplayWorkflowFromFile)
   205  	f1 := cwf.SignalChildWorkflow(ctx, "test-signal", "test-data")
   206  	err := f1.Get(ctx, nil)
   207  	if err != nil {
   208  		return err
   209  	}
   210  	return cwf.Get(ctx, &result)
   211  }
   212  
   213  func testActivity(ctx context.Context) error {
   214  	return nil
   215  }
   216  
   217  type localActivitiesCallingOptionsWorkflow struct {
   218  	t *testing.T
   219  }
   220  
   221  func (w localActivitiesCallingOptionsWorkflow) Execute(ctx Context, input []byte) (result []byte, err error) {
   222  	ao := LocalActivityOptions{
   223  		ScheduleToCloseTimeout: time.Second,
   224  	}
   225  	ctx = WithLocalActivityOptions(ctx, ao)
   226  
   227  	// By functions.
   228  	err = ExecuteLocalActivity(ctx, testActivityByteArgs, input).Get(ctx, nil)
   229  	require.NoError(w.t, err, err)
   230  
   231  	err = ExecuteLocalActivity(ctx, testActivityMultipleArgs, 2, []string{"test"}, true).Get(ctx, nil)
   232  	require.NoError(w.t, err, err)
   233  
   234  	err = ExecuteLocalActivity(ctx, testActivityNoResult, 2, "test").Get(ctx, nil)
   235  	require.NoError(w.t, err, err)
   236  
   237  	err = ExecuteLocalActivity(ctx, testActivityNoContextArg, 2, "test").Get(ctx, nil)
   238  	require.NoError(w.t, err, err)
   239  
   240  	f := ExecuteLocalActivity(ctx, testActivityReturnByteArray)
   241  	var r []byte
   242  	err = f.Get(ctx, &r)
   243  	require.NoError(w.t, err, err)
   244  	require.Equal(w.t, []byte("testActivity"), r)
   245  
   246  	f = ExecuteLocalActivity(ctx, testActivityReturnInt)
   247  	var rInt int
   248  	err = f.Get(ctx, &rInt)
   249  	require.NoError(w.t, err, err)
   250  	require.Equal(w.t, 5, rInt)
   251  
   252  	f = ExecuteLocalActivity(ctx, testActivityReturnString)
   253  	var rString string
   254  	err = f.Get(ctx, &rString)
   255  
   256  	require.NoError(w.t, err, err)
   257  	require.Equal(w.t, "testActivity", rString)
   258  
   259  	f = ExecuteLocalActivity(ctx, testActivityReturnEmptyString)
   260  	var r2String string
   261  	err = f.Get(ctx, &r2String)
   262  	require.NoError(w.t, err, err)
   263  	require.Equal(w.t, "", r2String)
   264  
   265  	f = ExecuteLocalActivity(ctx, testActivityReturnEmptyStruct)
   266  	var r2Struct testActivityResult
   267  	err = f.Get(ctx, &r2Struct)
   268  	require.NoError(w.t, err, err)
   269  	require.Equal(w.t, testActivityResult{}, r2Struct)
   270  
   271  	f = ExecuteLocalActivity(ctx, testActivityReturnNilStructPtr)
   272  	var rStructPtr *testActivityResult
   273  	err = f.Get(ctx, &rStructPtr)
   274  	require.NoError(w.t, err, err)
   275  	require.True(w.t, rStructPtr == nil)
   276  
   277  	f = ExecuteLocalActivity(ctx, testActivityReturnStructPtr)
   278  	err = f.Get(ctx, &rStructPtr)
   279  	require.NoError(w.t, err, err)
   280  	require.Equal(w.t, *rStructPtr, testActivityResult{Index: 10})
   281  
   282  	f = ExecuteLocalActivity(ctx, testActivityReturnNilStructPtrPtr)
   283  	var rStruct2Ptr **testActivityResult
   284  	err = f.Get(ctx, &rStruct2Ptr)
   285  	require.NoError(w.t, err, err)
   286  	require.True(w.t, rStruct2Ptr == nil)
   287  
   288  	f = ExecuteLocalActivity(ctx, testActivityReturnStructPtrPtr)
   289  	err = f.Get(ctx, &rStruct2Ptr)
   290  	require.NoError(w.t, err, err)
   291  	require.True(w.t, **rStruct2Ptr == testActivityResult{Index: 10})
   292  
   293  	return []byte("Done"), nil
   294  }
   295  
   296  func getTestReplayWorkflowFullHistory(t *testing.T) *shared.History {
   297  	return &shared.History{
   298  		Events: []*shared.HistoryEvent{
   299  			createTestEventWorkflowExecutionStarted(1, &shared.WorkflowExecutionStartedEventAttributes{
   300  				WorkflowType: &shared.WorkflowType{Name: common.StringPtr("go.uber.org/cadence/internal.testReplayWorkflow")},
   301  				TaskList:     &shared.TaskList{Name: common.StringPtr(testTaskList)},
   302  				Input:        testEncodeFunctionArgs(t, getDefaultDataConverter()),
   303  			}),
   304  			createTestEventDecisionTaskScheduled(2, &shared.DecisionTaskScheduledEventAttributes{}),
   305  			createTestEventDecisionTaskStarted(3),
   306  			createTestEventDecisionTaskCompleted(4, &shared.DecisionTaskCompletedEventAttributes{}),
   307  			createTestEventActivityTaskScheduled(5, &shared.ActivityTaskScheduledEventAttributes{
   308  				ActivityId:   common.StringPtr("0"),
   309  				ActivityType: &shared.ActivityType{Name: common.StringPtr("testActivity")},
   310  				TaskList:     &shared.TaskList{Name: &testTaskList},
   311  			}),
   312  			createTestEventActivityTaskStarted(6, &shared.ActivityTaskStartedEventAttributes{
   313  				ScheduledEventId: common.Int64Ptr(5),
   314  			}),
   315  			createTestEventActivityTaskCompleted(7, &shared.ActivityTaskCompletedEventAttributes{
   316  				ScheduledEventId: common.Int64Ptr(5),
   317  				StartedEventId:   common.Int64Ptr(6),
   318  			}),
   319  			createTestEventDecisionTaskScheduled(8, &shared.DecisionTaskScheduledEventAttributes{}),
   320  			createTestEventDecisionTaskStarted(9),
   321  			createTestEventDecisionTaskCompleted(10, &shared.DecisionTaskCompletedEventAttributes{
   322  				ScheduledEventId: common.Int64Ptr(8),
   323  				StartedEventId:   common.Int64Ptr(9),
   324  			}),
   325  			createTestEventWorkflowExecutionCompleted(11, &shared.WorkflowExecutionCompletedEventAttributes{
   326  				DecisionTaskCompletedEventId: common.Int64Ptr(10),
   327  			}),
   328  		},
   329  	}
   330  }
   331  
   332  func getTestReplayWorkflowPartialHistoryWithDecisionEvents(t *testing.T) *shared.History {
   333  	return &shared.History{
   334  		Events: []*shared.HistoryEvent{
   335  			createTestEventWorkflowExecutionStarted(1, &shared.WorkflowExecutionStartedEventAttributes{
   336  				WorkflowType: &shared.WorkflowType{Name: common.StringPtr("go.uber.org/cadence/internal.testReplayWorkflow")},
   337  				TaskList:     &shared.TaskList{Name: common.StringPtr(testTaskList)},
   338  				Input:        testEncodeFunctionArgs(t, getDefaultDataConverter()),
   339  			}),
   340  			createTestEventDecisionTaskScheduled(2, &shared.DecisionTaskScheduledEventAttributes{}),
   341  			createTestEventDecisionTaskStarted(3),
   342  			createTestEventDecisionTaskCompleted(4, &shared.DecisionTaskCompletedEventAttributes{}),
   343  			createTestEventActivityTaskScheduled(5, &shared.ActivityTaskScheduledEventAttributes{
   344  				ActivityId:   common.StringPtr("0"),
   345  				ActivityType: &shared.ActivityType{Name: common.StringPtr("testActivity-fm")},
   346  				TaskList:     &shared.TaskList{Name: &testTaskList},
   347  			}),
   348  		},
   349  	}
   350  }
   351  
   352  func getTestReplayWorkflowPartialHistoryNoDecisionEvents(t *testing.T) *shared.History {
   353  	return &shared.History{
   354  		Events: []*shared.HistoryEvent{
   355  			createTestEventWorkflowExecutionStarted(1, &shared.WorkflowExecutionStartedEventAttributes{
   356  				WorkflowType: &shared.WorkflowType{Name: common.StringPtr("go.uber.org/cadence/internal.testReplayWorkflow")},
   357  				TaskList:     &shared.TaskList{Name: common.StringPtr(testTaskList)},
   358  				Input:        testEncodeFunctionArgs(t, getDefaultDataConverter()),
   359  			}),
   360  			createTestEventDecisionTaskScheduled(2, &shared.DecisionTaskScheduledEventAttributes{}),
   361  			createTestEventDecisionTaskStarted(3),
   362  			createTestEventDecisionTaskFailed(4, &shared.DecisionTaskFailedEventAttributes{ScheduledEventId: common.Int64Ptr(2)}),
   363  			createTestEventDecisionTaskScheduled(5, &shared.DecisionTaskScheduledEventAttributes{}),
   364  			createTestEventDecisionTaskStarted(6),
   365  		},
   366  	}
   367  }
   368  
   369  func getTestReplayWorkflowMismatchHistory(t *testing.T) *shared.History {
   370  	return &shared.History{
   371  		Events: []*shared.HistoryEvent{
   372  			createTestEventWorkflowExecutionStarted(1, &shared.WorkflowExecutionStartedEventAttributes{
   373  				WorkflowType: &shared.WorkflowType{Name: common.StringPtr("go.uber.org/cadence/internal.testReplayWorkflow")},
   374  				TaskList:     &shared.TaskList{Name: common.StringPtr("taskList")},
   375  				Input:        testEncodeFunctionArgs(t, getDefaultDataConverter()),
   376  			}),
   377  			createTestEventDecisionTaskScheduled(2, &shared.DecisionTaskScheduledEventAttributes{}),
   378  			createTestEventDecisionTaskStarted(3),
   379  			createTestEventDecisionTaskCompleted(4, &shared.DecisionTaskCompletedEventAttributes{}),
   380  			createTestEventActivityTaskScheduled(5, &shared.ActivityTaskScheduledEventAttributes{
   381  				ActivityId:   common.StringPtr("0"),
   382  				ActivityType: &shared.ActivityType{Name: common.StringPtr("unknownActivityType")},
   383  				TaskList:     &shared.TaskList{Name: common.StringPtr("taskList")},
   384  			}),
   385  		},
   386  	}
   387  }
   388  
   389  func getTestReplayWorkflowLocalActivityHistory(t *testing.T) *shared.History {
   390  	return &shared.History{
   391  		Events: []*shared.HistoryEvent{
   392  			createTestEventWorkflowExecutionStarted(1, &shared.WorkflowExecutionStartedEventAttributes{
   393  				WorkflowType: &shared.WorkflowType{Name: common.StringPtr("go.uber.org/cadence/internal.testReplayWorkflowLocalActivity")},
   394  				TaskList:     &shared.TaskList{Name: common.StringPtr(testTaskList)},
   395  				Input:        testEncodeFunctionArgs(t, getDefaultDataConverter()),
   396  			}),
   397  			createTestEventDecisionTaskScheduled(2, &shared.DecisionTaskScheduledEventAttributes{}),
   398  			createTestEventDecisionTaskStarted(3),
   399  			createTestEventDecisionTaskCompleted(4, &shared.DecisionTaskCompletedEventAttributes{}),
   400  
   401  			createTestEventLocalActivity(5, &shared.MarkerRecordedEventAttributes{
   402  				MarkerName:                   common.StringPtr(localActivityMarkerName),
   403  				Details:                      createLocalActivityMarkerDataForTest("0", "go.uber.org/cadence/internal.testActivity"),
   404  				DecisionTaskCompletedEventId: common.Int64Ptr(4),
   405  			}),
   406  
   407  			createTestEventWorkflowExecutionCompleted(6, &shared.WorkflowExecutionCompletedEventAttributes{
   408  				DecisionTaskCompletedEventId: common.Int64Ptr(4),
   409  			}),
   410  		},
   411  	}
   412  }
   413  
   414  func getTestReplayWorkflowLocalActivityResultMismatchHistory(t *testing.T) *shared.History {
   415  	return &shared.History{
   416  		Events: []*shared.HistoryEvent{
   417  			createTestEventWorkflowExecutionStarted(1, &shared.WorkflowExecutionStartedEventAttributes{
   418  				WorkflowType: &shared.WorkflowType{Name: common.StringPtr("go.uber.org/cadence/internal.testReplayWorkflowLocalActivity")},
   419  				TaskList:     &shared.TaskList{Name: common.StringPtr(testTaskList)},
   420  				Input:        testEncodeFunctionArgs(t, getDefaultDataConverter()),
   421  			}),
   422  			createTestEventDecisionTaskScheduled(2, &shared.DecisionTaskScheduledEventAttributes{}),
   423  			createTestEventDecisionTaskStarted(3),
   424  			createTestEventDecisionTaskCompleted(4, &shared.DecisionTaskCompletedEventAttributes{}),
   425  
   426  			createTestEventLocalActivity(5, &shared.MarkerRecordedEventAttributes{
   427  				MarkerName:                   common.StringPtr(localActivityMarkerName),
   428  				Details:                      createLocalActivityMarkerDataForTest("0", ""),
   429  				DecisionTaskCompletedEventId: common.Int64Ptr(4),
   430  			}),
   431  
   432  			createTestEventWorkflowExecutionCompleted(6, &shared.WorkflowExecutionCompletedEventAttributes{
   433  				Result:                       []byte("some-incorrect-result"),
   434  				DecisionTaskCompletedEventId: common.Int64Ptr(4),
   435  			}),
   436  		},
   437  	}
   438  }
   439  
   440  func getTestReplayWorkflowLocalActivityTypeMismatchHistory(t *testing.T) *shared.History {
   441  	return &shared.History{
   442  		Events: []*shared.HistoryEvent{
   443  			createTestEventWorkflowExecutionStarted(1, &shared.WorkflowExecutionStartedEventAttributes{
   444  				WorkflowType: &shared.WorkflowType{Name: common.StringPtr("go.uber.org/cadence/internal.testReplayWorkflowLocalActivity")},
   445  				TaskList:     &shared.TaskList{Name: common.StringPtr(testTaskList)},
   446  				Input:        testEncodeFunctionArgs(t, getDefaultDataConverter()),
   447  			}),
   448  			createTestEventDecisionTaskScheduled(2, &shared.DecisionTaskScheduledEventAttributes{}),
   449  			createTestEventDecisionTaskStarted(3),
   450  			createTestEventDecisionTaskCompleted(4, &shared.DecisionTaskCompletedEventAttributes{}),
   451  
   452  			createTestEventLocalActivity(5, &shared.MarkerRecordedEventAttributes{
   453  				MarkerName:                   common.StringPtr(localActivityMarkerName),
   454  				Details:                      createLocalActivityMarkerDataForTest("0", "different-activity-type"),
   455  				DecisionTaskCompletedEventId: common.Int64Ptr(4),
   456  			}),
   457  
   458  			createTestEventWorkflowExecutionCompleted(6, &shared.WorkflowExecutionCompletedEventAttributes{
   459  				DecisionTaskCompletedEventId: common.Int64Ptr(4),
   460  			}),
   461  		},
   462  	}
   463  }
   464  
   465  func getTestReplayWorkflowContextPropagatorHistory(t *testing.T) *shared.History {
   466  	history := getTestReplayWorkflowFullHistory(t)
   467  	history.Events[0].WorkflowExecutionStartedEventAttributes.WorkflowType.Name = common.StringPtr("go.uber.org/cadence/internal.testReplayWorkflowContextPropagator")
   468  	history.Events[0].WorkflowExecutionStartedEventAttributes.Header = &shared.Header{
   469  		Fields: map[string][]byte{testHeader: []byte("testValue")},
   470  	}
   471  	return history
   472  }
   473  
   474  func createLocalActivityMarkerDataForTest(activityID, activityType string) []byte {
   475  	lamd := localActivityMarkerData{
   476  		ActivityID:   activityID,
   477  		ActivityType: activityType,
   478  		ReplayTime:   time.Now(),
   479  	}
   480  
   481  	// encode marker data
   482  	markerData, err := encodeArg(nil, lamd)
   483  	if err != nil {
   484  		panic(fmt.Sprintf("error encoding local activity marker data: %v", err))
   485  	}
   486  	return markerData
   487  }