Author: jbigelow Date: Fri Mar 6 13:45:17 2015 New Revision: 6491 URL: http://svnview.digium.com/svn/testsuite?view=rev&rev=6491 Log: Testsuite: Add ARI channel subscription tests.
This adds some local and non-local channel subscription tests for ARI. These tests ensure ARI events occur and/or don't occur for the appropriate stasis app(s). Four tests have been added under 'tests/rest_api/applications/channel-subscriptions/': * originate_to_dialplan/non_local_channels - Similiar to the existing test that this patch modifies as mentioned below. This required modifying pjsua_mod.py to allow more calls. * originate_to_other_stasis_app/local_channels - Creates two websockets, one for for each stasis app. Originates a local channel from AppA where half is sent into AppB and the other half send into the dialplan. * originate_to_other_stasis_app/non_local_channels - Creates two websockets, one for for each stasis app. Originates a PJSIP channel from AppA to a pjsua phone where is is placed into AppB. * originate_to_stasis_app/local_channels Note: The test 'tests/rest_api/applications/subscribe-channel' test has been renamed to 'basic-subscribe' under the same location as the new tests. The following test has been modified to ensure no ARI events are received: * tests/rest_api/channels/originate_to_dialplan ASTERISK-24586 #close Review: https://reviewboard.asterisk.org/r/4452/ Added: asterisk/trunk/tests/rest_api/applications/channel-subscriptions/ asterisk/trunk/tests/rest_api/applications/channel-subscriptions/basic_subscription/ - copied from r6475, asterisk/trunk/tests/rest_api/applications/subscribe-channel/ asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_dialplan/ asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_dialplan/non_local_channels/ asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_dialplan/non_local_channels/configs/ asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_dialplan/non_local_channels/configs/ast1/ asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_dialplan/non_local_channels/configs/ast1/extensions.conf (with props) asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_dialplan/non_local_channels/configs/ast1/pjsip.conf (with props) asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_dialplan/non_local_channels/test-config.yaml (with props) asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_dialplan/tests.yaml (with props) asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/ asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/local_channels/ asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/local_channels/configs/ asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/local_channels/configs/ast1/ asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/local_channels/configs/ast1/extensions.conf (with props) asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/local_channels/configs/ast1/http.conf (with props) asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/local_channels/run-test (with props) asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/local_channels/test-config.yaml (with props) asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/non_local_channels/ asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/non_local_channels/configs/ asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/non_local_channels/configs/ast1/ asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/non_local_channels/configs/ast1/http.conf (with props) asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/non_local_channels/configs/ast1/pjsip.conf (with props) asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/non_local_channels/run-test (with props) asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/non_local_channels/test-config.yaml (with props) asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/tests.yaml (with props) asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_stasis_app/ asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_stasis_app/local_channels/ asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_stasis_app/local_channels/configs/ asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_stasis_app/local_channels/configs/ast1/ asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_stasis_app/local_channels/configs/ast1/extensions.conf (with props) asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_stasis_app/local_channels/test-config.yaml (with props) asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_stasis_app/tests.yaml (with props) asterisk/trunk/tests/rest_api/applications/channel-subscriptions/tests.yaml (with props) Removed: asterisk/trunk/tests/rest_api/applications/subscribe-channel/ Modified: asterisk/trunk/lib/python/asterisk/pjsua_mod.py asterisk/trunk/tests/rest_api/applications/tests.yaml asterisk/trunk/tests/rest_api/channels/originate_to_dialplan/test-config.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=6491&r1=6490&r2=6491 ============================================================================== --- asterisk/trunk/lib/python/asterisk/pjsua_mod.py (original) +++ asterisk/trunk/lib/python/asterisk/pjsua_mod.py Fri Mar 6 13:45:17 2015 @@ -116,6 +116,8 @@ self.ami_connected = 0 self.callback_module = instance_config.get('callback_module') self.callback_method = instance_config.get('callback_method') + # Default is 4. Must be lower than PJSUA_MAX_CALLS (default is 32). + self.max_calls = 30 def __ami_connect(self, ami): """ @@ -131,9 +133,11 @@ len(self.test_object.ami))) return + ua_cfg = pj.UAConfig() + ua_cfg.max_calls = self.max_calls self.lib = pj.Lib() try: - self.lib.init() + self.lib.init(ua_cfg=ua_cfg) self.__create_transports() self.lib.set_null_snd_dev() self.__create_accounts() Added: asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_dialplan/non_local_channels/configs/ast1/extensions.conf URL: http://svnview.digium.com/svn/testsuite/asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_dialplan/non_local_channels/configs/ast1/extensions.conf?view=auto&rev=6491 ============================================================================== --- asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_dialplan/non_local_channels/configs/ast1/extensions.conf (added) +++ asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_dialplan/non_local_channels/configs/ast1/extensions.conf Fri Mar 6 13:45:17 2015 @@ -1,0 +1,47 @@ +[default] + +exten => dummy,1,Answer +same => n,Echo() +same => n,Hangup() + +exten => echo,1,Answer() +same => n,Echo() +same => n,Hangup() + +exten => test,1,UserEvent(${IF($[${location} = ${EXTEN}@${CONTEXT}:${PRIORITY}]?Success:Failed)}) +same => 2,Hangup() +same => 3,UserEvent(${IF($[${location} = ${EXTEN}@${CONTEXT}:${PRIORITY}]?Success:Failed)}) +same => 4,Hangup() +same => 5(dopey),UserEvent(${IF($[${location} = ${EXTEN}@${CONTEXT}:${PRIORITY}]?Success:Failed)}) +same => 6,Hangup() +same => 7(doc),UserEvent(${IF($[${location} = ${EXTEN}@${CONTEXT}:${PRIORITY}]?Success:Failed)}) +same => 8,Hangup() +same => 9,UserEvent(${IF($[${location} = ${EXTEN}@${CONTEXT}:${PRIORITY}]?Success:Failed)}) +same => 10,Hangup() +same => 11,UserEvent(${IF($[${location} = ${EXTEN}@${CONTEXT}:${PRIORITY}]?Success:Failed)}) +same => 12,Hangup() + +; Having an h extension prevents _. from matching when the channel hangs up +exten => h,1,NoOp() + +exten => _.,1,UserEvent(Failed) + +[grumpy] +exten => test,1,UserEvent(${IF($[${location} = ${EXTEN}@${CONTEXT}:${PRIORITY}]?Success:Failed)}) +same => 2,Hangup() +same => 3,UserEvent(${IF($[${location} = ${EXTEN}@${CONTEXT}:${PRIORITY}]?Success:Failed)}) +same => 4,Hangup() +same => 5(sleepy),UserEvent(${IF($[${location} = ${EXTEN}@${CONTEXT}:${PRIORITY}]?Success:Failed)}) +same => 6,Hangup() +same => 7(bashful),UserEvent(${IF($[${location} = ${EXTEN}@${CONTEXT}:${PRIORITY}]?Success:Failed)}) +same => 8,Hangup() +same => 9,UserEvent(${IF($[${location} = ${EXTEN}@${CONTEXT}:${PRIORITY}]?Success:Failed)}) +same => 10,Hangup() +same => 11,UserEvent(${IF($[${location} = ${EXTEN}@${CONTEXT}:${PRIORITY}]?Success:Failed)}) +same => 12,UserEvent(TestSuiteTestEnd) +same => 13,Hangup() + +; Having an h extension prevents _. from matching when the channel hangs up +exten => h,1,NoOp() + +exten => _.,1,UserEvent(Failed) Propchange: asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_dialplan/non_local_channels/configs/ast1/extensions.conf ------------------------------------------------------------------------------ svn:eol-style = native Propchange: asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_dialplan/non_local_channels/configs/ast1/extensions.conf ------------------------------------------------------------------------------ svn:keywords = Author Date Id Revision Propchange: asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_dialplan/non_local_channels/configs/ast1/extensions.conf ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_dialplan/non_local_channels/configs/ast1/pjsip.conf URL: http://svnview.digium.com/svn/testsuite/asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_dialplan/non_local_channels/configs/ast1/pjsip.conf?view=auto&rev=6491 ============================================================================== --- asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_dialplan/non_local_channels/configs/ast1/pjsip.conf (added) +++ asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_dialplan/non_local_channels/configs/ast1/pjsip.conf Fri Mar 6 13:45:17 2015 @@ -1,0 +1,26 @@ +[global] +type=global +debug=yes + +[system] +type=system + +[local] +type=transport +protocol=udp +bind=127.0.0.1:5060 + +[alice] +type=endpoint +context=default +disallow=all +allow=ulaw +direct_media=no +media_address=127.0.0.1 +aors=alice + +[alice] +type=aor +max_contacts=1 +contact=sip:alice@127.0.0.1:5061\;transport=udp + Propchange: asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_dialplan/non_local_channels/configs/ast1/pjsip.conf ------------------------------------------------------------------------------ svn:eol-style = native Propchange: asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_dialplan/non_local_channels/configs/ast1/pjsip.conf ------------------------------------------------------------------------------ svn:keywords = Author Date Id Revision Propchange: asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_dialplan/non_local_channels/configs/ast1/pjsip.conf ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_dialplan/non_local_channels/test-config.yaml URL: http://svnview.digium.com/svn/testsuite/asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_dialplan/non_local_channels/test-config.yaml?view=auto&rev=6491 ============================================================================== --- asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_dialplan/non_local_channels/test-config.yaml (added) +++ asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_dialplan/non_local_channels/test-config.yaml Fri Mar 6 13:45:17 2015 @@ -1,0 +1,223 @@ +testinfo: + summary: 'Test ARI origination of non-local channels to dialplan locations' + description: | + 'This attempts to test originating non-local channels to the dialplan, + using all combinations of extension, context, priority, and label. The + originations go in the following order: + * Only extension specified + * Extension and priority specified + * Extension and label specified + * Extension, priority, and label specified + * Extension and numeric label specified + * Extension, priority, and numeric label specified + * All of the above repeated, this time specifying a context. + + In total there are 12 originations performed. Each origination sets a + channel variable on the channel that specifies where we expect the + origination to end up. A user event is emitted from the dialplan to + indicate if the results meet expectations. Another user event is + emitted only for the last origination to indicate that the test is + complete and should be stopped. Additionally ensure that no ARI events + are received.' + +properties: + minversion: '13.2.0' + dependencies: + - python: autobahn.websocket + - python: requests + - python: twisted + - python: starpy + - python: pjsua + - asterisk: app_echo + - asterisk: app_userevent + - asterisk: res_ari_channels + - asterisk: res_pjsip + tags: + - ARI + - pjsip + +test-modules: + test-object: + config-section: originate-config + typename: ari.AriOriginateTestObject + modules: + - + config-section: pjsua-config + typename: phones.PjsuaPhoneController + - + config-section: pluggable-config + typename: pluggable_modules.EventActionModule + +pjsua-config: + transports: + - + name: 'local-ipv4-1' + bind: '127.0.0.1' + bindport: '5061' + accounts: + - + name: 'alice' + username: 'alice' + domain: '127.0.0.1' + transport: 'local-ipv4-1' + +originate-config: + apps: testsuite + test-iterations: + - + channelId: 'dummy' + endpoint: 'Local/dummy@default' + context: 'default' + extension: 'echo' + priority: '1' + +pluggable-config: + # Upon alice registering, originate the channels. + - + ami-events: + conditions: + match: + Event: TestEvent + State: 'AOR_CONTACT_ADDED' + AOR: 'alice' + count: 1 + ari-requests: + - + method: 'post' + uri: 'channels' + params: + endpoint: 'PJSIP/alice' + extension: 'test' + body: {'variables': {'location': 'test@default:1'}} + - + method: 'post' + uri: 'channels' + params: + endpoint: 'PJSIP/alice' + extension: 'test' + priority: '3' + body: {'variables': {'location': 'test@default:3'}} + - + method: 'post' + uri: 'channels' + params: + endpoint: 'PJSIP/alice' + extension: 'test' + label: 'dopey' + body: {'variables': {'location': 'test@default:5'}} + - + method: 'post' + uri: 'channels' + params: + endpoint: 'PJSIP/alice' + extension: 'test' + priority: '5' + label: 'doc' + body: {'variables': {'location': 'test@default:7'}} + - + method: 'post' + uri: 'channels' + params: + endpoint: 'PJSIP/alice' + extension: 'test' + label: '9' + body: {'variables': {'location': 'test@default:9'}} + - + method: 'post' + uri: 'channels' + params: + endpoint: 'PJSIP/alice' + extension: 'test' + priority: '5' + label: '11' + body: {'variables': {'location': 'test@default:11'}} + - + method: 'post' + uri: 'channels' + params: + endpoint: 'PJSIP/alice' + context: 'grumpy' + extension: 'test' + body: {'variables': {'location': 'test@grumpy:1'}} + - + method: 'post' + uri: 'channels' + params: + endpoint: 'PJSIP/alice' + context: 'grumpy' + extension: 'test' + priority: '3' + body: {'variables': {'location': 'test@grumpy:3'}} + - + method: 'post' + uri: 'channels' + params: + endpoint: 'PJSIP/alice' + context: 'grumpy' + extension: 'test' + label: 'sleepy' + body: {'variables': {'location': 'test@grumpy:5'}} + - + method: 'post' + uri: 'channels' + params: + endpoint: 'PJSIP/alice' + context: 'grumpy' + extension: 'test' + priority: '5' + label: 'bashful' + body: {'variables': {'location': 'test@grumpy:7'}} + - + method: 'post' + uri: 'channels' + params: + endpoint: 'PJSIP/alice' + context: 'grumpy' + extension: 'test' + label: '9' + body: {'variables': {'location': 'test@grumpy:9'}} + - + method: 'post' + uri: 'channels' + params: + endpoint: 'PJSIP/alice' + context: 'grumpy' + extension: 'test' + priority: '5' + label: '11' + body: {'variables': {'location': 'test@grumpy:11'}} + # Ensure no ARI events are received. + - + ari-events: + match: + type: '.*' + count: '0' + # Ensure we have the correct number of successful results. + - + ami-events: + conditions: + match: + Event: 'UserEvent' + UserEvent: 'Success' + count: '12' + # Ensure we have no failed results. + - + ami-events: + conditions: + match: + Event: 'UserEvent' + UserEvent: 'Failed' + count: '0' + # Ensure indication is received that all calls should have occurred. Then + # hang up the kick off dummy channel to end the test. + - + ami-events: + conditions: + match: + Event: 'UserEvent' + UserEvent: 'TestSuiteTestEnd' + count: '1' + ari-requests: + method: 'delete' + uri: 'channels/dummy' + Propchange: asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_dialplan/non_local_channels/test-config.yaml ------------------------------------------------------------------------------ svn:eol-style = native Propchange: asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_dialplan/non_local_channels/test-config.yaml ------------------------------------------------------------------------------ svn:keywords = Author Date Id Revision Propchange: asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_dialplan/non_local_channels/test-config.yaml ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_dialplan/tests.yaml URL: http://svnview.digium.com/svn/testsuite/asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_dialplan/tests.yaml?view=auto&rev=6491 ============================================================================== --- asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_dialplan/tests.yaml (added) +++ asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_dialplan/tests.yaml Fri Mar 6 13:45:17 2015 @@ -1,0 +1,3 @@ +# Enter tests here in the order they should be considered for execution: +tests: + - test: 'non_local_channels' Propchange: asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_dialplan/tests.yaml ------------------------------------------------------------------------------ svn:eol-style = native Propchange: asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_dialplan/tests.yaml ------------------------------------------------------------------------------ svn:keywords = Author Date Id Revision Propchange: asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_dialplan/tests.yaml ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/local_channels/configs/ast1/extensions.conf URL: http://svnview.digium.com/svn/testsuite/asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/local_channels/configs/ast1/extensions.conf?view=auto&rev=6491 ============================================================================== --- asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/local_channels/configs/ast1/extensions.conf (added) +++ asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/local_channels/configs/ast1/extensions.conf Fri Mar 6 13:45:17 2015 @@ -1,0 +1,10 @@ +[default] + +exten => do_stuff,1,NoOp() +same => n,Answer() +same => n,Playback(silence/1) +same => n,Hangup() + +exten => h,1,NoOp() +same => n,Hangup() + Propchange: asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/local_channels/configs/ast1/extensions.conf ------------------------------------------------------------------------------ svn:eol-style = native Propchange: asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/local_channels/configs/ast1/extensions.conf ------------------------------------------------------------------------------ svn:keywords = Author Date Id Revision Propchange: asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/local_channels/configs/ast1/extensions.conf ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/local_channels/configs/ast1/http.conf URL: http://svnview.digium.com/svn/testsuite/asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/local_channels/configs/ast1/http.conf?view=auto&rev=6491 ============================================================================== --- asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/local_channels/configs/ast1/http.conf (added) +++ asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/local_channels/configs/ast1/http.conf Fri Mar 6 13:45:17 2015 @@ -1,0 +1,5 @@ +[general] +enabled=yes +bindaddr=127.0.0.1 +bindport=8088 +prefix= Propchange: asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/local_channels/configs/ast1/http.conf ------------------------------------------------------------------------------ svn:eol-style = native Propchange: asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/local_channels/configs/ast1/http.conf ------------------------------------------------------------------------------ svn:keywords = Author Date Id Revision Propchange: asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/local_channels/configs/ast1/http.conf ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/local_channels/run-test URL: http://svnview.digium.com/svn/testsuite/asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/local_channels/run-test?view=auto&rev=6491 ============================================================================== --- asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/local_channels/run-test (added) +++ asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/local_channels/run-test Fri Mar 6 13:45:17 2015 @@ -1,0 +1,292 @@ +#!/usr/bin/env python +# vim: sw=3 et: +"""A test that verifies ARI app local channel subscriptions + +This creates two ARI apps. A local channel is created by the first app where +half is placed into the second app and the other half is placed into the +dialplan. This verifies that the ARI events are received by the appropriate app +and for the appropriate channel half. + +Copyright (C) 2015, Digium, Inc. +John Bigelow <jbige...@digium.com> + +This program is free software, distributed under the terms of +the GNU General Public License Version 2. +""" + +import sys +import logging + +from twisted.internet import reactor + +sys.path.append("lib/python") + +from asterisk.test_case import TestCase +from asterisk.ari import ARI, AriClientFactory + +LOGGER = logging.getLogger(__name__) + +USERPASS = ('testsuite', 'testsuite') + + +class BaseReceiver(object): + """Base class for an ARI protocol receiver""" + + def __init__(self, test_object): + """Constructor + + Keyword Arguments: + test_object -- our TestCase instance + """ + self.test_object = test_object + + def on_ws_event(self, message): + """Handler for WebSocket events + + Keyword Arguments: + message -- The WS event payload + """ + msg_type = message.get('type') + callback = getattr(self, 'handle_{0}'.format(msg_type.lower()), None) + if callback: + callback(message) + + def on_ws_open(self, protocol): + """Handler for WebSocket Client Protocol opened + + Keyword Arguments: + protocol -- The WS Client protocol object + """ + LOGGER.debug("{0}: WebSocket connection made {1}".format(self, + protocol)) + self.test_object.protocol_connected(protocol) + + def on_ws_closed(self, protocol): + """Handler for WebSocket Client Protocol closed + + Keyword Arguments: + protocol -- The WS Client protocol object + """ + LOGGER.debug("{0}: WebSocket connection closed {1}".format(self, + protocol)) + + +class App(BaseReceiver): + """A class that originates a channel + + Originates a channel to a single Asterisk instance. The app name and + channel id are verified of any received ARI events and the test is failed + if they are not what is expected. + """ + + def __init__(self, ast, test_object, app_name): + """Constructor + + Keyword Arguments: + ast -- our call originating Asterisk instance + test_object -- our TestCase object + app_name -- our name + """ + super(App, self).__init__(test_object) + self.app_name = app_name + self.channels = [] + self.ari_events = {'channeldialplan': 0, 'stasisstart': 0} + self.client = ARI(ast.host, userpass=USERPASS) + self.factory = AriClientFactory(receiver=self, + host=ast.host, + port=8088, + apps=app_name, + userpass=USERPASS) + self.factory.connect() + + def originate_call(self): + """Make me a call!""" + if self.test_object.originate_channel is None: + LOGGER.warn('ARI channel origination info not found!') + return + LOGGER.debug("{0}: Originating channel".format(self.app_name)) + self.client.post('channels', **self.test_object.originate_channel) + + def event_failure(self, message, item): + """Fail the test""" + if item == "application": + msg = "{0} received event {1} for {2}." + if item == "channelid": + msg = "{0} received event {1} with unexpected channel {2}." + LOGGER.warn(msg.format(self.app_name, message['type'], message[item])) + self.test_object.set_passed(False) + self.test_object.hangup_all_channels() + + def handle_channeldialplan(self, message): + """ChannelDialplan handler + + Keyword Arguments: + message -- the JSON message + """ + if message['application'] != self.app_name: + self.event_failure(message, "application") + return + if message['channel']['id'] != \ + self.test_object.originate_channel['otherChannelId']: + self.event_failure(message, "channelid") + return + + self.ari_events[message['type'].lower()] += 1 + + def handle_stasisend(self, message): + """StasisEnd handler + + Keyword Arguments: + message -- the JSON message + """ + channel_id = message['channel']['id'] + self.channels.remove(channel_id) + + def handle_stasisstart(self, message): + """StasisStart handler + + Keyword Arguments: + message -- the JSON message + """ + channel_id = message['channel']['id'] + self.channels.append(channel_id) + if message['application'] != self.app_name: + self.event_failure(message, "application") + return + if message['channel']['id'] != \ + self.test_object.originate_channel['channelId']: + self.event_failure(message, "channelid") + return + + self.ari_events[message['type'].lower()] += 1 + + def hangup_channels(self): + """Hang up all tracked channels""" + + # We will race between the StasisEnd event being processed + # from a BYE from the loaded systems and our attempt to + # delete the channel; ignore any HTTP errors + self.client.set_allow_errors(True) + for channel in self.channels: + LOGGER.debug('Hanging up {0}'.format(channel)) + self.client.delete('channels', channel) + self.client.set_allow_errors(False) + + +class OriginateToDifferentApp(TestCase): + """A class that manages this test + + This creates ARI apps and will fail the test if the number of ARI events + doesn't match the number of expected. + """ + + def __init__(self): + """Constructor""" + super(OriginateToDifferentApp, self).__init__() + self.create_asterisk(count=1) + self.protocols = [] + # Name of apps to create + self.app_names = ('AppA', 'AppB') + self.tmp_app_names = None + # App name and app object pairs + self.apps = {} + # The application that will originate the channel. + self.orig_src_app = self.app_names[0] + # The application that the originated channel will be put into. + self.orig_dst_app = self.app_names[1] + # Channel info to originate + self.originate_channel = {'endpoint': 'Local/do_stuff@default', + 'channelId': 'StasisHalf', + 'otherChannelId': 'DpHalf', + 'app': self.orig_dst_app} + # Expected number of ARI events each app receives. + self.expected = {self.app_names[0]: {'channeldialplan': 0, + 'stasisstart': 0}, + self.app_names[1]: {'channeldialplan': 6, + 'stasisstart': 1}} + + def run(self): + """Entry point for the twisted reactor""" + super(OriginateToDifferentApp, self).run() + + self.tmp_app_names = list(self.app_names) + self.tmp_app_names.reverse() + name = self.tmp_app_names.pop() + # Create the first ARI app + self.apps[name] = App(self.ast[0], self, name) + + def protocol_connected(self, protocol): + """Called by the various Apps on protocol connection + + This will create subsequent apps after the first and be called upon + protocol connection for each. + + Keyword Arguments: + protocol -- the twisted protocol that connected + """ + self.protocols.append(protocol) + + # Creating the apps immediately after one another leads to a random + # twisted error. So we create the next app upon the connection of the + # previously created app. + try: + name = self.tmp_app_names.pop() + self.apps[name] = App(self.ast[0], self, name) + except IndexError: + pass + + if len(self.protocols) != 2: + return + + LOGGER.info('Originating call!') + self.apps[self.orig_src_app].originate_call() + reactor.callLater(10, self.hangup_all_channels) + + def hangup_all_channels(self): + """Hangs up all channels in each app""" + for app in self.apps.values(): + app.hangup_channels() + for protocol in self.protocols: + protocol.transport.loseConnection() + self.check_results() + self.stop_reactor() + + def check_results(self): + """Check the number of ARI events received by each app + + This sets a failure if the number of received events doesn't match what + was expected. + """ + for name in self.app_names: + diff = [k for k in self.expected[name] + if self.apps[name].ari_events[k] != self.expected[name][k]] + if not diff: + continue + + self.set_passed(False) + for event in diff: + LOGGER.warn("{0} received {1} {2} events; expected " \ + "{3}".format(name, self.apps[name].ari_events[event], + event, self.expected[name][event])) + # Any previously set failures will override this. + self.set_passed(True) + + +def main(): + """Main entry point for the test. + + Returns: + 0 on test pass + 1 on test failure + """ + + test = OriginateToDifferentApp() + reactor.run() + + if not test.passed: + return 1 + + return 0 + +if __name__ == "__main__": + sys.exit(main()) Propchange: asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/local_channels/run-test ------------------------------------------------------------------------------ svn:eol-style = native Propchange: asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/local_channels/run-test ------------------------------------------------------------------------------ svn:executable = * Propchange: asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/local_channels/run-test ------------------------------------------------------------------------------ svn:keywords = Author Date Id Revision Propchange: asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/local_channels/run-test ------------------------------------------------------------------------------ svn:mime-type = text/plain Added: asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/local_channels/test-config.yaml URL: http://svnview.digium.com/svn/testsuite/asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/local_channels/test-config.yaml?view=auto&rev=6491 ============================================================================== --- asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/local_channels/test-config.yaml (added) +++ asterisk/trunk/tests/rest_api/applications/channel-subscriptions/originate_to_other_stasis_app/local_channels/test-config.yaml Fri Mar 6 13:45:17 2015 @@ -1,0 +1,32 @@ +testinfo: + summary: | + "Test subscriptions when originating a local channel to another Stasis + app and dialplan." + description: | + "This test creates two Stasis apps each with a separate websocket. Once + both websockets are established a local channel is originated from AppA + with specifying app AppB. Local channel half 'StasisHalf' is placed + into Stasis app AppB while the other half 'DpHalf' is put into the + dialplan where it executes dialplan applications and eventually hangs + up. + + This test verifies that both channel halves have been subscribed to by + the AppB Stasis app and AppB receives ARI events from both halves. It + ensures AppB receives ChannelDialplan events showing the dialplan + progression for 'DpHalf' and a StasisStart event for 'StasisHalf'. It + also ensures AppA does not receive any of the ARI events that is + expected for AppB to receive." + +properties: + minversion: '13.2.0' + dependencies: + - python: autobahn.websocket + - python: requests + - python: twisted + - asterisk: app_playback + - asterisk: res_ari_applications + - asterisk: res_ari_channels + - asterisk: res_pjsip + tags: + - ARI + [... 757 lines stripped ...] -- _____________________________________________________________________ -- Bandwidth and Colocation Provided by http://www.api-digital.com -- svn-commits mailing list To UNSUBSCRIBE or update options visit: http://lists.digium.com/mailman/listinfo/svn-commits