2014-04-30 53 views
1

我試圖測試我們的Freeswitch lua腳本與busted和我遇到了一個障礙。它的要點是,我需要能夠對間諜的代碼類似於下面的測試與破壞lua腳本

local req_host = session:getVariable('sip_req_host') 
session:setVariable('curl_timeout', 0) 

但我似乎無法弄清楚如何建立,我應該設置_G.session對象。關於如何使用被破壞的最好的/唯一的好例子是https://github.com/chris-allnutt/unit-tested-corona/blob/master/mocks/button.lua,但它似乎使用相同的簡單語法來構建一個被破壞的文檔所做的模擬對象。

local button = { 
    x = 0, 
    y = 0, 
    addEventListener = function() end 
} 

我可以看到這是如何爲不需要任何回報的簡單功能的工作,但我需要能夠獲得和使用的getVariable和setVariable功能會話對象設置變量。我簡單的模擬對象如下:

Session = {} 
Session.__index = Session 

function Session.create(params) 
    local session = {} 
    setmetatable(session, Session) 
    session.params = params 
    return session 
end 

function Session:getVariable(key) 
    return self.params[key] 
end 

function Session:setVariable(key, val) 
    self.params[key] = val 
end 

function Session:execute(cmd, code) 
end 

和試驗如下

require "busted" 
require("test_utils") 

describe("Test voip lua script", function() 
    it('Test webrtc bad domain', function() 
    domain = 'rtc.baddomain.com'; 
    session_params = {['sip_req_host'] = domain, 
         ['sip_req_user'] = 'TEST-WebRTC-Client', 
         ["sip_from_user"] = 'testwebrtc_p_12345', 
         ['sip_call_id'] = '[email protected]_id', 
         ['sip_authorized'] = 'false'} 
    exec_str = 'sofia_contact [email protected]'..domain; 
    api_params = {[exec_str] = 'error/user_not_registered'} 

    _G.session = mock(Session.create(session_params), 'execute') 
    _G.api = API.create(api_params) 
    _G.freeswitch = Freeswitch.create() 

    dofile("tested_script.lua") 

    assert.spy(_G.session.execute).called_with("respond", "407") 
    end) 
end) 

我結束了以下情況例外。 /usr/local/share/lua/5.2/luassert/spy.lua:78:試圖指數函數值

此異常是由luassert,在破獲庫的依賴拋出,在if語句如下

77:local function called_with(state, arguments) 
78: if rawget(state, "payload") and rawget(state, "payload").called_with then 
79: return state.payload:called_with(arguments) 
80: else 
81: error("'called_with' must be chained after 'spy(aspy)'") 
82: end 
83:end 

我是很新的LUA所以它很可能是我只是缺少語言的一些明顯的部分,但任何幫助或指針將不勝感激。

+0

是spy.lua與最後一個代碼片段的文件?如果是的話,哪一行是78行?如果不是什麼是spy.lua的第78行? –

+0

我編輯我的帖子以添加相關的行。整個文件位於https://github.com/Olivine-Labs/luassert/blob/master/src/spy.lua – user3587406

回答

1

因此,經過另一天的調試後發現的答案是,您確實需要使用表格作爲您調用的模擬對象。然而,因爲lua在構建具有可調用參數的對象時是一種非常寬容的語言,所以這仍然會起作用。由於與此問題無關的原因,我在對象周圍構建了一個包裝器,但您可以看到我最終在下面做了什麼。

function SessionConstructor.create(params) 
    local session_constructor = {} 
    setmetatable(session_constructor, SessionConstructor) 
    session_constructor.session = {} 
    session_constructor.session.params = params 
    session_constructor.session.getVariable = function(self,key) 
    return self.params[key] 
    end 
    session_constructor.session.setVariable = function(self, key, val) 
    self.params[key] = val 
    end 
    session_constructor.session.execute = function(self, cmd, code) 
    end 

    return session_constructor 
end 

function SessionConstructor:construct() 
    return self.session 
end 

一個重要的警告,因爲你怎麼也得自通入將與Lua的調用函數「」語法刺探叫什麼功能與確實發生了改變,如下面的測試文件中看到的方法。

require "busted" 
require "test_utils" 

describe("Test voip lua script", function() 
    it('Test webrtc bad domain', function() 
    domain = 'rtc.baddomain.com'; 
    session_params = {['sip_req_host'] = domain, 
         ['sip_req_user'] = 'TEST-WebRTC-Client', 
         ["sip_from_user"] = 'testwebrtc_p_12345', 
         ['sip_call_id'] = '[email protected]_id', 
         ['sip_authorized'] = 'false'} 
    local sess_con = SessionConstructor.create(session_params) 

    exec_str = 'sofia_contact [email protected]'..domain;  
    local api_con = APIConstructor.create() 
    api_con:expect_exec(exec_str, 'error/user_not_registered') 

    _G.session = mock(sess_con:construct()) 
    _G.api = mock(api_con:construct()) 
    _G.freeswitch = create_freeswitch() 

    dofile("tested_script.lua") 

    assert.spy(session.execute).was.called_with(session, "respond", "407") 
    assert.spy(session.execute).was_not.called_with("respond", "407") --This is unfortunate 
    end) 
end) 
1

FreeSWITCH中的mod_lua使用稍微定製的Lua解釋器,並且您似乎使用安裝在主機上的不同Lua解釋器。我猜他們不會輕易合作。

0

我做了busted斌腳本的一些逆向工程,並來到了下面的腳本(我們稱之爲runner.lua):

busted = require 'busted.core'() 
local environment = require 'busted.environment'(busted.context) 

function unpack(t, i) 
    i = i or 1 
    if t[i] ~= nil then 
    return t[i], unpack(t, i + 1) 
    end 
end 
busted.getTrace = function(element, level, msg) 
    level = level or 3 

    local info = debug.getinfo(level, 'Sl') 
    info.traceback = debug.traceback('', level) 
    info.message = msg 
    if msg ~= nil then 
     freeswitch.consoleLog("NOTICE", msg) 
    end 

    local file = busted.getFile(element) 
    return file.getTrace(file.name, info) 
end 

busted.safe = function(descriptor, run, element, setenv) 
    if setenv and (type(run) == 'function' or getmetatable(run).__call) then 
     -- prioritize __call if it exists, like in files 
     environment.wrap(getmetatable(run).__call or run) 
    end 

    busted.context.push(element) 
    local trace, message 

    local ret = { xpcall(run, function(msg) 
     message = busted.rewriteMessage(element, msg) 
     freeswitch.consoleLog("ERR", message) 
     trace = busted.getTrace(element, 3, msg) 
    end) } 

    if not ret[1] then 
     busted.publish({ 'error', descriptor }, element, busted.context.parent(element), message, trace) 
    end 

    busted.context.pop() 
    return unpack(ret) 
end 
require 'busted.init'(busted) 

local checkTag = function(name, tag, modifier) 
    local found = name:find('#' .. tag)   
    return (modifier == (found ~= nil))   
end           

local checkTags = function(name)    
    for i, tag in pairs(tags) do     
    if not checkTag(name, tag, true) then  
     return nil, false      
    end          
    end           

    for i, tag in pairs(excludeTags) do   
    if not checkTag(name, tag, false) then  
     return nil, false      
    end          
    end           

    return nil, true        
end   

local getTrace = function(filename, info)  
    local index = info.traceback:find('\n%s*%[C]') 
    info.traceback = info.traceback:sub(1, index) 
    return info, false        
end            

local file = setmetatable({ 
    getTrace = getTrace 
}, { 
    __call = loadfile("/path/scripts/main_spec.lua") 
}) 
busted.executors.file("main_spec.lua", file) 

local failures = 0      
local errors = 0       

busted.subscribe({ 'error' }, function() 
    errors = errors + 1     
end)          

busted.subscribe({ 'test', 'end' }, function(element, parent, status) 
    if status == 'failure' then        
    failures = failures + 1         
    end              
end)               

busted.publish({ 'suite', 'start' }) 
busted.execute() 
busted.publish({ 'suite', 'end' }) 
freeswitch.consoleLog("NOTICE", "Failures: " .. failures) 
freeswitch.consoleLog("NOTICE", "Errors: " .. errors) 

該腳本對一個文件而已,/path/scripts/main_spec.lua的事情,但仍然可用。 你可以用這個runner.lua腳本做什麼,與luarun從FreeSWITCH的控制檯運行它:

fs_cli 
luarun /path/to/runner.lua 

,你會得到輸出那裏。