github.com/asynkron/protoactor-go@v0.0.0-20240308120642-ef91a6abee75/scheduler/timer_test.go (about)

     1  package scheduler
     2  
     3  import (
     4  	"testing"
     5  	"time"
     6  
     7  	"github.com/asynkron/protoactor-go/actor"
     8  	"github.com/stretchr/testify/assert"
     9  )
    10  
    11  var system = actor.NewActorSystem()
    12  
    13  func TestNewTimerScheduler(t *testing.T) {
    14  	newActor := func(t *testing.T, n int) (pid *actor.PID, ch chan struct{}) {
    15  		ch = make(chan struct{}, n)
    16  		props := actor.PropsFromFunc(func(c actor.Context) {
    17  			switch c.Message().(type) {
    18  			case string:
    19  				select {
    20  				case ch <- struct{}{}:
    21  				default:
    22  					t.Errorf("exceeeded expected count %d", n)
    23  				}
    24  			}
    25  		})
    26  		return system.Root.Spawn(props), ch
    27  	}
    28  
    29  	// check verifies the number of times ch receives a message matches exp
    30  	// and executes once more to ensure no further messages are received
    31  	check := func(t *testing.T, ch chan struct{}, cancel CancelFunc, exp int) {
    32  		got := 0
    33  		for i := 0; i < exp+1; i++ {
    34  			select {
    35  			case <-ch:
    36  				got++
    37  				if got == exp {
    38  					cancel()
    39  				}
    40  			case <-time.After(3 * time.Millisecond):
    41  				if got != exp {
    42  					assert.Fail(t, "failed to receive message")
    43  				}
    44  			}
    45  		}
    46  		cancel()
    47  		assert.Equal(t, exp, got)
    48  	}
    49  
    50  	t.Run("does", func(t *testing.T) {
    51  		t.Run("send once", func(t *testing.T) {
    52  			s := NewTimerScheduler(system.Root)
    53  			pid, ch := newActor(t, 1)
    54  			tok := s.SendOnce(1*time.Millisecond, pid, "hello")
    55  
    56  			check(t, ch, tok, 1)
    57  		})
    58  
    59  		t.Run("send repeatedly", func(t *testing.T) {
    60  			s := NewTimerScheduler(system.Root)
    61  			pid, ch := newActor(t, 5)
    62  			tok := s.SendRepeatedly(1*time.Millisecond, 1*time.Millisecond, pid, "hello")
    63  			check(t, ch, tok, 5)
    64  		})
    65  
    66  		t.Run("request once", func(t *testing.T) {
    67  			s := NewTimerScheduler(system.Root)
    68  			pid, ch := newActor(t, 1)
    69  			tok := s.RequestOnce(1*time.Millisecond, pid, "hello")
    70  
    71  			check(t, ch, tok, 1)
    72  		})
    73  
    74  		t.Run("request repeatedly", func(t *testing.T) {
    75  			s := NewTimerScheduler(system.Root)
    76  			pid, ch := newActor(t, 5)
    77  			tok := s.RequestRepeatedly(1*time.Millisecond, 1*time.Millisecond, pid, "hello")
    78  			check(t, ch, tok, 5)
    79  		})
    80  	})
    81  
    82  	t.Run("does not", func(t *testing.T) {
    83  		t.Run("send once", func(t *testing.T) {
    84  			s := NewTimerScheduler(system.Root)
    85  			pid, ch := newActor(t, 1)
    86  			cancel := s.SendOnce(1*time.Millisecond, pid, "hello")
    87  			cancel()
    88  			check(t, ch, cancel, 0)
    89  		})
    90  
    91  		t.Run("send repeatedly", func(t *testing.T) {
    92  			s := NewTimerScheduler(system.Root)
    93  			pid, ch := newActor(t, 5)
    94  			cancel := s.SendRepeatedly(1*time.Millisecond, 1*time.Millisecond, pid, "hello")
    95  			cancel()
    96  			check(t, ch, cancel, 0)
    97  		})
    98  
    99  		t.Run("request once", func(t *testing.T) {
   100  			s := NewTimerScheduler(system.Root)
   101  			pid, ch := newActor(t, 1)
   102  			cancel := s.RequestOnce(1*time.Millisecond, pid, "hello")
   103  			cancel()
   104  			check(t, ch, cancel, 0)
   105  		})
   106  
   107  		t.Run("request repeatedly", func(t *testing.T) {
   108  			s := NewTimerScheduler(system.Root)
   109  			pid, ch := newActor(t, 5)
   110  			cancel := s.RequestRepeatedly(1*time.Millisecond, 1*time.Millisecond, pid, "hello")
   111  			cancel()
   112  			check(t, ch, cancel, 0)
   113  		})
   114  	})
   115  }