effil/tests/lua/shared_table.lua
mihacooper cac3cd09e7 Dealing with userdata types and metatable (#35)
* merge fixes

* add Lua version logging to test

* move StoredObject to shared_ptr

* rewrite metamethods impl

* fix for SEGFAULT, I hope
2017-04-06 18:54:00 +03:00

252 lines
8.6 KiB
Lua

TestSharedTable = {tearDown = tearDown}
function TestSharedTable:testPairs()
local share = effil.table()
local data = { 0, 0, 0, ["key1"] = 0, ["key2"] = 0, ["key3"] = 0 }
for k, _ in pairs(data) do
share[k] = k .. "-value"
end
for k,v in pairs(share) do
test.assertEquals(data[k], 0)
data[k] = 1
test.assertEquals(v, k .. "-value")
end
for k,v in pairs(data) do
log("Check: " .. k)
test.assertEquals(v, 1)
end
for k,v in ipairs(share) do
test.assertEquals(data[k], 1)
data[k] = 2
test.assertEquals(v, k .. "-value")
end
for k,v in ipairs(data) do
log("Check: " .. k)
test.assertEquals(v, 2)
end
end
function TestSharedTable:testLength()
local share = effil.table()
share[1] = 10
share[2] = 20
share[3] = 30
share[4] = 40
share["str"] = 50
log "Check values"
test.assertEquals(#share, 4)
share[3] = nil
test.assertEquals(#share, 2)
share[1] = nil
test.assertEquals(#share, 0)
end
function TestSharedTable:testSize()
local share = effil.table()
test.assertEquals(effil.size(share), 0)
share[1] = 10
test.assertEquals(effil.size(share), 1)
share[2] = "value1"
share["key1"] = function() end
test.assertEquals(effil.size(share), 3)
share[2] = nil
test.assertEquals(effil.size(share), 2)
end
function TestSharedTable:testUserDataClassification()
local share = effil.table()
share.thread = effil.thread(function(a, b) return a + b end)(19, 33)
share.sub_table = effil.table()
share.sub_table.some_key = "some_value"
local result = share.thread:get()
test.assertEquals(result, 52)
test.assertEquals(share.sub_table.some_key, "some_value")
end
TestGeneralSharedTableMetaTable = { tearDown = tearDown }
function TestGeneralSharedTableMetaTable:useMetatable(shared_table, metatable)
local mt = self.test_param()
for k, v in pairs(metatable) do
mt[k] = v
end
effil.setmetatable(shared_table, mt)
end
function TestGeneralSharedTableMetaTable:testMetamethodIndex()
local share = effil.table()
self:useMetatable(share, {
__index = function(t, key)
return "mt_" .. effil.rawget(t, key)
end
}
)
share.table_key = "table_value"
test.assertEquals(share.table_key, "mt_table_value")
end
function TestGeneralSharedTableMetaTable:testMetamethodNewIndex()
local share = effil.table()
self:useMetatable(share, {
__newindex = function(t, key, value)
effil.rawset(t, "mt_" .. key, "mt_" .. value)
end
}
)
share.table_key = "table_value"
test.assertEquals(share.mt_table_key, "mt_table_value")
end
function TestGeneralSharedTableMetaTable:testMetamethodCall()
local share = effil.table()
self:useMetatable(share, {
__call = function(t, val1, val2, val3)
return tostring(val1) .. "_" .. tostring(val2), tostring(val2) .. "_" .. tostring(val3)
end
}
)
local first_ret, second_ret = share("val1", "val2", "val3")
test.assertEquals(first_ret, "val1_val2")
test.assertEquals(second_ret, "val2_val3")
end
local function CreateMetatableTestForBinaryOperator(method_info, op)
for _, reversed in pairs({true, false}) do
TestGeneralSharedTableMetaTable["testMetamethod" .. method_info.metamethod
.. (reversed and "Reversed" or "")] =
function(self)
local testTable, operand = effil.table(), effil.table()
self:useMetatable(testTable, {
['__' .. string.lower(method_info.metamethod)] =
reversed and function(left, right)
right.was_called = true
return right.value .. '_'.. left.value
end
or function(left, right)
left.was_called = true
return left.value .. '_'.. right.value
end
}
)
testTable.was_called = false
testTable.value = "left"
operand.value = "right"
local left_operand, right_operand = unpack(reversed and {operand, testTable} or {testTable, operand})
test.assertEquals(op(left_operand, right_operand),
method_info.exp_value == nil and "left_right" or method_info.exp_value)
test.assertTrue(testTable.was_called)
end
end
end
CreateMetatableTestForBinaryOperator({ metamethod = "Concat"}, function(a, b) return a.. b end)
CreateMetatableTestForBinaryOperator({ metamethod = "Add"}, function(a, b) return a + b end)
CreateMetatableTestForBinaryOperator({ metamethod = "Sub"}, function(a, b) return a - b end)
CreateMetatableTestForBinaryOperator({ metamethod = "Mul"}, function(a, b) return a * b end)
CreateMetatableTestForBinaryOperator({ metamethod = "Div"}, function(a, b) return a / b end)
CreateMetatableTestForBinaryOperator({ metamethod = "Mod"}, function(a, b) return a % b end)
CreateMetatableTestForBinaryOperator({ metamethod = "Pow"}, function(a, b) return a ^ b end)
CreateMetatableTestForBinaryOperator({ metamethod = "Le", exp_value = true }, function(a, b) return a <= b end)
CreateMetatableTestForBinaryOperator({ metamethod = "Lt", exp_value = true }, function(a, b) return a < b end)
CreateMetatableTestForBinaryOperator({ metamethod = "Eq", exp_value = true },
function(a, b) return a == b end)
local function CreateMetatableTestForUnaryOperator(methodName, op)
TestGeneralSharedTableMetaTable["testMetamethod" .. methodName] =
function(self)
local share = effil.table()
self:useMetatable(share, {
['__' .. string.lower(methodName)] = function(t)
t.was_called = true
return t.value .. "_suffix"
end
}
)
share.was_called = false
share.value = "value"
test.assertEquals(op(share), "value_suffix")
test.assertTrue(share.was_called)
end
end
CreateMetatableTestForUnaryOperator("Unm", function(a) return -a end)
CreateMetatableTestForUnaryOperator("ToString", function(a) return tostring(a) end)
CreateMetatableTestForUnaryOperator("Len", function(a) return #a end)
make_test_with_param(TestGeneralSharedTableMetaTable, ".+" --[[ Any test in this test suite]],
function() return {} end,
function() return effil.table() end
)
TestSharedTableWithMetaTable = { tearDown = tearDown }
function TestSharedTableWithMetaTable:testMetamethodIterators()
local share = effil.table()
local iterator = self.test_param
effil.setmetatable(share, {
["__" .. iterator] = function(table)
return function(t, key)
local effil = require 'effil'
local ret = (key and key * 2) or 1
if ret > 2 ^ 10 then
return nil
end
return ret, effil.rawget(t, ret)
end, table
end
}
)
-- Add some values
for i = 0, 10 do
local pow = 2 ^ i
share[pow] = math.random(pow)
end
-- Add some noise
for i = 1, 100 do
share[math.random(1000) * 10 - 1] = math.random(1000)
end
-- Check that *pairs iterator works
local pow_iter = 1
for k,v in _G[iterator](share) do
test.assertEquals(k, pow_iter)
test.assertEquals(v, share[pow_iter])
pow_iter = pow_iter * 2
end
test.assertEquals(pow_iter, 2 ^ 11)
end
make_test_with_param(TestSharedTableWithMetaTable, "testMetamethodIterators", "pairs", "ipairs")
function TestSharedTableWithMetaTable:testMetatableAsSharedTable()
local share = effil.table()
local mt = effil.table()
effil.setmetatable(share, mt)
-- Empty metatable
test.assertEquals(share.table_key, nil)
-- Only __index metamethod
mt.__index = function(t, key)
return "mt_" .. effil.rawget(t, key)
end
share.table_key = "table_value"
test.assertEquals(share.table_key, "mt_table_value")
-- Both __index and __newindex metamethods
mt.__newindex = function(t, key, value)
effil.rawset(t, key, "mt_" .. value)
end
share.table_key = "table_value"
test.assertEquals(share.table_key, "mt_mt_table_value")
-- Remove __index, use only __newindex metamethods
mt.__index = nil
share.table_key = "table_value"
test.assertEquals(share.table_key, "mt_table_value")
end