From 3a60d1b57467b26da22266c6ced62d858d059502 Mon Sep 17 00:00:00 2001 From: Victor Seva Date: Sat, 19 Jul 2014 13:09:53 +0200 Subject: [PATCH] MT#8243 add NGCPDlgCounters class. TODO: tests doesn't play nice with redis mocks. Not activated. --- debian/control | 3 +- ngcp/dlgcnt.lua | 134 ++++++++++++++++++++++++++++++++ ngcp/utils.lua | 27 ++++++- tests/ngcp_dlgcnt.lua | 176 ++++++++++++++++++++++++++++++++++++++++++ tests/utils.lua | 30 ++++++- 5 files changed, 365 insertions(+), 5 deletions(-) create mode 100644 ngcp/dlgcnt.lua create mode 100644 tests/ngcp_dlgcnt.lua diff --git a/debian/control b/debian/control index 65f743c..7e8e2e6 100644 --- a/debian/control +++ b/debian/control @@ -11,7 +11,8 @@ Package: lua-ngcp-kamailio Section: libs Architecture: any Pre-Depends: ngcp-system-tools -Depends: lua-sql-mysql, +Depends: lua-redis, + lua-sql-mysql, ${misc:Depends}, ${shlibs:Depends} Provides: ${lua:Provides} diff --git a/ngcp/dlgcnt.lua b/ngcp/dlgcnt.lua new file mode 100644 index 0000000..070858c --- /dev/null +++ b/ngcp/dlgcnt.lua @@ -0,0 +1,134 @@ +-- +-- Copyright 2014 SipWise Team +-- +-- 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 . +-- . +-- 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 NGCPDlgCounters = { + __class__ = 'NGCPDlgCounters' +} +local redis = require 'redis'; +require 'ngcp.utils'; + +_ENV = NGCPDlgCounters + +-- class NGCPDlgCounters +local NGCPDlgCounters_MT = { __index = NGCPDlgCounters } + +NGCPDlgCounters_MT.__tostring = function (t) + return string.format("config:%s central:%s pair:%s", + table.tostring(t.config), table.tostring(t.central), + table.tostring(t.pair)); +end + + function NGCPDlgCounters.new() + local t = NGCPDlgCounters.init(); + setmetatable( t, NGCPDlgCounters_MT ); + return t; + end + + function NGCPDlgCounters.init() + local t = { + config = { + central = { + host = '127.0.0.1', + port = 6379, + db = "3" + }, + pair = { + host = '127.0.0.1', + port = 6379, + db = "4" + } + }, + central = {}, + pair = {} + }; + return t; + end + + function NGCPDlgCounters._test_connection(client) + if not client then return nil end + local ok, err = pcall(client.ping, client); + return ok + end + + function NGCPDlgCounters._connect(config) + local client = redis.connect(config.host,config.port); + client:select(config.db); + sr.log("dbg", string.format("connected to redis server %s:%d at %s\n", + config.host, config.port, config.db)); + return client; + end + + function NGCPDlgCounters:set(callid, key) + if not self._test_connection(self.central) then + self.central = self._connect(self.config.central); + end + local res = self.central:incr(key); + sr.log("dbg", string.format("central:incr[%s]=>%s\n", key, res)); + if not self._test_connection(self.pair) then + self.pair = self._connect(self.config.pair); + end + local pos = self.pair:lpush(callid, key); + sr.log("dbg", string.format("pair:lpush[%s]=>[%s] %s\n", callid, key, pos)); + end + + function NGCPDlgCounters:del_key(callid, key) + if not self._test_connection(self.pair) then + self.pair = self._connect(self.config.pair); + end + local num = self.pair:lrem(callid, 0, key); + sr.log("dbg", string.format("pair:lrem[%s]=>[%s] %d\n", callid, key, num)); + if not self._test_connection(self.central) then + self.central = self._connect(self.config.central); + end + local res = self.central:decr(key); + sr.log("dbg", string.format("central:decr[%s]=>[%s]\n", key, res)); + end + + function NGCPDlgCounters:del(callid) + if not self._test_connection(self.pair) then + self.pair = self._connect(self.config.pair); + end + local key = self.pair:lpop(callid); + if not key then + error(string.format("callid:%s list empty", callid)); + end + if not self._test_connection(self.central) then + self.central = self._connect(self.config.central); + end + local res; + while key do + res = self.central:decr(key); + sr.log("dbg", string.format("central:decr[%s]=>[%s]\n", key, res)); + sr.log("dbg", string.format("pair:lpop[%s]=>[%s]\n", callid, key)); + key = self.pair:lpop(callid); + end + end + + function NGCPDlgCounters:get(key) + if not self._test_connection(self.central) then + self.central = self._connect(self.config.central); + end + local res = self.central:get(key); + sr.log("dbg", string.format("central:get[%s]=>%s\n", key, res)); + return res; + end +-- class + +return NGCPDlgCounters +--EOF diff --git a/ngcp/utils.lua b/ngcp/utils.lua index cad5991..18b95d4 100644 --- a/ngcp/utils.lua +++ b/ngcp/utils.lua @@ -57,9 +57,9 @@ function table.deepcopy(object) return _copy(object) end -function table.contains(table, element) - if table then - for _, value in pairs(table) do +function table.contains(t, element) + if t then + for _, value in pairs(t) do if value == element then return true end @@ -75,6 +75,26 @@ function table.add(t, element) end end +function table.del(t, element) + local _,v,i + local pos = {} + + if t then + i = 1 + for _, v in pairs(t) do + if v == element then + table.insert(pos, i) + end + i = i + 1 + end + i = 0 + for _,v in ipairs(pos) do + table.remove(t, v-i) + i = i + 1 + end + end +end + function table.val_to_str ( v ) if "string" == type( v ) then v = string.gsub( v, "\n", "\\n" ) @@ -98,6 +118,7 @@ end function table.tostring( tbl ) local result, done = {}, {} + if not tbl then return "nil" end for k, v in ipairs( tbl ) do table.insert( result, table.val_to_str( v ) ) done[ k ] = true diff --git a/tests/ngcp_dlgcnt.lua b/tests/ngcp_dlgcnt.lua new file mode 100644 index 0000000..c2fe38a --- /dev/null +++ b/tests/ngcp_dlgcnt.lua @@ -0,0 +1,176 @@ +-- +-- Copyright 2014 SipWise Team +-- +-- 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 . +-- . +-- 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 lemock = require('lemock') +require('luaunit') +require 'ngcp.utils' + +if not sr then + require 'mocks.sr' + sr = srMock:new() +else + argv = {} +end + +local mc + +TestNGCPDlgCnt = {} --class + + function TestNGCPDlgCnt:setUp() + mc = lemock.controller() + self.fake_redis = mc:mock() + self.central = mc:mock() + self.pair = mc:mock() + + package.loaded.redis = self.fake_redis + local NGCPDlg = require 'ngcp.dlgcnt' + + self.dlg = NGCPDlg.new() + assertTrue(self.dlg) + + self.dlg.central = self.central; + self.dlg.pair = self.pair + end + + function TestNGCPDlgCnt:test_connection_ok() + local prev = self.central + self.central:ping() ;mc :returns(true) + + mc:replay() + local ok = self.dlg._test_connection(self.central) + mc:verify() + + assertTrue(ok) + assertIs(prev, self.central) + end + + function TestNGCPDlgCnt:test_connection_fail() + local prev = self.central + self.central:ping() ;mc :error("error") + + mc:replay() + local res = self.dlg._test_connection(self.central) + mc:verify() + + assertFalse(res) + assertIs(prev, self.central) + end + + function TestNGCPDlgCnt:test_connect_ok() + local c = self.dlg.config + self.fake_redis.connect(c.pair.host,c.pair.port) ;mc :returns(self.pair) + self.pair:select(c.pair.db) ;mc :returns(true) + + mc:replay() + local res = self.dlg._connect(c.pair) + mc:verify() + assertIs(res, self.pair) + end + + function TestNGCPDlgCnt:test_set_1() + local c = self.dlg.config + self.central:ping() ;mc :error("error") + self.fake_redis.connect(c.central.host,c.central.port) ;mc :returns(self.central) + self.central:select(c.central.db) ;mc :returns(true) + self.central:incr("total") ;mc :returns(1) + + self.pair:ping() ;mc :error("error") + self.fake_redis.connect(c.pair.host,c.pair.port) ;mc :returns(self.pair) + self.pair:select(c.pair.db) ;mc :returns(true) + self.pair:lpush("callid0", "total") ;mc :returns(1) + + mc:replay() + self.dlg:set("callid0", "total") + mc:verify() + end + + function TestNGCPDlgCnt:test_set_2() + local c = self.dlg.config + self.central:ping() ;mc :error("error") + self.fake_redis.connect(c.central.host,c.central.port) ;mc :returns(self.central) + self.central:select(c.central.db) ;mc :returns(true) + self.central:incr("total") ;mc :returns(1) + + self.pair:ping() ;mc :error("error") + self.fake_redis.connect(c.pair.host,c.pair.port) ;mc :returns(self.pair) + self.pair:select(c.pair.db) ;mc :returns(true) + self.pair:lpush("callid0", "total") ;mc :returns(1) + + self.central.ping(self.central) ;mc :returns(true) + self.pair:ping() ;mc :returns(true) + self.central:incr("total") ;mc :returns(2) + self.pair:lpush("callid1", "total") ;mc :returns(1) + + mc:replay() + self.dlg:set("callid0", "total") + self.dlg:set("callid1", "total") + mc:verify() + end + + function TestNGCPDlgCnt:test_del() + local c = self.dlg.config + self.pair:ping() ;mc :error("error") + self.fake_redis.connect(c.pair.host,c.pair.port) ;mc :returns(self.pair) + self.pair:select(c.pair.db) ;mc :returns(true) + self.pair:lpop("callid0") ;mc :returns("total") + self.pair:lpop("callid0") ;mc :returns(nil) + + self.central:ping() ;mc :error("error") + self.fake_redis.connect(c.central.host,c.central.port) ;mc :returns(self.central) + self.central:select(c.central.db) ;mc :returns(true) + self.central:decr("total") ;mc :returns(1) + + mc:replay() + self.dlg:del("callid0") + mc:verify() + + assertIs(self.dlg.central, self.central) + assertIs(self.dlg.pair, self.pair) + end + + function TestNGCPDlgCnt:test_del_multy() + local c = self.dlg.config + self.pair:ping() ;mc :error("error") + self.fake_redis.connect(c.pair.host,c.pair.port) ;mc :returns(self.pair) + self.pair:select(c.pair.db) ;mc :returns(true) + self.pair:lpop("callid0") ;mc :returns("total") + + self.central:ping() ;mc :error("error") + self.fake_redis.connect(c.central.host,c.central.port) ;mc :returns(self.central) + self.central:select(c.central.db) ;mc :returns(true) + self.central:decr("total") ;mc :returns(0) + + self.pair:lpop("callid0") ;mc :returns("whatever:gogo") + self.central:decr("whatever:gogo") ;mc :returns(0) + + self.pair:lpop("callid0") ;mc :returns("whatever:go") + self.central:decr("whatever:go") ;mc :returns(0) + + self.pair:lpop("callid0") ;mc :returns(nil) + + mc:replay() + self.dlg:del("callid0") + mc:verify() + + assertIs(self.dlg.central, self.central) + assertIs(self.dlg.pair, self.pair) + end + +-- class TestNGCPDlgCnt +--EOF diff --git a/tests/utils.lua b/tests/utils.lua index 0815d8a..8f348d1 100644 --- a/tests/utils.lua +++ b/tests/utils.lua @@ -58,6 +58,34 @@ TestUtils = {} --class assertEquals(self.simple_list, {1,2,3,5,4}) end + function TestUtils:test_table_del() + assertEquals(self.simple_list, {1,2,3}) + table.del(self.simple_list, 1) + assertEquals(self.simple_list, {2,3}) + table.del(self.simple_list, 3) + assertEquals(self.simple_list, {2}) + table.del(self.simple_list, 2) + assertEquals(self.simple_list, {}) + end + + function TestUtils:test_table_del_multy() + assertEquals(self.simple_list, {1,2,3}) + table.insert(self.simple_list, 2) + assertEquals(self.simple_list, {1,2,3,2}) + table.del(self.simple_list, 1) + assertEquals(self.simple_list, {2,3,2}) + table.del(self.simple_list, 2) + assertEquals(self.simple_list, {3}) + table.del(self.simple_list, 3) + assertEquals(self.simple_list, {}) + end + + function TestUtils:test_table_del_empty() + local t = {} + table.del(t, 4) + assertEquals(t, {}) + end + function TestUtils:test_table_shuffle() assertEquals(self.simple_list, {1,2,3}) table.add(self.simple_list, 4) @@ -102,7 +130,7 @@ TestUtils = {} --class end function TestUtils:test_table_tostring() - assertError(table.tostring,nil) + 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")