github.com/erikdubbelboer/gopher-lua@v0.0.0-20160512044044-e68f0dc85040/channellib_test.go (about) 1 package lua 2 3 import ( 4 "reflect" 5 "sync" 6 "testing" 7 "time" 8 ) 9 10 func TestChannelMake(t *testing.T) { 11 L := NewState() 12 defer L.Close() 13 errorIfScriptFail(t, L, ` 14 ch = channel.make() 15 `) 16 obj := L.GetGlobal("ch") 17 ch, ok := obj.(LChannel) 18 errorIfFalse(t, ok, "channel expected") 19 errorIfNotEqual(t, 0, reflect.ValueOf(ch).Cap()) 20 close(ch) 21 22 errorIfScriptFail(t, L, ` 23 ch = channel.make(10) 24 `) 25 obj = L.GetGlobal("ch") 26 ch, _ = obj.(LChannel) 27 errorIfNotEqual(t, 10, reflect.ValueOf(ch).Cap()) 28 close(ch) 29 } 30 31 func TestChannelSelectError(t *testing.T) { 32 L := NewState() 33 defer L.Close() 34 errorIfScriptFail(t, L, `ch = channel.make()`) 35 errorIfScriptNotFail(t, L, `channel.select({1,2,3})`, "invalid select case") 36 errorIfScriptNotFail(t, L, `channel.select({"<-|", 1, 3})`, "invalid select case") 37 errorIfScriptNotFail(t, L, `channel.select({"<-|", ch, function() end})`, "can not send a function") 38 errorIfScriptNotFail(t, L, `channel.select({"|<-", 1, 3})`, "invalid select case") 39 errorIfScriptNotFail(t, L, `channel.select({"<-->", 1, 3})`, "invalid channel direction") 40 errorIfScriptFail(t, L, `ch:close()`) 41 } 42 43 func TestChannelSelect1(t *testing.T) { 44 var result LValue 45 var wg sync.WaitGroup 46 receiver := func(ch, quit chan LValue) { 47 defer wg.Done() 48 L := NewState() 49 defer L.Close() 50 L.SetGlobal("ch", LChannel(ch)) 51 L.SetGlobal("quit", LChannel(quit)) 52 if err := L.DoString(` 53 buf = "" 54 local exit = false 55 while not exit do 56 channel.select( 57 {"|<-", ch, function(ok, v) 58 if not ok then 59 buf = buf .. "channel closed" 60 exit = true 61 else 62 buf = buf .. "received:" .. v 63 end 64 end}, 65 {"|<-", quit, function(ok, v) 66 buf = buf .. "quit" 67 end} 68 ) 69 end 70 `); err != nil { 71 panic(err) 72 } 73 result = L.GetGlobal("buf") 74 } 75 76 sender := func(ch, quit chan LValue) { 77 defer wg.Done() 78 L := NewState() 79 defer L.Close() 80 L.SetGlobal("ch", LChannel(ch)) 81 L.SetGlobal("quit", LChannel(quit)) 82 if err := L.DoString(` 83 ch:send("1") 84 ch:send("2") 85 `); err != nil { 86 panic(err) 87 } 88 ch <- LString("3") 89 quit <- LTrue 90 time.Sleep(1 * time.Second) 91 close(ch) 92 } 93 94 ch := make(chan LValue) 95 quit := make(chan LValue) 96 wg.Add(2) 97 go receiver(ch, quit) 98 go sender(ch, quit) 99 wg.Wait() 100 lstr, ok := result.(LString) 101 errorIfFalse(t, ok, "must be string") 102 str := string(lstr) 103 errorIfNotEqual(t, "received:1received:2received:3quitchannel closed", str) 104 105 } 106 107 func TestChannelSelect2(t *testing.T) { 108 var wg sync.WaitGroup 109 receiver := func(ch, quit chan LValue) { 110 defer wg.Done() 111 L := NewState() 112 defer L.Close() 113 L.SetGlobal("ch", LChannel(ch)) 114 L.SetGlobal("quit", LChannel(quit)) 115 errorIfScriptFail(t, L, ` 116 idx, rcv, ok = channel.select( 117 {"|<-", ch}, 118 {"|<-", quit} 119 ) 120 assert(idx == 1) 121 assert(rcv == "1") 122 assert(ok) 123 idx, rcv, ok = channel.select( 124 {"|<-", ch}, 125 {"|<-", quit} 126 ) 127 assert(idx == 1) 128 assert(rcv == nil) 129 assert(not ok) 130 `) 131 } 132 133 sender := func(ch, quit chan LValue) { 134 defer wg.Done() 135 L := NewState() 136 defer L.Close() 137 L.SetGlobal("ch", LChannel(ch)) 138 L.SetGlobal("quit", LChannel(quit)) 139 errorIfScriptFail(t, L, `ch:send("1")`) 140 errorIfScriptFail(t, L, `ch:close()`) 141 } 142 143 ch := make(chan LValue) 144 quit := make(chan LValue) 145 wg.Add(2) 146 go receiver(ch, quit) 147 go sender(ch, quit) 148 wg.Wait() 149 } 150 151 func TestChannelSelect3(t *testing.T) { 152 var wg sync.WaitGroup 153 receiver := func(ch chan LValue) { 154 defer wg.Done() 155 L := NewState() 156 defer L.Close() 157 L.SetGlobal("ch", LChannel(ch)) 158 errorIfScriptFail(t, L, ` 159 ok = true 160 while ok do 161 idx, rcv, ok = channel.select( 162 {"|<-", ch} 163 ) 164 end 165 `) 166 } 167 168 sender := func(ch chan LValue) { 169 defer wg.Done() 170 L := NewState() 171 defer L.Close() 172 L.SetGlobal("ch", LChannel(ch)) 173 errorIfScriptFail(t, L, ` 174 ok = false 175 channel.select( 176 {"<-|", ch, "1", function(v) 177 ok = true 178 end} 179 ) 180 assert(ok) 181 idx, rcv, ok = channel.select( 182 {"<-|", ch, "1"} 183 ) 184 assert(idx == 1) 185 ch:close() 186 `) 187 } 188 189 ch := make(chan LValue) 190 wg.Add(2) 191 go receiver(ch) 192 time.Sleep(1) 193 go sender(ch) 194 wg.Wait() 195 } 196 197 func TestChannelSelect4(t *testing.T) { 198 var wg sync.WaitGroup 199 receiver := func(ch chan LValue) { 200 defer wg.Done() 201 L := NewState() 202 defer L.Close() 203 L.SetGlobal("ch", LChannel(ch)) 204 errorIfScriptFail(t, L, ` 205 idx, rcv, ok = channel.select( 206 {"|<-", ch}, 207 {"default"} 208 ) 209 assert(idx == 2) 210 called = false 211 idx, rcv, ok = channel.select( 212 {"|<-", ch}, 213 {"default", function() 214 called = true 215 end} 216 ) 217 assert(called) 218 ch:close() 219 `) 220 } 221 222 ch := make(chan LValue) 223 wg.Add(1) 224 go receiver(ch) 225 wg.Wait() 226 } 227 228 func TestChannelSendReceive1(t *testing.T) { 229 var wg sync.WaitGroup 230 receiver := func(ch chan LValue) { 231 defer wg.Done() 232 L := NewState() 233 defer L.Close() 234 L.SetGlobal("ch", LChannel(ch)) 235 errorIfScriptFail(t, L, ` 236 local ok, v = ch:receive() 237 assert(ok) 238 assert(v == "1") 239 `) 240 time.Sleep(1 * time.Second) 241 errorIfScriptFail(t, L, ` 242 local ok, v = ch:receive() 243 assert(not ok) 244 assert(v == nil) 245 `) 246 } 247 sender := func(ch chan LValue) { 248 defer wg.Done() 249 L := NewState() 250 defer L.Close() 251 L.SetGlobal("ch", LChannel(ch)) 252 errorIfScriptFail(t, L, `ch:send("1")`) 253 errorIfScriptNotFail(t, L, `ch:send(function() end)`, "can not send a function") 254 errorIfScriptFail(t, L, `ch:close()`) 255 } 256 ch := make(chan LValue) 257 wg.Add(2) 258 go receiver(ch) 259 go sender(ch) 260 wg.Wait() 261 }