TT#64357 switch to lua5.2

* don't use globals, don't use module
  https://www.lua.org/manual/5.2/manual.html#8.2
* be aware that ngcp-klish/ngcp.lua is NOT a module
* clean luacheck errors/warnings
* remove lua-uri dependency
* migrate tests from lua-unit and lua-lemock to lua-busted

WARNING: ngcp-klish/ngcp.lua is outdated and most not work
with actual kamailio config

Change-Id: I10c6b674bc68ac07c3f02db072d6bff5ba2267a1
changes/68/39068/3
Victor Seva 5 years ago
parent 32ffcc894e
commit 595a5caacc

@ -0,0 +1,6 @@
return {
default = {
lua = "/usr/bin/lua5.2",
helper = "./spec/helper.lua",
},
}

1
.gitignore vendored

@ -0,0 +1 @@
results/

2
debian/control vendored

@ -14,7 +14,7 @@ Depends:
jq,
klish,
lua-ngcp-klish,
lua5.1,
lua5.2,
pssh,
${misc:Depends},
Conflicts:

@ -1 +1 @@
ngcp-klish/*lua usr/share/lua/5.1/ngcp-klish
ngcp-klish/*lua usr/share/lua/5.2/ngcp-klish

@ -35,42 +35,42 @@ local sort, concat, insert = table.sort, table.concat, table.insert
local pairs, ipairs, type, tonumber = pairs, ipairs, type, tonumber
local sub, find = string.sub, string.find
module "bencode"
local bencode = {
encode_rec = nil -- encode_list/dict and encode_rec are mutually recursive...
}
-- helpers
local function islist(t)
local n = #t
for k, v in pairs(t) do
if type(k) ~= "number"
local function islist(t)
local n = #t
for k, _ in pairs(t) do
if type(k) ~= "number"
or k % 1 ~= 0 -- integer?
or k < 1
or k > n
then
return false
end
end
or k > n
then
return false
end
end
for i = 1, n do
if t[i] == nil then
return false
end
end
if t[i] == nil then
return false
end
end
return true
end
end
-- encoder functions
local encode_rec -- encode_list/dict and encode_rec are mutually recursive...
local function encode_list(t, x)
insert(t, "l")
for _,v in ipairs(x) do
local err,ev = encode_rec(t, v); if err then return err,ev end
for _,v in ipairs(x) do
local err,ev = bencode.encode_rec(t, v); if err then return err,ev end
end
insert(t, "e")
insert(t, "e")
end
local function encode_dict(t, x)
@ -86,8 +86,8 @@ local function encode_dict(t, x)
sort(sortedkeys)
for k, v in ipairs(sortedkeys) do
local err,ev = encode_rec(t, v); if err then return err,ev end
err,ev = encode_rec(t, x[v]); if err then return err,ev end
local err,ev = bencode.encode_rec(t, v); if err then return err,ev end
err,ev = bencode.encode_rec(t, x[v]); if err then return err,ev end
end
insert(t, "e")
end
@ -102,12 +102,12 @@ end
local function encode_str(t, x)
insert(t, #x )
insert(t, #x )
insert(t, ":" )
insert(t, x )
end
encode_rec = function(t, x)
bencode.encode_rec = function(t, x)
local typx = type(x)
if typx == "string" then return encode_str (t, x)
@ -124,10 +124,10 @@ end
-- call recursive bencoder function with empty table, stringify that table.
-- this is the only encode* function visible to module users.
function encode(x)
function bencode.encode(x)
local t = {}
local err, val = encode_rec(t,x)
local err, val = bencode.encode_rec(t,x)
if not err then
return concat(t)
else
@ -137,70 +137,72 @@ end
-- decoder functions
local function decode_integer(s, index)
local a, b, int = find(s, "^(%-?%d+)e", index)
local function decode_integer(s, index)
local _, b, int = find(s, "^(%-?%d+)e", index)
if not int then return nil, "not a number", nil end
int = tonumber(int)
int = tonumber(int)
if not int then return nil, "not a number", int end
return int, b + 1
end
return int, b + 1
end
local function decode_list(s, index)
local t = {}
while sub(s, index, index) ~= "e" do
local function decode_list(s, index)
local t = {}
while sub(s, index, index) ~= "e" do
local obj, ev
obj, index, ev = decode(s, index)
obj, index, ev = bencode.decode(s, index)
if not obj then return obj, index, ev end
insert(t, obj)
end
index = index + 1
return t, index
end
local function decode_dictionary(s, index)
local t = {}
while sub(s, index, index) ~= "e" do
end
index = index + 1
return t, index
end
local function decode_dictionary(s, index)
local t = {}
while sub(s, index, index) ~= "e" do
local obj1, obj2, ev
obj1, index, ev = decode(s, index)
obj1, index, ev = bencode.decode(s, index)
if not obj1 then return obj1, index, ev end
obj2, index, ev = decode(s, index)
obj2, index, ev = bencode.decode(s, index)
if not obj2 then return obj2, index, ev end
t[obj1] = obj2
end
index = index + 1
return t, index
end
local function decode_string(s, index)
local a, b, len = find(s, "^([0-9]+):", index)
t[obj1] = obj2
end
index = index + 1
return t, index
end
local function decode_string(s, index)
local _, b, len = find(s, "^([0-9]+):", index)
if not len then return nil, "not a length", len end
index = b + 1
local v = sub(s, index, index + len - 1)
index = b + 1
local v = sub(s, index, index + len - 1)
if #v < len - 1 then return nil, "truncated string at end of input", v end
index = index + len
return v, index
end
function decode(s, index)
index = index + len
return v, index
end
function bencode.decode(s, index)
if not s then return nil, "no data", nil end
index = index or 1
local t = sub(s, index, index)
index = index or 1
local t = sub(s, index, index)
if not t then return nil, "truncation error", nil end
if t == "i" then
return decode_integer(s, index + 1)
elseif t == "l" then
return decode_list(s, index + 1)
elseif t == "d" then
return decode_dictionary(s, index + 1)
elseif t >= '0' and t <= '9' then
return decode_string(s, index)
else
if t == "i" then
return decode_integer(s, index + 1)
elseif t == "l" then
return decode_list(s, index + 1)
elseif t == "d" then
return decode_dictionary(s, index + 1)
elseif t >= '0' and t <= '9' then
return decode_string(s, index)
else
return nil, "invalid type", t
end
end
end
return bencode

@ -1,5 +1,5 @@
--
-- Copyright 2013 SipWise Team <development@sipwise.com>
-- Copyright 2013-2020 SipWise Team <development@sipwise.com>
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
@ -22,8 +22,10 @@ local constants
local DBI = require "DBI"
local io = require "io"
local configs = {}
-- return the content of file
function readAll(file)
function configs.readAll(file)
local f = io.open(file, "rb")
local content = f:read("*all")
f:close()
@ -31,16 +33,16 @@ function readAll(file)
end
-- return the ngcp constants as table
function get_constants(force)
function configs.get_constants(force)
if not constants or force then
constants = yaml.load(readAll('/etc/ngcp-config/constants.yml'))
constants = yaml.load(configs.readAll('/etc/ngcp-config/constants.yml'))
end
return constants
end
-- connection for provisioning
function get_connection()
get_constants()
function configs.get_connection()
configs.get_constants()
local config = {
dbname = constants.ossbss.provisioning.database.name,
dbuser = constants.ossbss.provisioning.database.user,
@ -56,8 +58,8 @@ function get_connection()
return dbh
end
function get_users()
local dbc = get_connection()
function configs.get_users()
local dbc = configs.get_connection()
local res, err = DBI.Do(dbc,
"select * from voip_subscribers where account_id is not null")
dbc:close()
@ -67,3 +69,5 @@ function get_users()
--affected_rows
return res
end
return configs

@ -2,55 +2,56 @@
-- http://lua-users.org/files/wiki_insecure/users/pshook/template/Expand.lua
local strfind = string.find
local strsub = string.sub
local gmatch = string.gmatch
local push = table.insert
local pop = table.remove
local concat = table.concat
local statements = {}
for w in string.gfind('do if for while repeat', '%a+') do
for w in gmatch('do if for while repeat', '%a+') do
statements[w] = true
end
function expand(str, ...)
return function (str, ...)
assert(type(str)=='string', 'expecting string')
local searchlist = arg
local searchlist = ...
local estring,evar
function estring(str)
function estring(_str)
local b,e,i
b,i = strfind(str, '%$.')
b,i = strfind(_str, '%$.')
if not b then return str end
local R, pos = {}, 1
repeat
b,e = strfind(str, '^%b{}', i)
b,e = strfind(_str, '^%b{}', i)
if b then
push(R, strsub(str, pos, b-2))
push(R, evar(strsub(str, b+1, e-1)))
push(R, strsub(_str, pos, b-2))
push(R, evar(strsub(_str, b+1, e-1)))
i = e+1
pos = i
else
b,e = strfind(str, '^%b()', i)
b,e = strfind(_str, '^%b()', i)
if b then
push(R, strsub(str, pos, b-2))
push(R, evar(strsub(str, b+1, e-1)))
push(R, strsub(_str, pos, b-2))
push(R, evar(strsub(_str, b+1, e-1)))
i = e+1
pos = i
elseif strfind(str, '^%a', i) then
push(R, strsub(str, pos, i-2))
push(R, evar(strsub(str, i, i)))
elseif strfind(_str, '^%a', i) then
push(R, strsub(_str, pos, i-2))
push(R, evar(strsub(_str, i, i)))
i = i+1
pos = i
elseif strfind(str, '^%$', i) then
push(R, strsub(str, pos, i))
elseif strfind(_str, '^%$', i) then
push(R, strsub(_str, pos, i))
i = i+1
pos = i
end
end
b,i = strfind(str, '%$.', i)
b,i = strfind(_str, '%$.', i)
until not b
push(R, strsub(str, pos))
push(R, strsub(_str, pos))
return concat(R)
end
@ -68,7 +69,7 @@ function expand(str, ...)
error('unknown variable: '.. index)
end
local function elist(var, v, str, sep)
local function elist(var, v, _str, sep)
local tab = search(v)
if tab then
assert(type(tab)=='table', 'expecting table from: '.. var)
@ -77,7 +78,7 @@ function expand(str, ...)
push(searchlist, 1, false)
for _,elem in ipairs(tab) do
searchlist[1] = elem
push(R, estring(str))
push(R, estring(_str))
end
pop(searchlist, 1)
pop(searchlist, 1)
@ -106,15 +107,15 @@ function expand(str, ...)
if strfind(var, '^[_%a][_%w]*$') then -- ${vn}
return estring(tostring(search(var)))
end
local b,e,cmd = strfind(var, '^(%a+)%s.')
local _,e,cmd = strfind(var, '^(%a+)%s.')
if cmd == 'foreach' then -- ${foreach vn xxx} or ${foreach vn/sep/xxx}
local vn,s
b,e,vn,s = strfind(var, '^([_%a][_%w]*)([%s%p]).', e)
_,e,vn,s = strfind(var, '^([_%a][_%w]*)([%s%p]).', e)
if vn then
if strfind(s, '%s') then
return elist(var, vn, strsub(var, e), '')
end
b = strfind(var, s, e, true)
local b = strfind(var, s, e, true)
if b then
return elist(var, vn, strsub(var, b+1), strsub(var,e,b-1))
end
@ -122,7 +123,7 @@ function expand(str, ...)
error('syntax error in: '.. var, 2)
elseif cmd == 'when' then -- $(when vn xxx)
local vn
b,e,vn = strfind(var, '^([_%a][_%w]*)%s.', e)
_,e,vn = strfind(var, '^([_%a][_%w]*)%s.', e)
if vn then
local t = search(vn)
if not t then

@ -1,5 +1,5 @@
--
-- Copyright 2013 SipWise Team <development@sipwise.com>
-- Copyright 2013-2020 SipWise Team <development@sipwise.com>
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
@ -17,16 +17,13 @@
-- On Debian systems, the complete text of the GNU General
-- Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".
--
require 'ngcp-klish.expand'
require 'ngcp-klish.configs'
local expand = require 'ngcp-klish.expand'
local cfg = require 'ngcp-klish.configs'
local MP = require 'ngcp-klish.rtpengine'
local URI = require 'uri'
require 'ngcp-klish.utils'
local ut = require 'ngcp-klish.utils'
local function uri_get_username(str)
local uri = URI:new(str)
return uri:username()
end
-- This is not a module!! list of commands:
-- luacheck: globals cc_stats cc_list cc_details reg_stats reg_info
-- templates
local templates = {
@ -93,7 +90,6 @@ local patterns = {
-- get the stats info
local function cc_stats_info()
local k,v
local prog_call='ngcp-kamctl proxy fifo dlg.profile_get_size'
local args = { total="", peerout="", internal="type", incoming="type" }
local stats = {
@ -102,9 +98,16 @@ local function cc_stats_info()
internal=-1, incoming=-1
}
-- get a temporary file name
local foutput_name = os.tmpname()
for k,v in pairs(args) do
local val, line
local foutput = io.popen (string.format('%s %s %s', prog_call, v, k), 'r')
local cmd = string.format('%s %s %s > %s', prog_call, v, k, foutput_name)
if(os.execute(cmd) ~= 0) then
os.remove(foutput_name)
error(string.format("error executing command %s", cmd))
end
local foutput = io.open(foutput_name, 'r')
for line in foutput:lines() do
for val in string.gmatch(line, patterns.cc_stats[k]) do
stats[k] = tonumber(val)
@ -112,6 +115,7 @@ local function cc_stats_info()
end
foutput:close()
end
os.remove(foutput_name)
return stats
end
@ -145,8 +149,8 @@ end
local function cc_list_prepare(t)
local f = {
callid=t.callid,
caller=uri_get_username(t.from_uri),
callee=uri_get_username(t.to_uri),
caller=ut.uri_get_username(t.from_uri),
callee=ut.uri_get_username(t.to_uri),
date=os.date('%Y/%m/%d %H:%M:%S', t.timestart),
peer='',
rtp_ports=rtp_info_prepare(t),
@ -160,7 +164,7 @@ local function dlg_info(foutput)
local result = {}
local temp,count
for line in foutput:lines() do
if string.starts(line,'hash') then
if ut.string.starts(line,'hash') then
if temp then result[temp.callid] = temp end
temp = {}; count = 0
end
@ -215,9 +219,9 @@ end
--get the dlg info for the callid
local function call_info(callid, rtp_info)
local prog_call='ngcp-kamcmd proxy dlg.dlg_list'
local foutput, result = {}
for k,v in pairs(rtp_info) do
foutput = io.popen (string.format('%s %s %s', prog_call, callid, k), 'r')
local result = {}
for k,_ in pairs(rtp_info) do
local foutput = io.popen (string.format('%s %s %s', prog_call, callid, k), 'r')
result = dlg_info(foutput)
if result[callid] then
result[callid]["rtp_info"] = rtp_info
@ -254,11 +258,9 @@ function cc_details(callid)
end
function reg_stats()
local k,v
local prog_call="ngcp-kamctl proxy fifo stats.get_statistics usrloc registered_users | jq '.[0]'"
local stats = {}
local val, line
local foutput = io.popen (string.format('%s', prog_call), 'r')
for line in foutput:lines() do
for val in string.gmatch(line, patterns.reg_stats.reg_users) do
@ -266,14 +268,13 @@ function reg_stats()
end
end
foutput:close()
stats.users = get_users()
stats.users = cfg.get_users()
print(expand(templates.reg_stats, stats))
end
function reg_info(aor)
local prog_call='ngcp-kamcmd proxy ul.lookup location'
local result = {}
local line, val, k, p
local count = 0
local foutput = io.popen (string.format('%s %s', prog_call, aor), 'r')

@ -1,5 +1,5 @@
--
-- Copyright 2013 SipWise Team <development@sipwise.com>
-- Copyright 2013-2020 SipWise Team <development@sipwise.com>
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
@ -23,13 +23,10 @@ local M = {}
-- importing
local math = math
local string = string
local io = io
local socket = require "socket"
require "ngcp-klish.bencode"
-- debug
local utils = require "ngcp-klish.utils"
-- forcing error on globals
_ENV = nil
local bencode = require "ngcp-klish.bencode"
function M:new(o)
o = o or {_ip='127.0.0.1', _port=2223}
@ -47,7 +44,7 @@ function M:server(host)
end
function M:port(port)
self._port = assert(tonumber())
self._port = assert(tonumber(port))
end
function M:cookie()
@ -89,13 +86,13 @@ function M:ping()
return false
end
function M:offer()
function M.offer()
end
function M:answer()
function M.answer()
end
function M:delete()
function M.delete()
end
function M:query(callid, from_tag, to_tag)
@ -106,7 +103,7 @@ function M:query(callid, from_tag, to_tag)
return _send(self, 'query', param)
end
function M:start_recording()
function M.start_recording()
end
-- end module

@ -1,5 +1,5 @@
--
-- Copyright 2013 SipWise Team <development@sipwise.com>
-- Copyright 2013-2020 SipWise Team <development@sipwise.com>
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
@ -18,26 +18,28 @@
-- Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".
--
local utils = { table = {}, string = {}}
-- copy a table
function table.deepcopy(object)
function utils.table.deepcopy(object)
local lookup_table = {}
local function _copy(object)
if type(object) ~= "table" then
return object
elseif lookup_table[object] then
return lookup_table[object]
local function _copy(obj)
if type(obj) ~= "table" then
return obj
elseif lookup_table[obj] then
return lookup_table[obj]
end
local new_table = {}
lookup_table[object] = new_table
for index, value in pairs(object) do
lookup_table[obj] = new_table
for index, value in pairs(obj) do
new_table[_copy(index)] = _copy(value)
end
return setmetatable(new_table, getmetatable(object))
return setmetatable(new_table, getmetatable(obj))
end
return _copy(object)
end
function table.contains(table, element)
function utils.table.contains(table, element)
if table then
for _, value in pairs(table) do
if value == element then
@ -49,13 +51,13 @@ function table.contains(table, element)
end
-- add if element is not in table
function table.add(t, element)
if not table.contains(t, element) then
function utils.table.add(t, element)
if not utils.table.contains(t, element) then
table.insert(t, element)
end
end
function table.val_to_str( v )
function utils.table.val_to_str( v )
if "string" == type( v ) then
v = string.gsub( v, "\n", "\\n" )
if string.match( string.gsub(v,"[^'\"]",""), '^"+$' ) then
@ -63,29 +65,29 @@ function table.val_to_str( v )
end
return '"' .. string.gsub(v,'"', '\\"' ) .. '"'
else
return "table" == type( v ) and table.tostring( v ) or
return "table" == type( v ) and utils.table.tostring( v ) or
tostring( v )
end
end
function table.key_to_str ( k )
function utils.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 ) .. "]"
return "[" .. utils.table.val_to_str( k ) .. "]"
end
end
function table.tostring( tbl )
function utils.table.tostring( tbl )
local result, done = {}, {}
for k, v in ipairs( tbl ) do
table.insert( result, table.val_to_str( v ) )
table.insert( result, utils.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 ) )
utils.table.key_to_str( k ) .. "=" .. utils.table.val_to_str( v ) )
end
end
return "{" .. table.concat( result, "," ) .. "}"
@ -97,7 +99,7 @@ end
-- "'a','b'"
-- implode("#",t)
-- "a#b"
function implode(delimiter, list, quoter)
function utils.implode(delimiter, list, quoter)
local len = #list
if not delimiter then
error("delimiter is nil")
@ -116,7 +118,7 @@ function implode(delimiter, list, quoter)
end
-- from string to table
function explode(delimiter, text)
function utils.explode(delimiter, text)
local list = {}
local pos = 1
@ -144,52 +146,55 @@ function explode(delimiter, text)
return list
end
function string.starts(String,Start)
function utils.string.starts(String,Start)
return string.sub(String,1,string.len(Start))==Start
end
function string.ends(String,End)
function utils.string.ends(String,End)
return End=='' or string.sub(String,-string.len(End))==End
end
function utils.uri_get_username(str)
return str:match('sip:([^@]+)')
end
-- Stack Table
-- Uses a table as stack, use <table>:push(value) and <table>:pop()
-- Lua 5.1 compatible
-- GLOBAL
Stack = {
utils.Stack = {
__class__ = 'Stack'
}
Stack_MT = {
local Stack_MT = {
__tostring = function(t)
return table.tostring(Stack.list(t))
return utils.table.tostring(utils.Stack.list(t))
end,
-- this works only on Lua5.2
__len = function(t)
return Stack.size(t)
return utils.Stack.size(t)
end,
__index = function(t,k)
if type(k) == 'number' then
return Stack.get(t,k)
return utils.Stack.get(t,k)
end
return rawget(Stack,k)
return rawget(utils.Stack,k)
end,
__newindex = function(t,k,v)
if type(k) == 'number' then
Stack.set(t,k,v)
utils.Stack.set(t,k,v)
end
end
}
-- Create a Table with stack functions
function Stack:new()
function utils.Stack.new()
local t = { _et = {} }
setmetatable(t, Stack_MT)
return t
end
-- push a value on to the stack
function Stack:push(...)
function utils.Stack:push(...)
if ... then
local targs = {...}
-- add values
@ -200,15 +205,15 @@ Stack_MT = {
end
-- pop a value from the stack
function Stack:pop(num)
function utils.Stack:pop(num)
-- get num values from stack
local num = num or 1
local _num = num or 1
-- return table
local entries = {}
-- get values into entries
for i = 1, num do
for _ = 1, _num do
-- get last entry
if #self._et ~= 0 then
table.insert(entries, self._et[#self._et])
@ -223,7 +228,7 @@ Stack_MT = {
end
-- get pos ( starts on 0)
function Stack:get(pos)
function utils.Stack:get(pos)
assert(pos)
assert(pos>=0)
local indx = #self._et - pos
@ -233,7 +238,7 @@ Stack_MT = {
end
-- set a value in a pos (stars on 0)
function Stack:set(pos, value)
function utils.Stack:set(pos, value)
assert(pos)
assert(pos>=0)
local indx = #self._et - pos
@ -247,12 +252,12 @@ Stack_MT = {
end
-- get entries
function Stack:size()
function utils.Stack:size()
return #self._et
end
-- list values
function Stack:list()
function utils.Stack:list()
local entries = {}
for i = #self._et, 1, -1 do
table.insert(entries, self._et[i])
@ -260,4 +265,6 @@ Stack_MT = {
return entries
end
-- end class
return utils
--EOF

@ -0,0 +1,65 @@
--
-- Copyright 2020 SipWise Team <development@sipwise.com>
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This package is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
-- .
-- On Debian systems, the complete text of the GNU General
-- Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".
--
describe("bencode", function()
local bencode
setup(function()
bencode = require("ngcp-klish.bencode")
end)
it("should encode a number", function()
assert.same('i345e', bencode.encode(345))
end)
it("should encode a string", function()
assert.same('7:g5323_1', bencode.encode('g5323_1'))
end)
it("should encode a list of numbers", function()
assert.same('li1ei2ei3ee', bencode.encode({1,2,3}))
end)
it("should encode a dict with mixed values",function()
assert.same(
'd3:dosi2e4:tres5:three3:unoi1ee',
bencode.encode({uno=1,dos=2,tres='three'})
)
end)
it("should decode a number", function()
assert.same(345, bencode.decode('i345e'))
end)
it("should decode a string", function()
assert.same('g5323_1', bencode.decode('7:g5323_1'))
end)
it("should decode a list of numbers", function()
assert.same({1,2,3}, bencode.decode('li1ei2ei3ee'))
end)
it("should decode a dict with mixed values",function()
assert.same(
{uno=1,dos=2,tres='three'},
bencode.decode('d3:dosi2e4:tres5:three3:unoi1ee')
)
end)
end)

@ -0,0 +1,156 @@
--
-- Copyright 2020 SipWise Team <development@sipwise.com>
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This package is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
-- .
-- On Debian systems, the complete text of the GNU General
-- Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".
--
local assert = require("luassert")
local say = require("say")
-- https://github.com/bluebird75/luaunit/blob/master/luaunit.lua
local function _is_table_equals(actual, expected, cycleDetectTable)
local type_a, type_e = type(actual), type(expected)
if type_a ~= type_e then
return false -- different types won't match
end
if type_a ~= 'table' then
-- other typtes compare directly
return actual == expected
end
cycleDetectTable = cycleDetectTable or { actual={}, expected={} }
if cycleDetectTable.actual[ actual ] then
-- oh, we hit a cycle in actual
if cycleDetectTable.expected[ expected ] then
-- uh, we hit a cycle at the same time in expected
-- so the two tables have similar structure
return true
end
-- cycle was hit only in actual, the structure differs from expected
return false
end
if cycleDetectTable.expected[ expected ] then
-- no cycle in actual, but cycle in expected
-- the structure differ
return false
end
-- at this point, no table cycle detected, we are
-- seeing this table for the first time
-- mark the cycle detection
cycleDetectTable.actual[ actual ] = true
cycleDetectTable.expected[ expected ] = true
local actualKeysMatched = {}
for k, v in pairs(actual) do
actualKeysMatched[k] = true -- Keep track of matched keys
if not _is_table_equals(v, expected[k], cycleDetectTable) then
-- table differs on this key
-- clear the cycle detection before returning
cycleDetectTable.actual[ actual ] = nil
cycleDetectTable.expected[ expected ] = nil
return false
end
end
for k, _ in pairs(expected) do
if not actualKeysMatched[k] then
-- Found a key that we did not see in "actual" -> mismatch
-- clear the cycle detection before returning
cycleDetectTable.actual[ actual ] = nil
cycleDetectTable.expected[ expected ] = nil
return false
end
-- Otherwise actual[k] was already matched against v = expected[k].
end
-- all key match, we have a match !
cycleDetectTable.actual[ actual ] = nil
cycleDetectTable.expected[ expected ] = nil
return true
end
local is_equal = _is_table_equals
local function table_findkeyof(t, element)
-- Return the key k of the given element in table t, so that t[k] == element
-- (or `nil` if element is not present within t). Note that we use our
-- 'general' is_equal comparison for matching, so this function should
-- handle table-type elements gracefully and consistently.
if type(t) == "table" then
for k, v in pairs(t) do
if is_equal(v, element) then
return k
end
end
end
return nil
end
local function _is_table_items_equals(actual, expected )
local type_a, type_e = type(actual), type(expected)
if type_a ~= type_e then
return false
elseif (type_a == 'table') --[[and (type_e == 'table')]] then
for _, v in pairs(actual) do
if table_findkeyof(expected, v) == nil then
return false -- v not contained in expected
end
end
for _, v in pairs(expected) do
if table_findkeyof(actual, v) == nil then
return false -- v not contained in actual
end
end
return true
elseif actual ~= expected then
return false
end
return true
end
--- end
local function set_failure_message(state, message)
if message ~= nil then
state.failure_message = message
end
end
local function equal_items(state, arguments)
if _is_table_items_equals(arguments[1], arguments[2]) then
return true
end
set_failure_message(state, arguments[3])
return false
end
say:set_namespace("en")
say:set("assertion.equal_items.positive",
"Expected objects have same items.\nPassed in:\n%s\nExpected:\n%s")
say:set("assertion.equal_items.negative",
"Expected objects don't have same items.\nPassed in:\n%s\nDid not expect:\n%s")
assert:register("assertion", "equal_items", equal_items,
"assertion.equal_items.positive", "assertion.equal_items.negative")

@ -0,0 +1,140 @@
--
-- Copyright 2020 SipWise Team <development@sipwise.com>
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This package is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
-- .
-- On Debian systems, the complete text of the GNU General
-- Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".
--
local bencode = require 'ngcp-klish.bencode'
local function msg_decode(received)
local _,q = string.find(received, '^([^_]+_%d+)')
local seq, message
if q then
seq = received:sub(1,q)
message = received:sub(q+2)
end
return seq, assert(bencode.decode(message))
end
local function msg_encode(seq, type, command, param)
local message = {}
message[type] = command
if not param then param = {} end
for k,v in pairs(param) do
message[k]=v
end
message = assert(bencode.encode(message))
return string.format('%s %s', seq, message)
end
describe("helper functions", function()
it("should encode", function()
assert.same(
'5323_1 d7:command4:pinge',
msg_encode("5323_1", 'command', 'ping')
)
end)
it("should decode", function()
local seq, msg = msg_decode('5323_1 d6:result4:ponge')
assert.same('5323_1', seq)
assert.same({result='pong'}, msg)
end)
end)
describe("rtpengine", function()
local rtp, mp
local socket
setup(function()
end)
before_each(function()
socket = {
dns = {
toip = true
},
udp = true
}
package.loaded['ngcp-klish.rtpengine'] = nil
package.loaded.socket = nil
package.preload['socket'] = function ()
return socket
end
rtp = require("ngcp-klish.rtpengine")
mp = rtp:new()
end)
it("should provide uniq cookies", function()
assert.same(tostring(mp._uniq).."_1", mp:cookie())
assert.same(tostring(mp._uniq).."_2", mp:cookie())
end)
it("should resolve host when server is called", function()
socket.dns.toip = function(server)
assert.same("fake.local", server)
return "172.0.0.1"
end
assert.same('127.0.0.1', mp._ip)
mp:server("fake.local")
assert.same('172.0.0.1', mp._ip)
end)
it("should have a default port", function()
assert.same(2223, mp._port)
end)
it("should support ping command", function()
local cookie = tostring(mp._uniq).."_1"
local message = msg_encode(cookie, 'command', 'ping')
local response = msg_encode(cookie, 'result', 'pong')
local t = {
sendto = function(_, msg, ip, port)
assert.same(message, msg)
assert.same(mp._ip, ip)
assert.same(mp._port, port)
return true
end,
receive = function(_) return(response) end
}
socket.udp = function() return t end
assert.is_true(mp:ping())
end)
it("should support query command", function()
local cookie = tostring(mp._uniq).."_1"
local param = {}
param['call-id'] = 'callid1'
local message = msg_encode(cookie, 'command', 'query', param)
-- luacheck: ignore
local respose_param = {created=1381997760,totals={input={rtcp={bytes=11054,packets=113,errors=0},rtp={bytes=3909179,packets=26195,errors=0}},output={rtcp={bytes=9048,packets=116,errors=0},rtp={bytes=0,packets=0,errors=0}}},streams={{{status="confirmed peer address",codec="unknown",stats={rtcp={counters={bytes=10976,packets=112,errors=0},["local port"]=30001,["advertised peer address"]={family="IPv4",port=50005,address="10.15.20.191"},["peer address"]={family="IPv4",port=50005,address="10.15.20.191"}},rtp={counters={bytes=3908936,packets=26194,errors=0},["local port"]=30000,["advertised peer address"]={family="IPv4",port=50004,address="10.15.20.191"},["peer address"]={family="IPv4",port=50004,address="10.15.20.191"}}},
tag="callid1"},{status="known but unconfirmed peer address",stats={rtcp={counters={bytes=8970,packets=115,errors=0},["local port"]=30003,["advertised peer address"]={family="IPv4",port=50007,address="10.15.20.191"},["peer address"]={family="IPv4",port=50007,address="10.15.20.191"}},rtp={counters={bytes=0,packets=0,errors=0},["local port"]=30002,["advertised peer address"]={family="IPv4",port=50006,address="10.15.20.191"},["peer address"]={family="IPv4",port=50006,address="10.15.20.191"}}},tag="7A4FE68B-525F9CC000060653-E28A0700"}},{{status="known but unconfirmed peer address",codec="unknown",stats={rtcp={counters={bytes=78,packets=1,errors=0},["local port"]=0,["advertised peer address"]={family="IPv6",port=0,address="::"},["peer address"]={family="IPv6",port=0,address="::"}},rtp={counters={bytes=243,packets=1,errors=0},["local port"]=0,["advertised peer address"]={family="IPv6",port=0,address="::"},["peer address"]={family="IPv6",port=0,address="::"}}},tag=""},{status="known but unconfirmed peer address",stats={rtcp={counters={bytes=78,packets=1,errors=0},["local port"]=0,["advertised peer address"]={family="IPv6",port=0,address="::"},["peer address"]={family="IPv6",port=0,address="::"}},rtp={counters={bytes=0,packets=0,errors=0},["local port"]=0,["advertised peer address"]={family="IPv6",port=0,address="::"},["peer address"]={family="IPv6",port=0,address="::"}}},tag=""}}}}
local response = msg_encode(cookie, 'result', 'ok', respose_param)
local t = {
sendto = function(_, msg, ip, port)
assert.same(message, msg)
assert.same(mp._ip, ip)
assert.same(mp._port, port)
return true
end,
receive = function(_) return(response) end
}
socket.udp = function() return t end
assert.same('ok', mp:query('callid1').result)
end)
end)

@ -0,0 +1,172 @@
--
-- Copyright 2020 SipWise Team <development@sipwise.com>
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This package is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
-- .
-- On Debian systems, the complete text of the GNU General
-- Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".
--
describe("utils", function()
local ut
local simple_hash
local simple_list
local complex_hash
setup(function()
ut = require("ngcp-klish.utils")
end)
before_each(function()
simple_hash = {
one = 1, two = 2, three = 3
}
simple_list = {
1, 2, 3
}
complex_hash = {
cone = simple_list,
ctwo = simple_hash
}
end)
describe("table", function()
it("deepcopy", function()
local res = ut.table.deepcopy(simple_hash)
assert.same(res, simple_hash)
assert.is_not(res, simple_hash)
end)
it("contains should find the value", function()
assert.True(ut.table.contains(simple_hash, 3))
end)
it("contains should not find the value", function()
assert.False(ut.table.contains(simple_hash, 4))
end)
it("contains should not find anything in nil", function()
assert.False(ut.table.contains(nil))
end)
it("contains should throw an error with a string", function()
local f = function()
ut.table.contains("hola", 1)
end
assert.has_error(f,
"bad argument #1 to 'pairs' (table expected, got string)")
end)
it("add", function ()
assert.same(simple_list, {1,2,3})
ut.table.add(simple_list, 1)
assert.same(simple_list, {1,2,3})
ut.table.add(simple_list, 5)
assert.same(simple_list, {1,2,3,5})
ut.table.add(simple_list, 4)
assert.same(simple_list, {1,2,3,5,4})
end)
it("tostring", function()
local f = function()
ut.table.tostring("nil")
end
assert.has_error(f)
assert.same(ut.table.tostring(simple_list), "{1,2,3}")
assert.not_nil(ut.table.tostring(simple_hash))
assert.not_nil(ut.table.tostring(complex_hash))
end)
end) -- end table
it("implode", function()
assert.same(ut.implode(',', simple_list, "'"), "'1','2','3'")
end)
it("implode should error with nil string", function()
local f = function()
ut.implode(nil, simple_list, "'")
end
assert.has_error(f)
end)
it("implode should error with nil table", function()
local f = function()
ut.implode(',', nil, "'")
end
assert.has_error(f)
end)
it("explode", function()
assert.equal_items(ut.explode(',',"1,2,3"), {'1','2','3'})
assert.equal_items(ut.explode('=>',"1=>2=>3"), {'1','2','3'})
end)
describe("string", function()
it("starts should error with nil", function()
local f = function()
ut.string.stats(nil, "g")
end
assert.has_error(f)
assert.has_error(function() ut.string.stats("goga", nil) end)
end)
it("starts", function()
assert.True(ut.string.starts("goga", "g"))
assert.True(ut.string.starts("goga", "go"))
assert.True(ut.string.starts("goga", "gog"))
assert.True(ut.string.starts("goga", "goga"))
assert.False(ut.string.starts("goga", "a"))
assert.True(ut.string.starts("$goga", "$"))
assert.True(ut.string.starts("(goga)", "("))
end)
it("ends should error with nil", function()
assert.has_error(function() ut.string.ends(nil, "g") end)
assert.has_error(function() ut.string.ends("goga", nil) end)
end)
it("ends", function()
assert.True(ut.string.ends("goga", "a"))
assert.True(ut.string.ends("goga", "ga"))
assert.True(ut.string.ends("goga", "oga"))
assert.True(ut.string.ends("goga", "goga"))
assert.False(ut.string.ends("goga", "f"))
end)
end) -- end string
describe("uri_get_username", function()
it("should wotk with dns", function()
assert.same(
'vseva',
ut.uri_get_username('sip:vseva@fake.local')
)
end)
it("should wotk with ipv4", function()
assert.same(
'vseva',
ut.uri_get_username('sip:vseva@127.0.0.1:50602')
)
end)
it("should wotk with ipv6", function()
local t = 'sip:vseva@[2620:0:2ef0:7070:250:60ff:fe03:32b7]:5060;transport=tcp'
assert.same(
'vseva',
ut.uri_get_username(t)
)
end)
end)
end)

@ -5,22 +5,16 @@ FROM docker.mgm.sipwise.com/sipwise-buster:latest
# is updated with the current date. It will force refresh of all
# of the base images and things like `apt-get update` won't be using
# old cached versions when the Dockerfile is built.
ENV REFRESHED_AT 2020-04-03
# files that get-code generates
COPY t/sources.list.d/builddeps.list /etc/apt/sources.list.d/
COPY t/sources.list.d/preferences /etc/apt/preferences.d/
ENV REFRESHED_AT 2020-05-20
RUN apt-get update && \
apt-get install --assume-yes \
jq \
lua-unit \
lua-lemock \
lua-busted \
lua-dbi-mysql \
lua-socket \
lua-uri \
lua-yaml \
lua5.1
lua5.2
RUN echo './t/testrunner' >>/root/.bash_history
@ -32,12 +26,6 @@ WORKDIR /code/
# To build the base image from scratch (or jump to the next section if
# you do not want to build it yourself):
#
# You need to put the proper NGCP sources at t/sources.list.d/builddeps.list
# for instance, trunk:
#
# % echo "deb https://deb.sipwise.com/autobuild/ release-trunk-buster main" \
# >t/sources.list.d/builddeps.list
#
# % docker build --tag="ngcp-klish-config-buster" -f t/Dockerfile .
# % docker run --rm -i -t -v $(pwd):/code:rw ngcp-klish-config-buster:latest bash
#

@ -1,57 +0,0 @@
--
-- Copyright 2013 SipWise Team <development@sipwise.com>
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This package is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
-- .
-- On Debian systems, the complete text of the GNU General
-- Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".
--
require 'luaunit'
require 'ngcp-klish.bencode'
Test = {}
function Test:test_encode_number()
assertEquals(bencode.encode(345), 'i345e')
end
function Test:test_encode_string()
assertEquals(bencode.encode('g5323_1'), '7:g5323_1')
end
function Test:test_encode_list()
assertEquals(bencode.encode({1,2,3}),
'li1ei2ei3ee')
end
function Test:test_encode_dict()
assertEquals(bencode.encode({uno=1,dos=2,tres='three'}),
'd3:dosi2e4:tres5:three3:unoi1ee')
end
function Test:test_decode_number()
assertEquals(bencode.decode('i345e'), 345)
end
function Test:test_decode_string()
assertEquals(bencode.decode('7:g5323_1'), 'g5323_1')
end
function Test:test_decode_list()
assertEquals(bencode.decode('li1ei2ei3ee'), {1,2,3})
end
function Test:test_decode_dict()
assertEquals(bencode.decode('d3:dosi2e4:tres5:three3:unoi1ee'),
{uno=1,dos=2,tres='three'})
end

@ -1,130 +0,0 @@
--
-- Copyright 2013 SipWise Team <development@sipwise.com>
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This package is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
-- .
-- On Debian systems, the complete text of the GNU General
-- Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".
--
require 'luaunit'
require 'lemock'
require 'ngcp-klish.bencode'
local mc, udp, socket
local MP
local function msg_decode(received)
local _,q = string.find(received, '^([^_]+_%d+)')
local seq, message
if q then
seq = received:sub(1,q)
message = received:sub(q+2)
end
return seq, assert(bencode.decode(message))
end
local function msg_encode(seq, type, command, param)
local message = {}
message[type] = command
if not param then param = {} end
for k,v in pairs(param) do
message[k]=v
end
message = assert(bencode.encode(message))
return string.format('%s %s', seq, message)
end
Test = {}
function Test:test_encode()
assertEquals('5323_1 d7:command4:pinge',
msg_encode("5323_1", 'command', 'ping'))
end
function Test:test_decode()
local seq, msg = msg_decode('5323_1 d6:result4:ponge')
assertEquals(seq, '5323_1')
assertEquals(msg, {result='pong'})
end
TestMP = {}
function TestMP:setUp()
mc = lemock.controller()
udp = mc:mock()
socket = {
dns={ toip=mc:mock() },
udp= udp
}
package.loaded['ngcp-klish.rtpengine'] = nil
package.loaded.socket = nil
package.preload['socket'] = function ()
return socket
end
MP = require 'ngcp-klish.rtpengine'
self.mp = MP:new()
end
function TestMP:test()
assertEquals(self.mp:cookie(), tostring(self.mp._uniq).."_1")
assertEquals(self.mp:cookie(), tostring(self.mp._uniq).."_2")
end
function TestMP:test_host()
-- default
assertEquals(self.mp._ip, '127.0.0.1')
socket.dns.toip('localhost') ;mc :returns('127.0.0.1')
mc:replay()
self.mp:server('localhost')
mc:verify()
assertEquals(self.mp._ip, '127.0.0.1')
end
function TestMP:test_port()
-- default
assertEquals(self.mp._port, 2223)
end
function TestMP:test_ping()
local cookie = tostring(self.mp._uniq).."_1"
local message = msg_encode(cookie, 'command', 'ping')
local response = msg_encode(cookie, 'result', 'pong')
socket.udp() ;mc :returns(udp)
udp:sendto(message, self.mp._ip, self.mp._port) ;mc :returns(true)
udp:receive() ;mc :returns(response)
mc:replay()
local res = self.mp:ping()
mc:verify()
assertTrue(res)
end
function TestMP:test_query()
local cookie = tostring(self.mp._uniq).."_1"
local param = {}
param['call-id'] = 'callid1'
local message = msg_encode(cookie, 'command', 'query', param)
local respose_param = {created=1381997760,totals={input={rtcp={bytes=11054,packets=113,errors=0},rtp={bytes=3909179,packets=26195,errors=0}},output={rtcp={bytes=9048,packets=116,errors=0},rtp={bytes=0,packets=0,errors=0}}},streams={{{status="confirmed peer address",codec="unknown",stats={rtcp={counters={bytes=10976,packets=112,errors=0},["local port"]=30001,["advertised peer address"]={family="IPv4",port=50005,address="10.15.20.191"},["peer address"]={family="IPv4",port=50005,address="10.15.20.191"}},rtp={counters={bytes=3908936,packets=26194,errors=0},["local port"]=30000,["advertised peer address"]={family="IPv4",port=50004,address="10.15.20.191"},["peer address"]={family="IPv4",port=50004,address="10.15.20.191"}}},
tag="callid1"},{status="known but unconfirmed peer address",stats={rtcp={counters={bytes=8970,packets=115,errors=0},["local port"]=30003,["advertised peer address"]={family="IPv4",port=50007,address="10.15.20.191"},["peer address"]={family="IPv4",port=50007,address="10.15.20.191"}},rtp={counters={bytes=0,packets=0,errors=0},["local port"]=30002,["advertised peer address"]={family="IPv4",port=50006,address="10.15.20.191"},["peer address"]={family="IPv4",port=50006,address="10.15.20.191"}}},tag="7A4FE68B-525F9CC000060653-E28A0700"}},{{status="known but unconfirmed peer address",codec="unknown",stats={rtcp={counters={bytes=78,packets=1,errors=0},["local port"]=0,["advertised peer address"]={family="IPv6",port=0,address="::"},["peer address"]={family="IPv6",port=0,address="::"}},rtp={counters={bytes=243,packets=1,errors=0},["local port"]=0,["advertised peer address"]={family="IPv6",port=0,address="::"},["peer address"]={family="IPv6",port=0,address="::"}}},tag=""},{status="known but unconfirmed peer address",stats={rtcp={counters={bytes=78,packets=1,errors=0},["local port"]=0,["advertised peer address"]={family="IPv6",port=0,address="::"},["peer address"]={family="IPv6",port=0,address="::"}},rtp={counters={bytes=0,packets=0,errors=0},["local port"]=0,["advertised peer address"]={family="IPv6",port=0,address="::"},["peer address"]={family="IPv6",port=0,address="::"}}},tag=""}}}}
local response = msg_encode(cookie, 'result', 'ok', respose_param)
socket.udp() ;mc :returns(udp)
udp:sendto(message, self.mp._ip, self.mp._port) ;mc :returns(true)
udp:receive() ;mc :returns(response)
mc:replay()
local res = self.mp:query('callid1')
mc:verify()
assertEquals(res.result,'ok')
end

@ -1,94 +1,19 @@
#!/bin/bash
set -u
# This script is used for running the tests with proper arguments
# from within Jenkins
PASS=0
FAIL=0
ID=0
LUA=${LUA:-lua5.1}
RESULTS=${RESULTS:-./results}
set -e
set -u
set -x
if [ -d /results ]; then
if [ -d /results ] ; then
# Running from Jenkins (RW)
RESULTS="/results"
FORMAT=JUNIT
cd "/code"
else
# Running locally in Docker
FORMAT=TAP
RESULTS="./results"
mkdir -p "${RESULTS}"
fi
case ${FORMAT} in
TAP) EXT=tap; OUT_FORCE=true ;;
JUNIT) EXT=xml; OUT_FORCE=false ;;
TEXT) EXT=txt; OUT_FORCE=true ;;
*) echo "ERROR: Unknown format ${FORMAT}"; exit 1 ;;
esac
# unique id across files
# See TT#4590
function fix_id() {
(( ID += 1))
local tmp_id
tmp_id=$(printf "%05d\\n" "$ID")
sed -i "s/id=\"00001\"/id=\"$tmp_id\"/" "$1"
}
function run_test() {
local tmpfile=$1
local output=$2
if ${OUT_FORCE} ; then
${LUA} - <"${tmpfile}" > "${output}"
else
${LUA} - --name "${output}" <"${tmpfile}"
fi
return $?
}
function do_test() {
local name="$1"
local RES="${RESULTS}/${name}.${EXT}"
local tmpfile
tmpfile=$(mktemp)
echo -n "testing ${name} -> ${RES}:"
cat >"${tmpfile}" <<EOF
EXPORT_ASSERT_TO_GLOBALS = true
require "t/${name}"
---- Control test output:
local lu = LuaUnit
lu:setOutputType('${FORMAT}')
os.exit(lu:run())
EOF
if run_test "${tmpfile}" "${RES}"; then
((PASS++))
echo "OK"
else
((FAIL++))
echo "FAIL"
fi
if [[ "${FORMAT}" == JUNIT ]] ; then
fix_id "${RES}"
fi
rm -f "${tmpfile}"
}
rm -rf "${RESULTS:-./results}"/*
if [[ -z "$*" ]]; then
mapfile -t TESTS < <(find t -name '*.lua' -exec basename {} .lua \;)
for t in "${TESTS[@]}"; do
do_test "$t"
done
else
for t in "${@}"; do
do_test "$(basename "${t}" .lua)"
done
fi
echo
echo "Finished test execution: ${PASS} passed, ${FAIL} failed"
echo "Test results available at ${RESULTS}"
busted -o junit > ${RESULTS}/test_busted.xml

@ -1,31 +0,0 @@
--
-- Copyright 2013 SipWise Team <development@sipwise.com>
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This package is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
-- .
-- On Debian systems, the complete text of the GNU General
-- Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".
--
require('luaunit')
local URI = require "uri"
TestUri = {}
function TestUri:test()
local u = URI:new('sip:username1:password@domain.com:5080;user=phone?header1=value1&header2=value2')
assertEquals(u:username(), 'username1')
assertEquals(u:port(), 5080)
assertEquals(u:host(), 'domain.com')
assertEquals(u:fragment(), 'user=phone')
assertEquals(u:query(), 'header1=value1&header2=value2')
end

@ -1,223 +0,0 @@
--
-- Copyright 2013 SipWise Team <development@sipwise.com>
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This package is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
-- .
-- On Debian systems, the complete text of the GNU General
-- Public License version 3 can be found in "/usr/share/common-licenses/GPL-3".
--
require('luaunit')
require 'ngcp-klish.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()
assertNotIs(table.deepcopy(self.simple_hash), self.simple_hash)
-- if the parameter is not a table... it has to be the same
assertIs(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_add()
assertEquals(self.simple_list, {1,2,3})
table.add(self.simple_list, 1)
assertEquals(self.simple_list, {1,2,3})
table.add(self.simple_list, 5)
assertEquals(self.simple_list, {1,2,3,5})
table.add(self.simple_list, 4)
assertEquals(self.simple_list, {1,2,3,5,4})
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'})
assertItemsEquals(explode('=>',"1=>2=>3"), {'1','2','3'})
end
function TestUtils:test_starts()
assertError(string.stats, nil, "g")
assertTrue(string.starts("goga", "g"))
assertTrue(string.starts("goga", "go"))
assertTrue(string.starts("goga", "gog"))
assertTrue(string.starts("goga", "goga"))
assertFalse(string.starts("goga", "a"))
assertError(string.starts, "goga", nil)
assertTrue(string.starts("$goga", "$"))
assertTrue(string.starts("(goga)", "("))
end
function TestUtils:test_ends()
assertError(string.ends, nil, "g")
assertTrue(string.ends("goga", "a"))
assertTrue(string.ends("goga", "ga"))
assertTrue(string.ends("goga", "oga"))
assertTrue(string.ends("goga", "goga"))
assertFalse(string.ends("goga", "f"))
assertError(string.ends, "goga", nil)
end
-- class TestUtils
TestStack = {}
function TestStack:test()
local s = Stack:new()
assertEquals(type(s), 'table')
assertEquals(s.__class__, 'Stack')
end
function TestStack:test_size()
local s = Stack:new()
assertEquals(s:size(),0)
s:push(1)
assertEquals(s:size(),1)
s:pop()
assertEquals(s:size(),0)
end
function TestStack:test_push()
local s s = Stack:new()
s:push(1)
assertEquals(s:size(),1)
end
function TestStack:test_pop()
local s = Stack:new()
assertEquals(s:pop(), nil)
s:push(1)
assertEquals(s:size(),1)
assertEquals(s:pop(),1)
assertEquals(s:size(),0)
end
function TestStack:test_get()
local s = Stack:new()
s:push(1)
assertEquals(s:get(0),1)
s:push({1,2,3})
assertEquals(s:get(0),{1,2,3})
assertEquals(s:get(1),1)
assertError(s.get, s, -1)
assertIsNil(s:get(2))
end
function TestStack:test_get_op()
local s = Stack:new()
s:push(1)
assertEquals(s[0],1)
s:push({1,2,3})
assertEquals(s[0],{1,2,3})
assertEquals(s[1],1)
assertIsNil(s[2])
end
function TestStack:test_set()
local s = Stack:new()
s:push(1)
s:push({1,2,3})
assertEquals(s:size(),2)
assertEquals(s:get(0),{1,2,3})
assertEquals(s:get(1),1)
s:set(1, 2)
assertEquals(s:size(),2)
assertEquals(s:get(0),{1,2,3})
assertEquals(s:get(1),2)
s:set(2, 3)
assertEquals(s:size(),2)
assertEquals(s:get(0),{1,2,3})
assertEquals(s:get(1),2)
assertIsNil(s:get(2))
assertError(s.set, s, "no", -1)
assertError(s.set, s, -1, 2)
end
function TestStack:test_set_op()
local s = Stack:new()
s:push(1)
s:push({1,2,3})
assertEquals(s:size(),2)
assertEquals(s:get(0),{1,2,3})
assertEquals(s:get(1),1)
s[1] = 2
assertEquals(s:size(),2)
assertEquals(s:get(0),{1,2,3})
assertEquals(s:get(1),2)
s[0] = "new"
assertEquals(s:size(),2)
assertEquals(s:get(0),"new")
assertEquals(s:get(1),2)
s[1] = "old"
assertEquals(s:get(0),"new")
assertEquals(s:get(1),"old")
assertEquals(s:size(),2)
s[2] = "error"
assertEquals(s:get(0),"new")
assertEquals(s:get(1),"old")
assertIsNil(s:get(2))
assertEquals(s:size(),2)
end
function TestStack:test_list()
local s = Stack:new()
local l = s:list()
assertEquals(#l, 0)
s:push(1)
s:push({1,2,3})
assertEquals(s:size(),2)
l = s:list()
assertItemsEquals(l[1],{1,2,3})
assertEquals(l[2],1)
assertEquals(s:size(),2)
end
function TestStack:test_tostring()
local s = Stack:new()
s:push(1)
assertEquals(tostring(s), "{1}")
s:push(2)
assertEquals(tostring(s), "{2,1}")
end
-- class TestStack
--EOF
Loading…
Cancel
Save