aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorBenoit Germain <benoit.germain@ubisoft.com>2024-04-11 15:14:52 +0200
committerBenoit Germain <benoit.germain@ubisoft.com>2024-04-11 15:14:52 +0200
commitadaa36dbec1ce9aaafd61873b9d3d898a8c240cf (patch)
tree4c81e8f5983c3d696a636e2cc433ce7c0a9c3dd8 /tests
parent1d310e6ecb6e156598337612f16573d9cd284f5e (diff)
downloadlanes-adaa36dbec1ce9aaafd61873b9d3d898a8c240cf.tar.gz
lanes-adaa36dbec1ce9aaafd61873b9d3d898a8c240cf.tar.bz2
lanes-adaa36dbec1ce9aaafd61873b9d3d898a8c240cf.zip
Bring all interesting fixes from the C++ implementation back into the C implementation
Diffstat (limited to 'tests')
-rw-r--r--tests/basic.lua14
-rw-r--r--tests/cancel.lua212
-rw-r--r--tests/errhangtest.lua15
-rw-r--r--tests/fifo.lua42
-rw-r--r--tests/keeper.lua63
-rw-r--r--tests/linda_perf.lua165
-rw-r--r--tests/protect_allocator.lua3
-rw-r--r--tests/timer.lua12
8 files changed, 332 insertions, 194 deletions
diff --git a/tests/basic.lua b/tests/basic.lua
index 385e22f..4b4fae6 100644
--- a/tests/basic.lua
+++ b/tests/basic.lua
@@ -154,7 +154,7 @@ PRINT(" "..st)
154assert( st == "cancelled" ) 154assert( st == "cancelled" )
155 155
156-- cancellation of lanes waiting on a linda 156-- cancellation of lanes waiting on a linda
157local limited = lanes.linda() 157local limited = lanes.linda("limited")
158limited:limit( "key", 1) 158limited:limit( "key", 1)
159-- [[################################################ 159-- [[################################################
160limited:send( "key", "hello") -- saturate linda 160limited:send( "key", "hello") -- saturate linda
@@ -234,7 +234,7 @@ local chunk= function( linda )
234 WR( "Lane ends!\n" ) 234 WR( "Lane ends!\n" )
235end 235end
236 236
237local linda= lanes_linda() 237local linda= lanes_linda("communications")
238assert( type(linda) == "userdata" ) 238assert( type(linda) == "userdata" )
239 -- 239 --
240 -- ["->"] master -> slave 240 -- ["->"] master -> slave
@@ -278,10 +278,12 @@ local complex_table = RECEIVE(); WR( type(complex_table).." received\n" )
278assert( complex_table[1] == complex_table[3] and complex_table[2] == complex_table[4]) 278assert( complex_table[1] == complex_table[3] and complex_table[2] == complex_table[4])
279WR( table.concat( {complex_table[1][1],complex_table[2][1],complex_table[3][1],complex_table[4][1]},", ")) 279WR( table.concat( {complex_table[1][1],complex_table[2][1],complex_table[3][1],complex_table[4][1]},", "))
280 280
281WR("collectgarbage")
281t = nil 282t = nil
282collectgarbage() 283collectgarbage()
283-- wait 284-- wait
284linda: receive( 1, "wait") 285WR("waiting 1s")
286linda:receive( 1, "wait")
285 287
286--############################################################## 288--##############################################################
287--############################################################## 289--##############################################################
@@ -336,6 +338,7 @@ for _, t in ipairs( stdlib_naming_tests) do
336 assert( f(t[1])[1] ) 338 assert( f(t[1])[1] )
337end 339end
338 340
341WR("collectgarbage")
339collectgarbage() 342collectgarbage()
340 343
341--############################################################## 344--##############################################################
@@ -361,12 +364,13 @@ local tc= lanes_gen( "io", {gc_cb = gc_cb},
361 end 364 end
362) 365)
363 366
364local linda= lanes_linda() 367local linda= lanes_linda("criss cross")
365 368
366local a,b= tc(linda, "A","B"), tc(linda, "B","A") -- launching two lanes, twisted comms 369local a,b= tc(linda, "A","B"), tc(linda, "B","A") -- launching two lanes, twisted comms
367 370
368local _= a[1],b[1] -- waits until they are both ready 371local _= a[1],b[1] -- waits until they are both ready
369 372
373WR("collectgarbage")
370a, b = nil 374a, b = nil
371collectgarbage() 375collectgarbage()
372 376
@@ -408,7 +412,7 @@ local function chunk2( linda )
408 linda:send( "up", function() return ":)" end, "ok2" ) 412 linda:send( "up", function() return ":)" end, "ok2" )
409end 413end
410 414
411local linda= lanes.linda() 415local linda= lanes.linda("linda")
412local t2= lanes_gen( "debug,string,io", {gc_cb = gc_cb}, chunk2 )(linda) -- prepare & launch 416local t2= lanes_gen( "debug,string,io", {gc_cb = gc_cb}, chunk2 )(linda) -- prepare & launch
413linda:send( "down", function(linda) linda:send( "up", "ready!" ) end, 417linda:send( "down", function(linda) linda:send( "up", "ready!" ) end,
414 "ok" ) 418 "ok" )
diff --git a/tests/cancel.lua b/tests/cancel.lua
index 0d9d143..4e57184 100644
--- a/tests/cancel.lua
+++ b/tests/cancel.lua
@@ -1,36 +1,47 @@
1local lanes = require "lanes" .configure{ with_timers = false} 1local which_tests, remaining_tests = {}, {}
2 2for k,v in ipairs{...} do
3local linda = lanes.linda() 3 print("got arg:", type(v), tostring(v))
4 which_tests[v] = true
5 remaining_tests[v] = true
6end
4 7
5--#################################################################### 8--####################################################################
6print "\n\n####################################################################\nbegin genlock & genatomic cancel test\n"
7
8-- get a lock and a atomic operator
9local lock = lanes.genlock( linda, "lock", 1)
10local atomic = lanes.genatomic( linda, "atomic")
11
12-- check that cancelled lindas give cancel_error as they should
13linda:cancel()
14assert( linda:get( "empty") == lanes.cancel_error)
15assert( lanes.genlock( linda, "any", 1) == lanes.cancel_error)
16assert( lanes.genatomic( linda, "any") == lanes.cancel_error)
17
18-- check that lock and atomic functions return cancel_error if the linda was cancelled
19assert( lock( 1) == lanes.cancel_error)
20assert( lock( -1) == lanes.cancel_error)
21assert( atomic( 1) == lanes.cancel_error)
22
23-- reset the linda so that the other tests work
24linda:cancel( "none")
25linda:limit( "lock", -1)
26linda:set( "lock")
27linda:limit( "atomic", -1)
28linda:set( "atomic")
29 9
10local lanes = require "lanes" .configure{ with_timers = false}
11
12local linda = lanes.linda()
30-- a numeric value to read 13-- a numeric value to read
31linda:set( "val", 33.0) 14linda:set( "val", 33.0)
32 15
33print "test OK" 16--####################################################################
17if not next(which_tests) or which_tests.genlock then
18 remaining_tests.genlock = nil
19 print "\n\n####################################################################\nbegin genlock & genatomic cancel test\n"
20
21 -- get a lock and a atomic operator
22 local lock = lanes.genlock( linda, "lock", 1)
23 local atomic = lanes.genatomic( linda, "atomic")
24
25 -- check that cancelled lindas give cancel_error as they should
26 linda:cancel()
27 assert( linda:get( "empty") == lanes.cancel_error)
28 assert( lanes.genlock( linda, "any", 1) == lanes.cancel_error)
29 assert( lanes.genatomic( linda, "any") == lanes.cancel_error)
30
31 -- check that lock and atomic functions return cancel_error if the linda was cancelled
32 assert( lock( 1) == lanes.cancel_error)
33 assert( lock( -1) == lanes.cancel_error)
34 assert( atomic( 1) == lanes.cancel_error)
35
36 -- reset the linda so that the other tests work
37 linda:cancel( "none")
38 linda:limit( "lock", -1)
39 linda:set( "lock")
40 linda:limit( "atomic", -1)
41 linda:set( "atomic")
42
43 print "test OK"
44end
34--#################################################################### 45--####################################################################
35 46
36local waitCancellation = function( h, expected_status) 47local waitCancellation = function( h, expected_status)
@@ -119,92 +130,115 @@ end
119--#################################################################### 130--####################################################################
120--#################################################################### 131--####################################################################
121 132
122print "\n\n####################################################################\nbegin linda cancel test\n" 133if not next(which_tests) or which_tests.linda then
123h = lanes.gen( "*", laneBody)( "receive", nil) -- start an infinite wait on the linda 134 remaining_tests.linda = nil
124 135 print "\n\n####################################################################\nbegin linda cancel test\n"
125print "wait 1s" 136 h = lanes.gen( "*", laneBody)( "receive", nil) -- start an infinite wait on the linda
126linda:receive( 1, "yeah")
127
128-- linda cancel: linda:receive() returns cancel_error immediately
129linda:cancel( "both")
130 137
131-- wait until cancellation is effective. 138 print "wait 1s"
132waitCancellation( h, "done") 139 linda:receive( 1, "yeah")
133 140
134-- reset the linda so that the other tests work 141 -- linda cancel: linda:receive() returns cancel_error immediately
135linda:cancel( "none") 142 print "cancelling"
143 linda:cancel( "both")
136 144
137print "\n\n####################################################################\nbegin soft cancel test\n" 145 -- wait until cancellation is effective.
138h = lanes.gen( "*", protectedBody)( "receive") -- start an infinite wait on the linda 146 waitCancellation( h, "done")
139 147
140print "wait 1s" 148 -- reset the linda so that the other tests work
141linda:receive( 1, "yeah") 149 linda:cancel( "none")
150end
142 151
143-- soft cancel, no awakening of waiting linda operations, should timeout 152if not next(which_tests) or which_tests.soft then
144local a, b = h:cancel( "soft", 1, false) 153 remaining_tests.soft = nil
145-- cancellation should fail as the lane is still waiting on its linda 154 print "\n\n####################################################################\nbegin soft cancel test\n"
146assert( a == false and b == "timeout") 155 h = lanes.gen( "*", protectedBody)( "receive") -- start an infinite wait on the linda
147waitCancellation( h, "waiting")
148 156
149-- soft cancel, this time awakens waiting linda operations, which returns cancel_error immediately, no timeout. 157 print "wait 1s"
150h:cancel( "soft", true) 158 linda:receive( 1, "yeah")
151 159
152-- wait until cancellation is effective. the lane will interrupt its loop and print the exit message 160 -- soft cancel, no awakening of waiting linda operations, should timeout
153waitCancellation( h, "done") 161 local a, b = h:cancel( "soft", 1, false)
162 -- cancellation should fail as the lane is still waiting on its linda
163 assert( a == false and b == "timeout")
164 waitCancellation( h, "waiting")
154 165
155-- do return end 166 -- soft cancel, this time awakens waiting linda operations, which returns cancel_error immediately, no timeout.
167 print "cancelling"
168 h:cancel( "soft", true)
156 169
157print "\n\n####################################################################\nbegin hook cancel test\n" 170 -- wait until cancellation is effective. the lane will interrupt its loop and print the exit message
158h = lanes.gen( "*", protectedBody)( "get", 300000) 171 waitCancellation( h, "done")
159print "wait 2s" 172end
160linda:receive( 2, "yeah")
161 173
162-- count hook cancel after 3 instructions 174if not next(which_tests) or which_tests.hook then
163h:cancel( "count", 300, 5.0) 175 remaining_tests.hook = nil
176 print "\n\n####################################################################\nbegin hook cancel test\n"
177 h = lanes.gen( "*", protectedBody)( "get", 300000)
178 print "wait 2s"
179 linda:receive( 2, "yeah")
164 180
165-- wait until cancellation is effective. the lane will interrupt its loop and print the exit message 181 -- count hook cancel after some instruction instructions
166waitCancellation( h, "cancelled") 182 print "cancelling"
183 h:cancel( "line", 300, 5.0)
167 184
168print "\n\n####################################################################\nbegin hard cancel test\n" 185 -- wait until cancellation is effective. the lane will interrupt its loop and print the exit message
169h = lanes.gen( "*", protectedBody)( "receive", nil) -- infinite timeout 186 waitCancellation( h, "cancelled")
187end
170 188
171-- wait 2s before cancelling the lane 189if not next(which_tests) or which_tests.hard then
172print "wait 2s" 190 remaining_tests.hard = nil
173linda:receive( 2, "yeah") 191 print "\n\n####################################################################\nbegin hard cancel test\n"
192 h = lanes.gen( "*", protectedBody)( "receive", nil) -- infinite timeout
174 193
175-- hard cancel: the lane will be interrupted from inside its current linda:receive() and won't return from it 194 -- wait 2s before cancelling the lane
176h:cancel() 195 print "wait 2s"
196 linda:receive( 2, "yeah")
177 197
178-- wait until cancellation is effective. the lane will be stopped by the linda operation throwing an error 198 -- hard cancel: the lane will be interrupted from inside its current linda:receive() and won't return from it
179waitCancellation( h, "cancelled") 199 print "cancelling"
200 h:cancel()
180 201
181print "\n\n####################################################################\nbegin hard cancel test with unprotected lane body\n" 202 -- wait until cancellation is effective. the lane will be stopped by the linda operation throwing an error
182h = lanes.gen( "*", laneBody)( "receive", nil) 203 waitCancellation( h, "cancelled")
204end
183 205
184-- wait 2s before cancelling the lane 206if not next(which_tests) or which_tests.hard_unprotected then
185print "wait 2s" 207 remaining_tests.hard_unprotected = nil
186linda:receive( 2, "yeah") 208 print "\n\n####################################################################\nbegin hard cancel test with unprotected lane body\n"
209 h = lanes.gen( "*", laneBody)( "receive", nil)
187 210
188-- hard cancel: the lane will be interrupted from inside its current linda:receive() and won't return from it 211 -- wait 2s before cancelling the lane
189h:cancel() 212 print "wait 2s"
213 linda:receive( 2, "yeah")
190 214
191-- wait until cancellation is effective. the lane will be stopped by the linda operation throwing an error 215 -- hard cancel: the lane will be interrupted from inside its current linda:receive() and won't return from it
192waitCancellation( h, "cancelled") 216 print "cancelling"
217 h:cancel()
193 218
194print "\n\n####################################################################\nbegin kill cancel test\n" 219 -- wait until cancellation is effective. the lane will be stopped by the linda operation throwing an error
195h = lanes.gen( "*", laneBody)( "busy", 50000000) -- start a pure Lua busy loop lane 220 waitCancellation( h, "cancelled")
221end
196 222
197-- wait 1/3s before cancelling the lane, before the busy loop can finish 223if not next(which_tests) or which_tests.kill then
198print "wait 0.3s" 224 remaining_tests.kill = nil
199linda:receive( 0.3, "yeah") 225 print "\n\n####################################################################\nbegin kill cancel test\n"
226 h = lanes.gen( "*", laneBody)( "busy", 50000000) -- start a pure Lua busy loop lane
200 227
201-- hard cancel with kill: the lane thread will be forcefully terminated 228 -- wait 1/3s before cancelling the lane, before the busy loop can finish
202h:cancel( true) 229 print "wait 0.3s"
230 linda:receive( 0.3, "yeah")
203 231
204-- wait until cancellation is effective. the lane will be stopped by the linda operation throwing an error 232 -- hard cancel with kill: the lane thread will be forcefully terminated. kill timeout is pthread-specific
205waitCancellation( h, "killed") 233 print "cancelling"
234 h:cancel( true, 1.0)
206 235
236 -- wait until cancellation is effective. the lane will be stopped by the linda operation throwing an error
237 waitCancellation( h, "killed")
238end
207--#################################################################### 239--####################################################################
208 240
209print "\ndone" 241local unknown_test, val = next(remaining_tests)
242assert(not unknown_test, tostring(unknown_test) .. " test is unknown")
210 243
244print "\nTHE END"
diff --git a/tests/errhangtest.lua b/tests/errhangtest.lua
index 7286fa5..d26dcef 100644
--- a/tests/errhangtest.lua
+++ b/tests/errhangtest.lua
@@ -4,10 +4,19 @@ local linda = lanes.linda()
4 4
5local coro = coroutine.create(function() end) 5local coro = coroutine.create(function() end)
6 6
7local fun = function() print "fun" end
8local t_in = { [fun] = fun, fun = fun }
9
10-- send a string
11print( pcall(linda.send,linda, 'test', "oh boy"))
12-- send a table that contains a function
13print( pcall(linda.send,linda, 'test', t_in))
7-- we are not allowed to send coroutines through a lanes 14-- we are not allowed to send coroutines through a lanes
8-- however, this should raise an error, not hang the program... 15-- however, this should raise an error, not hang the program...
9print( pcall(linda.send,linda, 'test', "oh boy"))
10print( pcall(linda.send,linda, 'test', coro)) 16print( pcall(linda.send,linda, 'test', coro))
11k,res = linda:receive('test') 17k,str = linda:receive('test') -- read the contents successfully sent
12print( res) 18print( str) -- "oh boy"
19k,t_out = linda:receive('test') -- read the contents successfully sent
20t_out.fun() -- "fun"
13-- linda:send( 'test', coro) 21-- linda:send( 'test', coro)
22print "SUCCESS" \ No newline at end of file
diff --git a/tests/fifo.lua b/tests/fifo.lua
index bef60d5..498f540 100644
--- a/tests/fifo.lua
+++ b/tests/fifo.lua
@@ -6,24 +6,27 @@
6 6
7local lanes = require "lanes".configure{shutdown_timeout=3,with_timers=true} 7local lanes = require "lanes".configure{shutdown_timeout=3,with_timers=true}
8 8
9local linda = lanes.linda( "atom") 9local atomic_linda = lanes.linda( "atom")
10local atomic_inc= lanes.genatomic( linda, "FIFO_n") 10local atomic_inc= lanes.genatomic( atomic_linda, "FIFO_n")
11
12local fifo_linda = lanes.linda( "fifo")
11 13
12assert( atomic_inc()==1) 14assert( atomic_inc()==1)
13assert( atomic_inc()==2) 15assert( atomic_inc()==2)
14 16
15local function FIFO() 17local function FIFO()
16 local my_channel= "FIFO"..atomic_inc() 18 local my_channel= "FIFO_"..atomic_inc()
17 19
18 return { 20 return {
19 -- Giving explicit 'nil' timeout allows numbers to be used as 'my_channel' 21 -- Giving explicit 'nil' timeout allows numbers to be used as 'my_channel'
20 -- 22 --
21 send = function(self, ...) 23 send = function(self, ...)
22 linda:send( nil, my_channel, ...) 24 fifo_linda:send( nil, my_channel, ...)
23 end, 25 end,
24 receive = function(self, timeout) 26 receive = function(self, timeout)
25 return linda:receive( timeout, my_channel) 27 return fifo_linda:receive( timeout, my_channel)
26 end 28 end,
29 channel = my_channel
27 } 30 }
28end 31end
29 32
@@ -36,11 +39,38 @@ A:send( 1,2,3,4,5)
36print "Sending to B.." 39print "Sending to B.."
37B:send( 'a','b','c') 40B:send( 'a','b','c')
38 41
42print "Dumping linda stats.. [1]" -- count everything
43for key,count in pairs(fifo_linda:count()) do
44 print("channel " .. key .. " contains " .. count .. " entries.")
45 -- print(i, key_count[1], key_count[2])
46end
47print "Dumping linda stats.. [2]" -- query count for known channels one at a time
48print("channel " .. A.channel .. " contains " .. fifo_linda:count(A.channel) .. " entries.")
49print("channel " .. B.channel .. " contains " .. fifo_linda:count(B.channel) .. " entries.")
50print "Dumping linda stats.. [3]" -- query counts for a predefined list of keys
51for key,count in pairs(fifo_linda:count(A.channel, B.channel)) do
52 print("channel " .. key .. " contains " .. count .. " entries.")
53 -- print(i, key_count[1], key_count[2])
54end
55print "Dumping linda stats.. [4]" -- count everything
56for key,contents in pairs(fifo_linda:dump()) do
57 print("channel " .. key .. ": limit=".. contents.limit, " first=" .. contents.first, " count=" .. contents.count)
58 for k,v in pairs(contents.fifo) do
59 print("[".. k.."] = " .. v)
60 end
61end
62
39print "Reading A.." 63print "Reading A.."
40print( A:receive( 1.0)) 64print( A:receive( 1.0))
65print( A:receive( 1.0))
66print( A:receive( 1.0))
67print( A:receive( 1.0))
68print( A:receive( 1.0))
41 69
42print "Reading B.." 70print "Reading B.."
43print( B:receive( 2.0)) 71print( B:receive( 2.0))
72print( B:receive( 2.0))
73print( B:receive( 2.0))
44 74
45-- Note: A and B can be passed between threads, or used as upvalues 75-- Note: A and B can be passed between threads, or used as upvalues
46-- by multiple threads (other parts will be copied but the 'linda' 76-- by multiple threads (other parts will be copied but the 'linda'
diff --git a/tests/keeper.lua b/tests/keeper.lua
index f8c915d..3333938 100644
--- a/tests/keeper.lua
+++ b/tests/keeper.lua
@@ -4,7 +4,34 @@
4-- Test program for Lua Lanes 4-- Test program for Lua Lanes
5-- 5--
6 6
7local lanes = require "lanes".configure{ with_timers = false, nb_keepers = 200} 7local lanes = require "lanes".configure{ with_timers = false, nb_keepers = 1, keepers_gc_threshold = 500}
8
9do
10 print "Linda names test:"
11 local unnamedLinda = lanes.linda()
12 local unnamedLinda2 = lanes.linda("")
13 local veeeerrrryyyylooongNamedLinda= lanes.linda( "veeeerrrryyyylooongNamedLinda", 1)
14 print(unnamedLinda, unnamedLinda2, veeeerrrryyyylooongNamedLinda)
15 print "GC deadlock test start"
16 -- store a linda in another linda (-> in a keeper)
17 unnamedLinda:set("here", lanes.linda("temporary linda"))
18 -- repeatedly add and remove stuff in the linda so that a GC happens during the keeper operation
19 for i = 1, 1000 do
20 for j = 1, 1000 do -- send 1000 tables
21 unnamedLinda:send("here", {"a", "table", "with", "some", "stuff"})
22 end
23 unnamedLinda:set("here") -- clear everything
24 end
25end
26print "collecting garbage"
27collectgarbage()
28print "GC deadlock test done"
29
30local print_id = 0
31local PRINT = function(...)
32 print_id = print_id + 1
33 print("main", print_id .. ".", ...)
34end
8 35
9local function keeper(linda) 36local function keeper(linda)
10 local mt= { 37 local mt= {
@@ -25,23 +52,49 @@ local A= keeper( lindaA )
25local lindaB= lanes.linda( "B", 2) 52local lindaB= lanes.linda( "B", 2)
26local B= keeper( lindaB ) 53local B= keeper( lindaB )
27 54
55local lindaC= lanes.linda( "C", 3)
56local C= keeper( lindaC )
57print("Created", lindaA, lindaB, lindaC)
58
28A.some= 1 59A.some= 1
29print( A.some ) 60PRINT("A.some == " .. A.some )
30assert( A.some==1 ) 61assert( A.some==1 )
31 62
32B.some= "hoo" 63B.some= "hoo"
64PRINT("B.some == " .. B.some )
33assert( B.some=="hoo" ) 65assert( B.some=="hoo" )
34assert( A.some==1 ) 66assert( A.some==1 )
67assert( C.some==nil )
35 68
36function lane() 69function lane()
70 local print_id = 0
71 local PRINT = function(...)
72 print_id = print_id + 1
73 print("lane", print_id .. ".", ...)
74 end
75
37 local a= keeper(lindaA) 76 local a= keeper(lindaA)
38 print( a.some ) 77 PRINT("a.some == " .. a.some )
39 assert( a.some==1 ) 78 assert( a.some==1 )
40 a.some= 2 79 a.some= 2
80 assert( a.some==2 )
81 PRINT("a.some == " .. a.some )
82
83 local c = keeper(lindaC)
84 assert( c.some==nil )
85 PRINT("c.some == " .. tostring(c.some))
86 c.some= 3
87 assert( c.some==3 )
88 PRINT("c.some == " .. c.some)
41end 89end
42 90
91PRINT("lane started")
43local h= lanes.gen( "io", lane )() 92local h= lanes.gen( "io", lane )()
44h:join() 93PRINT("lane joined:", h:join())
45 94
46print( A.some ) -- 2 95PRINT("A.some = " .. A.some )
47assert( A.some==2 ) 96assert( A.some==2 )
97PRINT("C.some = " .. C.some )
98assert( C.some==3 )
99lindaC:set("some")
100assert( C.some==nil ) \ No newline at end of file
diff --git a/tests/linda_perf.lua b/tests/linda_perf.lua
index a170b01..61b8f05 100644
--- a/tests/linda_perf.lua
+++ b/tests/linda_perf.lua
@@ -1,38 +1,62 @@
1local lanes = require "lanes" 1local lanes = require "lanes"
2lanes.configure{ with_timers = false} 2lanes.configure{ with_timers = false, keepers_gc_threshold=30000 }
3
4-- set TEST1, PREFILL1, FILL1, TEST2, PREFILL2, FILL2 from the command line
3 5
4-- Lua 5.1/5.2 compatibility 6-- Lua 5.1/5.2 compatibility
5local table_unpack = unpack or table.unpack 7local table_unpack = unpack or table.unpack
6 8
9local finalizer = function(err, stk)
10 if err == lanes.cancel_error then
11 -- note that we don't get the cancel_error when running wrapped inside a protected call if it doesn't rethrow it
12 print(" laneBody after cancel" )
13 elseif err then
14 print(" laneBody error: "..tostring(err))
15 else
16 print(" laneBody finalized")
17 end
18end
19
20--##################################################################################################
21
7-- this lane eats items in the linda one by one 22-- this lane eats items in the linda one by one
8local eater = function( l, loop) 23local eater = function( l, loop)
24 set_finalizer(finalizer)
9 -- wait for start signal 25 -- wait for start signal
10 l:receive( "go") 26 l:receive( "go")
11 -- eat data one by one 27 -- eat data one by one
12 for i = 1, loop do 28 for i = 1, loop do
13 local val, key = l:receive( "key") 29 local key, val = l:receive( "key")
14 --print( val) 30 -- print("eater:", val)
15 end 31 end
16 -- print "loop is over" 32 -- print "loop is over"
17 key, val = l:receive( "done") 33 key, val = l:receive( "done")
18 -- print( val) 34 print("eater: done ("..val..")")
19end 35end
20 36
37--##################################################################################################
38
21-- this lane eats items in the linda in batches 39-- this lane eats items in the linda in batches
22local batched = function( l, loop, batch) 40local gobbler = function( l, loop, batch)
41 set_finalizer(finalizer)
23 -- wait for start signal 42 -- wait for start signal
24 l:receive( "go") 43 l:receive( "go")
25 -- eat data in batches 44 -- eat data in batches
26 for i = 1, loop/batch do 45 for i = 1, loop/batch do
27 l:receive( l.batched, "key", batch) 46 l:receive( l.batched, "key", batch)
47 -- print("gobbler:", batch)
28 end 48 end
29 print "loop is over" 49 print "loop is over"
30 key, val = l:receive( "done") 50 key, val = l:receive( "done")
31 print( val) 51 print("gobbler: done ("..val..")")
32end 52end
33 53
54--##################################################################################################
55
34local lane_eater_gen = lanes.gen( "*", {priority = 3}, eater) 56local lane_eater_gen = lanes.gen( "*", {priority = 3}, eater)
35local lane_batched_gen = lanes.gen( "*", {priority = 3}, batched) 57local lane_gobbler_gen = lanes.gen( "*", {priority = 3}, gobbler)
58
59--##################################################################################################
36 60
37-- main thread writes data while a lane reads it 61-- main thread writes data while a lane reads it
38local function ziva( preloop, loop, batch) 62local function ziva( preloop, loop, batch)
@@ -46,7 +70,7 @@ local function ziva( preloop, loop, batch)
46 print( "stored " .. l:count( "key") .. " items in the linda before starting consumer lane") 70 print( "stored " .. l:count( "key") .. " items in the linda before starting consumer lane")
47 if batch > 0 then 71 if batch > 0 then
48 if l.batched then 72 if l.batched then
49 lane = lane_batched_gen( l, top, batch) 73 lane = lane_gobbler_gen( l, top, batch)
50 else 74 else
51 print "no batch support in this version of Lanes" 75 print "no batch support in this version of Lanes"
52 lane = lane_eater_gen( l, top) 76 lane = lane_eater_gen( l, top)
@@ -63,7 +87,9 @@ local function ziva( preloop, loop, batch)
63 for i = 1, batch do 87 for i = 1, batch do
64 table.insert( batch_values, i) 88 table.insert( batch_values, i)
65 end 89 end
90 local batch_send_log = "main: sending "..batch.." values"
66 local batch_send = function() 91 local batch_send = function()
92 -- print(batch_send_log)
67 l:send( "key", table_unpack( batch_values)) 93 l:send( "key", table_unpack( batch_values))
68 end 94 end
69 if loop > preloop then 95 if loop > preloop then
@@ -76,57 +102,35 @@ local function ziva( preloop, loop, batch)
76 return lanes.now_secs() - t1 102 return lanes.now_secs() - t1
77end 103end
78 104
105--##################################################################################################
106
107TEST1 = TEST1 or 1000
108PREFILL1 = PREFILL1 or 10000
109FILL1 = FILL1 or 2000000
110
79local tests1 = 111local tests1 =
80{ 112{
81 { 10000, 2000000, 0}, 113 { PREFILL1, FILL1, 0},
82 { 10000, 2000000, 1}, 114 { PREFILL1, FILL1, 1},
83 { 10000, 2000000, 2}, 115 { PREFILL1, FILL1, 2},
84 { 10000, 2000000, 3}, 116 { PREFILL1, FILL1, 3},
85 { 10000, 2000000, 5}, 117 { PREFILL1, FILL1, 5},
86 { 10000, 2000000, 8}, 118 { PREFILL1, FILL1, 8},
87 { 10000, 2000000, 13}, 119 { PREFILL1, FILL1, 13},
88 { 10000, 2000000, 21}, 120 { PREFILL1, FILL1, 21},
89 { 10000, 2000000, 44}, 121 { PREFILL1, FILL1, 44},
122 { PREFILL1, FILL1, 65},
90} 123}
91print "############################################\ntests #1" 124print "############################################ tests #1"
92for k, v in pairs( tests1) do 125for i, v in ipairs( tests1) do
126 if i > TEST1 then break end
93 local pre, loop, batch = v[1], v[2], v[3] 127 local pre, loop, batch = v[1], v[2], v[3]
94 print( "testing", pre, loop, batch) 128 print("-------------------------------------------------\n")
95 print( pre, loop, batch, "duration = " .. ziva( pre, loop, batch) .. "\n") 129 print("START", "prefill="..pre, "fill="..loop, "batch="..batch)
130 print("DURATION = " .. ziva( pre, loop, batch) .. "\n")
96end 131end
97 132
98--[[ 133--##################################################################################################
99 V 2.1.0:
100 ziva( 20000, 0) -> 4s ziva( 10000, 20000) -> 3s
101 ziva( 30000, 0) -> 8s ziva( 20000, 30000) -> 7s
102 ziva( 40000, 0) -> 15s ziva( 30000, 40000) -> 15s
103 ziva( 50000, 0) -> 24s ziva( 40000, 50000) -> 23s
104 ziva( 60000, 0) -> 34s ziva( 50000, 60000) -> 33s
105
106 SIMPLIFIED:
107 ziva( 20000, 0) -> 4s ziva( 10000, 20000) -> 3s
108 ziva( 30000, 0) -> 9s ziva( 20000, 30000) -> 8s
109 ziva( 40000, 0) -> 15s ziva( 30000, 40000) -> 15s
110 ziva( 50000, 0) -> 25s ziva( 40000, 50000) -> 24s
111 ziva( 60000, 0) -> 35s ziva( 50000, 60000) -> 35s
112
113 FIFO:
114 ziva( 2000000, 0) -> 9s ziva( 1000000, 2000000) -> 33s
115 ziva( 3000000, 0) -> 14s ziva( 2000000, 3000000) -> 40s
116 ziva( 4000000, 0) -> 20s ziva( 3000000, 4000000) -> 27s
117 ziva( 5000000, 0) -> 24s ziva( 4000000, 5000000) -> 42s
118 ziva( 6000000, 0) -> 29s ziva( 5000000, 6000000) -> 55s
119
120 FIFO BATCHED:
121 ziva( 4000000, 0, 1) -> 20s
122 ziva( 4000000, 0, 2) -> 11s
123 ziva( 4000000, 0, 3) -> 7s
124 ziva( 4000000, 0, 5) -> 5s
125 ziva( 4000000, 0, 8) -> 3s
126 ziva( 4000000, 0, 13) -> 3s
127 ziva( 4000000, 0, 21) -> 3s
128 ziva( 4000000, 0, 44) -> 2s
129]]
130 134
131-- sequential write/read (no parallelization involved) 135-- sequential write/read (no parallelization involved)
132local function ziva2( preloop, loop, batch) 136local function ziva2( preloop, loop, batch)
@@ -159,7 +163,7 @@ local function ziva2( preloop, loop, batch)
159 for i = 1, preloop, step do 163 for i = 1, preloop, step do
160 batch_send() 164 batch_send()
161 end 165 end
162 print( "stored " .. (l:count( "key") or 0) .. " items in the linda before starting consumer lane") 166 print( "stored " .. (l:count( "key") or 0) .. " items in the linda before starting the alternating reads and writes")
163 -- loop that alternatively sends and reads data off the linda 167 -- loop that alternatively sends and reads data off the linda
164 if loop > preloop then 168 if loop > preloop then
165 for i = preloop + 1, loop, step do 169 for i = preloop + 1, loop, step do
@@ -169,40 +173,39 @@ local function ziva2( preloop, loop, batch)
169 end 173 end
170 -- here, we have preloop elements still waiting inside the linda 174 -- here, we have preloop elements still waiting inside the linda
171 for i = 1, preloop, step do 175 for i = 1, preloop, step do
172 batch_read() 176 batch_read()
173 end 177 end
174 return lanes.now_secs() - t1 178 return lanes.now_secs() - t1
175end 179end
176 180
181--##################################################################################################
182
183TEST2 = TEST2 or 1000
184PREFILL2 = PREFILL2 or 0
185FILL2 = FILL2 or 4000000
186
177local tests2 = 187local tests2 =
178{ 188{
179 -- prefill, then consume everything 189 { PREFILL2, FILL2},
180 --[[ 190 { PREFILL2, FILL2, 1},
181 { 4000000, 0}, 191 { PREFILL2, FILL2, 2},
182 { 4000000, 0, 1}, 192 { PREFILL2, FILL2, 3},
183 { 4000000, 0, 2}, 193 { PREFILL2, FILL2, 5},
184 { 4000000, 0, 3}, 194 { PREFILL2, FILL2, 8},
185 { 4000000, 0, 5}, 195 { PREFILL2, FILL2, 13},
186 { 4000000, 0, 8}, 196 { PREFILL2, FILL2, 21},
187 { 4000000, 0, 13}, 197 { PREFILL2, FILL2, 44},
188 { 4000000, 0, 21}, 198 { PREFILL2, FILL2, 65},
189 { 4000000, 0, 44},
190 --]]
191 -- alternatively fill and consume
192 { 0, 4000000},
193 { 0, 4000000, 1},
194 { 0, 4000000, 2},
195 { 0, 4000000, 3},
196 { 0, 4000000, 5},
197 { 0, 4000000, 8},
198 { 0, 4000000, 13},
199 { 0, 4000000, 21},
200 { 0, 4000000, 44},
201} 199}
202 200
203print "\n############################################\ntests #2" 201print "############################################ tests #2"
204for k, v in pairs( tests2) do 202for i, v in ipairs( tests2) do
203 if i > TEST2 then break end
205 local pre, loop, batch = v[1], v[2], v[3] 204 local pre, loop, batch = v[1], v[2], v[3]
206 print( "testing", pre, loop, batch) 205 print("-------------------------------------------------\n")
207 print( pre, loop, batch, "duration = " .. ziva2( pre, loop, batch) .. "\n") 206 print("START", "prefill="..pre, "fill="..loop, "batch="..(batch or "no"))
207 print("DURATION = " .. ziva2( pre, loop, batch) .. "\n")
208end 208end
209
210print "############################################"
211print "THE END" \ No newline at end of file
diff --git a/tests/protect_allocator.lua b/tests/protect_allocator.lua
index 593261e..5cbb1d8 100644
--- a/tests/protect_allocator.lua
+++ b/tests/protect_allocator.lua
@@ -46,5 +46,8 @@ for i = 1, COUNT do
46end 46end
47 47
48-- wait for completion 48-- wait for completion
49print "wait for completion"
49linda:receive( linda.batched, "key", COUNT) 50linda:receive( linda.batched, "key", COUNT)
51print "waiting a bit more ..."
52linda:receive( 1, "foo")
50print "SUCCESS" 53print "SUCCESS"
diff --git a/tests/timer.lua b/tests/timer.lua
index ec23cee..73ecb93 100644
--- a/tests/timer.lua
+++ b/tests/timer.lua
@@ -18,13 +18,14 @@ end
18 18
19local T1= "1s" -- these keys can be anything... 19local T1= "1s" -- these keys can be anything...
20local T2= "5s" 20local T2= "5s"
21local PING_DURATION = 20
21 22
22local step= {} 23local step= {}
23 24
24lanes.timer( linda, T1, 1.0, 1.0 ) 25lanes.timer( linda, T1, 1.0, 1.0 )
25step[T1]= 1.0 26step[T1]= 1.0
26 27
27PRINT( "\n*** Timers every second (not synced to wall clock) ***\n" ) 28PRINT( "\n*** Starting 1s Timer (not synced to wall clock) ***\n" )
28 29
29local v_first 30local v_first
30local v_last= {} -- { [channel]= num } 31local v_last= {} -- { [channel]= num }
@@ -46,14 +47,15 @@ while true do
46 -- do not make measurements, first round is not 5secs due to wall clock adjustment 47 -- do not make measurements, first round is not 5secs due to wall clock adjustment
47 T2_first_round= false 48 T2_first_round= false
48 else 49 else
49 assert( math.abs(v-v_last[channel]- step[channel]) < 0.02 ) 50 local dt = math.abs(v-v_last[channel]- step[channel])
51 assert( dt < 0.02, "channel " .. channel .. " is late: " .. dt)
50 end 52 end
51 end 53 end
52 54
53 if not v_first then 55 if not v_first then
54 v_first= v 56 v_first= v
55 elseif v-v_first > 3.0 and (not step[T2]) then 57 elseif v-v_first > 3.0 and (not step[T2]) then
56 PRINT( "\n*** Adding timers every 5 second (synced to wall clock) ***\n" ) 58 PRINT( "\n*** Starting 5s timer (synced to wall clock) ***\n" )
57 59
58 -- The first event can be in the past (just cut seconds down to 5s) 60 -- The first event can be in the past (just cut seconds down to 5s)
59 -- 61 --
@@ -63,7 +65,7 @@ while true do
63 lanes.timer( linda, T2, date, 5.0 ) 65 lanes.timer( linda, T2, date, 5.0 )
64 step[T2]= 5.0 66 step[T2]= 5.0
65 67
66 elseif v-v_first > 10 then -- exit condition 68 elseif v-v_first > PING_DURATION then -- exit condition
67 break 69 break
68 end 70 end
69 v_last[channel]= v 71 v_last[channel]= v
@@ -80,7 +82,7 @@ PRINT( "\n*** Listing timers ***\n" )
80local r = lanes.timers() -- list of {linda, key, {}} 82local r = lanes.timers() -- list of {linda, key, {}}
81for _,t in ipairs( r) do 83for _,t in ipairs( r) do
82 local linda, key, timer = t[1], t[2], t[3] 84 local linda, key, timer = t[1], t[2], t[3]
83 print( tostring( linda), key, timer[1], timer[2]) 85 print( tostring( linda), key, timer[1], timer[2])
84end 86end
85 87
86 88