<p>Friendly Automation <strong>submitted</strong> this change.</p><p><a href="https://gerrit.asterisk.org/c/testsuite/+/19218">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span></span><br></pre><div style="white-space:pre-wrap">Approvals:
  George Joseph: Looks good to me, approved
  Friendly Automation: Approved for Submit

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">testsuite: NOTIFY count tests unstable<br><br>scenario_iterator - new asterisk testsuite py module to allow<br>iteration of tests that require a series of sipp scenario(s)<br>+ ami event(s) pairs.  Each iteration is started at the stop<br>of the previous to prevent collision.<br><br>mwi_aggregate and mailbox_count_changes - modified to use<br>this new method<br><br>ASTERISK-30214<br><br>Change-Id: Ic7f318bc953416ff8d8673ed4768fef264046fe3<br>---<br>A lib/python/asterisk/scenario_iterator.py<br>M tests/channels/pjsip/subscriptions/mwi/mwi_aggregate/mwi_check.py<br>M tests/channels/pjsip/subscriptions/mwi/mwi_aggregate/test-config.yaml<br>M tests/channels/pjsip/subscriptions/mwi/unsolicited/mailbox_count_changes/mwi_check.py<br>M tests/channels/pjsip/subscriptions/mwi/unsolicited/mailbox_count_changes/test-config.yaml<br>5 files changed, 329 insertions(+), 73 deletions(-)<br><br></pre>
<pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/lib/python/asterisk/scenario_iterator.py b/lib/python/asterisk/scenario_iterator.py</span><br><span>new file mode 100644</span><br><span>index 0000000..cff1af3</span><br><span>--- /dev/null</span><br><span>+++ b/lib/python/asterisk/scenario_iterator.py</span><br><span>@@ -0,0 +1,231 @@</span><br><span style="color: hsl(120, 100%, 40%);">+'''</span><br><span style="color: hsl(120, 100%, 40%);">+Copyright (C) 2022, Sangoma Technologies Corp</span><br><span style="color: hsl(120, 100%, 40%);">+Mike Bradeen <mbradeen@sangoma.com></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+This program is free software, distributed under the terms of</span><br><span style="color: hsl(120, 100%, 40%);">+the GNU General Public License Version 2.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+The scenario_iterator is designed to let us start sipp, then perform an ami</span><br><span style="color: hsl(120, 100%, 40%);">+action as a cycle of start sipp->generate event(s)->sipp stops, start sipp...</span><br><span style="color: hsl(120, 100%, 40%);">+This is for tests that are performing the same test different ways or performing</span><br><span style="color: hsl(120, 100%, 40%);">+different iterations of the same test.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+An example would be to start a scenario that waits for a NOTIFY, then send the AMI</span><br><span style="color: hsl(120, 100%, 40%);">+to generate that NOTIFY, then starts a second scenario, send a second AMI, etc.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+There are two classes for this, the singleIterator and the multiIterator.  The</span><br><span style="color: hsl(120, 100%, 40%);">+singleIterator is one-to-one, with each scenario start triggering the next ami and the</span><br><span style="color: hsl(120, 100%, 40%);">+scenario stop triggering the next scenario start.  It is fed a pair of lists, one is a</span><br><span style="color: hsl(120, 100%, 40%);">+list of scenarios and the other is a list of AMI actions.  After the final scenario,</span><br><span style="color: hsl(120, 100%, 40%);">+we add a 'done' indicator to the sipp side and a final event on the AMI side, example:</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+scenarios = [</span><br><span style="color: hsl(120, 100%, 40%);">+    {'Name': 'none'},</span><br><span style="color: hsl(120, 100%, 40%);">+    {'Name': 'alice-is-notified-1.xml', 'port': '5061', 'target': '127.0.0.1'},</span><br><span style="color: hsl(120, 100%, 40%);">+    {'Name': 'alice-is-notified-2.xml', 'port': '5061', 'target': '127.0.0.1'},</span><br><span style="color: hsl(120, 100%, 40%);">+    {'Name': 'done'}</span><br><span style="color: hsl(120, 100%, 40%);">+]</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+actions = [</span><br><span style="color: hsl(120, 100%, 40%);">+    {'Action': 'UserEvent', 'UserEvent': 'testStarted'}</span><br><span style="color: hsl(120, 100%, 40%);">+    {'Action': 'MWIUpdate', 'Mailbox': 'alice', 'NewMessages':'2', 'OldMessages':'0'},</span><br><span style="color: hsl(120, 100%, 40%);">+    {'Action': 'MWIDelete', 'Mailbox': 'alice'},</span><br><span style="color: hsl(120, 100%, 40%);">+    {'Action': 'UserEvent', 'UserEvent': 'testComplete'}</span><br><span style="color: hsl(120, 100%, 40%);">+]</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+You then define a local instance and run it:</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def start_test(test_object, junk):</span><br><span style="color: hsl(120, 100%, 40%);">+    testrunner = singleIterator(test_object, scenarios, actions)</span><br><span style="color: hsl(120, 100%, 40%);">+    testrunner.run(junk)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+The multiIterator is a many-to-many mapper that allows multiple scenarios to be started, followed</span><br><span style="color: hsl(120, 100%, 40%);">+by multiple actions.  The end of the last scenario in the list causes the next scenario to start.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Multiple sequences can be tied to individual actions, or vice versa. In this example we start two</span><br><span style="color: hsl(120, 100%, 40%);">+scenarios but then only generate one corresponding AMI:</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+scenarios = [</span><br><span style="color: hsl(120, 100%, 40%);">+        {'Name': 'mailbox_a', 'sequence': [</span><br><span style="color: hsl(120, 100%, 40%);">+            {'Name': 'alice-is-notified-1.xml', 'port': '5061', 'target': '127.0.0.1'},</span><br><span style="color: hsl(120, 100%, 40%);">+            {'Name': 'bob-is-notified-1.xml', 'port': '5062', 'target': '127.0.0.1'} ]},</span><br><span style="color: hsl(120, 100%, 40%);">+        {'Name': 'done'}</span><br><span style="color: hsl(120, 100%, 40%);">+]</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+actions = [</span><br><span style="color: hsl(120, 100%, 40%);">+        {'Messages': [{'Action': 'MWIUpdate', 'Mailbox': 'mailbox_a', 'NewMessages':'2', 'OldMessages':'1'}]},</span><br><span style="color: hsl(120, 100%, 40%);">+        {'Messages': [{'Action': 'UserEvent', 'UserEvent': 'testComplete'}]}</span><br><span style="color: hsl(120, 100%, 40%);">+]</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+In the above examples, we end the test with a testComplete event that we then use to trigger the</span><br><span style="color: hsl(120, 100%, 40%);">+test stop event in the corresponding yaml file, example:</span><br><span style="color: hsl(120, 100%, 40%);">+ami-config:</span><br><span style="color: hsl(120, 100%, 40%);">+    -</span><br><span style="color: hsl(120, 100%, 40%);">+        ami-events:</span><br><span style="color: hsl(120, 100%, 40%);">+            conditions:</span><br><span style="color: hsl(120, 100%, 40%);">+                match:</span><br><span style="color: hsl(120, 100%, 40%);">+                    Event: 'UserEvent'</span><br><span style="color: hsl(120, 100%, 40%);">+                    UserEvent: 'testComplete'</span><br><span style="color: hsl(120, 100%, 40%);">+            count: 1</span><br><span style="color: hsl(120, 100%, 40%);">+        stop_test:</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Also, this test REQUIRES the following be set in the sipp configuration section of your yaml file if</span><br><span style="color: hsl(120, 100%, 40%);">+you are using a sipp scenario (like a REGISTER) to kick off the sequnce:</span><br><span style="color: hsl(120, 100%, 40%);">+    stop-after-scenarios: False</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+A Name of 'none' for a scenario(list) or an Action of 'none' skips that particular scenario or action,</span><br><span style="color: hsl(120, 100%, 40%);">+but not the other. This is mostly to allow one or more AMI events to be triggered before the</span><br><span style="color: hsl(120, 100%, 40%);">+corresponding sipp scenario is started but could also allow for intermediate sipp scenarios. Setting</span><br><span style="color: hsl(120, 100%, 40%);">+both to 'none' would be functionally the same as waiting for 1 second before going on to the next</span><br><span style="color: hsl(120, 100%, 40%);">+iteration.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+'''</span><br><span style="color: hsl(120, 100%, 40%);">+from asterisk.sipp import SIPpScenarioSequence</span><br><span style="color: hsl(120, 100%, 40%);">+from asterisk.sipp import SIPpScenario</span><br><span style="color: hsl(120, 100%, 40%);">+from twisted.internet import reactor</span><br><span style="color: hsl(120, 100%, 40%);">+import sys</span><br><span style="color: hsl(120, 100%, 40%);">+import logging</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+sys.path.append("lib/python")</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+LOGGER = logging.getLogger(__name__)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+sipp_terminator = {'Name': 'done'}</span><br><span style="color: hsl(120, 100%, 40%);">+empty_action = {'Action': 'none'}</span><br><span style="color: hsl(120, 100%, 40%);">+empty_action_list = {'Messages': [{'Action': 'none'}] }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+class singleIterator(object):</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def __init__(self, test_object, scenarios, actions):</span><br><span style="color: hsl(120, 100%, 40%);">+        self.test_object = test_object</span><br><span style="color: hsl(120, 100%, 40%);">+        self.scenarios = scenarios</span><br><span style="color: hsl(120, 100%, 40%);">+        self.actions = actions</span><br><span style="color: hsl(120, 100%, 40%);">+        self.iteration = 0</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def __iterate(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        try:</span><br><span style="color: hsl(120, 100%, 40%);">+            scenario = self.scenarios[self.iteration]</span><br><span style="color: hsl(120, 100%, 40%);">+        except IndexError:</span><br><span style="color: hsl(120, 100%, 40%);">+            LOGGER.warning("End of scenario list without proper termination")</span><br><span style="color: hsl(120, 100%, 40%);">+            scenario = sipp_terminator</span><br><span style="color: hsl(120, 100%, 40%);">+        try:</span><br><span style="color: hsl(120, 100%, 40%);">+            message = self.actions[self.iteration]</span><br><span style="color: hsl(120, 100%, 40%);">+        except IndexError:</span><br><span style="color: hsl(120, 100%, 40%);">+            LOGGER.warning("End of action list without proper termination")</span><br><span style="color: hsl(120, 100%, 40%);">+            message = empty_action</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        self.iteration += 1</span><br><span style="color: hsl(120, 100%, 40%);">+        if scenario['Name'] == 'none':</span><br><span style="color: hsl(120, 100%, 40%);">+            # skip ahead to the next iteration but send the AMI</span><br><span style="color: hsl(120, 100%, 40%);">+            # action if set. Speed up the iteration.</span><br><span style="color: hsl(120, 100%, 40%);">+            self.__sendMessage(message, 0)</span><br><span style="color: hsl(120, 100%, 40%);">+            reactor.callLater(1, self.run)</span><br><span style="color: hsl(120, 100%, 40%);">+        elif scenario['Name'] != 'done':</span><br><span style="color: hsl(120, 100%, 40%);">+            # A scenaro was specified so run it then schedule the</span><br><span style="color: hsl(120, 100%, 40%);">+            # AMI event if there is one.</span><br><span style="color: hsl(120, 100%, 40%);">+            self.__startScenario(scenario)</span><br><span style="color: hsl(120, 100%, 40%);">+            self.__sendMessage(message)</span><br><span style="color: hsl(120, 100%, 40%);">+        else:</span><br><span style="color: hsl(120, 100%, 40%);">+            # At the final iteration, send any final AMI immediately</span><br><span style="color: hsl(120, 100%, 40%);">+            self.__sendMessage(message, 0)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def __startScenario(self, scenario):</span><br><span style="color: hsl(120, 100%, 40%);">+        LOGGER.info("Starting sipp scenario %s" % scenario['Name'])</span><br><span style="color: hsl(120, 100%, 40%);">+        sipp_scenario = SIPpScenario(self.test_object.test_name,</span><br><span style="color: hsl(120, 100%, 40%);">+                                     {'scenario': scenario['Name'],</span><br><span style="color: hsl(120, 100%, 40%);">+                                      '-p': scenario['port']},</span><br><span style="color: hsl(120, 100%, 40%);">+                                     target=scenario['target'])</span><br><span style="color: hsl(120, 100%, 40%);">+        exiter = sipp_scenario.run(self.test_object)</span><br><span style="color: hsl(120, 100%, 40%);">+        exiter.addCallback(self.run)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def __sendMessage(self, message, delay=2):</span><br><span style="color: hsl(120, 100%, 40%);">+        if message['Action'] != 'none':</span><br><span style="color: hsl(120, 100%, 40%);">+            testami = self.test_object.ami[0]</span><br><span style="color: hsl(120, 100%, 40%);">+            LOGGER.info("Scheduling AMI %s" % message['Action'])</span><br><span style="color: hsl(120, 100%, 40%);">+            reactor.callLater(delay, testami.sendMessage, message)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def run(self, junk=None):</span><br><span style="color: hsl(120, 100%, 40%);">+        self.__iterate()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+class multiIterator(object):</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def __init__(self, test_object, scenariosequences, actions):</span><br><span style="color: hsl(120, 100%, 40%);">+        self.test_object = test_object</span><br><span style="color: hsl(120, 100%, 40%);">+        self.scenariosequences = scenariosequences</span><br><span style="color: hsl(120, 100%, 40%);">+        self.actions = actions</span><br><span style="color: hsl(120, 100%, 40%);">+        self.iteration = 0</span><br><span style="color: hsl(120, 100%, 40%);">+        self.sequencecounter = 1</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def __iterate(self):</span><br><span style="color: hsl(120, 100%, 40%);">+        try:</span><br><span style="color: hsl(120, 100%, 40%);">+            sippsequence = self.scenariosequences[self.iteration]</span><br><span style="color: hsl(120, 100%, 40%);">+        except IndexError:</span><br><span style="color: hsl(120, 100%, 40%);">+            LOGGER.warning("End of scenarios list without proper termination")</span><br><span style="color: hsl(120, 100%, 40%);">+            sippsequence = sipp_terminator</span><br><span style="color: hsl(120, 100%, 40%);">+        try:</span><br><span style="color: hsl(120, 100%, 40%);">+            messagesequence = self.actions[self.iteration]</span><br><span style="color: hsl(120, 100%, 40%);">+        except IndexError:</span><br><span style="color: hsl(120, 100%, 40%);">+            LOGGER.warning("End of action list without proper termination")</span><br><span style="color: hsl(120, 100%, 40%);">+            messagesequence = empty_action_list</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        self.iteration += 1</span><br><span style="color: hsl(120, 100%, 40%);">+        if sippsequence['Name'] == 'none':</span><br><span style="color: hsl(120, 100%, 40%);">+            # skip ahead to the next iteration but send any AMI actions if</span><br><span style="color: hsl(120, 100%, 40%);">+            # set, one second apart. Run the next iteration based on how far</span><br><span style="color: hsl(120, 100%, 40%);">+            # out we've scheduled messages.</span><br><span style="color: hsl(120, 100%, 40%);">+            sequencedelay = self.__sendMessages(messagesequence['Messages'], 1)</span><br><span style="color: hsl(120, 100%, 40%);">+            reactor.callLater(sequencedelay, self.run)</span><br><span style="color: hsl(120, 100%, 40%);">+        elif sippsequence['Name'] != 'done':</span><br><span style="color: hsl(120, 100%, 40%);">+            # A scenaro sequence was specified so run it then schedule the</span><br><span style="color: hsl(120, 100%, 40%);">+            # AMI event(s) normally. Set the delay equal to how many scenarios</span><br><span style="color: hsl(120, 100%, 40%);">+            # were registered (as seconds) to try and scale against complexity</span><br><span style="color: hsl(120, 100%, 40%);">+            LOGGER.info("Starting sipp sequence %s" % sippsequence['Name'])</span><br><span style="color: hsl(120, 100%, 40%);">+            self.__startScenarios(sippsequence['sequence'])</span><br><span style="color: hsl(120, 100%, 40%);">+            self.__sendMessages(messagesequence['Messages'], self.sequencecounter)</span><br><span style="color: hsl(120, 100%, 40%);">+        else:</span><br><span style="color: hsl(120, 100%, 40%);">+            # At the final iteration, send any final AMI</span><br><span style="color: hsl(120, 100%, 40%);">+            sequencedelay = self.__sendMessages(messagesequence['Messages'], 0)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def __startScenarios(self, sippscenarios):</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        sipp_sequence = SIPpScenarioSequence(self.test_object,</span><br><span style="color: hsl(120, 100%, 40%);">+                                             fail_on_any=True,</span><br><span style="color: hsl(120, 100%, 40%);">+                                             stop_on_done=False)</span><br><span style="color: hsl(120, 100%, 40%);">+        self.sequencecounter = 0</span><br><span style="color: hsl(120, 100%, 40%);">+        for scenario in sippscenarios:</span><br><span style="color: hsl(120, 100%, 40%);">+            LOGGER.info("Adding scenario %s to sequence" % scenario['Name'])</span><br><span style="color: hsl(120, 100%, 40%);">+            sipp_scenario = SIPpScenario(self.test_object.test_name,</span><br><span style="color: hsl(120, 100%, 40%);">+                                         {'scenario': scenario['Name'],</span><br><span style="color: hsl(120, 100%, 40%);">+                                          '-p': scenario['port']},</span><br><span style="color: hsl(120, 100%, 40%);">+                                         target=scenario['target'])</span><br><span style="color: hsl(120, 100%, 40%);">+            sipp_sequence.register_scenario(sipp_scenario)</span><br><span style="color: hsl(120, 100%, 40%);">+            # keep track of how many scenarios we register so we don't</span><br><span style="color: hsl(120, 100%, 40%);">+            # iterate until we have stop_callback hits for all of them</span><br><span style="color: hsl(120, 100%, 40%);">+            self.sequencecounter += 1</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        sipp_sequence.register_scenario_stop_callback(self.run)</span><br><span style="color: hsl(120, 100%, 40%);">+        sipp_sequence.execute()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def __sendMessages(self, messages, delay = 2):</span><br><span style="color: hsl(120, 100%, 40%);">+        testami = self.test_object.ami[0]</span><br><span style="color: hsl(120, 100%, 40%);">+        messagedelay = delay</span><br><span style="color: hsl(120, 100%, 40%);">+        for message in messages:</span><br><span style="color: hsl(120, 100%, 40%);">+            if message['Action'] !='none':</span><br><span style="color: hsl(120, 100%, 40%);">+                LOGGER.info("Scheduling AMI %s" % message['Action'])</span><br><span style="color: hsl(120, 100%, 40%);">+                reactor.callLater(delay, testami.sendMessage, message)</span><br><span style="color: hsl(120, 100%, 40%);">+                # spread out the messages by 2 seconds</span><br><span style="color: hsl(120, 100%, 40%);">+                messagedelay += 2</span><br><span style="color: hsl(120, 100%, 40%);">+        # return last action's delay + 2, ie when to run the next</span><br><span style="color: hsl(120, 100%, 40%);">+        # command if you want it evenly distributed and after the</span><br><span style="color: hsl(120, 100%, 40%);">+        # last message scheduled here</span><br><span style="color: hsl(120, 100%, 40%);">+        return messagedelay</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    def run(self, junk=None):</span><br><span style="color: hsl(120, 100%, 40%);">+        # only run the next iteration once there is a call-back for</span><br><span style="color: hsl(120, 100%, 40%);">+        # each sipp scenario in the sequence.  Otherwise, decrement</span><br><span style="color: hsl(120, 100%, 40%);">+        # until we get there</span><br><span style="color: hsl(120, 100%, 40%);">+        if self.sequencecounter == 1:</span><br><span style="color: hsl(120, 100%, 40%);">+            self.__iterate()</span><br><span style="color: hsl(120, 100%, 40%);">+        else:</span><br><span style="color: hsl(120, 100%, 40%);">+            self.sequencecounter -= 1</span><br><span>diff --git a/tests/channels/pjsip/subscriptions/mwi/mwi_aggregate/mwi_check.py b/tests/channels/pjsip/subscriptions/mwi/mwi_aggregate/mwi_check.py</span><br><span>index 9a5d5e3..9fadeb0 100644</span><br><span>--- a/tests/channels/pjsip/subscriptions/mwi/mwi_aggregate/mwi_check.py</span><br><span>+++ b/tests/channels/pjsip/subscriptions/mwi/mwi_aggregate/mwi_check.py</span><br><span>@@ -8,32 +8,39 @@</span><br><span> the GNU General Public License Version 2.</span><br><span> """</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+import mailbox</span><br><span> import sys</span><br><span> import logging</span><br><span> </span><br><span> sys.path.append("lib/python")</span><br><span style="color: hsl(0, 100%, 40%);">-from twisted.internet import reactor</span><br><span style="color: hsl(120, 100%, 40%);">+from asterisk.scenario_iterator import multiIterator</span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-mwis = [</span><br><span style="color: hsl(0, 100%, 40%);">-    {'mailbox': 'mailbox_a', 'new': '2', 'old': '1'},</span><br><span style="color: hsl(0, 100%, 40%);">-    {'mailbox': 'mailbox_b', 'new': '3', 'old': '3'},</span><br><span style="color: hsl(120, 100%, 40%);">+mwiscenarios = [</span><br><span style="color: hsl(120, 100%, 40%);">+        {'Name': 'mailbox_a', 'sequence': [</span><br><span style="color: hsl(120, 100%, 40%);">+                {'Name': 'alice-is-notified-1.xml', 'port': '5061', 'target': '127.0.0.1'},</span><br><span style="color: hsl(120, 100%, 40%);">+                {'Name': 'bob-is-notified-1.xml', 'port': '5062', 'target': '127.0.0.1'} ]},</span><br><span style="color: hsl(120, 100%, 40%);">+        {'Name': 'mailbox_b', 'sequence': [</span><br><span style="color: hsl(120, 100%, 40%);">+                {'Name': 'alice-is-notified-2.xml', 'port': '5061', 'target': '127.0.0.1'},</span><br><span style="color: hsl(120, 100%, 40%);">+                {'Name': 'bob-is-notified-2.xml', 'port': '5062', 'target': '127.0.0.1'} ]},</span><br><span style="color: hsl(120, 100%, 40%);">+        {'Name': 'done'}</span><br><span> ]</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-def walk_states(test_object, accounts):</span><br><span style="color: hsl(120, 100%, 40%);">+mwis = [</span><br><span style="color: hsl(120, 100%, 40%);">+        {'Messages': [</span><br><span style="color: hsl(120, 100%, 40%);">+                {'Action': 'MWIUpdate', 'Mailbox': 'mailbox_a', 'NewMessages':'2', 'OldMessages':'1'} ]},</span><br><span style="color: hsl(120, 100%, 40%);">+        {'Messages': [</span><br><span style="color: hsl(120, 100%, 40%);">+                {'Action': 'MWIUpdate', 'Mailbox': 'mailbox_b', 'NewMessages':'3', 'OldMessages':'3'} ]},</span><br><span style="color: hsl(120, 100%, 40%);">+        {'Messages': [</span><br><span style="color: hsl(120, 100%, 40%);">+                {'Action': 'UserEvent', 'UserEvent': 'testComplete'} ]}</span><br><span style="color: hsl(120, 100%, 40%);">+]</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-    testami = test_object.ami[0]</span><br><span style="color: hsl(0, 100%, 40%);">-    statedelay = 2</span><br><span style="color: hsl(0, 100%, 40%);">-    for mwi in mwis:</span><br><span style="color: hsl(0, 100%, 40%);">-        LOGGER.info("Sending MWI update. new: %s, old %s" %</span><br><span style="color: hsl(0, 100%, 40%);">-                    (mwi['new'],</span><br><span style="color: hsl(0, 100%, 40%);">-                     mwi['old']))</span><br><span style="color: hsl(0, 100%, 40%);">-        message = {</span><br><span style="color: hsl(0, 100%, 40%);">-            'Action': 'MWIUpdate',</span><br><span style="color: hsl(0, 100%, 40%);">-            'Mailbox': mwi['mailbox'],</span><br><span style="color: hsl(0, 100%, 40%);">-            'NewMessages': mwi['new'],</span><br><span style="color: hsl(0, 100%, 40%);">-            'OldMessages': mwi['old']</span><br><span style="color: hsl(0, 100%, 40%);">-        }</span><br><span style="color: hsl(0, 100%, 40%);">-        reactor.callLater(statedelay, testami.sendMessage, message)</span><br><span style="color: hsl(0, 100%, 40%);">-        statedelay += 1</span><br><span style="color: hsl(120, 100%, 40%);">+def start_test(test_object, junk):</span><br><span style="color: hsl(120, 100%, 40%);">+    LOGGER.info("Starting mwi_check")</span><br><span style="color: hsl(120, 100%, 40%);">+    testrunner = multiIterator(test_object, mwiscenarios, mwis)</span><br><span style="color: hsl(120, 100%, 40%);">+    testrunner.run(junk)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def stop_test():</span><br><span style="color: hsl(120, 100%, 40%);">+    return</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>diff --git a/tests/channels/pjsip/subscriptions/mwi/mwi_aggregate/test-config.yaml b/tests/channels/pjsip/subscriptions/mwi/mwi_aggregate/test-config.yaml</span><br><span>index 48a0971..cabe5e2 100644</span><br><span>--- a/tests/channels/pjsip/subscriptions/mwi/mwi_aggregate/test-config.yaml</span><br><span>+++ b/tests/channels/pjsip/subscriptions/mwi/mwi_aggregate/test-config.yaml</span><br><span>@@ -1,5 +1,4 @@</span><br><span> testinfo:</span><br><span style="color: hsl(0, 100%, 40%);">-    skip: 'Unstable - ASTERISK-30214'</span><br><span>     summary:     'Ensures mailbox state is aggregated or not aggregated when appropriate'</span><br><span>     description: |</span><br><span>         "Alice and Bob both receive mailbox updates for mailbox_a and mailbox_b. However, Alice</span><br><span>@@ -30,13 +29,18 @@</span><br><span>     test-object:</span><br><span>         config-section: sipp-config</span><br><span>         typename: 'sipp.SIPpTestCase'</span><br><span style="color: hsl(120, 100%, 40%);">+    modules:</span><br><span style="color: hsl(120, 100%, 40%);">+        -</span><br><span style="color: hsl(120, 100%, 40%);">+            config-section: 'ami-config'</span><br><span style="color: hsl(120, 100%, 40%);">+            typename: 'pluggable_modules.EventActionModule'</span><br><span> </span><br><span> sipp-config:</span><br><span>     connect-ami: 'True'</span><br><span>     reactor-timeout: 30</span><br><span>     fail-on-any: True</span><br><span style="color: hsl(0, 100%, 40%);">-    start_callback_module: 'mwi_check'</span><br><span style="color: hsl(0, 100%, 40%);">-    start_callback_method: 'walk_states'</span><br><span style="color: hsl(120, 100%, 40%);">+    stop-after-scenarios: False</span><br><span style="color: hsl(120, 100%, 40%);">+    stop_callback_module: 'mwi_check'</span><br><span style="color: hsl(120, 100%, 40%);">+    stop_callback_method: 'start_test'</span><br><span>     test-iterations:</span><br><span>         # We pass the initial registers the -aa flag then let them run for a second so they can get the</span><br><span>         # 1-2 initial NOTIFY messages we don't care about.  The MWI AMI updates are set to start after</span><br><span>@@ -46,12 +50,12 @@</span><br><span>                     'ordered-args': {'-aa'} }</span><br><span>                 - { 'key-args': {'scenario': 'bob-registers.xml', '-p': '5062'},</span><br><span>                     'ordered-args': {'-aa'}  }</span><br><span style="color: hsl(0, 100%, 40%);">-        # Combining this with the -m makes the scripts regex conditional on call_number</span><br><span style="color: hsl(0, 100%, 40%);">-        -</span><br><span style="color: hsl(0, 100%, 40%);">-            scenarios:</span><br><span style="color: hsl(0, 100%, 40%);">-                - { 'key-args': {'scenario': 'alice-is-notified-1.xml', '-p': '5061'} }</span><br><span style="color: hsl(0, 100%, 40%);">-                - { 'key-args': {'scenario': 'bob-is-notified-1.xml', '-p': '5062'} }</span><br><span style="color: hsl(0, 100%, 40%);">-        -</span><br><span style="color: hsl(0, 100%, 40%);">-            scenarios:</span><br><span style="color: hsl(0, 100%, 40%);">-                - { 'key-args': {'scenario': 'alice-is-notified-2.xml', '-p': '5061'} }</span><br><span style="color: hsl(0, 100%, 40%);">-                - { 'key-args': {'scenario': 'bob-is-notified-2.xml', '-p': '5062'} }</span><br><span style="color: hsl(120, 100%, 40%);">+ami-config:</span><br><span style="color: hsl(120, 100%, 40%);">+    -</span><br><span style="color: hsl(120, 100%, 40%);">+        ami-events:</span><br><span style="color: hsl(120, 100%, 40%);">+            conditions:</span><br><span style="color: hsl(120, 100%, 40%);">+                match:</span><br><span style="color: hsl(120, 100%, 40%);">+                    Event: 'UserEvent'</span><br><span style="color: hsl(120, 100%, 40%);">+                    UserEvent: 'testComplete'</span><br><span style="color: hsl(120, 100%, 40%);">+            count: 1</span><br><span style="color: hsl(120, 100%, 40%);">+        stop_test:</span><br><span>diff --git a/tests/channels/pjsip/subscriptions/mwi/unsolicited/mailbox_count_changes/mwi_check.py b/tests/channels/pjsip/subscriptions/mwi/unsolicited/mailbox_count_changes/mwi_check.py</span><br><span>index f5378aa..28c4ded 100644</span><br><span>--- a/tests/channels/pjsip/subscriptions/mwi/unsolicited/mailbox_count_changes/mwi_check.py</span><br><span>+++ b/tests/channels/pjsip/subscriptions/mwi/unsolicited/mailbox_count_changes/mwi_check.py</span><br><span>@@ -6,36 +6,31 @@</span><br><span> sys.path.append("lib/python")</span><br><span> </span><br><span> from twisted.internet import reactor</span><br><span style="color: hsl(120, 100%, 40%);">+from asterisk.scenario_iterator import singleIterator</span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-mwis = [</span><br><span style="color: hsl(0, 100%, 40%);">-        {'new': '2', 'old': '0'},</span><br><span style="color: hsl(0, 100%, 40%);">-        {'new': '1', 'old': '1'},</span><br><span style="color: hsl(0, 100%, 40%);">-        {'new': '0', 'old': '2'},</span><br><span style="color: hsl(120, 100%, 40%);">+mwiscenarios = [</span><br><span style="color: hsl(120, 100%, 40%);">+    {'Name': 'alice-is-notified-1.xml', 'port': '5061', 'target': '127.0.0.1'},</span><br><span style="color: hsl(120, 100%, 40%);">+    {'Name': 'alice-is-notified-2.xml', 'port': '5061', 'target': '127.0.0.1'},</span><br><span style="color: hsl(120, 100%, 40%);">+    {'Name': 'alice-is-notified-3.xml', 'port': '5061', 'target': '127.0.0.1'},</span><br><span style="color: hsl(120, 100%, 40%);">+    {'Name': 'alice-is-notified-4.xml', 'port': '5061', 'target': '127.0.0.1'},</span><br><span style="color: hsl(120, 100%, 40%);">+    {'Name': 'done'}</span><br><span> ]</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-def walk_states(test_object, junk):</span><br><span style="color: hsl(120, 100%, 40%);">+mwis = [</span><br><span style="color: hsl(120, 100%, 40%);">+        {'Action': 'MWIUpdate', 'Mailbox': 'alice', 'NewMessages':'2', 'OldMessages':'0'},</span><br><span style="color: hsl(120, 100%, 40%);">+        {'Action': 'MWIUpdate', 'Mailbox': 'alice', 'NewMessages':'1', 'OldMessages':'1'},</span><br><span style="color: hsl(120, 100%, 40%);">+        {'Action': 'MWIUpdate', 'Mailbox': 'alice', 'NewMessages':'0', 'OldMessages':'2'},</span><br><span style="color: hsl(120, 100%, 40%);">+        {'Action': 'MWIDelete', 'Mailbox': 'alice'},</span><br><span style="color: hsl(120, 100%, 40%);">+        {'Action': 'UserEvent', 'UserEvent': 'testComplete'}</span><br><span style="color: hsl(120, 100%, 40%);">+]</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-    testami = test_object.ami[0]</span><br><span style="color: hsl(0, 100%, 40%);">-    statedelay = 2</span><br><span style="color: hsl(0, 100%, 40%);">-    for mwi in mwis:</span><br><span style="color: hsl(0, 100%, 40%);">-        LOGGER.info("Sending MWI update. new: %s, old %s" %</span><br><span style="color: hsl(0, 100%, 40%);">-                    (mwi['new'],</span><br><span style="color: hsl(0, 100%, 40%);">-                     mwi['old']))</span><br><span style="color: hsl(0, 100%, 40%);">-        message = {</span><br><span style="color: hsl(0, 100%, 40%);">-            'Action': 'MWIUpdate',</span><br><span style="color: hsl(0, 100%, 40%);">-            'Mailbox': 'alice',</span><br><span style="color: hsl(0, 100%, 40%);">-            'NewMessages': mwi['new'],</span><br><span style="color: hsl(0, 100%, 40%);">-            'OldMessages': mwi['old']</span><br><span style="color: hsl(0, 100%, 40%);">-        }</span><br><span style="color: hsl(0, 100%, 40%);">-        reactor.callLater(statedelay, testami.sendMessage, message)</span><br><span style="color: hsl(0, 100%, 40%);">-        statedelay += .25</span><br><span style="color: hsl(120, 100%, 40%);">+def start_test(test_object, junk):</span><br><span style="color: hsl(120, 100%, 40%);">+    LOGGER.info("Starting mwi_check")</span><br><span style="color: hsl(120, 100%, 40%);">+    testrunner = singleIterator(test_object, mwiscenarios, mwis)</span><br><span style="color: hsl(120, 100%, 40%);">+    testrunner.run(junk)</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-    # delete mailbox after walking states</span><br><span style="color: hsl(0, 100%, 40%);">-    LOGGER.info("Deleting Mailbox")</span><br><span style="color: hsl(0, 100%, 40%);">-    message = {</span><br><span style="color: hsl(0, 100%, 40%);">-            'Action': 'MWIDelete',</span><br><span style="color: hsl(0, 100%, 40%);">-            'Mailbox': 'alice',</span><br><span style="color: hsl(0, 100%, 40%);">-        }</span><br><span style="color: hsl(0, 100%, 40%);">-    reactor.callLater(statedelay, testami.sendMessage, message)</span><br><span style="color: hsl(120, 100%, 40%);">+def stop_test():</span><br><span style="color: hsl(120, 100%, 40%);">+    return</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>diff --git a/tests/channels/pjsip/subscriptions/mwi/unsolicited/mailbox_count_changes/test-config.yaml b/tests/channels/pjsip/subscriptions/mwi/unsolicited/mailbox_count_changes/test-config.yaml</span><br><span>index 5cb1150..14f9456 100644</span><br><span>--- a/tests/channels/pjsip/subscriptions/mwi/unsolicited/mailbox_count_changes/test-config.yaml</span><br><span>+++ b/tests/channels/pjsip/subscriptions/mwi/unsolicited/mailbox_count_changes/test-config.yaml</span><br><span>@@ -1,5 +1,4 @@</span><br><span> testinfo:</span><br><span style="color: hsl(0, 100%, 40%);">-    skip: 'See ASTERISK-30214'</span><br><span>     summary:     'Ensures MWI bodies consist of accurate information'</span><br><span>     description: |</span><br><span>         "Unsolicited MWI notifications are sent to an endpoint as mailbox state updates. sipp</span><br><span>@@ -26,13 +25,18 @@</span><br><span>     test-object:</span><br><span>         config-section: sipp-config</span><br><span>         typename: 'sipp.SIPpTestCase'</span><br><span style="color: hsl(120, 100%, 40%);">+    modules:</span><br><span style="color: hsl(120, 100%, 40%);">+        -</span><br><span style="color: hsl(120, 100%, 40%);">+            config-section: 'ami-config'</span><br><span style="color: hsl(120, 100%, 40%);">+            typename: 'pluggable_modules.EventActionModule'</span><br><span> </span><br><span> sipp-config:</span><br><span>     connect-ami: 'True'</span><br><span>     reactor-timeout: 30</span><br><span>     fail-on-any: True</span><br><span style="color: hsl(0, 100%, 40%);">-    start_callback_module: 'mwi_check'</span><br><span style="color: hsl(0, 100%, 40%);">-    start_callback_method: 'walk_states'</span><br><span style="color: hsl(120, 100%, 40%);">+    stop-after-scenarios: False</span><br><span style="color: hsl(120, 100%, 40%);">+    stop_callback_module: 'mwi_check'</span><br><span style="color: hsl(120, 100%, 40%);">+    stop_callback_method: 'start_test'</span><br><span>     test-iterations:</span><br><span>         # We pass the initial registers the -aa flag then let them run for a second so they can get the</span><br><span>         # 1-2 initial NOTIFY messages we don't care about.  The MWI AMI updates are set to start after</span><br><span>@@ -40,16 +44,12 @@</span><br><span>             scenarios:</span><br><span>                 - { 'key-args': {'scenario': 'alice-registers.xml', '-p': '5061'},</span><br><span>                     'ordered-args': {'-aa'} }</span><br><span style="color: hsl(0, 100%, 40%);">-        # Combining this with the -m makes the scripts regex conditional on call_number</span><br><span style="color: hsl(0, 100%, 40%);">-        -</span><br><span style="color: hsl(0, 100%, 40%);">-            scenarios:</span><br><span style="color: hsl(0, 100%, 40%);">-                - { 'key-args': {'scenario': 'alice-is-notified-1.xml', '-p': '5061'} }</span><br><span style="color: hsl(0, 100%, 40%);">-        -</span><br><span style="color: hsl(0, 100%, 40%);">-            scenarios:</span><br><span style="color: hsl(0, 100%, 40%);">-                - { 'key-args': {'scenario': 'alice-is-notified-2.xml', '-p': '5061'} }</span><br><span style="color: hsl(0, 100%, 40%);">-        -</span><br><span style="color: hsl(0, 100%, 40%);">-            scenarios:</span><br><span style="color: hsl(0, 100%, 40%);">-                - { 'key-args': {'scenario': 'alice-is-notified-3.xml', '-p': '5061'} }</span><br><span style="color: hsl(0, 100%, 40%);">-        -</span><br><span style="color: hsl(0, 100%, 40%);">-            scenarios:</span><br><span style="color: hsl(0, 100%, 40%);">-                - { 'key-args': {'scenario': 'alice-is-notified-4.xml', '-p': '5061'} }</span><br><span style="color: hsl(120, 100%, 40%);">+ami-config:</span><br><span style="color: hsl(120, 100%, 40%);">+    -</span><br><span style="color: hsl(120, 100%, 40%);">+        ami-events:</span><br><span style="color: hsl(120, 100%, 40%);">+            conditions:</span><br><span style="color: hsl(120, 100%, 40%);">+                match:</span><br><span style="color: hsl(120, 100%, 40%);">+                    Event: 'UserEvent'</span><br><span style="color: hsl(120, 100%, 40%);">+                    UserEvent: 'testComplete'</span><br><span style="color: hsl(120, 100%, 40%);">+            count: 1</span><br><span style="color: hsl(120, 100%, 40%);">+        stop_test:</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/testsuite/+/19218">change 19218</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/c/testsuite/+/19218"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: testsuite </div>
<div style="display:none"> Gerrit-Branch: 19 </div>
<div style="display:none"> Gerrit-Change-Id: Ic7f318bc953416ff8d8673ed4768fef264046fe3 </div>
<div style="display:none"> Gerrit-Change-Number: 19218 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Michael Bradeen <mbradeen@sangoma.com> </div>
<div style="display:none"> Gerrit-Reviewer: Friendly Automation </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>