You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
399 lines
10 KiB
399 lines
10 KiB
--[[
|
|
//////////////////////////////////////////////////////////////////////////
|
|
// date : 2013-5-4
|
|
// auth : macroli(idehong@gmail.com)
|
|
// ver : 0.3
|
|
// desc : assert and except
|
|
//////////////////////////////////////////////////////////////////////////
|
|
--]]
|
|
------------------------------------------------------------------------------
|
|
|
|
--module(..., package.seeall)
|
|
|
|
-- for assert base
|
|
local assert_mt_base = {}
|
|
assert_mt_base.__eq = function(v1, v2)
|
|
return type(v1.data) == type(v2.data) and v1.data == v2.data
|
|
end
|
|
|
|
assert_mt_base.__lt = function (v1, v2)
|
|
return false
|
|
end
|
|
|
|
assert_mt_base.__le = function (v1, v2)
|
|
return false
|
|
end
|
|
|
|
assert_mt_base.__tostring = function (v1)
|
|
return tostring(v1.data)
|
|
end
|
|
|
|
local CBaseAssert = {}
|
|
function CBaseAssert:new(oo)
|
|
local o = oo or {}
|
|
setmetatable(o, assert_mt_base)
|
|
return o
|
|
end
|
|
|
|
|
|
local assert_mt_default = {}
|
|
assert_mt_default.__eq = function(v1, v2)
|
|
return type(v1.data) == type(v2.data) and v1.data == v2.data
|
|
end
|
|
|
|
assert_mt_default.__lt = function (v1, v2)
|
|
return type(v1.data) == type(v2.data) and v1.data < v2.data
|
|
end
|
|
|
|
assert_mt_default.__le = function (v1, v2)
|
|
return type(v1.data) == type(v2.data) and v1.data <= v2.data
|
|
end
|
|
|
|
assert_mt_default.__tostring = function (v1)
|
|
return tostring(v1.data)
|
|
end
|
|
|
|
|
|
local CNumberAssert = {}
|
|
function CNumberAssert:new(oo)
|
|
local o = oo or {}
|
|
setmetatable(o, assert_mt_default)
|
|
return o
|
|
end
|
|
|
|
|
|
local CStringAssert = {}
|
|
function CStringAssert:new(oo)
|
|
local o = oo or {}
|
|
setmetatable(o, assert_mt_default)
|
|
return o
|
|
end
|
|
|
|
local _strCmpField = ""
|
|
|
|
-- for less than, equal than, great than result
|
|
local _iTableLT, _iTableEQ, _iTableGT = -1, 0, 1
|
|
|
|
-- compare function for table
|
|
local function _cmpTable(left, right, iCurLevel, iMaxLevel)
|
|
if iCurLevel >= iMaxLevel then return _iTableLT end
|
|
|
|
local tmpTypeTab = type({})
|
|
if tmpTypeTab ~= type(left) or tmpTypeTab ~= type(right) then return _iTableLT end
|
|
|
|
local tK1 = {}
|
|
for k, v in pairs(left) do table.insert(tK1, k) end
|
|
table.sort(tK1, function(a, b) return tostring(a) < tostring(b) end)
|
|
|
|
local tK2 = {}
|
|
for k, v in pairs(right) do table.insert(tK2, k) end
|
|
table.sort(tK2, function(a, b) return tostring(a) < tostring(b) end)
|
|
|
|
local iLen1, iLen2 = #tK1, #tK2
|
|
local iLenMin = math.min(iLen1, iLen2)
|
|
|
|
local tmp1, tmp2, tmpTyp1, tmpTyp2 = 0, 0, 0, 0
|
|
local tmpTypeStr = type("")
|
|
local tmpTypeInt = type(0)
|
|
|
|
local iTmpResult = _iTableEQ
|
|
for i = 1, iLenMin do
|
|
tmp1 = left[ tK1[i] ]
|
|
if tmp1 == nil then return _iTableLT end
|
|
|
|
tmp2 = right[ tK2[i] ]
|
|
if tmp2 == nil then return _iTableGT end
|
|
|
|
_strCmpField = string.format("level:%d, field:%s vs :%s", iCurLevel, tK1[i] , tK1[i] )
|
|
|
|
tmpTyp1, tmpTyp2 = type(tmp1), type(tmp2)
|
|
if tmpTyp1 ~= tmpTyp2 then return _iTableLT end
|
|
|
|
if tmpTyp1 == tmpTypeStr or tmpTyp1 == tmpTypeInt then
|
|
if tmp1 < tmp2 then return _iTableLT end
|
|
if tmp1 > tmp2 then return _iTableGT end
|
|
elseif tmpTyp1 == tmpTypeTab then
|
|
iTmpResult = _cmpTable(tmp1, tmp2, iCurLevel + 1, iMaxLevel)
|
|
if iTmpResult ~= _iTableEQ then return iTmpResult end
|
|
else
|
|
return _iTableLT
|
|
end
|
|
end
|
|
|
|
_strCmpField = string.format("level:%d, num: %d vs %d", iCurLevel, iLen1, iLen2)
|
|
|
|
if iLen1 < iLen2 then return _iTableLT end
|
|
if iLen1 > iLen2 then return _iTableGT end
|
|
|
|
return _iTableEQ
|
|
end
|
|
|
|
|
|
-- concat function for table
|
|
local function _strTable(left, strTip, iCurLevel, iMaxLevel)
|
|
if iCurLevel >= iMaxLevel then return strTip end
|
|
|
|
local tmpTypeTab = type({})
|
|
if tmpTypeTab ~= type(left) then return strTip end
|
|
|
|
local tK1 = {}
|
|
for k, v in pairs(left) do table.insert(tK1, k) end
|
|
table.sort(tK1, function(a, b) return tostring(a) < tostring(b) end)
|
|
|
|
local iLen1 = #tK1
|
|
local tmp1, tmpTyp1 = 0, 0
|
|
for i = 1, iLen1 do
|
|
tmp1 = left[ tK1[i] ]
|
|
tmpTyp1 = type(tmp1)
|
|
if tmpTyp1 == tmpTypeTab then
|
|
strTip = strTip .. _strTable(tmp1, strTip .. string.format("%s={", tostring(tK1[i]) ), iCurLevel + 1, iMaxLevel) .. "},"
|
|
else
|
|
strTip = strTip .. string.format("%s=%s,", tostring(tK1[i]), tostring(tmp1))
|
|
end
|
|
end
|
|
|
|
return strTip
|
|
end
|
|
|
|
-- for table recursion level number
|
|
local _iTableLevel = 5
|
|
local assert_mt_table = {}
|
|
assert_mt_table.__eq = function(v1, v2)
|
|
local mt1 = getmetatable(v1.data)
|
|
local mt2 = getmetatable(v1.data)
|
|
|
|
if mt1 and mt2 and mt1["__eq"] and mt2["__eq"] then
|
|
return v1.data == v2.data
|
|
else
|
|
return type(v1.data) == type(v2.data) and _cmpTable(v1.data, v2.data, 0, _iTableLevel) == _iTableEQ
|
|
end
|
|
end
|
|
|
|
assert_mt_table.__lt = function (v1, v2)
|
|
local mt1 = getmetatable(v1.data)
|
|
local mt2 = getmetatable(v1.data)
|
|
|
|
if mt1 and mt2 and mt1["__lt"] and mt2["__lt"] then
|
|
return v1.data < v2.data
|
|
else
|
|
return type(v1.data) == type(v2.data) and _cmpTable(v1.data, v2.data, 0, _iTableLevel) == _iTableLT
|
|
end
|
|
end
|
|
|
|
assert_mt_table.__le = function (v1, v2)
|
|
local mt1 = getmetatable(v1.data)
|
|
local mt2 = getmetatable(v1.data)
|
|
|
|
if mt1 and mt2 and mt1["__le"] and mt2["__le"] then
|
|
return v1.data <= v2.data
|
|
else
|
|
return type(v1.data) == type(v2.data) and _cmpTable(v1.data, v2.data, 0, _iTableLevel) <= _iTableEQ
|
|
end
|
|
end
|
|
|
|
assert_mt_table.__tostring = function (v1)
|
|
local mt1 = getmetatable(v1.data)
|
|
|
|
if mt1 and mt1["__tostring"] then
|
|
return tostring(v1.data)
|
|
else
|
|
return _strTable(v1.data, "{", 0, _iTableLevel) .. "}"
|
|
end
|
|
end
|
|
|
|
|
|
local CTableAssert = {}
|
|
function CTableAssert:new(oo)
|
|
local o = oo or {}
|
|
setmetatable(o, assert_mt_table)
|
|
return o
|
|
end
|
|
|
|
|
|
-- for test assert and except
|
|
CAssertMgr = {}
|
|
function CAssertMgr:new(oo)
|
|
local o = oo or {}
|
|
o.result = true
|
|
o.at = {}
|
|
|
|
o.at[tostring(type(nil)) ] = {ld={}, rd={},}
|
|
local oTmp = o.at[tostring(type(nil))]
|
|
oTmp.left = CBaseAssert:new(oTmp.ld)
|
|
oTmp.right = CBaseAssert:new(oTmp.rd)
|
|
|
|
o.at[tostring(type(1)) ] = {ld={}, rd={},}
|
|
local oTmp = o.at[tostring(type(1))]
|
|
oTmp.left = CNumberAssert:new(oTmp.ld)
|
|
oTmp.right = CNumberAssert:new(oTmp.rd)
|
|
|
|
o.at[tostring(type("")) ] = {ld={}, rd={},}
|
|
local oTmp = o.at[tostring(type(""))]
|
|
oTmp.left = CStringAssert:new(oTmp.ld)
|
|
oTmp.right = CStringAssert:new(oTmp.rd)
|
|
|
|
o.at[tostring(type(true)) ] = {ld={}, rd={},}
|
|
local oTmp = o.at[tostring(type(true))]
|
|
oTmp.left = CBaseAssert:new(oTmp.ld)
|
|
oTmp.right = CBaseAssert:new(oTmp.rd)
|
|
|
|
o.at[tostring(type({})) ] = {ld={}, rd={},}
|
|
local oTmp = o.at[tostring(type({}))]
|
|
oTmp.left = CTableAssert:new(oTmp.ld)
|
|
oTmp.right = CTableAssert:new(oTmp.rd)
|
|
|
|
o.at[tostring(type(print)) ] = {ld={}, rd={},}
|
|
local oTmp = o.at[tostring(type(print))]
|
|
oTmp.left = CBaseAssert:new(oTmp.ld)
|
|
oTmp.right = CBaseAssert:new(oTmp.rd)
|
|
|
|
o.at["thread"] = {ld={}, rd={},}
|
|
local oTmp = o.at["thread"]
|
|
oTmp.left = CBaseAssert:new(oTmp.ld)
|
|
oTmp.right = CBaseAssert:new(oTmp.rd)
|
|
|
|
o.at["userdata"] = {ld={}, rd={},}
|
|
local oTmp = o.at["userdata"]
|
|
oTmp.left = CBaseAssert:new(oTmp.ld)
|
|
oTmp.right = CBaseAssert:new(oTmp.rd)
|
|
|
|
setmetatable(o, self)
|
|
self.__index = self
|
|
return o
|
|
end
|
|
|
|
function CAssertMgr.GetResult(self)
|
|
return self.result
|
|
end
|
|
|
|
function CAssertMgr.helpWrapper(self, v1, v2)
|
|
self.result = false
|
|
_strCmpField = ""
|
|
local tmp = self.at[type(v1)]
|
|
if not tmp then return end
|
|
tmp.ld.data = v1
|
|
tmp.rd.data = v2
|
|
return tmp.left, tmp.right, type(v1)
|
|
end
|
|
|
|
function CAssertMgr.CheckResult(self, lv, strTip)
|
|
if not self:GetResult() then error(strTip, lv) end
|
|
end
|
|
|
|
function CAssertMgr.PCRTip(self, bNoPrintDetail, strTip, lv, v1, iParaNum)
|
|
local tmp = self.at[type(v1)]
|
|
l = tmp.left
|
|
r = tmp.right
|
|
|
|
local strTmp = ""
|
|
while true do
|
|
if type(v1) == type({}) and bNoPrintDetail then
|
|
strTmp = string.format("%s --> field=%s.", strTip, _strCmpField)
|
|
break
|
|
end
|
|
|
|
if iParaNum > 1 then
|
|
if _strCmpField and #_strCmpField > 0 then
|
|
strTmp = string.format("%s --> field=%s, left:%s, right:%s.", strTip, _strCmpField, tostring(l), tostring(r))
|
|
else
|
|
strTmp = string.format("%s --> left:%s, right:%s.", strTip, tostring(l), tostring(r))
|
|
end
|
|
else
|
|
if _strCmpField and #_strCmpField > 0 then
|
|
strTmp = string.format("%s --> field=%s, value:%s.", strTip, _strCmpField, tostring(l))
|
|
else
|
|
strTmp = string.format("%s --> value:%s.", strTip, tostring(l))
|
|
end
|
|
end
|
|
break
|
|
end
|
|
return strTmp
|
|
end
|
|
|
|
-- PCR = PCallCheckResult1
|
|
function CAssertMgr.PCR1(self, bNoPrintDetail, lv, strTip, v1)
|
|
local bRet = self:GetResult()
|
|
if not bRet then
|
|
local strTmp = self:PCRTip(bNoPrintDetail, strTip, lv, v1, 1)
|
|
local bResult, strError = pcall(function () self:CheckResult(lv, strTmp) end)
|
|
if not bResult and strError then self:print("\t" .. strError) end
|
|
end
|
|
return bRet
|
|
end
|
|
|
|
function CAssertMgr.PCR(self, bNoPrintDetail, lv, strTip, v1, v2)
|
|
local bRet = self:GetResult()
|
|
if not bRet then
|
|
local strTmp = self:PCRTip(bNoPrintDetail, strTip, lv, v1, 2)
|
|
local bResult, strError = pcall(function () self:CheckResult(lv, strTmp) end)
|
|
if not bResult and strError then self:print("\t" .. strError) end
|
|
end
|
|
return bRet
|
|
end
|
|
|
|
function CAssertMgr.print(self, ...)
|
|
if not self:GetResult() then self.oOutput:FailedTxt(...) end
|
|
return self
|
|
end
|
|
|
|
|
|
function CAssertMgr.AssertEQ(self, v1, v2)
|
|
local l, r, t = self:helpWrapper(v1, v2)
|
|
self.result = l == r
|
|
return self
|
|
end
|
|
|
|
function CAssertMgr.AssertLT(self, v1, v2)
|
|
local l, r, t = self:helpWrapper(v1, v2)
|
|
self.result = l < r
|
|
return self
|
|
end
|
|
|
|
function CAssertMgr.AssertLE(self, v1, v2)
|
|
local l, r,t = self:helpWrapper(v1, v2)
|
|
self.result = l <= r
|
|
return self
|
|
end
|
|
|
|
function CAssertMgr.AssertGT(self, v1, v2)
|
|
local l, r, t = self:helpWrapper(v1, v2)
|
|
self.result = l > r
|
|
return self
|
|
end
|
|
|
|
function CAssertMgr.AssertGE(self, v1, v2)
|
|
local l, r, t = self:helpWrapper(v1, v2)
|
|
self.result = l >= r
|
|
return self
|
|
end
|
|
|
|
function CAssertMgr.AssertNE(self, v1, v2)
|
|
self.result = false
|
|
local l, r, t = self:helpWrapper(v1, v2)
|
|
if type(v1) == type(v2) then
|
|
self.result = l ~= r
|
|
end
|
|
return self
|
|
end
|
|
|
|
function CAssertMgr.AssertNear(self, v1, v2, nearValue)
|
|
self.result = false
|
|
local l, r, t = self:helpWrapper(v1, v2)
|
|
if type(v1) == type(v2) and type(v1) == type(0.1) then
|
|
if v1 > v2 then self.result = (v1 - v2 < nearValue) end
|
|
if v1 < v2 then self.result = (v2 - v1 < nearValue) end
|
|
end
|
|
return self
|
|
end
|
|
|
|
function CAssertMgr.AssertTrue(self, v1)
|
|
local l, r, t = self:helpWrapper(v1, v1)
|
|
if v1 then self.result = true else self.result = false end
|
|
return self
|
|
end
|
|
|
|
function CAssertMgr.AssertFalse(self, v1)
|
|
self:AssertTrue(v1)
|
|
self.result = not self.result
|
|
return self
|
|
end
|
|
|