go.uber.org/cadence@v1.2.9/test/activity_test.go (about) 1 // Copyright (c) 2017-2020 Uber Technologies Inc. 2 // Portions of the Software are attributed to Copyright (c) 2020 Temporal Technologies Inc. 3 // 4 // Permission is hereby granted, free of charge, to any person obtaining a copy 5 // of this software and associated documentation files (the "Software"), to deal 6 // in the Software without restriction, including without limitation the rights 7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 8 // copies of the Software, and to permit persons to whom the Software is 9 // furnished to do so, subject to the following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included in 12 // all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 // THE SOFTWARE. 21 22 package test 23 24 import ( 25 "context" 26 "fmt" 27 "strings" 28 "sync" 29 "time" 30 31 "go.uber.org/cadence" 32 "go.uber.org/cadence/activity" 33 "go.uber.org/cadence/worker" 34 ) 35 36 type Activities struct { 37 mu sync.Mutex 38 invocations []string 39 activities2 *Activities2 40 } 41 42 type Activities2 struct { 43 impl *Activities 44 } 45 46 var errFailOnPurpose = cadence.NewCustomError("failing-on-purpose") 47 48 func newActivities() *Activities { 49 activities2 := &Activities2{} 50 result := &Activities{activities2: activities2} 51 activities2.impl = result 52 return result 53 } 54 55 func (a *Activities) RetryTimeoutStableErrorActivity() error { 56 time.Sleep(time.Second * 3) 57 return errFailOnPurpose 58 } 59 60 func (a *Activities) Sleep(_ context.Context, delay time.Duration) error { 61 a.append("sleep") 62 time.Sleep(delay) 63 return nil 64 } 65 66 func LocalSleep(_ context.Context, delay time.Duration) error { 67 time.Sleep(delay) 68 return nil 69 } 70 71 func (a *Activities) HeartbeatAndSleep(ctx context.Context, seq int, delay time.Duration) (int, error) { 72 a.append("heartbeatAndSleep") 73 if activity.HasHeartbeatDetails(ctx) { 74 var prev int 75 if err := activity.GetHeartbeatDetails(ctx, &prev); err == nil { 76 seq = prev 77 } 78 } 79 seq++ 80 activity.RecordHeartbeat(ctx, seq) 81 time.Sleep(delay) 82 return seq, nil 83 } 84 85 func (a *Activities) fail(_ context.Context) error { 86 a.append("fail") 87 return errFailOnPurpose 88 } 89 90 func (a *Activities) DuplicateStringInContext(ctx context.Context) (string, error) { 91 originalString := ctx.Value(contextKey(testContextKey)) 92 if originalString == nil { 93 return "", fmt.Errorf("context did not propagate to activity") 94 } 95 return strings.Repeat(originalString.(string), 2), nil 96 } 97 98 func (a *Activities) append(name string) { 99 a.mu.Lock() 100 defer a.mu.Unlock() 101 a.invocations = append(a.invocations, name) 102 } 103 104 func (a *Activities) invoked() []string { 105 a.mu.Lock() 106 defer a.mu.Unlock() 107 result := make([]string, len(a.invocations)) 108 copy(result, a.invocations) 109 return result 110 } 111 112 func (a *Activities) clearInvoked() { 113 a.mu.Lock() 114 defer a.mu.Unlock() 115 a.invocations = []string{} 116 } 117 118 func (a *Activities2) ToUpper(_ context.Context, arg string) (string, error) { 119 a.impl.append("toUpper") 120 return strings.ToUpper(arg), nil 121 } 122 123 func (a *Activities2) ToUpperWithDelay(_ context.Context, arg string, delay time.Duration) (string, error) { 124 a.impl.append("toUpperWithDelay") 125 time.Sleep(delay) 126 return strings.ToUpper(arg), nil 127 } 128 129 func (a *Activities) GetMemoAndSearchAttr(_ context.Context, memo, searchAttr string) (string, error) { 130 a.append("getMemoAndSearchAttr") 131 return memo + ", " + searchAttr, nil 132 } 133 134 func (a *Activities) InspectActivityInfo(ctx context.Context, domain, taskList, wfType string) error { 135 a.append("inspectActivityInfo") 136 info := activity.GetInfo(ctx) 137 if info.WorkflowDomain != domain { 138 return fmt.Errorf("expected domainName %v but got %v", domain, info.WorkflowDomain) 139 } 140 if info.WorkflowType == nil || info.WorkflowType.Name != wfType { 141 return fmt.Errorf("expected workflowType %v but got %v", wfType, info.WorkflowType) 142 } 143 if info.TaskList != taskList { 144 return fmt.Errorf("expected taskList %v but got %v", taskList, info.TaskList) 145 } 146 return nil 147 } 148 149 func (a *Activities) register(worker worker.Worker) { 150 // Kept to verify backward compatibility of activity registration. 151 activity.RegisterWithOptions(a, activity.RegisterOptions{Name: "Activities_", DisableAlreadyRegisteredCheck: true}) 152 // Check reregistration 153 worker.RegisterActivityWithOptions(a.fail, activity.RegisterOptions{Name: "Fail", DisableAlreadyRegisteredCheck: true}) 154 // Check prefix 155 worker.RegisterActivityWithOptions(a.activities2, activity.RegisterOptions{Name: "Prefix_", DisableAlreadyRegisteredCheck: true}) 156 worker.RegisterActivityWithOptions(a.InspectActivityInfo, activity.RegisterOptions{Name: "inspectActivityInfo"}) 157 worker.RegisterActivityWithOptions(a.HeartbeatAndSleep, activity.RegisterOptions{Name: "HeartbeatAndSleep", EnableAutoHeartbeat: true}) 158 }