[svn-commits] kmoore: testsuite/asterisk/trunk r3346 - in /asterisk/trunk/tests/channels/SI...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Fri Jul 20 10:04:01 CDT 2012


Author: kmoore
Date: Fri Jul 20 10:03:56 2012
New Revision: 3346

URL: http://svnview.digium.com/svn/testsuite?view=rev&rev=3346
Log:
Convert sip_attended_transfer test to use TestCase and PJSUA

This test has been disabled for a long time now because it was failing.
This change updates the test to use the TestCase class to bring it in line
with current practices and changes it over to using the pjsua python
library to avoid threading issues with the twisted reactor as well as
using a nicer interface to access the required features.

(closes issue SWP-4659)

Modified:
    asterisk/trunk/tests/channels/SIP/sip_attended_transfer/configs/ast1/sip.conf
    asterisk/trunk/tests/channels/SIP/sip_attended_transfer/run-test
    asterisk/trunk/tests/channels/SIP/sip_attended_transfer/test-config.yaml

Modified: asterisk/trunk/tests/channels/SIP/sip_attended_transfer/configs/ast1/sip.conf
URL: http://svnview.digium.com/svn/testsuite/asterisk/trunk/tests/channels/SIP/sip_attended_transfer/configs/ast1/sip.conf?view=diff&rev=3346&r1=3345&r2=3346
==============================================================================
--- asterisk/trunk/tests/channels/SIP/sip_attended_transfer/configs/ast1/sip.conf (original)
+++ asterisk/trunk/tests/channels/SIP/sip_attended_transfer/configs/ast1/sip.conf Fri Jul 20 10:03:56 2012
@@ -4,26 +4,14 @@
 [end_a]
 context=transfertest
 type=friend
-host=127.0.0.1
-port=5065
 insecure=invite
-disallow=all
-allow=ulaw
 
 [end_b]
-context=transfertest
 type=friend
-host=127.0.0.1
-port=5066
+host=dynamic
 insecure=invite
-disallow=all
-allow=ulaw
 
 [end_c]
-context=transfertest
 type=friend
-host=127.0.0.1
-port=5067
+host=dynamic
 insecure=invite
-disallow=all
-allow=ulaw

Modified: asterisk/trunk/tests/channels/SIP/sip_attended_transfer/run-test
URL: http://svnview.digium.com/svn/testsuite/asterisk/trunk/tests/channels/SIP/sip_attended_transfer/run-test?view=diff&rev=3346&r1=3345&r2=3346
==============================================================================
--- asterisk/trunk/tests/channels/SIP/sip_attended_transfer/run-test (original)
+++ asterisk/trunk/tests/channels/SIP/sip_attended_transfer/run-test Fri Jul 20 10:03:56 2012
@@ -9,144 +9,130 @@
 
 import sys
 import os
-import signal
-import subprocess
-from twisted.application import service, internet
-from twisted.internet import reactor, defer
-from starpy import manager
+from twisted.internet import reactor
+import pjsua as pj
+import threading
 
 sys.path.append("lib/python")
-from asterisk.asterisk import Asterisk
+from asterisk.TestCase import TestCase
+import logging
 
-workingdir = "sip_attended_transfer"
-testdir = "tests/%s" % workingdir
+LOGGER = logging.getLogger(__name__)
 
-class AttTransferTest:
+class AutoAnswerCallback(pj.AccountCallback):
+    def __init__(self, account):
+        self.sem = threading.Semaphore(0)
+        pj.AccountCallback.__init__(self, account)
+
+    def wait(self):
+        if self.sem:
+            self.sem.acquire()
+
+    def on_reg_state(self):
+        if self.sem:
+            if self.account.info().reg_status >= 200:
+                self.sem.release()
+                self.sem = None
+
+    def on_incoming_call(self, call):
+        call.answer(200)
+
+class AttTransferTest(TestCase):
     def __init__(self):
-        self.last_step = ""
-        self.passed = False
-
-        reactor.callWhenRunning(self.run)
-
-        self.ast1 = Asterisk(base=workingdir)
-        self.ast1.install_configs("%s/configs/ast1" % (testdir))
-
-    def readResult(self):
-        self.logLastStep("Reading results")
-        self.ast1.cli_exec("core show locks")   # get lock output in case of deadlock before tearing down.
-        self.ast1.cli_exec("core show channels")# if channels are still up for some reason, we want to know that as well
-        self.stopProcesses()
-
-        if self.passed == True:
-            print 'SIP Attended Transfer Test Passed!'
-        else:
-            print 'SIP Attended Transfer Test Failed'
-
-        if reactor.running:
-            print "Stopping Reactor ..."
-            reactor.stop()
-
-    def amiOnConnect(self, ami):
-        self.logLastStep("Connected to the AMI")
-        self.ami = ami
-
-    def amiLoginError(self, ami):
-        self.logLastStep("AMI login failed")
-        reactor.callLater(1, self.readResult)
-
-    def amiLogin(self):
-        self.logLastStep("Logging in to the AMI")
-        self.ami_factory = manager.AMIFactory("user", "mysecret")
-        self.ami_factory.login('127.0.0.1', 5038).addCallbacks(self.amiOnConnect, self.amiLoginError)
-
-    def checkBridgeResult(self, result):
-        print 'Result', result
-        if "bridgedchannel" not in result[0]:
-            print "bridgedchannel was not a valid key."
-        elif result[0]['bridgedchannel'] == 'SIP/end_b-00000001':
-            self.passed = True
-
-        if "link" not in result[0]:
-            print "'link' was not a valid key."
-        elif result[0]['link'] == 'SIP/end_b-00000001': # check link for older versions of asterisk
-            self.passed = True
-
-        if self.passed == True:
-            self.logLastStep("Found Bridge!!!")
-        else:
-            self.logLastStep("Detecting Bridge failed")
-
-    def checkBridgeError(self, reason):
-        print reason.getTraceback()
-        self.logLastStep("Checking Bridge failed.  Channel did not exist.")
-        reactor.callLater(1, self.readResult)
-
-    def amiCheckBridge(self):
-        self.logLastStep("Get AMI results")
-        self.ami.status('SIP/end_c-00000003').addCallbacks(self.checkBridgeResult, self.checkBridgeError)
-
-    def aCallB(self):
-        self.logLastStep("A Calling B")
-        self.pja.stdin.write("m\n")
-        self.pja.stdin.write("sip:call_b at 127.0.0.1:5060\n")
-
-    def aCallC(self):
-        self.logLastStep("A Calling C")
-        self.pja.stdin.write("m\n")
-        self.pja.stdin.write("sip:call_c at 127.0.0.1:5060\n")
-
-    def aTransferBToC(self):
-        self.logLastStep("A Transfering B to C")
-        self.pja.stdin.write("X\n")
-        self.pja.stdin.write("1\n")
-
-    def startProcesses(self):
-        self.logLastStep("Starting Processes")
-        self.ast1.start()
-        self.pja = subprocess.Popen(['pjsua', '--local-port=5065',
-                                     '--auto-answer=200', '--null-audio'],
-                                     stdin=subprocess.PIPE)
-        self.pjb = subprocess.Popen(['pjsua', '--local-port=5066',
-                                     '--auto-answer=200', '--null-audio'],
-                                     stdin=subprocess.PIPE,
-                                     stdout=subprocess.PIPE)
-        self.pjc = subprocess.Popen(['pjsua', '--local-port=5067',
-                                     '--auto-answer=200', '--null-audio'],
-                                     stdin=subprocess.PIPE,
-                                     stdout=subprocess.PIPE)
-
-    def stopProcesses(self):
-        self.logLastStep("Stopping Processes")
-        self.ast1.stop()
-        os.kill(self.pja.pid, signal.SIGKILL)
-        os.kill(self.pjb.pid, signal.SIGKILL)
-        os.kill(self.pjc.pid, signal.SIGKILL)
-
-    def logLastStep(self, step):
-        print step
-        self.lastStep = step
+        TestCase.__init__(self)
+        #self.reactor_timeout = 60
+        self.create_asterisk()
+	self.chans = []
+        self.final_bridge = 0
+        self.lib = None
+        self.ext_a = None
+        self.ext_b = None
+        self.ext_c = None
+        self.callToB = None
+        self.callToC = None
 
     def run(self):
+        TestCase.run(self)
+        self.create_ami_factory()
 
-        # start up the processes
-        self.startProcesses()
+    def ami_connect(self, ami):
+        # start pjsua clients
+        self.lib = pj.Lib()
+        try:
+            self.lib.init()
+            self.lib.create_transport(pj.TransportType.UDP, pj.TransportConfig())
+            self.lib.set_null_snd_dev()
+            self.lib.start()
 
-        # call extensions
-        self.amiLogin()
-        reactor.callLater(5, self.aCallB)
-        reactor.callLater(10, self.aCallC)
-        reactor.callLater(15, self.aTransferBToC)
-        reactor.callLater(20, self.amiCheckBridge)
+            # we'll need this for later...
+            self.ext_a = self.lib.create_account(pj.AccountConfig("127.0.0.1", "end_a"))
+            self.ext_b = self.lib.create_account(pj.AccountConfig("127.0.0.1", "end_b"))
+            self.ext_c = self.lib.create_account(pj.AccountConfig("127.0.0.1", "end_c"))
+            # only legs B and C receive calls, so only those two need to register and autoanswer
+            ext_b_cb = AutoAnswerCallback(self.ext_b)
+            ext_c_cb = AutoAnswerCallback(self.ext_c)
+            self.ext_b.set_callback(ext_b_cb)
+            self.ext_c.set_callback(ext_c_cb)
+            # wait for registration
+            ext_b_cb.wait()
+            ext_c_cb.wait()
 
-        # stop and read results after timeout
-        reactor.callLater(25, self.readResult)
+        except pj.Error, e:
+            print "Exception: " + str(e)
+            self.doCleanup()
+            return
+
+
+        # register callbacks required to handle call completion events
+        self.ami[0].registerEvent('Bridge', self.bridge_callback)
+        self.ami[0].registerEvent('VarSet', self.bridgepeer_callback)
+
+        # kick off first call from A to B
+        LOGGER.info("Kicking off A-to-B call")
+        self.callToB = self.ext_a.make_call("sip:call_b at 127.0.0.1:5060")
+
+    def bridge_callback(self, ami, event):
+	self.chans.append(event['channel2'])
+        numchans = len(self.chans)
+        if numchans == 1:
+            # kick off second call from A to C
+            LOGGER.info("Kicking off A-to-C call")
+            self.callToC = self.ext_a.make_call("sip:call_c at 127.0.0.1:5060")
+        elif numchans == 2:
+            # both channels are now up, so initiate the transfer
+            LOGGER.info("Kicking off transfer")
+            self.callToC.transfer_to_call(self.callToB)
+
+    def bridgepeer_callback(self, ami, event):
+        if event['variable'] != "BRIDGEPEER" or len(self.chans) < 2:
+            return
+
+        LOGGER.info("Inspecting BRIDGEPEER VarSet")
+
+        # we should get 2 bridgepeers with swapped channel and value headers indicating the bridged channels
+        if self.chans[:2] == [event['channel'], event['value']] or\
+            self.chans[:2] == [event['value'], event['channel']]:
+            LOGGER.info("Got expected VarSet")
+            self.final_bridge += 1
+            if self.final_bridge == 2:
+                LOGGER.info("Transfer successful!")
+                # success!
+                self.passed = True
+                self.doCleanup()
+
+    def doCleanup(self):
+        #self.ami[0].hangup(self.chans[0])
+        self.ast[0].cli_exec("core show locks")   # get lock output in case of deadlock before tearing down.
+        self.ast[0].cli_exec("core show channels")# if channels are still up for some reason, we want to know that as well
+        self.lib.destroy()
+        self.lib = None
+        reactor.stop()
 
 def main():
     # Run Attended Transfer Test
-    att_transfer_test = AttTransferTest()
+    test = AttTransferTest()
     reactor.run()
-    att_transfer_test.stopProcesses()
-    if att_transfer_test.passed != True:
+    if test.passed != True:
         return 1
     return 0
 

Modified: asterisk/trunk/tests/channels/SIP/sip_attended_transfer/test-config.yaml
URL: http://svnview.digium.com/svn/testsuite/asterisk/trunk/tests/channels/SIP/sip_attended_transfer/test-config.yaml?view=diff&rev=3346&r1=3345&r2=3346
==============================================================================
--- asterisk/trunk/tests/channels/SIP/sip_attended_transfer/test-config.yaml (original)
+++ asterisk/trunk/tests/channels/SIP/sip_attended_transfer/test-config.yaml Fri Jul 20 10:03:56 2012
@@ -1,5 +1,4 @@
 testinfo:
-    skip: 'Skip while failures are debugged'
     summary:     'Test SIP Attended Transfer'
     description: |
         'This test verifies the SIP_REFER with Replaces attended transfer routine.'
@@ -9,7 +8,7 @@
     dependencies:
         - python : 'twisted'
         - python : 'starpy'
-        - app : 'pjsua'
+        - python : 'pjsua'
     tags:
         - SIP
-        - transfer
+        - transfer




More information about the svn-commits mailing list