blob: 2eb2847a98c6039465936300a38c24bdfb38374c [file] [log] [blame]
package common
import (
"testing"
"time"
"github.com/stretchr/testify/require"
"go.temporal.io/sdk/testsuite"
"go.temporal.io/sdk/workflow"
)
// Test cases here use simulated workflow environment to advance timers,
// different timers are set up such that the futures are fulfilled at
// different point of workflow progress, and then be able to test
// different states of futures.
func Test_NewFuture_WaitOnAllFutures(t *testing.T) {
testSuite := &testsuite.WorkflowTestSuite{}
env := testSuite.NewTestWorkflowEnvironment()
env.ExecuteWorkflow(func(ctx workflow.Context) error {
f1 := workflow.NewTimer(ctx, 10*time.Second)
f2 := workflow.NewTimer(ctx, 20*time.Second)
f := NewFutureWithFutures(ctx, f1, f2)
require.NoError(t, f.Get(ctx, nil))
require.True(t, f1.IsReady())
require.True(t, f2.IsReady())
return nil
})
require.NoError(t, env.GetWorkflowError())
}
func Test_NewFuture_NilFutures_NoOp(t *testing.T) {
testSuite := &testsuite.WorkflowTestSuite{}
env := testSuite.NewTestWorkflowEnvironment()
env.ExecuteWorkflow(func(ctx workflow.Context) error {
f1 := workflow.NewTimer(ctx, 10*time.Second)
f := NewFutureWithFutures(ctx, nil, f1)
require.NoError(t, f.Get(ctx, nil))
require.True(t, f1.IsReady())
f = NewFutureWithFutures(ctx, nil, nil)
require.NoError(t, f.Get(ctx, nil))
f = NewFutureWithFutures(ctx)
require.NoError(t, f.Get(ctx, nil))
return nil
})
require.NoError(t, env.GetWorkflowError())
}
func Test_NewFuture_NestedFuture(t *testing.T) {
testSuite := &testsuite.WorkflowTestSuite{}
env := testSuite.NewTestWorkflowEnvironment()
env.ExecuteWorkflow(func(ctx workflow.Context) error {
// t10
// t20 -> f1
// t1 -> f2
t1 := workflow.NewTimer(ctx, time.Second)
t10 := workflow.NewTimer(ctx, 10*time.Second)
t20 := workflow.NewTimer(ctx, 20*time.Second)
f1 := NewFutureWithFutures(ctx, t10, t20)
f2 := NewFutureWithFutures(ctx, t1, f1)
require.NoError(t, f2.Get(ctx, nil))
require.True(t, f1.IsReady())
require.True(t, t1.IsReady())
require.True(t, t10.IsReady())
require.True(t, t20.IsReady())
return nil
})
require.NoError(t, env.GetWorkflowError())
}
func Test_NewFuture_WithFulfilledFuture_ShouldReturn(t *testing.T) {
testSuite := &testsuite.WorkflowTestSuite{}
env := testSuite.NewTestWorkflowEnvironment()
env.ExecuteWorkflow(func(ctx workflow.Context) error {
t10 := workflow.NewTimer(ctx, 10*time.Second)
require.NoError(t, t10.Get(ctx, nil))
t20 := workflow.NewTimer(ctx, 20*time.Second)
f1 := NewFutureWithFutures(ctx, t10, t20)
require.NoError(t, f1.Get(ctx, nil))
require.True(t, t10.IsReady())
require.True(t, t20.IsReady())
return nil
})
require.NoError(t, env.GetWorkflowError())
}
func Test_NewFuture_WithDuplicates_ShouldReturn(t *testing.T) {
testSuite := &testsuite.WorkflowTestSuite{}
env := testSuite.NewTestWorkflowEnvironment()
env.ExecuteWorkflow(func(ctx workflow.Context) error {
t10 := workflow.NewTimer(ctx, 10*time.Second)
f1 := NewFutureWithFutures(ctx, t10, t10, t10)
require.NoError(t, f1.Get(ctx, nil))
require.True(t, t10.IsReady())
return nil
})
require.NoError(t, env.GetWorkflowError())
}
func Test_NewFuture_Cancel(t *testing.T) {
testSuite := &testsuite.WorkflowTestSuite{}
env := testSuite.NewTestWorkflowEnvironment()
env.RegisterDelayedCallback(func() {
env.CancelWorkflow()
}, 25*time.Second)
env.ExecuteWorkflow(func(ctx workflow.Context, waitTime time.Duration) error {
t10 := workflow.NewTimer(ctx, 10*time.Second)
longWait := workflow.NewTimer(ctx, waitTime)
f1 := NewFutureWithFutures(ctx, longWait, t10)
// Wait for all futures are done until the context is cancelled.
err := f1.Get(ctx, nil)
require.ErrorContains(t, err, "canceled")
// cancelled futures should be in ready state but with errors when Get()
require.True(t, f1.IsReady())
require.True(t, longWait.IsReady())
require.True(t, t10.IsReady())
// completed future shouldn't contain errors
require.NoError(t, t10.Get(ctx, nil))
require.ErrorContains(t, longWait.Get(ctx, nil), "canceled")
// populate errors to be captured by the caller.
return err
}, time.Hour)
require.Error(t, env.GetWorkflowError())
}