github.com/asynkron/protoactor-go@v0.0.0-20240308120642-ef91a6abee75/actor/mailbox_test.go (about) 1 package actor 2 3 import ( 4 "fmt" 5 "log" 6 "math/rand" 7 "sync" 8 "testing" 9 "time" 10 11 rbqueue "github.com/Workiva/go-datastructures/queue" 12 13 "github.com/stretchr/testify/assert" 14 ) 15 16 type invoker struct { 17 count int 18 max int 19 wg *sync.WaitGroup 20 } 21 22 func (i *invoker) InvokeSystemMessage(interface{}) { 23 i.count++ 24 if i.count == i.max { 25 i.wg.Done() 26 } 27 if i.count > i.max { 28 log.Println("Unexpected data..") 29 } 30 } 31 32 func (i *invoker) InvokeUserMessage(interface{}) { 33 i.count++ 34 if i.count == i.max { 35 i.wg.Done() 36 } 37 if i.count > i.max { 38 log.Println("Unexpected data..") 39 } 40 } 41 42 func (*invoker) EscalateFailure(_ interface{}, _ interface{}) {} 43 44 func TestUnboundedLockfreeMailboxUsermessageConsistency(t *testing.T) { 45 max := 1000000 46 c := 100 47 var wg sync.WaitGroup 48 wg.Add(1) 49 p := UnboundedLockfree() 50 mi := &invoker{ 51 max: max, 52 wg: &wg, 53 } 54 q := p() 55 q.RegisterHandlers(mi, NewDefaultDispatcher(300)) 56 57 for j := 0; j < c; j++ { 58 cmax := max / c 59 go func(j int) { 60 for i := 0; i < cmax; i++ { 61 if rand.Intn(10) == 0 { 62 time.Sleep(time.Duration(rand.Intn(1000))) 63 } 64 q.PostUserMessage(fmt.Sprintf("%v %v", j, i)) 65 } 66 }(j) 67 } 68 wg.Wait() 69 time.Sleep(1 * time.Second) 70 } 71 72 type sysDummy struct { 73 value string 74 } 75 76 func (*sysDummy) SystemMessage() { 77 } 78 79 func TestUnboundedLockfreeMailboxSysMessageConsistency(t *testing.T) { 80 max := 1000000 81 c := 100 82 var wg sync.WaitGroup 83 wg.Add(1) 84 p := UnboundedLockfree() 85 mi := &invoker{ 86 max: max, 87 wg: &wg, 88 } 89 q := p() 90 q.RegisterHandlers(mi, NewDefaultDispatcher(300)) 91 92 for j := 0; j < c; j++ { 93 cmax := max / c 94 go func(j int) { 95 for i := 0; i < cmax; i++ { 96 if rand.Intn(10) == 0 { 97 time.Sleep(time.Duration(rand.Intn(100))) 98 } 99 q.PostSystemMessage( 100 &sysDummy{ 101 value: fmt.Sprintf("%v %v", j, i), 102 }) 103 } 104 }(j) 105 } 106 wg.Wait() 107 time.Sleep(1 * time.Second) 108 } 109 110 func TestBoundedMailbox(t *testing.T) { 111 size := 3 112 m := boundedMailboxQueue{ 113 userMailbox: rbqueue.NewRingBuffer(uint64(size)), 114 dropping: false, 115 } 116 m.Push("1") 117 m.Push("2") 118 m.Push("3") 119 assert.Equal(t, "1", m.Pop()) 120 } 121 122 func TestBoundedDroppingMailbox(t *testing.T) { 123 size := 3 124 m := boundedMailboxQueue{ 125 userMailbox: rbqueue.NewRingBuffer(uint64(size)), 126 dropping: true, 127 } 128 m.Push("1") 129 m.Push("2") 130 m.Push("3") 131 m.Push("4") 132 assert.Equal(t, "2", m.Pop()) 133 } 134 135 func TestMailboxUserMessageCount(t *testing.T) { 136 max := 10 137 c := 10 138 var wg sync.WaitGroup 139 wg.Add(1) 140 p := UnboundedLockfree() 141 mi := &invoker{ 142 max: max, 143 wg: &wg, 144 } 145 q := p() 146 q.RegisterHandlers(mi, NewDefaultDispatcher(300)) 147 148 for j := 0; j < c; j++ { 149 q.PostUserMessage(fmt.Sprintf("%v", j)) 150 } 151 assert.Equal(t, c, q.UserMessageCount()) 152 wg.Wait() 153 time.Sleep(100 * time.Millisecond) 154 }