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

--[[
//////////////////////////////////////////////////////////////////////////
// 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