diff options
author | Benoit Germain <benoit.germain@ubisoft.com> | 2024-05-31 11:40:28 +0200 |
---|---|---|
committer | Benoit Germain <benoit.germain@ubisoft.com> | 2024-05-31 11:40:28 +0200 |
commit | a65a84cfad4eae38e5e84b1ab11f60a62833f287 (patch) | |
tree | 3d3b6cc88c188f2c34d3283e081316d6cc05ae83 | |
parent | 731556711e453a501f1d1d06a6013b8fbd53414e (diff) | |
download | lanes-a65a84cfad4eae38e5e84b1ab11f60a62833f287.tar.gz lanes-a65a84cfad4eae38e5e84b1ab11f60a62833f287.tar.bz2 lanes-a65a84cfad4eae38e5e84b1ab11f60a62833f287.zip |
Improved multi-keeper tests
-rw-r--r-- | src/deep.cpp | 9 | ||||
-rw-r--r-- | src/lanes.cpp | 2 | ||||
-rw-r--r-- | src/lanes.lua | 37 | ||||
-rw-r--r-- | tests/keeper.lua | 235 | ||||
-rw-r--r-- | tests/nb_keepers.lua | 20 |
5 files changed, 178 insertions, 125 deletions
diff --git a/src/deep.cpp b/src/deep.cpp index f5716bf..34cc4b4 100644 --- a/src/deep.cpp +++ b/src/deep.cpp | |||
@@ -78,9 +78,9 @@ namespace { | |||
78 | 78 | ||
79 | // can work without a universe if creating a deep userdata from some external C module when Lanes isn't loaded | 79 | // can work without a universe if creating a deep userdata from some external C module when Lanes isn't loaded |
80 | // in that case, we are not multithreaded and locking isn't necessary anyway | 80 | // in that case, we are not multithreaded and locking isn't necessary anyway |
81 | bool const isLastRef{ _p->refcount.fetch_sub(1, std::memory_order_relaxed) == 1 }; | 81 | bool const _isLastRef{ _p->refcount.fetch_sub(1, std::memory_order_relaxed) == 1 }; |
82 | 82 | ||
83 | if (isLastRef) { | 83 | if (_isLastRef) { |
84 | // retrieve wrapped __gc, if any | 84 | // retrieve wrapped __gc, if any |
85 | lua_pushvalue(L_, lua_upvalueindex(1)); // L_: self __gc? | 85 | lua_pushvalue(L_, lua_upvalueindex(1)); // L_: self __gc? |
86 | if (!lua_isnil(L_, -1)) { | 86 | if (!lua_isnil(L_, -1)) { |
@@ -123,6 +123,7 @@ namespace { | |||
123 | // ################################################################################################# | 123 | // ################################################################################################# |
124 | // ################################################################################################# | 124 | // ################################################################################################# |
125 | 125 | ||
126 | // NEVER call deleteDeepObjectInternal by itself, ALWAYS go through DeleteDeepObject() | ||
126 | void DeepFactory::DeleteDeepObject(lua_State* const L_, DeepPrelude* const o_) | 127 | void DeepFactory::DeleteDeepObject(lua_State* const L_, DeepPrelude* const o_) |
127 | { | 128 | { |
128 | STACK_CHECK_START_REL(L_, 0); | 129 | STACK_CHECK_START_REL(L_, 0); |
@@ -310,7 +311,7 @@ int DeepFactory::pushDeepUserdata(DestState const L_, int const nuv_) const | |||
310 | 311 | ||
311 | if (_prelude->magic != kDeepVersion) { | 312 | if (_prelude->magic != kDeepVersion) { |
312 | // just in case, don't leak the newly allocated deep userdata object | 313 | // just in case, don't leak the newly allocated deep userdata object |
313 | deleteDeepObjectInternal(L_, _prelude); | 314 | DeleteDeepObject(L_, _prelude); |
314 | raise_luaL_error(L_, "Bad Deep Factory: kDeepVersion is incorrect, rebuild your implementation with the latest deep implementation"); | 315 | raise_luaL_error(L_, "Bad Deep Factory: kDeepVersion is incorrect, rebuild your implementation with the latest deep implementation"); |
315 | } | 316 | } |
316 | 317 | ||
@@ -319,7 +320,7 @@ int DeepFactory::pushDeepUserdata(DestState const L_, int const nuv_) const | |||
319 | 320 | ||
320 | if (lua_gettop(L_) - _oldtop != 0) { | 321 | if (lua_gettop(L_) - _oldtop != 0) { |
321 | // just in case, don't leak the newly allocated deep userdata object | 322 | // just in case, don't leak the newly allocated deep userdata object |
322 | deleteDeepObjectInternal(L_, _prelude); | 323 | DeleteDeepObject(L_, _prelude); |
323 | raise_luaL_error(L_, "Bad DeepFactory::newDeepObjectInternal overload: should not push anything on the stack"); | 324 | raise_luaL_error(L_, "Bad DeepFactory::newDeepObjectInternal overload: should not push anything on the stack"); |
324 | } | 325 | } |
325 | 326 | ||
diff --git a/src/lanes.cpp b/src/lanes.cpp index 4b4f9a8..41450f3 100644 --- a/src/lanes.cpp +++ b/src/lanes.cpp | |||
@@ -664,7 +664,7 @@ LUAG_FUNC(configure) | |||
664 | 664 | ||
665 | STACK_CHECK(L_, 2); | 665 | STACK_CHECK(L_, 2); |
666 | DeepFactory::PushDeepProxy(DestState{ L_ }, _U->timerLinda, 0, LookupMode::LaneBody, L_); // L_: settings M timerLinda | 666 | DeepFactory::PushDeepProxy(DestState{ L_ }, _U->timerLinda, 0, LookupMode::LaneBody, L_); // L_: settings M timerLinda |
667 | lua_setfield(L_, -2, "timer_gateway"); // L_: settings M | 667 | lua_setfield(L_, -2, "timerLinda"); // L_: settings M |
668 | STACK_CHECK(L_, 2); | 668 | STACK_CHECK(L_, 2); |
669 | 669 | ||
670 | // prepare the metatable for threads | 670 | // prepare the metatable for threads |
diff --git a/src/lanes.lua b/src/lanes.lua index 1c36b46..d5a04e5 100644 --- a/src/lanes.lua +++ b/src/lanes.lua | |||
@@ -376,8 +376,9 @@ local timer = function() error "timers are not active" end | |||
376 | local timers = timer | 376 | local timers = timer |
377 | local timer_lane = nil | 377 | local timer_lane = nil |
378 | 378 | ||
379 | -- timer_gateway should always exist, even when the settings disable the timers | 379 | -- timerLinda should always exist, even when the settings disable the timers |
380 | local timer_gateway | 380 | -- is upvalue of timer stuff and lanes.sleep() |
381 | local timerLinda | ||
381 | 382 | ||
382 | local TGW_KEY = "(timer control)" -- the key does not matter, a 'weird' key may help debugging | 383 | local TGW_KEY = "(timer control)" -- the key does not matter, a 'weird' key may help debugging |
383 | local TGW_QUERY, TGW_REPLY = "(timer query)", "(timer reply)" | 384 | local TGW_QUERY, TGW_REPLY = "(timer query)", "(timer reply)" |
@@ -387,7 +388,7 @@ local TGW_QUERY, TGW_REPLY = "(timer query)", "(timer reply)" | |||
387 | local configure_timers = function() | 388 | local configure_timers = function() |
388 | -- On first 'require "lanes"', a timer lane is spawned that will maintain | 389 | -- On first 'require "lanes"', a timer lane is spawned that will maintain |
389 | -- timer tables and sleep in between the timer events. All interaction with | 390 | -- timer tables and sleep in between the timer events. All interaction with |
390 | -- the timer lane happens via a 'timer_gateway' Linda, which is common to | 391 | -- the timer lane happens via a 'timerLinda' Linda, which is common to |
391 | -- all that 'require "lanes"'. | 392 | -- all that 'require "lanes"'. |
392 | -- | 393 | -- |
393 | -- Linda protocol to timer lane: | 394 | -- Linda protocol to timer lane: |
@@ -399,8 +400,8 @@ local configure_timers = function() | |||
399 | 400 | ||
400 | -- Timer lane; initialize only on the first 'require "lanes"' instance (which naturally has 'table' always declared) | 401 | -- Timer lane; initialize only on the first 'require "lanes"' instance (which naturally has 'table' always declared) |
401 | local first_time_key = "first time" | 402 | local first_time_key = "first time" |
402 | local first_time = timer_gateway:get(first_time_key) == nil | 403 | local first_time = timerLinda:get(first_time_key) == nil |
403 | timer_gateway:set(first_time_key, true) | 404 | timerLinda:set(first_time_key, true) |
404 | if first_time then | 405 | if first_time then |
405 | 406 | ||
406 | assert(type(now_secs) == "function") | 407 | assert(type(now_secs) == "function") |
@@ -552,7 +553,7 @@ local configure_timers = function() | |||
552 | return next_wakeup -- may be 'nil' | 553 | return next_wakeup -- may be 'nil' |
553 | end -- check_timers() | 554 | end -- check_timers() |
554 | 555 | ||
555 | local timer_gateway_batched = timer_gateway.batched | 556 | local timer_gateway_batched = timerLinda.batched |
556 | set_finalizer(function(err, stk) | 557 | set_finalizer(function(err, stk) |
557 | if err and type(err) ~= "userdata" then | 558 | if err and type(err) ~= "userdata" then |
558 | error("LanesTimer error: "..tostring(err)) | 559 | error("LanesTimer error: "..tostring(err)) |
@@ -572,18 +573,18 @@ local configure_timers = function() | |||
572 | secs = next_wakeup - now_secs() | 573 | secs = next_wakeup - now_secs() |
573 | if secs < 0 then secs = 0 end | 574 | if secs < 0 then secs = 0 end |
574 | end | 575 | end |
575 | local key, what = timer_gateway:receive(secs, TGW_KEY, TGW_QUERY) | 576 | local key, what = timerLinda:receive(secs, TGW_KEY, TGW_QUERY) |
576 | 577 | ||
577 | if key == TGW_KEY then | 578 | if key == TGW_KEY then |
578 | assert(getmetatable(what) == "Linda") -- 'what' should be a linda on which the client sets a timer | 579 | assert(getmetatable(what) == "Linda") -- 'what' should be a linda on which the client sets a timer |
579 | local _, key, wakeup_at, period = timer_gateway:receive(0, timer_gateway_batched, TGW_KEY, 3) | 580 | local _, key, wakeup_at, period = timerLinda:receive(0, timer_gateway_batched, TGW_KEY, 3) |
580 | assert(key) | 581 | assert(key) |
581 | set_timer(what, key, wakeup_at, period and period > 0 and period or nil) | 582 | set_timer(what, key, wakeup_at, period and period > 0 and period or nil) |
582 | elseif key == TGW_QUERY then | 583 | elseif key == TGW_QUERY then |
583 | if what == "get_timers" then | 584 | if what == "get_timers" then |
584 | timer_gateway:send(TGW_REPLY, get_timers()) | 585 | timerLinda:send(TGW_REPLY, get_timers()) |
585 | else | 586 | else |
586 | timer_gateway:send(TGW_REPLY, "unknown query " .. what) | 587 | timerLinda:send(TGW_REPLY, "unknown query " .. what) |
587 | end | 588 | end |
588 | --elseif secs == nil then -- got no value while block-waiting? | 589 | --elseif secs == nil then -- got no value while block-waiting? |
589 | -- WR("timer lane: no linda, aborted?") | 590 | -- WR("timer lane: no linda, aborted?") |
@@ -610,7 +611,7 @@ local configure_timers = function() | |||
610 | linda_:set(key_, now_secs()) | 611 | linda_:set(key_, now_secs()) |
611 | 612 | ||
612 | if not period_ or period_ == 0.0 then | 613 | if not period_ or period_ == 0.0 then |
613 | timer_gateway:send(TGW_KEY, linda_, key_, nil, nil ) -- clear the timer | 614 | timerLinda:send(TGW_KEY, linda_, key_, nil, nil ) -- clear the timer |
614 | return -- nothing more to do | 615 | return -- nothing more to do |
615 | end | 616 | end |
616 | when_ = period_ | 617 | when_ = period_ |
@@ -620,7 +621,7 @@ local configure_timers = function() | |||
620 | or (when_ and now_secs()+when_ or nil) | 621 | or (when_ and now_secs()+when_ or nil) |
621 | -- queue to timer | 622 | -- queue to timer |
622 | -- | 623 | -- |
623 | timer_gateway:send(TGW_KEY, linda_, key_, wakeup_at, period_) | 624 | timerLinda:send(TGW_KEY, linda_, key_, wakeup_at, period_) |
624 | end -- timer() | 625 | end -- timer() |
625 | 626 | ||
626 | ----- | 627 | ----- |
@@ -628,11 +629,11 @@ local configure_timers = function() | |||
628 | -- | 629 | -- |
629 | -- PUBLIC LANES API | 630 | -- PUBLIC LANES API |
630 | timers = function() | 631 | timers = function() |
631 | timer_gateway:send(TGW_QUERY, "get_timers") | 632 | timerLinda:send(TGW_QUERY, "get_timers") |
632 | local _, r = timer_gateway:receive(TGW_REPLY) | 633 | local _, r = timerLinda:receive(TGW_REPLY) |
633 | return r | 634 | return r |
634 | end -- timers() | 635 | end -- timers() |
635 | end | 636 | end -- configure_timers() |
636 | 637 | ||
637 | -- ################################################################################################# | 638 | -- ################################################################################################# |
638 | -- ###################################### lanes.sleep() ############################################ | 639 | -- ###################################### lanes.sleep() ############################################ |
@@ -651,8 +652,8 @@ local sleep = function(seconds_) | |||
651 | error("invalid duration " .. string_format("%q", tostring(seconds_))) | 652 | error("invalid duration " .. string_format("%q", tostring(seconds_))) |
652 | end | 653 | end |
653 | -- receive data on a channel no-one ever sends anything, thus blocking for the specified duration | 654 | -- receive data on a channel no-one ever sends anything, thus blocking for the specified duration |
654 | return timer_gateway:receive(seconds_, "ac100de1-a696-4619-b2f0-a26de9d58ab8") | 655 | return timerLinda:receive(seconds_, "ac100de1-a696-4619-b2f0-a26de9d58ab8") |
655 | end -- sleep | 656 | end -- sleep() |
656 | 657 | ||
657 | -- ################################################################################################# | 658 | -- ################################################################################################# |
658 | -- ##################################### lanes.genlock() ########################################### | 659 | -- ##################################### lanes.genlock() ########################################### |
@@ -782,7 +783,7 @@ local configure = function(settings_) | |||
782 | -- avoid pulling the whole core module as upvalue when cancel_error is enough | 783 | -- avoid pulling the whole core module as upvalue when cancel_error is enough |
783 | -- these are locals declared above, that we need to set prior to calling configure_timers() | 784 | -- these are locals declared above, that we need to set prior to calling configure_timers() |
784 | cancel_error = assert(core.cancel_error) | 785 | cancel_error = assert(core.cancel_error) |
785 | timer_gateway = assert(core.timer_gateway) | 786 | timerLinda = assert(core.timerLinda) |
786 | 787 | ||
787 | if settings.with_timers then | 788 | if settings.with_timers then |
788 | configure_timers(settings) | 789 | configure_timers(settings) |
diff --git a/tests/keeper.lua b/tests/keeper.lua index d08dd98..2d432f4 100644 --- a/tests/keeper.lua +++ b/tests/keeper.lua | |||
@@ -4,99 +4,170 @@ | |||
4 | -- Test program for Lua Lanes | 4 | -- Test program for Lua Lanes |
5 | -- | 5 | -- |
6 | -- TODO: there is a random crash when nb_user_keepers > 1. Will have to investigate if it rears its ugly head again | 6 | -- TODO: there is a random crash when nb_user_keepers > 1. Will have to investigate if it rears its ugly head again |
7 | local lanes = require "lanes".configure{ nb_user_keepers = 3, keepers_gc_threshold = 500 } | 7 | -- 3 keepers in addition to the one reserved for the timer linda |
8 | local require_lanes_result_1, require_lanes_result_2 = require "lanes".configure{nb_user_keepers = 3, keepers_gc_threshold = 500} | ||
9 | print("require_lanes_result:", require_lanes_result_1, require_lanes_result_2) | ||
10 | local lanes = require_lanes_result_1 | ||
8 | 11 | ||
9 | do | 12 | local require_assert_result_1, require_assert_result_2 = require "assert" -- assert.fails() |
10 | print "Linda names test:" | 13 | print("require_assert_result:", require_assert_result_1, require_assert_result_2) |
11 | local unnamedLinda = lanes.linda(1) | 14 | |
15 | -- ################################################################################################# | ||
16 | |||
17 | local print_id = 0 | ||
18 | local P = function(whence_, ...) | ||
19 | print_id = print_id + 1 | ||
20 | print(whence_, print_id .. ".", ...) | ||
21 | end | ||
22 | |||
23 | local PRINT = function(...) P("main", ...) end | ||
24 | |||
25 | local DONE = function() | ||
26 | PRINT "collecting garbage" | ||
27 | collectgarbage() | ||
28 | PRINT "SUCCESS\n" | ||
29 | end | ||
30 | |||
31 | -- ################################################################################################# | ||
32 | -- ################################################################################################# | ||
33 | |||
34 | if false then | ||
35 | PRINT "=========================================================================================" | ||
36 | PRINT "Linda groups test:" | ||
37 | |||
38 | local createLinda = function(...) | ||
39 | return lanes.linda(...) | ||
40 | end | ||
41 | |||
42 | -- should succeed | ||
43 | assert.failsnot(function() createLinda("zero", 0) end) | ||
44 | assert.failsnot(function() createLinda("one", 1) end) | ||
45 | assert.failsnot(function() createLinda("two", 2) end) | ||
46 | assert.failsnot(function() createLinda("three", 3) end) | ||
47 | -- should fail (and not create the lindas) | ||
48 | assert.fails(function() createLinda("minus 1", -1) end) | ||
49 | assert.fails(function() createLinda("none") end) | ||
50 | assert.fails(function() createLinda("four", 4) end) | ||
51 | |||
52 | end | ||
53 | -- should only collect the 4 successfully created lindas | ||
54 | DONE() | ||
55 | |||
56 | -- ################################################################################################# | ||
57 | |||
58 | if false then | ||
59 | PRINT "=========================================================================================" | ||
60 | PRINT "Linda names test:" | ||
61 | local unnamedLinda1 = lanes.linda(1) | ||
12 | local unnamedLinda2 = lanes.linda("", 2) | 62 | local unnamedLinda2 = lanes.linda("", 2) |
13 | local veeeerrrryyyylooongNamedLinda= lanes.linda( "veeeerrrryyyylooongNamedLinda", 3) | 63 | local veeeerrrryyyylooongNamedLinda3 = lanes.linda( "veeeerrrryyyylooongNamedLinda", 3) |
14 | print(unnamedLinda, unnamedLinda2, veeeerrrryyyylooongNamedLinda) | 64 | assert(tostring(veeeerrrryyyylooongNamedLinda3) == "Linda: veeeerrrryyyylooongNamedLinda") |
15 | print "GC deadlock test start" | 65 | local shortNamedLinda0 = lanes.linda( "short", 0) |
16 | -- store a linda in another linda (-> in a keeper) | 66 | assert(tostring(shortNamedLinda0) == "Linda: short") |
17 | unnamedLinda:set("here", lanes.linda("temporary linda", 0)) | 67 | PRINT(shortNamedLinda0, unnamedLinda1, unnamedLinda2, veeeerrrryyyylooongNamedLinda3) |
18 | -- repeatedly add and remove stuff in the linda so that a GC happens during the keeper operation | 68 | end |
69 | -- collect the 4 lindas we created | ||
70 | DONE() | ||
71 | |||
72 | -- ################################################################################################# | ||
73 | |||
74 | if true then | ||
75 | PRINT "=========================================================================================" | ||
76 | PRINT "Linda GC test:" | ||
77 | local a = lanes.linda("A", 1) | ||
78 | local b = lanes.linda("B", 2) | ||
79 | local c = lanes.linda("C", 3) | ||
80 | |||
81 | -- store lindas in each other and in themselves | ||
82 | a:set("here", lanes.linda("temporary linda", 0)) | ||
83 | b:set("here", a, b, c) | ||
84 | c:set("here", a, b, c) | ||
85 | |||
86 | -- repeatedly add and remove stuff in the linda 'a' so that a GC happens during the keeper operation | ||
19 | for i = 1, 100 do | 87 | for i = 1, 100 do |
88 | io.stdout:write "." | ||
20 | for j = 1, 1000 do -- send 1000 tables | 89 | for j = 1, 1000 do -- send 1000 tables |
21 | -- print("send #" .. j) | 90 | -- PRINT("send #" .. j) |
22 | unnamedLinda:send("here", {"a", "table", "with", "some", "stuff"}) | 91 | a:send("here", {"a", "table", "with", "some", "stuff"}, j) |
23 | end | 92 | end |
24 | -- print(clearing) | 93 | -- PRINT(clearing) |
25 | unnamedLinda:set("here") -- clear everything | 94 | a:set("here") -- clear everything, including the temporary linda for which we have no reference |
26 | end | 95 | end |
96 | io.stdout:write "\n" | ||
97 | b:set("here") | ||
98 | c:set("here") | ||
27 | end | 99 | end |
28 | print "collecting garbage" | 100 | -- should successfully collect a, b, and c and destroy the underlying Deep objects |
29 | collectgarbage() | 101 | DONE() |
30 | print "GC deadlock test done" | ||
31 | 102 | ||
32 | local print_id = 0 | 103 | -- ################################################################################################# |
33 | local PRINT = function(...) | ||
34 | print_id = print_id + 1 | ||
35 | print("main", print_id .. ".", ...) | ||
36 | end | ||
37 | 104 | ||
38 | local function keeper(linda) | 105 | if false then |
39 | local mt= { | 106 | PRINT "=========================================================================================" |
40 | __index= function( _, key ) | 107 | PRINT "General test:" |
41 | return linda:get( key ) | ||
42 | end, | ||
43 | __newindex= function( _, key, val ) | ||
44 | linda:set( key, val ) | ||
45 | end | ||
46 | } | ||
47 | return setmetatable( {}, mt ) | ||
48 | end | ||
49 | 108 | ||
50 | -- | 109 | local function keeper(linda) |
51 | local lindaA= lanes.linda( "A", 1) | 110 | local mt= { |
52 | local A= keeper( lindaA ) | 111 | __index= function( _, key ) |
53 | 112 | return linda:get( key ) | |
54 | local lindaB= lanes.linda( "B", 2) | 113 | end, |
55 | local B= keeper( lindaB ) | 114 | __newindex= function( _, key, val ) |
56 | 115 | linda:set( key, val ) | |
57 | local lindaC= lanes.linda( "C", 3) | 116 | end |
58 | local C= keeper( lindaC ) | 117 | } |
59 | print("Created", lindaA, lindaB, lindaC) | 118 | return setmetatable( {}, mt ) |
60 | |||
61 | A.some= 1 | ||
62 | PRINT("A.some == " .. A.some ) | ||
63 | assert( A.some==1 ) | ||
64 | |||
65 | B.some= "hoo" | ||
66 | PRINT("B.some == " .. B.some ) | ||
67 | assert( B.some=="hoo" ) | ||
68 | assert( A.some==1 ) | ||
69 | assert( C.some==nil ) | ||
70 | |||
71 | function lane() | ||
72 | local print_id = 0 | ||
73 | local PRINT = function(...) | ||
74 | print_id = print_id + 1 | ||
75 | print("lane", print_id .. ".", ...) | ||
76 | end | 119 | end |
120 | |||
121 | -- | ||
122 | local lindaA= lanes.linda( "A", 1) | ||
123 | local A= keeper( lindaA ) | ||
124 | |||
125 | local lindaB= lanes.linda( "B", 2) | ||
126 | local B= keeper( lindaB ) | ||
127 | |||
128 | local lindaC= lanes.linda( "C", 3) | ||
129 | local C= keeper( lindaC ) | ||
130 | PRINT("Created", lindaA, lindaB, lindaC) | ||
131 | |||
132 | A.some= 1 | ||
133 | PRINT("A.some == " .. A.some ) | ||
134 | assert( A.some==1 ) | ||
135 | |||
136 | B.some= "hoo" | ||
137 | PRINT("B.some == " .. B.some ) | ||
138 | assert( B.some=="hoo" ) | ||
139 | assert( A.some==1 ) | ||
140 | assert( C.some==nil ) | ||
141 | |||
142 | function lane() | ||
143 | local PRINT = function(...) P("lane", ...) end | ||
77 | 144 | ||
78 | local a= keeper(lindaA) | 145 | local a= keeper(lindaA) |
79 | PRINT("a.some == " .. a.some ) | 146 | PRINT("a.some == " .. a.some ) |
80 | assert( a.some==1 ) | 147 | assert( a.some==1 ) |
81 | a.some= 2 | 148 | a.some= 2 |
82 | assert( a.some==2 ) | 149 | assert( a.some==2 ) |
83 | PRINT("a.some == " .. a.some ) | 150 | PRINT("a.some == " .. a.some ) |
84 | |||
85 | local c = keeper(lindaC) | ||
86 | assert( c.some==nil ) | ||
87 | PRINT("c.some == " .. tostring(c.some)) | ||
88 | c.some= 3 | ||
89 | assert( c.some==3 ) | ||
90 | PRINT("c.some == " .. c.some) | ||
91 | end | ||
92 | 151 | ||
93 | PRINT("lane started") | 152 | local c = keeper(lindaC) |
94 | local h= lanes.gen( "io", lane )() | 153 | assert( c.some==nil ) |
95 | PRINT("lane joined:", h:join()) | 154 | PRINT("c.some == " .. tostring(c.some)) |
155 | c.some= 3 | ||
156 | assert( c.some==3 ) | ||
157 | PRINT("c.some == " .. c.some) | ||
158 | end | ||
159 | |||
160 | PRINT("lane started") | ||
161 | local h= lanes.gen( "io", lane )() | ||
162 | PRINT("lane joined:", h:join()) | ||
163 | |||
164 | PRINT("A.some = " .. A.some ) | ||
165 | assert( A.some==2 ) | ||
166 | PRINT("C.some = " .. C.some ) | ||
167 | assert( C.some==3 ) | ||
168 | lindaC:set("some") | ||
169 | assert( C.some==nil ) | ||
170 | end | ||
171 | DONE() | ||
96 | 172 | ||
97 | PRINT("A.some = " .. A.some ) | 173 | print "\nTEST OK" \ No newline at end of file |
98 | assert( A.some==2 ) | ||
99 | PRINT("C.some = " .. C.some ) | ||
100 | assert( C.some==3 ) | ||
101 | lindaC:set("some") | ||
102 | assert( C.some==nil ) | ||
diff --git a/tests/nb_keepers.lua b/tests/nb_keepers.lua deleted file mode 100644 index 575138c..0000000 --- a/tests/nb_keepers.lua +++ /dev/null | |||
@@ -1,20 +0,0 @@ | |||
1 | -- 2 keepers in addition to the one reserved for the timer linda | ||
2 | local require_lanes_result_1, require_lanes_result_2 = require "lanes".configure{nb_user_keepers = 2} | ||
3 | print("require_lanes_result:", require_lanes_result_1, require_lanes_result_2) | ||
4 | local lanes = require_lanes_result_1 | ||
5 | |||
6 | local require_assert_result_1, require_assert_result_2 = require "assert" -- assert.fails() | ||
7 | print("require_assert_result:", require_assert_result_1, require_assert_result_2) | ||
8 | |||
9 | local createLinda = function(...) | ||
10 | return lanes.linda(...) | ||
11 | end | ||
12 | |||
13 | -- should succeed | ||
14 | assert.failsnot(function() createLinda("one", 1) end) | ||
15 | assert.failsnot(function() createLinda("two", 2) end) | ||
16 | -- should fail | ||
17 | assert.fails(function() createLinda("none") end) | ||
18 | assert.fails(function() createLinda("zero", 0) end) | ||
19 | assert.fails(function() createLinda("three", 3) end) | ||
20 | print "TEST OK" | ||