mirror of
https://github.com/sica42/RollFor.git
synced 2025-10-26 12:06:49 +00:00
3251 lines
106 KiB
Lua
3251 lines
106 KiB
Lua
--[[
|
||
zlib License
|
||
|
||
(C) 2018-2020 Haoqian He
|
||
|
||
This software is provided 'as-is', without any express or implied
|
||
warranty. In no event will the authors be held liable for any damages
|
||
arising from the use of this software.
|
||
|
||
Permission is granted to anyone to use this software for any purpose,
|
||
including commercial applications, and to alter it and redistribute it
|
||
freely, subject to the following restrictions:
|
||
|
||
1. The origin of this software must not be misrepresented; you must not
|
||
claim that you wrote the original software. If you use this software
|
||
in a product, an acknowledgment in the product documentation would be
|
||
appreciated but is not required.
|
||
2. Altered source versions must be plainly marked as such, and must not be
|
||
misrepresented as being the original software.
|
||
3. This notice may not be removed or altered from any source distribution.
|
||
|
||
--]]
|
||
|
||
|
||
-- Run this tests at the folder where LibDeflate.lua located, like this.
|
||
-- lua tests/Test.lua
|
||
-- Don't run two "tests/Test.lua" at the same time,
|
||
-- because they will conflict!!!
|
||
|
||
package.path = ("?.lua;tests/LibCompress/?.lua;")..(package.path or "")
|
||
|
||
do
|
||
local test_lua = io.open("tests/Test.lua")
|
||
assert(test_lua
|
||
, "Must run this script in the root folder of LibDeflate repository")
|
||
test_lua:close()
|
||
end
|
||
|
||
local old_globals = {}
|
||
for k, v in pairs(_G) do
|
||
old_globals[k] = v
|
||
end
|
||
local LibDeflate = require("LibDeflate")
|
||
for k, v in pairs(_G) do
|
||
assert(v == old_globals[k], "LibDeflate global leak at key: "..tostring(k))
|
||
end
|
||
for k, v in pairs(old_globals) do
|
||
assert(v == _G[k], "LibDeflate global leak at key: "..tostring(k))
|
||
end
|
||
|
||
-- UnitTests
|
||
local lu = require("luaunit")
|
||
assert(lu)
|
||
|
||
local assert = assert
|
||
local loadstring = loadstring or load
|
||
local math = math
|
||
local string = string
|
||
local table = table
|
||
local collectgarbage = collectgarbage
|
||
local os = os
|
||
local type = type
|
||
local io = io
|
||
local print = print
|
||
local tostring = tostring
|
||
local string_char = string.char
|
||
local string_byte = string.byte
|
||
local string_len = string.len
|
||
local string_sub = string.sub
|
||
local unpack = unpack or table.unpack
|
||
local table_insert = table.insert
|
||
local table_concat = table.concat
|
||
|
||
math.randomseed(0) -- I don't like true random tests that I cant 100% reproduce.
|
||
|
||
local _pow2 = {}
|
||
do
|
||
local pow = 1
|
||
for i = 0, 32 do
|
||
_pow2[i] = pow
|
||
pow = pow * 2
|
||
end
|
||
end
|
||
|
||
local function DeepCopy(obj)
|
||
local SearchTable = {} -- luacheck: ignore
|
||
|
||
local function Func(object)
|
||
if type(object) ~= "table" then
|
||
return object
|
||
end
|
||
local NewTable = {}
|
||
SearchTable[object] = NewTable
|
||
for k, v in pairs(object) do
|
||
NewTable[Func(k)] = Func(v)
|
||
end
|
||
|
||
return setmetatable(NewTable, getmetatable(object))
|
||
end
|
||
|
||
return Func(obj)
|
||
end
|
||
|
||
local function GetTableSize(t)
|
||
local size = 0
|
||
for _, _ in pairs(t) do
|
||
size = size + 1
|
||
end
|
||
return size
|
||
end
|
||
|
||
local HexToString
|
||
local HalfByteToHex
|
||
do
|
||
local _byte0 = string_byte("0", 1)
|
||
local _byte9 = string_byte("9", 1)
|
||
local _byteA = string_byte("A", 1)
|
||
local _byteF = string_byte("F", 1)
|
||
local _bytea = string_byte("a", 1)
|
||
local _bytef = string_byte("f", 1)
|
||
function HexToString(str)
|
||
local t = {}
|
||
local val = 1
|
||
for i=1, str:len()+1 do
|
||
local b = string_byte(str, i, i) or -1
|
||
if b >= _byte0 and b <= _byte9 then
|
||
val = val*16 + b - _byte0
|
||
elseif b >= _byteA and b <= _byteF then
|
||
val = val*16 + b - _byteA + 10
|
||
elseif b >= _bytea and b <= _bytef then
|
||
val = val*16 + b - _bytea + 10
|
||
elseif val ~= 1 and val < 32 then -- one digit followed by delimiter
|
||
val = val + 240 -- make it look like two digits
|
||
end
|
||
if val > 255 then
|
||
t[#t+1] = string_char(val % 256)
|
||
val = 1
|
||
end
|
||
end
|
||
return table.concat(t)
|
||
end
|
||
assert(HexToString("f") == string_char(15))
|
||
assert(HexToString("1f") == string_char(31))
|
||
assert(HexToString("1f 2") == string_char(31)..string_char(2))
|
||
assert(HexToString("1f 22") == string_char(31)..string_char(34))
|
||
assert(HexToString("F") == string_char(15))
|
||
assert(HexToString("1F") == string_char(31))
|
||
assert(HexToString("1F 2") == string_char(31)..string_char(2))
|
||
assert(HexToString("1F 22") == string_char(31)..string_char(34))
|
||
|
||
assert(HexToString("a") == string_char(10))
|
||
assert(HexToString("1a") == string_char(26))
|
||
assert(HexToString("1a 90") == string_char(26)..string_char(144))
|
||
assert(HexToString("1a 9") == string_char(26)..string_char(9))
|
||
assert(HexToString("A") == string_char(10))
|
||
assert(HexToString("1A") == string_char(26))
|
||
assert(HexToString("1A 09") == string_char(26)..string_char(9))
|
||
assert(HexToString("1A 00") == string_char(26)..string_char(0))
|
||
|
||
function HalfByteToHex(half_byte)
|
||
assert (half_byte >= 0 and half_byte < 16)
|
||
if half_byte < 10 then
|
||
return string_char(_byte0 + half_byte)
|
||
else
|
||
return string_char(_bytea + half_byte-10)
|
||
end
|
||
end
|
||
end
|
||
|
||
local function StringToHex(str)
|
||
if not str then
|
||
return "nil"
|
||
end
|
||
local tmp = {}
|
||
for i = 1, str:len() do
|
||
local b = string_byte(str, i, i)
|
||
if b < 16 then
|
||
tmp[#tmp+1] = "0"..HalfByteToHex(b)
|
||
else
|
||
tmp[#tmp+1] = HalfByteToHex((b-b%16)/16)..HalfByteToHex(b%16)
|
||
end
|
||
end
|
||
return table.concat(tmp, " ")
|
||
end
|
||
assert (StringToHex("\000"), "00")
|
||
assert (StringToHex("\000\255"), "00 ff")
|
||
assert (StringToHex(HexToString("05 e0 81 91 24 cb b2 2c 49 e2 0f 2e 8b 9a"
|
||
.." 47 56 9f fb fe ec d2 ff 1f"))
|
||
== "05 e0 81 91 24 cb b2 2c 49 e2 0f 2e 8b 9a 47 56 9f fb fe ec d2 ff 1f")
|
||
|
||
-- Return a string with limited size
|
||
local function StringForPrint(str)
|
||
if str:len() < 101 then
|
||
return str
|
||
else
|
||
return str:sub(1, 101)..(" (%d more characters not shown)")
|
||
:format(str:len()-101)
|
||
end
|
||
end
|
||
|
||
local function OpenFile(filename, mode)
|
||
local f = io.open(filename, mode)
|
||
lu.assertNotNil(f, ("Cannot open the file: %s, with mode: %s")
|
||
:format(filename, mode))
|
||
return f
|
||
end
|
||
|
||
local function GetFileData(filename)
|
||
local f = OpenFile(filename, "rb")
|
||
local str = f:read("*all")
|
||
f:close()
|
||
return str
|
||
end
|
||
|
||
local function WriteToFile(filename, data)
|
||
local f = io.open(filename, "wb")
|
||
lu.assertNotNil(f, ("Cannot open the file: %s, with mode: %s")
|
||
:format(filename, "wb"))
|
||
f:write(data)
|
||
f:flush()
|
||
f:close()
|
||
end
|
||
|
||
local function GetLimitedRandomString(strlen)
|
||
local randoms = {}
|
||
for _=1, 7 do
|
||
randoms[#randoms+1] = string.char(math.random(1, 255))
|
||
end
|
||
local tmp = {}
|
||
for _=1, strlen do
|
||
tmp[#tmp+1] = randoms[math.random(1, 7)]
|
||
end
|
||
return table.concat(tmp)
|
||
end
|
||
|
||
local function GetRandomString(strlen)
|
||
local tmp = {}
|
||
for _=1, strlen do
|
||
tmp[#tmp+1] = string_char(math.random(0, 255))
|
||
end
|
||
return table.concat(tmp)
|
||
end
|
||
|
||
-- Get a random string with at least 256 len which includes all characters
|
||
local function GetRandomStringUniqueChars(strlen)
|
||
local taken = {}
|
||
local tmp = {}
|
||
for i=0, (strlen < 256) and strlen-1 or 255 do
|
||
local rand = math.random(1, 256-i)
|
||
local count = 0
|
||
for j=0, 255 do
|
||
if (not taken[j]) then
|
||
count = count + 1
|
||
end
|
||
if count == rand then
|
||
taken[j] = true
|
||
tmp[#tmp+1] = string_char(j)
|
||
break
|
||
end
|
||
end
|
||
end
|
||
if strlen > 256 then
|
||
for _=1, strlen-256 do
|
||
table_insert(tmp, math.random(1, #tmp+1)
|
||
, string_char(math.random(0, 255)))
|
||
end
|
||
end
|
||
return table_concat(tmp)
|
||
end
|
||
assert(GetRandomStringUniqueChars(3):len() == 3)
|
||
assert(GetRandomStringUniqueChars(255):len() == 255)
|
||
assert(GetRandomStringUniqueChars(256):len() == 256)
|
||
assert(GetRandomStringUniqueChars(500):len() == 500)
|
||
do
|
||
local taken = {}
|
||
local str = GetRandomStringUniqueChars(256)
|
||
for i=1, 256 do
|
||
local byte = string_byte(str, i, i)
|
||
assert(not taken[byte])
|
||
taken[byte] = true
|
||
end
|
||
end
|
||
|
||
-- Repeatedly collect memory garbarge until memory usage no longer changes
|
||
local function FullMemoryCollect()
|
||
local memory_used = collectgarbage("count")
|
||
local last_memory_used
|
||
local stable_count = 0
|
||
repeat
|
||
last_memory_used = memory_used
|
||
collectgarbage("collect")
|
||
memory_used = collectgarbage("count")
|
||
|
||
if memory_used >= last_memory_used then
|
||
stable_count = stable_count + 1
|
||
else
|
||
stable_count = 0
|
||
end
|
||
until stable_count == 10
|
||
-- Stop full memory collect until memory does not decrease for 10 times.
|
||
end
|
||
|
||
local function RunProgram(program, input_filename, stdout_filename)
|
||
local stderr_filename = stdout_filename..".stderr"
|
||
local status, _, ret = os.execute(program.." "..input_filename
|
||
.. "> "..stdout_filename.." 2> "..stderr_filename)
|
||
local returned_status
|
||
if type(status) == "number" then -- lua 5.1
|
||
returned_status = status
|
||
else -- Lua 5.2/5.3
|
||
returned_status = ret
|
||
if not status and ret == 0 then
|
||
returned_status = -1
|
||
-- Lua bug on Windows when the returned value is -1, ret is 0
|
||
end
|
||
end
|
||
local stdout = GetFileData(stdout_filename)
|
||
local stderr = GetFileData(stderr_filename)
|
||
return returned_status, stdout, stderr
|
||
end
|
||
|
||
local function AssertLongStringEqual(actual, expected, msg)
|
||
if actual ~= expected then
|
||
lu.assertNotNil(actual, ("%s actual is nil"):format(msg or ""))
|
||
lu.assertNotNil(expected, ("%s expected is nil"):format(msg or ""))
|
||
local diff_index = 1
|
||
for i=1, math.max(expected:len(), actual:len()) do
|
||
if string_byte(actual, i, i) ~= string_byte(expected, i, i) then
|
||
diff_index = i
|
||
break
|
||
end
|
||
end
|
||
local actual_msg = string.format(
|
||
"%s actualLen: %d, expectedLen:%d, first difference at: %d,"
|
||
.." actualByte: %s, expectByte: %s", msg or "", actual:len()
|
||
, expected:len(), diff_index,
|
||
string.byte(actual, diff_index) or "nil",
|
||
string.byte(expected, diff_index) or "nil")
|
||
lu.assertTrue(false, actual_msg)
|
||
end
|
||
end
|
||
|
||
local function MemCheckAndBenchmarkFunc(lib, func_name, ...)
|
||
local memory_before
|
||
local memory_running
|
||
local memory_after
|
||
local start_time
|
||
local elapsed_time
|
||
local ret
|
||
FullMemoryCollect()
|
||
memory_before = math.floor(collectgarbage("count")*1024)
|
||
FullMemoryCollect()
|
||
start_time = os.clock()
|
||
elapsed_time = -1
|
||
local repeat_count = 0
|
||
while elapsed_time < 0.015 do
|
||
ret = {lib[func_name](lib, ...)}
|
||
elapsed_time = os.clock() - start_time
|
||
repeat_count = repeat_count + 1
|
||
end
|
||
memory_running = math.floor(collectgarbage("count")*1024)
|
||
FullMemoryCollect()
|
||
memory_after = math.floor(collectgarbage("count")*1024)
|
||
local memory_used = memory_running - memory_before
|
||
local memory_leaked = memory_after - memory_before
|
||
|
||
return memory_leaked, memory_used
|
||
, elapsed_time*1000/repeat_count, unpack(ret)
|
||
end
|
||
|
||
local function GetFirstBlockType(compressed_data, isZlib)
|
||
local first_block_byte_index = 1
|
||
if isZlib then
|
||
local byte2 = string.byte(compressed_data, 2, 2)
|
||
local has_dict = ((byte2-byte2%32)/32)%2
|
||
if has_dict == 1 then
|
||
first_block_byte_index = 7
|
||
else
|
||
first_block_byte_index = 3
|
||
end
|
||
end
|
||
local first_byte = string.byte(compressed_data
|
||
, first_block_byte_index, first_block_byte_index)
|
||
local bit3 = first_byte % 8
|
||
return (bit3 - bit3 % 2) / 2
|
||
end
|
||
|
||
local function PutRandomBitsInPaddingBits(compressed_data, padding_bitlen)
|
||
if padding_bitlen > 0 then
|
||
local len = #compressed_data
|
||
local last_byte = string.byte(compressed_data, len)
|
||
local random_last_byte = math.random(0, 255)
|
||
random_last_byte = random_last_byte
|
||
- random_last_byte % _pow2[8-padding_bitlen]
|
||
random_last_byte = random_last_byte
|
||
+ last_byte % _pow2[8-padding_bitlen]
|
||
compressed_data = compressed_data:sub(1, len-1)
|
||
..string.char(random_last_byte)
|
||
end
|
||
return compressed_data
|
||
end
|
||
|
||
local dictionary32768_str = GetFileData("tests/dictionary32768.txt")
|
||
local dictionary32768 = LibDeflate:CreateDictionary(dictionary32768_str
|
||
, 32768, 4072834167)
|
||
|
||
local _CheckCompressAndDecompressCounter = 0
|
||
local function CheckCompressAndDecompress(string_or_filename, is_file, levels
|
||
, strategy, output_prefix)
|
||
|
||
-- For 100% code coverage
|
||
if _CheckCompressAndDecompressCounter % 3 == 0 then
|
||
LibDeflate.internals.InternalClearCache()
|
||
end
|
||
if _CheckCompressAndDecompressCounter % 2 == 0 then
|
||
-- Init cache table in these functions
|
||
-- , to help memory leak check in the following codes.
|
||
LibDeflate:EncodeForWoWAddonChannel("")
|
||
LibDeflate:EncodeForWoWChatChannel("")
|
||
else
|
||
LibDeflate:DecodeForWoWAddonChannel("")
|
||
LibDeflate:DecodeForWoWChatChannel("")
|
||
end
|
||
_CheckCompressAndDecompressCounter = _CheckCompressAndDecompressCounter + 1
|
||
|
||
local origin
|
||
if is_file then
|
||
origin = GetFileData(string_or_filename)
|
||
else
|
||
origin = string_or_filename
|
||
end
|
||
|
||
FullMemoryCollect()
|
||
local total_memory_before = math.floor(collectgarbage("count")*1024)
|
||
|
||
do
|
||
if levels == "all" then
|
||
levels = {0,1,2,3,4,5,6,7,8,9}
|
||
else
|
||
levels = levels or {1}
|
||
end
|
||
|
||
local compress_filename
|
||
local decompress_filename
|
||
|
||
if output_prefix then
|
||
compress_filename = output_prefix..".compress"
|
||
decompress_filename = output_prefix..".decompress"
|
||
else
|
||
if is_file then
|
||
compress_filename = string_or_filename..".compress"
|
||
else
|
||
compress_filename = "tests/string.compress"
|
||
end
|
||
decompress_filename = compress_filename..".decompress"
|
||
end
|
||
|
||
for i=1, #levels+1 do -- also test level == nil
|
||
local level = levels[i]
|
||
local configs = {level = level, strategy = strategy}
|
||
|
||
print(
|
||
(">>>>> %s: %s size: %d B Level: %s Strategy: %s")
|
||
:format(is_file and "File" or "String",
|
||
string_or_filename:sub(1, 40), origin:len()
|
||
,tostring(level), tostring(strategy)
|
||
))
|
||
local compress_to_run = {
|
||
{"CompressDeflate", origin, configs},
|
||
{"CompressDeflateWithDict", origin, dictionary32768
|
||
, configs},
|
||
{"CompressZlib", origin, configs},
|
||
{"CompressZlibWithDict", origin, dictionary32768, configs},
|
||
}
|
||
|
||
for j, compress_running in ipairs(compress_to_run) do
|
||
-- Compress by raw deflate
|
||
local compress_func_name = compress_running[1]
|
||
local compress_memory_leaked, compress_memory_used
|
||
, compress_time, compress_data, compress_pad_bitlen =
|
||
MemCheckAndBenchmarkFunc(LibDeflate
|
||
, unpack(compress_running))
|
||
|
||
if compress_running[1]:find("Deflate") then
|
||
lu.assertTrue(0 <= compress_pad_bitlen
|
||
and compress_pad_bitlen < 8
|
||
, compress_func_name)
|
||
-- put random value in the padding bits,
|
||
-- to see if it is still okay to decompress
|
||
|
||
else
|
||
lu.assertEquals(compress_pad_bitlen, 0
|
||
, compress_func_name)
|
||
end
|
||
|
||
-- Test encoding
|
||
local compress_data_WoW_addon_encoded =
|
||
LibDeflate:EncodeForWoWAddonChannel(compress_data)
|
||
AssertLongStringEqual(
|
||
LibDeflate:DecodeForWoWAddonChannel(
|
||
compress_data_WoW_addon_encoded), compress_data
|
||
, compress_func_name)
|
||
|
||
local compress_data_data_WoW_chat_encoded =
|
||
LibDeflate:EncodeForWoWChatChannel(compress_data)
|
||
AssertLongStringEqual(
|
||
LibDeflate:DecodeForWoWChatChannel(
|
||
compress_data_data_WoW_chat_encoded), compress_data
|
||
, compress_func_name)
|
||
|
||
-- Put random bits in the padding bits of compressed data.
|
||
-- to see if decompression still works.
|
||
compress_data = PutRandomBitsInPaddingBits(compress_data
|
||
, compress_pad_bitlen)
|
||
local isZlib = compress_func_name:find("Zlib")
|
||
if strategy == "fixed" then
|
||
lu.assertEquals(GetFirstBlockType(compress_data, isZlib)
|
||
, (level == 0) and 0 or 1,
|
||
compress_func_name.." "..tostring(level))
|
||
elseif strategy == "dynamic" then
|
||
lu.assertEquals(GetFirstBlockType(compress_data, isZlib)
|
||
, (level == 0) and 0 or 2,
|
||
compress_func_name.." "..tostring(level))
|
||
elseif strategy == "huffman_only" then -- luacheck: ignore
|
||
-- Emtpy
|
||
elseif strategy == nil then -- luacheck: ignore
|
||
-- Empty
|
||
else
|
||
lu.assertTrue(false, "Unexpected strategy: "
|
||
..tostring(strategy))
|
||
end
|
||
WriteToFile(compress_filename, compress_data)
|
||
|
||
if not compress_running[1] == "CompressDeflate" then
|
||
local returnedStatus_puff, stdout_puff =
|
||
RunProgram("puff -w ", compress_filename
|
||
, decompress_filename)
|
||
lu.assertEquals(returnedStatus_puff, 0
|
||
, compress_func_name
|
||
.." puff decompression failed with code "
|
||
..returnedStatus_puff)
|
||
AssertLongStringEqual(stdout_puff, origin
|
||
, "puff fails with "..compress_func_name)
|
||
end
|
||
|
||
local decompress_to_run = {
|
||
{"DecompressDeflate", compress_data},
|
||
{"DecompressDeflateWithDict", compress_data
|
||
, dictionary32768, configs},
|
||
|
||
{"DecompressZlib", compress_data, configs},
|
||
{"DecompressZlibWithDict", compress_data
|
||
, dictionary32768, configs},
|
||
}
|
||
lu.assertEquals(#decompress_to_run, #compress_to_run)
|
||
|
||
local zdeflate_decompress_to_run = {
|
||
"zdeflate -d <",
|
||
"zdeflate -d --dict tests/dictionary32768.txt <",
|
||
"zdeflate --zlib -d <",
|
||
"zdeflate --zlib -d --dict tests/dictionary32768.txt <",
|
||
}
|
||
lu.assertEquals(#zdeflate_decompress_to_run, #compress_to_run)
|
||
|
||
-- Try decompress by zdeflate
|
||
-- zdeflate is a C program calling zlib library
|
||
-- which is modifed from zlib example.
|
||
-- zdeflate can do all compression and decompression doable
|
||
-- by LibDeflate (except encode and decode)
|
||
local returnedStatus_zdeflate, stdout_zdeflate
|
||
, stderr_zdeflate =
|
||
RunProgram(zdeflate_decompress_to_run[j], compress_filename
|
||
, decompress_filename)
|
||
lu.assertEquals(returnedStatus_zdeflate, 0
|
||
, compress_func_name
|
||
..":zdeflate decompression failed with msg "
|
||
..stderr_zdeflate)
|
||
AssertLongStringEqual(stdout_zdeflate, origin
|
||
, compress_func_name
|
||
.."zdeflate decompress result not match origin string.")
|
||
|
||
-- Try decompress by LibDeflate
|
||
local decompress_memory_leaked, decompress_memory_used,
|
||
decompress_time, decompress_data,
|
||
decompress_unprocess_byte =
|
||
MemCheckAndBenchmarkFunc(LibDeflate
|
||
, unpack(decompress_to_run[j]))
|
||
AssertLongStringEqual(decompress_data, origin
|
||
, compress_func_name
|
||
.." LibDeflate decompress result not match origin string.")
|
||
lu.assertEquals(decompress_unprocess_byte, 0
|
||
, compress_func_name
|
||
.." Unprocessed bytes after LibDeflate decompression "
|
||
..tostring(decompress_unprocess_byte))
|
||
|
||
print(
|
||
("%s: Size : %d B,Time: %.3f ms, "
|
||
.."Speed: %.0f KB/s, Memory: %d B,"
|
||
.." Mem/input: %.2f, (memleak?: %d B) padbit: %d\n")
|
||
:format(compress_func_name
|
||
, compress_data:len(), compress_time
|
||
, compress_data:len()/compress_time
|
||
, compress_memory_used
|
||
, compress_memory_used/origin:len()
|
||
, compress_memory_leaked
|
||
, compress_pad_bitlen
|
||
),
|
||
("%s: cRatio: %.2f,Time: %.3f ms"
|
||
..", Speed: %.0f KB/s, Memory: %d B,"
|
||
.." Mem/input: %.2f, (memleak?: %d B)"):format(
|
||
decompress_to_run[j][1]
|
||
, origin:len()/compress_data:len(), decompress_time
|
||
, decompress_data:len()/decompress_time
|
||
, decompress_memory_used
|
||
, decompress_memory_used/origin:len()
|
||
, decompress_memory_leaked
|
||
)
|
||
)
|
||
end
|
||
print("")
|
||
end
|
||
|
||
-- Use all avaiable strategies of zdeflate to compress the data
|
||
-- , and see if LibDeflate can decompress it.
|
||
local tmp_filename = "tests/tmp.tmp"
|
||
WriteToFile(tmp_filename, origin)
|
||
|
||
local zdeflate_level, zdeflate_strategy
|
||
local strategies = {"--filter", "--huffman", "--rle"
|
||
, "--fix", "--default"}
|
||
local unique_compress = {}
|
||
local uniques_compress_count = 0
|
||
for level=0, 8 do
|
||
zdeflate_level = "-"..level
|
||
for j=1, #strategies do
|
||
zdeflate_strategy = strategies[j]
|
||
local status, stdout, stderr =
|
||
RunProgram("zdeflate "..zdeflate_level
|
||
.." "..zdeflate_strategy
|
||
.." < ", tmp_filename, tmp_filename..".out")
|
||
lu.assertEquals(status, 0
|
||
, ("zdeflate cant compress the file? "
|
||
.."stderr: %s level: %s, strategy: %s")
|
||
:format(stderr, zdeflate_level, zdeflate_strategy))
|
||
if not unique_compress[stdout] then
|
||
unique_compress[stdout] = true
|
||
uniques_compress_count = uniques_compress_count + 1
|
||
local decompressData =
|
||
LibDeflate:DecompressDeflate(stdout)
|
||
AssertLongStringEqual(decompressData, origin,
|
||
("My decompress fail to decompress "
|
||
.."at zdeflate level: %s, strategy: %s")
|
||
:format(level, zdeflate_strategy))
|
||
end
|
||
end
|
||
end
|
||
print(
|
||
(">>>>> %s: %s size: %d B\n")
|
||
:format(is_file and "File" or "String"
|
||
, string_or_filename:sub(1, 40), origin:len()),
|
||
("Full decompress coverage test ok. unique compresses: %d\n")
|
||
:format(uniques_compress_count),
|
||
"\n")
|
||
end
|
||
|
||
FullMemoryCollect()
|
||
local total_memory_after = math.floor(collectgarbage("count")*1024)
|
||
|
||
local total_memory_difference = total_memory_before - total_memory_after
|
||
|
||
if total_memory_difference > 0 then
|
||
local ignore_leak_jit = ""
|
||
if _G.jit then
|
||
ignore_leak_jit = " (Ignore when the test is run by LuaJIT)"
|
||
end
|
||
print(
|
||
(">>>>> %s: %s size: %d B\n")
|
||
:format(is_file and "File" or "String"
|
||
, string_or_filename:sub(1, 40), origin:len()),
|
||
("Actual Memory Leak in the test: %d"..ignore_leak_jit.."\n")
|
||
:format(total_memory_difference),
|
||
"\n")
|
||
-- ^If above "leak" is very small
|
||
-- , it is very likely that it is false positive.
|
||
if not _G.jit and total_memory_difference > 64 then
|
||
-- Lua JIT has some problems to garbage collect stuffs
|
||
-- , so don't consider as failure.
|
||
lu.assertTrue(false
|
||
, ("Fail the test because too many actual "
|
||
.."Memory Leak in the test: %d")
|
||
:format(total_memory_difference))
|
||
end
|
||
end
|
||
|
||
return 0
|
||
end
|
||
|
||
local function CheckCompressAndDecompressString(str, levels, strategy)
|
||
return CheckCompressAndDecompress(str, false, levels, strategy)
|
||
end
|
||
|
||
local function CheckCompressAndDecompressFile(inputFileName, levels, strategy
|
||
, output_prefix)
|
||
return CheckCompressAndDecompress(inputFileName, true, levels, strategy
|
||
, output_prefix)
|
||
end
|
||
|
||
local function CheckDecompressIncludingError(compress, decompress, is_zlib)
|
||
assert (is_zlib == true or is_zlib == nil)
|
||
local d, decompress_status
|
||
if is_zlib then
|
||
d, decompress_status = LibDeflate:DecompressZlib(compress)
|
||
else
|
||
d, decompress_status = LibDeflate:DecompressDeflate(compress)
|
||
end
|
||
lu.assertTrue(type(d) == "string" or type(d) == "nil")
|
||
lu.assertEquals(type(decompress_status), "number")
|
||
lu.assertEquals(decompress_status % 1, 0)
|
||
if d ~= decompress then
|
||
lu.assertTrue(false, ("My decompress does not match expected result."
|
||
.."expected: %s, actual: %s, Returned status of decompress: %d")
|
||
:format(StringForPrint(StringToHex(d))
|
||
, StringForPrint(StringToHex(decompress)), decompress_status))
|
||
else
|
||
-- Check my decompress result with "puff"
|
||
local input_filename = "tests/tmpFile"
|
||
local inputFile = io.open(input_filename, "wb")
|
||
inputFile:setvbuf("full")
|
||
inputFile:write(compress)
|
||
inputFile:flush()
|
||
inputFile:close()
|
||
local returned_status_puff, stdout_puff =
|
||
RunProgram("puff -w", input_filename
|
||
, input_filename..".decompress")
|
||
local returnedStatus_zdeflate, stdout_zdeflate =
|
||
RunProgram(is_zlib and "zdeflate --zlib -d <"
|
||
or "zdeflate -d <", input_filename, input_filename..".decompress")
|
||
if not d then
|
||
if not is_zlib then
|
||
if returned_status_puff ~= 0
|
||
and returnedStatus_zdeflate ~= 0 then
|
||
print((">>>> %q cannot be decompress as expected")
|
||
:format((StringForPrint(StringToHex(compress)))))
|
||
elseif returned_status_puff ~= 0
|
||
and returnedStatus_zdeflate == 0 then
|
||
lu.assertTrue(false,
|
||
(">>>> %q puff error but not zdeflate?")
|
||
:format((StringForPrint(StringToHex(compress)))))
|
||
elseif returned_status_puff == 0
|
||
and returnedStatus_zdeflate ~= 0 then
|
||
lu.assertTrue(false,
|
||
(">>>> %q zdeflate error but not puff?")
|
||
:format((StringForPrint(StringToHex(compress)))))
|
||
else
|
||
lu.assertTrue(false,
|
||
(">>>> %q my decompress error, but not puff or zdeflate")
|
||
:format((StringForPrint(StringToHex(compress)))))
|
||
end
|
||
else
|
||
if returnedStatus_zdeflate ~= 0 then
|
||
print((">>>> %q cannot be zlib decompress as expected")
|
||
:format(StringForPrint(StringToHex(compress))))
|
||
else
|
||
lu.assertTrue(false,
|
||
(">>>> %q my decompress error, but not zdeflate")
|
||
:format((StringForPrint(StringToHex(compress)))))
|
||
end
|
||
end
|
||
|
||
else
|
||
AssertLongStringEqual(d, stdout_zdeflate)
|
||
if not is_zlib then
|
||
AssertLongStringEqual(d, stdout_puff)
|
||
end
|
||
print((">>>> %q is decompressed to %q as expected")
|
||
:format(StringForPrint(StringToHex(compress))
|
||
, StringForPrint(StringToHex(d))))
|
||
end
|
||
end
|
||
end
|
||
|
||
local function CheckZlibDecompressIncludingError(compress, decompress)
|
||
return CheckDecompressIncludingError(compress, decompress, true)
|
||
end
|
||
|
||
local function CreateDictionaryWithoutVerify(str)
|
||
-- Dont do this in the real program.
|
||
-- Dont calculate adler32 in runtime. Do hardcode it as constant.
|
||
-- This is just for test purpose
|
||
local dict = LibDeflate:CreateDictionary(str, #str, LibDeflate:Adler32(str))
|
||
return dict
|
||
end
|
||
|
||
local function CreateAndCheckDictionary(str)
|
||
local strlen = #str
|
||
local dictionary = CreateDictionaryWithoutVerify(str)
|
||
|
||
lu.assertTrue(LibDeflate.internals.IsValidDictionary(dictionary))
|
||
for i=1, strlen do
|
||
lu.assertEquals(dictionary.string_table[i], string_byte(str, i, i))
|
||
end
|
||
lu.assertEquals(dictionary.strlen, str:len())
|
||
for i=1, strlen-2 do
|
||
local hash = string_byte(str, i, i)*65536
|
||
+ string_byte(str, i+1, i+1)*256
|
||
+ string_byte(str, i+2, i+2)
|
||
local hash_chain = dictionary.hash_tables[hash]
|
||
lu.assertNotNil(hash_chain, "nil hash_chain?")
|
||
local found = false
|
||
for j = 1, #hash_chain do
|
||
if hash_chain[j] == i-strlen then
|
||
found = true
|
||
break
|
||
end
|
||
end
|
||
lu.assertTrue(found
|
||
, ("hash index %d not found in dictionary hash_table."):format(i))
|
||
end
|
||
return dictionary
|
||
end
|
||
|
||
|
||
|
||
-- the input dictionary must can make compressed data smaller.
|
||
-- otherwise, set dontCheckEffectivenss
|
||
local function CheckDictEffectiveness(str, dictionary, dict_str
|
||
, dontCheckEffectiveness)
|
||
local configs = {level = 7}
|
||
local compress_dict = LibDeflate:CompressDeflateWithDict(str
|
||
, dictionary, configs)
|
||
local decompressed_dict =
|
||
LibDeflate:DecompressDeflateWithDict(compress_dict, dictionary)
|
||
AssertLongStringEqual(decompressed_dict, str)
|
||
|
||
local compress_no_dict = LibDeflate:CompressDeflate(str, configs)
|
||
local decompressed_no_dict =
|
||
LibDeflate:DecompressDeflate(compress_no_dict)
|
||
AssertLongStringEqual(decompressed_no_dict, str)
|
||
|
||
local byte_smaller_with_dict = compress_no_dict:len()
|
||
- compress_dict:len()
|
||
if not dontCheckEffectiveness then
|
||
lu.assertTrue(byte_smaller_with_dict > 0)
|
||
print((">>> %d bytes smaller with (deflate dict) "..
|
||
"DICT: %s, DATA: %s")
|
||
:format(byte_smaller_with_dict
|
||
, StringForPrint(dict_str), StringForPrint(str)))
|
||
end
|
||
|
||
local zlib_compress_dict = LibDeflate:
|
||
CompressZlibWithDict(str, dictionary, configs)
|
||
local zlib_decompressed_dict =
|
||
LibDeflate:DecompressZlibWithDict(zlib_compress_dict, dictionary)
|
||
AssertLongStringEqual(zlib_decompressed_dict, str)
|
||
|
||
local zlib_compress_no_dict = LibDeflate:CompressZlib(str, configs)
|
||
local zlib_decompressed_no_dict =
|
||
LibDeflate:DecompressZlib(zlib_compress_no_dict)
|
||
AssertLongStringEqual(zlib_decompressed_no_dict, str)
|
||
|
||
local zlib_byte_smaller_with_dict = zlib_compress_no_dict:len()
|
||
- zlib_compress_dict:len()
|
||
-- for zlib with dict, 4 extra bytes needed to store
|
||
-- the adler32 of dictionary
|
||
if not dontCheckEffectiveness then
|
||
lu.assertTrue(zlib_byte_smaller_with_dict > -4)
|
||
print((">>> %d bytes smaller with (zlib dict) DICT: %s DATA: %s")
|
||
:format(zlib_byte_smaller_with_dict
|
||
, StringForPrint(dict_str), StringForPrint(str)))
|
||
end
|
||
|
||
return compress_dict, compress_no_dict
|
||
, zlib_compress_dict, zlib_compress_no_dict
|
||
end
|
||
|
||
-- Commandline
|
||
local arg = _G.arg
|
||
if arg and #arg >= 1 and type(arg[0]) == "string" then
|
||
if #arg >= 2 and arg[1] == "-o" then
|
||
-- For testing purpose (test_from_random_files_in_disk.py),
|
||
-- check if the file can be opened by lua
|
||
local input = arg[2]
|
||
local inputFile = io.open(input, "rb")
|
||
if not inputFile then
|
||
os.exit(1)
|
||
end
|
||
inputFile.close()
|
||
os.exit(0)
|
||
elseif #arg >= 3 and arg[1] == "-c" then
|
||
-- For testing purpose (test_from_random_files_in_disk.py)
|
||
-- , check the if a file can be correctly compress and decompress to origin
|
||
os.exit(CheckCompressAndDecompressFile(arg[2], "all", nil
|
||
, "tests/tmp"))
|
||
end
|
||
end
|
||
|
||
-------------------------------------------------------------------------
|
||
-- LibCompress encode code to help verity encode code in LibDeflate -----
|
||
-------------------------------------------------------------------------
|
||
local LibCompressEncoder = {}
|
||
do
|
||
local gsub_escape_table = {
|
||
['\000'] = "%z",
|
||
[('(')] = "%(",
|
||
[(')')] = "%)",
|
||
[('.')] = "%.",
|
||
[('%')] = "%%",
|
||
[('+')] = "%+",
|
||
[('-')] = "%-",
|
||
[('*')] = "%*",
|
||
[('?')] = "%?",
|
||
[('[')] = "%[",
|
||
[(']')] = "%]",
|
||
[('^')] = "%^",
|
||
[('$')] = "%$"
|
||
}
|
||
|
||
local function escape_for_gsub(str)
|
||
return str:gsub("([%z%(%)%.%%%+%-%*%?%[%]%^%$])", gsub_escape_table)
|
||
end
|
||
|
||
function LibCompressEncoder:GetEncodeTable(reservedChars, escapeChars
|
||
, mapChars)
|
||
reservedChars = reservedChars or ""
|
||
escapeChars = escapeChars or ""
|
||
mapChars = mapChars or ""
|
||
|
||
-- select a default escape character
|
||
if escapeChars == "" then
|
||
return nil, "No escape characters supplied"
|
||
end
|
||
|
||
if #reservedChars < #mapChars then
|
||
return nil, "Number of reserved characters must be at least "
|
||
.."as many as the number of mapped chars"
|
||
end
|
||
|
||
if reservedChars == "" then
|
||
return nil, "No characters to encode"
|
||
end
|
||
|
||
-- list of characters that must be encoded
|
||
local encodeBytes = reservedChars..escapeChars..mapChars
|
||
|
||
-- build list of bytes not available as a suffix to a prefix byte
|
||
local taken = {}
|
||
for i = 1, string_len(encodeBytes) do
|
||
taken[string_sub(encodeBytes, i, i)] = true
|
||
end
|
||
|
||
-- allocate a table to hold encode/decode strings/functions
|
||
local codecTable = {}
|
||
|
||
-- the encoding can be a single gsub,
|
||
-- but the decoding can require multiple gsubs
|
||
local decode_func_string = {}
|
||
|
||
local encode_search = {}
|
||
local encode_translate = {}
|
||
local encode_func
|
||
local decode_search = {}
|
||
local decode_translate = {}
|
||
local decode_func
|
||
local c, r, to, from
|
||
local escapeCharIndex, escapeChar = 0
|
||
|
||
-- map single byte to single byte
|
||
if #mapChars > 0 then
|
||
for i = 1, #mapChars do
|
||
from = string_sub(reservedChars, i, i)
|
||
to = string_sub(mapChars, i, i)
|
||
encode_translate[from] = to
|
||
table_insert(encode_search, from)
|
||
decode_translate[to] = from
|
||
table_insert(decode_search, to)
|
||
end
|
||
codecTable["decode_search"..tostring(escapeCharIndex)]
|
||
= "([".. escape_for_gsub(table_concat(decode_search)).."])"
|
||
codecTable["decode_translate"..tostring(escapeCharIndex)] =
|
||
decode_translate
|
||
table_insert(decode_func_string, "str = str:gsub(self.decode_search"
|
||
..tostring(escapeCharIndex)..", self.decode_translate"
|
||
..tostring(escapeCharIndex)..");")
|
||
end
|
||
|
||
-- map single byte to double-byte
|
||
escapeCharIndex = escapeCharIndex + 1
|
||
escapeChar = string_sub(escapeChars, escapeCharIndex, escapeCharIndex)
|
||
r = 0 -- suffix char value to the escapeChar
|
||
decode_search = {}
|
||
decode_translate = {}
|
||
for i = 1, string_len(encodeBytes) do
|
||
c = string_sub(encodeBytes, i, i)
|
||
if not encode_translate[c] then
|
||
-- this loop will update escapeChar and r
|
||
while r >= 256 or taken[string_char(r)] do -- Defliate patch
|
||
-- bug in LibCompress r81
|
||
-- while r < 256 and taken[string_char(r)] do
|
||
r = r + 1
|
||
if r > 255 then -- switch to next escapeChar
|
||
if escapeChar == "" then
|
||
-- we are out of escape chars and we need more!
|
||
return nil, "Out of escape characters"
|
||
end
|
||
|
||
codecTable["decode_search"..tostring(escapeCharIndex)] =
|
||
escape_for_gsub(escapeChar)
|
||
.."(["..
|
||
escape_for_gsub(table_concat(decode_search)).."])"
|
||
codecTable["decode_translate"
|
||
..tostring(escapeCharIndex)] = decode_translate
|
||
table_insert(decode_func_string,
|
||
"str = str:gsub(self.decode_search"
|
||
..tostring(escapeCharIndex)
|
||
..", self.decode_translate"
|
||
..tostring(escapeCharIndex)..");")
|
||
|
||
escapeCharIndex = escapeCharIndex + 1
|
||
escapeChar = string_sub(escapeChars
|
||
, escapeCharIndex, escapeCharIndex)
|
||
|
||
r = 0
|
||
decode_search = {}
|
||
decode_translate = {}
|
||
end
|
||
end
|
||
encode_translate[c] = escapeChar..string_char(r)
|
||
table_insert(encode_search, c)
|
||
decode_translate[string_char(r)] = c
|
||
table_insert(decode_search, string_char(r))
|
||
r = r + 1
|
||
end
|
||
end
|
||
|
||
if r > 0 then
|
||
codecTable["decode_search"..tostring(escapeCharIndex)] =
|
||
escape_for_gsub(escapeChar)
|
||
.."([".. escape_for_gsub(table_concat(decode_search)).."])"
|
||
codecTable["decode_translate"..tostring(escapeCharIndex)] =
|
||
decode_translate
|
||
table_insert(decode_func_string,
|
||
"str = str:gsub(self.decode_search"..tostring(escapeCharIndex)
|
||
..", self.decode_translate"..tostring(escapeCharIndex)..");")
|
||
end
|
||
|
||
-- change last line from "str = ...;" to "return ...;";
|
||
decode_func_string[#decode_func_string] =
|
||
decode_func_string[#decode_func_string]
|
||
:gsub("str = (.*);", "return %1;")
|
||
decode_func_string = "return function(self, str) "
|
||
..table_concat(decode_func_string).." end"
|
||
|
||
encode_search = "(["
|
||
.. escape_for_gsub(table_concat(encode_search)).."])"
|
||
decode_search = escape_for_gsub(escapeChars)
|
||
.."([".. escape_for_gsub(table_concat(decode_search)).."])"
|
||
|
||
encode_func = assert(loadstring(
|
||
"return function(self, str) "
|
||
.."return str:gsub(self.encode_search, "
|
||
.."self.encode_translate); end"))()
|
||
decode_func = assert(loadstring(decode_func_string))()
|
||
|
||
codecTable.encode_search = encode_search
|
||
codecTable.encode_translate = encode_translate
|
||
codecTable.Encode = encode_func
|
||
codecTable.decode_search = decode_search
|
||
codecTable.decode_translate = decode_translate
|
||
codecTable.Decode = decode_func
|
||
|
||
codecTable.decode_func_string = decode_func_string -- to be deleted
|
||
return codecTable
|
||
end
|
||
|
||
-- Addons: Call this only once and reuse the returned
|
||
-- table for all encodings/decodings.
|
||
function LibCompressEncoder:GetAddonEncodeTable(reservedChars
|
||
, escapeChars, mapChars )
|
||
reservedChars = reservedChars or ""
|
||
escapeChars = escapeChars or ""
|
||
mapChars = mapChars or ""
|
||
-- Following byte values are not allowed:
|
||
-- \000
|
||
if escapeChars == "" then
|
||
escapeChars = "\001"
|
||
end
|
||
return self:GetEncodeTable( (reservedChars or "").."\000"
|
||
, escapeChars, mapChars)
|
||
end
|
||
|
||
-- Addons: Call this only once and reuse the returned
|
||
-- table for all encodings/decodings.
|
||
function LibCompressEncoder:GetChatEncodeTable(reservedChars
|
||
, escapeChars, mapChars)
|
||
reservedChars = reservedChars or ""
|
||
escapeChars = escapeChars or ""
|
||
mapChars = mapChars or ""
|
||
local r = {}
|
||
for i = 128, 255 do
|
||
table_insert(r, string_char(i))
|
||
end
|
||
reservedChars = "sS\000\010\013\124%"
|
||
..table_concat(r)..(reservedChars or "")
|
||
if escapeChars == "" then
|
||
escapeChars = "\029\031"
|
||
end
|
||
if mapChars == "" then
|
||
mapChars = "\015\020";
|
||
end
|
||
return self:GetEncodeTable(reservedChars, escapeChars, mapChars)
|
||
end
|
||
end
|
||
|
||
local _libcompress_addon_codec = LibCompressEncoder:GetAddonEncodeTable()
|
||
local _libcompress_chat_codec = LibCompressEncoder:GetChatEncodeTable()
|
||
|
||
-- Check if LibDeflate's encoding works properly
|
||
local function CheckEncodeAndDecode(str, reserved_chars, escape_chars
|
||
, map_chars)
|
||
if reserved_chars then
|
||
local encode_decode_table_libcompress =
|
||
LibCompressEncoder:GetEncodeTable(reserved_chars
|
||
, escape_chars, map_chars)
|
||
local encode_decode_table, message =
|
||
LibDeflate:CreateCodec(reserved_chars
|
||
, escape_chars, map_chars)
|
||
if not encode_decode_table then
|
||
print(message)
|
||
end
|
||
local encoded_libcompress = encode_decode_table_libcompress:Encode(str)
|
||
local encoded = encode_decode_table:Encode(str)
|
||
AssertLongStringEqual(encoded, encoded_libcompress
|
||
, "Encoded result does not match libcompress")
|
||
AssertLongStringEqual(encode_decode_table:Decode(encoded), str
|
||
, "Encoded str cant be decoded to origin")
|
||
end
|
||
|
||
local encoded_addon = LibDeflate:EncodeForWoWAddonChannel(str)
|
||
local encoded_addon_libcompress =
|
||
_libcompress_addon_codec:Encode(str)
|
||
AssertLongStringEqual(encoded_addon, encoded_addon_libcompress
|
||
, "Encoded addon channel result does not match libcompress")
|
||
AssertLongStringEqual(LibDeflate:DecodeForWoWAddonChannel(encoded_addon)
|
||
, str, "Encoded for addon channel str cant be decoded to origin")
|
||
|
||
local encoded_chat = LibDeflate:EncodeForWoWChatChannel(str)
|
||
local encoded_chat_libcompress = _libcompress_chat_codec:Encode(str)
|
||
AssertLongStringEqual(encoded_chat, encoded_chat_libcompress
|
||
, "Encoded chat channel result does not match libcompress")
|
||
AssertLongStringEqual(LibDeflate:DecodeForWoWChatChannel(encoded_chat), str
|
||
, "Encoded for chat channel str cant be decoded to origin")
|
||
end
|
||
|
||
--------------------------------------------------------------
|
||
-- Actual Tests Start ----------------------------------------
|
||
--------------------------------------------------------------
|
||
TestBasicStrings = {}
|
||
function TestBasicStrings:TestEmpty()
|
||
CheckCompressAndDecompressString("", "all")
|
||
end
|
||
function TestBasicStrings:TestAllLiterals1()
|
||
CheckCompressAndDecompressString("ab", "all")
|
||
end
|
||
function TestBasicStrings:TestAllLiterals2()
|
||
CheckCompressAndDecompressString("abcdefgh", "all")
|
||
end
|
||
function TestBasicStrings:TestAllLiterals3()
|
||
local t = {}
|
||
for i=0, 255 do
|
||
t[#t+1] = string.char(i)
|
||
end
|
||
local str = table.concat(t)
|
||
CheckCompressAndDecompressString(str, "all")
|
||
end
|
||
|
||
function TestBasicStrings:TestRepeat()
|
||
CheckCompressAndDecompressString("aaaaaaaaaaaaaaaaaa", "all")
|
||
end
|
||
|
||
function TestBasicStrings:TestLongRepeat()
|
||
local repeated = {}
|
||
for i=1, 100000 do
|
||
repeated[i] = "c"
|
||
end
|
||
CheckCompressAndDecompressString(table.concat(repeated), "all")
|
||
end
|
||
|
||
TestMyData = {}
|
||
function TestMyData:TestItemStrings()
|
||
CheckCompressAndDecompressFile("tests/data/itemStrings.txt", "all")
|
||
end
|
||
|
||
function TestMyData:TestSmallTest()
|
||
CheckCompressAndDecompressFile("tests/data/smalltest.txt", "all")
|
||
end
|
||
|
||
function TestMyData:TestReconnectData()
|
||
CheckCompressAndDecompressFile("tests/data/reconnectData.txt", "all")
|
||
end
|
||
|
||
TestThirdPartySmall = {}
|
||
function TestThirdPartySmall:TestEmpty()
|
||
CheckCompressAndDecompressFile("tests/data/3rdparty/empty", "all")
|
||
end
|
||
|
||
function TestThirdPartySmall:TestX()
|
||
CheckCompressAndDecompressFile("tests/data/3rdparty/x", "all")
|
||
end
|
||
|
||
function TestThirdPartySmall:TestXYZZY()
|
||
CheckCompressAndDecompressFile("tests/data/3rdparty/xyzzy", "all")
|
||
end
|
||
|
||
TestThirdPartyMedium = {}
|
||
function TestThirdPartyMedium:Test10x10y()
|
||
CheckCompressAndDecompressFile("tests/data/3rdparty/10x10y", "all")
|
||
end
|
||
|
||
function TestThirdPartyMedium:TestQuickFox()
|
||
CheckCompressAndDecompressFile("tests/data/3rdparty/quickfox", "all")
|
||
end
|
||
|
||
function TestThirdPartyMedium:Test64x()
|
||
CheckCompressAndDecompressFile("tests/data/3rdparty/64x", "all")
|
||
end
|
||
|
||
function TestThirdPartyMedium:TestUkkonoona()
|
||
CheckCompressAndDecompressFile("tests/data/3rdparty/ukkonooa", "all")
|
||
end
|
||
|
||
function TestThirdPartyMedium:TestMonkey()
|
||
CheckCompressAndDecompressFile("tests/data/3rdparty/monkey", "all")
|
||
end
|
||
|
||
function TestThirdPartyMedium:TestRandomChunks()
|
||
CheckCompressAndDecompressFile("tests/data/3rdparty/random_chunks"
|
||
, "all")
|
||
end
|
||
|
||
function TestThirdPartyMedium:TestGrammerLsp()
|
||
CheckCompressAndDecompressFile("tests/data/3rdparty/grammar.lsp"
|
||
, "all")
|
||
end
|
||
|
||
function TestThirdPartyMedium:TestXargs1()
|
||
CheckCompressAndDecompressFile("tests/data/3rdparty/xargs.1", "all")
|
||
end
|
||
|
||
function TestThirdPartyMedium:TestRandomOrg10KBin()
|
||
CheckCompressAndDecompressFile("tests/data/3rdparty/random_org_10k.bin"
|
||
, "all")
|
||
end
|
||
|
||
function TestThirdPartyMedium:TestCpHtml()
|
||
CheckCompressAndDecompressFile("tests/data/3rdparty/cp.html", "all")
|
||
end
|
||
|
||
function TestThirdPartyMedium:TestBadData1Snappy()
|
||
CheckCompressAndDecompressFile("tests/data/3rdparty/baddata1.snappy"
|
||
, "all")
|
||
end
|
||
|
||
function TestThirdPartyMedium:TestBadData2Snappy()
|
||
CheckCompressAndDecompressFile("tests/data/3rdparty/baddata2.snappy"
|
||
, "all")
|
||
end
|
||
|
||
function TestThirdPartyMedium:TestBadData3Snappy()
|
||
CheckCompressAndDecompressFile("tests/data/3rdparty/baddata3.snappy"
|
||
, "all")
|
||
end
|
||
|
||
function TestThirdPartyMedium:TestSum()
|
||
CheckCompressAndDecompressFile("tests/data/3rdparty/sum", "all")
|
||
end
|
||
|
||
Test_64K = {}
|
||
function Test_64K:Test64KFile()
|
||
CheckCompressAndDecompressFile("tests/data/64k.txt", "all")
|
||
end
|
||
function Test_64K:Test64KFilePlus1()
|
||
CheckCompressAndDecompressFile("tests/data/64kplus1.txt", "all")
|
||
end
|
||
function Test_64K:Test64KFilePlus2()
|
||
CheckCompressAndDecompressFile("tests/data/64kplus2.txt", "all")
|
||
end
|
||
function Test_64K:Test64KFilePlus3()
|
||
CheckCompressAndDecompressFile("tests/data/64kplus3.txt", "all")
|
||
end
|
||
function Test_64K:Test64KFilePlus4()
|
||
CheckCompressAndDecompressFile("tests/data/64kplus4.txt", "all")
|
||
end
|
||
function Test_64K:Test64KFileMinus1()
|
||
CheckCompressAndDecompressFile("tests/data/64kminus1.txt", "all")
|
||
end
|
||
function Test_64K:Test64KRepeated()
|
||
local repeated = {}
|
||
for i=1, 65536 do
|
||
repeated[i] = "c"
|
||
end
|
||
CheckCompressAndDecompressString(table.concat(repeated), "all")
|
||
end
|
||
function Test_64K:Test64KRepeatedPlus1()
|
||
local repeated = {}
|
||
for i=1, 65536+1 do
|
||
repeated[i] = "c"
|
||
end
|
||
CheckCompressAndDecompressString(table.concat(repeated), "all")
|
||
end
|
||
function Test_64K:Test64KRepeatedPlus2()
|
||
local repeated = {}
|
||
for i=1, 65536+2 do
|
||
repeated[i] = "c"
|
||
end
|
||
CheckCompressAndDecompressString(table.concat(repeated), "all")
|
||
end
|
||
function Test_64K:Test64KRepeatedPlus3()
|
||
local repeated = {}
|
||
for i=1, 65536+3 do
|
||
repeated[i] = "c"
|
||
end
|
||
CheckCompressAndDecompressString(table.concat(repeated), "all")
|
||
end
|
||
function Test_64K:Test64KRepeatedPlus4()
|
||
local repeated = {}
|
||
for i=1, 65536+4 do
|
||
repeated[i] = "c"
|
||
end
|
||
CheckCompressAndDecompressString(table.concat(repeated), "all")
|
||
end
|
||
function Test_64K:Test64KRepeatedMinus1()
|
||
local repeated = {}
|
||
for i=1, 65536-1 do
|
||
repeated[i] = "c"
|
||
end
|
||
CheckCompressAndDecompressString(table.concat(repeated), "all")
|
||
end
|
||
function Test_64K:Test64KRepeatedMinus2()
|
||
local repeated = {}
|
||
for i=1, 65536-2 do
|
||
repeated[i] = "c"
|
||
end
|
||
CheckCompressAndDecompressString(table.concat(repeated), "all")
|
||
end
|
||
|
||
-- > 64K
|
||
TestThirdPartyBig = {}
|
||
function TestThirdPartyBig:TestBackward65536()
|
||
CheckCompressAndDecompressFile("tests/data/3rdparty/backward65536"
|
||
, "all")
|
||
end
|
||
function TestThirdPartyBig:TestHTML()
|
||
CheckCompressAndDecompressFile("tests/data/3rdparty/html"
|
||
, {0,1,2,3,4,5})
|
||
end
|
||
function TestThirdPartyBig:TestPaper100kPdf()
|
||
CheckCompressAndDecompressFile("tests/data/3rdparty/paper-100k.pdf"
|
||
, {0,1,2,3,4,5})
|
||
end
|
||
function TestThirdPartyBig:TestGeoProtodata()
|
||
CheckCompressAndDecompressFile("tests/data/3rdparty/geo.protodata"
|
||
, {0,1,2,3,4,5})
|
||
end
|
||
function TestThirdPartyBig:TestFireworksJpeg()
|
||
CheckCompressAndDecompressFile("tests/data/3rdparty/fireworks.jpeg"
|
||
, {0,1,2,3,4,5})
|
||
end
|
||
function TestThirdPartyBig:TestAsyoulik()
|
||
CheckCompressAndDecompressFile("tests/data/3rdparty/asyoulik.txt"
|
||
, {0,1,2,3,4,5})
|
||
end
|
||
function TestThirdPartyBig:TestCompressedRepeated()
|
||
CheckCompressAndDecompressFile(
|
||
"tests/data/3rdparty/compressed_repeated", {0,1,2,3,4,5})
|
||
end
|
||
function TestThirdPartyBig:TestAlice29()
|
||
CheckCompressAndDecompressFile("tests/data/3rdparty/alice29.txt"
|
||
, {0,1,2,3,4,5})
|
||
end
|
||
function TestThirdPartyBig:TestQuickfox_repeated()
|
||
CheckCompressAndDecompressFile("tests/data/3rdparty/quickfox_repeated"
|
||
, {0,1,2,3,4,5})
|
||
end
|
||
function TestThirdPartyBig:TestKppknGtb()
|
||
CheckCompressAndDecompressFile("tests/data/3rdparty/kppkn.gtb"
|
||
, {0,1,2,3,4,5})
|
||
end
|
||
function TestThirdPartyBig:TestZeros()
|
||
CheckCompressAndDecompressFile("tests/data/3rdparty/zeros"
|
||
, {0,1,2,3,4,5})
|
||
end
|
||
function TestThirdPartyBig:TestMapsdatazrh()
|
||
CheckCompressAndDecompressFile("tests/data/3rdparty/mapsdatazrh"
|
||
, {0,1,2,3,4,5})
|
||
end
|
||
function TestThirdPartyBig:TestHtml_x_4()
|
||
CheckCompressAndDecompressFile("tests/data/3rdparty/html_x_4"
|
||
, {0,1,2,3,4})
|
||
end
|
||
function TestThirdPartyBig:TestLcet10()
|
||
CheckCompressAndDecompressFile("tests/data/3rdparty/lcet10.txt"
|
||
, {0,1,2,3,4,5})
|
||
end
|
||
function TestThirdPartyBig:TestPlrabn12()
|
||
CheckCompressAndDecompressFile("tests/data/3rdparty/plrabn12.txt"
|
||
, {0,1,2,3,4,5})
|
||
end
|
||
function TestThirdPartyBig:TestUrls10K()
|
||
CheckCompressAndDecompressFile("tests/data/3rdparty/urls.10K"
|
||
, {0,1,2,3,4,5})
|
||
end
|
||
function TestThirdPartyBig:Testptt5()
|
||
CheckCompressAndDecompressFile("tests/data/3rdparty/ptt5"
|
||
, {0,1,2,3,4})
|
||
end
|
||
function TestThirdPartyBig:TestKennedyXls()
|
||
CheckCompressAndDecompressFile("tests/data/3rdparty/kennedy.xls"
|
||
, {0,1,2,3,4})
|
||
end
|
||
|
||
TestWoWData = {}
|
||
function TestWoWData:TestWarlockWeakAuras()
|
||
CheckCompressAndDecompressFile("tests/data/warlockWeakAuras.txt"
|
||
, {0,1,2,3,4})
|
||
end
|
||
function TestWoWData:TestTotalRp3Data()
|
||
CheckCompressAndDecompressFile("tests/data/totalrp3.txt"
|
||
, {0,1,2,3,4})
|
||
end
|
||
|
||
TestDecompress = {}
|
||
-- Test from puff
|
||
function TestDecompress:TestStoreEmpty()
|
||
CheckDecompressIncludingError("\001\000\000\255\255", "")
|
||
end
|
||
function TestDecompress:TestStore1()
|
||
CheckDecompressIncludingError("\001\001\000\254\255\010", "\010")
|
||
end
|
||
function TestDecompress:TestStore2()
|
||
local t = {}
|
||
for i=1, 65535 do
|
||
t[i] = "a"
|
||
end
|
||
local str = table.concat(t)
|
||
CheckDecompressIncludingError("\001\255\255\000\000"..str, str)
|
||
end
|
||
function TestDecompress:TestStore3()
|
||
local t = {}
|
||
for i=1, 65535 do
|
||
t[i] = "a"
|
||
end
|
||
local str = table.concat(t)
|
||
CheckDecompressIncludingError("\000\255\255\000\000"..str
|
||
.."\001\255\255\000\000"..str, str..str)
|
||
end
|
||
function TestDecompress:TestStore4()
|
||
-- 0101 00fe ff31
|
||
CheckDecompressIncludingError("\001\001\000\254\255\049", "1")
|
||
end
|
||
function TestDecompress:TestStore5()
|
||
local size = 0x5555
|
||
local str = GetLimitedRandomString(size)
|
||
CheckDecompressIncludingError("\001\085\085\170\170"..str, str)
|
||
end
|
||
|
||
function TestDecompress:TestStoreRandom()
|
||
for _ = 1, 20 do
|
||
local size = math.random(1, 65535)
|
||
local str = GetLimitedRandomString(size)
|
||
CheckDecompressIncludingError("\001"..string.char(size%256)
|
||
..string.char((size-size%256)/256)
|
||
..string.char(255-size%256)
|
||
..string.char(255-(size-size%256)/256)..str, str)
|
||
end
|
||
end
|
||
function TestDecompress:TestFix1()
|
||
CheckDecompressIncludingError("\003\000", "")
|
||
end
|
||
function TestDecompress:TestFix2()
|
||
CheckDecompressIncludingError("\051\004\000", "1")
|
||
end
|
||
function TestDecompress:TestFixThenStore1()
|
||
local t = {}
|
||
for i=1, 65535 do
|
||
t[i] = "a"
|
||
end
|
||
local str = table.concat(t)
|
||
CheckDecompressIncludingError("\050\004\000\255\255\000\000"
|
||
..str.."\001\255\255\000\000"..str, "1"..str..str)
|
||
end
|
||
function TestDecompress:TestIncomplete()
|
||
-- Additonal 1 byte after the end of compression data
|
||
CheckDecompressIncludingError("\001\001\000\254\255\010\000", "\010")
|
||
end
|
||
function TestDecompress:TestStoreSizeTooBig()
|
||
CheckDecompressIncludingError("\001\001\000\254\255", nil)
|
||
CheckDecompressIncludingError("\001\002\000\253\255\001", nil)
|
||
end
|
||
function TestDecompress:TestEmtpy()
|
||
CheckDecompressIncludingError("", nil)
|
||
end
|
||
function TestDecompress:TestOneByte()
|
||
for i=0, 255 do
|
||
CheckDecompressIncludingError(string.char(i), nil)
|
||
end
|
||
end
|
||
function TestDecompress:TestPuffReturn2()
|
||
CheckDecompressIncludingError("\000", nil)
|
||
CheckDecompressIncludingError("\002", nil)
|
||
CheckDecompressIncludingError("\004", nil)
|
||
CheckDecompressIncludingError(HexToString("00 01 00 fe ff"), nil)
|
||
CheckDecompressIncludingError(
|
||
HexToString("04 80 49 92 24 49 92 24 0f b4 ff ff c3 04"), nil)
|
||
end
|
||
function TestDecompress:TestPuffReturn245()
|
||
CheckDecompressIncludingError(HexToString(
|
||
"0c c0 81 00 00 00 00 00 90 ff 6b 04"), nil)
|
||
end
|
||
function TestDecompress:TestPuffReturn246()
|
||
CheckDecompressIncludingError(HexToString("1a 07"), nil)
|
||
CheckDecompressIncludingError(HexToString("02 7e ff ff"), nil)
|
||
CheckDecompressIncludingError(HexToString(
|
||
"04 c0 81 08 00 00 00 00 20 7f eb 0b 00 00"), nil)
|
||
end
|
||
function TestDecompress:TestPuffReturn247()
|
||
CheckDecompressIncludingError(HexToString(
|
||
"04 00 24 e9 ff 6d"), nil)
|
||
end
|
||
function TestDecompress:TestPuffReturn248()
|
||
CheckDecompressIncludingError(HexToString(
|
||
"04 80 49 92 24 49 92 24 0f b4 ff ff c3 84"), nil)
|
||
end
|
||
function TestDecompress:TestPuffReturn249()
|
||
CheckDecompressIncludingError(HexToString(
|
||
"04 80 49 92 24 49 92 24 71 ff ff 93 11 00"), nil)
|
||
end
|
||
function TestDecompress:TestPuffReturn250()
|
||
CheckDecompressIncludingError(HexToString(
|
||
"04 00 24 e9 ff ff"), nil)
|
||
end
|
||
function TestDecompress:TestPuffReturn251()
|
||
CheckDecompressIncludingError(HexToString("04 00 24 49"), nil)
|
||
end
|
||
function TestDecompress:TestPuffReturn252()
|
||
CheckDecompressIncludingError(HexToString("04 00 fe ff"), nil)
|
||
end
|
||
function TestDecompress:TestPuffReturn253()
|
||
CheckDecompressIncludingError(HexToString("fc 00 00"), nil)
|
||
end
|
||
function TestDecompress:TestPuffReturn254()
|
||
CheckDecompressIncludingError(HexToString("00 00 00 00 00"), nil)
|
||
end
|
||
function TestDecompress:TestZlibCoverSupport()
|
||
CheckDecompressIncludingError(HexToString("63 00"), nil)
|
||
CheckDecompressIncludingError(HexToString("63 18 05"), nil)
|
||
CheckDecompressIncludingError(
|
||
HexToString("63 18 68 30 d0 0 0"), ("\000"):rep(257))
|
||
CheckDecompressIncludingError(HexToString("3 00"), "")
|
||
CheckDecompressIncludingError("", nil)
|
||
CheckDecompressIncludingError("", nil, true)
|
||
end
|
||
function TestDecompress:TestZlibCoverWrap()
|
||
CheckZlibDecompressIncludingError(
|
||
HexToString("77 85"), nil) -- Bad zlib header
|
||
CheckZlibDecompressIncludingError(
|
||
HexToString("70 85"), nil) -- Bad zlib header
|
||
CheckZlibDecompressIncludingError(
|
||
HexToString("88 9c"), nil) -- Bad window size
|
||
CheckZlibDecompressIncludingError(
|
||
HexToString("f8 9c"), nil) -- Bad window size
|
||
CheckZlibDecompressIncludingError(
|
||
HexToString("78 90"), nil) -- Bad zlib header check
|
||
CheckZlibDecompressIncludingError(
|
||
HexToString("78 9c 63 00 00 00 01 00 01"), "\000") -- check Adler32
|
||
CheckZlibDecompressIncludingError(
|
||
HexToString("78 9c 63 00 00 00 01 00"), nil) -- Adler32 incomplete
|
||
CheckZlibDecompressIncludingError(
|
||
HexToString("78 9c 63 00 00 00 01 00 02"), nil) -- wrong Adler32
|
||
CheckZlibDecompressIncludingError(
|
||
HexToString("78 9c 63 0"), nil) -- no Adler32
|
||
end
|
||
function TestDecompress:TestZlibCoverInflate()
|
||
CheckDecompressIncludingError(
|
||
HexToString("0 0 0 0 0"), nil) -- invalid store block length
|
||
CheckDecompressIncludingError(
|
||
HexToString("3 0"), "", nil) -- Fixed block
|
||
CheckDecompressIncludingError(
|
||
HexToString("6"), nil) -- Invalid block type
|
||
CheckDecompressIncludingError(
|
||
HexToString("1 1 0 fe ff 0"), "\000") -- Stored block
|
||
CheckDecompressIncludingError(
|
||
HexToString("fc 0 0"), nil) -- Too many length or distance symbols
|
||
CheckDecompressIncludingError(
|
||
HexToString("4 0 fe ff"), nil) -- Invalid code lengths set
|
||
CheckDecompressIncludingError(
|
||
HexToString("4 0 24 49 0"), nil) -- Invalid bit length repeat
|
||
CheckDecompressIncludingError(
|
||
HexToString("4 0 24 e9 ff ff"), nil) -- Invalid bit length repeat
|
||
-- Invalid code: missing end of block
|
||
CheckDecompressIncludingError(
|
||
HexToString("4 0 24 e9 ff 6d"), nil)
|
||
-- Invalid literal/lengths set
|
||
CheckDecompressIncludingError(
|
||
HexToString("4 80 49 92 24 49 92 24 71 ff ff 93 11 0"), nil)
|
||
CheckDecompressIncludingError(
|
||
HexToString("4 80 49 92 24 49 92 24 71 ff ff 93 11 0"), nil)
|
||
-- Invalid distance set
|
||
CheckDecompressIncludingError(
|
||
HexToString("4 80 49 92 24 49 92 24 f b4 ff ff c3 84"), nil)
|
||
-- Invalid literal/length code
|
||
CheckDecompressIncludingError(
|
||
HexToString("4 c0 81 8 0 0 0 0 20 7f eb b 0 0"), nil)
|
||
CheckDecompressIncludingError(
|
||
HexToString("2 7e ff ff"), nil) -- Invalid distance code
|
||
-- Invalid distance too far
|
||
CheckDecompressIncludingError(
|
||
HexToString("c c0 81 0 0 0 0 0 90 ff 6b 4 0"), nil)
|
||
-- incorrect data check
|
||
CheckDecompressIncludingError(
|
||
HexToString("1f 8b 8 0 0 0 0 0 0 0 3 0 0 0 0 1"), nil)
|
||
-- incorrect length check
|
||
CheckDecompressIncludingError(
|
||
HexToString("1f 8b 8 0 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 1"), nil)
|
||
-- pull 17
|
||
CheckDecompressIncludingError(
|
||
HexToString("5 c0 21 d 0 0 0 80 b0 fe 6d 2f 91 6c"), "")
|
||
-- long code
|
||
CheckDecompressIncludingError(
|
||
HexToString(
|
||
"05 e0 81 91 24 cb b2 2c 49 e2 0f 2e 8b 9a 47 56 9f fb fe ec d2 ff 1f")
|
||
, "")
|
||
-- extra length
|
||
CheckDecompressIncludingError(
|
||
HexToString("ed c0 1 1 0 0 0 40 20 ff 57 1b 42 2c 4f")
|
||
, ("\000"):rep(516))
|
||
-- long distance and extra
|
||
CheckDecompressIncludingError(
|
||
HexToString(
|
||
"ed cf c1 b1 2c 47 10 c4 30 fa 6f 35 1d 1 82 59 3d fb be 2e 2a fc f c")
|
||
, ("\000"):rep(518))
|
||
-- Window end
|
||
CheckDecompressIncludingError(
|
||
HexToString(
|
||
"ed c0 81 0 0 0 0 80 a0 fd a9 17 a9 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0")
|
||
, nil)
|
||
-- inflate_fast TYPE return
|
||
CheckDecompressIncludingError(HexToString("2 8 20 80 0 3 0"), "")
|
||
-- Window wrap
|
||
CheckDecompressIncludingError(HexToString("63 18 5 40 c 0")
|
||
, ("\000"):rep(262))
|
||
end
|
||
function TestDecompress:TestZlibCoverFast()
|
||
-- fast length extra bits
|
||
CheckDecompressIncludingError(
|
||
HexToString(
|
||
"e5 e0 81 ad 6d cb b2 2c c9 01 1e 59 63 ae 7d ee fb 4d fd b5 35 41 68")
|
||
, nil)
|
||
-- fast distance extra bits
|
||
CheckDecompressIncludingError(
|
||
HexToString(
|
||
"25 fd 81 b5 6d 59 b6 6a 49 ea af 35 6 34 eb 8c b9 f6 b9 1e ef 67 49"
|
||
, nil))
|
||
-- Fast invalid distance code
|
||
CheckDecompressIncludingError(HexToString("3 7e 0 0 0 0 0"), nil)
|
||
-- Fast literal/length code
|
||
CheckDecompressIncludingError(HexToString("1b 7 0 0 0 0 0"), nil)
|
||
-- fast 2nd level codes and too far back
|
||
CheckDecompressIncludingError(
|
||
HexToString(
|
||
"d c7 1 ae eb 38 c 4 41 a0 87 72 de df fb 1f b8 36 b1 38 5d ff ff 0")
|
||
, nil)
|
||
-- Very common case
|
||
CheckDecompressIncludingError(
|
||
HexToString("63 18 5 8c 10 8 0 0 0 0")
|
||
, ("\000"):rep(258)..("\000\001"):rep(4))
|
||
-- Continous and wrap aroudn window
|
||
CheckDecompressIncludingError(
|
||
HexToString("63 60 60 18 c9 0 8 18 18 18 26 c0 28 0 29 0 0 0")
|
||
, ("\000"):rep(261)..("\144")..("\000"):rep(6)..("\144\000"))
|
||
-- Copy direct from output
|
||
CheckDecompressIncludingError(
|
||
HexToString("63 0 3 0 0 0 0 0"), ("\000"):rep(6))
|
||
end
|
||
function TestDecompress:TestAdditionalCoverage()
|
||
-- no zlib FLG
|
||
CheckZlibDecompressIncludingError(HexToString("78"), nil)
|
||
-- Stored block no len
|
||
CheckDecompressIncludingError(HexToString("1"), nil)
|
||
-- Stored block no len comp
|
||
CheckDecompressIncludingError(HexToString("1 1 0"), nil)
|
||
-- Stored block not one's complement
|
||
CheckDecompressIncludingError(HexToString("1 1 0 ff ff 0"), nil)
|
||
-- Stored block not one's complement
|
||
CheckDecompressIncludingError(HexToString("1 1 0 fe fe 0"), nil)
|
||
CheckDecompressIncludingError(
|
||
HexToString("1 34 43 cb bc")..("\000"):rep(17204)
|
||
, ("\000"):rep(17204)) -- Stored block
|
||
-- Stored block with 1 less byte
|
||
CheckDecompressIncludingError(
|
||
HexToString("1 34 43 cb bc")..("\000"):rep(17203), nil)
|
||
CheckDecompressIncludingError(
|
||
HexToString("1 34 43 cb bc")..("\000"):rep(17202), nil)
|
||
end
|
||
|
||
function TestDecompress:Test2ndReturn()
|
||
for _ = 1, 10 do
|
||
local str = GetLimitedRandomString(math.random(100, 300))
|
||
local compressed = LibDeflate:CompressDeflate(str)
|
||
local extra_len = math.random(1, 10)
|
||
local extra = GetLimitedRandomString(extra_len)
|
||
compressed = compressed..extra
|
||
local decompressed, unprocessed =
|
||
LibDeflate:DecompressDeflate(compressed)
|
||
AssertLongStringEqual(str, decompressed)
|
||
lu.assertEquals(unprocessed, extra_len)
|
||
end
|
||
for _ = 1, 10 do
|
||
local dict = CreateDictionaryWithoutVerify(
|
||
GetLimitedRandomString(math.random(100, 300)))
|
||
local str = GetLimitedRandomString(math.random(100, 300))
|
||
local compressed = LibDeflate:CompressDeflateWithDict(str, dict)
|
||
local extra_len = math.random(1, 10)
|
||
local extra = GetLimitedRandomString(extra_len)
|
||
compressed = compressed..extra
|
||
local decompressed, unprocessed =
|
||
LibDeflate:DecompressDeflateWithDict(compressed, dict)
|
||
AssertLongStringEqual(str, decompressed)
|
||
lu.assertEquals(unprocessed, extra_len)
|
||
end
|
||
for _ = 1, 10 do
|
||
local str = GetLimitedRandomString(math.random(100, 300))
|
||
local compressed = LibDeflate:CompressZlib(str)
|
||
local extra_len = math.random(1, 10)
|
||
local extra = GetLimitedRandomString(extra_len)
|
||
compressed = compressed..extra
|
||
local decompressed, unprocessed =
|
||
LibDeflate:DecompressZlib(compressed)
|
||
AssertLongStringEqual(str, decompressed)
|
||
lu.assertEquals(unprocessed, extra_len)
|
||
end
|
||
for _ = 1, 10 do
|
||
local dict = CreateDictionaryWithoutVerify(
|
||
GetLimitedRandomString(math.random(100, 300)))
|
||
local str = GetLimitedRandomString(math.random(100, 300))
|
||
local compressed = LibDeflate:CompressZlibWithDict(str, dict)
|
||
local extra_len = math.random(1, 10)
|
||
local extra = GetLimitedRandomString(extra_len)
|
||
compressed = compressed..extra
|
||
local decompressed, unprocessed =
|
||
LibDeflate:DecompressZlibWithDict(compressed, dict)
|
||
AssertLongStringEqual(str, decompressed)
|
||
lu.assertEquals(unprocessed, extra_len)
|
||
end
|
||
end
|
||
|
||
function TestDecompress:TestDecompressWithDict()
|
||
local dict = CreateDictionaryWithoutVerify("abcdefgh")
|
||
-- local adler32 = LibDeflate:Adler32("abcdefgh")
|
||
-- adler == 0x0e000325
|
||
lu.assertEquals(LibDeflate:DecompressZlib(
|
||
HexToString("78 9c 63 00 00 00 01 00 01")), "\000")
|
||
-- The data needs dictionary, but calling
|
||
-- DecompressZlib instead of DecompressZlibWithDict
|
||
lu.assertEquals(LibDeflate:DecompressZlib(
|
||
HexToString("78 bb 63 00 00 00 01 00 01")), nil)
|
||
lu.assertEquals(LibDeflate:DecompressZlib(
|
||
HexToString("78 bb 25 03 00 0e 63 00 00 00 01 00 01")), nil)
|
||
lu.assertEquals(LibDeflate:DecompressZlibWithDict(
|
||
HexToString("78 bb 0e 00 03 25 63 00 00 00 01 00 01"), dict)
|
||
, "\000")
|
||
|
||
-- input ends before dictionary adler32 is read.
|
||
lu.assertEquals(LibDeflate:DecompressZlibWithDict(
|
||
HexToString("78 bb 0e 00 03 "), dict)
|
||
, nil)
|
||
lu.assertEquals(LibDeflate:DecompressZlibWithDict(
|
||
HexToString("78 bb 0e 00 "), dict)
|
||
, nil)
|
||
lu.assertEquals(LibDeflate:DecompressZlibWithDict(
|
||
HexToString("78 bb 0e "), dict)
|
||
, nil)
|
||
lu.assertEquals(LibDeflate:DecompressZlibWithDict(
|
||
HexToString("78 bb "), dict)
|
||
, nil)
|
||
|
||
-- adler32 does not match
|
||
lu.assertEquals(LibDeflate:DecompressZlibWithDict(
|
||
HexToString("78 bb 25 03 00 0e 63 00 00 00 01 00 01"), dict)
|
||
, nil)
|
||
lu.assertEquals(LibDeflate:DecompressZlibWithDict(
|
||
HexToString("78 bb 0e 00 03 26 63 00 00 00 01 00 01"), dict)
|
||
, nil)
|
||
end
|
||
|
||
TestInternals = {}
|
||
-- Test from puff
|
||
function TestInternals:TestLoadString()
|
||
local LoadStringToTable = LibDeflate.internals.LoadStringToTable
|
||
local tmp
|
||
for _=1, 50 do
|
||
local t = {}
|
||
local strlen = math.random(0, 1000)
|
||
local str = GetLimitedRandomString(strlen)
|
||
local uncorruped_data = {}
|
||
for i=1, strlen do
|
||
uncorruped_data[i] = math.random(1, 12345)
|
||
t[i] = uncorruped_data[i]
|
||
end
|
||
local start
|
||
local stop
|
||
if strlen >= 1 then
|
||
start = math.random(1, strlen)
|
||
stop = math.random(1, strlen)
|
||
else
|
||
start = 1
|
||
stop = 0
|
||
end
|
||
if start > stop then
|
||
tmp = start
|
||
start = stop
|
||
stop = tmp
|
||
end
|
||
local offset = math.random(0, strlen)
|
||
LoadStringToTable(str, t, start, stop, offset)
|
||
for i=-1000, 2000 do
|
||
if i < start-offset or i > stop-offset then
|
||
lu.assertEquals(t[i], uncorruped_data[i]
|
||
, "loadStr corrupts unintended location")
|
||
else
|
||
lu.assertEquals(t[i], string_byte(str, i+offset)
|
||
, ("loadStr gives wrong data!, start=%d, stop=%d, i=%d")
|
||
:format(start, stop, i))
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
function TestInternals:TestSimpleRandom()
|
||
for _=1, 30 do
|
||
local strlen = math.random(0, 1000)
|
||
local str = GetLimitedRandomString(strlen)
|
||
local level = (math.random() < 0.5) and (math.random(1, 8)) or nil
|
||
local expected = str
|
||
local configs = {level = level}
|
||
local compress = LibDeflate:CompressDeflate(str, configs)
|
||
local _, actual = pcall(function() return LibDeflate
|
||
:DecompressDeflate(compress) end)
|
||
if expected ~= actual then
|
||
local strDumpFile = io.open("fail_random.tmp", "wb")
|
||
if (strDumpFile) then
|
||
strDumpFile:write(str)
|
||
print(("Failed test has been dumped to fail_random.tmp,"
|
||
.. "with level=%s"):
|
||
format(tostring(level)))
|
||
strDumpFile:close()
|
||
if type(actual) == "string" then
|
||
print(("Error msg is:\n"), actual:sub(1, 100))
|
||
end
|
||
end
|
||
lu.assertEquals(false, "My decompress does not match origin.")
|
||
end
|
||
end
|
||
end
|
||
|
||
function TestInternals:TestAdler32()
|
||
lu.assertEquals(LibDeflate:Adler32(""), 1)
|
||
lu.assertEquals(LibDeflate:Adler32("1"), 0x00320032)
|
||
lu.assertEquals(LibDeflate:Adler32("12"), 0x00960064)
|
||
lu.assertEquals(LibDeflate:Adler32("123"), 0x012D0097)
|
||
lu.assertEquals(LibDeflate:Adler32("1234"), 0x01F800CB)
|
||
lu.assertEquals(LibDeflate:Adler32("12345"), 0x02F80100)
|
||
lu.assertEquals(LibDeflate:Adler32("123456"), 0x042E0136)
|
||
lu.assertEquals(LibDeflate:Adler32("1234567"), 0x059B016D)
|
||
lu.assertEquals(LibDeflate:Adler32("12345678"), 0x074001A5)
|
||
lu.assertEquals(LibDeflate:Adler32("123456789"), 0x091E01DE)
|
||
lu.assertEquals(LibDeflate:Adler32("1234567890"), 0x0B2C020E)
|
||
lu.assertEquals(LibDeflate:Adler32("1234567890a"), 0x0D9B026F)
|
||
lu.assertEquals(LibDeflate:Adler32("1234567890ab"), 0x106C02D1)
|
||
lu.assertEquals(LibDeflate:Adler32("1234567890abc"), 0x13A00334)
|
||
lu.assertEquals(LibDeflate:Adler32("1234567890abcd"), 0x17380398)
|
||
lu.assertEquals(LibDeflate:Adler32("1234567890abcde"), 0x1B3503FD)
|
||
lu.assertEquals(LibDeflate:Adler32("1234567890abcdef"), 0x1F980463)
|
||
lu.assertEquals(LibDeflate:Adler32("1234567890abcefg"), 0x1F9E0466)
|
||
lu.assertEquals(LibDeflate:Adler32("1234567890abcefgh"), 0x246C04CE)
|
||
lu.assertEquals(LibDeflate:Adler32("1234567890abcefghi"), 0x29A30537)
|
||
lu.assertEquals(LibDeflate:Adler32("1234567890abcefghij"), 0x2F4405A1)
|
||
lu.assertEquals(LibDeflate:Adler32("1234567890abcefghijk"), 0x3550060C)
|
||
lu.assertEquals(LibDeflate:Adler32("1234567890abcefghijkl")
|
||
, 0x3BC80678)
|
||
lu.assertEquals(LibDeflate:Adler32("1234567890abcefghijklm")
|
||
, 0x42AD06E5)
|
||
lu.assertEquals(LibDeflate:Adler32("1234567890abcefghijklmn")
|
||
, 0x4A000753)
|
||
lu.assertEquals(LibDeflate:Adler32(
|
||
"1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
||
, 0x8C40150C)
|
||
local adler32Test = GetFileData("tests/data/adler32Test.txt")
|
||
lu.assertEquals(LibDeflate:Adler32(adler32Test), 0x5D9BAF5D)
|
||
local adler32Test2 = GetFileData("tests/data/adler32Test2.txt")
|
||
lu.assertEquals(LibDeflate:Adler32(adler32Test2), 0xD6A07E29)
|
||
end
|
||
|
||
function TestInternals:TestLibStub()
|
||
-- Start of LibStub
|
||
local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2
|
||
-- NOTE: It is intended that LibStub is global
|
||
LibStub = _G[LIBSTUB_MAJOR]
|
||
|
||
if not LibStub or LibStub.minor < LIBSTUB_MINOR then
|
||
LibStub = LibStub or {libs = {}, minors = {} }
|
||
_G[LIBSTUB_MAJOR] = LibStub
|
||
LibStub.minor = LIBSTUB_MINOR
|
||
function LibStub:NewLibrary(major, minor)
|
||
assert(type(major) ==
|
||
"string"
|
||
, "Bad argument #2 to `NewLibrary' (string expected)")
|
||
minor = assert(tonumber(string.match(minor, "%d+"))
|
||
, "Minor version must either be a number or contain a number.")
|
||
|
||
local oldminor = self.minors[major]
|
||
if oldminor and oldminor >= minor then return nil end
|
||
self.minors[major], self.libs[major] =
|
||
minor, self.libs[major] or {}
|
||
return self.libs[major], oldminor
|
||
end
|
||
function LibStub:GetLibrary(major, silent)
|
||
if not self.libs[major] and not silent then
|
||
error(("Cannot find a library instance of %q.")
|
||
:format(tostring(major)), 2)
|
||
end
|
||
return self.libs[major], self.minors[major]
|
||
end
|
||
function LibStub:IterateLibraries() return pairs(self.libs) end
|
||
setmetatable(LibStub, { __call = LibStub.GetLibrary })
|
||
end
|
||
-- End of LibStub
|
||
local LibStub = _G.LibStub
|
||
lu.assertNotNil(LibStub, "LibStub not in global?")
|
||
local MAJOR = "LibDeflate"
|
||
CheckCompressAndDecompressString("aaabbbcccddddddcccbbbaaa", "all")
|
||
lu.assertNotNil(package.loaded["LibDeflate"]
|
||
, "LibDeflate is not loaded")
|
||
package.loaded["LibDeflate"] = nil
|
||
-- Not sure if luaconv can recognize code in dofile()
|
||
-- let's just use require
|
||
LibDeflate = require("LibDeflate")
|
||
lu.assertNotNil(package.loaded["LibDeflate"]
|
||
, "LibDeflate is not loaded")
|
||
lu.assertNotNil(LibDeflate, "LibStub does not return LibDeflate")
|
||
lu.assertEquals(LibStub:GetLibrary(MAJOR, true), LibDeflate
|
||
, "Cant find LibDeflate in LibStub.")
|
||
CheckCompressAndDecompressString("aaabbbcccddddddcccbbbaaa", "all")
|
||
------------------------------------------------------
|
||
FullMemoryCollect()
|
||
local memory1 = math.floor(collectgarbage("collect")*1024)
|
||
lu.assertNotNil(package.loaded["LibDeflate"]
|
||
, "LibDeflate is not loaded")
|
||
package.loaded["LibDeflate"] = nil
|
||
-- Not sure if luaconv can recognize code in dofile()
|
||
-- let's just use require
|
||
local LibDeflateTmp = require("LibDeflate")
|
||
lu.assertNotNil(package.loaded["LibDeflate"]
|
||
, "LibDeflate is not loaded")
|
||
lu.assertEquals(LibDeflateTmp, LibDeflate
|
||
, "LibStub unexpectedly recreates the library.")
|
||
lu.assertNotNil(LibDeflate, "LibStub does not return LibDeflate")
|
||
lu.assertEquals(LibStub:GetLibrary(MAJOR, true), LibDeflate
|
||
, "Cant find LibDeflate in LibStub.")
|
||
CheckCompressAndDecompressString("aaabbbcccddddddcccbbbaaa", "all")
|
||
FullMemoryCollect()
|
||
local memory2 = math.floor(collectgarbage("collect")*1024)
|
||
if not _G.jit then
|
||
lu.assertTrue((memory2 - memory1 <= 32)
|
||
, ("Too much Memory leak after LibStub without update: %d")
|
||
:format(memory2-memory1))
|
||
end
|
||
----------------------------------------------------
|
||
LibStub.minors[MAJOR] = -1000
|
||
FullMemoryCollect()
|
||
local memory3 = math.floor(collectgarbage("collect")*1024)
|
||
lu.assertNotNil(package.loaded["LibDeflate"]
|
||
, "LibDeflate is not loaded")
|
||
package.loaded["LibDeflate"] = nil
|
||
-- Not sure if luaconv can recognize code in dofile()
|
||
-- let's just use require
|
||
LibDeflateTmp = require("LibDeflate")
|
||
lu.assertNotNil(package.loaded["LibDeflate"]
|
||
, "LibDeflate is not loaded")
|
||
CheckCompressAndDecompressString("aaabbbcccddddddcccbbbaaa", "all")
|
||
FullMemoryCollect()
|
||
local memory4 = math.floor(collectgarbage("collect")*1024)
|
||
lu.assertEquals(LibDeflateTmp, LibDeflate
|
||
, "LibStub unexpectedly recreates the library.")
|
||
lu.assertTrue(LibStub.minors[MAJOR] > -1000
|
||
, "LibDeflate is not updated.")
|
||
if not _G.jit then
|
||
lu.assertTrue((memory4 - memory3 <= 100)
|
||
, ("Too much Memory leak after LibStub update: %d")
|
||
:format(memory4-memory3))
|
||
end
|
||
end
|
||
|
||
function TestInternals:TestByteTo6bitChar()
|
||
local _byte_to_6bit_char = LibDeflate.internals._byte_to_6bit_char
|
||
lu.assertNotNil(_byte_to_6bit_char)
|
||
lu.assertEquals(GetTableSize(_byte_to_6bit_char), 64)
|
||
for i= 0, 25 do
|
||
lu.assertEquals(_byte_to_6bit_char[i],
|
||
string.char(string.byte("a", 1) + i))
|
||
end
|
||
for i = 26, 51 do
|
||
lu.assertEquals(_byte_to_6bit_char[i],
|
||
string.char(string.byte("A", 1) + i - 26))
|
||
end
|
||
for i = 52, 61 do
|
||
lu.assertEquals(_byte_to_6bit_char[i],
|
||
string.char(string.byte("0", 1) + i - 52))
|
||
end
|
||
lu.assertEquals(_byte_to_6bit_char[62], "(")
|
||
lu.assertEquals(_byte_to_6bit_char[63], ")")
|
||
end
|
||
|
||
function TestInternals:Test6BitToByte()
|
||
local _6bit_to_byte = LibDeflate.internals._6bit_to_byte
|
||
lu.assertNotNil(_6bit_to_byte)
|
||
lu.assertEquals(GetTableSize(_6bit_to_byte), 64)
|
||
for i = string.byte("a", 1), string.byte("z", 1) do
|
||
lu.assertEquals(_6bit_to_byte[i], i - string.byte("a", 1))
|
||
end
|
||
for i = string.byte("A", 1), string.byte("Z", 1) do
|
||
lu.assertEquals(_6bit_to_byte[i], i - string.byte("A", 1) + 26)
|
||
end
|
||
for i = string.byte("0", 1), string.byte("9", 1) do
|
||
lu.assertEquals(_6bit_to_byte[i], i - string.byte("0", 1) + 52)
|
||
end
|
||
lu.assertEquals(_6bit_to_byte[string.byte("(", 1)], 62)
|
||
lu.assertEquals(_6bit_to_byte[string.byte(")", 1)], 63)
|
||
end
|
||
|
||
TestPresetDict = {}
|
||
function TestPresetDict:TestExample()
|
||
local dict_str = [[ilvl::::::::110:::1517:3336:3528:3337]]
|
||
local dictionary = CreateAndCheckDictionary(dict_str)
|
||
local fileData = GetFileData("tests/data/itemStrings.txt")
|
||
CheckDictEffectiveness(fileData, dictionary, dict_str)
|
||
end
|
||
|
||
function TestPresetDict:TestEmptyString()
|
||
for i=1, 16 do
|
||
local dict_str = GetRandomString(i)
|
||
local dictionary = CreateAndCheckDictionary(dict_str)
|
||
CheckDictEffectiveness("", dictionary, dict_str, true)
|
||
end
|
||
end
|
||
|
||
function TestPresetDict:TestCheckDictRandomComplete()
|
||
for _ = 1, 10 do
|
||
local dict_str = GetRandomStringUniqueChars(
|
||
256+math.random(0, 1000))
|
||
CreateAndCheckDictionary(dict_str)
|
||
end
|
||
end
|
||
|
||
-- Test if last two bytes in the dictionary are hashed, with dict size 3.
|
||
function TestPresetDict:TestLength3String1()
|
||
for _ = 1, 10 do
|
||
local dict_str = GetRandomStringUniqueChars(3)
|
||
local dictionary = CreateAndCheckDictionary(dict_str)
|
||
local str = dict_str
|
||
local compress_dict =
|
||
CheckDictEffectiveness(str, dictionary, dict_str)
|
||
lu.assertTrue(compress_dict:len() <= 4)
|
||
end
|
||
end
|
||
|
||
-- Test if last two bytes in the dictionary is hashed, with dict size 2
|
||
function TestPresetDict:TestLength3String2()
|
||
for _ = 1, 10 do
|
||
local str = GetRandomStringUniqueChars(3)
|
||
local dict_str = str:sub(1, 2)
|
||
str = str:sub(3, 3)..str
|
||
local dictionary = CreateAndCheckDictionary(dict_str)
|
||
|
||
local compress_dict =
|
||
CheckDictEffectiveness(str, dictionary, dict_str)
|
||
lu.assertTrue(compress_dict:len() <= 5)
|
||
end
|
||
end
|
||
|
||
-- Test if last two bytes in the dictionary is hashed, with dict size 1
|
||
function TestPresetDict:TestLength3String3()
|
||
for _ = 1, 10 do
|
||
local str = GetRandomStringUniqueChars(3)
|
||
local dict_str = str:sub(1, 1)
|
||
str = str:sub(2, 3)..str
|
||
local dictionary = CreateAndCheckDictionary(dict_str)
|
||
|
||
local compress_dict =
|
||
CheckDictEffectiveness(str, dictionary, dict_str)
|
||
lu.assertTrue(compress_dict:len() <= 6)
|
||
end
|
||
end
|
||
|
||
function TestPresetDict:TestLength257String()
|
||
for _ = 1, 10 do
|
||
local dict_str = GetRandomStringUniqueChars(257)
|
||
local dictionary = CreateAndCheckDictionary(dict_str)
|
||
local str = dict_str
|
||
local compress_dict =
|
||
CheckDictEffectiveness(str, dictionary, dict_str)
|
||
lu.assertTrue(compress_dict:len() <= 5)
|
||
end
|
||
end
|
||
|
||
function TestPresetDict:TestLength258String()
|
||
for _ = 1, 10 do
|
||
local dict_str = GetRandomStringUniqueChars(258)
|
||
local dictionary = CreateAndCheckDictionary(dict_str)
|
||
local str = dict_str
|
||
local compress_dict =
|
||
CheckDictEffectiveness(str, dictionary, dict_str)
|
||
lu.assertTrue(compress_dict:len() <= 4)
|
||
end
|
||
end
|
||
|
||
function TestPresetDict:TestLength259String()
|
||
for _ = 1, 10 do
|
||
local dict_str = GetRandomStringUniqueChars(259)
|
||
local dictionary = CreateAndCheckDictionary(dict_str)
|
||
local str = dict_str
|
||
local compress_dict =
|
||
CheckDictEffectiveness(str, dictionary, dict_str)
|
||
lu.assertTrue(compress_dict:len() <= 5)
|
||
end
|
||
end
|
||
|
||
function TestPresetDict:TestIsEqualAdler32()
|
||
local IsEqualAdler32 = LibDeflate.internals.IsEqualAdler32
|
||
lu.assertTrue(IsEqualAdler32(4072834167, -222133129))
|
||
for _ = 1, 30 do
|
||
local rand = math.random(0, 1000)
|
||
lu.assertTrue(IsEqualAdler32(rand, rand))
|
||
lu.assertTrue(IsEqualAdler32(rand+256*256*256*256, rand))
|
||
lu.assertTrue(IsEqualAdler32(rand, rand+256*256*256*256))
|
||
lu.assertTrue(IsEqualAdler32(rand-256*256*256*256, rand))
|
||
lu.assertTrue(IsEqualAdler32(rand, rand-256*256*256*256))
|
||
lu.assertTrue(IsEqualAdler32(rand+256*256*256*256
|
||
, rand+256*256*256*256))
|
||
end
|
||
end
|
||
|
||
TestEncode = {}
|
||
function TestEncode:TestBasic()
|
||
CheckEncodeAndDecode("")
|
||
for i=0, 255 do
|
||
CheckEncodeAndDecode(string_char(i))
|
||
end
|
||
|
||
end
|
||
|
||
function TestEncode:TestRandom()
|
||
for _ = 0, 200 do
|
||
local str = GetRandomStringUniqueChars(math.random(256, 1000))
|
||
CheckEncodeAndDecode(str)
|
||
end
|
||
end
|
||
|
||
-- Bug in LibCompress:GetEncodeTable()
|
||
-- version LibCompress Revision 81
|
||
-- Date: 2018-02-25 06:31:34 +0000 (Sun, 25 Feb 2018)
|
||
function TestEncode:TestLibCompressEncodeBug()
|
||
local reservedChars =
|
||
"\132\109\114\143\11\32\153\92\230\66\131\127\87\106\89\142\55\228\56"
|
||
.."\158\151\53\48\13\71\9\37\208\101\42\217\76\19\250\125\214\146\14"
|
||
.."\215\204\249\223\165\45\222\120\161\65\28\144\196\12\43\116\242\179"
|
||
.."\194\1\253\147\121\99\3\107\96\67\27\44\100\148\130\221\138\85\129"
|
||
.."\166\185\246\239\50\218\94\157\90\81\134\80\175\186\79\122\93\190"
|
||
.."\150\154\183\91\152\70\234\169\126\108\251\6\2\22\95\233\180\105"
|
||
.."\119\38\229\171\29\192\219\21\241\74\207\159\117\247\72\237\110"
|
||
.."\78\118"
|
||
local escapedChars = "\145\54"
|
||
for _ = 1, 10 do
|
||
local str = GetRandomStringUniqueChars(1000)
|
||
CheckEncodeAndDecode(str, reservedChars, escapedChars, "")
|
||
end
|
||
end
|
||
function TestEncode:TestRandomComplete1()
|
||
for _ = 0, 30 do
|
||
local tmp = GetRandomStringUniqueChars(256)
|
||
local reserved = tmp:sub(1, 10)
|
||
local escaped = tmp:sub(11, 11)
|
||
local mapped = tmp:sub(12, 12+math.random(0, 9))
|
||
local str = GetRandomStringUniqueChars(math.random(256, 1000))
|
||
CheckEncodeAndDecode(str, reserved, escaped, mapped)
|
||
end
|
||
end
|
||
|
||
function TestEncode:TestRandomComplete2()
|
||
for _ = 0, 30 do
|
||
local tmp = GetRandomStringUniqueChars(256)
|
||
local reserved = tmp:sub(1, 10)
|
||
local escaped = tmp:sub(11, 11)
|
||
local str = GetRandomStringUniqueChars(math.random(256, 1000))
|
||
CheckEncodeAndDecode(str, reserved, escaped, "")
|
||
end
|
||
end
|
||
|
||
function TestEncode:TestRandomComplete3()
|
||
for _ = 0, 30 do
|
||
local tmp = GetRandomStringUniqueChars(256)
|
||
local reserved = tmp:sub(1, 130) -- Over half chractrs escaped
|
||
local escaped = tmp:sub(131, 132) -- Two escape char needed.
|
||
local mapped = tmp:sub(133, 133+math.random(0, 20))
|
||
local str = GetRandomStringUniqueChars(math.random(256, 1000))
|
||
CheckEncodeAndDecode(str, reserved, escaped, mapped)
|
||
end
|
||
end
|
||
|
||
function TestEncode:TestRandomComplete4()
|
||
for _ = 0, 30 do
|
||
local tmp = GetRandomStringUniqueChars(256)
|
||
local reserved = tmp:sub(1, 130) -- Over half chractrs escaped
|
||
local escaped = tmp:sub(131, 132) -- Two escape char needed.
|
||
local str = GetRandomStringUniqueChars(math.random(256, 1000))
|
||
CheckEncodeAndDecode(str, reserved, escaped, "")
|
||
end
|
||
end
|
||
|
||
local function CheckEncodeForPrint(str)
|
||
AssertLongStringEqual(LibDeflate:DecodeForPrint(LibDeflate
|
||
:EncodeForPrint(str))
|
||
, str)
|
||
-- test prefixed and trailig control characters or space.
|
||
for _, byte in pairs({0, 1, 9, 10, 11, 12, 13, 31, 32, 127}) do
|
||
local char = string.char(byte)
|
||
AssertLongStringEqual(LibDeflate:DecodeForPrint(LibDeflate
|
||
:EncodeForPrint(str)..char)
|
||
, str)
|
||
AssertLongStringEqual(LibDeflate:DecodeForPrint(LibDeflate
|
||
:EncodeForPrint(str)..char..char)
|
||
, str)
|
||
AssertLongStringEqual(LibDeflate:DecodeForPrint(LibDeflate
|
||
:EncodeForPrint(str)..char..char..char)
|
||
, str)
|
||
AssertLongStringEqual(LibDeflate:DecodeForPrint(char..LibDeflate
|
||
:EncodeForPrint(str))
|
||
, str)
|
||
AssertLongStringEqual(LibDeflate:DecodeForPrint(char..char..
|
||
LibDeflate:EncodeForPrint(str))
|
||
, str)
|
||
end
|
||
|
||
end
|
||
function TestEncode:TestEncodeForPrint()
|
||
CheckEncodeForPrint("")
|
||
for _ = 1, 100 do
|
||
CheckEncodeForPrint(GetRandomStringUniqueChars(
|
||
math.random(1, 10)))
|
||
end
|
||
for i = 0, 255 do
|
||
CheckEncodeForPrint(string.char(i))
|
||
end
|
||
for _ = 1, 400 do
|
||
CheckEncodeForPrint(GetRandomStringUniqueChars(
|
||
math.random(100, 1000)))
|
||
end
|
||
local encode_6bit_weakaura =
|
||
GetFileData("tests/data/reference/encode_6bit_weakaura.txt")
|
||
local decode_6bit_weakaura =
|
||
GetFileData("tests/data/reference/decode_6bit_weakaura.txt")
|
||
AssertLongStringEqual(LibDeflate:EncodeForPrint(decode_6bit_weakaura)
|
||
, encode_6bit_weakaura)
|
||
end
|
||
function TestEncode:TestDecodeForPrintErrors()
|
||
for i = 0, 255 do
|
||
if string.char(i):find("[%c ]") then
|
||
lu.assertEquals(LibDeflate:DecodeForPrint(string.char(i)), "")
|
||
else
|
||
lu.assertNil(LibDeflate:DecodeForPrint(string.char(i)))
|
||
end
|
||
end
|
||
for i = 0, 255 do
|
||
if not LibDeflate.internals._6bit_to_byte[i] then
|
||
lu.assertNil(LibDeflate:DecodeForPrint(("1"
|
||
..string.char(i)):rep(100).."1"))
|
||
end
|
||
end
|
||
-- Test multiple string lengths.
|
||
for i = 0, 255 do
|
||
for reps = 1, 16 do
|
||
if not LibDeflate.internals._6bit_to_byte[i] then
|
||
lu.assertNil(LibDeflate:DecodeForPrint("2"..(
|
||
string.char(i)):rep(reps).."3"))
|
||
end
|
||
end
|
||
end
|
||
end
|
||
|
||
function TestEncode:TestDecodeError()
|
||
for _ = 0, 100 do
|
||
local tmp = GetRandomStringUniqueChars(256)
|
||
local reserved = tmp:sub(1, 10)
|
||
local escaped = tmp:sub(11, 11)
|
||
local str = GetRandomStringUniqueChars(math.random(256, 1000))
|
||
local t = LibDeflate:CreateCodec(reserved, escaped, "")
|
||
local encode_funcs = {
|
||
{t.Encode, t},
|
||
{LibDeflate.EncodeForWoWAddonChannel, LibDeflate},
|
||
{LibDeflate.EncodeForWoWChatChannel, LibDeflate},
|
||
}
|
||
local decode_funcs = {
|
||
{t.Decode, t},
|
||
{LibDeflate.DecodeForWoWAddonChannel, LibDeflate},
|
||
{LibDeflate.DecodeForWoWChatChannel, LibDeflate},
|
||
}
|
||
local reserved_chars = {
|
||
reserved,
|
||
"\000",
|
||
"sS\000\010\013\124%",
|
||
}
|
||
for j, func in ipairs(encode_funcs) do
|
||
local encoded = func[1](func[2], str)
|
||
reserved = reserved_chars[j]
|
||
local random = math.random(1, #reserved)
|
||
local reserved_char = reserved:sub(random, random)
|
||
random = math.random(1, #encoded)
|
||
encoded = encoded:sub(1, random-1)
|
||
..reserved_char..encoded:sub(random, #encoded)
|
||
lu.assertNil(decode_funcs[j][1](decode_funcs[j][2], encoded))
|
||
end
|
||
end
|
||
end
|
||
function TestEncode:TestFailCreateCodec()
|
||
local t, err
|
||
t, err = LibDeflate:CreateCodec("1", "", "2")
|
||
lu.assertNil(t)
|
||
lu.assertEquals(err, "No escape characters supplied.")
|
||
t, err = LibDeflate:CreateCodec("1", "a", "23")
|
||
lu.assertNil(t)
|
||
lu.assertEquals(err, "The number of reserved characters must be"
|
||
.." at least as many as the number of mapped chars.")
|
||
t, err = LibDeflate:CreateCodec("", "1", "")
|
||
lu.assertNil(t)
|
||
lu.assertEquals(err, "No characters to encode.")
|
||
t, err = LibDeflate:CreateCodec("1", "2", "1")
|
||
lu.assertNil(t)
|
||
lu.assertEquals(err, "There must be no duplicate characters in the"
|
||
.." concatenation of reserved_chars, escape_chars and"
|
||
.." map_chars.")
|
||
t, err = LibDeflate:CreateCodec("2", "1", "1")
|
||
lu.assertNil(t)
|
||
lu.assertEquals(err, "There must be no duplicate characters in the"
|
||
.." concatenation of reserved_chars, escape_chars and"
|
||
.." map_chars.")
|
||
t, err = LibDeflate:CreateCodec("1", "1", "2")
|
||
lu.assertNil(t)
|
||
lu.assertEquals(err, "There must be no duplicate characters in the"
|
||
.." concatenation of reserved_chars, escape_chars and"
|
||
.." map_chars.")
|
||
local r = {}
|
||
for i = 128, 255 do
|
||
r[#r+1] = string.char(i)
|
||
end
|
||
local reserved_chars = "sS\000\010\013\124%"..table_concat(r)
|
||
t, err = LibDeflate:CreateCodec(reserved_chars, "\029"
|
||
, "\015\020")
|
||
lu.assertNil(t)
|
||
lu.assertEquals(err, "Out of escape characters.")
|
||
t, err = LibDeflate:CreateCodec(reserved_chars, "\029\031"
|
||
, "\015\020")
|
||
lu.assertIsTable(t)
|
||
lu.assertNil(err)
|
||
end
|
||
|
||
TestCompressStrategy = {}
|
||
function TestCompressStrategy:TestHtml_x_4Fixed()
|
||
CheckCompressAndDecompressFile("tests/data/3rdparty/html_x_4"
|
||
, {0,1,3,4}, "fixed")
|
||
end
|
||
function TestCompressStrategy:TestHtml_x_4HuffmanOnly()
|
||
CheckCompressAndDecompressFile("tests/data/3rdparty/html_x_4"
|
||
, {0,1,3,4}, "huffman_only")
|
||
end
|
||
function TestCompressStrategy:TestHtml_x_4Dynamic()
|
||
CheckCompressAndDecompressFile("tests/data/3rdparty/html_x_4"
|
||
, {0,1,2,3,4}, "dynamic")
|
||
end
|
||
function TestCompressStrategy:TestAsyoulikFixed()
|
||
CheckCompressAndDecompressFile("tests/data/3rdparty/asyoulik.txt"
|
||
, {0,1,3,4}, "fixed")
|
||
end
|
||
function TestCompressStrategy:TestAsyoulikHuffmanOnly()
|
||
CheckCompressAndDecompressFile("tests/data/3rdparty/asyoulik.txt"
|
||
, {0,1,3,4}, "huffman_only")
|
||
end
|
||
function TestCompressStrategy:TestAsyoulikDynamic()
|
||
CheckCompressAndDecompressFile("tests/data/3rdparty/asyoulik.txt"
|
||
, {0,1,3,4}, "dynamic")
|
||
end
|
||
|
||
-- Some hard coded compresses length here.
|
||
-- Modify if algorithm changes.
|
||
-- (I don't think it will happen in the future though)
|
||
function TestCompressStrategy:TestIsFixedStrategyInEffect()
|
||
local str = ""
|
||
for i=0, 255 do
|
||
str = str..string.char(i)
|
||
end
|
||
for i=255, 0, -1 do
|
||
str = str..string.char(i)
|
||
end
|
||
|
||
lu.assertEquals(
|
||
LibDeflate:CompressDeflate(str):len(), 517)
|
||
lu.assertEquals(
|
||
GetFirstBlockType(
|
||
LibDeflate:CompressDeflate(str, {strategy = "fixed"}), false)
|
||
, 1)
|
||
lu.assertEquals(
|
||
LibDeflate:CompressDeflate(str, {strategy = "fixed"}):len()
|
||
, 542)
|
||
lu.assertEquals(
|
||
GetFirstBlockType(
|
||
LibDeflate:CompressZlib(str, {strategy = "fixed"}, true))
|
||
, 1)
|
||
lu.assertEquals(
|
||
LibDeflate:CompressZlib(str, {strategy = "fixed"}):len()
|
||
, 548)
|
||
end
|
||
function TestCompressStrategy:TestIsHuffmanOnlyStrategyInEffect()
|
||
local str = ("a"):rep(1000)
|
||
lu.assertEquals(
|
||
LibDeflate:CompressDeflate(str):len()
|
||
, 10)
|
||
lu.assertEquals(
|
||
LibDeflate:CompressDeflate(str, {strategy = "huffman_only"}):len()
|
||
, 138)
|
||
lu.assertEquals(
|
||
LibDeflate:CompressZlib(str):len()
|
||
,16)
|
||
lu.assertEquals(
|
||
LibDeflate:CompressZlib(str, {strategy = "huffman_only"}):len()
|
||
, 144)
|
||
end
|
||
function TestCompressStrategy:TestIsDynamicStrategyInEffect()
|
||
local str = ""
|
||
for i=0, 255 do
|
||
str = str..string.char(i)
|
||
end
|
||
for i=255, 0, -1 do
|
||
str = str..string.char(i)
|
||
end
|
||
|
||
lu.assertEquals(
|
||
LibDeflate:CompressDeflate(str):len(), 517)
|
||
lu.assertEquals(
|
||
GetFirstBlockType(
|
||
LibDeflate:CompressDeflate(str, {strategy = "dynamic"}), false)
|
||
, 2)
|
||
lu.assertEquals(
|
||
LibDeflate:CompressDeflate(str, {strategy = "dynamic"}):len()
|
||
, 536)
|
||
lu.assertEquals(
|
||
GetFirstBlockType(
|
||
LibDeflate:CompressZlib(str, {strategy = "dynamic"}, true))
|
||
, 2)
|
||
lu.assertEquals(
|
||
LibDeflate:CompressZlib(str, {strategy = "dynamic"}):len()
|
||
, 542)
|
||
end
|
||
|
||
TestErrors = {}
|
||
local function TestCorruptedDictionary(msg_prefix, func, dict)
|
||
-- Test corrupted dictionary
|
||
local backup = DeepCopy(dict)
|
||
for i = 1, 100 do
|
||
if i == 1 then
|
||
dict = nil
|
||
elseif i == 2 then
|
||
dict.string_table = 1
|
||
elseif i == 3 then
|
||
dict.string_table = nil
|
||
elseif i == 4 then
|
||
dict.strlen = {}
|
||
elseif i == 5 then
|
||
dict.strlen = 32769
|
||
elseif i == 6 then
|
||
dict.string_table[#dict.string_table+1] = 97
|
||
elseif i == 7 then
|
||
dict.hash_tables = 1
|
||
elseif i == 8 then
|
||
dict.hash_tables = nil
|
||
elseif i == 9 then
|
||
dict.adler32 = nil
|
||
else
|
||
break
|
||
end
|
||
if i == 1 then
|
||
lu.assertErrorMsgContains(
|
||
msg_prefix
|
||
.."'dictionary' - table expected got 'nil'."
|
||
, function() return func(dict) end)
|
||
else
|
||
lu.assertErrorMsgContains(
|
||
msg_prefix
|
||
.."'dictionary' - corrupted dictionary."
|
||
, function() return func(dict) end)
|
||
end
|
||
dict = backup
|
||
backup = DeepCopy(dict)
|
||
func(dict)
|
||
end
|
||
end
|
||
|
||
-- arguments to "func": str, dictionary, configs
|
||
local function TestInvalidCompressDecompressArgs(msg_prefix, func
|
||
, check_dictionary, check_configs)
|
||
lu.assertErrorMsgContains(
|
||
msg_prefix
|
||
.."'str' - string expected got 'nil'."
|
||
, function() return func() end)
|
||
lu.assertErrorMsgContains(
|
||
msg_prefix
|
||
.."'str' - string expected got 'table'."
|
||
, function() return func({}) end)
|
||
local str = GetRandomString(0, 5)
|
||
local dict = CreateDictionaryWithoutVerify(
|
||
GetRandomString(math.random(1, 32768)))
|
||
if check_dictionary then
|
||
TestCorruptedDictionary(msg_prefix,
|
||
function(dict2) return func(str, dict2, {}) end, dict)
|
||
else
|
||
func(str, nil, {})
|
||
end
|
||
if check_configs then
|
||
func(str, dict, nil)
|
||
func(str, dict, {})
|
||
lu.assertErrorMsgContains(
|
||
(
|
||
msg_prefix
|
||
.."'configs' - nil or table expected got '%s'.")
|
||
:format(type(1))
|
||
, function() return func(str, dict, 1) end)
|
||
for i = 0, 9 do
|
||
func(str, dict, {level = i})
|
||
end
|
||
local strategies = {"fixed", "huffman_only", "dynamic"}
|
||
for _, strategy in ipairs(strategies) do
|
||
func(str, dict, {strategy = strategy})
|
||
func(str, dict, {level = math.random(0, 9) -- NOTE: here
|
||
, strategy = strategy})
|
||
end
|
||
lu.assertErrorMsgContains(
|
||
msg_prefix
|
||
.."'configs' - unsupported table key in the configs:"
|
||
.." 'not_a_key'."
|
||
, function() return func(str, dict, {not_a_key=1}) end)
|
||
lu.assertErrorMsgContains(
|
||
msg_prefix
|
||
.."'configs' - unsupported 'level': 10."
|
||
, function() return func(str, dict, {level=10}) end)
|
||
lu.assertErrorMsgContains(
|
||
msg_prefix
|
||
.."'configs' - unsupported 'strategy': 'dne'."
|
||
, function() return func(str, dict, {strategy="dne"}) end)
|
||
else
|
||
func(str, dict, 1)
|
||
end
|
||
end
|
||
|
||
function TestErrors:TestAdler32()
|
||
lu.assertErrorMsgContains("Usage: LibDeflate:Adler32(str): 'str'"
|
||
.." - string expected got 'nil'."
|
||
, function() LibDeflate:Adler32() end)
|
||
lu.assertErrorMsgContains("Usage: LibDeflate:Adler32(str): 'str'"
|
||
.." - string expected got 'table'."
|
||
, function() LibDeflate:Adler32({}) end)
|
||
LibDeflate:Adler32("") -- No error
|
||
end
|
||
function TestErrors:TestCreateDictionary()
|
||
LibDeflate:CreateDictionary("1", 1, 0x00320032)
|
||
lu.assertErrorMsgContains(
|
||
"Usage: LibDeflate:CreateDictionary(str, strlen, adler32):"
|
||
.." 'str' - string expected got 'nil'."
|
||
, function() LibDeflate:CreateDictionary(nil, 1, 0x00320032) end)
|
||
lu.assertErrorMsgContains(
|
||
"Usage: LibDeflate:CreateDictionary(str, strlen, adler32):"
|
||
.." 'str' - string expected got 'table'."
|
||
, function() LibDeflate:CreateDictionary({}, 1, 0x00320032) end)
|
||
lu.assertErrorMsgContains(
|
||
"Usage: LibDeflate:CreateDictionary(str, strlen, adler32):"
|
||
.." 'strlen' - number expected got 'nil'."
|
||
, function() LibDeflate:CreateDictionary("1", nil, 0x00320032) end)
|
||
lu.assertErrorMsgContains(
|
||
"Usage: LibDeflate:CreateDictionary(str, strlen, adler32):"
|
||
.." 'adler32' - number expected got 'nil'."
|
||
, function() LibDeflate:CreateDictionary("1", 1, nil) end)
|
||
lu.assertEquals(LibDeflate:Adler32(""), 1)
|
||
lu.assertErrorMsgContains(
|
||
"Usage: LibDeflate:CreateDictionary(str, strlen, adler32):"
|
||
.." 'str' - Empty string is not allowed."
|
||
, function() LibDeflate:CreateDictionary("", 0, 1) end)
|
||
lu.assertErrorMsgContains(
|
||
"Usage: LibDeflate:CreateDictionary(str, strlen, adler32):"
|
||
.." 'str' - string longer than 32768 bytes is not allowed."
|
||
.." Got 32769 bytes."
|
||
, function() LibDeflate:CreateDictionary(("\000"):rep(32769)
|
||
, 32769, LibDeflate:Adler32(("\000"):rep(32769))) end)
|
||
-- ^ Dont calculate Adler32 in run-time in real problem plz.
|
||
LibDeflate:CreateDictionary(("\000"):rep(32768)
|
||
, 32768, LibDeflate:Adler32(("\000"):rep(32768)))
|
||
lu.assertErrorMsgContains(
|
||
"Usage: LibDeflate:CreateDictionary(str, strlen, adler32):"
|
||
.." 'strlen' does not match the actual length of 'str'."
|
||
.." 'strlen': 32767, '#str': 32768 ."
|
||
.." Please check if 'str' is modified unintentionally."
|
||
, function() LibDeflate:CreateDictionary(("\000"):rep(32768)
|
||
, 32767, LibDeflate:Adler32(("\000"):rep(32768))) end)
|
||
-- ^ Dont calculate Adler32 in run-time in real problem plz.
|
||
lu.assertErrorMsgContains(
|
||
("Usage: LibDeflate:CreateDictionary(str, strlen, adler32):"
|
||
.." 'adler32' does not match the actual adler32 of 'str'."
|
||
.." 'adler32': %u, 'Adler32(str)': %u ."
|
||
.." Please check if 'str' is modified unintentionally.")
|
||
:format(LibDeflate:Adler32(("\000"):rep(32768))+1
|
||
, LibDeflate:Adler32(("\000"):rep(32768)))
|
||
, function() LibDeflate:CreateDictionary(("\000"):rep(32768)
|
||
, 32768, LibDeflate:Adler32(("\000"):rep(32768))+1) end)
|
||
end
|
||
function TestErrors:TestCompressDeflate()
|
||
TestInvalidCompressDecompressArgs(
|
||
"Usage: LibDeflate:CompressDeflate(str, configs): "
|
||
, function(str, _, configs)
|
||
return LibDeflate:CompressDeflate(str, configs) end
|
||
, false, true)
|
||
end
|
||
function TestErrors:TestCompressDeflateWithDict()
|
||
TestInvalidCompressDecompressArgs(
|
||
"Usage: LibDeflate:CompressDeflateWithDict"
|
||
.."(str, dictionary, configs): "
|
||
, function(str, dictionary, configs)
|
||
return LibDeflate:
|
||
CompressDeflateWithDict(str, dictionary, configs) end
|
||
, true, true)
|
||
end
|
||
function TestErrors:TestCompressZlib()
|
||
TestInvalidCompressDecompressArgs(
|
||
"Usage: LibDeflate:CompressZlib(str, configs): "
|
||
, function(str, _, configs)
|
||
return LibDeflate:CompressZlib(str, configs) end
|
||
, false, true)
|
||
end
|
||
function TestErrors:TestCompressZlibWithDict()
|
||
TestInvalidCompressDecompressArgs(
|
||
"Usage: LibDeflate:CompressZlibWithDict"
|
||
.."(str, dictionary, configs): "
|
||
, function(str, dictionary, configs)
|
||
return LibDeflate:
|
||
CompressZlibWithDict(str, dictionary, configs) end
|
||
, true, true)
|
||
end
|
||
function TestErrors:TestDecompressDeflate()
|
||
TestInvalidCompressDecompressArgs(
|
||
"Usage: LibDeflate:DecompressDeflate(str): "
|
||
, function(str, _, _)
|
||
return LibDeflate:DecompressDeflate(str) end
|
||
, false, false)
|
||
end
|
||
function TestErrors:TestDecompressZlib()
|
||
TestInvalidCompressDecompressArgs(
|
||
"Usage: LibDeflate:DecompressZlib(str): "
|
||
, function(str, _, _)
|
||
return LibDeflate:DecompressZlib(str) end
|
||
, false, false)
|
||
end
|
||
function TestErrors:TestDecompressDeflateWithDict()
|
||
TestInvalidCompressDecompressArgs(
|
||
"Usage: LibDeflate:DecompressDeflateWithDict(str, dictionary): "
|
||
, function(str, dict, _)
|
||
return LibDeflate:DecompressDeflateWithDict(str, dict) end
|
||
, true, false)
|
||
end
|
||
function TestErrors:TestDecompressZlibWithDict()
|
||
TestInvalidCompressDecompressArgs(
|
||
"Usage: LibDeflate:DecompressZlibWithDict(str, dictionary): "
|
||
, function(str, dict, _)
|
||
return LibDeflate:DecompressZlibWithDict(str, dict) end
|
||
, true, false)
|
||
end
|
||
function TestErrors:TestCreateCodec()
|
||
lu.assertErrorMsgContains(
|
||
"Usage: LibDeflate:CreateCodec(reserved_chars,"
|
||
.." escape_chars, map_chars):"
|
||
.." All arguments must be string."
|
||
, function()
|
||
LibDeflate:CreateCodec(nil, "", "")
|
||
end)
|
||
lu.assertErrorMsgContains(
|
||
"Usage: LibDeflate:CreateCodec(reserved_chars,"
|
||
.." escape_chars, map_chars):"
|
||
.." All arguments must be string."
|
||
, function()
|
||
LibDeflate:CreateCodec("", nil, "")
|
||
end)
|
||
lu.assertErrorMsgContains(
|
||
"Usage: LibDeflate:CreateCodec(reserved_chars,"
|
||
.." escape_chars, map_chars):"
|
||
.." All arguments must be string."
|
||
, function()
|
||
LibDeflate:CreateCodec("", "", nil)
|
||
end)
|
||
local t, err = LibDeflate:CreateCodec("1", "2", "")
|
||
lu.assertNil(err)
|
||
end
|
||
function TestErrors:TestEncodeDecode()
|
||
local codec = LibDeflate:CreateCodec("\000", "\001", "")
|
||
lu.assertErrorMsgContains(
|
||
"Usage: codec:Encode(str):"
|
||
.." 'str' - string expected got 'nil'."
|
||
, function() codec:Encode() end)
|
||
lu.assertErrorMsgContains(
|
||
"Usage: codec:Decode(str):"
|
||
.." 'str' - string expected got 'nil'."
|
||
, function() codec:Decode() end)
|
||
lu.assertErrorMsgContains(
|
||
"Usage: LibDeflate:EncodeForWoWAddonChannel(str):"
|
||
.." 'str' - string expected got 'nil'."
|
||
, function() LibDeflate:EncodeForWoWAddonChannel() end)
|
||
lu.assertErrorMsgContains(
|
||
"Usage: LibDeflate:DecodeForWoWAddonChannel(str):"
|
||
.." 'str' - string expected got 'nil'."
|
||
, function() LibDeflate:DecodeForWoWAddonChannel() end)
|
||
lu.assertErrorMsgContains(
|
||
"Usage: LibDeflate:EncodeForWoWChatChannel(str):"
|
||
.." 'str' - string expected got 'nil'."
|
||
, function() LibDeflate:EncodeForWoWChatChannel() end)
|
||
lu.assertErrorMsgContains(
|
||
"Usage: LibDeflate:DecodeForWoWChatChannel(str):"
|
||
.." 'str' - string expected got 'nil'."
|
||
, function() LibDeflate:DecodeForWoWChatChannel() end)
|
||
lu.assertErrorMsgContains(
|
||
"Usage: LibDeflate:EncodeForPrint(str):"
|
||
.." 'str' - string expected got 'nil'."
|
||
, function() LibDeflate:EncodeForPrint() end)
|
||
lu.assertErrorMsgContains(
|
||
"Usage: LibDeflate:DecodeForPrint(str):"
|
||
.." 'str' - string expected got 'nil'."
|
||
, function() LibDeflate:DecodeForPrint() end)
|
||
end
|
||
|
||
|
||
|
||
local lua_program = "lua"
|
||
local function RunCommandline(args, stdin)
|
||
local input_filename = "tests/test.stdin"
|
||
if stdin then
|
||
WriteToFile(input_filename, stdin)
|
||
else
|
||
WriteToFile(input_filename, "")
|
||
end
|
||
local stdout_filename = "tests/test.stderr"
|
||
local stderr_filename = "tests/test.stdout"
|
||
local libdeflate_file = "./LibDeflate.lua"
|
||
if os.getenv("OS") and os.getenv("OS"):find("Windows") then
|
||
libdeflate_file = "LibDeflate.lua"
|
||
end
|
||
local status, _, ret = os.execute(lua_program.." "..libdeflate_file.." "
|
||
..args.." >"..input_filename
|
||
.. "> "..stdout_filename.." 2> "..stderr_filename)
|
||
|
||
local returned_status
|
||
if type(status) == "number" then -- lua 5.1
|
||
returned_status = status
|
||
else -- Lua 5.2/5.3
|
||
returned_status = ret
|
||
if not status and ret == 0 then
|
||
returned_status = -1
|
||
-- Lua bug on Windows when the returned value is -1, ret is 0
|
||
end
|
||
end
|
||
|
||
local stdout = GetFileData(stdout_filename)
|
||
local stderr = GetFileData(stderr_filename)
|
||
return returned_status, stdout, stderr
|
||
end
|
||
|
||
TestCommandLine = {}
|
||
function TestCommandLine:TestHelp()
|
||
local returned_status, stdout, stderr = RunCommandline("-h")
|
||
lu.assertEquals(returned_status, 0)
|
||
|
||
local str = LibDeflate._COPYRIGHT
|
||
.."\nUsage: lua LibDeflate.lua [OPTION] [INPUT] [OUTPUT]\n"
|
||
.." -0 store only. no compression.\n"
|
||
.." -1 fastest compression.\n"
|
||
.." -9 slowest and best compression.\n"
|
||
.." -d do decompression instead of compression.\n"
|
||
.." --dict <filename> specify the file that contains"
|
||
.." the entire preset dictionary.\n"
|
||
.." -h give this help.\n"
|
||
.." --strategy <fixed/huffman_only/dynamic>"
|
||
.." specify a special compression strategy.\n"
|
||
.." -v print the version and copyright info.\n"
|
||
.." --zlib use zlib format instead of raw deflate.\n"
|
||
|
||
if stdout:find(str, 1, true) then
|
||
lu.assertStrContains(stdout, str)
|
||
else
|
||
str = str:gsub("\n", "\r\n")
|
||
lu.assertStrContains(stdout, str)
|
||
end
|
||
lu.assertEquals(stderr, "")
|
||
end
|
||
|
||
function TestCommandLine:TestCopyright()
|
||
local returned_status, stdout, stderr = RunCommandline("-v")
|
||
lu.assertEquals(returned_status, 0)
|
||
|
||
local str = LibDeflate._COPYRIGHT
|
||
|
||
if stdout:find(str, 1, true) then
|
||
lu.assertStrContains(stdout, str)
|
||
else
|
||
str = str:gsub("\n", "\r\n")
|
||
lu.assertStrContains(stdout, str)
|
||
end
|
||
lu.assertEquals(stderr, "")
|
||
end
|
||
|
||
function TestCommandLine:TestErrors()
|
||
local returned_status, stdout, stderr
|
||
|
||
returned_status, stdout, stderr =
|
||
RunCommandline("-invalid")
|
||
lu.assertNotEquals(returned_status, 0)
|
||
lu.assertEquals(stdout, "")
|
||
lu.assertStrContains(stderr, ("LibDeflate: Invalid argument: %s")
|
||
:format("-invalid"))
|
||
|
||
returned_status, stdout, stderr =
|
||
RunCommandline("tests/data/reference/item_strings.txt --dict")
|
||
lu.assertNotEquals(returned_status, 0)
|
||
lu.assertEquals(stdout, "")
|
||
lu.assertStrContains(stderr, "You must speicify the dict filename")
|
||
|
||
returned_status, stdout, stderr =
|
||
RunCommandline("tests/data/reference/item_strings.txt --dict DNE")
|
||
lu.assertNotEquals(returned_status, 0)
|
||
lu.assertEquals(stdout, "")
|
||
lu.assertStrContains(stderr,
|
||
("LibDeflate: Cannot read the dictionary file '%s':")
|
||
:format("DNE"))
|
||
|
||
returned_status, stdout, stderr =
|
||
RunCommandline("DNE DNE")
|
||
lu.assertNotEquals(returned_status, 0)
|
||
lu.assertEquals(stdout, "")
|
||
lu.assertStrContains(stderr, "LibDeflate: Cannot read the file 'DNE':")
|
||
|
||
returned_status, stdout, stderr =
|
||
RunCommandline("tests/data/reference/item_strings.txt ..")
|
||
lu.assertNotEquals(returned_status, 0)
|
||
lu.assertEquals(stdout, "")
|
||
lu.assertStrContains(stderr, "LibDeflate: Cannot write the file '..':")
|
||
|
||
returned_status, stdout, stderr =
|
||
RunCommandline("tests/data/reference/item_strings.txt")
|
||
lu.assertNotEquals(returned_status, 0)
|
||
lu.assertEquals(stdout, "")
|
||
lu.assertStrContains(stderr, "LibDeflate:"
|
||
.." You must specify both input and output files.")
|
||
|
||
returned_status, stdout, stderr =
|
||
RunCommandline("-d tests/data/reference/item_strings.txt"
|
||
.." tests/test_commandline.tmp")
|
||
lu.assertNotEquals(returned_status, 0)
|
||
lu.assertEquals(stdout, "")
|
||
lu.assertStrContains(stderr, "LibDeflate: Decompress fails.")
|
||
end
|
||
|
||
function TestCommandLine:TestCompressAndDecompress()
|
||
local funcs = {"CompressDeflate", "CompressDeflateWithDict"
|
||
, "CompressZlib", "CompressZlibWithDict"
|
||
, "DecompressDeflate", "DecompressDeflateWithDict"
|
||
, "DecompressZlib", "DecompressZlibWithDict"}
|
||
local args = {"", "--dict tests/dictionary32768.txt"
|
||
, "--zlib", "--zlib --dict tests/dictionary32768.txt"
|
||
, "-d", "-d --dict tests/dictionary32768.txt"
|
||
, "-d --zlib", "-d --zlib --dict tests/dictionary32768.txt"}
|
||
local inputs = {"tests/data/reference/item_strings.txt"
|
||
,"tests/data/reference/item_strings.txt"
|
||
, "tests/data/reference/item_strings.txt"
|
||
, "tests/data/reference/item_strings.txt"
|
||
, "tests/data/reference/item_strings_deflate.txt"
|
||
, "tests/data/reference/item_strings_deflate_with_dict.txt"
|
||
, "tests/data/reference/item_strings_zlib.txt"
|
||
, "tests/data/reference/item_strings_zlib_with_dict.txt"}
|
||
local addition_args = {
|
||
"-0 "
|
||
, "-1 --strategy huffman_only"
|
||
, "-5 --strategy dynamic"
|
||
, "-9 --strategy fixed"
|
||
, ""
|
||
}
|
||
local addition_configs = {
|
||
{level = 0}
|
||
, {level = 1, strategy = "huffman_only"}
|
||
, {level = 5, strategy = "dynamic"}
|
||
, {level = 9, strategy = "fixed"}
|
||
, nil
|
||
}
|
||
for k, func_name in ipairs(funcs) do
|
||
local configs
|
||
local addition_arg
|
||
for i = 1, #addition_args do
|
||
configs = addition_configs[i]
|
||
addition_arg = addition_args[i]
|
||
if not configs then
|
||
print(("Testing TestCommandline: %s")
|
||
:format(func_name))
|
||
else
|
||
print(
|
||
("Testing TestCommandline: %s level: %s strategy: %s")
|
||
:format(func_name, tostring(configs.level)
|
||
, tostring(configs.strategy)))
|
||
end
|
||
local returned_status, stdout, stderr =
|
||
RunCommandline(args[k].." "..addition_arg
|
||
.." "..inputs[k]
|
||
.." tests/test_commandline.tmp")
|
||
lu.assertEquals(stdout, "")
|
||
lu.assertStrContains(stderr, ("Successfully writes %d bytes")
|
||
:format(GetFileData("tests/test_commandline.tmp"):len()))
|
||
lu.assertEquals(returned_status, 0)
|
||
local result
|
||
if func_name:find("Dict") then
|
||
result = LibDeflate[func_name](LibDeflate, GetFileData(
|
||
inputs[k]), dictionary32768, configs)
|
||
else
|
||
result = LibDeflate[func_name](LibDeflate, GetFileData(
|
||
inputs[k]), configs)
|
||
end
|
||
lu.assertNotNil(result)
|
||
lu.assertEquals(GetFileData("tests/test_commandline.tmp")
|
||
, result)
|
||
end
|
||
end
|
||
end
|
||
|
||
TestCompressRatio = {}
|
||
-- May need to modify number if algorithm changes.
|
||
function TestCompressRatio:TestSmallTest()
|
||
-- avoid github auto CRLF problem by removing \n in the file.
|
||
local fileData = GetFileData("tests/data/smalltest_no_newline.txt")
|
||
lu.assertEquals(fileData:len(), 28453)
|
||
lu.assertTrue(LibDeflate:CompressDeflate(fileData, {level=0}):len()
|
||
<= 28458)
|
||
lu.assertTrue(LibDeflate:CompressDeflate(fileData, {level=1}):len()
|
||
<= 7467)
|
||
lu.assertTrue(LibDeflate:CompressDeflate(fileData, {level=2}):len()
|
||
<= 7011)
|
||
lu.assertTrue(LibDeflate:CompressDeflate(fileData, {level=3}):len()
|
||
<= 6740)
|
||
lu.assertTrue(LibDeflate:CompressDeflate(fileData, {level=4}):len()
|
||
<= 6401)
|
||
lu.assertTrue(LibDeflate:CompressDeflate(fileData, {level=5}):len()
|
||
<= 5992)
|
||
lu.assertTrue(LibDeflate:CompressDeflate(fileData, {level=6}):len()
|
||
<= 5884)
|
||
lu.assertTrue(LibDeflate:CompressDeflate(fileData, {level=7}):len()
|
||
<= 5829)
|
||
lu.assertTrue(LibDeflate:CompressDeflate(fileData, {level=8}):len()
|
||
<= 5820)
|
||
lu.assertTrue(LibDeflate:CompressDeflate(fileData, {level=9}):len()
|
||
<= 5820)
|
||
end
|
||
|
||
TestExported = {}
|
||
function TestExported:TestExported()
|
||
local exported = {
|
||
EncodeForWoWChatChannel = "function",
|
||
_COPYRIGHT = "string",
|
||
DecodeForWoWAddonChannel = "function",
|
||
CompressDeflate = "function",
|
||
DecompressDeflate = "function",
|
||
CompressDeflateWithDict = "function",
|
||
DecompressZlibWithDict = "function",
|
||
CreateCodec = "function",
|
||
DecodeForWoWChatChannel = "function",
|
||
internals = "table",
|
||
_VERSION = "string",
|
||
_MAJOR = "string",
|
||
_MINOR = "number",
|
||
Adler32 = "function",
|
||
CreateDictionary = "function",
|
||
CompressZlibWithDict = "function",
|
||
EncodeForPrint = "function",
|
||
CompressZlib = "function",
|
||
DecodeForPrint = "function",
|
||
DecompressDeflateWithDict = "function",
|
||
EncodeForWoWAddonChannel = "function",
|
||
DecompressZlib = "function",
|
||
}
|
||
for k, v in pairs(exported) do
|
||
lu.assertEquals(v, type(LibDeflate[k]))
|
||
end
|
||
for k, v in pairs(LibDeflate) do
|
||
lu.assertEquals(type(v), exported[k])
|
||
end
|
||
end
|
||
--------------------------------------------------------------
|
||
-- Coverage Tests --------------------------------------------
|
||
--------------------------------------------------------------
|
||
local function AddToCoverageTest(suite, test)
|
||
assert(suite)
|
||
assert(type(suite[test]) == "function")
|
||
CodeCoverage[test] = function(_, ...)
|
||
return suite[test](_G[suite], ...) end
|
||
end
|
||
local function AddAllToCoverageTest(suite)
|
||
for k, _ in pairs(suite) do
|
||
AddToCoverageTest(suite, k)
|
||
end
|
||
end
|
||
|
||
-- Run "luajit -lluacov tests/Test.lua CodeCoverage" for test coverage test.
|
||
CodeCoverage = {}
|
||
AddAllToCoverageTest(TestBasicStrings)
|
||
AddAllToCoverageTest(TestDecompress)
|
||
AddAllToCoverageTest(TestInternals)
|
||
AddAllToCoverageTest(TestPresetDict)
|
||
AddAllToCoverageTest(TestEncode)
|
||
AddAllToCoverageTest(TestErrors)
|
||
AddToCoverageTest(TestMyData, "TestSmallTest")
|
||
AddToCoverageTest(TestThirdPartyBig, "Testptt5")
|
||
AddToCoverageTest(TestThirdPartyBig, "TestGeoProtodata")
|
||
AddToCoverageTest(TestCompressStrategy, "TestIsFixedStrategyInEffect")
|
||
AddToCoverageTest(TestCompressStrategy, "TestIsDynamicStrategyInEffect")
|
||
AddToCoverageTest(TestCompressStrategy, "TestIsHuffmanOnlyStrategyInEffect")
|
||
|
||
-- Run "lua tests/Test.lua CommandLineCodeCoverage "
|
||
-- for test coverage test and CommandLineCodeCoverage
|
||
-- DONT run with "luajit -lluaconv"
|
||
CommandLineCodeCoverage = {}
|
||
for k, v in pairs(TestCommandLine) do
|
||
CommandLineCodeCoverage[k] = function(_, ...)
|
||
lua_program = "lua -lluacov"
|
||
return TestCommandLine[k](TestCommandLine, ...)
|
||
end
|
||
end
|
||
|
||
-- Check if decompress will produce any lua error for random string.
|
||
-- Expectation is that no Lua error.
|
||
-- This test is not run in CI.
|
||
DecompressLuaErrorTest = {}
|
||
function DecompressLuaErrorTest:Test()
|
||
math.randomseed(os.time())
|
||
for _=1, 10000 do
|
||
local len = math.random(0, 10000)
|
||
local str = GetRandomString(len)
|
||
local dict = CreateDictionaryWithoutVerify(
|
||
GetRandomString(math.random(1, 32768)))
|
||
local r1, r2
|
||
r1, r2 = LibDeflate:DecompressDeflate(str)
|
||
-- Check the type of return value
|
||
assert((type(r1) == "string" or type(r1) == "nil") and r2 % 1 == 0)
|
||
r1, r2 = LibDeflate:DecompressZlib(str)
|
||
assert((type(r1) == "string" or type(r1) == "nil") and r2 % 1 == 0)
|
||
r1, r2 = LibDeflate:DecompressDeflateWithDict(str, dict)
|
||
assert((type(r1) == "string" or type(r1) == "nil") and r2 % 1 == 0)
|
||
r1, r2 = LibDeflate:DecompressZlibWithDict(str, dict)
|
||
assert((type(r1) == "string" or type(r1) == "nil") and r2 % 1 == 0)
|
||
print("Decompressed one random string without Lua error.")
|
||
print(StringForPrint(StringToHex(str)))
|
||
end
|
||
end
|
||
|
||
-- Tests for some huge test data.
|
||
-- The test data is not in the repository.
|
||
-- Run the batch script in tests\dev_scripts\download_huge_data.bat
|
||
-- to download.
|
||
-- This test is not run in CI.
|
||
HugeTests = {}
|
||
function HugeTests:TestCanterburyBible()
|
||
CheckCompressAndDecompressFile("tests/huge_data/bible.txt", "all")
|
||
end
|
||
function HugeTests:TestCanterburyEColi()
|
||
CheckCompressAndDecompressFile("tests/huge_data/E.coli", "all")
|
||
end
|
||
function HugeTests:TestCanterburyWorld129()
|
||
CheckCompressAndDecompressFile("tests/huge_data/world192.txt", "all")
|
||
end
|
||
do
|
||
local silesia_files = {"dickens", "mozilla", "mr", "nci", "ooffice"
|
||
, "osdb", "reymont", "samba", "sao", "webster", "xml", "x-ray"}
|
||
for _, f in pairs(silesia_files) do
|
||
HugeTests["TestSilesia"..f:sub(1, 1):upper()..f:sub(2)] = function()
|
||
CheckCompressAndDecompressFile("tests/huge_data/"..f
|
||
, {0, 1, 2, 3, 4})
|
||
end
|
||
end
|
||
end
|
||
|
||
for k, v in pairs(_G) do
|
||
if type(k) == "string" and (k:find("^Test") or k:find("^test")) then
|
||
assert(type(v) == "table", "Globals start with Test or test"
|
||
.." must be table: "..k)
|
||
for kk, vv in pairs(v) do
|
||
assert(type(kk) == "string"
|
||
and kk:find("^Test"), "All members in test table"
|
||
.." s key must start with Test: "..tostring(kk))
|
||
assert(type(vv) == "function", "All members in test table"
|
||
.." must be function")
|
||
end
|
||
end
|
||
end
|
||
|
||
--
|
||
-- Performance Evaluation, compared with LibCompress
|
||
--
|
||
local function CheckCompressAndDecompressLibCompress(
|
||
string_or_filename, is_file)
|
||
|
||
FullMemoryCollect()
|
||
local LibCompress = require("LibCompress")
|
||
|
||
local origin
|
||
if is_file then
|
||
origin = GetFileData(string_or_filename)
|
||
else
|
||
origin = string_or_filename
|
||
end
|
||
|
||
FullMemoryCollect()
|
||
local total_memory_before = math.floor(collectgarbage("count")*1024)
|
||
|
||
do
|
||
print(
|
||
(">>>>> %s: %s size: %d B (LibCompress)")
|
||
:format(is_file and "File" or "String",
|
||
string_or_filename:sub(1, 40), origin:len()
|
||
))
|
||
local compress_to_run = {
|
||
{"Compress", origin},
|
||
{"CompressLZW", origin},
|
||
{"CompressHuffman", origin},
|
||
}
|
||
|
||
for j, compress_running in ipairs(compress_to_run) do
|
||
-- Compress by raw deflate
|
||
local compress_func_name = compress_running[1]
|
||
local compress_memory_leaked, compress_memory_used
|
||
, compress_time, compress_data =
|
||
MemCheckAndBenchmarkFunc(LibCompress
|
||
, unpack(compress_running))
|
||
|
||
local decompress_to_run = {
|
||
{"Decompress", compress_data},
|
||
{"Decompress", compress_data},
|
||
{"Decompress", compress_data},
|
||
}
|
||
lu.assertEquals(#decompress_to_run, #compress_to_run)
|
||
|
||
-- Try decompress by LibDeflate
|
||
local decompress_memory_leaked, decompress_memory_used,
|
||
decompress_time, decompress_data =
|
||
MemCheckAndBenchmarkFunc(LibCompress
|
||
, unpack(decompress_to_run[j]))
|
||
AssertLongStringEqual(decompress_data, origin
|
||
, compress_func_name
|
||
.." LibCompress decompress result not match origin string.")
|
||
|
||
print(
|
||
("%s: Size : %d B,Time: %.3f ms, "
|
||
.."Speed: %.0f KB/s, Memory: %d B,"
|
||
.." Mem/input: %.2f, (memleak?: %d B)\n")
|
||
:format(compress_func_name
|
||
, compress_data:len(), compress_time
|
||
, compress_data:len()/compress_time
|
||
, compress_memory_used
|
||
, compress_memory_used/origin:len()
|
||
, compress_memory_leaked
|
||
),
|
||
("%s: cRatio: %.2f,Time: %.3f ms"
|
||
..", Speed: %.0f KB/s, Memory: %d B,"
|
||
.." Mem/input: %.2f, (memleak?: %d B)"):format(
|
||
decompress_to_run[j][1]
|
||
, origin:len()/compress_data:len(), decompress_time
|
||
, decompress_data:len()/decompress_time
|
||
, decompress_memory_used
|
||
, decompress_memory_used/origin:len()
|
||
, decompress_memory_leaked
|
||
)
|
||
)
|
||
print("")
|
||
end
|
||
end
|
||
|
||
FullMemoryCollect()
|
||
local total_memory_after = math.floor(collectgarbage("count")*1024)
|
||
|
||
local total_memory_difference = total_memory_before - total_memory_after
|
||
|
||
if total_memory_difference > 0 then
|
||
local ignore_leak = " (Ignore when the test is for LibCompress)"
|
||
print(
|
||
(">>>>> %s: %s size: %d B\n")
|
||
:format(is_file and "File" or "String"
|
||
, string_or_filename:sub(1, 40), origin:len()),
|
||
("Actual Memory Leak in the test: %d"..ignore_leak.."\n")
|
||
:format(total_memory_difference),
|
||
"\n")
|
||
end
|
||
end
|
||
|
||
local function EvaluatePerformance(filename)
|
||
local interpreter = _G._VERSION
|
||
if _G.jit then
|
||
interpreter = interpreter.."(LuaJIT)"
|
||
end
|
||
print(interpreter)
|
||
print("^^^^^^^^^^^^")
|
||
CheckCompressAndDecompressLibCompress(filename, true)
|
||
CheckCompressAndDecompressFile(filename, "all")
|
||
end
|
||
|
||
PerformanceEvaluation = {}
|
||
function PerformanceEvaluation:TestEvaluateWarlockWeakAuras()
|
||
EvaluatePerformance("tests/data/warlockWeakAuras.txt")
|
||
end
|
||
function PerformanceEvaluation:TestEvaluateTotalRp3Data()
|
||
EvaluatePerformance("tests/data/totalrp3.txt")
|
||
end
|
||
|
||
local runner = lu.LuaUnit.new()
|
||
local exitCode = runner:runSuite()
|
||
print("========================================================")
|
||
print("LibDeflate", "Version:", LibDeflate._VERSION, "\n")
|
||
print("Exported keys:")
|
||
for k, v in pairs(LibDeflate) do
|
||
assert(type(k) == "string")
|
||
print(k, type(v))
|
||
end
|
||
print("--------------------------------------------------------")
|
||
if exitCode == 0 then
|
||
print("TEST OK")
|
||
else
|
||
print("TEST FAILED")
|
||
end
|
||
|
||
os.exit(exitCode) |