aboutsummaryrefslogtreecommitdiff
path: root/llthreads2/test
diff options
context:
space:
mode:
Diffstat (limited to 'llthreads2/test')
-rw-r--r--llthreads2/test/test_alive.lua35
-rw-r--r--llthreads2/test/test_join_detach.lua59
-rw-r--r--llthreads2/test/test_join_error.lua24
-rw-r--r--llthreads2/test/test_join_timeout.lua23
-rw-r--r--llthreads2/test/test_llthreads.lua60
-rw-r--r--llthreads2/test/test_load_llthreads2.lua7
-rw-r--r--llthreads2/test/test_logger.lua24
-rw-r--r--llthreads2/test/test_pass_cfunction.lua17
-rw-r--r--llthreads2/test/test_register_ffi.lua14
-rw-r--r--llthreads2/test/test_register_llthreads.lua15
-rw-r--r--llthreads2/test/test_table_copy.lua134
-rw-r--r--llthreads2/test/test_threads.lua67
-rw-r--r--llthreads2/test/utils.lua63
13 files changed, 542 insertions, 0 deletions
diff --git a/llthreads2/test/test_alive.lua b/llthreads2/test/test_alive.lua
new file mode 100644
index 0000000..ecce163
--- /dev/null
+++ b/llthreads2/test/test_alive.lua
@@ -0,0 +1,35 @@
1local llthreads = require"llthreads"
2local utils = require "utils"
3local sleep = utils.sleep
4
5local include = utils.thread_init .. [[
6local llthreads = require"llthreads"
7local sleep = require "utils".sleep
8]]
9
10local thread = llthreads.new(include .. [[
11 sleep(5)
12 return 1,2,3
13]])
14
15assert(nil == thread:alive())
16
17thread:start()
18
19assert(true == thread:alive())
20
21for i = 1, 10 do
22 if not thread:alive() then break end
23 sleep(1)
24end
25
26assert(false == thread:alive())
27
28local ok,a,b,c = thread:join(0)
29assert(ok == true)
30assert(a == 1)
31assert(b == 2)
32assert(c == 3)
33
34print("Done!")
35
diff --git a/llthreads2/test/test_join_detach.lua b/llthreads2/test/test_join_detach.lua
new file mode 100644
index 0000000..533a36f
--- /dev/null
+++ b/llthreads2/test/test_join_detach.lua
@@ -0,0 +1,59 @@
1local llthreads = require"llthreads"
2local utils = require "utils"
3
4do
5
6local thread = llthreads.new(utils.thread_init .. [[
7 local sleep = require"utils".sleep
8 while true do sleep(1) end
9]])
10
11-- detached + joindable
12thread:start(true, true)
13
14local ok, err = thread:join(0)
15print("thread:join(0): ", ok, err)
16assert(ok == nil)
17assert(err == "timeout")
18
19end
20
21-- enforce collect `thread` object
22-- we should not hungup
23for i = 1, 10 do collectgarbage("collect") end
24
25
26do
27
28local thread = llthreads.new(utils.thread_init .. [[
29 local sleep = require"utils".sleep
30 sleep(1)
31]])
32
33-- detached + joindable
34thread:start(true, true)
35
36local ok, err = thread:join(0)
37print("thread:join(0): ", ok, err)
38assert(ok == nil)
39assert(err == "timeout")
40
41for i = 1, 12 do
42 utils.sleep(5)
43 ok, err = thread:join(0)
44 print("thread:join(0)#" .. i .. ": ", ok, err)
45 if ok then break end
46 assert(err == 'timeout')
47end
48
49assert(ok)
50
51end
52
53-- enforce collect `thread` object
54-- we should not get av
55for i = 1, 10 do collectgarbage("collect") end
56
57
58print("Done!")
59
diff --git a/llthreads2/test/test_join_error.lua b/llthreads2/test/test_join_error.lua
new file mode 100644
index 0000000..90780b1
--- /dev/null
+++ b/llthreads2/test/test_join_error.lua
@@ -0,0 +1,24 @@
1local llthreads = require "llthreads"
2local utils = require "utils"
3local sleep = utils.sleep
4
5local include = utils.thread_init .. [[
6local llthreads = require"llthreads"
7local sleep = require "utils".sleep
8]]
9
10local thread = llthreads.new(include .. [[
11 sleep(5)
12]])
13
14thread:start()
15
16local ok, err = thread:join()
17assert(ok == true)
18assert(err == nil)
19
20local res, ok, err = pcall(thread.join, thread)
21assert(res == true)
22assert(ok == nil)
23assert(err ~= nil)
24
diff --git a/llthreads2/test/test_join_timeout.lua b/llthreads2/test/test_join_timeout.lua
new file mode 100644
index 0000000..b9cf155
--- /dev/null
+++ b/llthreads2/test/test_join_timeout.lua
@@ -0,0 +1,23 @@
1local llthreads = require"llthreads"
2local utils = require "utils"
3local sleep = utils.sleep
4
5local include = utils.thread_init .. [[
6local llthreads = require"llthreads"
7local sleep = require "utils".sleep
8]]
9
10local thread = llthreads.new(include .. [[
11 sleep(5)
12]])
13thread:start()
14local ok, err = thread:join(0)
15print("thread:join(0): ", ok, err)
16assert(ok == nil)
17assert(err == "timeout")
18
19local ok, err = thread:join()
20print("thread:join(): ", ok, err)
21assert(ok, err)
22print("Done!")
23
diff --git a/llthreads2/test/test_llthreads.lua b/llthreads2/test/test_llthreads.lua
new file mode 100644
index 0000000..e0e214b
--- /dev/null
+++ b/llthreads2/test/test_llthreads.lua
@@ -0,0 +1,60 @@
1-- Copyright (c) 2011 by Robert G. Jakabosky <bobby@sharedrealm.com>
2--
3-- Permission is hereby granted, free of charge, to any person obtaining a copy
4-- of this software and associated documentation files (the "Software"), to deal
5-- in the Software without restriction, including without limitation the rights
6-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7-- copies of the Software, and to permit persons to whom the Software is
8-- furnished to do so, subject to the following conditions:
9--
10-- The above copyright notice and this permission notice shall be included in
11-- all copies or substantial portions of the Software.
12--
13-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19-- THE SOFTWARE.
20
21local llthreads = require"llthreads"
22local sleep = require"utils".sleep
23
24print("LLThreads version : ", llthreads._VERSION)
25
26local function detached_thread(...)
27 local thread = llthreads.new([[ print("print_detached_thread:", ...) ]], ...)
28 -- start detached thread
29 assert(thread:start(true))
30 return thread
31end
32
33local function print_thread(...)
34 local thread = llthreads.new([[ print("print_thread:", ...); ]], ...)
35 -- start joinable thread
36 assert(thread:start())
37 return thread
38end
39
40local function pass_through_thread(...)
41 local thread = llthreads.new([[ return "pass_thread:", ... ]], ...)
42 -- start joinable thread
43 assert(thread:start())
44 return thread
45end
46
47local thread1 = detached_thread("number:", 1234, "nil:", nil, "bool:", true)
48
49sleep(1)
50
51local thread2 = print_thread("number:", 1234, "nil:", nil, "bool:", true)
52print("thread2:join: results # = ", select('#', thread2:join()))
53
54sleep(1)
55
56local thread3 = pass_through_thread("number:", 1234, "nil:", nil, "bool:", true)
57print("thread3:join:", thread3:join())
58
59sleep(1)
60
diff --git a/llthreads2/test/test_load_llthreads2.lua b/llthreads2/test/test_load_llthreads2.lua
new file mode 100644
index 0000000..11bf0a0
--- /dev/null
+++ b/llthreads2/test/test_load_llthreads2.lua
@@ -0,0 +1,7 @@
1local llthreads = require"llthreads2"
2
3llthreads.new([[
4 local os = require "os"
5 print("Done!")
6 os.exit(0)
7]]):start():join() \ No newline at end of file
diff --git a/llthreads2/test/test_logger.lua b/llthreads2/test/test_logger.lua
new file mode 100644
index 0000000..f85a896
--- /dev/null
+++ b/llthreads2/test/test_logger.lua
@@ -0,0 +1,24 @@
1local utils = require "utils"
2
3require "llthreads".new(utils.thread_init .. [[
4require "string"
5
6require "llthreads".set_logger(function(msg)
7 if type(msg) ~= 'string' then
8 print("ERROR! Invalid error message: ", msg)
9 os.exit(-2)
10 end
11 if not msg:find("SOME ERROR", nil, true) then
12 print("ERROR! Invalid error message: ", msg)
13 os.exit(-1)
14 end
15 print("Done!")
16 os.exit(0)
17end)
18
19error("SOME ERROR")
20]]):start():join()
21
22print("ERROR! Logger has not been call!")
23os.exit(-1)
24
diff --git a/llthreads2/test/test_pass_cfunction.lua b/llthreads2/test/test_pass_cfunction.lua
new file mode 100644
index 0000000..86fcd3d
--- /dev/null
+++ b/llthreads2/test/test_pass_cfunction.lua
@@ -0,0 +1,17 @@
1local llthreads = require"llthreads"
2local utils = require"utils"
3
4local thread = llthreads.new(utils.thread_init .. [[
5 require "llthreads"
6 local fn = ...
7
8 if type(fn) ~= 'function' then
9 print("ERROR! No function : ", fn, type(fn))
10 os.exit(-2)
11 end
12
13 fn("print('Done!'); require'os'.exit(0)"):start():join()
14]], llthreads.new)
15
16print(thread:start():join())
17os.exit(-1) \ No newline at end of file
diff --git a/llthreads2/test/test_register_ffi.lua b/llthreads2/test/test_register_ffi.lua
new file mode 100644
index 0000000..e98167f
--- /dev/null
+++ b/llthreads2/test/test_register_ffi.lua
@@ -0,0 +1,14 @@
1if jit then
2 local llthreads = require "llthreads"
3 local thread = llthreads.new([[
4 if not package.preload.ffi then
5 print("ffi does not register in thread")
6 os.exit(-1)
7 end
8 local ok, err = pcall(require, "ffi")
9 if not ok then
10 print("can not load ffi: ", err)
11 os.exit(-2)
12 end
13 ]]):start():join()
14end
diff --git a/llthreads2/test/test_register_llthreads.lua b/llthreads2/test/test_register_llthreads.lua
new file mode 100644
index 0000000..5b234a9
--- /dev/null
+++ b/llthreads2/test/test_register_llthreads.lua
@@ -0,0 +1,15 @@
1-- Test if you build module with
2-- LLTHREAD_REGISTER_THREAD_LIBRARY
3
4local llthreads = require "llthreads"
5local thread = llthreads.new([[
6 if not package.preload.llthreads then
7 print("llthreads does not register in thread")
8 os.exit(-1)
9 end
10 local ok, err = pcall(require, "llthreads")
11 if not ok then
12 print("can not load llthreads: ", err)
13 os.exit(-2)
14 end
15]]):start():join()
diff --git a/llthreads2/test/test_table_copy.lua b/llthreads2/test/test_table_copy.lua
new file mode 100644
index 0000000..0408ad3
--- /dev/null
+++ b/llthreads2/test/test_table_copy.lua
@@ -0,0 +1,134 @@
1-- Copyright (c) 2011 by Robert G. Jakabosky <bobby@sharedrealm.com>
2--
3-- Permission is hereby granted, free of charge, to any person obtaining a copy
4-- of this software and associated documentation files (the "Software"), to deal
5-- in the Software without restriction, including without limitation the rights
6-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7-- copies of the Software, and to permit persons to whom the Software is
8-- furnished to do so, subject to the following conditions:
9--
10-- The above copyright notice and this permission notice shall be included in
11-- all copies or substantial portions of the Software.
12--
13-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19-- THE SOFTWARE.
20
21local llthreads = require"llthreads"
22
23local sleep
24local status, socket = pcall(require,"socket")
25if status then
26 sleep = function(secs)
27 return socket.sleep(secs)
28 end
29else
30 sleep = function(secs)
31 os.execute("sleep " .. tonumber(secs))
32 end
33end
34
35local dump_code = [==[
36local function dump_recur(seen, obj, depth)
37 local out
38 local t = type(obj)
39 -- if not a table just convert to string.
40 if t ~= "table" then
41 if t == "string" then
42 return '"' .. obj .. '"'
43 end
44 return tostring(obj)
45 end
46 -- check if this table has been seen already.
47 if seen[obj] then
48 return "Already dumped " .. tostring(obj)
49 end
50 seen[obj] = true
51 -- restrict max depth.
52 if depth >= 10 then
53 return "{... max depth reached ...}"
54 end
55 depth = depth + 1
56 -- output table key/value pairs
57 local tabs = string.rep(" ",depth)
58 local out = "{\n"
59 for k,v in pairs(obj) do
60 if type(k) ~= "number" then
61 out = out .. tabs .. '[' .. dump_recur(seen, k, depth) .. '] = ' ..
62 dump_recur(seen, v, depth) .. ',\n'
63 else
64 out = out .. tabs .. '[' .. k .. '] = ' .. dump_recur(seen, v, depth) .. ',\n'
65 end
66 end
67 return out .. tabs:sub(1,-3) .. "}"
68end
69
70local obj = ...
71local seen = {}
72return dump_recur(seen, obj, 0)
73]==]
74
75local dump = (loadstring or load)(dump_code)
76
77local child_code = [==[
78local dump = (loadstring or load)[[
79]==] .. dump_code .. [==[
80]]
81local args = ...
82
83print("Child thread args:", dump(args))
84
85-- return all values.
86return ...
87]==]
88
89local function test_thread_value_copying(...)
90 local args = {...}
91 print("Main thread args:", dump(args))
92 local thread = llthreads.new(child_code, args)
93 -- start joinable thread
94 assert(thread:start())
95
96 local status, results = thread:join()
97 print("Main thread results:", dump(results))
98end
99
100-- create some tables.
101local a1 = { "a1" }
102local a2 = { "a2" }
103local a3 = { "a3" }
104local a4 = { "a4" }
105local b1 = { a1, a2, a3, a4 }
106local b2 = { a1=a1, a2=a2, a3=a3, a4=a4 }
107
108--
109-- no loops
110--
111test_thread_value_copying(b1, b2)
112
113local top = {}
114-- self reference.
115top.top = top
116top[top] = top
117-- nested reference.
118top.sub1 = { sub2 = { sub3 = { top } } }
119
120--
121-- loops
122--
123test_thread_value_copying(top)
124
125--
126-- Test max depth
127--
128local outer = {}
129for n=1,100 do
130 outer = {outer}
131end
132local status, err = pcall(test_thread_value_copying,outer)
133assert(not status, "Assertion failed: max depth test failed.")
134
diff --git a/llthreads2/test/test_threads.lua b/llthreads2/test/test_threads.lua
new file mode 100644
index 0000000..459604d
--- /dev/null
+++ b/llthreads2/test/test_threads.lua
@@ -0,0 +1,67 @@
1-- Copyright (c) 2011 by Ross Anderson <ross_j_anderson@yahoo.com>
2--
3-- Permission is hereby granted, free of charge, to any person obtaining a copy
4-- of this software and associated documentation files (the "Software"), to deal
5-- in the Software without restriction, including without limitation the rights
6-- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7-- copies of the Software, and to permit persons to whom the Software is
8-- furnished to do so, subject to the following conditions:
9--
10-- The above copyright notice and this permission notice shall be included in
11-- all copies or substantial portions of the Software.
12--
13-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14-- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15-- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16-- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17-- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18-- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19-- THE SOFTWARE.
20
21-- Sub-thread processing example in Lua using llthreads - 1,000 quick sub-thread execution
22
23-- luajit sub_threads.lua
24
25local llthreads = require"llthreads"
26local utils = require "utils"
27
28local num_threads = tonumber(arg[1] or 1000)
29
30-- level 0 string literal enclosure [[ ]] of child execution code
31local thread_code = utils.thread_init .. [[
32
33 local num_threads = ...
34 print("CHILD: received from ROOT params:", ...)
35 local llthreads = require"llthreads" -- need to re-declare this under this scope
36 local t = {} -- thread storage table
37
38 -- create a new child sub-thread execution code - it requires level 1 literal string [=[ ]=] enclosures, level 2 would be [==[ ]==]
39 local executed_child_code = [=[
40 return "Hello from child sub-thread, new input params:", ...
41 ]=]
42
43 -- create 1000 sub-threads - which creates an incremental 30% / 20% utilization spike on the two AMD cpu cores
44 print("CHILD: Create sub threads:", num_threads)
45 for i=1,num_threads do
46 -- create child sub-thread with code to execute and the input parmeters
47 local thread = llthreads.new(executed_child_code , "number:", 1000 + i, "nil:", nil, "bool:", true)
48 assert(thread:start()) -- start new child sub-thread
49 table.insert(t, thread) -- append the thread at the end of the thread table
50 end
51
52 -- wait (block) for all child sub-threads to complete before returning to ROOT
53 while true do
54 -- always wait on the first element, since order is not important
55 print("CHILD: sub-thread returned: ", t[1]:join())
56 table.remove(t,1) -- always remove the first element
57 if (#t == 0) then break end
58 end
59 return ... -- return the parents' input params back to the root
60]]
61
62-- create child thread.
63local thread = llthreads.new(thread_code, num_threads, "number:", 1000, "nil:", nil, "bool:", true)
64-- start joinable child thread.
65assert(thread:start())
66-- wait for all child and child sub-threads to finish
67print("ROOT: child returned: ", thread:join())
diff --git a/llthreads2/test/utils.lua b/llthreads2/test/utils.lua
new file mode 100644
index 0000000..d9b5fe5
--- /dev/null
+++ b/llthreads2/test/utils.lua
@@ -0,0 +1,63 @@
1local lua_version_t
2local function lua_version()
3 if not lua_version_t then
4 local version = rawget(_G,"_VERSION")
5 local maj,min = version:match("^Lua (%d+)%.(%d+)$")
6 if maj then lua_version_t = {tonumber(maj),tonumber(min)}
7 elseif not math.mod then lua_version_t = {5,2}
8 elseif table.pack and not pack then lua_version_t = {5,2}
9 else lua_version_t = {5,2} end
10 end
11 return lua_version_t[1], lua_version_t[2]
12end
13
14local LUA_MAJOR, LUA_MINOR = lua_version()
15local IS_LUA_51 = (LUA_MAJOR == 5) and (LUA_MINOR == 1)
16local IS_LUA_52 = (LUA_MAJOR == 5) and (LUA_MINOR == 2)
17
18local LUA_INIT = "LUA_INIT"
19local LUA_INIT_VER
20if not IS_LUA_51 then
21 LUA_INIT_VER = LUA_INIT .. "_" .. LUA_MAJOR .. "_" .. LUA_MINOR
22end
23
24LUA_INIT = LUA_INIT_VER and os.getenv( LUA_INIT_VER ) or os.getenv( LUA_INIT ) or ""
25
26LUA_INIT = [[do
27 local lua_init = ]] .. ("%q"):format(LUA_INIT) .. [[
28 if lua_init and #lua_init > 0 then
29 if lua_init:sub(1,1) == '@' then
30 dofile(lua_init:sub(2))
31 else
32 assert((loadstring or load)(lua_init))()
33 end
34 end
35end;]]
36
37local sleep
38local status, socket = pcall(require,"socket")
39if status then
40 sleep = function(secs)
41 return socket.sleep(secs)
42 end
43end
44
45if not sleep then
46 local status, ztimer = pcall(require, "lzmq.timer")
47 if status then
48 sleep = function(secs)
49 ztimer.sleep(secs * 1000)
50 end
51 end
52end
53
54if not sleep then
55 sleep = function(secs)
56 os.execute("sleep " .. tonumber(secs))
57 end
58end
59
60return {
61 thread_init = LUA_INIT,
62 sleep = sleep,
63}