Toggle menu
15
236
90
27.9K
Kenshi Wiki
Toggle preferences menu
Toggle personal menu
Not logged in
Your IP address will be publicly visible if you make any edits.
Refer to
Module:TableTools



-- Unit tests for [[Module:TableTools]]. Click talk page to run tests.

local tt = require('Module:TableTools/sandbox') -- the module to be tested
local ScribuntoUnit = require('Module:ScribuntoUnit')
local suite = ScribuntoUnit:new()

------------------------------------------------------------------------
-- Helper functions
------------------------------------------------------------------------

function suite.concatIpairs(t)
	local ret = ''
	for i, v in ipairs(t) do
		ret = ret .. tostring(v)
	end
	return ret
end

suite.isNan = tt.isNan

function suite:assertErrorEquals(expected, func, ...)
	local success, msg = pcall(func, ...)
	self:assertEquals(expected, msg)
end

function suite:assertTypeErrorEquals(argId, name, expectedType, actualType, func, ...)
	local expected = "bad argument #%d to '%s' (%s expected, got %s)"
	expected = expected:format(argId, name, expectedType, actualType)
	self:assertErrorEquals(expected, func, ...)
end

------------------------------------------------------------------------
-- Test isPositiveInteger
------------------------------------------------------------------------

function suite:testIsPositiveInteger()
	self:assertTrue(tt.isPositiveInteger(1))
	self:assertTrue(tt.isPositiveInteger(2))
	self:assertTrue(tt.isPositiveInteger(2323874623))
	self:assertFalse(tt.isPositiveInteger(0))
	self:assertFalse(tt.isPositiveInteger(-1))
	self:assertFalse(tt.isPositiveInteger(0.5))
	self:assertFalse(tt.isPositiveInteger(1.5))
	self:assertFalse(tt.isPositiveInteger('1'))
	self:assertFalse(tt.isPositiveInteger(math.huge))
	self:assertFalse(tt.isPositiveInteger('foo'))
end

------------------------------------------------------------------------
-- Test isNan
------------------------------------------------------------------------

function suite:testIsNan()
	self:assertTrue(tt.isNan(0/0))
	self:assertTrue(tt.isNan(-(0/0)))
	self:assertTrue(tt.isNan(math.huge * 0))
	self:assertTrue(tt.isNan(-math.huge * 0))
	self:assertTrue(tt.isNan(-1 * math.huge * 0))
	self:assertFalse(tt.isNan(0))
	self:assertFalse(tt.isNan(1))
	self:assertFalse(tt.isNan(6))
	self:assertFalse(tt.isNan(-100))
	self:assertFalse(tt.isNan(2^0.5))
	self:assertFalse(tt.isNan(99999999999999999999999999999999999999999999999))
	self:assertFalse(tt.isNan(math.pi))
end

------------------------------------------------------------------------
-- Test removeDuplicates
------------------------------------------------------------------------

function suite:testRemoveDuplicates()
	local dupes =     {1, 2, 2, 3, 3, 3, 4, 2, 0/0, 5, -(0/0), 5}
	-- Dupes removed: {1, 2,    3,       4,    NaN, 5, NaN}
	local removed = tt.removeDuplicates(dupes)
	self:assertEquals(7, #removed)
	self:assertEquals(1, removed[1])
	self:assertEquals(2, removed[2])
	self:assertEquals(3, removed[3])
	self:assertEquals(4, removed[4])
	self:assertTrue(suite.isNan(removed[5]))
	self:assertEquals(5, removed[6])
	self:assertTrue(suite.isNan(removed[7]))
	self:assertTypeErrorEquals(1, 'removeDuplicates', 'table', 'number', tt.removeDuplicates, 4)
	self:assertTypeErrorEquals(1, 'removeDuplicates', 'table', 'nil', tt.removeDuplicates)
end

------------------------------------------------------------------------
-- Sparse array variables
------------------------------------------------------------------------

local sparseArray = {1, nil, 2, nil, 3, nil, [math.huge] = math.huge, foo = 'bar', [1.5] = 1.5, ['4'] = 'four_string'}
local sparseArrayConcatenated = '123'
local numKeysConcatenated = '135'
local reverseSparseArrayConcatenated = '321'
local reverseNumKeysConcatenated = '531'

------------------------------------------------------------------------
-- Test numKeys
------------------------------------------------------------------------

function suite:testnumKeys()
	local numKeys = tt.numKeys(sparseArray)
    self:assertEquals(numKeysConcatenated, suite.concatIpairs(numKeys))
	self:assertTypeErrorEquals(1, 'numKeys', 'table', 'number', tt.numKeys, 4)
	self:assertTypeErrorEquals(1, 'numKeys', 'table', 'nil', tt.numKeys)
end

------------------------------------------------------------------------
-- Test affixNums
------------------------------------------------------------------------

local affixArray = {1, a0 = 'a0', a001 = 'a001', a1 = 'a1', b2 = 'b2', a3 = 'a3', c4d = 'c4d', b5 = 'b5', B6 = 'B6', f7 = 'f7', c8d = 'c8d', a9 = nil, a10 = 'a10', [11] = 11, ['e-f12'] = 'e-f12'}
local aNumsConcatenated = '1310'
local aValsConcatenated = 'a1a3a10'
local bNumsConcatenated = '25'
local bValsConcatenated = 'b2b5'
local cdNumsConcatenated = '48'
local cdValsConcatenated = 'c4dc8d'
local efNumsConcatenated = '12'
local efValsConcatenated = 'e-f12'

function suite.concatAffixVals(t, nums, prefix, suffix)
	local ret = ''
	for i, num in ipairs(nums) do
		local key = (prefix or '') .. tostring(num) .. (suffix or '')
		ret = ret .. tostring(t[key])
	end
	return ret
end

function suite:testaffixNums()
	local aNums = tt.affixNums(affixArray, 'a')
	local bNums = tt.affixNums(affixArray, 'b')
	local cdNums = tt.affixNums(affixArray, 'c', 'd')
	local efNums = tt.affixNums(affixArray, 'e-f') -- "-" is magic, so we need to escape it.
    self:assertEquals(aNumsConcatenated, suite.concatIpairs(aNums))
    self:assertEquals(aValsConcatenated, suite.concatAffixVals(affixArray, aNums, 'a'))
    self:assertEquals(bNumsConcatenated, suite.concatIpairs(bNums))
    self:assertEquals(bValsConcatenated, suite.concatAffixVals(affixArray, bNums, 'b'))
    self:assertEquals(cdNumsConcatenated, suite.concatIpairs(cdNums))
    self:assertEquals(cdValsConcatenated, suite.concatAffixVals(affixArray, cdNums, 'c', 'd'))
    self:assertEquals(efNumsConcatenated, suite.concatIpairs(efNums))
    self:assertEquals(efValsConcatenated, suite.concatAffixVals(affixArray, efNums, 'e-f'))
	self:assertTypeErrorEquals(1, 'affixNums', 'table', 'number', tt.affixNums, 4)
	self:assertTypeErrorEquals(1, 'affixNums', 'table', 'nil', tt.affixNums)
end

------------------------------------------------------------------------
-- Test numData
------------------------------------------------------------------------

function suite:testNumData()
	local t = {1, 2, [5] = 5, foo = "foo", foo1 = "foo1", bar1 = "bar1", foo6 = "foo6", bar6 = "bar6"}
	local uncompressed = tt.numData(t)
	local compressed = tt.numData(t, true)

	-- Test uncompressed.
	self:assertEquals(1, uncompressed[1][1])
	self:assertEquals(2, uncompressed[2][1])
	self:assertEquals(5, uncompressed[5][1])
	self:assertEquals("foo", uncompressed.other.foo)
	self:assertEquals("foo1", uncompressed[1].foo)
	self:assertEquals("bar1", uncompressed[1].bar)
	self:assertEquals("foo6", uncompressed[6].foo)
	self:assertEquals("bar6", uncompressed[6].bar)
	self:assertEquals(nil, uncompressed[4])

	-- Test compressed.
	self:assertEquals(1, compressed[1][1])
	self:assertEquals(2, compressed[2][1])
	self:assertEquals(5, compressed[3][1])
	self:assertEquals("foo", compressed.other.foo)
	self:assertEquals("foo1", compressed[1].foo)
	self:assertEquals("bar1", compressed[1].bar)
	self:assertEquals("foo6", compressed[4].foo)
	self:assertEquals("bar6", compressed[4].bar)
	self:assertEquals(nil, compressed[5])
end

------------------------------------------------------------------------
-- Test sparse array functions
------------------------------------------------------------------------

function suite:testCompressSparseArray()
	local compressedArray = tt.compressSparseArray(sparseArray)
    self:assertEquals(sparseArrayConcatenated, suite.concatIpairs(compressedArray))
	self:assertTypeErrorEquals(1, 'compressSparseArray', 'table', 'number', tt.compressSparseArray, 4)
	self:assertTypeErrorEquals(1, 'compressSparseArray', 'table', 'nil', tt.compressSparseArray)
end

function suite:testSparseIpairs()
	local arrayText = ''
	for i, v in tt.sparseIpairs(sparseArray) do
		arrayText = arrayText .. tostring(v)
	end
	self:assertEquals(sparseArrayConcatenated, arrayText)
	self:assertTypeErrorEquals(1, 'sparseIpairs', 'table', 'number', tt.sparseIpairs, 4)
	self:assertTypeErrorEquals(1, 'sparseIpairs', 'table', 'nil', tt.sparseIpairs)
end

------------------------------------------------------------------------
-- Test size function
------------------------------------------------------------------------

function suite:testSize()
	self:assertEquals(0, tt.size{})
	self:assertEquals(3, tt.size{foo = 'foo', bar = 'bar', baz = 'baz'})
	self:assertEquals(1, tt.size{1})
	self:assertEquals(5, tt.size{foo = 'foo', bar = 'bar', baz = 'baz', 1, 2})
	self:assertTypeErrorEquals(1, 'size', 'table', 'number', tt.size, 4)
	self:assertTypeErrorEquals(1, 'size', 'table', 'nil', tt.size)
end

------------------------------------------------------------------------
-- Test binaryLength function
------------------------------------------------------------------------

function suite:testLengthOfEmptyTableIsZero()
	self:assertEquals(0, tt.length{})
end

function suite:testLengthOfArray()
	local data = {"a","b","c","d","e","f"}
	self:assertEquals(6, tt.length(data))
	local meta = setmetatable({}, {__index = data})
	self:assertEquals(6, tt.length(meta))
end

function suite:testLengthOfQuasiArrayWithPrefixes()
	local data = {key1 = "value1", key2 = "value2", key3 = "value3"}
	self:assertEquals(3, tt.length(data, "key"))
	local meta = setmetatable({}, {__index = data})
	self:assertEquals(3, tt.length(meta, "key"))
end

function suite:testLengthChecksForTypeErrors()
	self:assertTypeErrorEquals(1, 'length', 'table', 'number', tt.length, 1)
	self:assertTypeErrorEquals(2, 'length', 'string', 'number', tt.length, {}, 2)
end

function suite:testInArray()
	self:assertTrue(tt.inArray({"a", "b", "c", "d"}, "b"))
	self:assertTrue(tt.inArray({"a", "b", "c", "d"}, "b", 0))
	self:assertTrue(tt.inArray({"a", "b", "c", "d"}, "b", 1))
	self:assertTrue(tt.inArray({"a", "b", "c", "d"}, "b", 2))
	self:assertTrue(tt.inArray({"a", "b", "c", "d"}, "b", -3))
	self:assertTrue(tt.inArray({"a", "b", "c", "d"}, "b", -5))
	self:assertTrue(tt.inArray({[1] = "a",[100] = "b",[101] = "c"}, "b"))
	self:assertTrue(tt.inArray({[1] = "a",[2] = "b",[3] = "c"}, "b", 0))
	self:assertTrue(tt.inArray({first = "a", second = "b", third = "c"}, "b"))
	self:assertFalse(tt.inArray({"a", "b", "c", "d"})) -- value missing
	self:assertFalse(tt.inArray({"a", "b", "c", "d"}, "e")) -- "e" is not in array
	self:assertFalse(tt.inArray({"a", "b", "c", "d"}, "b", 3)) -- "b" is before position 3
	self:assertFalse(tt.inArray({"a", "b", "c", "d"}, "b", 5)) -- 5 is larger than #array
	self:assertFalse(tt.inArray({"a", "b", "c", "d"}, "b", -2)) -- "b" is not in the last two positions
	self:assertFalse(tt.inArray({[1] = "a", [100] = "b", [101] = "c"}, "b", 0)) -- key 100 is non-consecutive
	self:assertFalse(tt.inArray({first = "a", second = "b", third = "c"}, "b", 0)) -- key "second" is not an integer
end

function suite:testMerge()
	self:assertDeepEquals({}, tt.merge())
	local function f() return "foo" end
	self:assertDeepEquals({"a",1,2,f,3}, tt.merge({"a",1,2,f,3}))
	self:assertDeepEquals({0.1,f,2,"3",{foo="bar"}}, tt.merge({0.1,f}, {[0.0]=f,2,"3",[1.0]="y"}, {{foo="bar"},f=f}))
	local function fn() tt.merge(2,3) end
	self:assertThrows(fn, "bad argument #1 to 'merge' (table expected, got number)")
end

function suite:testExtend()
	local t = {Z=1,{"Z"}}
	tt.extend(t, {[0.1]="k",-1})
	self:assertDeepEquals({{"Z"},Z=1,-1}, t)
	local function fn() tt.extend(t, "banana") end
	self:assertThrows(fn, "bad argument #2 to 'extend' (table expected, got string)")
	local function fn() tt.extend(fn, t) end
	self:assertThrows(fn, "bad argument #1 to 'extend' (table expected, got function)")
end

return suite