[asterisk-commits] jrose: testsuite/asterisk/trunk r5249 - in /asterisk/trunk/tests/pbx: ./ mana...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Jul 16 13:51:51 CDT 2014


Author: jrose
Date: Wed Jul 16 13:51:44 2014
New Revision: 5249

URL: http://svnview.digium.com/svn/testsuite?view=rev&rev=5249
Log:
testsuite: Add tests for DialplanExtensionAdd and DialplanExtensionRemove

Adds a multiphase test for manager commands DialplanExtensionAdd and
DialplanExtension Remove. The test covers adding to existing extensions,
adding/removing extensions with CID matching, removing single priorities
in an extension, removing entire extensions with multiple priorities,
replacement of existing extensions, and numerous off-nominal uses of
the Add/Remove operations which result in errors.

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

Added:
    asterisk/trunk/tests/pbx/manager_extensions/
    asterisk/trunk/tests/pbx/manager_extensions/ami_extension_control.py   (with props)
    asterisk/trunk/tests/pbx/manager_extensions/configs/
    asterisk/trunk/tests/pbx/manager_extensions/configs/ast1/
    asterisk/trunk/tests/pbx/manager_extensions/configs/ast1/extensions.conf   (with props)
    asterisk/trunk/tests/pbx/manager_extensions/test-config.yaml   (with props)
Modified:
    asterisk/trunk/tests/pbx/tests.yaml

Added: asterisk/trunk/tests/pbx/manager_extensions/ami_extension_control.py
URL: http://svnview.digium.com/svn/testsuite/asterisk/trunk/tests/pbx/manager_extensions/ami_extension_control.py?view=auto&rev=5249
==============================================================================
--- asterisk/trunk/tests/pbx/manager_extensions/ami_extension_control.py (added)
+++ asterisk/trunk/tests/pbx/manager_extensions/ami_extension_control.py Wed Jul 16 13:51:44 2014
@@ -1,0 +1,150 @@
+#!/usr/bin/env python
+'''
+Copyright (C) 2014, Digium, Inc.
+Jonathan Rose <jrose at digium.com>
+
+This program is free software, distributed under the terms of
+the GNU General Public License Version 2.
+'''
+
+import logging
+from test_case import TestCase
+from twisted.internet import defer
+
+LOGGER = logging.getLogger(__name__)
+
+
+class AMIExtensionControl(TestCase):
+    """Specialized test case that performs AMI actions and checks their
+    results as defined by the test-config and then originates a series
+    of calls to channels defined by the test-config.
+    """
+
+    def __init__(self, path=None, test_config=None):
+        """Create an AMIExtensionControl TestCase.
+
+        Keyword Arguments:
+        test_path Optional parameter that specifies the path where this test
+                  resides
+        test_config Loaded YAML test configuration
+        """
+
+        super(AMIExtensionControl, self).__init__(path, test_config)
+
+        if test_config is None:
+            raise Exception("No configuration provided")
+
+        self.commands = test_config['commands']
+        self.originates = test_config['originates']
+        self.responses_received = 0
+        self.test_ami = None  # Will be set on ami_connect
+        self.create_asterisk()
+
+    def originate_calls(self):
+        """Originates channels defined by the test-config to originate at test
+        """
+
+        def _pass_test(results, test_object):
+            """ Validates the results of all originate actions
+            """
+            passed = all(result[0] for result in results if result[0])
+            test_object.set_passed(passed)
+
+        deferds = []
+        for channel in self.originates:
+            deferred = self.test_ami.originate(channel=channel['channel'],
+                                               exten='originate',
+                                               context='test',
+                                               priority='1',
+                                               timeout='5',
+                                               callerid='"test_id" <1337>')
+            deferred.addErrback(self.handle_originate_failure)
+            deferds.append(deferred)
+
+        deferred_list = defer.DeferredList(deferds)
+        deferred_list.addCallback(_pass_test, self)
+
+    def response_received(self):
+        """Tracks the number of responses received to the test-config defined
+        AMI actions. Once the responses received adds up to the number of
+        actions performed, the origination portion of the test will be
+        started.
+        """
+
+        self.responses_received += 1
+
+        if self.responses_received == len(self.commands):
+            self.originate_calls()
+
+    def run(self):
+        """Run the test as normal for a TestCase and start an AMI instance
+        """
+
+        super(AMIExtensionControl, self).run()
+        self.create_ami_factory()
+
+    def ami_connect(self, ami):
+        """On AMI connect, run through all of the AMI commands defined by
+        the test-config.
+        """
+
+        def _expect_success(message):
+            """Callback for when the resposnse to a message is Success.
+            Verifies that the response is success and sets failure if it
+            isn't. Calls response_received to bump the responses_received
+            count and begin the next phase when ready.
+            """
+
+            # Check type of message because we receive a message when the
+            # connection closes that isn't a dictionary.
+            if type(message) is not dict:
+                return 0
+
+            if message.get('response') != 'Success':
+                self.create_fail_token("Received response '%s' when "
+                                       "successful response was expected."
+                                       % message)
+            self.response_received()
+            return 0
+
+        def _expect_error(message):
+            """Same as _expect_success, only the expected response is Error.
+            """
+
+            # Check type of message because we receive a message when the
+            # connection closes that isn't a dictionary.
+            if type(message) is not dict:
+                return 0
+
+            if message.get('response') != 'Error':
+                self.create_fail_token("Received response '%s' when error "
+                                       "response was expected." % message)
+            self.response_received()
+            return 0
+
+        def _handle_hangup(ami, event):
+            """Responds to Hangup manager events and stops the test once a
+            hangup has occured for each originate action"""
+            hung_up = event.get('channel')
+
+            for originate in self.originates:
+                this_chan = originate['channel']
+
+                if hung_up.lower().startswith(this_chan.lower()):
+                    self.originates.remove(originate)
+                    break
+
+            if len(self.originates) == 0:
+                self.stop_reactor()
+
+            return 0
+
+        self.test_ami = ami
+        ami.registerEvent("Hangup", _handle_hangup)
+
+        for action in self.commands:
+            message = action['command']
+            if action['expected-response'] == 'Success':
+                ami.sendMessage(message, responseCallback=_expect_success)
+            else:
+                ami.sendMessage(message, responseCallback=_expect_error)

Propchange: asterisk/trunk/tests/pbx/manager_extensions/ami_extension_control.py
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: asterisk/trunk/tests/pbx/manager_extensions/ami_extension_control.py
------------------------------------------------------------------------------
    svn:executable = *

Propchange: asterisk/trunk/tests/pbx/manager_extensions/ami_extension_control.py
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Propchange: asterisk/trunk/tests/pbx/manager_extensions/ami_extension_control.py
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: asterisk/trunk/tests/pbx/manager_extensions/configs/ast1/extensions.conf
URL: http://svnview.digium.com/svn/testsuite/asterisk/trunk/tests/pbx/manager_extensions/configs/ast1/extensions.conf?view=auto&rev=5249
==============================================================================
--- asterisk/trunk/tests/pbx/manager_extensions/configs/ast1/extensions.conf (added)
+++ asterisk/trunk/tests/pbx/manager_extensions/configs/ast1/extensions.conf Wed Jul 16 13:51:44 2014
@@ -1,0 +1,44 @@
+[general]
+static=yes
+writeprotect=no
+
+[alpha] ; Remove / Replace Only
+exten => test1,1,NoOp()
+exten => test1,2,Answer()
+exten => test1,3,UserEvent(ExtensionTest,Expected: Yes,Extension: ${EXTEN})  ; This doesn't get removed
+exten => test1,4,UserEvent(ExtensionTest,Expected: No,Extension: ${EXTEN})   ; This gets removed
+
+exten => test2,1,NoOp()
+exten => test2,2,Answer()
+exten => test2,3,UserEvent(ExtensionTest,Expected: No,Extension: ${EXTEN})   ; All of these get removed
+exten => test2,4,UserEvent(ExtensionTest,Expected: No,Extension: ${EXTEN})
+
+exten => test6,1,NoOp()
+exten => test6,2,Answer()
+exten => test6,3,UserEvent(ExtensionTest,Expected: No,Extension: ${EXTEN})   ; This gets replaced
+
+exten => test7,1,NoOp()
+exten => test7,2,Answer()
+exten => test7,3,UserEvent(ExtensionTest,Expected: Yes,Extension: ${EXTEN})  ; This doesn't get replaced
+
+exten => test8/1337,1,NoOp()
+exten => test8/1337,2,Answer()
+exten => test8/1337,3,UserEvent(ExtensionTest,Expected: Yes,Extension: ${EXTEN})  ; Doesn't get replaced
+exten => test8/1337,4,UserEvent(ExtensionTest,Expected: No,Extension: ${EXTEN})   ; This gets removed
+
+; test2 ends up here since the whole extension gets deleted and we still need to answer the originate
+exten => _.,1,Answer()
+exten => _.,n,UserEvent(ExtensionDNE,Extension: ${EXTEN})
+
+[beta] ; Add Only
+;tests 3/4/5 will be registered via AMI
+
+; test4 ends up here because the caller ID matching will prevent it
+exten => _.,1,Answer()
+exten => _.,n,UserEvent(ExtensionDNE,Extension: ${EXTEN})
+
+
+[test]
+exten => originate,1,NoOp()
+exten => originate,n,Answer()
+exten => originate,n,Echo()

Propchange: asterisk/trunk/tests/pbx/manager_extensions/configs/ast1/extensions.conf
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: asterisk/trunk/tests/pbx/manager_extensions/configs/ast1/extensions.conf
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Propchange: asterisk/trunk/tests/pbx/manager_extensions/configs/ast1/extensions.conf
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: asterisk/trunk/tests/pbx/manager_extensions/test-config.yaml
URL: http://svnview.digium.com/svn/testsuite/asterisk/trunk/tests/pbx/manager_extensions/test-config.yaml?view=auto&rev=5249
==============================================================================
--- asterisk/trunk/tests/pbx/manager_extensions/test-config.yaml (added)
+++ asterisk/trunk/tests/pbx/manager_extensions/test-config.yaml Wed Jul 16 13:51:44 2014
@@ -1,0 +1,271 @@
+testinfo:
+    summary: 'Test manager commands that add and remove dialplan extensions'
+    description: |
+        'Working from a basic dialplan, some extensions are removed with
+        the DialplanExtensionRemove command while others are added with the
+        DialplanExtensionAdd command in such a way that whole extensions are
+        removed, single priorities of extensions are removed, priorities in
+        existing extensions are replaced, and new extensions are created.
+        Afterwards, calls are originated to each of the extensions involved
+        to make sure that all events for the remaining extensions and the
+        new extensions are received while calls to extensions and priorities
+        that were removed/replaced do not generate any such events.'
+
+test-modules:
+    add-test-to-search-path: 'True'
+    test-object:
+        config-section: 'control-config'
+        typename: 'ami_extension_control.AMIExtensionControl'
+    modules:
+        -
+            config-section: 'ami-events-config'
+            typename: 'ami.AMIEventModule'
+
+control-config:
+    commands:
+        -
+            # Test 1: Simple remove existing extension w/ priority
+            expected-response: 'Success'
+            command:
+                Action: 'DialplanExtensionRemove'
+                Context: 'alpha'
+                Extension: 'test1'
+                Priority: '4'
+                ActionID: 'testaction1'
+        -
+            # Test 2: Remove existing whole extension
+            expected-response: 'Success'
+            command:
+                Action: 'DialplanExtensionRemove'
+                Context: 'alpha'
+                Extension: 'test2'
+                ActionID: 'testaction2'
+        -
+            # Test 3: Simple add extension
+            expected-response: 'Success'
+            command:
+                Action: 'DialplanExtensionAdd'
+                Context: 'beta'
+                Extension: 'test3'
+                Priority: '1'
+                Application: 'Answer'
+                ActionID: 'testaction3_1'
+        -
+            expected-response: 'Success'
+            command:
+                Action: 'DialplanExtensionAdd'
+                Context: 'beta'
+                Extension: 'test3'
+                Priority: '2'
+                Application: 'UserEvent'
+                ApplicationData: 'ExtensionTest,Expected: Yes,Extension: ${EXTEN}'
+                ActionID: 'testaction3_2'
+        -
+            # Test 4: Add Extension with CID matching that won't match
+            expected-response: 'Success'
+            command:
+                Action: 'DialplanExtensionAdd'
+                Context: 'beta'
+                Extension: 'test4/unmatchable'
+                Priority: '1'
+                Application: 'Answer'
+                ActionID: 'testaction4_1'
+        -
+            expected-response: 'Success'
+            command:
+                Action: 'DialplanExtensionAdd'
+                Context: 'beta'
+                Extension: 'test4/unmatchable'
+                Priority: '2'
+                Application: 'UserEvent'
+                ApplicationData: 'ExtensionTest,Expected: No,Extension: ${EXTEN}'
+                ActionID: 'testaction4_2'
+        -
+            # Test 5: Add Extension with CID matching that will match
+            expected-response: 'Success'
+            command:
+                Action: 'DialplanExtensionAdd'
+                Context: 'beta'
+                Extension: 'test5/1337'
+                Priority: '1'
+                Application: 'Answer'
+                ActionID: 'testaction5_1'
+        -
+            expected-response: 'Success'
+            command:
+                Action: 'DialplanExtensionAdd'
+                Context: 'beta'
+                Extension: 'test5/1337'
+                Priority: '2'
+                Application: 'UserEvent'
+                ApplicationData: 'ExtensionTest,Expected: Yes,Extension: ${EXTEN}'
+                ActionID: 'testaction5_2'
+        -
+            # Test 6: Add Extension that replaces an existing priority
+            expected-response: 'Success'
+            command:
+                Action: 'DialplanExtensionAdd'
+                Context: 'alpha'
+                Extension: 'test6'
+                Priority: '3'
+                Application: 'UserEvent'
+                ApplicationData: 'ExtensionTest,Expected: Yes,Extension: ${EXTEN}'
+                Replace: 'yes'
+                ActionID: 'testaction6'
+        -
+            # Test 7: Failure to add extension because it already exists
+            expected-response: 'Error'
+            command:
+                Action: 'DialplanExtensionAdd'
+                Context: 'alpha'
+                Extension: 'test7'
+                Priority: '3'
+                Application: 'UserEvent'
+                ApplicationData: 'ExtensionTest,Expected: No,Extension: ${EXTEN}'
+                Replace: 'no'
+                ActionID: 'testaction7'
+        -
+            # Test 8: Remove an extension with caller ID matching
+            expected-response: 'Success'
+            command:
+                Action: 'DialplanExtensionRemove'
+                Context: 'alpha'
+                Extension: 'test8/1337'
+                Priority: '4'
+                ActionID: 'testaction8'
+        -
+            # Test 9: Failure to add extension because a priority isn't set
+            # No originate needed to test this
+            expected-response: 'Error'
+            command:
+                Action: 'DialplanExtensionAdd'
+                Context: 'beta'
+                Extension: 'test9'
+                Application: 'NoOp'
+                ActionID: 'testaction9'
+        -
+            # Test 10: Failure to add extension because application isn't set
+            # No originate needed to test this
+            expected-response: 'Error'
+            command:
+                Action: 'DialplanExtensionAdd'
+                Context: 'beta'
+                Extension: 'test10'
+                Priority: '1'
+                ActionID: 'testaction10'
+        -
+            # Test 11: Failure to remove extension because it doesn't exist
+            # No originate needed to test this
+            expected-response: 'Error'
+            command:
+                Action: 'DialplanExtensionRemove'
+                Context: 'alpha'
+                Extension: 'test11'
+                ActionID: 'testaction11'
+
+    originates:
+        -
+            channel: 'LOCAL/test1 at alpha'
+        -
+            channel: 'LOCAL/test2 at alpha'
+        -
+            channel: 'LOCAL/test3 at beta'
+        -
+            channel: 'LOCAL/test4 at beta'
+        -
+            channel: 'LOCAL/test5 at beta'
+        -
+            channel: 'LOCAL/test6 at alpha'
+        -
+            channel: 'LOCAL/test7 at alpha'
+        -
+            channel: 'LOCAL/test8 at alpha'
+
+ami-events-config:
+    -
+        type: 'headermatch'
+        conditions:
+            match:
+                Event: 'UserEvent'
+                UserEvent: 'ExtensionTest'
+                Expected: 'Yes'
+                Extension: 'test1'
+        count: '1'
+    -
+        type: 'headermatch'
+        conditions:
+            match:
+                Event: 'UserEvent'
+                UserEvent: 'ExtensionDNE'
+                Extension: 'test2'
+        count: '1'
+    -
+        type: 'headermatch'
+        conditions:
+            match:
+                Event: 'UserEvent'
+                UserEvent: 'ExtensionTest'
+                Expected: 'Yes'
+                Extension: 'test3'
+        count: '1'
+    -
+        type: 'headermatch'
+        conditions:
+            match:
+                Event: 'UserEvent'
+                UserEvent: 'ExtensionDNE'
+                Extension: 'test4'
+        count: '1'
+    -
+        type: 'headermatch'
+        conditions:
+            match:
+                Event: 'UserEvent'
+                UserEvent: 'ExtensionTest'
+                Expected: 'Yes'
+                Extension: 'test5'
+        count: '1'
+    -
+        type: 'headermatch'
+        conditions:
+            match:
+                Event: 'UserEvent'
+                UserEvent: 'ExtensionTest'
+                Expected: 'Yes'
+                Extension: 'test6'
+        count: '1'
+    -
+        type: 'headermatch'
+        conditions:
+            match:
+                Event: 'UserEvent'
+                UserEvent: 'ExtensionTest'
+                Expected: 'Yes'
+                Extension: 'test7'
+        count: '1'
+    -
+        type: 'headermatch'
+        conditions:
+            match:
+                Event: 'UserEvent'
+                UserEvent: 'ExtensionTest'
+                Expected: 'Yes'
+                Extension: 'test8'
+        count: '1'
+    -
+        type: 'headermatch'
+        conditions:
+            match:
+                Event: 'UserEvent'
+                UserEvent: 'ExtensionTest'
+                Expected: 'No'
+        count: '0'
+
+
+properties:
+    minversion: '13.0.0'
+    dependencies:
+        - python : 'twisted'
+        - python : 'starpy'
+    tags:
+        - pbx

Propchange: asterisk/trunk/tests/pbx/manager_extensions/test-config.yaml
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: asterisk/trunk/tests/pbx/manager_extensions/test-config.yaml
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision

Propchange: asterisk/trunk/tests/pbx/manager_extensions/test-config.yaml
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: asterisk/trunk/tests/pbx/tests.yaml
URL: http://svnview.digium.com/svn/testsuite/asterisk/trunk/tests/pbx/tests.yaml?view=diff&rev=5249&r1=5248&r2=5249
==============================================================================
--- asterisk/trunk/tests/pbx/tests.yaml (original)
+++ asterisk/trunk/tests/pbx/tests.yaml Wed Jul 16 13:51:44 2014
@@ -12,6 +12,7 @@
     - test: 'dialplan_reload'
     - test: 'pbx_lua_goto'
     - test: 'pbx_lua_background'
+    - test: 'manager_extensions'
     # this test currently doesn't work due to a bug (ASTERISK-18230)
     #- test: 'merge_contexts'
     # Temporarily disabled while failures are debugged




More information about the asterisk-commits mailing list