- Added lemock library ( Debian package needed )

- Added Mock for kamailio sr module
- Added NGCP, NGCPPrefs, NGCPConfig, NGCPPeerPrefs and NGCPDomainPref classes.
  This is just a playground to figure out how can we organize the code. WIP
squeeze-backports
Victor Seva 13 years ago
parent 48d303bc90
commit 4f4f571709

@ -1,5 +1,33 @@
#!/usr/bin/env lua5.1
# Kamailio Lua utils
-- Kamailio Lua utils
-- kamailio log for a table
function table.log(t, msg, level)
if not level then
level = "debug"
end
if msg then
sr.log(level, msg)
end
if not t then
-- empty table
return
end
for i,v in pairs(t) do
if type(i) == "number" then
iformat = "%d"
elseif type(i) == "string" then
iformat = "%s"
end
if type(v) == "string" then
sr.log(level, string.format("i:" .. iformat .. " v: %s", i, v))
elseif type(v) == "number" then
sr.log(level, string.format("i:" .. iformat .. " v: %d", i, v))
elseif type(v) == "table" then
table.log(v,string.format("i:" .. iformat .. " v:", i),level)
end
end
end
-- cleans and sets string values from the table list
function sets_avps(list)
@ -24,6 +52,9 @@ function seti_avps(list)
end
function clean_avps(list)
if not list then
error("list is empty")
end
local i,v
for i,v in pairs(list) do
@ -31,4 +62,4 @@ function clean_avps(list)
end
end
#EOF
--EOF

@ -0,0 +1,659 @@
------ THIS FILE IS TANGLED FROM LITERATE SOURCE FILES ------
-- Copyright (C) 2009 Tommy Pettersson <ptp@lysator.liu.se>
-- See terms in file COPYRIGHT, or at http://lemock.luaforge.net
module( 'lemock', package.seeall )
_VERSION = "LeMock 0.6"
_COPYRIGHT = "Copyright (C) 2009 Tommy Pettersson <ptp@lysator.liu.se>"
local class, object, qtostring, sfmt, add_to_set
local elements_of_set, value_equal
function object (class)
return setmetatable( {}, class )
end
function class (parent)
local c = object(parent)
c.__index = c
return c
end
sfmt = string.format
function qtostring (v)
if type(v) == 'string' then
return sfmt( '%q', v )
else
return tostring( v )
end
end
function add_to_set (o, setname, element)
if not o[setname] then
o[setname] = {}
end
local l = o[setname]
for i = 1, #l do
if l[i] == element then return end
end
l[#l+1] = element
end
function elements_of_set (o, setname)
local l = o[setname]
local i = l and #l+1 or 0
return function ()
i = i - 1
if i > 0 then return l[i] end
end
end
function value_equal (a, b)
if a == b then return true end
if a ~= a and b ~= b then return true end -- NaN == NaN
return false
end
local mock_controller_map = setmetatable( {}, {__mode='k'} )
-- All the classes are private
local Action, Argv, Callable, Controller, Mock
Action = {}
-- abstract
Action.generic = class()
function Action.generic:add_close (label)
add_to_set( self, 'closelist', label )
end
function Action.generic:add_depend (d)
add_to_set( self, 'dependlist', d )
end
function Action.generic:add_label (label)
add_to_set( self, 'labellist', label )
end
function Action.generic:assert_satisfied ()
assert( self.replay_count <= self.max_replays, "lemock internal error" )
if not (
self.min_replays <= self.replay_count
) then
error( sfmt( "Wrong replay count %d (expected %d..%d) for %s"
, self.replay_count
, self.min_replays, self.max_replays
, self:tostring()
)
, 0
)
end
end
function Action.generic:blocks ()
if self:is_satisfied() then
return function () end
end
return elements_of_set( self, 'labellist' )
end
function Action.generic:closes ()
return elements_of_set( self, 'closelist' )
end
function Action.generic:depends ()
return elements_of_set( self, 'dependlist' )
end
function Action.generic:has_label (l)
for x in elements_of_set( self, 'labellist' ) do
if x == l then return true end
end
return false
end
function Action.generic:is_expected ()
return self.replay_count < self.max_replays
and not self.is_blocked
and not self.is_closed
end
function Action.generic:is_satisfied ()
return
self.min_replays <= self.replay_count
end
function Action.generic:match (key)
if getmetatable(self) ~= getmetatable(key) then return false end
if self.mock ~= key.mock then return false end
return self:is_expected()
end
function Action.generic:new (mock)
local a = object( self )
a.mock = mock
a.replay_count = 0
a.min_replays = 1
a.max_replays = 1
return a
end
function Action.generic:set_times (a, b)
min = a or 1
max = b or min
min, max = tonumber(min), tonumber(max)
if (not min) or (not max) or (min >= math.huge)
or (min ~= min) or (max ~= max) -- NaN
or (min < 0) or (max <= 0) or (min > max) then
error( sfmt( "Unrealistic time arguments (%s, %s)"
, qtostring( min )
, qtostring( max )
)
, 0
)
end
self.min_replays = min
self.max_replays = max
end
Action.generic_call = class( Action.generic )
Action.generic_call.can_return = true
function Action.generic_call:get_returnvalue ()
if self.has_returnvalue then
return self.returnvalue:unpack()
end
end
function Action.generic_call:set_returnvalue (...)
self.returnvalue = Argv:new(...)
self.has_returnvalue = true
end
function Action.generic_call:match (q)
if not Action.generic.match( self, q ) then return false end
if not self.argv:equal( q.argv ) then return false end
return true
end
function Action.generic_call:new (m, ...)
local a = Action.generic.new( self, m )
a.argv = Argv:new(...)
return a
end
-- concrete
Action.call = class( Action.generic_call )
function Action.call:match (q)
if not Action.generic_call.match( self, q ) then return false end
if self.key ~= q.key then return false end
return true
end
function Action.call:new (m, key, ...)
local a = Action.generic_call.new( self, m, ... )
a.key = key
return a
end
function Action.call:tostring ()
if self.has_returnvalue then
return sfmt( "call %s(%s) => %s"
, tostring(self.key)
, self.argv:tostring()
, self.returnvalue:tostring()
)
else
return sfmt( "call %s(%s)"
, tostring(self.key)
, self.argv:tostring()
)
end
end
Action.index = class( Action.generic )
Action.index.can_return = true
function Action.index:get_returnvalue ()
return self.returnvalue
end
function Action.index:set_returnvalue (v)
self.returnvalue = v
self.has_returnvalue = true
end
function Action.index:match (q)
if not Action.generic.match( self, q ) then return false end
if self.key ~= q.key then return false end
return true
end
function Action.index:new (m, key)
local a = Action.generic.new( self, m )
a.key = key
return a
end
function Action.index:tostring ()
local key = 'index '..tostring( self.key )
if self.has_returnvalue then
return sfmt( "index %s => %s"
, tostring( self.key )
, qtostring( self.returnvalue )
)
elseif self.is_callable then
return sfmt( "index %s()"
, tostring( self.key )
)
else
return sfmt( "index %s"
, tostring( self.key )
)
end
end
Action.newindex = class( Action.generic )
function Action.newindex:match (q)
if not Action.generic.match( self, q ) then return false end
if self.key ~= q.key then return false end
if not value_equal( self.val, q.val )
and self.val ~= Argv.ANYARG
and q.val ~= Argv.ANYARG then return false end
return true
end
function Action.newindex:new (m, key, val)
local a = Action.generic.new( self, m )
a.key = key
a.val = val
return a
end
function Action.newindex:tostring ()
return sfmt( "newindex %s = %s"
, tostring(self.key)
, qtostring(self.val)
)
end
Action.selfcall = class( Action.generic_call )
function Action.selfcall:match (q)
return Action.generic_call.match( self, q )
end
function Action.selfcall:new (m, ...)
local a = Action.generic_call.new( self, m, ... )
return a
end
function Action.selfcall:tostring ()
if self.has_returnvalue then
return sfmt( "selfcall (%s) => %s"
, self.argv:tostring()
, self.returnvalue:tostring()
)
else
return sfmt( "selfcall (%s)"
, self.argv:tostring()
)
end
end
Argv = class()
Argv.ANYARGS = newproxy() local ANYARGS = Argv.ANYARGS
Argv.ANYARG = newproxy() local ANYARG = Argv.ANYARG
function Argv:equal (other)
local a1, n1 = self.v, self.len
local a2, n2 = other.v, other.len
if n1-1 <= n2 and a1[n1] == ANYARGS then
n1 = n1-1
n2 = n1
elseif n2-1 <= n1 and a2[n2] == ANYARGS then
n2 = n2-1
n1 = n2
end
if n1 ~= n2 then
return false
end
for i = 1, n1 do
local v1, v2 = a1[i], a2[i]
if not value_equal(v1,v2) and v1 ~= ANYARG and v2 ~= ANYARG then
return false
end
end
return true
end
function Argv:new (...)
local av = object( self )
av.v = {...}
av.len = select('#',...)
for i = 1, av.len - 1 do
if av.v[i] == Argv.ANYARGS then
error( "ANYARGS not at end.", 0 )
end
end
return av
end
function Argv:tostring ()
local res = {}
local function w (v)
res[#res+1] = qtostring( v )
end
local av, ac = self.v, self.len
for i = 1, ac do
if av[i] == Argv.ANYARG then
res[#res+1] = 'ANYARG'
elseif av[i] == Argv.ANYARGS then
res[#res+1] = 'ANYARGS'
else
w( av[i] )
end
if i < ac then
res[#res+1] = ',' -- can not use qtostring in w()
end
end
return table.concat( res )
end
function Argv:unpack ()
return unpack( self.v, 1, self.len )
end
Callable = {}
Callable.generic = class()
Callable.record = class( Callable.generic )
Callable.replay = class( Callable.generic )
function Callable.generic:new ( index_action )
local f = object( self )
f.action = index_action
return f
end
function Callable.record:__call (...)
local index_action = self.action
local m = index_action.mock
local mc = mock_controller_map[m]
assert( mc.is_recording, "client uses cached callable from recording" )
mc:make_callable( index_action )
mc:add_action( Action.call:new( m, index_action.key, ... ))
end
function Callable.replay:__call (...)
local index_action = self.action
local m = index_action.mock
local mc = mock_controller_map[m]
local call_action = mc:lookup( Action.call:new( m, index_action.key, ... ))
mc:replay_action( call_action )
if call_action.throws_error then
error( call_action.errorvalue, 2 )
end
return call_action:get_returnvalue()
end
Controller = class()
-- Exported methods
function Controller:close (...)
if not self.is_recording then
error( "Can not insert close in replay mode.", 2 )
end
local action = self:get_last_action()
for _, close in ipairs{ ... } do
action:add_close( close )
end
return self -- for chaining
end
function Controller:depend (...)
if not self.is_recording then
error( "Can not add dependency in replay mode.", 2 )
end
local action = self:get_last_action()
for _, dependency in ipairs{ ... } do
action:add_depend( dependency )
end
return self -- for chaining
end
function Controller:error (value)
if not self.is_recording then
error( "Error called during replay.", 2 )
end
local action = self:get_last_action()
if action.has_returnvalue or action.throws_error then
error( "Returns and/or Error called twice for same action.", 2 )
end
action.throws_error = true
action.errorvalue = value
return self -- for chaining
end
function Controller:label (...)
if not self.is_recording then
error( "Can not add labels in replay mode.", 2 )
end
local action = self:get_last_action()
for _, label in ipairs{ ... } do
action:add_label( label )
end
return self -- for chaining
end
function Controller:mock ()
if not self.is_recording then
error( "New mock during replay.", 2 )
end
local m = object( Mock.record )
mock_controller_map[m] = self
return m
end
function Controller:new ()
local mc = object( self )
mc.actionlist = {}
mc.is_recording = true
return mc
end
function Controller:replay ()
if not self.is_recording then
error( "Replay called twice.", 2 )
end
self.is_recording = false
for m, mc in pairs( mock_controller_map ) do
if mc == self then
setmetatable( m, Mock.replay )
end
end
self:update_dependencies()
self:assert_no_dependency_cycles()
end
function Controller:returns (...)
if not self.is_recording then
error( "Returns called during replay.", 2 )
end
local action = self:get_last_action()
assert( not action.is_callable, "lemock internal error" )
if not action.can_return then
error( "Previous action can not return anything.", 2 )
end
if action.has_returnvalue or action.throws_error then
error( "Returns and/or Error called twice for same action.", 2 )
end
action:set_returnvalue(...)
return self -- for chaining
end
function Controller:times (min, max)
if not self.is_recording then
error( "Can not set times in replay mode.", 0 )
end
self:get_last_action():set_times( min, max )
return self -- for chaining
end
-- convenience functions
function Controller:anytimes() return self:times( 0, math.huge ) end
function Controller:atleastonce() return self:times( 1, math.huge ) end
function Controller:verify ()
if self.is_recording then
error( "Verify called during record.", 2 )
end
for a in self:actions() do
a:assert_satisfied()
end
end
-- Protected methods
function Controller:actions (q)
local l = self.actionlist
local i = 0
return function ()
i = i + 1
return l[i]
end
end
function Controller:add_action (a)
assert( a ~= nil, "lemock internal error" ) -- breaks array property
table.insert( self.actionlist, a )
end
function Controller:assert_no_dependency_cycles ()
local function is_in_path (label, path)
if not path then return false end -- is root
for _, l in ipairs( path ) do
if l == label then return true end
end
if path.prev then return is_in_path( label, path.prev ) end
return false
end
local function can_block (action, node)
for _, label in ipairs( node ) do
if action:has_label( label ) then return true end
end
return false
end
local function step (action, path)
local new_head
for label in action:depends() do
if is_in_path( label, path ) then
error( "Detected dependency cycle", 0 )
end
-- only create table if needed to reduce garbage
if not new_head then new_head = { prev=path } end
new_head[#new_head+1] = label
end
return new_head
end
local function search_depth_first (path)
for action in self:actions() do
if can_block( action, path ) then
local new_head = step( action, path )
if new_head then
search_depth_first( new_head )
end
end
end
end
for action in self:actions() do
local root = step( action, nil )
if root then search_depth_first( root ) end
end
end
function Controller:close_actions( ... ) -- takes iterator
for label in ... do
for candidate in self:actions() do
if candidate:has_label( label ) then
if not candidate:is_satisfied() then
error( "Closes unsatisfied action: "..candidate:tostring(), 0 )
end
candidate.is_closed = true
end
end
end
end
function Controller:get_last_action ()
local l = self.actionlist
if #l == 0 then
error( "No action is recorded yet.", 0 )
end
return l[#l]
end
function Controller:lookup (actual)
for action in self:actions() do
if action:match( actual ) then
return action
end
end
local expected = {}
for _, a in ipairs( self.actionlist ) do
if a:is_expected() and not a.is_callable then
expected[#expected+1] = a:tostring()
end
end
table.sort( expected )
if #expected == 0 then
expected[1] = "(Nothing)"
end
error( sfmt( "Unexpected action %s, expected:\n%s\n"
, actual:tostring()
, table.concat(expected,'\n')
)
, 0
)
end
function Controller:make_callable (action)
if action.has_returnvalue then
error( "Can not call "..action.key..". It has a returnvalue.", 0 )
end
action.is_callable = true
action.min_replays = 0
action.max_replays = math.huge
end
function Controller:new ()
local mc = object( self )
mc.actionlist = {}
mc.is_recording = true
return mc
end
function Controller:replay_action ( action )
assert( action:is_expected(), "lemock internal error" )
assert( action.replay_count < action.max_replays, "lemock internal error" )
local was_satisfied = action:is_satisfied()
action.replay_count = action.replay_count + 1
if not was_satisfied and action.labellist and action:is_satisfied() then
self:update_dependencies()
end
if action.closelist then
self:close_actions( action:closes() )
end
end
function Controller:update_dependencies ()
local blocked = {}
for action in self:actions() do
for label in action:blocks() do
blocked[label] = true
end
end
local function is_blocked (action)
for label in action:depends() do
if blocked[label] then return true end
end
return false
end
for action in self:actions() do
action.is_blocked = is_blocked( action )
end
end
Mock = { record={}, replay={} } -- no self-referencing __index!
function Mock.record:__index (key)
local mc = mock_controller_map[self]
local action = Action.index:new( self, key )
mc:add_action( action )
return Callable.record:new( action )
end
function Mock.record:__newindex (key, val)
local mc = mock_controller_map[self]
mc:add_action( Action.newindex:new( self, key, val ))
end
function Mock.record:__call (...)
local mc = mock_controller_map[self]
mc:add_action( Action.selfcall:new( self, ... ))
end
function Mock.replay:__index (key)
local mc = mock_controller_map[self]
local index_action = mc:lookup( Action.index:new( self, key ))
mc:replay_action( index_action )
if index_action.throws_error then
error( index_action.errorvalue, 2 )
end
if index_action.is_callable then
return Callable.replay:new( index_action )
else
return index_action:get_returnvalue()
end
end
function Mock.replay:__newindex (key, val)
local mc = mock_controller_map[self]
local newindex_action = mc:lookup( Action.newindex:new( self, key, val ))
mc:replay_action( newindex_action )
if newindex_action.throws_error then
error( newindex_action.errorvalue, 2 )
end
end
function Mock.replay:__call (...)
local mc = mock_controller_map[self]
local selfcall_action = mc:lookup( Action.selfcall:new( self, ... ))
mc:replay_action( selfcall_action )
if selfcall_action.throws_error then
error( selfcall_action.errorvalue, 2 )
end
return selfcall_action:get_returnvalue()
end
function controller ()
local exported_methods = {
'anytimes',
'atleastonce',
'close',
'depend',
'error',
'label',
'mock',
'new',
'replay',
'returns',
'times',
'verify',
}
local mc = Controller:new()
local wrapper = {}
for _, method in ipairs( exported_methods ) do
wrapper[ method ] = function (self, ...)
return mc[ method ]( mc, ... )
end
end
wrapper.ANYARG = Argv.ANYARG
wrapper.ANYARGS = Argv.ANYARGS
return wrapper
end
return _M

@ -0,0 +1,17 @@
#!/usr/bin/env lua5.1
require 'lemock'
mc = lemock.controller()
srMock = {
__class__ = 'srMock',
pv = mc:mock()
}
srMock_MT = { __index = srMock, __newindex = mc:mock() }
function srMock:new()
--print("srMock:new")
local t = {}
setmetatable(t, srMock_MT)
return t
end
--EOF

@ -0,0 +1,28 @@
#!/usr/bin/env lua5.1
require 'ngcp.pref'
-- class NGCPDomainPrefs
NGCPDomainPrefs = {
__class__ = 'NGCPDomainPrefs'
}
NGCPDomainPrefs_MT = { __index = NGCPDomainPrefs, __newindex = NGCPPrefs }
function NGCPDomainPrefs:new()
local t = NGCPDomainPrefs.init()
setmetatable( t, NGCPDomainPrefs_MT )
return t
end
function NGCPDomainPrefs.init()
local t = NGCPPrefs.init()
return t
end
function NGCPDomainPrefs:clean(...)
--print("NGCPDomainPrefs:clean")
--print(table.tostring(getmetatable(self)))
--print(table.tostring(self))
NGCPPrefs.clean(self, ...)
end
-- class
--EOF

@ -1,18 +1,6 @@
#!/usr/bin/env lua5.1
-- class NGCPPreference
NGCPPreference = {
__class__ = 'NGCPPreference'
}
NGCPPreference_MT = { __index = NGCPPreference }
function NGCPPreference:new(name)
local t = {}
t.name = name
setmetatable( t, NGCPPreference_MT )
return t
end
-- class
require 'ngcp.pp'
require 'ngcp.dp'
-- class NGCPConfig
NGCPConfig = {
@ -34,14 +22,20 @@ NGCP = {
NGCP_MT = { __index = NGCP }
function NGCP:new()
local t = {}
t.config = NGCPConfig:new()
t.preference = {
domain = NGCPPreference:new('domain'),
peer = NGCPPreference:new('peer'),
}
local t = NGCP.init()
setmetatable( t, NGCP_MT )
return t
end
function NGCP.init()
local t = {
config = NGCPConfig:new(),
prefs = {
domain = NGCPDomainPrefs:new(),
peer = NGCPPeerPrefs:new()
}
}
return t
end
-- class
--EOF

@ -0,0 +1,88 @@
#!/usr/bin/env lua5.1
require 'ngcp.pref'
-- class NGCPPeerPrefs
NGCPPeerPrefs = {
__class__ = 'NGCPPeerPrefs'
}
NGCPPeerPrefs_MT = { __index = NGCPPeerPrefs, __newindex = NGCPPrefs }
function NGCPPeerPrefs:new()
local t = NGCPPeerPrefs.init()
setmetatable( t, NGCPPeerPrefs_MT )
return t
end
function NGCPPeerPrefs.init()
local t = NGCPPrefs.init()
t.inbound = {
peer_peer_callee_auth_user = "",
peer_peer_callee_auth_pass = "",
peer_peer_callee_auth_realm = "",
caller_use_rtpproxy = "",
peer_caller_ipv46_for_rtpproxy = "",
caller_force_outbound_calls_to_peer = "",
peer_caller_find_subscriber_by_uuid = "",
pstn_dp_caller_in_id = "",
pstn_dp_callee_in_id = "",
pstn_dp_caller_out_id = "",
pstn_dp_callee_out_id = "",
rewrite_caller_in_dpid = "",
rewrite_caller_out_dpid = "",
rewrite_callee_in_dpid = "",
rewrite_callee_out_dpid = "",
caller_peer_concurrent_max = "",
peer_caller_sst_enable = "",
peer_caller_sst_expires = "",
peer_caller_sst_min_timer = "",
peer_caller_sst_max_timer = "",
peer_caller_sst_refresh_method = "",
caller_inbound_upn = "",
caller_inbound_npn = "",
caller_inbound_uprn = ""
}
t.outbound = {
peer_peer_caller_auth_user = "",
peer_peer_caller_auth_pass = "",
peer_peer_caller_auth_realm = "",
callee_use_rtpproxy = "",
peer_callee_ipv46_for_rtpproxy = "",
peer_callee_concurrent_max = "",
peer_callee_concurrent_max_ou = "",
peer_callee_outbound_socke = "",
pstn_dp_caller_in_i = "",
pstn_dp_callee_in_i = "",
pstn_dp_caller_out_i = "",
pstn_dp_callee_out_i = "",
rewrite_caller_in_dpi = "",
rewrite_caller_out_dpi = "",
rewrite_caller_out_dpi = "",
rewrite_callee_in_dpi = "",
rewrite_callee_out_dpi = "",
peer_callee_sst_enabl = "",
peer_callee_sst_expire = "",
peer_callee_sst_min_time = "",
peer_callee_sst_max_time = "",
peer_callee_sst_refresh_metho = "",
callee_outbound_from_displa = "",
callee_outbound_from_use = "",
callee_outbound_pai_use = "",
callee_outbound_ppi_use = "",
callee_outbound_diversio = "",
concurrent_ma = "",
concurrent_max_ou = "",
concurrent_max_per_accoun = "",
concurrent_max_out_per_account = ""
}
--print("NGCPPeerPrefs:init" .. "\n" .. table.tostring(t))
return t
end
function NGCPPeerPrefs:clean(...)
--print("NGCPPeerPrefs:clean")
--print(table.tostring(getmetatable(self)))
--print(table.tostring(self))
NGCPPrefs.clean(self, ...)
end
-- class
--EOF

@ -0,0 +1,42 @@
#!/usr/bin/env lua5.1
require 'kam_utils'
-- class NGCPPrefs
NGCPPrefs = {
__class__ = 'NGCPPrefs'
}
NGCPPrefs_MT = { __index = NGCPPrefs }
function NGCPPrefs:new()
local t = NGCPPrefs.init()
setmetatable( t, NGCPPrefs_MT )
return t
end
function NGCPPrefs.init()
local t = {
inbound = {},
outbound = {},
common = {},
groups = {'inbound', 'outbound', 'common'}
}
--print("NGCPPrefs:init" .. "\n" .. table.tostring(t))
return t
end
function NGCPPrefs:clean(group)
--print("NGCPPrefs:clean")
--print(table.tostring(getmetatable(self)))
--print(table.tostring(self))
if group then
if self[group] then
clean_avps(self[group])
end
else
for k,v in ipairs(self.groups) do
clean_avps(self[v])
end
end
end
-- class
--EOF

@ -0,0 +1,28 @@
#!/usr/bin/env lua5.1
require('luaunit')
require 'mocks.sr'
TestMock = {}
function TestMock:testMock()
m = mc:mock()
m.pv = mc:mock()
m.titi( 42 )
m.toto( 33, "abc", { 21} )
end
TestSRMock = {}
function TestSRMock:setUp()
self.sr = srMock:new()
end
function TestSRMock:test_ini()
assertTrue(self.sr.pv)
self.sr.pv.sets("$avp('hithere')", "value")
end
---- Control test output:
lu = LuaUnit
lu:setOutputType( "TAP" )
lu:setVerbosity( 1 )
lu:run()
--EOF

@ -1,6 +1,29 @@
#!/usr/bin/env lua5.1
require('luaunit')
require 'ngcp'
require 'ngcp.ngcp'
require 'mocks.sr'
require 'utils'
sr = srMock:new()
TestNGCPPrefs = {} --class
function TestNGCPPrefs:setUp()
self.prefs = NGCPPrefs:new()
end
function TestNGCPPrefs:test_prefs_init()
assertItemsEquals(self.prefs.groups, {"inbound","outbound","common"})
assertTrue(self.prefs.inbound)
assertTrue(self.prefs.outbound)
assertTrue(self.prefs.common)
end
function TestNGCPPrefs:test_pref_clean()
--self.prefs:clean()
assertError(self.prefs.clean, nil)
end
-- class TestNGCPPrefs
TestNGCP = {} --class
@ -9,8 +32,24 @@ TestNGCP = {} --class
end
function TestNGCP:test_config()
assertEquals( self.ngcp.preference.domain.name , 'domain' )
assertEquals( self.ngcp.preference.peer.name , 'peer' )
assertTrue(self.ngcp.config)
end
function TestNGCP:test_prefs_init()
--print("TestNGCP:test_prefs_init")
assertTrue(self.ngcp)
end
function TestNGCP:test_peerpref_clean()
--print("TestNGCP:test_peerpref_clean")
assertTrue(self.ngcp.prefs.peer)
self.ngcp.prefs.peer:clean()
end
function TestNGCP:test_domainpref_clean()
--print("TestNGCP:test_domainpref_clean")
assertTrue(self.ngcp.prefs.domain)
self.ngcp.prefs.domain:clean()
end
-- class TestNGCP

@ -0,0 +1,59 @@
#!/usr/bin/env lua5.1
require('luaunit')
require 'mocks.sr'
require 'utils'
TestUtils = {} --class
function TestUtils:setUp()
self.simple_hash = {
one = 1, two = 2, three = 3
}
self.simple_list = {
1, 2, 3
}
self.complex_hash = {
cone = self.simple_list,
ctwo = self.simple_hash
}
end
function TestUtils:test_table_deepcopy()
assertNotEquals(table.deepcopy(self.simple_hash), self.simple_hash)
-- if the parameter is not a table... it has te be the same
assertEquals(table.deepcopy("hola"), "hola")
end
function TestUtils:test_table_contains()
assertTrue(table.contains(self.simple_hash, 3))
assertFalse(table.contains(self.simple_hash, 4))
assertFalse(table.contains(nil))
assertError(table.contains, "hola",1)
end
function TestUtils:test_table_tostring()
assertError(table.tostring,nil)
assertEquals(table.tostring(self.simple_list), "{1,2,3}")
assertTrue(table.tostring(self.simple_hash))
--print(table.tostring(self.simple_hash) .. "\n")
assertTrue(table.tostring(self.complex_hash))
--print(table.tostring(self.complex_hash))
end
function TestUtils:test_implode()
assertEquals(implode(',', self.simple_list, "'"), "'1','2','3'")
assertError(implode, nil, self.simple_list, "'")
assertError(implode, ',', nil, "'")
end
function TestUtils:test_explode()
assertItemsEquals(explode(',',"1,2,3"), {'1','2','3'})
end
-- class TestUtils
---- Control test output:
lu = LuaUnit
lu:setOutputType( "TAP" )
lu:setVerbosity( 1 )
lu:run()
--EOF

@ -1,36 +1,8 @@
#!/usr/bin/env lua5.1
# Lua utils
-- kamailio log for a table
function log_table(table, msg, level)
if not level then
level = "debug"
end
if msg then
sr.log(level, msg)
end
if not table then
-- empty table
return
end
for i,v in pairs(table) do
if type(i) == "number" then
iformat = "%d"
elseif type(i) == "string" then
iformat = "%s"
end
if type(v) == "string" then
sr.log(level, string.format("i:" .. iformat .. " v: %s", i, v))
elseif type(v) == "number" then
sr.log(level, string.format("i:" .. iformat .. " v: %d", i, v))
elseif type(v) == "table" then
log_table(v,string.format("i:" .. iformat .. " v:", i),level)
end
end
end
-- Lua utils
-- copy a table
function table_deepcopy(object)
function table.deepcopy(object)
local lookup_table = {}
local function _copy(object)
if type(object) ~= "table" then
@ -48,6 +20,53 @@ function table_deepcopy(object)
return _copy(object)
end
function table.contains(table, element)
if table then
for _, value in pairs(table) do
if value == element then
return true
end
end --for
end --if
return false
end
function table.val_to_str ( v )
if "string" == type( v ) then
v = string.gsub( v, "\n", "\\n" )
if string.match( string.gsub(v,"[^'\"]",""), '^"+$' ) then
return "'" .. v .. "'"
end
return '"' .. string.gsub(v,'"', '\\"' ) .. '"'
else
return "table" == type( v ) and table.tostring( v ) or
tostring( v )
end
end
function table.key_to_str ( k )
if "string" == type( k ) and string.match( k, "^[_%a][_%a%d]*$" ) then
return k
else
return "[" .. table.val_to_str( k ) .. "]"
end
end
function table.tostring( tbl )
local result, done = {}, {}
for k, v in ipairs( tbl ) do
table.insert( result, table.val_to_str( v ) )
done[ k ] = true
end
for k, v in pairs( tbl ) do
if not done[ k ] then
table.insert( result,
table.key_to_str( k ) .. "=" .. table.val_to_str( v ) )
end
end
return "{" .. table.concat( result, "," ) .. "}"
end
-- from table to string
-- t = {'a','b'}
-- implode(",",t,"'")
@ -56,6 +75,9 @@ end
-- "a#b"
function implode(delimiter, list, quoter)
local len = #list
if not delimiter then
error("delimiter is nil")
end
if len == 0 then
return nil
end
@ -71,14 +93,22 @@ end
-- from string to table
function explode(delimiter, text)
local list = {}; local pos = 1
local list = {}
local pos = 1
if not delimiter then
error("delimiter is nil")
end
if not text then
error("text is nil")
end
if string.find("", delimiter, 1) then
-- We'll look at error handling later!
error("delimiter matches empty string!")
end
while 1 do
local first, last = string.find(text, delimiter, pos)
print (first, last)
-- print (first, last)
if first then
table.insert(list, string.sub(text, pos, first-1))
pos = last+1
@ -89,13 +119,4 @@ function explode(delimiter, text)
end
return list
end
function compare_desc_len(a,b)
return string.len(a) > string.len(b)
end
function findpattern(text, pattern, start)
return string.sub(text, string.find(text, pattern, start))
end
#EOF
--EOF
Loading…
Cancel
Save