github.com/asynkron/protoactor-go@v0.0.0-20240308120642-ef91a6abee75/actor/future_test.go (about) 1 package actor 2 3 import ( 4 "testing" 5 "time" 6 7 "github.com/stretchr/testify/assert" 8 ) 9 10 func TestFuture_PipeTo_Message(t *testing.T) { 11 a1, p1 := spawnMockProcess("a1") 12 a2, p2 := spawnMockProcess("a2") 13 a3, p3 := spawnMockProcess("a3") 14 defer func() { 15 removeMockProcess(a1) 16 removeMockProcess(a2) 17 removeMockProcess(a3) 18 }() 19 20 f := NewFuture(system, 1*time.Second) 21 22 p1.On("SendUserMessage", a1, "hello") 23 p2.On("SendUserMessage", a2, "hello") 24 p3.On("SendUserMessage", a3, "hello") 25 26 f.PipeTo(a1) 27 f.PipeTo(a2) 28 f.PipeTo(a3) 29 30 ref, _ := system.ProcessRegistry.Get(f.pid) 31 assert.IsType(t, &futureProcess{}, ref) 32 fp, _ := ref.(*futureProcess) 33 34 fp.SendUserMessage(f.pid, "hello") 35 p1.AssertExpectations(t) 36 p2.AssertExpectations(t) 37 p3.AssertExpectations(t) 38 assert.Empty(t, fp.pipes, "pipes were not cleared") 39 } 40 41 func TestFuture_PipeTo_TimeoutSendsError(t *testing.T) { 42 a1, p1 := spawnMockProcess("a1") 43 a2, p2 := spawnMockProcess("a2") 44 a3, p3 := spawnMockProcess("a3") 45 defer func() { 46 removeMockProcess(a1) 47 removeMockProcess(a2) 48 removeMockProcess(a3) 49 }() 50 51 p1.On("SendUserMessage", a1, ErrTimeout) 52 p2.On("SendUserMessage", a2, ErrTimeout) 53 p3.On("SendUserMessage", a3, ErrTimeout) 54 55 f := NewFuture(system, 10*time.Millisecond) 56 ref, _ := system.ProcessRegistry.Get(f.pid) 57 58 f.PipeTo(a1) 59 f.PipeTo(a2) 60 f.PipeTo(a3) 61 62 err := f.Wait() 63 assert.Error(t, err) 64 65 assert.IsType(t, &futureProcess{}, ref) 66 fp, _ := ref.(*futureProcess) 67 68 p1.AssertExpectations(t) 69 p2.AssertExpectations(t) 70 p3.AssertExpectations(t) 71 assert.Empty(t, fp.pipes, "pipes were not cleared") 72 } 73 74 func TestNewFuture_TimeoutNoRace(t *testing.T) { 75 76 future := NewFuture(system, 1*time.Microsecond) 77 a := rootContext.Spawn(PropsFromFunc(func(context Context) { 78 switch context.Message().(type) { 79 case *Started: 80 context.Send(future.PID(), EchoResponse{}) 81 } 82 })) 83 _ = rootContext.StopFuture(a).Wait() 84 _, _ = future.Result() 85 } 86 87 func assertFutureSuccess(future *Future, t *testing.T) interface{} { 88 res, err := future.Result() 89 assert.NoError(t, err, "timed out") 90 return res 91 } 92 93 func TestFuture_Result_DeadLetterResponse(t *testing.T) { 94 a := assert.New(t) 95 96 future := NewFuture(system, 1*time.Second) 97 rootContext.Send(future.PID(), &DeadLetterResponse{}) 98 resp, err := future.Result() 99 a.Equal(ErrDeadLetter, err) 100 a.Nil(resp) 101 } 102 103 func TestFuture_Result_Timeout(t *testing.T) { 104 a := assert.New(t) 105 106 future := NewFuture(system, 1*time.Second) 107 resp, err := future.Result() 108 a.Equal(ErrTimeout, err) 109 a.Nil(resp) 110 } 111 112 func TestFuture_Result_Success(t *testing.T) { 113 a := assert.New(t) 114 115 future := NewFuture(system, 1*time.Second) 116 rootContext.Send(future.PID(), EchoResponse{}) 117 resp := assertFutureSuccess(future, t) 118 a.Equal(EchoResponse{}, resp) 119 }