github.com/bitxmesh/gopher-lua@v0.0.0-20190327085718-93c344ef97a4/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  }