@@ -3,8 +3,8 @@ package updateworkflowoptions
33import (
44 "context"
55 "testing"
6+ "time"
67
7- "github.com/stretchr/testify/assert"
88 "github.com/stretchr/testify/require"
99 "github.com/stretchr/testify/suite"
1010 commonpb "go.temporal.io/api/common/v1"
@@ -28,7 +28,9 @@ import (
2828 wcache "go.temporal.io/server/service/history/workflow/cache"
2929 "go.uber.org/mock/gomock"
3030 "google.golang.org/protobuf/proto"
31+ "google.golang.org/protobuf/types/known/durationpb"
3132 "google.golang.org/protobuf/types/known/fieldmaskpb"
33+ "google.golang.org/protobuf/types/known/timestamppb"
3234)
3335
3436type noopVersionMembershipCache struct {}
@@ -94,28 +96,28 @@ func TestMergeOptions_VersionOverrideMask(t *testing.T) {
9496 if err != nil {
9597 t .Error (err )
9698 }
97- assert .EqualExportedValues (t , unpinnedOverrideOptions , merged )
99+ require .EqualExportedValues (t , unpinnedOverrideOptions , merged )
98100
99101 // Merge pinned_A into unpinned options
100102 merged , err = mergeWorkflowExecutionOptions (input , pinnedOverrideOptionsA , updateMask )
101103 if err != nil {
102104 t .Error (err )
103105 }
104- assert .EqualExportedValues (t , pinnedOverrideOptionsA , merged )
106+ require .EqualExportedValues (t , pinnedOverrideOptionsA , merged )
105107
106108 // Merge pinned_B into pinned_A options
107109 merged , err = mergeWorkflowExecutionOptions (input , pinnedOverrideOptionsB , updateMask )
108110 if err != nil {
109111 t .Error (err )
110112 }
111- assert .EqualExportedValues (t , pinnedOverrideOptionsB , merged )
113+ require .EqualExportedValues (t , pinnedOverrideOptionsB , merged )
112114
113115 // Unset versioning override
114116 merged , err = mergeWorkflowExecutionOptions (input , emptyOptions , updateMask )
115117 if err != nil {
116118 t .Error (err )
117119 }
118- assert .EqualExportedValues (t , emptyOptions , merged )
120+ require .EqualExportedValues (t , emptyOptions , merged )
119121}
120122
121123func TestMergeOptions_PartialMask (t * testing.T ) {
@@ -124,14 +126,14 @@ func TestMergeOptions_PartialMask(t *testing.T) {
124126 deploymentOnlyUpdateMask := & fieldmaskpb.FieldMask {Paths : []string {"versioning_override.deployment" }}
125127
126128 _ , err := mergeWorkflowExecutionOptions (emptyOptions , unpinnedOverrideOptions , behaviorOnlyUpdateMask )
127- assert .Error (t , err )
129+ require .Error (t , err )
128130
129131 _ , err = mergeWorkflowExecutionOptions (emptyOptions , unpinnedOverrideOptions , deploymentOnlyUpdateMask )
130- assert .Error (t , err )
132+ require .Error (t , err )
131133
132134 merged , err := mergeWorkflowExecutionOptions (emptyOptions , unpinnedOverrideOptions , bothUpdateMask )
133- assert .NoError (t , err )
134- assert .EqualExportedValues (t , unpinnedOverrideOptions , merged )
135+ require .NoError (t , err )
136+ require .EqualExportedValues (t , unpinnedOverrideOptions , merged )
135137}
136138
137139func TestMergeOptions_EmptyMask (t * testing.T ) {
@@ -140,25 +142,25 @@ func TestMergeOptions_EmptyMask(t *testing.T) {
140142
141143 // Don't merge anything
142144 merged , err := mergeWorkflowExecutionOptions (input , pinnedOverrideOptionsA , emptyUpdateMask )
143- assert .NoError (t , err )
144- assert .EqualExportedValues (t , input , merged )
145+ require .NoError (t , err )
146+ require .EqualExportedValues (t , input , merged )
145147
146148 // Don't merge anything
147149 merged , err = mergeWorkflowExecutionOptions (input , nil , emptyUpdateMask )
148- assert .NoError (t , err )
149- assert .EqualExportedValues (t , input , merged )
150+ require .NoError (t , err )
151+ require .EqualExportedValues (t , input , merged )
150152}
151153
152154func TestMergeOptions_AsteriskMask (t * testing.T ) {
153155 asteriskUpdateMask := & fieldmaskpb.FieldMask {Paths : []string {"*" }}
154156 _ , err := mergeWorkflowExecutionOptions (emptyOptions , unpinnedOverrideOptions , asteriskUpdateMask )
155- assert .Error (t , err )
157+ require .Error (t , err )
156158}
157159
158160func TestMergeOptions_FooMask (t * testing.T ) {
159161 fooUpdateMask := & fieldmaskpb.FieldMask {Paths : []string {"foo" }}
160162 _ , err := mergeWorkflowExecutionOptions (emptyOptions , unpinnedOverrideOptions , fooUpdateMask )
161- assert .Error (t , err )
163+ require .Error (t , err )
162164}
163165
164166type (
@@ -283,3 +285,108 @@ func (s *updateWorkflowOptionsSuite) TestInvoke_Success() {
283285 s .NotNil (resp )
284286 proto .Equal (expectedOverrideOptions , resp .GetWorkflowExecutionOptions ())
285287}
288+
289+ func TestMergeAndApply_TimeSkippingConfig (t * testing.T ) {
290+ oneHour := durationpb .New (time .Hour )
291+ twoHours := durationpb .New (2 * time .Hour )
292+ thirtyMin := durationpb .New (30 * time .Minute )
293+ targetTime := timestamppb .New (time .Date (2026 , 1 , 1 , 0 , 0 , 0 , 0 , time .UTC ))
294+
295+ testCases := []struct {
296+ name string
297+ initialConfig * workflowpb.TimeSkippingConfig
298+ updateOptions * workflowpb.WorkflowExecutionOptions
299+ updateMask * fieldmaskpb.FieldMask
300+ expectedConfig * workflowpb.TimeSkippingConfig
301+ }{
302+ {
303+ name : "update max_skipped_duration preserves enabled and disable_propagation" ,
304+ initialConfig : & workflowpb.TimeSkippingConfig {
305+ Enabled : true ,
306+ DisablePropagation : true ,
307+ Bound : & workflowpb.TimeSkippingConfig_MaxSkippedDuration {
308+ MaxSkippedDuration : oneHour ,
309+ },
310+ },
311+ updateOptions : & workflowpb.WorkflowExecutionOptions {
312+ TimeSkippingConfig : & workflowpb.TimeSkippingConfig {
313+ Bound : & workflowpb.TimeSkippingConfig_MaxSkippedDuration {
314+ MaxSkippedDuration : twoHours ,
315+ },
316+ },
317+ },
318+ updateMask : & fieldmaskpb.FieldMask {Paths : []string {"time_skipping_config.max_skipped_duration" }},
319+ expectedConfig : & workflowpb.TimeSkippingConfig {
320+ Enabled : true ,
321+ DisablePropagation : true ,
322+ Bound : & workflowpb.TimeSkippingConfig_MaxSkippedDuration {
323+ MaxSkippedDuration : twoHours ,
324+ },
325+ },
326+ },
327+ {
328+ name : "change bound type to max_elapsed_duration preserves enabled" ,
329+ initialConfig : & workflowpb.TimeSkippingConfig {
330+ Enabled : true ,
331+ Bound : & workflowpb.TimeSkippingConfig_MaxSkippedDuration {
332+ MaxSkippedDuration : oneHour ,
333+ },
334+ },
335+ updateOptions : & workflowpb.WorkflowExecutionOptions {
336+ TimeSkippingConfig : & workflowpb.TimeSkippingConfig {
337+ Bound : & workflowpb.TimeSkippingConfig_MaxElapsedDuration {
338+ MaxElapsedDuration : thirtyMin ,
339+ },
340+ },
341+ },
342+ updateMask : & fieldmaskpb.FieldMask {Paths : []string {"time_skipping_config.max_elapsed_duration" }},
343+ expectedConfig : & workflowpb.TimeSkippingConfig {
344+ Enabled : true ,
345+ Bound : & workflowpb.TimeSkippingConfig_MaxElapsedDuration {
346+ MaxElapsedDuration : thirtyMin ,
347+ },
348+ },
349+ },
350+ {
351+ name : "change bound type to max_target_time preserves enabled" ,
352+ initialConfig : & workflowpb.TimeSkippingConfig {
353+ Enabled : true ,
354+ Bound : & workflowpb.TimeSkippingConfig_MaxSkippedDuration {
355+ MaxSkippedDuration : oneHour ,
356+ },
357+ },
358+ updateOptions : & workflowpb.WorkflowExecutionOptions {
359+ TimeSkippingConfig : & workflowpb.TimeSkippingConfig {
360+ Bound : & workflowpb.TimeSkippingConfig_MaxTargetTime {
361+ MaxTargetTime : targetTime ,
362+ },
363+ },
364+ },
365+ updateMask : & fieldmaskpb.FieldMask {Paths : []string {"time_skipping_config.max_target_time" }},
366+ expectedConfig : & workflowpb.TimeSkippingConfig {
367+ Enabled : true ,
368+ Bound : & workflowpb.TimeSkippingConfig_MaxTargetTime {
369+ MaxTargetTime : targetTime ,
370+ },
371+ },
372+ },
373+ }
374+
375+ for _ , tc := range testCases {
376+ t .Run (tc .name , func (t * testing.T ) {
377+ ctrl := gomock .NewController (t )
378+ ms := historyi .NewMockMutableState (ctrl )
379+ ms .EXPECT ().GetExecutionInfo ().Return (& persistencespb.WorkflowExecutionInfo {
380+ TimeSkippingInfo : & persistencespb.TimeSkippingInfo {
381+ Config : tc .initialConfig ,
382+ },
383+ }).AnyTimes ()
384+ ms .EXPECT ().AddWorkflowExecutionOptionsUpdatedEvent (nil , true , "" , nil , nil , "" , nil ).Return (& historypb.HistoryEvent {}, nil )
385+
386+ result , hasChanges , err := MergeAndApply (ms , tc .updateOptions , tc .updateMask , "" )
387+ require .NoError (t , err )
388+ require .True (t , hasChanges )
389+ require .True (t , proto .Equal (tc .expectedConfig , result .GetTimeSkippingConfig ()))
390+ })
391+ }
392+ }
0 commit comments