aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorPeter Drahoš <drahosp@gmail.com>2010-10-01 03:22:32 +0200
committerPeter Drahoš <drahosp@gmail.com>2010-10-01 03:22:32 +0200
commit89d9c98af1ac352ba4d49d660e61b0853d6e1a86 (patch)
tree15c56d2ce66b4ab147171c0f674cdb4a435ff13f /tests
downloadlanes-89d9c98af1ac352ba4d49d660e61b0853d6e1a86.tar.gz
lanes-89d9c98af1ac352ba4d49d660e61b0853d6e1a86.tar.bz2
lanes-89d9c98af1ac352ba4d49d660e61b0853d6e1a86.zip
Import to git
Diffstat (limited to 'tests')
-rw-r--r--tests/argtable.lua38
-rw-r--r--tests/assert.lua318
-rw-r--r--tests/atomic.lua18
-rw-r--r--tests/basic.lua331
-rw-r--r--tests/cyclic.lua64
-rw-r--r--tests/ehynes.lua52
-rw-r--r--tests/error.lua47
-rw-r--r--tests/fibonacci.lua75
-rw-r--r--tests/fifo.lua43
-rw-r--r--tests/finalizer.lua81
-rw-r--r--tests/hangtest.lua26
-rw-r--r--tests/irayo_closure.lua35
-rw-r--r--tests/irayo_recursive.lua18
-rw-r--r--tests/keeper.lua47
-rw-r--r--tests/launchtest.lua78
-rw-r--r--tests/objects.lua76
-rw-r--r--tests/perftest.lua184
-rw-r--r--tests/recursive.lua21
-rw-r--r--tests/require.lua30
-rw-r--r--tests/timer.lua93
20 files changed, 1675 insertions, 0 deletions
diff --git a/tests/argtable.lua b/tests/argtable.lua
new file mode 100644
index 0000000..5ed5d4e
--- /dev/null
+++ b/tests/argtable.lua
@@ -0,0 +1,38 @@
1--
2-- ARGTABLE.LUA Copyright (c) 2007, Asko Kauppi <akauppi@gmail.com>
3--
4-- Command line parameter parsing
5--
6-- NOTE: Wouldn't hurt having such a service built-in to Lua...? :P
7--
8
9local m= {}
10
11-- tbl= argtable(...)
12--
13-- Returns a table with 1..N indices being 'value' parameters, and any
14-- "-flag[=xxx]" or "--flag[=xxx]" parameters set to { flag=xxx/true }.
15--
16-- In other words, makes handling command line parameters simple. :)
17--
18-- 15 --> { 15 }
19-- -20 --> { -20 }
20-- -a --> { ['a']=true }
21-- --some=15 --> { ['some']=15 }
22-- --more=big --> { ['more']='big' }
23--
24function m.argtable(...)
25 local ret= {}
26 for i=1,select('#',...) do
27 local v= select(i,...)
28 local flag,val= string.match( v, "^%-+([^=]+)%=?(.*)" )
29 if flag and not tonumber(v) then
30 ret[flag]= (val=="") and true or tonumber(val) or val
31 else
32 table.insert( ret, v ) -- 1..N
33 end
34 end
35 return ret
36end
37
38return m
diff --git a/tests/assert.lua b/tests/assert.lua
new file mode 100644
index 0000000..85febfb
--- /dev/null
+++ b/tests/assert.lua
@@ -0,0 +1,318 @@
1--
2-- ASSERT.LUA Copyright (c) 2006-07, <akauppi@gmail.com>
3--
4-- Converting the Lua 'assert' function into a namespace table (without
5-- breaking compatibility with the basic 'assert()' calling).
6--
7-- This module allows shorthand use s.a. 'assert.table()' for asserting
8-- variable types, and is also being used by Lua-super constraints system
9-- for testing function parameter & return types.
10--
11-- All in all, a worthy module and could be part of Lua future versions.
12--
13-- Note: the 'assert' table is available for your own assertions, too. Just add
14-- more functions s.a. 'assert.myobj()' to check for custom invariants.
15-- They will then be available for the constraints check, too.
16--
17-- Author: <akauppi@gmail.com>
18--
19--[[
20/******************************************************************************
21* Lua 5.1.1 support and extension functions (assert.lua)
22*
23* Copyright (C) 2006-07, Asko Kauppi.
24*
25* NOTE: This license concerns only the particular source file; not necessarily
26* the project with which it has been delivered (the project may have a more
27* restrictive license, s.a. [L]GPL).
28*
29* Permission is hereby granted, free of charge, to any person obtaining
30* a copy of this software and associated documentation files (the
31* "Software"), to deal in the Software without restriction, including
32* without limitation the rights to use, copy, modify, merge, publish,
33* distribute, sublicense, and/or sell copies of the Software, and to
34* permit persons to whom the Software is furnished to do so, subject to
35* the following conditions:
36*
37* The above copyright notice and this permission notice shall be
38* included in all copies or substantial portions of the Software.
39*
40* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
41* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
42* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
43* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
44* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
45* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
46* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
47******************************************************************************/
48]]--
49
50local m= { _info= { MODULE= "Assert.* functions for constraints, and unit testing",
51 AUTHOR= "akauppi@gmail.com",
52 VERSION= 20070603, -- last change (yyyymmdd)
53 LICENSE= "MIT/X11" } }
54
55-- Global changes:
56-- 'assert' redefined, in a backwards compatible way
57--
58-- Module functions:
59-- none
60
61assert( type(assert) == "function" ) -- system assert function
62
63-----
64-- Integer range: INT_MIN..INT_MAX
65--
66local function try_maxint( n )
67 return (n > n-1) and n-1 -- false when outside the integer range
68end
69
70local INT_MAX=
71 try_maxint( 2^64 ) or
72 try_maxint( 2^32 ) or
73 try_maxint( 2^24 ) or -- float (24-bit mantissa)
74 assert( false )
75
76local INT_MIN= -(INT_MAX+1)
77
78
79---=== assert.*() ===---
80
81local at_msg= "type assertion error" -- TBD: better messages, about that exact situation
82local av_msg= "value assertion error"
83
84-- void= _assert( val [, msg_str [, lev_uint]] )
85--
86local function _assert( cond, msg, lev )
87 -- original 'assert' provides no level override, so we use 'error'.
88 --
89 if not cond then
90 error( msg or "assertion failed!", (lev or 1)+1 )
91 end
92end
93
94-- Note: following code uses the _new_ 'assert()' by purpose, since it provides
95-- a level override (original doesn't)
96--
97local function assert_v( v0 )
98 return function(v,msg)
99 _assert( v == v0, msg or av_msg, 2 )
100 return v
101 end
102end
103local function assert_t( str )
104 return function(v,msg)
105 _assert( type(v) == str, msg or at_msg, 2 )
106 return v
107 end
108end
109local function assert_t2( str )
110 return function(v,subtype,msg)
111 local t,st= type(v)
112 _assert( t==str and ((not subtype) or (st==subtype)),
113 msg or at_msg, 2 )
114 return v
115 end
116end
117
118assert=
119 {
120 __call= function(_,v,msg) -- plain 'assert()' (compatibility)
121 if v then return v end
122 _assert( v, msg, 2 )
123 end,
124
125 -- Hopefully, Lua will allow use of 'nil', 'function' and other reserved words as table
126 -- shortcuts in the future (5.1.1 does not).
127 --
128 ["nil"]= assert_v( nil ),
129 boolean= assert_t "boolean",
130 table= assert_t2 "table",
131 ["function"]= assert_t "function",
132 userdata= assert_t2 "userdata",
133
134 string= function( v, msg )
135 local s= tostring(v)
136 _assert( s, msg or at_msg, 2 )
137 return v
138 end,
139
140 char= function( v, msg )
141 -- 'char' is _not_ doing int->string conversion
142 _assert( type(v)=="string" and v:len()==1, msg or at_msg, 2 )
143 return v
144 end,
145
146 number= function( v, msg )
147 _assert( tonumber(v), msg or at_msg, 2 )
148 return v
149 end,
150
151 int= function( v, msg )
152 local n= tonumber(v)
153 _assert( n and (n >= INT_MIN) and (n <= INT_MAX) and math.floor(n) == n,
154 msg or at_msg, 2 )
155 return v
156 end,
157
158 uint= function( v, msg )
159 local n= tonumber(v)
160 -- unsigned integer upper range is the same as integers' (there's no
161 -- real unsigned within the Lua)
162 _assert( n and (n >= 0) and (n <= INT_MAX) and math.floor(n) == n,
163 msg or at_msg, 2 )
164 return v
165 end,
166
167 ['true']= assert_v( true ),
168 ['false']= assert_v( false ),
169
170 string_or_table= function( v, msg )
171 assert( tostring(v) or type(v)=="table", msg or at_msg, 2 )
172 return v
173 end,
174
175 number_or_string= function( v, msg )
176 assert( tonumber(v) or type(v)=="table", msg or at_msg, 2 )
177 return v
178 end,
179
180 any= function( v, msg )
181 assert( v ~= nil, msg or av_msg, 2 )
182 return v
183 end,
184
185 -- Range assertion, with extra parameters per instance
186 --
187 -- Note: values may be of _any_ type that can do >=, <= comparisons.
188 --
189 range= function( lo, hi )
190 _assert( lo and hi and lo <= hi, "Bad limits", 2 )
191 -- make sure the limits make sense (just once)
192
193 return function(v,msg,lev)
194 if ( (lo and v<lo) or (hi and v>hi) ) then
195 msg= msg or "not in range: ("..(lo or "")..","..(hi or "")..")"
196 _assert( false, msg, 2 )
197 end
198 return v
199 end
200 end,
201
202 -- Table contents assertion
203 -- - no unknown (non-numeric) keys are allowed
204 -- - numeric keys are ignored
205 --
206 -- Constraints patch should point to this, when using the ":{ ... }" constraint.
207 --
208 ["{}"]= function( tbl )
209
210 -- check all keys in 't' (including numeric, if any) that they do exist,
211 -- and carry the right type
212 --
213 local function subf1(v,t,msg,lev)
214 _assert(lev)
215 for k,f in pairs(t) do
216 -- 'f' is an assert function, or subtable
217 local ft= type(f)
218 if ft=="function" then
219 f( v[k], msg, lev+1 )
220 elseif ft=="table" then
221 _assert( type(v[k])=="table", msg or "no subtable "..tostring(k), lev+1 )
222 subf1( v[k], f, msg, lev+1 )
223 else
224 error( "Bad constraints table for '"..tostring(k).."'! (not a function)", lev+1 )
225 end
226 end
227 end
228
229 -- check there are no other (non-numeric) keys in 'v'
230 local function subf2(v,t,msg,lev)
231 _assert(lev)
232 for k,vv in pairs(v) do
233 if type(k)=="number" then
234 -- skip them
235 elseif not t[k] then
236 _assert( false, msg or "extra field: '"..tostring(k).."'", lev+1 )
237 elseif type(vv)=="table" then
238 subf2( vv, t[k], msg, lev+1 )
239 end
240 end
241 end
242
243 _assert( type(tbl)=="table", "Wrong parameter to assert['{}']" )
244
245 return function( v, msg, lev )
246 lev= (lev or 1)+1
247 _assert( type(v)=="table" ,msg, lev )
248 subf1( v, tbl, msg, lev )
249 subf2( v, tbl, msg, lev )
250 return v
251 end
252 end,
253
254 -- ...
255}
256setmetatable( assert, assert )
257
258assert.void= assert["nil"]
259
260
261-----
262-- void= assert.fails( function [,err_msg_str] )
263--
264-- Special assert function, to make sure the call within it fails, and gives a
265-- specific error message (to be used in unit testing).
266--
267function assert.fails( func_block, err_msg )
268 --
269 local st,err= pcall( func_block )
270 if st then
271 _assert( false, "Block expected to fail, but didn't.", 2 )
272 elseif err_msg and err ~= err_msg then
273 _assert( false, "Failed with wrong error message: \n"..
274 "'"..err.."'\nexpected: '"..err_msg.."'", 2 )
275 end
276end
277
278
279-----
280-- void= assert.failsnot( function [,err_msg_str] )
281--
282-- Similar to 'assert.fails' but expects the code to survive.
283--
284function assert.failsnot( func_block, err_msg )
285 --
286 local st,err= pcall( func_block )
287 if not st then
288 _assert( false, "Block expected NOT to fail, but did."..
289 (err and "\n\tError: '"..err.."'" or ""), 2 )
290 end
291end
292
293
294-----
295-- void= assert.nilerr( function [,err_msg_str] )
296--
297-- Expects the function to return with 'nil,err' failure code, with
298-- optionally error string matching. Similar to --> 'assert.fails()'
299--
300function assert.nilerr( func_block, err_msg )
301 --
302 local v,err= func_block()
303 _assert( v==nil, "Expected to return nil, but didn't: "..tostring(v), 2 )
304 if err_msg and err ~= err_msg then
305 _assert( false, "Failed with wrong error message: \n"..
306 "'"..err.."'\nexpected: '"..err_msg.."'", 2 )
307 end
308end
309
310
311-- Sanity check
312--
313assert( true )
314assert.fails( function() assert( false ) end )
315assert.fails( function() assert( nil ) end )
316
317
318return m -- just info
diff --git a/tests/atomic.lua b/tests/atomic.lua
new file mode 100644
index 0000000..a027453
--- /dev/null
+++ b/tests/atomic.lua
@@ -0,0 +1,18 @@
1--
2-- ATOMIC.LUA
3--
4-- Test program for Lua Lanes
5--
6
7require "lanes"
8
9local linda= lanes.linda()
10local key= "$"
11
12local f= lanes.genatomic( linda, key, 5 )
13
14local v
15v= f(); print(v); assert(v==6)
16v= f(-0.5); print(v); assert(v==5.5)
17
18v= f(-10); print(v); assert(v==-4.5)
diff --git a/tests/basic.lua b/tests/basic.lua
new file mode 100644
index 0000000..ee31ed1
--- /dev/null
+++ b/tests/basic.lua
@@ -0,0 +1,331 @@
1--
2-- BASIC.LUA Copyright (c) 2007-08, Asko Kauppi <akauppi@gmail.com>
3--
4-- Selftests for Lua Lanes
5--
6-- To do:
7-- - ...
8--
9
10require "lanes"
11require "assert" -- assert.fails()
12
13local lanes_gen= assert( lanes.gen )
14local lanes_linda= assert( lanes.linda )
15
16local tostring= assert( tostring )
17
18local function PRINT(...)
19 local str=""
20 for i=1,select('#',...) do
21 str= str..tostring(select(i,...)).."\t"
22 end
23 if io then
24 io.stderr:write(str.."\n")
25 end
26end
27
28
29---=== Local helpers ===---
30
31local tables_match
32
33-- true if 'a' is a subtable of 'b'
34--
35local function subtable( a, b )
36 --
37 assert( type(a)=="table" and type(b)=="table" )
38
39 for k,v in pairs(b) do
40 if type(v)~=type(a[k]) then
41 return false -- not subtable (different types, or missing key)
42 elseif type(v)=="table" then
43 if not tables_match(v,a[k]) then return false end
44 else
45 if a[k] ~= v then return false end
46 end
47 end
48 return true -- is a subtable
49end
50
51-- true when contents of 'a' and 'b' are identific
52--
53tables_match= function( a, b )
54 return subtable( a, b ) and subtable( b, a )
55end
56
57
58---=== Tasking (basic) ===---
59
60local function task( a, b, c )
61 --error "111" -- testing error messages
62 assert(hey)
63 local v=0
64 for i=a,b,c do
65 v= v+i
66 end
67 return v, hey
68end
69
70local task_launch= lanes_gen( "", { globals={hey=true} }, task )
71 -- base stdlibs, normal priority
72
73-- 'task_launch' is a factory of multithreaded tasks, we can launch several:
74
75local lane1= task_launch( 100,200,3 )
76local lane2= task_launch( 200,300,4 )
77
78-- At this stage, states may be "pending", "running" or "done"
79
80local st1,st2= lane1.status, lane2.status
81PRINT(st1,st2)
82assert( st1=="pending" or st1=="running" or st1=="done" )
83assert( st2=="pending" or st2=="running" or st2=="done" )
84
85-- Accessing results ([1..N]) pends until they are available
86--
87PRINT("waiting...")
88local v1, v1_hey= lane1[1], lane1[2]
89local v2, v2_hey= lane2[1], lane2[2]
90
91PRINT( v1, v1_hey )
92assert( v1_hey == true )
93
94PRINT( v2, v2_hey )
95assert( v2_hey == true )
96
97assert( lane1.status == "done" )
98assert( lane1.status == "done" )
99
100
101---=== Tasking (cancelling) ===---
102
103local task_launch2= lanes_gen( "", { cancelstep=100, globals={hey=true} }, task )
104
105local N=999999999
106local lane9= task_launch2(1,N,1) -- huuuuuuge...
107
108-- Wait until state changes "pending"->"running"
109--
110local st
111local t0= os.time()
112while os.time()-t0 < 5 do
113 st= lane9.status
114 io.stderr:write( (i==1) and st.." " or '.' )
115 if st~="pending" then break end
116end
117PRINT(" "..st)
118
119if st=="error" then
120 local _= lane9[0] -- propagate the error here
121end
122if st=="done" then
123 error( "Looping to "..N.." was not long enough (cannot test cancellation)" )
124end
125assert( st=="running" )
126
127lane9:cancel()
128
129local t0= os.time()
130while os.time()-t0 < 5 do
131 st= lane9.status
132 io.stderr:write( (i==1) and st.." " or '.' )
133 if st~="running" then break end
134end
135PRINT(" "..st)
136assert( st == "cancelled" )
137
138
139---=== Communications ===---
140
141local function WR(...) io.stderr:write(...) end
142
143local chunk= function( linda )
144
145 local function receive() return linda:receive( "->" ) end
146 local function send(...) linda:send( "<-", ... ) end
147
148 WR( "Lane starts!\n" )
149
150 local v
151 v=receive(); WR( v.." received\n" ); assert( v==1 )
152 v=receive(); WR( v.." received\n" ); assert( v==2 )
153 v=receive(); WR( v.." received\n" ); assert( v==3 )
154
155 send( 1,2,3 ); WR( "1,2,3 sent\n" )
156 send 'a'; WR( "'a' sent\n" )
157 send { 'a', 'b', 'c', d=10 }; WR( "{'a','b','c',d=10} sent\n" )
158
159 v=receive(); WR( v.." received\n" ); assert( v==4 )
160
161 WR( "Lane ends!\n" )
162end
163
164local linda= lanes_linda()
165assert( type(linda) == "userdata" )
166 --
167 -- ["->"] master -> slave
168 -- ["<-"] slave <- master
169
170local function PEEK() return linda:get("<-") end
171local function SEND(...) linda:send( "->", ... ) end
172local function RECEIVE() return linda:receive( "<-" ) end
173
174local t= lanes_gen("io",chunk)(linda) -- prepare & launch
175
176SEND(1); WR( "1 sent\n" )
177SEND(2); WR( "2 sent\n" )
178for i=1,100 do
179 WR "."
180 assert( PEEK() == nil ) -- nothing coming in, yet
181end
182SEND(3); WR( "3 sent\n" )
183
184local a,b,c= RECEIVE(), RECEIVE(), RECEIVE()
185 WR( a..", "..b..", "..c.." received\n" )
186assert( a==1 and b==2 and c==3 )
187
188local a= RECEIVE(); WR( a.." received\n" )
189assert( a=='a' )
190
191local a= RECEIVE(); WR( type(a).." received\n" )
192assert( tables_match( a, {'a','b','c',d=10} ) )
193
194assert( PEEK() == nil )
195SEND(4)
196
197
198---=== Stdlib naming ===---
199
200local function io_os_f()
201 assert(io)
202 assert(os)
203 assert(print)
204 return true
205end
206
207local f1= lanes_gen( "io,os", io_os_f ) -- any delimiter will do
208local f2= lanes_gen( "io+os", io_os_f )
209local f3= lanes_gen( "io,os,base", io_os_f )
210
211assert.fails( function() lanes_gen( "xxx", io_os_f ) end )
212
213assert( f1()[1] )
214assert( f2()[1] )
215assert( f3()[1] )
216
217
218---=== Comms criss cross ===---
219
220-- We make two identical lanes, which are using the same Linda channel.
221--
222local tc= lanes_gen( "io",
223 function( linda, ch_in, ch_out )
224
225 local function STAGE(str)
226 io.stderr:write( ch_in..": "..str.."\n" )
227 linda:send( nil, ch_out, str )
228 local v= linda:receive( nil, ch_in )
229 assert(v==str)
230 end
231 STAGE("Hello")
232 STAGE("I was here first!")
233 STAGE("So waht?")
234 end
235)
236
237local linda= lanes_linda()
238
239local a,b= tc(linda, "A","B"), tc(linda, "B","A") -- launching two lanes, twisted comms
240
241local _= a[1],b[1] -- waits until they are both ready
242
243
244---=== Receive & send of code ===---
245
246local upvalue="123"
247
248local function chunk2( linda )
249 assert( upvalue=="123" ) -- even when running as separate thread
250
251 -- function name & line number should be there even as separate thread
252 --
253 local info= debug.getinfo(1) -- 1 = us
254 --
255 for k,v in pairs(info) do PRINT(k,v) end
256
257 assert( info.nups == 2 ) -- one upvalue + PRINT
258 assert( info.what == "Lua" )
259
260 --assert( info.name == "chunk2" ) -- name does not seem to come through
261 assert( string.match( info.source, "^@tests[/\\]basic.lua$" ) )
262 assert( string.match( info.short_src, "^tests[/\\]basic.lua$" ) )
263
264 -- These vary so let's not be picky (they're there..)
265 --
266 assert( info.linedefined > 200 ) -- start of 'chunk2'
267 assert( info.currentline > info.linedefined ) -- line of 'debug.getinfo'
268 assert( info.lastlinedefined > info.currentline ) -- end of 'chunk2'
269
270 local func,k= linda:receive( "down" )
271 assert( type(func)=="function" )
272 assert( k=="down" )
273
274 func(linda)
275
276 local str= linda:receive( "down" )
277 assert( str=="ok" )
278
279 linda:send( "up", function() return ":)" end, "ok2" )
280end
281
282local linda= lanes.linda()
283
284local t2= lanes_gen( "debug,string", chunk2 )(linda) -- prepare & launch
285
286linda:send( "down", function(linda) linda:send( "up", "ready!" ) end,
287 "ok" )
288
289-- wait to see if the tiny function gets executed
290--
291local s= linda:receive( "up" )
292PRINT(s)
293assert( s=="ready!" )
294
295-- returns of the 'chunk2' itself
296--
297local f= linda:receive( "up" )
298assert( type(f)=="function" )
299
300local s2= f()
301assert( s2==":)" )
302
303local ok2= linda:receive( "up" )
304assert( ok2 == "ok2" )
305
306
307---=== :join test ===---
308
309-- NOTE: 'unpack()' cannot be used on the lane handle; it will always return nil
310-- (unless [1..n] has been read earlier, in which case it would seemingly
311-- work).
312
313local S= lanes_gen( "table",
314 function(arg)
315 aux= {}
316 for i, v in ipairs(arg) do
317 table.insert (aux, 1, v)
318 end
319 return unpack(aux)
320end )
321
322h= S { 12, 13, 14 } -- execution starts, h[1..3] will get the return values
323
324local a,b,c,d= h:join()
325assert(a==14)
326assert(b==13)
327assert(c==12)
328assert(d==nil)
329
330--
331io.stderr:write "Done! :)\n"
diff --git a/tests/cyclic.lua b/tests/cyclic.lua
new file mode 100644
index 0000000..06452bd
--- /dev/null
+++ b/tests/cyclic.lua
@@ -0,0 +1,64 @@
1--
2-- CYCLIC.LUA
3--
4-- Test program for Lua Lanes
5--
6
7require "lanes"
8
9local table_concat= assert(table.concat)
10
11local function WR(str,...)
12 for i=1,select('#',...) do
13 str= str.."\t"..tostring( select(i,...) )
14 end
15 io.stderr:write( str..'\n' )
16end
17
18local function same(k,l)
19 return k==l and "same" or ("NOT SAME: "..k.." "..l)
20end
21
22local a= {}
23local b= {a}
24a[1]= b
25
26-- Getting the tables as upvalues should still have the <-> linkage
27--
28local function lane1()
29 WR( "Via upvalue: ", same(a,b[1]), same(a[1],b) )
30 assert( a[1]==b )
31 assert( b[1]==a )
32end
33local L1= lanes.gen( "io", lane1 )()
34 -- ...running
35
36-- Getting the tables as parameters should also keep the linkage
37--
38local function lane2( aa, bb )
39 WR( "Via parameters:", same(aa,bb[1]), same(aa[1],bb) )
40 assert( aa[1]==bb )
41 assert( bb[1]==aa )
42end
43local L2= lanes.gen( "io", lane2 )( a, b )
44 -- ...running
45
46-- Really unnecessary, but let's try a directly recursive table
47--
48c= {}
49c.a= c
50
51local function lane3( cc )
52 WR( "Directly recursive: ", same(cc, cc.a) )
53 assert( cc and cc.a==cc )
54end
55local L3= lanes.gen("io", lane3)(c)
56
57-- Without a wait, exit from the main lane will close the process
58--
59-- Waiting for multiple lanes at once could be done using a Linda
60-- (but we're okay waiting them in order)
61--
62L1:join()
63L2:join()
64L3:join()
diff --git a/tests/ehynes.lua b/tests/ehynes.lua
new file mode 100644
index 0000000..4cc370e
--- /dev/null
+++ b/tests/ehynes.lua
@@ -0,0 +1,52 @@
1--
2-- Test from <ehynes at dharmagaia.com>
3--
4require 'lanes'
5
6local function PRINT_FMT( fmt, ... )
7 io.stderr:write( string.format(fmt,...).."\n" )
8end
9
10-- a linda for sending messages
11local linda = lanes.linda()
12
13-- a linda message receiver
14local receiver_gen = lanes.gen( 'base', 'os', 'string', 'io',
15 function (message_name)
16 PRINT_FMT( 'receiver for message %s entered', message_name )
17 local n = 1
18 while linda:receive(message_name) do
19 PRINT_FMT( '%s %d receieved', message_name, n )
20 n = n + 1
21 end
22 end
23)
24
25-- create a receiver
26local receiver1 = receiver_gen('message')
27
28-- create a second receiver (a second receiver in the same linda
29-- appears to be needed to trigger the delays)
30--
31-- AKa 4-Aug-2008: No, with svn version it isn't. But it causes the 2nd
32-- message to be hanging...
33--
34local receiver2 = receiver_gen('another message')
35
36-- a function to pause and log the execution for debugging
37local function logf(s, f, ...)
38 os.execute('sleep 1')
39 PRINT_FMT( "*** %s", s )
40 f(...)
41end
42
43-- first message sent is received right away
44logf('first message sent', linda.send, linda, 'message', true)
45
46-- second message sent is not received immediatly
47logf('second message sent', linda.send, linda, 'message', true)
48
49-- third message sent triggers receipt of both second and third messages
50logf('third message sent', linda.send, linda, 'message', true)
51
52logf('all done', function() end)
diff --git a/tests/error.lua b/tests/error.lua
new file mode 100644
index 0000000..673bcb5
--- /dev/null
+++ b/tests/error.lua
@@ -0,0 +1,47 @@
1--
2-- Error reporting
3--
4-- Note: this code is supposed to end in errors; not included in 'make test'
5--
6
7require "lanes"
8
9local function lane()
10
11 local subf= function() -- this so that we can see the call stack
12 --error "aa"
13 error({})
14 error(error)
15 end
16 local subf2= function()
17 subf()
18 end
19 subf2()
20end
21
22local function cleanup(err)
23end
24
25local lgen = lanes.gen("*", { --[[finalizer=cleanup]] }, lane)
26
27---
28io.stderr:write( "\n** Error catching **\n" )
29--
30local h= lgen()
31local _,err,stack= h:join() -- wait for the lane (no automatic error propagation)
32
33if err then
34 assert( type(stack)=="table" )
35 io.stderr:write( "Lane error: "..tostring(err).."\n" )
36
37 io.stderr:write( "\t", table.concat(stack,"\n\t"), "\n" );
38end
39
40---
41io.stderr:write( "\n** Error propagation **\n" )
42--
43local h2= lgen()
44local _= h2[0]
45assert(false) -- does NOT get here
46
47--never ends
diff --git a/tests/fibonacci.lua b/tests/fibonacci.lua
new file mode 100644
index 0000000..8867e14
--- /dev/null
+++ b/tests/fibonacci.lua
@@ -0,0 +1,75 @@
1--
2-- FIBONACCI.LUA Copyright (c) 2007-08, Asko Kauppi <akauppi@gmail.com>
3--
4-- Parallel calculation of Fibonacci numbers
5--
6-- A sample of task splitting like Intel TBB library does.
7--
8-- References:
9-- Intel Threading Building Blocks, 'test all'
10-- <http://shareit.intel.com/WikiHome/Articles/111111316>
11--
12
13-- Need to say it's 'local' so it can be an upvalue
14--
15local lanes= require "lanes"
16
17local function WR(str)
18 io.stderr:write( str.."\n" )
19end
20
21-- Threshold for serial calculation (optimal depends on multithreading fixed
22-- cost and is system specific)
23--
24local KNOWN= { [0]=0, 1,1,2,3,5,8,13,21,34,55,89,144 }
25
26--
27-- uint= fib( n_uint )
28--
29local function fib( n )
30 --
31 local sum
32 local floor= assert(math.floor)
33
34 WR( "fib("..n..")" )
35
36 if n <= #KNOWN then
37 sum= KNOWN[n]
38 else
39 -- Splits into two; this task remains waiting for the results
40 --
41 local gen_f= lanes.gen( "io,math,debug", fib )
42
43 local n1=floor(n/2) +1
44 local n2=floor(n/2) -1 + n%2
45
46 WR( "splitting "..n.." -> "..n1.." "..n2 )
47
48 local a= gen_f( n1 )
49 local b= gen_f( n2 )
50
51 -- children running...
52
53 local a2= a[1]^2
54 local b2= b[1]^2
55
56 sum = (n%2==1) and a2+b2 or a2-b2
57 end
58
59 io.stderr:write( "fib("..n..") = "..sum.."\n" )
60
61 return sum
62end
63
64--
65-- Right answers from: <http://sonic.net/~douglasi/fibo.htm>
66--
67local right= { 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181, 6765, 10946, 17711, 28657, 46368, 75025, 121393, 196418, 317811, 514229, 832040, 1346269, 2178309, 3524578, 5702887, 9227465, 14930352, 24157817, 39088169, 63245986, 102334155, 165580141, 267914296, 433494437, 701408733, 1134903170, 1836311903, 2971215073, 4807526976, 7778742049, 12586269025, 20365011074, 32951280099, 53316291173, 86267571272, 139583862445, 225851433717, 365435296162, 591286729879, 956722026041, 1548008755920, 2504730781961, 4052739537881, 6557470319842, 10610209857723, 17167680177565, 27777890035288, 44945570212853, 72723460248141, 117669030460994, 190392490709135, 308061521170129, 498454011879264, 806515533049393, 1304969544928657, 2111485077978050, 3416454622906707, 5527939700884757, 8944394323791464, 14472334024676220, 23416728348467684, 37889062373143900, 61305790721611580, 99194853094755490, 160500643816367070, 259695496911122560, 420196140727489660, 679891637638612200, 1100087778366101900, 1779979416004714000, 2880067194370816000, 4660046610375530000, 7540113804746346000, 12200160415121877000, 19740274219868226000, 31940434634990105000, 51680708854858334000, 83621143489848440000, 135301852344706780000, 218922995834555200000
68}
69assert( #right==99 )
70
71local N= 80
72local res= fib(N)
73print( right[N] )
74assert( res==right[N] )
75
diff --git a/tests/fifo.lua b/tests/fifo.lua
new file mode 100644
index 0000000..898b04d
--- /dev/null
+++ b/tests/fifo.lua
@@ -0,0 +1,43 @@
1--
2-- FIFO.LUA
3--
4-- Sample program for Lua Lanes
5--
6
7require "lanes"
8
9local linda= lanes.linda()
10local atomic_inc= lanes.genatomic( linda, "FIFO_n" )
11
12assert( atomic_inc()==1 )
13assert( atomic_inc()==2 )
14
15local function FIFO()
16 local my_channel= "FIFO"..atomic_inc()
17
18 return {
19 -- Giving explicit 'nil' timeout allows numbers to be used as 'my_channel'
20 --
21 send= function(...) linda:send( nil, my_channel, ... ) end,
22 receive= function(timeout) linda:receive( timeout, my_channel ) end
23 }
24end
25
26local A= FIFO()
27local B= FIFO()
28
29print "Sending to A.."
30A:send( 1,2,3,4,5 )
31
32print "Sending to B.."
33B:send( 'a','b','c' )
34
35print "Reading A.."
36print( A:receive( 1.0 ) )
37
38print "Reading B.."
39print( B:receive( 2.0 ) )
40
41-- Note: A and B can be passed between threads, or used as upvalues
42-- by multiple threads (other parts will be copied but the 'linda'
43-- handle is shared userdata and will thus point to the single place)
diff --git a/tests/finalizer.lua b/tests/finalizer.lua
new file mode 100644
index 0000000..c94b36d
--- /dev/null
+++ b/tests/finalizer.lua
@@ -0,0 +1,81 @@
1--
2-- Test resource cleanup
3--
4-- This feature was ... by discussion on the Lua list about exceptions.
5-- The idea is to always run a certain block at exit, whether due to success
6-- or error. Normally, 'pcall' would be used for such but as Lua already
7-- does that, simply giving a 'cleanup=function' parameter is a logical
8-- thing to do. -- AKa 22-Jan-2009
9--
10
11require "lanes"
12
13local FN= "finalizer-test.tmp"
14
15local cleanup
16
17local which= os.time() % 2 -- 0/1
18
19local function lane()
20
21 set_finalizer(cleanup)
22
23 local f,err= io.open(FN,"w")
24 if not f then
25 error( "Could not create "..FN..": "..err )
26 end
27
28 f:write( "Test file that should get removed." )
29
30 io.stderr:write( "File "..FN.." created\n" )
31
32 if which==0 then
33 error("aa") -- exception here; the value needs NOT be a string
34 end
35
36 -- no exception
37end
38
39--
40-- This is called at the end of the lane; whether succesful or not.
41-- Gets the 'error()' parameter as parameter ('nil' if normal return).
42--
43cleanup= function(err)
44
45 -- An error in finalizer will override an error (or success) in the main
46 -- chunk.
47 --
48 --error( "This is important!" )
49
50 if err then
51 io.stderr:write( "Cleanup after error: "..tostring(err).."\n" )
52 else
53 io.stderr:write( "Cleanup after normal return\n" )
54 end
55
56 local _,err2= os.remove(FN)
57 assert(not err2) -- if this fails, it will be shown in the calling script
58 -- as an error from the lane itself
59
60 io.stderr:write( "Removed file "..FN.."\n" )
61end
62
63local lgen = lanes.gen("*", lane)
64
65io.stderr:write "Launching the lane!\n"
66
67local h= lgen()
68
69local _,err,stack= h:join() -- wait for the lane (no automatic error propagation)
70if err then
71 assert(stack)
72 io.stderr:write( "Lane error: "..tostring(err).."\n" )
73 io.stderr:write( "\t", table.concat(stack,"\t\n"), "\n" )
74end
75
76local f= io.open(FN,"r")
77if f then
78 error( "CLEANUP DID NOT WORK: "..FN.." still exists!" )
79end
80
81io.stderr:write "Finished!\n"
diff --git a/tests/hangtest.lua b/tests/hangtest.lua
new file mode 100644
index 0000000..d0bbea4
--- /dev/null
+++ b/tests/hangtest.lua
@@ -0,0 +1,26 @@
1--
2-- Test case for hang on [1]s and :join()s.
3--
4
5require "lanes"
6
7local function ret(b)
8 return b
9end
10local lgen = lanes.gen("*", {}, ret)
11
12for i=1,10000 do
13 local ln = lgen(i)
14
15 print( "getting result for "..i )
16
17 -- Hangs here forever every few hundred runs or so,
18 -- can be illustrated by putting another print() statement
19 -- after, which will never be called.
20 --
21 local result = ln[1];
22
23 assert (result == i);
24end
25
26print "Finished!"
diff --git a/tests/irayo_closure.lua b/tests/irayo_closure.lua
new file mode 100644
index 0000000..faf08fd
--- /dev/null
+++ b/tests/irayo_closure.lua
@@ -0,0 +1,35 @@
1--
2-- Bugs filed by irayo Jul-2008
3--
4--[[
5"Another issue I've noticed is trying to pass a table with a function
6that uses closures in it as a global variable into a new lane. This
7causes a segmentation fault and it appears to be related to the
8luaG_inter_move function near line 835-836 or so in lanes.c, but I
9haven't investigated further.
10e.g. { globals = { data = 1, func = function() useclosurehere() end } }"
11]]
12
13require "lanes"
14
15local function testrun()
16 assert( print )
17 assert( data==1 )
18 assert( type(func)=="function" )
19 func() -- "using the closure"
20 return true
21end
22
23-- Should also work without these lines, but currently doesn't (bug in Lanes,
24-- a function thrown over isn't connected to receiving lane's globals)
25--
26--local print=print
27--local assert=assert
28
29local function useclosurehere()
30 assert( print )
31 print "using the closure"
32end
33
34local lane= lanes.gen( "", { globals = { data=1, func=useclosurehere } }, testrun )()
35print(lane[1])
diff --git a/tests/irayo_recursive.lua b/tests/irayo_recursive.lua
new file mode 100644
index 0000000..82e5a54
--- /dev/null
+++ b/tests/irayo_recursive.lua
@@ -0,0 +1,18 @@
1--
2-- Bugs filed by irayo Jul-2008
3--
4--[[
5This code showed lack of caching 'select', 'type' etc. in 'src/lanes.lua'.
6]]
7local function recurse()
8 print("level "..i);
9 if i > 10 then return "finished" end
10
11 require "lanes"
12
13 local lane = lanes.gen( "*", { globals = { ["i"]= i + 1 } }, recurse ) ()
14 return lane[1]
15end
16
17i = 0;
18recurse()
diff --git a/tests/keeper.lua b/tests/keeper.lua
new file mode 100644
index 0000000..5c8c23a
--- /dev/null
+++ b/tests/keeper.lua
@@ -0,0 +1,47 @@
1--
2-- KEEPER.LUA
3--
4-- Test program for Lua Lanes
5--
6
7require "lanes"
8
9local function keeper(linda)
10 local mt= {
11 __index= function( _, key )
12 return linda:get( key )
13 end,
14 __newindex= function( _, key, val )
15 linda:set( key, val )
16 end
17 }
18 return setmetatable( {}, mt )
19end
20
21--
22local lindaA= lanes.linda()
23local A= keeper( lindaA )
24
25local lindaB= lanes.linda()
26local B= keeper( lindaB )
27
28A.some= 1
29print( A.some )
30assert( A.some==1 )
31
32B.some= "hoo"
33assert( B.some=="hoo" )
34assert( A.some==1 )
35
36function lane()
37 local a= keeper(lindaA)
38 print( a.some )
39 assert( a.some==1 )
40 a.some= 2
41end
42
43local h= lanes.gen( "io", lane )()
44h:join()
45
46print( A.some ) -- 2
47assert( A.some==2 )
diff --git a/tests/launchtest.lua b/tests/launchtest.lua
new file mode 100644
index 0000000..5e3037f
--- /dev/null
+++ b/tests/launchtest.lua
@@ -0,0 +1,78 @@
1--
2-- LAUNCHTEST.LUA Copyright (c) 2007-08, Asko Kauppi <akauppi@gmail.com>
3--
4-- Tests launching speed of N threads
5--
6-- Usage:
7-- [time] lua -lstrict launchtest.lua [threads] [-libs[=io,os,math,...]]
8--
9-- threads: number of threads to launch (like: 2000) :)
10-- libs: combination of "os","io","math","package", ...
11-- just "-libs" for all libraries
12--
13-- Note:
14-- One _can_ reach the system threading level, ie. doing 10000 on
15-- PowerBook G4:
16-- <<
17-- pthread_create( ref, &a, lane_main, data ) failed @ line 316: 35
18-- Command terminated abnormally.
19-- <<
20--
21-- (Lua Lanes _can_ be made tolerable to such congestion cases. Just
22-- currently, it is not. btw, 5000 seems to run okay - system limit
23-- being 2040 simultaneous threads)
24--
25-- To do:
26-- - ...
27--
28
29local N= 1000 -- threads/loops to use
30local M= 1000 -- sieves from 1..M
31local LIBS= nil -- default: load no libraries
32
33local function HELP()
34 io.stderr:write( "Usage: lua launchtest.lua [threads] [-libs[=io,os,math,...]]\n" )
35 exit(1)
36end
37
38local m= require "argtable"
39local argtable= assert(m.argtable)
40
41for k,v in pairs( argtable(...) ) do
42 if k==1 then N= tonumber(v) or HELP()
43 elseif k=="libs" then LIBS= (v==true) and "*" or v
44 else HELP()
45 end
46end
47
48require "lanes"
49
50local g= lanes.gen( LIBS, function(i)
51 --io.stderr:write( i.."\t" )
52 return i
53 end )
54
55local t= {}
56
57for i=1,N do
58 t[i]= g(i)
59end
60
61if false then
62 -- just finish here, without waiting for threads to finish
63 --
64 local st= t[N].status
65 print(st) -- if that is "done", they flew already! :)
66else
67 -- mark that all have been launched, now wait for them to return
68 --
69 io.stderr:write( N.." lanes launched.\n" )
70
71 for i=1,N do
72 local rc= t[i]:join()
73 assert( rc==i )
74 end
75
76 io.stderr:write( N.." lanes finished.\n" )
77end
78
diff --git a/tests/objects.lua b/tests/objects.lua
new file mode 100644
index 0000000..8f56a5f
--- /dev/null
+++ b/tests/objects.lua
@@ -0,0 +1,76 @@
1--
2-- OBJECTS.LUA
3--
4-- Tests that objects (metatables) can be passed between lanes.
5--
6
7require "lanes"
8
9local linda= lanes.linda()
10
11local start_lane= lanes.gen( "io",
12 function( obj1 )
13
14 assert( obj1.v )
15 assert( obj1.print )
16
17 assert( obj1 )
18 local mt1= getmetatable(obj1)
19 assert(mt1)
20
21 local obj2= linda:receive("")
22 assert( obj2 )
23 local mt2= getmetatable(obj2)
24 assert(mt2)
25 assert( mt1==mt2 )
26
27 local v= obj1:print()
28 assert( v=="aaa" )
29
30 v= obj2:print()
31 assert( v=="bbb" )
32
33 return true
34 end
35)
36
37
38local WR= function(str)
39 io.stderr:write( tostring(str).."\n")
40end
41
42
43-- Lanes identifies metatables and copies them only once per each lane.
44--
45-- Having methods in the metatable will make passing objects lighter than
46-- having the methods 'fixed' in the object tables themselves.
47--
48local o_mt= {
49 __index= function( me, key )
50 if key=="print" then
51 return function() WR(me.v); return me.v end
52 end
53 end
54}
55
56local function obj_gen(v)
57 local o= { v=v }
58 setmetatable( o, o_mt )
59 return o
60end
61
62local a= obj_gen("aaa")
63local b= obj_gen("bbb")
64
65assert( a and b )
66
67local mt_a= getmetatable(a)
68local mt_b= getmetatable(b)
69assert( mt_a and mt_a==mt_b )
70
71local h= start_lane(a) -- 1st object as parameter
72
73linda:send( "", b ) -- 2nd object via Linda
74
75assert( h[1]==true ) -- wait for return
76
diff --git a/tests/perftest.lua b/tests/perftest.lua
new file mode 100644
index 0000000..8ce1b3c
--- /dev/null
+++ b/tests/perftest.lua
@@ -0,0 +1,184 @@
1--
2-- PERFTEST.LUA Copyright (c) 2007-08, Asko Kauppi <akauppi@gmail.com>
3--
4-- Performance comparison of multithreaded Lua (= how much ballast does using
5-- Lua Lanes introduce)
6--
7-- Usage:
8-- [time] lua -lstrict perftest.lua [threads] [-plain|-single[=2..n]] [-time] [-prio[=-2..+2[,-2..+2]]]
9--
10-- threads: number of threads to launch (loops in 'plain' mode)
11-- -plain: runs in nonthreaded mode, to get a comparison baseline
12-- -single: runs using just a single CPU core (or 'n' cores if given)
13-- -prio: sets odd numbered threads to higher/lower priority
14--
15-- History:
16-- AKa 20-Jul-08: updated to Lanes 2008
17-- AK 14-Apr-07: works on Win32
18--
19-- To do:
20-- (none?)
21--
22
23-- On MSYS, stderr is buffered. In this test it matters.
24-- Seems, even with this MSYS wants to buffer linewise, needing '\n'
25-- before actual output.
26--
27local MSYS= os.getenv("OSTYPE")=="msys"
28
29
30require "lanes"
31
32local m= require "argtable"
33local argtable= assert( m.argtable )
34
35local N= 1000 -- threads/loops to use
36local M= 1000 -- sieves from 1..M
37local PLAIN= false -- single threaded (true) or using Lanes (false)
38local SINGLE= false -- cores to use (false / 1..n)
39local TIME= false -- use Lua for the timing
40local PRIO_ODD, PRIO_EVEN -- -3..+3
41
42local function HELP()
43 io.stderr:write( "Usage: lua perftest.lua [threads]\n" )
44end
45
46-- nil -> +2
47-- odd_prio[,even_prio]
48--
49local function prio_param(v)
50 if v==true then return 2,-2 end
51
52 local a,b= string.match( v, "^([%+%-]?%d+)%,([%+%-]?%d+)$" )
53 if a then
54 return tonumber(a), tonumber(b)
55 elseif tonumber(v) then
56 return tonumber(v)
57 else
58 error( "Bad priority: "..v )
59 end
60end
61
62for k,v in pairs( argtable(...) ) do
63 if k==1 then N= tonumber(v) or HELP()
64 elseif k=="plain" then PLAIN= true
65 elseif k=="single" then SINGLE= v -- true/number
66 elseif k=="time" then TIME= true
67 elseif k=="prio" then PRIO_ODD, PRIO_EVEN= prio_param(v)
68 else HELP()
69 end
70end
71
72PRIO_ODD= PRIO_ODD or 0
73PRIO_EVEN= PRIO_EVEN or 0
74
75
76-- SAMPLE ADOPTED FROM Lua 5.1.1 test/sieve.lua --
77
78-- the sieve of of Eratosthenes programmed with coroutines
79-- typical usage: lua -e N=1000 sieve.lua | column
80
81-- AK: Wrapped within a surrounding function, so we can pass it to Lanes
82-- Note that coroutines can perfectly fine be used within each Lane. :)
83--
84-- AKa 20-Jul-2008: Now the wrapping to one function is no longer needed;
85-- Lanes 2008 can take the used functions as upvalues.
86--
87local function sieve_lane(N,id)
88
89 if MSYS then
90 io.stderr:setvbuf "no"
91 end
92
93 -- generate all the numbers from 2 to n
94 local function gen (n)
95 return coroutine.wrap(function ()
96 for i=2,n do coroutine.yield(i) end
97 end)
98 end
99
100 -- filter the numbers generated by `g', removing multiples of `p'
101 local function filter (p, g)
102 return coroutine.wrap(function ()
103 while 1 do
104 local n = g()
105 if n == nil then return end
106 if math.mod(n, p) ~= 0 then coroutine.yield(n) end
107 end
108 end)
109 end
110
111 local ret= {} -- returned values: { 2, 3, 5, 7, 11, ... }
112 N=N or 1000 -- from caller
113 local x = gen(N) -- generate primes up to N
114 while 1 do
115 local n = x() -- pick a number until done
116 if n == nil then break end
117 --print(n) -- must be a prime number
118 table.insert( ret, n )
119
120 x = filter(n, x) -- now remove its multiples
121 end
122
123 io.stderr:write(id..(MSYS and "\n" or "\t")) -- mark we're ready
124
125 return ret
126end
127-- ** END OF LANE ** --
128
129
130-- Keep preparation code outside of the performance test
131--
132local f_even= lanes.gen( "base,coroutine,math,table,io", -- "*" = all
133 { priority= PRIO_EVEN }, sieve_lane )
134
135local f_odd= lanes.gen( "base,coroutine,math,table,io", -- "*" = all
136 { priority= PRIO_ODD }, sieve_lane )
137
138io.stderr:write( "*** Counting primes 1.."..M.." "..N.." times ***\n\n" )
139
140local t0= TIME and os.time()
141
142if PLAIN then
143 io.stderr:write( "Plain (no multithreading):\n" )
144
145 for i=1,N do
146 local tmp= sieve_lane(M,i)
147 assert( type(tmp)=="table" and tmp[1]==2 and tmp[168]==997 )
148 end
149else
150 if SINGLE then
151 io.stderr:write( (tonumber(SINGLE) and SINGLE or 1) .. " core(s):\n" )
152 lanes.single(SINGLE) -- limit to N cores (just OS X)
153 else
154 io.stderr:write( "Multi core:\n" )
155 end
156
157 if PRIO_ODD ~= PRIO_EVEN then
158 io.stderr:write( ( PRIO_ODD > PRIO_EVEN and "ODD" or "EVEN" )..
159 " LANES should come first (odd:"..PRIO_ODD..", even:"..PRIO_EVEN..")\n\n" )
160 else
161 io.stderr:write( "EVEN AND ODD lanes should be mingled (both: "..PRIO_ODD..")\n\n" )
162 end
163 local t= {}
164 for i=1,N do
165 t[i]= ((i%2==0) and f_even or f_odd) (M,i)
166 end
167
168 -- Make sure all lanes finished
169 --
170 for i=1,N do
171 local tmp= t[i]:join()
172 assert( type(tmp)=="table" and tmp[1]==2 and tmp[168]==997 )
173 end
174end
175
176io.stderr:write "\n"
177
178if TIME then
179 local t= os.time() - t0
180 io.stderr:write( "*** TIMING: "..t.." seconds ***\n" )
181end
182
183--
184-- end
diff --git a/tests/recursive.lua b/tests/recursive.lua
new file mode 100644
index 0000000..49c03d3
--- /dev/null
+++ b/tests/recursive.lua
@@ -0,0 +1,21 @@
1--
2-- RECURSIVE.LUA
3--
4-- Test program for Lua Lanes
5--
6
7io.stderr:write( "depth:" )
8local function func( depth )
9 io.stderr:write(" " .. depth)
10 if depth > 10 then
11 return "done!"
12 end
13
14 require "lanes"
15 local lane= lanes.gen("*", func)( depth+1 )
16 return lane[1]
17end
18
19local v= func(0)
20assert(v=="done!")
21io.stderr:write("\n")
diff --git a/tests/require.lua b/tests/require.lua
new file mode 100644
index 0000000..2cfe780
--- /dev/null
+++ b/tests/require.lua
@@ -0,0 +1,30 @@
1--
2-- REQUIRE.LUA
3--
4-- Test that 'require' works from sublanes
5--
6require 'lanes'
7
8local function a_lane()
9 -- To require 'math' we still actually need to have it initialized for
10 -- the lane.
11 --
12 require "math"
13 assert( math and math.sqrt )
14 assert( math.sqrt(4)==2 )
15
16 assert( lanes==nil )
17 require "lanes"
18 assert( lanes and lanes.gen )
19
20 local h= lanes.gen( function() return 42 end ) ()
21 local v= h[1]
22
23 return v==42
24end
25
26local gen= lanes.gen( "math,package,string,table", a_lane )
27
28local h= gen()
29local ret= h[1]
30assert( ret==true )
diff --git a/tests/timer.lua b/tests/timer.lua
new file mode 100644
index 0000000..e95f326
--- /dev/null
+++ b/tests/timer.lua
@@ -0,0 +1,93 @@
1--
2-- TIMER.LUA
3--
4-- Sample program for Lua Lanes
5--
6
7-- On MSYS, stderr is buffered. In this test it matters.
8io.stderr:setvbuf "no"
9
10
11require "lanes"
12
13local linda= lanes.linda()
14
15local function PRINT(str)
16 io.stderr:write(str.."\n")
17end
18
19local T1= "1s" -- these keys can be anything...
20local T2= "5s"
21
22local step= {}
23
24lanes.timer( linda, T1, 1.0, 1.0 )
25step[T1]= 1.0
26
27PRINT( "\n*** Timers every second (not synced to wall clock) ***\n" )
28
29local v_first
30local v_last= {} -- { [channel]= num }
31local T2_first_round= true
32
33local caught= {} -- { [T1]= bool, [T2]= bool }
34
35while true do
36 io.stderr:write("waiting...\t")
37 local v,channel= linda:receive( 6.0, T1,T2 )
38 assert( channel==T1 or channel==T2 )
39 caught[channel]= true
40
41 io.stderr:write( ((channel==T1) and "" or "\t\t").. string.format("%.3f",v),"\n" )
42 assert( type(v)=="number" )
43
44 if v_last[channel] then
45 if channel==T2 and T2_first_round then
46 -- do not make measurements, first round is not 5secs due to wall clock adjustment
47 T2_first_round= false
48 else
49 assert( math.abs(v-v_last[channel]- step[channel]) < 0.02 )
50 end
51 end
52
53 if not v_first then
54 v_first= v
55 elseif v-v_first > 3.0 and (not step[T2]) then
56 PRINT( "\n*** Adding timers every 5 second (synced to wall clock) ***\n" )
57
58 -- The first event can be in the past (just cut seconds down to 5s)
59 --
60 local date= os.date("*t")
61 date.sec = date.sec - date.sec%5
62
63 lanes.timer( linda, T2, date, 5.0 )
64 step[T2]= 5.0
65
66 elseif v-v_first > 10 then -- exit condition
67 break
68 end
69 v_last[channel]= v
70end
71
72-- Windows version had a bug where T2 timers were not coming through, at all.
73-- AKa 24-Jan-2009
74--
75assert( caught[T1] )
76assert( caught[T2] )
77
78PRINT( "\n*** Clearing timers ***\n" )
79
80lanes.timer( linda, T1, 0 ) -- reset; no reoccuring ticks
81lanes.timer( linda, T2, 0 )
82
83linda:receive( 0, T1 ) -- clear out; there could be one tick left
84linda:receive( 0, T2 )
85
86assert( linda:get(T1) == nil )
87assert( linda:get(T2) == nil )
88
89PRINT "...making sure no ticks are coming..."
90
91local v= linda:receive( 1.5, T1,T2 ) -- should not get any
92assert(v==nil)
93