1package phony 2 3import ( 4 "testing" 5 "unsafe" 6) 7 8func TestInboxSize(t *testing.T) { 9 var a Inbox 10 var q queueElem 11 t.Logf("Inbox size: %d, message size: %d", unsafe.Sizeof(a), unsafe.Sizeof(q)) 12} 13 14func TestBlock(t *testing.T) { 15 var a Inbox 16 var results []int 17 for idx := 0; idx < 1024; idx++ { 18 n := idx // Because idx gets mutated in place 19 Block(&a, func() { 20 results = append(results, n) 21 }) 22 } 23 for idx, n := range results { 24 if n != idx { 25 t.Errorf("value %d != index %d", n, idx) 26 } 27 } 28} 29 30func TestAct(t *testing.T) { 31 var a Inbox 32 var results []int 33 Block(&a, func() { 34 for idx := 0; idx < 1024; idx++ { 35 n := idx // Because idx gets mutated in place 36 a.Act(&a, func() { 37 results = append(results, n) 38 }) 39 } 40 }) 41 Block(&a, func() {}) 42 for idx, n := range results { 43 if n != idx { 44 t.Errorf("value %d != index %d", n, idx) 45 } 46 } 47} 48 49func TestPanicAct(t *testing.T) { 50 defer func() { 51 if r := recover(); r == nil { 52 t.Errorf("The code did not panic") 53 } 54 }() 55 var a Inbox 56 a.Act(nil, nil) 57} 58 59func TestPanicBlockActor(t *testing.T) { 60 defer func() { 61 if r := recover(); r == nil { 62 t.Errorf("The code did not panic") 63 } 64 }() 65 Block(nil, nil) 66} 67 68func TestPanicBlockAction(t *testing.T) { 69 defer func() { 70 if r := recover(); r == nil { 71 t.Errorf("The code did not panic") 72 } 73 }() 74 var a Inbox 75 Block(&a, nil) 76} 77 78func BenchmarkLoopActor(b *testing.B) { 79 var a Inbox 80 done := make(chan struct{}) 81 idx := 0 82 var f func() 83 f = func() { 84 if idx < b.N { 85 idx++ 86 a.Act(nil, f) 87 } else { 88 close(done) 89 } 90 } 91 a.Act(nil, f) 92 <-done 93} 94 95func BenchmarkLoopChannel(b *testing.B) { 96 ch := make(chan func(), 1) 97 defer close(ch) 98 go func() { 99 for f := range ch { 100 f() 101 } 102 }() 103 done := make(chan struct{}) 104 idx := 0 105 var f func() 106 f = func() { 107 if idx < b.N { 108 idx++ 109 ch <- f 110 } else { 111 close(done) 112 } 113 } 114 ch <- f 115 <-done 116} 117 118func BenchmarkSendActor(b *testing.B) { 119 var a, s Inbox 120 done := make(chan struct{}) 121 idx := 0 122 var f func() 123 f = func() { 124 if idx < b.N { 125 idx++ 126 a.Act(&s, func() {}) 127 s.Act(nil, f) 128 } else { 129 a.Act(&s, func() { close(done) }) 130 } 131 } 132 s.Act(nil, f) 133 <-done 134} 135 136func BenchmarkSendChannel(b *testing.B) { 137 done := make(chan struct{}) 138 ch := make(chan func()) 139 go func() { 140 for f := range ch { 141 f() 142 } 143 close(done) 144 }() 145 f := func() {} 146 for i := 0; i < b.N; i++ { 147 ch <- f 148 } 149 close(ch) 150 <-done 151} 152 153func BenchmarkRequestResponseActor(b *testing.B) { 154 var pinger, ponger Inbox 155 done := make(chan struct{}) 156 idx := 0 157 var ping, pong func() 158 ping = func() { 159 if idx < b.N { 160 idx++ 161 ponger.Act(&pinger, pong) 162 pinger.Act(nil, ping) // loop asynchronously 163 } else { 164 ponger.Act(&pinger, func() { 165 pinger.Act(nil, func() { 166 close(done) 167 }) 168 }) 169 } 170 } 171 pong = func() { 172 pinger.Act(nil, func() {}) // send a response without backpressure 173 } 174 pinger.Act(nil, ping) 175 <-done 176} 177 178func BenchmarkRequestResponseChannel(b *testing.B) { 179 done := make(chan struct{}) 180 toPing := make(chan func(), 1) 181 toPong := make(chan func(), 1) 182 defer close(toPing) 183 defer close(toPong) 184 var ping func() 185 var pong func() 186 ping = func() { 187 for idx := 0; idx < b.N; idx++ { 188 toPong <- pong 189 f := <-toPing 190 f() 191 } 192 toPong <- func() { 193 toPing <- func() { 194 close(done) 195 } 196 } 197 } 198 pong = func() { 199 toPing <- func() {} 200 } 201 go func() { 202 for f := range toPing { 203 f() 204 } 205 }() 206 go func() { 207 for f := range toPong { 208 f() 209 } 210 }() 211 toPing <- ping 212 <-done 213} 214 215func BenchmarkBlock(b *testing.B) { 216 var a Inbox 217 for i := 0; i < b.N; i++ { 218 Block(&a, func() {}) 219 } 220} 221