Test RTP Lua Agent

Introduction

The TestRtpLuaAgent is an asynchronous helper for LUA scripts running within the LogicApp. It is used for performing RTP Testing. This agent exists primarily to support the automated regression testing of the N-Squared family of SIP/RTP products (the N2SIP framework).

The agent supports the ability to automate testing of:

The agent does not currently support the ability to send RTP audio stream packets into N2SIP.

The agent does not currently support the ability to send or receive RTCP.

The TestRtpLuaAgent communicates with one or more instances of the TestRtpApp which performs the RTP packet send/receive over UDP.

The TestRtpLuaAgent communicates with the TestRtpApp using the TEST-RTP-… messages.

The TestRtpLuaAgent is tied to the test_rtp action key.

The N-Squared application with which we exchange the RTP Requests and Responses is the RtpApp, although in theory any external RTP endpoint can be tested using this library.

Configuring TestRtpLuaAgent

The TestRtpLuaAgent is configured within a LogicApp.

    <?xml version="1.0" encoding="utf-8"?>
    <n2svcd>
      ...
      <applications>
        ...
        <application name="Logic" module="LogicApp">
          <include>
            <lib>../apps/logic/lib</lib>
          </include>
          <parameters>
            ...
            <parameter name="default_test_rtp_app_name" value="TestRtpApp"/>
          </parameters>
          <config>
            <services>
              ...
            </services>
            <agents>
              <agent module="TestRtpApp::TestRtpLuaAgent" libs="../../n2sip/apps/test_rtp/lib"/>
            </agents>
          </config>
        </application>
        ...
      </application>
      ...
    </n2svcd>

Under normal installation, following agent attributes apply:

Attribute Type XML Type Description
module TestRtpApp::TestRtpLuaAgent Attribute [Required] The module name containing the Test RTP Agent code.
libs ../../n2sip/apps/test_rtp/lib Element Location of the module for TestRtpLuaAgent.
expect_secs Integer Attribute The number of seconds to wait for an inbound message (or no-message).
This value is set globally and currently cannot be controlled on a per-request basis.
(Default = 10 seconds).

In addition, the TestRtpLuaAgent must be configured with the name of the TestRtpApp with which it will communicate. This is configured within the parameters of the containing LogicApp.

Attribute Type Description
parameters Array Array of name = value Parameters for this Application instance.
.default_test_rtp_app_name String Default name for the TestRtpApp to which TestRtpLuaAgent will send test instructions and receive test inputs.

The TestRtpLuaAgent API

All methods may raise a LUA Error in the case of exception, including:

Complete Example

A LUA Script can access the TestRtpLuaAgent test_rtp action with code such as the following.

This example uses the Test SIP Agent to set up a SIP call which establishes an RTP stream, during which digit collection is performed:

local n2svcd         = require "n2.n2svcd"
local utils          = require "n2.utils"
local match          = require "n2.n2svcd.tester.match"
local manage         = require "n2.n2svcd.tester.manage"
local edr_file_agent = require "n2.n2svcd.edr_file_agent"
local tsuo           = require "n2.n2svcd.tester.test_sip_agent"
local truo           = require "n2.n2svcd.tester.test_rtp_agent"

local args = ...

-- Register our local RTP port.
local result = truo.register ()
local rtp_listener_port = result.local_port

-- Basic call parameters.
local endpoints = tsuo.default_endpoints ({ local_rtp_port = rtp_listener_port })
local calling_party = '665566'
local called_party = '8000'
local context = tsuo.invite_context (endpoints, calling_party, called_party)
local sdp_offer = tsuo.sdp_offer (context, tsuo.SDP_MEDIA_LINPHONE)

-- INVITE.
local tv = match.elapsed ()
tsuo.invite_send_request (context, sdp_offer, { { name = 'Scenario', value = '801' } })
tsuo.invite_expect_response (context, 100, "Trying")

-- 200 OK.
local response = tsuo.invite_expect_response (context, 200, "OK", nil, { sdp_media = tsuo.SDP_MEDIA_LINPHONE_U })
tv = match.elapsed ("Call Answered (immediate)", tv, 0)
tsuo.invite_send_2xx_ack (context)

-- Request our RTP tester to connect to the far-end IP/port.  Now we can send RTP as well as receive it.
truo.connect (response.sdp.connection.ip4.address, response.sdp.media.audio.port)

-- The prompt is 3.6s long.  We start entering digits (telephone-event ID 102) after 2 seconds.
n2svcd.wait (2.0)

-- This should interrupt the announcement and start the spooling of silence until we're finished.
truo.send_telephone_event (102, truo.DIGIT_CODES['1'], 200)
n2svcd.wait (0.4)
truo.send_telephone_event (102, truo.DIGIT_CODES['2'], 210)
n2svcd.wait (0.4)
truo.send_telephone_event (102, truo.DIGIT_CODES['3'], 190)
n2svcd.wait (0.4)
truo.send_telephone_event (102, truo.DIGIT_CODES['4'], 990)
-- That last digit will take 1 second to complete.
-- Then we get the variable part announcement.
-- Then we get the goodbye announcement.

tsuo.bye_expect_request (context)
tv = match.elapsed ("PACUI Script Ends (8.35s)", tv, 8.35, 8.55)

-- Construct and Send ACK Request suitable for the 200 response we received.
-- The LHO is now in PLAYING state (waiting for the ARI).
tsuo.bye_send_response (context, 200, "OK")

-- Define list of expected announcements and silence we expect in our buffer.
local expected_rtp_config = {
    encoding = 'PCMU/8000',
    fragments = {
        { files = { 'English/announcements/Enter_Amount.ul' }, min = 2.15, max = 2.3 },
        { silence_min = 1.94, silence_max = 2.1 },
        { files = {
                'English/announcements/You_Entered.ul',
                'English/variable_parts/1.ul',
                'English/variable_parts/2.ul',
                'English/variable_parts/3.ul',
                'English/variable_parts/4.ul',
            }
        },
        { silence_min = 0, silence_max = 0.1 },
        { files = { 'English/announcements/Goodbye.ul' } },
        { silence_min = 0, silence_max = 0.1 },
    }
}
-- Trigger a collection of RTP packets and match against the expected configuration.
truo.fetch_and_match (expected_rtp_config);

Endpoint Setup

At the start of each stream, we must negotiate with the Test RTP Agent to specify the UDP port numbers and IP addresses that will be used in each direction.

Refer to the RTP Endpoint Setup methods.

Stream Sending

The test library supports the ability to send telephone-event RTP packets, and to send AMR wideband stream attribute change packets. It is not currently possible to send audio data to the remote endpoint using this library.

Refer to the RTP Send methods.

Stream Matching

Audio stream packets sent to the tester by the remote endpoint are cached in a buffer until such time as the tester may be ready to validate them. The test library provides a method which will retrieve all of the received/cached audio packets and validate them against an expected audio stream.

Refer to the RTP Stream Matching methods.