aboutsummaryrefslogtreecommitdiff
path: root/unit_tests/deep_tests.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--unit_tests/deep_tests.cpp152
1 files changed, 73 insertions, 79 deletions
diff --git a/unit_tests/deep_tests.cpp b/unit_tests/deep_tests.cpp
index c1708e1..60dadb7 100644
--- a/unit_tests/deep_tests.cpp
+++ b/unit_tests/deep_tests.cpp
@@ -8,94 +8,88 @@
8// ################################################################################################# 8// #################################################################################################
9// ################################################################################################# 9// #################################################################################################
10 10
11class DeepTests : public ::testing::Test 11TEST_CASE("deep_test")
12{ 12{
13 protected:
14 LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } }; 13 LuaState S{ LuaState::WithBaseLibs{ true }, LuaState::WithFixture{ true } };
14 S.requireSuccess(
15 " lanes = require 'lanes'.configure()"
16 " fixture = require 'fixture'"
17 " deep_test = require 'deep_test'"
18 );
15 19
16 void SetUp() override 20 SECTION("garbage collection collects")
17 { 21 {
18 std::ignore = S.doString("lanes = require 'lanes'.configure()"); 22 S.requireSuccess("assert(true)");
19 std::ignore = S.doString("fixture = require 'fixture'"); 23 S.requireFailure("assert(false)");
20 std::ignore = S.doString("deep_test = require 'deep_test'"); 24 if constexpr (LUA_VERSION_NUM >= 503) { // Lua < 5.3 only supports a table uservalue
25 S.requireSuccess(
26 // create a deep userdata object without referencing it. First uservalue is a function, and should be called on __gc
27 " deep_test.new_deep(1):setuv(1, function() collected = collected and collected + 1 or 1 end)"
28 " deep_test.new_deep(1):setuv(1, function() collected = collected and collected + 1 or 1 end)"
29 " collectgarbage()" // and collect it
30 " assert(collected == 2)"
31 );
32 }
21 } 33 }
22};
23 34
24// ################################################################################################# 35 // ---------------------------------------------------------------------------------------------
25// #################################################################################################
26 36
27TEST_F(DeepTests, DeepIsCollected) 37 SECTION("reference counting")
28{ 38 {
29 ASSERT_EQ(S.doString("assert(true)"), LuaError::OK) << S; 39 S.requireSuccess(
30 ASSERT_NE(S.doString("assert(false)"), LuaError::OK) << S; 40 " d = deep_test.new_deep(1)" // create a deep userdata object
31 if constexpr (LUA_VERSION_NUM >= 503) { // Lua < 5.3 only supports a table uservalue 41 " d:set(42)" // set some value
32 ASSERT_EQ(S.doString( 42 " assert(d:refcount() == 1)"
33 // create a deep userdata object without referencing it. First uservalue is a function, and should be called on __gc 43 );
34 " deep_test.new_deep(1):setuv(1, function() collected = collected and collected + 1 or 1 end)" 44 S.requireSuccess(
35 " deep_test.new_deep(1):setuv(1, function() collected = collected and collected + 1 or 1 end)" 45 " l = lanes.linda()"
36 " collectgarbage()" // and collect it 46 " b, s = l:set('k', d, d)" // store it twice in the linda
37 " assert(collected == 2)" 47 " assert(b == false and s == 'under')" // no waking, under capacity
38 ), LuaError::OK) << S; 48 " assert(d:refcount() == 2)" // 1 ref here, 1 in the keeper (even if we sent it twice)
49 );
50 S.requireSuccess(
51 " n, d = l:get('k')" // pull it out of the linda
52 " assert(n == 1 and type(d) == 'userdata')" // got 1 item out of the linda
53 " assert(d:get() == 42 and d:refcount() == 2)" // 1 ref here, 1 in the keeper (even if we sent it twice)
54 );
55 S.requireSuccess(
56 " l = nil"
57 " collectgarbage()" // clears the linda, removes its storage from the keeper
58 " lanes.collectgarbage()" // collect garbage inside the keepers too, to finish cleanup
59 " assert(d:refcount() == 1)" // 1 ref here
60 );
61 if constexpr (LUA_VERSION_NUM >= 503) { // Lua < 5.3 only supports a table uservalue
62 S.requireSuccess(
63 " d:setuv(1, function() collected = collected and collected + 1 or 1 end)"
64 " d = nil" // clear last reference
65 " collectgarbage()" // force collection
66 " assert(collected == 1)" // we should see it
67 );
68 }
39 } 69 }
40}
41 70
42// ################################################################################################# 71 // ---------------------------------------------------------------------------------------------
43 72
44TEST_F(DeepTests, DeepRefcounting) 73 SECTION("collection from inside a Linda")
45{ 74 {
46 ASSERT_EQ(S.doString( 75 S.requireSuccess(
47 " d = deep_test.new_deep(1)" // create a deep userdata object 76 " d = deep_test.new_deep(1)" // create a deep userdata object
48 " d:set(42)" // set some value 77 " d:set(42)" // set some value
49 " assert(d:refcount() == 1)" 78 " assert(d:refcount() == 1)"
50 ), LuaError::OK) << S; 79 );
51 ASSERT_EQ(S.doString( 80 S.requireSuccess(
52 " l = lanes.linda()" 81 " l = lanes.linda()"
53 " b, s = l:set('k', d, d)" // store it twice in the linda 82 " b, s = l:set('k', d, d)" // store it twice in the linda
54 " assert(b == false and s == 'under')" // no waking, under capacity 83 " assert(b == false and s == 'under')" // no waking, under capacity
55 " assert(d:refcount() == 2)" // 1 ref here, 1 in the keeper (even if we sent it twice) 84 " assert(d:refcount() == 2)" // 1 ref here, 1 in the keeper (even if we sent it twice)
56 ), LuaError::OK) << S; 85 );
57 ASSERT_EQ(S.doString( 86 S.requireSuccess(
58 " n, d = l:get('k')" // pull it out of the linda 87 " d = nil"
59 " assert(n == 1 and type(d) == 'userdata')" // got 1 item out of the linda 88 " collectgarbage()" // force collection
60 " assert(d:get() == 42 and d:refcount() == 2)" // 1 ref here, 1 in the keeper (even if we sent it twice) 89 " l = nil"
61 ), LuaError::OK) << S; 90 " collectgarbage()" // clears the linda, removes its storage from the keeper
62 ASSERT_EQ(S.doString( 91 " lanes.collectgarbage()" // collect garbage inside the keepers too, to finish cleanup
63 " l = nil" 92 " assert(deep_test.get_deep_count() == 0)"
64 " collectgarbage()" // clears the linda, removes its storage from the keeper 93 );
65 " lanes.collectgarbage()" // collect garbage inside the keepers too, to finish cleanup
66 " assert(d:refcount() == 1)" // 1 ref here
67 ), LuaError::OK) << S;
68 if constexpr (LUA_VERSION_NUM >= 503) { // Lua < 5.3 only supports a table uservalue
69 ASSERT_EQ(S.doString(
70 " d:setuv(1, function() collected = collected and collected + 1 or 1 end)"
71 " d = nil" // clear last reference
72 " collectgarbage()" // force collection
73 " assert(collected == 1)" // we should see it
74 ), LuaError::OK) << S;
75 } 94 }
76}
77
78// #################################################################################################
79
80TEST_F(DeepTests, DeepCollectedFromInsideLinda)
81{
82 ASSERT_EQ(S.doString(
83 " d = deep_test.new_deep(1)" // create a deep userdata object
84 " d:set(42)" // set some value
85 " assert(d:refcount() == 1)"
86 ), LuaError::OK) << S;
87 ASSERT_EQ(S.doString(
88 " l = lanes.linda()"
89 " b, s = l:set('k', d, d)" // store it twice in the linda
90 " assert(b == false and s == 'under')" // no waking, under capacity
91 " assert(d:refcount() == 2)" // 1 ref here, 1 in the keeper (even if we sent it twice)
92 ), LuaError::OK) << S;
93 ASSERT_EQ(S.doString(
94 " d = nil"
95 " collectgarbage()" // force collection
96 " l = nil"
97 " collectgarbage()" // clears the linda, removes its storage from the keeper
98 " lanes.collectgarbage()" // collect garbage inside the keepers too, to finish cleanup
99 " assert(deep_test.get_deep_count() == 0)"
100 ), LuaError::OK) << S;
101} \ No newline at end of file 95} \ No newline at end of file