[svn-commits] mmichelson: testsuite/asterisk/trunk r6282 - in /asterisk/trunk: lib/python/a...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Wed Jan 14 15:15:50 CST 2015


Author: mmichelson
Date: Wed Jan 14 15:15:42 2015
New Revision: 6282

URL: http://svnview.digium.com/svn/testsuite?view=rev&rev=6282
Log:
Add a test for remote attended transfers.

This sets up two Asterisk boxes and a single PJSUA "phone". The PJSUA
endpoint has simultaneous conversations with parties on both Asterisk boxes
and places an attended transfer in order to link the Asterisk boxes directly
together. This test ensures that it goes smoothly.

Review: https://reviewboard.asterisk.org/r/4317


Added:
    asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/
    asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/configs/
    asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/configs/ast1/
    asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/configs/ast1/extensions.conf   (with props)
    asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/configs/ast1/pjsip.conf   (with props)
    asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/configs/ast2/
    asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/configs/ast2/extensions.conf   (with props)
    asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/configs/ast2/pjsip.conf   (with props)
    asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/test-config.yaml   (with props)
    asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/transfer.py   (with props)
Modified:
    asterisk/trunk/lib/python/asterisk/pjsua_mod.py
    asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/tests.yaml

Modified: asterisk/trunk/lib/python/asterisk/pjsua_mod.py
URL: http://svnview.digium.com/svn/testsuite/asterisk/trunk/lib/python/asterisk/pjsua_mod.py?view=diff&rev=6282&r1=6281&r2=6282
==============================================================================
--- asterisk/trunk/lib/python/asterisk/pjsua_mod.py (original)
+++ asterisk/trunk/lib/python/asterisk/pjsua_mod.py Wed Jan 14 15:15:42 2015
@@ -113,7 +113,7 @@
         self.lib = None
         self.num_regs = 0
         self.num_accts = 0
-        self.ami = None
+        self.ami_connected = 0
         self.callback_module = instance_config['callback_module']
         self.callback_method = instance_config['callback_method']
 
@@ -124,7 +124,13 @@
         We use AMI connection as the signal to start creating PJSUA accounts
         and starting PJLIB.
         """
-        self.ami = ami
+        self.ami_connected += 1
+        if (self.ami_connected < len(self.test_object.ami)):
+            LOGGER.info("{0} ami connected. Waiting for "
+                        "{1}".format(self.ami_connected,
+                                     len(self.test_object.ami)))
+            return
+
         self.lib = pj.Lib()
         try:
             self.lib.init()

Added: asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/configs/ast1/extensions.conf
URL: http://svnview.digium.com/svn/testsuite/asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/configs/ast1/extensions.conf?view=auto&rev=6282
==============================================================================
--- asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/configs/ast1/extensions.conf (added)
+++ asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/configs/ast1/extensions.conf Wed Jan 14 15:15:42 2015
@@ -1,0 +1,9 @@
+[default]
+
+exten => echo,1,Answer()
+same => n,Echo()
+
+exten => bob,1,Dial(PJSIP/bob)
+
+exten => external_replaces,1,NoOp()
+same => n,Dial(PJSIP/asterisk2/${SIPREFERTOHDR})

Propchange: asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/configs/ast1/extensions.conf
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/configs/ast1/extensions.conf
------------------------------------------------------------------------------
    svn:keywords = 'Author Date Id Revision'

Propchange: asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/configs/ast1/extensions.conf
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/configs/ast1/pjsip.conf
URL: http://svnview.digium.com/svn/testsuite/asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/configs/ast1/pjsip.conf?view=auto&rev=6282
==============================================================================
--- asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/configs/ast1/pjsip.conf (added)
+++ asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/configs/ast1/pjsip.conf Wed Jan 14 15:15:42 2015
@@ -1,0 +1,23 @@
+[globals]
+type = global
+debug = yes
+
+[main-transport]
+type = transport
+protocol = udp
+bind = 127.0.0.1:5060
+
+[bob]
+type = endpoint
+context = default
+allow = ulaw
+aors = bob
+
+[bob]
+type = aor
+contact = sip:bob at 127.0.0.1:5062
+
+[asterisk2]
+type = endpoint
+allow = ulaw
+from_user = asterisk1

Propchange: asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/configs/ast1/pjsip.conf
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/configs/ast1/pjsip.conf
------------------------------------------------------------------------------
    svn:keywords = 'Author Date Id Revision'

Propchange: asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/configs/ast1/pjsip.conf
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/configs/ast2/extensions.conf
URL: http://svnview.digium.com/svn/testsuite/asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/configs/ast2/extensions.conf?view=auto&rev=6282
==============================================================================
--- asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/configs/ast2/extensions.conf (added)
+++ asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/configs/ast2/extensions.conf Wed Jan 14 15:15:42 2015
@@ -1,0 +1,6 @@
+[default]
+
+exten => echo,1,Dial(Local/echo2 at default)
+
+exten => echo2,1,Answer()
+same => n,Echo()

Propchange: asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/configs/ast2/extensions.conf
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/configs/ast2/extensions.conf
------------------------------------------------------------------------------
    svn:keywords = 'Author Date Id Revision'

Propchange: asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/configs/ast2/extensions.conf
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/configs/ast2/pjsip.conf
URL: http://svnview.digium.com/svn/testsuite/asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/configs/ast2/pjsip.conf?view=auto&rev=6282
==============================================================================
--- asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/configs/ast2/pjsip.conf (added)
+++ asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/configs/ast2/pjsip.conf Wed Jan 14 15:15:42 2015
@@ -1,0 +1,23 @@
+[global]
+type = global
+debug = yes
+
+[main-transport]
+type = transport
+protocol = udp
+bind = 127.0.0.1:5061
+
+[bob]
+type = endpoint
+context = default
+allow = ulaw
+aors = bob
+
+[bob]
+type = aor
+max_contacts = 1
+
+[asterisk1]
+type = endpoint
+allow = ulaw
+from_user = asterisk2

Propchange: asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/configs/ast2/pjsip.conf
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/configs/ast2/pjsip.conf
------------------------------------------------------------------------------
    svn:keywords = 'Author Date Id Revision'

Propchange: asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/configs/ast2/pjsip.conf
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/test-config.yaml
URL: http://svnview.digium.com/svn/testsuite/asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/test-config.yaml?view=auto&rev=6282
==============================================================================
--- asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/test-config.yaml (added)
+++ asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/test-config.yaml Wed Jan 14 15:15:42 2015
@@ -1,0 +1,89 @@
+testinfo:
+    summary: "Ensure that a nominal remote attended transfer works as expected."
+    description: |
+        "This test uses two Asterisk and a PJSUA instance to perform a remote attended
+        transfer. The PJSUA instance registers to Asterisk B, but Asterisk A has been
+        configured to be able to call the PJSUA instance directly.
+
+        Asterisk A originates a call. The first leg of the origination goes into the
+        dialplan and runs Echo(). The second leg of the origination places a call to
+        the PJSUA instance.
+
+        Once it is confirmed that Asterisk A and the PJSUA instance are bridged, the
+        PJSUA issues a call to Asterisk B. Asterisk B dials a local channel that runs
+        Echo().
+
+        Once it is confirmed that the PJSUA instance and Asterisk 2 are bridged, the
+        PJSUA instance performs an attended transfer. This results in the PJSUA instance
+        sending a REFER request to Asterisk A. Since the referenced dialog in the
+        REFER's Refer-To header is not in Asterisk A, Asterisk A must perform a remote
+        attended transfer.
+
+        A remote attended transfer, from the perspective of the Asterisk server that
+        is performing the transfer, actually appears to be a blind transfer, so a
+        BlindTransfer event is emitted during this transfer.
+
+        The end result should be that Asterisk A and Asterisk B are connected via SIP,
+        and the PJSUA instance has hung up.
+
+        This test kills two birds with one stone. Asterisk A is tested to ensure
+        that it properly handles a REFER that refers to a remote dialog. Asterisk B
+        is tested to ensure that it behaves correctly when receiving an INVITE with
+        replaces."
+
+test-modules:
+    add-test-to-search-path: True
+    test-object:
+        config-section: test-object-config
+        typename: test_case.TestCaseModule
+    modules:
+        -
+            config-section: pjsua-config
+            typename: 'pjsua_mod.PJsua'
+        -
+            config-section: ami-config
+            typename: 'ami.AMIEventModule'
+
+test-object-config:
+    connect-ami: True
+    asterisk-instances: 2
+
+pjsua-config:
+    callback_module: 'transfer'
+    callback_method: 'bob_registered'
+    transports:
+        -
+            name: 'local-ipv4'
+            bind: '127.0.0.1'
+            bindport: '5062'
+    accounts:
+        -
+            name: 'bob'
+            username: 'bob'
+            password: 'bob'
+            domain: '127.0.0.1:5061'
+
+ami-config:
+    -
+        type: 'headermatch'
+        id: '0'
+        conditions:
+            match:
+                Event: 'BlindTransfer'
+        requirements:
+            match:
+                TransfererChannel: 'PJSIP/bob-00000000'
+                TransfereeChannel: 'Local/echo at default-00000000;1'
+                Context: 'default'
+                Extension: 'external_replaces'
+
+properties:
+    minversion: '13.2.0'
+    dependencies:
+        - python: 'twisted'
+        - python: 'starpy'
+        - python: 'pjsua'
+        - asterisk: 'res_pjsip'
+        - asterisk: 'res_pjsip_session'
+        - asterisk: 'res_pjsip_refer'
+

Propchange: asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/test-config.yaml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/test-config.yaml
------------------------------------------------------------------------------
    svn:keywords = 'Author Date Id Revision'

Propchange: asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/test-config.yaml
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/transfer.py
URL: http://svnview.digium.com/svn/testsuite/asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/transfer.py?view=auto&rev=6282
==============================================================================
--- asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/transfer.py (added)
+++ asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/transfer.py Wed Jan 14 15:15:42 2015
@@ -1,0 +1,148 @@
+"""
+Copyright (C) 2014, Digium, Inc.
+Mark Michelson <mmichelson at digium.com>
+
+This program is free software, distributed under the terms of
+the GNU General Public License Version 2.
+"""
+
+import logging
+import pjsua as pj
+
+LOGGER = logging.getLogger(__name__)
+
+# Initial state. Bob has registered, but no calls have been placed yet.
+INITIAL = 0
+# Asterisk A has placed a call to Bob.
+BOB_CALLED = 1
+# Asterisk A and Bob are bridged, and now Bob has placed a call to Asterisk B.
+AST_B_CALLED = 2
+# Bob and Asterisk B are bridged, and Bob has now initiated the remote attended
+# transfer
+TRANSFER_INITIATED = 3
+# Asterisk A and Asterisk B are now bridged, and so the call is now being hung
+# up.
+HANGING_UP = 4
+
+class BobAccountCallback(pj.AccountCallback):
+    def __init__(self, account):
+        pj.AccountCallback.__init__(self, account)
+        self.incoming_call = None
+
+    def on_incoming_call(self, call):
+        LOGGER.info("Bob has incoming call from Asterisk A. Answering")
+        call.answer(200)
+        self.incoming_call = call
+
+
+class Transfer(object):
+    def __init__(self, test_object, bob):
+        super(Transfer, self).__init__()
+        self.ami_a = test_object.ami[0]
+
+        # BridgeEnter and BridgeLeave for Asterisk A are used to count the
+        # number of bridged channels. When two channels are bridged, then we
+        # know that a call is up and we can move on to the next state.
+        self.ami_a.registerEvent('BridgeEnter', self.ami_a_bridge_enter)
+        self.ami_a.registerEvent('BridgeLeave', self.ami_a_bridge_leave)
+        self.a_bridged_channels = 0
+
+        # BridgeEnter and BridgeLeave for Asterisk B are used for the same
+        # purposes as for Asterisk A.
+        self.ami_b = test_object.ami[1]
+        self.ami_b.registerEvent('BridgeEnter', self.ami_b_bridge_enter)
+        self.ami_b.registerEvent('BridgeLeave', self.ami_b_bridge_leave)
+        self.b_bridged_channels = 0
+
+        # Newchannel and Hangup events are used as a way of globally counting
+        # the number of channels on both Asterisk A and Asterisk B. We know the
+        # scenario can be stopped when the total number of channels reaches 0 on
+        # a hangup.
+        self.ami_a.registerEvent('Newchannel', self.ami_new_channel)
+        self.ami_b.registerEvent('Newchannel', self.ami_new_channel)
+        self.ami_a.registerEvent('Hangup', self.ami_hangup)
+        self.ami_b.registerEvent('Hangup', self.ami_hangup)
+        self.channels = 0
+
+        self.bob = bob
+        self.bob_callback = BobAccountCallback(self.bob)
+        self.bob.set_callback(self.bob_callback)
+        self.call_from_bob = None
+
+        self.test_object = test_object
+        self.state = INITIAL
+
+    def ami_a_bridge_enter(self, ami, event):
+        LOGGER.info("Asterisk A channel {0} entered "
+                    "bridge".format(event['channel']))
+
+        if self.state == BOB_CALLED:
+            self.a_bridged_channels += 1
+            if self.a_bridged_channels == 2:
+                LOGGER.info("Initial bridge complete, placing call from Bob to B")
+                self.call_from_bob = self.bob.make_call(
+                        'sip:echo at 127.0.0.1:5061', pj.CallCallback())
+                self.state = AST_B_CALLED
+        elif self.state == TRANSFER_INITIATED:
+            self.a_bridged_channels += 1
+            if self.a_bridged_channels == 2:
+                LOGGER.info("Second bridge complete, Hanging up call")
+                hangup_msg = {
+                    'Action': 'Hangup',
+                    'Channel': 'Local/echo at default-00000000;2',
+                }
+                self.ami_a.sendMessage(hangup_msg)
+                self.state = HANGING_UP
+        else:
+            LOGGER.error("Received BridgeEnter event during unexpected state "
+                         "{0}".format(self.state))
+
+    def ami_a_bridge_leave(self, ami, event):
+        LOGGER.info("Asterisk A channel {0} left "
+                    "bridge".format(event['channel']))
+        self.a_bridged_channels -= 1
+
+    def ami_b_bridge_enter(self, ami, event):
+        LOGGER.info("Asterisk B channel {0} entered "
+                    "bridge".format(event['channel']))
+
+        if self.state == AST_B_CALLED:
+            self.b_bridged_channels += 1
+            if self.b_bridged_channels == 2:
+                LOGGER.info("Initial bridge complete. Can now perform transfer")
+                self.bob_callback.incoming_call.transfer_to_call(self.call_from_bob)
+                self.state = TRANSFER_INITIATED
+
+    def ami_b_bridge_leave(self, ami, event):
+        LOGGER.info("Asterisk B channel {0} left "
+                    "bridge".format(event['channel']))
+        self.b_bridged_channels -= 1
+
+    def ami_new_channel(self, ami, event):
+        self.channels += 1
+
+    def ami_hangup(self, ami, event):
+        self.channels -= 1
+
+        if self.channels == 0:
+            LOGGER.info("All channels hung up! Ending Test")
+            self.test_object.set_passed(True)
+            self.test_object.stop_reactor()
+
+    def call_bob(self):
+        originate_msg = {
+            'Action': 'Originate',
+            'Channel': 'Local/echo at default',
+            'Exten': 'bob',
+            'Context': 'default',
+            'Priority': '1',
+        }
+        self.ami_a.sendMessage(originate_msg)
+        LOGGER.info("Placed call from Asterisk A to Bob")
+        self.state = BOB_CALLED
+
+
+def bob_registered(test_object, accounts):
+    transfer = Transfer(test_object, accounts.get('bob').account)
+    transfer.call_bob()
+

Propchange: asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/transfer.py
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/transfer.py
------------------------------------------------------------------------------
    svn:executable = *

Propchange: asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/transfer.py
------------------------------------------------------------------------------
    svn:keywords = 'Author Date Id Revision'

Propchange: asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/callee_remote/transfer.py
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/tests.yaml
URL: http://svnview.digium.com/svn/testsuite/asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/tests.yaml?view=diff&rev=6282&r1=6281&r2=6282
==============================================================================
--- asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/tests.yaml (original)
+++ asterisk/trunk/tests/channels/pjsip/transfers/attended_transfer/nominal/tests.yaml Wed Jan 14 15:15:42 2015
@@ -2,4 +2,4 @@
 tests:
     - test: 'caller_local'
     - test: 'callee_local'
-
+    - test: 'callee_remote'




More information about the svn-commits mailing list