[asterisk-commits] kmoore: testsuite/asterisk/trunk r3346 - in /asterisk/trunk/tests/channels/SI...
SVN commits to the Asterisk project
asterisk-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 asterisk-commits
mailing list