- 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,46 +75,48 @@ 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
if not quoter then
quoter = ""
end
local string = quoter .. list[1] .. quoter
for i = 2, len do
string = string .. delimiter .. quoter .. list[i] .. quoter
end
return string
return nil
end
if not quoter then
quoter = ""
end
local string = quoter .. list[1] .. quoter
for i = 2, len do
string = string .. delimiter .. quoter .. list[i] .. quoter
end
return string
end
-- from string to table
function explode(delimiter, text)
local list = {}; local pos = 1
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)
if first then
table.insert(list, string.sub(text, pos, first-1))
pos = last+1
else
table.insert(list, string.sub(text, pos))
break
end
end
return list
end
local list = {}
local pos = 1
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))
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)
if first then
table.insert(list, string.sub(text, pos, first-1))
pos = last+1
else
table.insert(list, string.sub(text, pos))
break
end
end
return list
end
#EOF
--EOF
Loading…
Cancel
Save