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  }