<p>Jenkins2 <strong>merged</strong> this change.</p><p><a href="https://gerrit.asterisk.org/9315">View Change</a></p><div style="white-space:pre-wrap">Approvals:
Kevin Harwell: Looks good to me, but someone else must approve
George Joseph: Looks good to me, approved
Jenkins2: Approved for Submit
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">Begin work on python3 compatability.<br><br>* Use explicit relative import syntax.<br>* Correct syntax for print and except.<br>* Fix incorrect usage of IOError in astcdr.py - IOError is not a tuple.<br>* Use items, values instead of iteritems, itervalues.<br>* Use OrderedDict from collections if available (python 2.7+).<br>* Do not unpack tuples from argument list, save tuple to variable then<br> unpack within code.<br>* Use exception handler to import Python3 version of urlencode if the<br> Python2 version fails to import.<br>* Remove unused import unittest from opensslversion.<br>* Move executable tests to separate files to resolve issues with<br> relative imports:<br> - buildoptions<br> - cdr<br> - cel<br> - channel_test_condition<br> - config<br> - lock_test_condition<br> - sip_dialog_test_condition (disabled)<br> - sippversion<br>* Modify utils_socket test to use new harness_shared module.<br>* Remove unused executable flag and shebang from phones.py.<br>* Update self_test script to run tests from new location.<br>* Remove ability to use config.py to display a config file.<br>* Allow PYTHON environmental variable to tell run-local to use a<br> specific python binary.<br>* Execute test_runner.py using python -m syntax. This avoids conflicts<br> between needing to use relative imports for modules but not being<br> allowed to use them in executable scripts.<br>* Encode self.realbase for use with md5 function.<br>* Remove executable flag and shebang from test_runner.py. Remove<br> redundant appending of sys.path.<br>* Modify output for running test and status to print the name of the<br> test instead of the command used to run the test.<br>* Use key= sorter argument to compare sizes of tmp filesystems. This<br> may cause us to use /var/tmp instead of /tmp even if /var/tmp has only<br> a few kilobytes more space but python3 does not support cmp= argument<br> to sorter.<br>* Decode binary to utf-8<br> - CLI output<br> - runtest.py subprocess output<br> - XML printed to stdout<br> - SyncAMI data<br> - SIPp runtime and version output<br>* Update test_runner.load_and_parse_module to check for the module in<br> lib/python/asterisk, make required adjustments if found.<br>* Update __strip_illegal_xml_chars to work with unicode version of<br> str.translate which does not support second argument.<br>* Update import statements from all *.py modules within tests/ to use<br> absolute names for asterisk modules. This is required for python2 to<br> continue functioning with the new way that test_runner must be executed.<br> No attempt has been made to fix python3 compatibility issues in these<br> modules.<br><br>Some tests may pass using python3. Doing so requires using an updated<br>starpy and no python sources within tests/ have been updated. Unit<br>tests from lib/python can be run against python2 and python3 using<br>./self_test.<br><br>The goal of this is for all tests to continue functioning using python2.<br>Some tests may work under python3 but individual tests will need to be<br>addressed separately. For tests which do not contain a run-test script<br>the version of python used to execute ./runtests.py will be used:<br>./runtests.py -t tests/manager/originate<br>python2 ./runtests.py -t tests/manager/originate<br>python3 ./runtests.py -t tests/manager/originate<br><br>These commands will be python, python2 and python3 respectively. The<br>first example where no interpreter is specified uses the shebang from<br>./runtests.py. The interpreter used by ./run-local can be controlled<br>by setting PYTHON environmental variable:<br>PYTHON=python3 ./run-local run -t tests/manager/originate<br><br>Change-Id: If76c2d3e11e4ab4552d0df7841287c8bb2de7918<br>---<br>M lib/python/asterisk/ami.py<br>M lib/python/asterisk/apptest.py<br>M lib/python/asterisk/ari.py<br>M lib/python/asterisk/astconfigparser.py<br>M lib/python/asterisk/astcsv.py<br>M lib/python/asterisk/astdicts.py<br>M lib/python/asterisk/asterisk.py<br>M lib/python/asterisk/bridge_test_case.py<br>M lib/python/asterisk/buildoptions.py<br>M lib/python/asterisk/cdr.py<br>M lib/python/asterisk/cel.py<br>M lib/python/asterisk/channel_test_condition.py<br>M lib/python/asterisk/confbridge.py<br>M lib/python/asterisk/config.py<br>M lib/python/asterisk/fd_test_condition.py<br>M lib/python/asterisk/lock_test_condition.py<br>M lib/python/asterisk/matcher.py<br>M lib/python/asterisk/matcher_listener.py<br>M lib/python/asterisk/opensslversion.py<br>M lib/python/asterisk/originate.py<br>M lib/python/asterisk/pcap.py<br>M lib/python/asterisk/phones.py<br>M lib/python/asterisk/pjsua_mod.py<br>M lib/python/asterisk/pluggable_modules.py<br>M lib/python/asterisk/pluggable_registry.py<br>M lib/python/asterisk/realtime_converter.py<br>M lib/python/asterisk/realtime_odbc_module.py<br>M lib/python/asterisk/realtime_test_module.py<br>A lib/python/asterisk/self_test/harness_shared.py<br>A lib/python/asterisk/self_test/locks-backtrace.txt<br>A lib/python/asterisk/self_test/locks-fail.txt<br>A lib/python/asterisk/self_test/locks-large-multiple-object.txt<br>A lib/python/asterisk/self_test/locks-multiple-objects-no-backtrace.txt<br>A lib/python/asterisk/self_test/locks-pass.txt<br>A lib/python/asterisk/self_test/locks-single-object-no-held-info.txt<br>A lib/python/asterisk/self_test/locks-single-object.txt<br>A lib/python/asterisk/self_test/test_buildoptions.py<br>A lib/python/asterisk/self_test/test_cdr.py<br>A lib/python/asterisk/self_test/test_cel.py<br>A lib/python/asterisk/self_test/test_channel_test_condition.py<br>A lib/python/asterisk/self_test/test_config.py<br>A lib/python/asterisk/self_test/test_lock_test_condition.py<br>R lib/python/asterisk/self_test/test_matcher.py<br>A lib/python/asterisk/self_test/test_sip_dialog_test_condition.py.txt<br>A lib/python/asterisk/self_test/test_sippversion.py<br>M lib/python/asterisk/self_test/test_utils_socket.py<br>M lib/python/asterisk/sip_channel_test_condition.py<br>M lib/python/asterisk/sip_dialog_test_condition.py<br>M lib/python/asterisk/sipp.py<br>M lib/python/asterisk/sippversion.py<br>M lib/python/asterisk/syncami.py<br>M lib/python/asterisk/test_case.py<br>M lib/python/asterisk/test_conditions.py<br>M lib/python/asterisk/test_config.py<br>M lib/python/asterisk/test_runner.py<br>M lib/python/asterisk/test_suite_utils.py<br>M lib/python/asterisk/thread_test_condition.py<br>M lib/python/asterisk/voicemail.py<br>M lib/python/rlmi.py<br>M lib/python/sip_message.py<br>M run-local<br>M runtests.py<br>M self_test<br>M tests/cdr/cdr-tests.py<br>M tests/cdr/sqlite3/cdr_sqlite3.py<br>M tests/channels/SIP/tcpauthlimit/sipp_scenario.py<br>M tests/channels/pjsip/registration/inbound/nominal/contact_acl/ipv4/scenario_generator.py<br>M tests/channels/pjsip/registration/inbound/nominal/contact_acl/ipv6/scenario_generator.py<br>M tests/channels/pjsip/subscriptions/presence/verify_bodies/presence.py<br>M tests/channels/pjsip/subscriptions/rls/rls_test.py<br>M tests/channels/pjsip/transfers/attended_transfer/nominal/packet_sniffer.py<br>M tests/codecs/audio_analyzer.py<br>M tests/codecs/rtp_analyzer.py<br>M tests/hep/hep_capture_node.py<br>M tests/manager/config/ManagerConfigTest.py<br>M tests/manager/device_state_changed/ami_device_state.py<br>M tests/manager/device_state_list/ami_device_state_list.py<br>M tests/manager/exten_state_list/ami_exten_state_list.py<br>M tests/manager/presence_state_changed/ami_presence_state.py<br>M tests/manager/presence_state_list/ami_presence_state_list.py<br>M tests/pbx/manager_extensions/ami_extension_control.py<br>M tests/rest_api/external_interaction/attended_transfer/attended_transfer.py<br>M tests/rest_api/external_interaction/blind_transfer/call_transfer.py<br>M tests/rest_api/message/message_modules.py<br>M usage.py<br>85 files changed, 1,910 insertions(+), 1,841 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/lib/python/asterisk/ami.py b/lib/python/asterisk/ami.py</span><br><span>index fb52d1c..2e0fe4e 100644</span><br><span>--- a/lib/python/asterisk/ami.py</span><br><span>+++ b/lib/python/asterisk/ami.py</span><br><span>@@ -13,7 +13,8 @@</span><br><span> import logging</span><br><span> import re</span><br><span> import json</span><br><span style="color: hsl(0, 100%, 40%);">-from pluggable_registry import PLUGGABLE_EVENT_REGISTRY,\</span><br><span style="color: hsl(120, 100%, 40%);">+from .test_runner import load_and_parse_module</span><br><span style="color: hsl(120, 100%, 40%);">+from .pluggable_registry import PLUGGABLE_EVENT_REGISTRY,\</span><br><span> PLUGGABLE_ACTION_REGISTRY, var_replace</span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span>@@ -361,7 +362,7 @@</span><br><span> lower_key = key.lower()</span><br><span> if lower_key == 'extra':</span><br><span> value = dict((key.lower(), value)</span><br><span style="color: hsl(0, 100%, 40%);">- for key, value in value.iteritems())</span><br><span style="color: hsl(120, 100%, 40%);">+ for key, value in value.items())</span><br><span> self.requirements[lower_key] = value</span><br><span> self.orderings = requirements.get('partialorder') or []</span><br><span> self.named_id = requirements.get('id')</span><br><span>@@ -529,8 +530,7 @@</span><br><span> </span><br><span> def event_callback(self, ami, event):</span><br><span> """Callback called when an event is received from AMI"""</span><br><span style="color: hsl(0, 100%, 40%);">- callback_module = __import__(self.callback_module)</span><br><span style="color: hsl(0, 100%, 40%);">- method = getattr(callback_module, self.callback_method)</span><br><span style="color: hsl(120, 100%, 40%);">+ method = load_and_parse_module(self.callback_module + '.' + self.callback_method)</span><br><span> self.passed = method(ami, event)</span><br><span> if self.passed is None:</span><br><span> LOGGER.error("Callback %s.%s returned None instead of a boolean",</span><br><span>@@ -828,7 +828,7 @@</span><br><span> </span><br><span> def replace_ami_vars(mydict, values):</span><br><span> outdict = {}</span><br><span style="color: hsl(0, 100%, 40%);">- for key, value in mydict.iteritems():</span><br><span style="color: hsl(120, 100%, 40%);">+ for key, value in mydict.items():</span><br><span> outdict[key] = var_replace(value, values)</span><br><span> </span><br><span> return outdict</span><br><span>diff --git a/lib/python/asterisk/apptest.py b/lib/python/asterisk/apptest.py</span><br><span>index 1fc8496..2c33ad9 100644</span><br><span>--- a/lib/python/asterisk/apptest.py</span><br><span>+++ b/lib/python/asterisk/apptest.py</span><br><span>@@ -18,8 +18,8 @@</span><br><span> from twisted.internet import reactor, defer</span><br><span> </span><br><span> sys.path.append("lib/python")</span><br><span style="color: hsl(0, 100%, 40%);">-from test_case import TestCase</span><br><span style="color: hsl(0, 100%, 40%);">-from ami import AMIEventInstance</span><br><span style="color: hsl(120, 100%, 40%);">+from .test_case import TestCase</span><br><span style="color: hsl(120, 100%, 40%);">+from .ami import AMIEventInstance</span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span> </span><br><span>@@ -165,7 +165,7 @@</span><br><span> A Scenario is considered done if all results have been met and</span><br><span> all expected actions have been executed.</span><br><span> """</span><br><span style="color: hsl(0, 100%, 40%);">- return (all(self._expected_results.itervalues()) and</span><br><span style="color: hsl(120, 100%, 40%);">+ return (all(self._expected_results.values()) and</span><br><span> all(i.ran_actions or i.unexpected</span><br><span> for i in self._event_instances))</span><br><span> </span><br><span>diff --git a/lib/python/asterisk/ari.py b/lib/python/asterisk/ari.py</span><br><span>index da19cee..23672dd 100644</span><br><span>--- a/lib/python/asterisk/ari.py</span><br><span>+++ b/lib/python/asterisk/ari.py</span><br><span>@@ -12,12 +12,16 @@</span><br><span> import re</span><br><span> import requests</span><br><span> import traceback</span><br><span style="color: hsl(0, 100%, 40%);">-import urllib</span><br><span style="color: hsl(120, 100%, 40%);">+try:</span><br><span style="color: hsl(120, 100%, 40%);">+ from urllib.parse import urlencode</span><br><span style="color: hsl(120, 100%, 40%);">+except:</span><br><span style="color: hsl(120, 100%, 40%);">+ from urllib import urlencode</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-from test_case import TestCase</span><br><span style="color: hsl(0, 100%, 40%);">-from pluggable_registry import PLUGGABLE_EVENT_REGISTRY,\</span><br><span style="color: hsl(120, 100%, 40%);">+from .test_case import TestCase</span><br><span style="color: hsl(120, 100%, 40%);">+from .test_runner import load_and_parse_module</span><br><span style="color: hsl(120, 100%, 40%);">+from .pluggable_registry import PLUGGABLE_EVENT_REGISTRY,\</span><br><span> PLUGGABLE_ACTION_REGISTRY, var_replace</span><br><span style="color: hsl(0, 100%, 40%);">-from test_suite_utils import all_match</span><br><span style="color: hsl(120, 100%, 40%);">+from .test_suite_utils import all_match</span><br><span> from twisted.internet import reactor</span><br><span> try:</span><br><span> from autobahn.websocket import WebSocketClientFactory, \</span><br><span>@@ -332,7 +336,7 @@</span><br><span> """</span><br><span> url = "ws://%s:%d/ari/events?%s" % \</span><br><span> (host, port,</span><br><span style="color: hsl(0, 100%, 40%);">- urllib.urlencode({'app': apps, 'api_key': '%s:%s' % userpass}))</span><br><span style="color: hsl(120, 100%, 40%);">+ urlencode({'app': apps, 'api_key': '%s:%s' % userpass}))</span><br><span> if subscribe_all:</span><br><span> url += '&subscribeAll=true'</span><br><span> LOGGER.info("WebSocketClientFactory(url=%s)", url)</span><br><span>@@ -560,7 +564,7 @@</span><br><span> url = self.ari.build_url(uri)</span><br><span> requests_method = getattr(requests, self.method)</span><br><span> params = dict((key, var_replace(val, values))</span><br><span style="color: hsl(0, 100%, 40%);">- for key, val in self.params.iteritems())</span><br><span style="color: hsl(120, 100%, 40%);">+ for key, val in self.params.items())</span><br><span> </span><br><span> response = requests_method(</span><br><span> url,</span><br><span>@@ -580,7 +584,7 @@</span><br><span> response.status_code, response.text)</span><br><span> return False</span><br><span> else:</span><br><span style="color: hsl(0, 100%, 40%);">- if response.status_code / 100 != 2:</span><br><span style="color: hsl(120, 100%, 40%);">+ if response.status_code // 100 != 2:</span><br><span> LOGGER.error('sent %s %s %s response %d %s',</span><br><span> self.method, self.uri, self.params,</span><br><span> response.status_code, response.text)</span><br><span>@@ -606,8 +610,7 @@</span><br><span> </span><br><span> callback = self.instance_config.get('callback')</span><br><span> if callback:</span><br><span style="color: hsl(0, 100%, 40%);">- module = __import__(callback['module'])</span><br><span style="color: hsl(0, 100%, 40%);">- self.callback = getattr(module, callback['method'])</span><br><span style="color: hsl(120, 100%, 40%);">+ self.callback = load_and_parse_module(callback['module'] + '.' + callback['method'])</span><br><span> else:</span><br><span> # No callback; just use a no-op</span><br><span> self.callback = lambda *args, **kwargs: True</span><br><span>diff --git a/lib/python/asterisk/astconfigparser.py b/lib/python/asterisk/astconfigparser.py</span><br><span>index dc79e80..e8da255 100644</span><br><span>--- a/lib/python/asterisk/astconfigparser.py</span><br><span>+++ b/lib/python/asterisk/astconfigparser.py</span><br><span>@@ -8,8 +8,7 @@</span><br><span> import re</span><br><span> import itertools</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-from astdicts import OrderedDict</span><br><span style="color: hsl(0, 100%, 40%);">-from astdicts import MultiOrderedDict</span><br><span style="color: hsl(120, 100%, 40%);">+from .astdicts import OrderedDict, MultiOrderedDict</span><br><span> </span><br><span> </span><br><span> def merge_values(left, right, key):</span><br><span>@@ -270,11 +269,11 @@</span><br><span> </span><br><span> def write_dicts(config_file, mdicts):</span><br><span> """Write the contents of the mdicts to the specified config file"""</span><br><span style="color: hsl(0, 100%, 40%);">- for section, sect_list in mdicts.iteritems():</span><br><span style="color: hsl(120, 100%, 40%);">+ for section, sect_list in mdicts.items():</span><br><span> # every section contains a list of dictionaries</span><br><span> for sect in sect_list:</span><br><span> config_file.write("[%s]\n" % section)</span><br><span style="color: hsl(0, 100%, 40%);">- for key, val_list in sect.iteritems():</span><br><span style="color: hsl(120, 100%, 40%);">+ for key, val_list in sect.items():</span><br><span> # every value is also a list</span><br><span> for v in val_list:</span><br><span> key_val = key</span><br><span>@@ -355,7 +354,7 @@</span><br><span> if self._includes:</span><br><span> res.extend(list(itertools.chain(*[</span><br><span> incl.get_sections(key, attr, searched)</span><br><span style="color: hsl(0, 100%, 40%);">- for incl in self._includes.itervalues()])))</span><br><span style="color: hsl(120, 100%, 40%);">+ for incl in self._includes.values()])))</span><br><span> if self._parent:</span><br><span> res += self._parent.get_sections(key, attr, searched)</span><br><span> return res</span><br><span>@@ -445,7 +444,7 @@</span><br><span> with open(filename, 'rt') as config_file:</span><br><span> self._read(config_file, sect)</span><br><span> except IOError:</span><br><span style="color: hsl(0, 100%, 40%);">- print "Could not open file ", filename, " for reading"</span><br><span style="color: hsl(120, 100%, 40%);">+ print("Could not open file ", filename, " for reading")</span><br><span> </span><br><span> def _read(self, config_file, sect):</span><br><span> """Parse configuration information from the config_file"""</span><br><span>@@ -478,7 +477,7 @@</span><br><span> def write(self, config_file):</span><br><span> """Write configuration information out to a file"""</span><br><span> try:</span><br><span style="color: hsl(0, 100%, 40%);">- for key, val in self._includes.iteritems():</span><br><span style="color: hsl(120, 100%, 40%);">+ for key, val in self._includes.items():</span><br><span> val.write(key)</span><br><span> config_file.write('#include "%s"\n' % key)</span><br><span> </span><br><span>@@ -490,4 +489,4 @@</span><br><span> with open(config_file, 'wt') as fp:</span><br><span> self.write(fp)</span><br><span> except IOError:</span><br><span style="color: hsl(0, 100%, 40%);">- print "Could not open file ", config_file, " for writing"</span><br><span style="color: hsl(120, 100%, 40%);">+ print("Could not open file ", config_file, " for writing")</span><br><span>diff --git a/lib/python/asterisk/astcsv.py b/lib/python/asterisk/astcsv.py</span><br><span>index 67d25d3..7619bf5 100644</span><br><span>--- a/lib/python/asterisk/astcsv.py</span><br><span>+++ b/lib/python/asterisk/astcsv.py</span><br><span>@@ -1,4 +1,3 @@</span><br><span style="color: hsl(0, 100%, 40%);">-#!/usr/bin/env python</span><br><span> """Asterisk CSV-based testing</span><br><span> </span><br><span> This module implements the basic CSV testing backend for things like</span><br><span>@@ -11,7 +10,6 @@</span><br><span> the GNU General Public License Version 2.</span><br><span> """</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-import unittest</span><br><span> import sys</span><br><span> import csv</span><br><span> import re</span><br><span>@@ -57,10 +55,10 @@</span><br><span> else:</span><br><span> cmp_fn = (lambda x, y: str(x).lower() == str(y).lower())</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- for key, value in self.iteritems():</span><br><span style="color: hsl(120, 100%, 40%);">+ for key, value in self.items():</span><br><span> if None not in (value, other.get(key)) and not cmp_fn(value, other.get(key)):</span><br><span> if not silent:</span><br><span style="color: hsl(0, 100%, 40%);">- LOGGER.warn("CSV MATCH FAILED, Expected: %s: '%s' "</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGGER.warning("CSV MATCH FAILED, Expected: %s: '%s' "</span><br><span> "Got: %s: '%s'" % (key, value, key,</span><br><span> other.get(key)))</span><br><span> return False</span><br><span>@@ -70,9 +68,9 @@</span><br><span> """Retrieve a value from the specified column key"""</span><br><span> return self.__columns.get(key)</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- def iteritems(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ def items(self):</span><br><span> """Iterate over the values in the columns"""</span><br><span style="color: hsl(0, 100%, 40%);">- return self.__columns.iteritems()</span><br><span style="color: hsl(120, 100%, 40%);">+ return self.__columns.items()</span><br><span> </span><br><span> def __str__(self):</span><br><span> return ",".join(["\"%s\"" % (self.__dict__[x]) for x in self.__fields])</span><br><span>@@ -94,12 +92,14 @@</span><br><span> self.__records = []</span><br><span> </span><br><span> csvreader = None</span><br><span style="color: hsl(120, 100%, 40%);">+ csvfile = None</span><br><span> </span><br><span> try:</span><br><span style="color: hsl(0, 100%, 40%);">- csvreader = csv.DictReader(open(self.filename, "r"), fields, ",")</span><br><span style="color: hsl(0, 100%, 40%);">- except IOError as (errno, strerror):</span><br><span style="color: hsl(120, 100%, 40%);">+ csvfile = open(self.filename, "r")</span><br><span style="color: hsl(120, 100%, 40%);">+ csvreader = csv.DictReader(csvfile, fields, ",")</span><br><span style="color: hsl(120, 100%, 40%);">+ except IOError as e:</span><br><span> LOGGER.error("IOError %d[%s] while opening file '%s'" %</span><br><span style="color: hsl(0, 100%, 40%);">- (errno, strerror, self.filename))</span><br><span style="color: hsl(120, 100%, 40%);">+ (e.errno, e.strerror, self.filename))</span><br><span> except:</span><br><span> LOGGER.error("Unexpected error: %s" % (sys.exc_info()[0]))</span><br><span> </span><br><span>@@ -111,6 +111,8 @@</span><br><span> record = self.row_factory(**row)</span><br><span> self.__records.append(record)</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ csvfile.close()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> def __len__(self):</span><br><span> return len(self.__records)</span><br><span> </span><br><span>@@ -125,7 +127,7 @@</span><br><span> each record"""</span><br><span> </span><br><span> if not partial and (len(self) != len(other)):</span><br><span style="color: hsl(0, 100%, 40%);">- LOGGER.warn("CSV MATCH FAILED, different number of records, "</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGGER.warning("CSV MATCH FAILED, different number of records, "</span><br><span> "self=%d and other=%d" % (len(self), len(other)))</span><br><span> return False</span><br><span> </span><br><span>@@ -147,7 +149,7 @@</span><br><span> size = len(list_a)</span><br><span> </span><br><span> # attempt two orderings: forward and reversed</span><br><span style="color: hsl(0, 100%, 40%);">- guess_orders = (range(size), list(reversed(range(size))))</span><br><span style="color: hsl(120, 100%, 40%);">+ guess_orders = (list(range(size)), list(reversed(range(size))))</span><br><span> found_orders = []</span><br><span> </span><br><span> for guess_order in guess_orders:</span><br><span>@@ -185,7 +187,7 @@</span><br><span> # have it complain immediately.</span><br><span> for i, item in enumerate(self):</span><br><span> if not item.match(other[i], exact=exactness):</span><br><span style="color: hsl(0, 100%, 40%);">- LOGGER.warn("Failed to match entry %d" % (i,))</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGGER.warning("Failed to match entry %d" % (i,))</span><br><span> return False</span><br><span> assert False</span><br><span> </span><br><span>@@ -193,7 +195,7 @@</span><br><span> pass # joy!</span><br><span> </span><br><span> elif len(matches) > 1:</span><br><span style="color: hsl(0, 100%, 40%);">- LOGGER.warn("More than one CSV permutation results in success")</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGGER.warning("More than one CSV permutation results in success")</span><br><span> </span><br><span> return True</span><br><span> </span><br><span>@@ -205,9 +207,6 @@</span><br><span> try:</span><br><span> open(self.filename, "w").close()</span><br><span> except:</span><br><span style="color: hsl(0, 100%, 40%);">- LOGGER.warn("Unable to empty CSV file %s" % (self.filename))</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-if __name__ == '__main__':</span><br><span style="color: hsl(0, 100%, 40%);">- unittest.main()</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGGER.warning("Unable to empty CSV file %s" % (self.filename))</span><br><span> </span><br><span> # vim:sw=4:ts=4:expandtab:textwidth=79</span><br><span>diff --git a/lib/python/asterisk/astdicts.py b/lib/python/asterisk/astdicts.py</span><br><span>index ae63075..4e70eec 100644</span><br><span>--- a/lib/python/asterisk/astdicts.py</span><br><span>+++ b/lib/python/asterisk/astdicts.py</span><br><span>@@ -3,260 +3,264 @@</span><br><span> # copied from http://code.activestate.com/recipes/576693/</span><br><span> </span><br><span> try:</span><br><span style="color: hsl(0, 100%, 40%);">- from thread import get_ident as _get_ident</span><br><span style="color: hsl(120, 100%, 40%);">+ # Use builtin OrderedDict() from Python2.7.</span><br><span style="color: hsl(120, 100%, 40%);">+ from collections import OrderedDict</span><br><span> except ImportError:</span><br><span style="color: hsl(0, 100%, 40%);">- from dummy_thread import get_ident as _get_ident</span><br><span style="color: hsl(120, 100%, 40%);">+ try:</span><br><span style="color: hsl(120, 100%, 40%);">+ from thread import get_ident as _get_ident</span><br><span style="color: hsl(120, 100%, 40%);">+ except ImportError:</span><br><span style="color: hsl(120, 100%, 40%);">+ from dummy_thread import get_ident as _get_ident</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-try:</span><br><span style="color: hsl(0, 100%, 40%);">- from _abcoll import KeysView, ValuesView, ItemsView</span><br><span style="color: hsl(0, 100%, 40%);">-except ImportError:</span><br><span style="color: hsl(0, 100%, 40%);">- pass</span><br><span style="color: hsl(120, 100%, 40%);">+ try:</span><br><span style="color: hsl(120, 100%, 40%);">+ from _abcoll import KeysView, ValuesView, ItemsView</span><br><span style="color: hsl(120, 100%, 40%);">+ except ImportError:</span><br><span style="color: hsl(120, 100%, 40%);">+ pass</span><br><span> </span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-class OrderedDict(dict):</span><br><span style="color: hsl(0, 100%, 40%);">- 'Dictionary that remembers insertion order'</span><br><span style="color: hsl(0, 100%, 40%);">- # An inherited dict maps keys to values.</span><br><span style="color: hsl(0, 100%, 40%);">- # The inherited dict provides __getitem__, __len__, __contains__, and get.</span><br><span style="color: hsl(0, 100%, 40%);">- # The remaining methods are order-aware.</span><br><span style="color: hsl(0, 100%, 40%);">- # Big-O running times for all methods are the same as for regular dictionaries.</span><br><span style="color: hsl(120, 100%, 40%);">+ class OrderedDict(dict):</span><br><span style="color: hsl(120, 100%, 40%);">+ 'Dictionary that remembers insertion order'</span><br><span style="color: hsl(120, 100%, 40%);">+ # An inherited dict maps keys to values.</span><br><span style="color: hsl(120, 100%, 40%);">+ # The inherited dict provides __getitem__, __len__, __contains__, and get.</span><br><span style="color: hsl(120, 100%, 40%);">+ # The remaining methods are order-aware.</span><br><span style="color: hsl(120, 100%, 40%);">+ # Big-O running times for all methods are the same as for regular dictionaries.</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- # The internal self.__map dictionary maps keys to links in a doubly linked list.</span><br><span style="color: hsl(0, 100%, 40%);">- # The circular doubly linked list starts and ends with a sentinel element.</span><br><span style="color: hsl(0, 100%, 40%);">- # The sentinel element never gets deleted (this simplifies the algorithm).</span><br><span style="color: hsl(0, 100%, 40%);">- # Each link is stored as a list of length three: [PREV, NEXT, KEY].</span><br><span style="color: hsl(120, 100%, 40%);">+ # The internal self.__map dictionary maps keys to links in a doubly linked list.</span><br><span style="color: hsl(120, 100%, 40%);">+ # The circular doubly linked list starts and ends with a sentinel element.</span><br><span style="color: hsl(120, 100%, 40%);">+ # The sentinel element never gets deleted (this simplifies the algorithm).</span><br><span style="color: hsl(120, 100%, 40%);">+ # Each link is stored as a list of length three: [PREV, NEXT, KEY].</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- def __init__(self, *args, **kwds):</span><br><span style="color: hsl(0, 100%, 40%);">- '''Initialize an ordered dictionary. Signature is the same as for</span><br><span style="color: hsl(0, 100%, 40%);">- regular dictionaries, but keyword arguments are not recommended</span><br><span style="color: hsl(0, 100%, 40%);">- because their insertion order is arbitrary.</span><br><span style="color: hsl(120, 100%, 40%);">+ def __init__(self, *args, **kwds):</span><br><span style="color: hsl(120, 100%, 40%);">+ '''Initialize an ordered dictionary. Signature is the same as for</span><br><span style="color: hsl(120, 100%, 40%);">+ regular dictionaries, but keyword arguments are not recommended</span><br><span style="color: hsl(120, 100%, 40%);">+ because their insertion order is arbitrary.</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- '''</span><br><span style="color: hsl(0, 100%, 40%);">- if len(args) > 1:</span><br><span style="color: hsl(0, 100%, 40%);">- raise TypeError('expected at most 1 arguments, got %d' % len(args))</span><br><span style="color: hsl(0, 100%, 40%);">- try:</span><br><span style="color: hsl(0, 100%, 40%);">- self.__root</span><br><span style="color: hsl(0, 100%, 40%);">- except AttributeError:</span><br><span style="color: hsl(0, 100%, 40%);">- self.__root = root = [] # sentinel node</span><br><span style="color: hsl(0, 100%, 40%);">- root[:] = [root, root, None]</span><br><span style="color: hsl(0, 100%, 40%);">- self.__map = {}</span><br><span style="color: hsl(0, 100%, 40%);">- self.__update(*args, **kwds)</span><br><span style="color: hsl(120, 100%, 40%);">+ '''</span><br><span style="color: hsl(120, 100%, 40%);">+ if len(args) > 1:</span><br><span style="color: hsl(120, 100%, 40%);">+ raise TypeError('expected at most 1 arguments, got %d' % len(args))</span><br><span style="color: hsl(120, 100%, 40%);">+ try:</span><br><span style="color: hsl(120, 100%, 40%);">+ self.__root</span><br><span style="color: hsl(120, 100%, 40%);">+ except AttributeError:</span><br><span style="color: hsl(120, 100%, 40%);">+ self.__root = root = [] # sentinel node</span><br><span style="color: hsl(120, 100%, 40%);">+ root[:] = [root, root, None]</span><br><span style="color: hsl(120, 100%, 40%);">+ self.__map = {}</span><br><span style="color: hsl(120, 100%, 40%);">+ self.__update(*args, **kwds)</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- def __setitem__(self, key, value, dict_setitem=dict.__setitem__):</span><br><span style="color: hsl(0, 100%, 40%);">- 'od.__setitem__(i, y) <==> od[i]=y'</span><br><span style="color: hsl(0, 100%, 40%);">- # Setting a new item creates a new link which goes at the end of the linked</span><br><span style="color: hsl(0, 100%, 40%);">- # list, and the inherited dictionary is updated with the new key/value pair.</span><br><span style="color: hsl(0, 100%, 40%);">- if key not in self:</span><br><span style="color: hsl(120, 100%, 40%);">+ def __setitem__(self, key, value, dict_setitem=dict.__setitem__):</span><br><span style="color: hsl(120, 100%, 40%);">+ 'od.__setitem__(i, y) <==> od[i]=y'</span><br><span style="color: hsl(120, 100%, 40%);">+ # Setting a new item creates a new link which goes at the end of the linked</span><br><span style="color: hsl(120, 100%, 40%);">+ # list, and the inherited dictionary is updated with the new key/value pair.</span><br><span style="color: hsl(120, 100%, 40%);">+ if key not in self:</span><br><span style="color: hsl(120, 100%, 40%);">+ root = self.__root</span><br><span style="color: hsl(120, 100%, 40%);">+ last = root[0]</span><br><span style="color: hsl(120, 100%, 40%);">+ last[1] = root[0] = self.__map[key] = [last, root, key]</span><br><span style="color: hsl(120, 100%, 40%);">+ dict_setitem(self, key, value)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def __delitem__(self, key, dict_delitem=dict.__delitem__):</span><br><span style="color: hsl(120, 100%, 40%);">+ 'od.__delitem__(y) <==> del od[y]'</span><br><span style="color: hsl(120, 100%, 40%);">+ # Deleting an existing item uses self.__map to find the link which is</span><br><span style="color: hsl(120, 100%, 40%);">+ # then removed by updating the links in the predecessor and successor nodes.</span><br><span style="color: hsl(120, 100%, 40%);">+ dict_delitem(self, key)</span><br><span style="color: hsl(120, 100%, 40%);">+ link_prev, link_next, key = self.__map.pop(key)</span><br><span style="color: hsl(120, 100%, 40%);">+ link_prev[1] = link_next</span><br><span style="color: hsl(120, 100%, 40%);">+ link_next[0] = link_prev</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def __iter__(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ 'od.__iter__() <==> iter(od)'</span><br><span> root = self.__root</span><br><span style="color: hsl(0, 100%, 40%);">- last = root[0]</span><br><span style="color: hsl(0, 100%, 40%);">- last[1] = root[0] = self.__map[key] = [last, root, key]</span><br><span style="color: hsl(0, 100%, 40%);">- dict_setitem(self, key, value)</span><br><span style="color: hsl(120, 100%, 40%);">+ curr = root[1]</span><br><span style="color: hsl(120, 100%, 40%);">+ while curr is not root:</span><br><span style="color: hsl(120, 100%, 40%);">+ yield curr[2]</span><br><span style="color: hsl(120, 100%, 40%);">+ curr = curr[1]</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- def __delitem__(self, key, dict_delitem=dict.__delitem__):</span><br><span style="color: hsl(0, 100%, 40%);">- 'od.__delitem__(y) <==> del od[y]'</span><br><span style="color: hsl(0, 100%, 40%);">- # Deleting an existing item uses self.__map to find the link which is</span><br><span style="color: hsl(0, 100%, 40%);">- # then removed by updating the links in the predecessor and successor nodes.</span><br><span style="color: hsl(0, 100%, 40%);">- dict_delitem(self, key)</span><br><span style="color: hsl(0, 100%, 40%);">- link_prev, link_next, key = self.__map.pop(key)</span><br><span style="color: hsl(0, 100%, 40%);">- link_prev[1] = link_next</span><br><span style="color: hsl(0, 100%, 40%);">- link_next[0] = link_prev</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def __iter__(self):</span><br><span style="color: hsl(0, 100%, 40%);">- 'od.__iter__() <==> iter(od)'</span><br><span style="color: hsl(0, 100%, 40%);">- root = self.__root</span><br><span style="color: hsl(0, 100%, 40%);">- curr = root[1]</span><br><span style="color: hsl(0, 100%, 40%);">- while curr is not root:</span><br><span style="color: hsl(0, 100%, 40%);">- yield curr[2]</span><br><span style="color: hsl(0, 100%, 40%);">- curr = curr[1]</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def __reversed__(self):</span><br><span style="color: hsl(0, 100%, 40%);">- 'od.__reversed__() <==> reversed(od)'</span><br><span style="color: hsl(0, 100%, 40%);">- root = self.__root</span><br><span style="color: hsl(0, 100%, 40%);">- curr = root[0]</span><br><span style="color: hsl(0, 100%, 40%);">- while curr is not root:</span><br><span style="color: hsl(0, 100%, 40%);">- yield curr[2]</span><br><span style="color: hsl(0, 100%, 40%);">- curr = curr[0]</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def clear(self):</span><br><span style="color: hsl(0, 100%, 40%);">- 'od.clear() -> None. Remove all items from od.'</span><br><span style="color: hsl(0, 100%, 40%);">- try:</span><br><span style="color: hsl(0, 100%, 40%);">- for node in self.__map.itervalues():</span><br><span style="color: hsl(0, 100%, 40%);">- del node[:]</span><br><span style="color: hsl(120, 100%, 40%);">+ def __reversed__(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ 'od.__reversed__() <==> reversed(od)'</span><br><span> root = self.__root</span><br><span style="color: hsl(0, 100%, 40%);">- root[:] = [root, root, None]</span><br><span style="color: hsl(0, 100%, 40%);">- self.__map.clear()</span><br><span style="color: hsl(0, 100%, 40%);">- except AttributeError:</span><br><span style="color: hsl(0, 100%, 40%);">- pass</span><br><span style="color: hsl(0, 100%, 40%);">- dict.clear(self)</span><br><span style="color: hsl(120, 100%, 40%);">+ curr = root[0]</span><br><span style="color: hsl(120, 100%, 40%);">+ while curr is not root:</span><br><span style="color: hsl(120, 100%, 40%);">+ yield curr[2]</span><br><span style="color: hsl(120, 100%, 40%);">+ curr = curr[0]</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- def popitem(self, last=True):</span><br><span style="color: hsl(0, 100%, 40%);">- '''od.popitem() -> (k, v), return and remove a (key, value) pair.</span><br><span style="color: hsl(0, 100%, 40%);">- Pairs are returned in LIFO order if last is true or FIFO order if false.</span><br><span style="color: hsl(120, 100%, 40%);">+ def clear(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ 'od.clear() -> None. Remove all items from od.'</span><br><span style="color: hsl(120, 100%, 40%);">+ try:</span><br><span style="color: hsl(120, 100%, 40%);">+ for node in self.__map.itervalues():</span><br><span style="color: hsl(120, 100%, 40%);">+ del node[:]</span><br><span style="color: hsl(120, 100%, 40%);">+ root = self.__root</span><br><span style="color: hsl(120, 100%, 40%);">+ root[:] = [root, root, None]</span><br><span style="color: hsl(120, 100%, 40%);">+ self.__map.clear()</span><br><span style="color: hsl(120, 100%, 40%);">+ except AttributeError:</span><br><span style="color: hsl(120, 100%, 40%);">+ pass</span><br><span style="color: hsl(120, 100%, 40%);">+ dict.clear(self)</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- '''</span><br><span style="color: hsl(0, 100%, 40%);">- if not self:</span><br><span style="color: hsl(0, 100%, 40%);">- raise KeyError('dictionary is empty')</span><br><span style="color: hsl(0, 100%, 40%);">- root = self.__root</span><br><span style="color: hsl(0, 100%, 40%);">- if last:</span><br><span style="color: hsl(0, 100%, 40%);">- link = root[0]</span><br><span style="color: hsl(0, 100%, 40%);">- link_prev = link[0]</span><br><span style="color: hsl(0, 100%, 40%);">- link_prev[1] = root</span><br><span style="color: hsl(0, 100%, 40%);">- root[0] = link_prev</span><br><span style="color: hsl(0, 100%, 40%);">- else:</span><br><span style="color: hsl(0, 100%, 40%);">- link = root[1]</span><br><span style="color: hsl(0, 100%, 40%);">- link_next = link[1]</span><br><span style="color: hsl(0, 100%, 40%);">- root[1] = link_next</span><br><span style="color: hsl(0, 100%, 40%);">- link_next[0] = root</span><br><span style="color: hsl(0, 100%, 40%);">- key = link[2]</span><br><span style="color: hsl(0, 100%, 40%);">- del self.__map[key]</span><br><span style="color: hsl(0, 100%, 40%);">- value = dict.pop(self, key)</span><br><span style="color: hsl(0, 100%, 40%);">- return key, value</span><br><span style="color: hsl(120, 100%, 40%);">+ def popitem(self, last=True):</span><br><span style="color: hsl(120, 100%, 40%);">+ '''od.popitem() -> (k, v), return and remove a (key, value) pair.</span><br><span style="color: hsl(120, 100%, 40%);">+ Pairs are returned in LIFO order if last is true or FIFO order if false.</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- # -- the following methods do not depend on the internal structure --</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def keys(self):</span><br><span style="color: hsl(0, 100%, 40%);">- 'od.keys() -> list of keys in od'</span><br><span style="color: hsl(0, 100%, 40%);">- return list(self)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def values(self):</span><br><span style="color: hsl(0, 100%, 40%);">- 'od.values() -> list of values in od'</span><br><span style="color: hsl(0, 100%, 40%);">- return [self[key] for key in self]</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def items(self):</span><br><span style="color: hsl(0, 100%, 40%);">- 'od.items() -> list of (key, value) pairs in od'</span><br><span style="color: hsl(0, 100%, 40%);">- return [(key, self[key]) for key in self]</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def iterkeys(self):</span><br><span style="color: hsl(0, 100%, 40%);">- 'od.iterkeys() -> an iterator over the keys in od'</span><br><span style="color: hsl(0, 100%, 40%);">- return iter(self)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def itervalues(self):</span><br><span style="color: hsl(0, 100%, 40%);">- 'od.itervalues -> an iterator over the values in od'</span><br><span style="color: hsl(0, 100%, 40%);">- for k in self:</span><br><span style="color: hsl(0, 100%, 40%);">- yield self[k]</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def iteritems(self):</span><br><span style="color: hsl(0, 100%, 40%);">- 'od.iteritems -> an iterator over the (key, value) items in od'</span><br><span style="color: hsl(0, 100%, 40%);">- for k in self:</span><br><span style="color: hsl(0, 100%, 40%);">- yield (k, self[k])</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def update(*args, **kwds):</span><br><span style="color: hsl(0, 100%, 40%);">- '''od.update(E, **F) -> None. Update od from dict/iterable E and F.</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- If E is a dict instance, does: for k in E: od[k] = E[k]</span><br><span style="color: hsl(0, 100%, 40%);">- If E has a .keys() method, does: for k in E.keys(): od[k] = E[k]</span><br><span style="color: hsl(0, 100%, 40%);">- Or if E is an iterable of items, does: for k, v in E: od[k] = v</span><br><span style="color: hsl(0, 100%, 40%);">- In either case, this is followed by: for k, v in F.items(): od[k] = v</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- '''</span><br><span style="color: hsl(0, 100%, 40%);">- if len(args) > 2:</span><br><span style="color: hsl(0, 100%, 40%);">- raise TypeError('update() takes at most 2 positional '</span><br><span style="color: hsl(0, 100%, 40%);">- 'arguments (%d given)' % (len(args),))</span><br><span style="color: hsl(0, 100%, 40%);">- elif not args:</span><br><span style="color: hsl(0, 100%, 40%);">- raise TypeError('update() takes at least 1 argument (0 given)')</span><br><span style="color: hsl(0, 100%, 40%);">- self = args[0]</span><br><span style="color: hsl(0, 100%, 40%);">- # Make progressively weaker assumptions about "other"</span><br><span style="color: hsl(0, 100%, 40%);">- other = ()</span><br><span style="color: hsl(0, 100%, 40%);">- if len(args) == 2:</span><br><span style="color: hsl(0, 100%, 40%);">- other = args[1]</span><br><span style="color: hsl(0, 100%, 40%);">- if isinstance(other, dict):</span><br><span style="color: hsl(0, 100%, 40%);">- for key in other:</span><br><span style="color: hsl(0, 100%, 40%);">- self[key] = other[key]</span><br><span style="color: hsl(0, 100%, 40%);">- elif hasattr(other, 'keys'):</span><br><span style="color: hsl(0, 100%, 40%);">- for key in other.keys():</span><br><span style="color: hsl(0, 100%, 40%);">- self[key] = other[key]</span><br><span style="color: hsl(0, 100%, 40%);">- else:</span><br><span style="color: hsl(0, 100%, 40%);">- for key, value in other:</span><br><span style="color: hsl(0, 100%, 40%);">- self[key] = value</span><br><span style="color: hsl(0, 100%, 40%);">- for key, value in kwds.items():</span><br><span style="color: hsl(0, 100%, 40%);">- self[key] = value</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- __update = update # let subclasses override update without breaking __init__</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- __marker = object()</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def pop(self, key, default=__marker):</span><br><span style="color: hsl(0, 100%, 40%);">- '''od.pop(k[,d]) -> v, remove specified key and return the corresponding value.</span><br><span style="color: hsl(0, 100%, 40%);">- If key is not found, d is returned if given, otherwise KeyError is raised.</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- '''</span><br><span style="color: hsl(0, 100%, 40%);">- if key in self:</span><br><span style="color: hsl(0, 100%, 40%);">- result = self[key]</span><br><span style="color: hsl(0, 100%, 40%);">- del self[key]</span><br><span style="color: hsl(0, 100%, 40%);">- return result</span><br><span style="color: hsl(0, 100%, 40%);">- if default is self.__marker:</span><br><span style="color: hsl(0, 100%, 40%);">- raise KeyError(key)</span><br><span style="color: hsl(0, 100%, 40%);">- return default</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def setdefault(self, key, default=None):</span><br><span style="color: hsl(0, 100%, 40%);">- 'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od'</span><br><span style="color: hsl(0, 100%, 40%);">- if key in self:</span><br><span style="color: hsl(0, 100%, 40%);">- return self[key]</span><br><span style="color: hsl(0, 100%, 40%);">- self[key] = default</span><br><span style="color: hsl(0, 100%, 40%);">- return default</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def __repr__(self, _repr_running={}):</span><br><span style="color: hsl(0, 100%, 40%);">- 'od.__repr__() <==> repr(od)'</span><br><span style="color: hsl(0, 100%, 40%);">- call_key = id(self), _get_ident()</span><br><span style="color: hsl(0, 100%, 40%);">- if call_key in _repr_running:</span><br><span style="color: hsl(0, 100%, 40%);">- return '...'</span><br><span style="color: hsl(0, 100%, 40%);">- _repr_running[call_key] = 1</span><br><span style="color: hsl(0, 100%, 40%);">- try:</span><br><span style="color: hsl(120, 100%, 40%);">+ '''</span><br><span> if not self:</span><br><span style="color: hsl(0, 100%, 40%);">- return '%s()' % (self.__class__.__name__,)</span><br><span style="color: hsl(0, 100%, 40%);">- return '%s(%r)' % (self.__class__.__name__, self.items())</span><br><span style="color: hsl(0, 100%, 40%);">- finally:</span><br><span style="color: hsl(0, 100%, 40%);">- del _repr_running[call_key]</span><br><span style="color: hsl(120, 100%, 40%);">+ raise KeyError('dictionary is empty')</span><br><span style="color: hsl(120, 100%, 40%);">+ root = self.__root</span><br><span style="color: hsl(120, 100%, 40%);">+ if last:</span><br><span style="color: hsl(120, 100%, 40%);">+ link = root[0]</span><br><span style="color: hsl(120, 100%, 40%);">+ link_prev = link[0]</span><br><span style="color: hsl(120, 100%, 40%);">+ link_prev[1] = root</span><br><span style="color: hsl(120, 100%, 40%);">+ root[0] = link_prev</span><br><span style="color: hsl(120, 100%, 40%);">+ else:</span><br><span style="color: hsl(120, 100%, 40%);">+ link = root[1]</span><br><span style="color: hsl(120, 100%, 40%);">+ link_next = link[1]</span><br><span style="color: hsl(120, 100%, 40%);">+ root[1] = link_next</span><br><span style="color: hsl(120, 100%, 40%);">+ link_next[0] = root</span><br><span style="color: hsl(120, 100%, 40%);">+ key = link[2]</span><br><span style="color: hsl(120, 100%, 40%);">+ del self.__map[key]</span><br><span style="color: hsl(120, 100%, 40%);">+ value = dict.pop(self, key)</span><br><span style="color: hsl(120, 100%, 40%);">+ return key, value</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- def __reduce__(self):</span><br><span style="color: hsl(0, 100%, 40%);">- 'Return state information for pickling'</span><br><span style="color: hsl(0, 100%, 40%);">- items = [[k, self[k]] for k in self]</span><br><span style="color: hsl(0, 100%, 40%);">- inst_dict = vars(self).copy()</span><br><span style="color: hsl(0, 100%, 40%);">- for k in vars(OrderedDict()):</span><br><span style="color: hsl(0, 100%, 40%);">- inst_dict.pop(k, None)</span><br><span style="color: hsl(0, 100%, 40%);">- if inst_dict:</span><br><span style="color: hsl(0, 100%, 40%);">- return (self.__class__, (items,), inst_dict)</span><br><span style="color: hsl(0, 100%, 40%);">- return self.__class__, (items,)</span><br><span style="color: hsl(120, 100%, 40%);">+ # -- the following methods do not depend on the internal structure --</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- def copy(self):</span><br><span style="color: hsl(0, 100%, 40%);">- 'od.copy() -> a shallow copy of od'</span><br><span style="color: hsl(0, 100%, 40%);">- return self.__class__(self)</span><br><span style="color: hsl(120, 100%, 40%);">+ def keys(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ 'od.keys() -> list of keys in od'</span><br><span style="color: hsl(120, 100%, 40%);">+ return list(self)</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- @classmethod</span><br><span style="color: hsl(0, 100%, 40%);">- def fromkeys(cls, iterable, value=None):</span><br><span style="color: hsl(0, 100%, 40%);">- '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S</span><br><span style="color: hsl(0, 100%, 40%);">- and values equal to v (which defaults to None).</span><br><span style="color: hsl(120, 100%, 40%);">+ def values(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ 'od.values() -> list of values in od'</span><br><span style="color: hsl(120, 100%, 40%);">+ return [self[key] for key in self]</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- '''</span><br><span style="color: hsl(0, 100%, 40%);">- d = cls()</span><br><span style="color: hsl(0, 100%, 40%);">- for key in iterable:</span><br><span style="color: hsl(0, 100%, 40%);">- d[key] = value</span><br><span style="color: hsl(0, 100%, 40%);">- return d</span><br><span style="color: hsl(120, 100%, 40%);">+ def items(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ 'od.items() -> list of (key, value) pairs in od'</span><br><span style="color: hsl(120, 100%, 40%);">+ return [(key, self[key]) for key in self]</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- def __eq__(self, other):</span><br><span style="color: hsl(0, 100%, 40%);">- '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive</span><br><span style="color: hsl(0, 100%, 40%);">- while comparison to a regular mapping is order-insensitive.</span><br><span style="color: hsl(120, 100%, 40%);">+ def iterkeys(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ 'od.iterkeys() -> an iterator over the keys in od'</span><br><span style="color: hsl(120, 100%, 40%);">+ return iter(self)</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- '''</span><br><span style="color: hsl(0, 100%, 40%);">- if isinstance(other, OrderedDict):</span><br><span style="color: hsl(0, 100%, 40%);">- return len(self)==len(other) and self.items() == other.items()</span><br><span style="color: hsl(0, 100%, 40%);">- return dict.__eq__(self, other)</span><br><span style="color: hsl(120, 100%, 40%);">+ def itervalues(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ 'od.itervalues -> an iterator over the values in od'</span><br><span style="color: hsl(120, 100%, 40%);">+ for k in self:</span><br><span style="color: hsl(120, 100%, 40%);">+ yield self[k]</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- def __ne__(self, other):</span><br><span style="color: hsl(0, 100%, 40%);">- return not self == other</span><br><span style="color: hsl(120, 100%, 40%);">+ def iteritems(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ 'od.iteritems -> an iterator over the (key, value) items in od'</span><br><span style="color: hsl(120, 100%, 40%);">+ for k in self:</span><br><span style="color: hsl(120, 100%, 40%);">+ yield (k, self[k])</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- # -- the following methods are only used in Python 2.7 --</span><br><span style="color: hsl(120, 100%, 40%);">+ def update(*args, **kwds):</span><br><span style="color: hsl(120, 100%, 40%);">+ '''od.update(E, **F) -> None. Update od from dict/iterable E and F.</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- def viewkeys(self):</span><br><span style="color: hsl(0, 100%, 40%);">- "od.viewkeys() -> a set-like object providing a view on od's keys"</span><br><span style="color: hsl(0, 100%, 40%);">- return KeysView(self)</span><br><span style="color: hsl(120, 100%, 40%);">+ If E is a dict instance, does: for k in E: od[k] = E[k]</span><br><span style="color: hsl(120, 100%, 40%);">+ If E has a .keys() method, does: for k in E.keys(): od[k] = E[k]</span><br><span style="color: hsl(120, 100%, 40%);">+ Or if E is an iterable of items, does: for k, v in E: od[k] = v</span><br><span style="color: hsl(120, 100%, 40%);">+ In either case, this is followed by: for k, v in F.items(): od[k] = v</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- def viewvalues(self):</span><br><span style="color: hsl(0, 100%, 40%);">- "od.viewvalues() -> an object providing a view on od's values"</span><br><span style="color: hsl(0, 100%, 40%);">- return ValuesView(self)</span><br><span style="color: hsl(120, 100%, 40%);">+ '''</span><br><span style="color: hsl(120, 100%, 40%);">+ if len(args) > 2:</span><br><span style="color: hsl(120, 100%, 40%);">+ raise TypeError('update() takes at most 2 positional '</span><br><span style="color: hsl(120, 100%, 40%);">+ 'arguments (%d given)' % (len(args),))</span><br><span style="color: hsl(120, 100%, 40%);">+ elif not args:</span><br><span style="color: hsl(120, 100%, 40%);">+ raise TypeError('update() takes at least 1 argument (0 given)')</span><br><span style="color: hsl(120, 100%, 40%);">+ self = args[0]</span><br><span style="color: hsl(120, 100%, 40%);">+ # Make progressively weaker assumptions about "other"</span><br><span style="color: hsl(120, 100%, 40%);">+ other = ()</span><br><span style="color: hsl(120, 100%, 40%);">+ if len(args) == 2:</span><br><span style="color: hsl(120, 100%, 40%);">+ other = args[1]</span><br><span style="color: hsl(120, 100%, 40%);">+ if isinstance(other, dict):</span><br><span style="color: hsl(120, 100%, 40%);">+ for key in other:</span><br><span style="color: hsl(120, 100%, 40%);">+ self[key] = other[key]</span><br><span style="color: hsl(120, 100%, 40%);">+ elif hasattr(other, 'keys'):</span><br><span style="color: hsl(120, 100%, 40%);">+ for key in other.keys():</span><br><span style="color: hsl(120, 100%, 40%);">+ self[key] = other[key]</span><br><span style="color: hsl(120, 100%, 40%);">+ else:</span><br><span style="color: hsl(120, 100%, 40%);">+ for key, value in other:</span><br><span style="color: hsl(120, 100%, 40%);">+ self[key] = value</span><br><span style="color: hsl(120, 100%, 40%);">+ for key, value in kwds.items():</span><br><span style="color: hsl(120, 100%, 40%);">+ self[key] = value</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- def viewitems(self):</span><br><span style="color: hsl(0, 100%, 40%);">- "od.viewitems() -> a set-like object providing a view on od's items"</span><br><span style="color: hsl(0, 100%, 40%);">- return ItemsView(self)</span><br><span style="color: hsl(120, 100%, 40%);">+ __update = update # let subclasses override update without breaking __init__</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ __marker = object()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def pop(self, key, default=__marker):</span><br><span style="color: hsl(120, 100%, 40%);">+ '''od.pop(k[,d]) -> v, remove specified key and return the corresponding value.</span><br><span style="color: hsl(120, 100%, 40%);">+ If key is not found, d is returned if given, otherwise KeyError is raised.</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%);">+ if key in self:</span><br><span style="color: hsl(120, 100%, 40%);">+ result = self[key]</span><br><span style="color: hsl(120, 100%, 40%);">+ del self[key]</span><br><span style="color: hsl(120, 100%, 40%);">+ return result</span><br><span style="color: hsl(120, 100%, 40%);">+ if default is self.__marker:</span><br><span style="color: hsl(120, 100%, 40%);">+ raise KeyError(key)</span><br><span style="color: hsl(120, 100%, 40%);">+ return default</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def setdefault(self, key, default=None):</span><br><span style="color: hsl(120, 100%, 40%);">+ 'od.setdefault(k[,d]) -> od.get(k,d), also set od[k]=d if k not in od'</span><br><span style="color: hsl(120, 100%, 40%);">+ if key in self:</span><br><span style="color: hsl(120, 100%, 40%);">+ return self[key]</span><br><span style="color: hsl(120, 100%, 40%);">+ self[key] = default</span><br><span style="color: hsl(120, 100%, 40%);">+ return default</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def __repr__(self, _repr_running={}):</span><br><span style="color: hsl(120, 100%, 40%);">+ 'od.__repr__() <==> repr(od)'</span><br><span style="color: hsl(120, 100%, 40%);">+ call_key = id(self), _get_ident()</span><br><span style="color: hsl(120, 100%, 40%);">+ if call_key in _repr_running:</span><br><span style="color: hsl(120, 100%, 40%);">+ return '...'</span><br><span style="color: hsl(120, 100%, 40%);">+ _repr_running[call_key] = 1</span><br><span style="color: hsl(120, 100%, 40%);">+ try:</span><br><span style="color: hsl(120, 100%, 40%);">+ if not self:</span><br><span style="color: hsl(120, 100%, 40%);">+ return '%s()' % (self.__class__.__name__,)</span><br><span style="color: hsl(120, 100%, 40%);">+ return '%s(%r)' % (self.__class__.__name__, self.items())</span><br><span style="color: hsl(120, 100%, 40%);">+ finally:</span><br><span style="color: hsl(120, 100%, 40%);">+ del _repr_running[call_key]</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def __reduce__(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ 'Return state information for pickling'</span><br><span style="color: hsl(120, 100%, 40%);">+ items = [[k, self[k]] for k in self]</span><br><span style="color: hsl(120, 100%, 40%);">+ inst_dict = vars(self).copy()</span><br><span style="color: hsl(120, 100%, 40%);">+ for k in vars(OrderedDict()):</span><br><span style="color: hsl(120, 100%, 40%);">+ inst_dict.pop(k, None)</span><br><span style="color: hsl(120, 100%, 40%);">+ if inst_dict:</span><br><span style="color: hsl(120, 100%, 40%);">+ return (self.__class__, (items,), inst_dict)</span><br><span style="color: hsl(120, 100%, 40%);">+ return self.__class__, (items,)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def copy(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ 'od.copy() -> a shallow copy of od'</span><br><span style="color: hsl(120, 100%, 40%);">+ return self.__class__(self)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ @classmethod</span><br><span style="color: hsl(120, 100%, 40%);">+ def fromkeys(cls, iterable, value=None):</span><br><span style="color: hsl(120, 100%, 40%);">+ '''OD.fromkeys(S[, v]) -> New ordered dictionary with keys from S</span><br><span style="color: hsl(120, 100%, 40%);">+ and values equal to v (which defaults to None).</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%);">+ d = cls()</span><br><span style="color: hsl(120, 100%, 40%);">+ for key in iterable:</span><br><span style="color: hsl(120, 100%, 40%);">+ d[key] = value</span><br><span style="color: hsl(120, 100%, 40%);">+ return d</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def __eq__(self, other):</span><br><span style="color: hsl(120, 100%, 40%);">+ '''od.__eq__(y) <==> od==y. Comparison to another OD is order-sensitive</span><br><span style="color: hsl(120, 100%, 40%);">+ while comparison to a regular mapping is order-insensitive.</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%);">+ if isinstance(other, OrderedDict):</span><br><span style="color: hsl(120, 100%, 40%);">+ return len(self)==len(other) and self.items() == other.items()</span><br><span style="color: hsl(120, 100%, 40%);">+ return dict.__eq__(self, other)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def __ne__(self, other):</span><br><span style="color: hsl(120, 100%, 40%);">+ return not self == other</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ # -- the following methods are only used in Python 2.7 --</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def viewkeys(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ "od.viewkeys() -> a set-like object providing a view on od's keys"</span><br><span style="color: hsl(120, 100%, 40%);">+ return KeysView(self)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def viewvalues(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ "od.viewvalues() -> an object providing a view on od's values"</span><br><span style="color: hsl(120, 100%, 40%);">+ return ValuesView(self)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def viewitems(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ "od.viewitems() -> a set-like object providing a view on od's items"</span><br><span style="color: hsl(120, 100%, 40%);">+ return ItemsView(self)</span><br><span> </span><br><span> ###############################################################################</span><br><span> ### MultiOrderedDict</span><br><span>@@ -292,7 +296,7 @@</span><br><span> # TODO - find out why for some reason copies</span><br><span> # the [] as an [[]], so do manually</span><br><span> c = MultiOrderedDict() #self.__class__(self)</span><br><span style="color: hsl(0, 100%, 40%);">- for key, val in self.iteritems():</span><br><span style="color: hsl(120, 100%, 40%);">+ for key, val in self.items():</span><br><span> for v in val:</span><br><span> c[key] = v</span><br><span> return c</span><br><span>diff --git a/lib/python/asterisk/asterisk.py b/lib/python/asterisk/asterisk.py</span><br><span>old mode 100755</span><br><span>new mode 100644</span><br><span>index 985afea..c3996f6</span><br><span>--- a/lib/python/asterisk/asterisk.py</span><br><span>+++ b/lib/python/asterisk/asterisk.py</span><br><span>@@ -1,4 +1,3 @@</span><br><span style="color: hsl(0, 100%, 40%);">-#!/usr/bin/env python</span><br><span> """Asterisk Instances in Python.</span><br><span> </span><br><span> This module provides an interface for creating instances of Asterisk</span><br><span>@@ -18,9 +17,9 @@</span><br><span> import logging</span><br><span> import fileinput</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-import test_suite_utils</span><br><span style="color: hsl(120, 100%, 40%);">+from . import test_suite_utils</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-from config import ConfigFile</span><br><span style="color: hsl(120, 100%, 40%);">+from .config import ConfigFile</span><br><span> </span><br><span> from twisted.internet import reactor, protocol, defer, utils, error</span><br><span> from twisted.python.failure import Failure</span><br><span>@@ -54,7 +53,7 @@</span><br><span> def dataReceived(self, data):</span><br><span> """Called when we receive data back"""</span><br><span> LOGGER.debug(data)</span><br><span style="color: hsl(0, 100%, 40%);">- self.output += data</span><br><span style="color: hsl(120, 100%, 40%);">+ self.output += data.decode('utf-8', 'ignore')</span><br><span> </span><br><span> def connectionLost(self, reason):</span><br><span> """Called when the connect is lost"""</span><br><span>@@ -206,7 +205,8 @@</span><br><span> def _set_properties(self, result):</span><br><span> """Set the properties based on the result of the</span><br><span> getProcessOutputAndValue call"""</span><br><span style="color: hsl(0, 100%, 40%);">- self.output, self.err, self.exitcode = result</span><br><span style="color: hsl(120, 100%, 40%);">+ bintxt, self.err, self.exitcode = result</span><br><span style="color: hsl(120, 100%, 40%);">+ self.output = bintxt.decode('utf-8', 'ignore')</span><br><span> </span><br><span> </span><br><span> class AsteriskProtocol(protocol.ProcessProtocol):</span><br><span>@@ -232,7 +232,7 @@</span><br><span> </span><br><span> def outReceived(self, data):</span><br><span> """Override of ProcessProtocol.outReceived"""</span><br><span style="color: hsl(0, 100%, 40%);">- self.output += data</span><br><span style="color: hsl(120, 100%, 40%);">+ self.output += data.decode('utf-8', 'ignore')</span><br><span> </span><br><span> def connectionMade(self):</span><br><span> """Override of ProcessProtocol.connectionMade"""</span><br><span>@@ -311,20 +311,6 @@</span><br><span> we're not running into the asterisk.ctl AF_UNIX limit.</span><br><span> """</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- def compare_free_space(x, y):</span><br><span style="color: hsl(0, 100%, 40%);">- if os.stat(y).st_dev == os.stat(x).st_dev:</span><br><span style="color: hsl(0, 100%, 40%);">- return 0</span><br><span style="color: hsl(0, 100%, 40%);">- # statvfs can return a long; comparison functions must return an</span><br><span style="color: hsl(0, 100%, 40%);">- # int. Where both are same filesystem, bavail might change from</span><br><span style="color: hsl(0, 100%, 40%);">- # one call to the next, but hopefully it is not more than 1000.</span><br><span style="color: hsl(0, 100%, 40%);">- difference = os.statvfs(y).f_bavail - os.statvfs(x).f_bavail</span><br><span style="color: hsl(0, 100%, 40%);">- if (difference > 1000):</span><br><span style="color: hsl(0, 100%, 40%);">- return 1</span><br><span style="color: hsl(0, 100%, 40%);">- elif (difference < 1000):</span><br><span style="color: hsl(0, 100%, 40%);">- return -1</span><br><span style="color: hsl(0, 100%, 40%);">- else:</span><br><span style="color: hsl(0, 100%, 40%);">- return 0</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> localtest_root = os.getenv("AST_TEST_ROOT")</span><br><span> if localtest_root:</span><br><span> # Base location of the temporary files created by the testsuite</span><br><span>@@ -333,7 +319,7 @@</span><br><span> default_etc_directory = os.path.join(localtest_root, "etc/asterisk")</span><br><span> else:</span><br><span> # select tmp path with most available space</span><br><span style="color: hsl(0, 100%, 40%);">- best_tmp = sorted(['/tmp', '/var/tmp'], cmp=compare_free_space)[0]</span><br><span style="color: hsl(120, 100%, 40%);">+ best_tmp = sorted(['/tmp', '/var/tmp'], key=lambda path: os.statvfs(path).f_bavail)[0]</span><br><span> # Base location of the temporary files created by the testsuite</span><br><span> test_suite_root = best_tmp + "/asterisk-testsuite"</span><br><span> # The default etc directory for Asterisk</span><br><span>@@ -955,7 +941,7 @@</span><br><span> ast_file.write("#include \"%s/asterisk.options.conf.inc\"\n" %</span><br><span> (self.astetcdir))</span><br><span> if ast_conf_options:</span><br><span style="color: hsl(0, 100%, 40%);">- for (var, val) in ast_conf_options.iteritems():</span><br><span style="color: hsl(120, 100%, 40%);">+ for (var, val) in ast_conf_options.items():</span><br><span> ast_file.write("%s = %s\n" % (var, val))</span><br><span> for (var, val) in cat.options:</span><br><span> if not ast_conf_options or var not in ast_conf_options:</span><br><span>diff --git a/lib/python/asterisk/bridge_test_case.py b/lib/python/asterisk/bridge_test_case.py</span><br><span>index ea1767e..155b3a1 100644</span><br><span>--- a/lib/python/asterisk/bridge_test_case.py</span><br><span>+++ b/lib/python/asterisk/bridge_test_case.py</span><br><span>@@ -13,7 +13,7 @@</span><br><span> from time import sleep</span><br><span> </span><br><span> sys.path.append("lib/python")</span><br><span style="color: hsl(0, 100%, 40%);">-from test_case import TestCase</span><br><span style="color: hsl(120, 100%, 40%);">+from .test_case import TestCase</span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span> </span><br><span>diff --git a/lib/python/asterisk/buildoptions.py b/lib/python/asterisk/buildoptions.py</span><br><span>index 3b0b4b9..833053a 100644</span><br><span>--- a/lib/python/asterisk/buildoptions.py</span><br><span>+++ b/lib/python/asterisk/buildoptions.py</span><br><span>@@ -1,4 +1,3 @@</span><br><span style="color: hsl(0, 100%, 40%);">-#!/usr/bin/env python</span><br><span> """Asterisk Build Options Handling</span><br><span> </span><br><span> This module implements an Asterisk build options parser. It</span><br><span>@@ -13,7 +12,6 @@</span><br><span> """</span><br><span> </span><br><span> import sys</span><br><span style="color: hsl(0, 100%, 40%);">-import unittest</span><br><span> </span><br><span> </span><br><span> class AsteriskBuildOptions(object):</span><br><span>@@ -51,7 +49,7 @@</span><br><span> except IOError:</span><br><span> return ret_val</span><br><span> except:</span><br><span style="color: hsl(0, 100%, 40%);">- print "Unexpected error: %s" % sys.exc_info()[0]</span><br><span style="color: hsl(120, 100%, 40%);">+ print("Unexpected error: %s" % sys.exc_info()[0])</span><br><span> return ret_val</span><br><span> for line in file_lines:</span><br><span> if "#define" in line:</span><br><span>@@ -59,7 +57,7 @@</span><br><span> if (define_tuple[0] == "" or define_tuple[2] == ""):</span><br><span> msg = ("Unable to parse build option line [%s] into "</span><br><span> "compiler flag token and value" % line)</span><br><span style="color: hsl(0, 100%, 40%);">- print msg</span><br><span style="color: hsl(120, 100%, 40%);">+ print(msg)</span><br><span> else:</span><br><span> flag = define_tuple[0].strip()</span><br><span> allowed = define_tuple[2].strip()</span><br><span>@@ -89,22 +87,3 @@</span><br><span> elif expected_value == "0":</span><br><span> return True</span><br><span> return False</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-class AsteriskBuildOptionsTests(unittest.TestCase):</span><br><span style="color: hsl(0, 100%, 40%);">- """Unit tests for AsteriskBuildOptions"""</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_1(self):</span><br><span style="color: hsl(0, 100%, 40%);">- """Test the defaults paths"""</span><br><span style="color: hsl(0, 100%, 40%);">- build_options = AsteriskBuildOptions()</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(1)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-def main():</span><br><span style="color: hsl(0, 100%, 40%);">- """Main entry point for unit tests"""</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- unittest.main()</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-if __name__ == "__main__":</span><br><span style="color: hsl(0, 100%, 40%);">- main()</span><br><span>diff --git a/lib/python/asterisk/cdr.py b/lib/python/asterisk/cdr.py</span><br><span>index cc5226b..c5d62db 100644</span><br><span>--- a/lib/python/asterisk/cdr.py</span><br><span>+++ b/lib/python/asterisk/cdr.py</span><br><span>@@ -1,4 +1,3 @@</span><br><span style="color: hsl(0, 100%, 40%);">-#!/usr/bin/env python</span><br><span> """Asterisk call detail record testing</span><br><span> </span><br><span> This module implements an Asterisk CDR parser.</span><br><span>@@ -10,9 +9,8 @@</span><br><span> the GNU General Public License Version 2.</span><br><span> """</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-import unittest</span><br><span> import sys</span><br><span style="color: hsl(0, 100%, 40%);">-import astcsv</span><br><span style="color: hsl(120, 100%, 40%);">+from . import astcsv</span><br><span> import logging</span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span>@@ -138,32 +136,4 @@</span><br><span> AsteriskCSVCDRLine.fields, AsteriskCSVCDRLine)</span><br><span> </span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-class AsteriskCSVCDRTests(unittest.TestCase):</span><br><span style="color: hsl(0, 100%, 40%);">- """Unit tests for AsteriskCSVCDR"""</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_cdr(self):</span><br><span style="color: hsl(0, 100%, 40%);">- """Test the self_test/Master.csv record"""</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- cdr = AsteriskCSVCDR("self_test/Master.csv")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(len(cdr), 2)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(</span><br><span style="color: hsl(0, 100%, 40%);">- AsteriskCSVCDRLine(duration=7, lastapp="hangup").match(</span><br><span style="color: hsl(0, 100%, 40%);">- cdr[0],</span><br><span style="color: hsl(0, 100%, 40%);">- exact=(True, True)))</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(cdr[0].match(</span><br><span style="color: hsl(0, 100%, 40%);">- AsteriskCSVCDRLine(duration=7, lastapp="hangup"),</span><br><span style="color: hsl(0, 100%, 40%);">- exact=(True, True)))</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertFalse(cdr[1].match(cdr[0]))</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertFalse(cdr[0].match(cdr[1]))</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(cdr[0].billsec, "7")</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(cdr.match(cdr))</span><br><span style="color: hsl(0, 100%, 40%);">- cdr2 = AsteriskCSVCDR("self_test/Master2.csv")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertFalse(cdr.match(cdr2))</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-if __name__ == '__main__':</span><br><span style="color: hsl(0, 100%, 40%);">- unittest.main()</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> # vim:sw=4:ts=4:expandtab:textwidth=79</span><br><span>diff --git a/lib/python/asterisk/cel.py b/lib/python/asterisk/cel.py</span><br><span>index d22d67f..9965270 100644</span><br><span>--- a/lib/python/asterisk/cel.py</span><br><span>+++ b/lib/python/asterisk/cel.py</span><br><span>@@ -1,4 +1,3 @@</span><br><span style="color: hsl(0, 100%, 40%);">-#!/usr/bin/env python</span><br><span> """Asterisk call detail record testing</span><br><span> </span><br><span> This module implements an Asterisk CEL parser.</span><br><span>@@ -11,8 +10,7 @@</span><br><span> """</span><br><span> </span><br><span> import yaml</span><br><span style="color: hsl(0, 100%, 40%);">-import unittest</span><br><span style="color: hsl(0, 100%, 40%);">-import astcsv</span><br><span style="color: hsl(120, 100%, 40%);">+from . import astcsv</span><br><span> import re</span><br><span> import logging</span><br><span> </span><br><span>@@ -177,36 +175,4 @@</span><br><span> AsteriskCSVCELLine.fields, AsteriskCSVCELLine)</span><br><span> </span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-class AsteriskCSVCELTests(unittest.TestCase):</span><br><span style="color: hsl(0, 100%, 40%);">- """Unit tests for AsteriskCSVCEL"""</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_cel(self):</span><br><span style="color: hsl(0, 100%, 40%);">- """Test CEL using self_test/CELMaster1.csv"""</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- cel = AsteriskCSVCEL("self_test/CELMaster1.csv")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(len(cel), 16)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(AsteriskCSVCELLine(</span><br><span style="color: hsl(0, 100%, 40%);">- eventtype="LINKEDID_END",</span><br><span style="color: hsl(0, 100%, 40%);">- channel="TinCan/string").match(cel[-1],</span><br><span style="color: hsl(0, 100%, 40%);">- silent=True,</span><br><span style="color: hsl(0, 100%, 40%);">- exact=(True, True)))</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(cel[-1].match(</span><br><span style="color: hsl(0, 100%, 40%);">- AsteriskCSVCELLine(eventtype="LINKEDID_END",</span><br><span style="color: hsl(0, 100%, 40%);">- channel="TinCan/string"),</span><br><span style="color: hsl(0, 100%, 40%);">- silent=True,</span><br><span style="color: hsl(0, 100%, 40%);">- exact=(True, True)))</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertFalse(cel[1].match(cel[0], silent=True))</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertFalse(cel[0].match(cel[1], silent=True))</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(cel[-1].channel, "TinCan/string")</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(cel.match(cel))</span><br><span style="color: hsl(0, 100%, 40%);">- cel2 = AsteriskCSVCEL("self_test/CELMaster2.csv")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertFalse(cel.match(cel2))</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-if __name__ == '__main__':</span><br><span style="color: hsl(0, 100%, 40%);">- logging.basicConfig()</span><br><span style="color: hsl(0, 100%, 40%);">- unittest.main()</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> # vim:sw=4:ts=4:expandtab:textwidth=79</span><br><span>diff --git a/lib/python/asterisk/channel_test_condition.py b/lib/python/asterisk/channel_test_condition.py</span><br><span>index ec1d774..36421a4 100644</span><br><span>--- a/lib/python/asterisk/channel_test_condition.py</span><br><span>+++ b/lib/python/asterisk/channel_test_condition.py</span><br><span>@@ -1,4 +1,3 @@</span><br><span style="color: hsl(0, 100%, 40%);">-#!/usr/bin/env python</span><br><span> """Test condition for channels</span><br><span> </span><br><span> Copyright (C) 2011-2012, Digium, Inc.</span><br><span>@@ -9,9 +8,7 @@</span><br><span> """</span><br><span> </span><br><span> from twisted.internet import defer</span><br><span style="color: hsl(0, 100%, 40%);">-from test_conditions import TestCondition</span><br><span style="color: hsl(0, 100%, 40%);">-import logging</span><br><span style="color: hsl(0, 100%, 40%);">-import unittest</span><br><span style="color: hsl(120, 100%, 40%);">+from .test_conditions import TestCondition</span><br><span> import re</span><br><span> </span><br><span> </span><br><span>@@ -86,155 +83,3 @@</span><br><span> defer.DeferredList(exec_list).addCallback(_raise_finished,</span><br><span> finish_deferred)</span><br><span> return finish_deferred</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-class AstMockOutput(object):</span><br><span style="color: hsl(0, 100%, 40%);">- """mock cli output base class"""</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def __init__(self):</span><br><span style="color: hsl(0, 100%, 40%);">- """Constructor"""</span><br><span style="color: hsl(0, 100%, 40%);">- self.host = "127.0.0.1"</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def MockDefer(self, output):</span><br><span style="color: hsl(0, 100%, 40%);">- """use real defer to mock deferred output"""</span><br><span style="color: hsl(0, 100%, 40%);">- self.output = output</span><br><span style="color: hsl(0, 100%, 40%);">- deferred = defer.Deferred()</span><br><span style="color: hsl(0, 100%, 40%);">- deferred.callback(self)</span><br><span style="color: hsl(0, 100%, 40%);">- return deferred</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-class AstMockObjectInactive(AstMockOutput):</span><br><span style="color: hsl(0, 100%, 40%);">- """mock cli output showing no active channels"""</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def cli_exec(self, command):</span><br><span style="color: hsl(0, 100%, 40%);">- """presume command is core show channels and generate output"""</span><br><span style="color: hsl(0, 100%, 40%);">- output = ""</span><br><span style="color: hsl(0, 100%, 40%);">- output += "Channel Location State Application(Data)\n"</span><br><span style="color: hsl(0, 100%, 40%);">- output += "0 active channels\n"</span><br><span style="color: hsl(0, 100%, 40%);">- output += "0 active calls\n"</span><br><span style="color: hsl(0, 100%, 40%);">- output += "2 calls processed\n"</span><br><span style="color: hsl(0, 100%, 40%);">- output += "Asterisk ending (0).\n"</span><br><span style="color: hsl(0, 100%, 40%);">- return self.MockDefer(output)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-class AstMockObjectSingle(AstMockOutput):</span><br><span style="color: hsl(0, 100%, 40%);">- """mock cli output showing single active channel"""</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def cli_exec(self, command):</span><br><span style="color: hsl(0, 100%, 40%);">- """presume command is core show channels and generate output"""</span><br><span style="color: hsl(0, 100%, 40%);">- output = ""</span><br><span style="color: hsl(0, 100%, 40%);">- output += "Channel Location State Application(Data)\n"</span><br><span style="color: hsl(0, 100%, 40%);">- output += "Local/123@default-00 (None) Down ()\n"</span><br><span style="color: hsl(0, 100%, 40%);">- output += "1 active channels\n"</span><br><span style="color: hsl(0, 100%, 40%);">- output += "0 active calls\n"</span><br><span style="color: hsl(0, 100%, 40%);">- output += "2 calls processed\n"</span><br><span style="color: hsl(0, 100%, 40%);">- output += "Asterisk ending (0).\n"</span><br><span style="color: hsl(0, 100%, 40%);">- return self.MockDefer(output)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-class AstMockObjectMultiple(AstMockOutput):</span><br><span style="color: hsl(0, 100%, 40%);">- """mock cli output showing multiple active channels"""</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def cli_exec(self, command):</span><br><span style="color: hsl(0, 100%, 40%);">- """presume command is core show channels and generate output"""</span><br><span style="color: hsl(0, 100%, 40%);">- output = ""</span><br><span style="color: hsl(0, 100%, 40%);">- output += "Channel Location State Application(Data)\n"</span><br><span style="color: hsl(0, 100%, 40%);">- output += "PJSIP/123@default-00 (None) Down ()\n"</span><br><span style="color: hsl(0, 100%, 40%);">- output += "Local/123@default-00 (None) Down ()\n"</span><br><span style="color: hsl(0, 100%, 40%);">- output += "SIP/alice@default-00 (None) Down ()\n"</span><br><span style="color: hsl(0, 100%, 40%);">- output += "3 active channels\n"</span><br><span style="color: hsl(0, 100%, 40%);">- output += "0 active calls\n"</span><br><span style="color: hsl(0, 100%, 40%);">- output += "2 calls processed\n"</span><br><span style="color: hsl(0, 100%, 40%);">- output += "Asterisk ending (0).\n"</span><br><span style="color: hsl(0, 100%, 40%);">- return self.MockDefer(output)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-class AstMockObjectLeaked(AstMockOutput):</span><br><span style="color: hsl(0, 100%, 40%);">- """mock cli output showing leaked channel"""</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def cli_exec(self, command):</span><br><span style="color: hsl(0, 100%, 40%);">- """presume command is core show channels and generate output"""</span><br><span style="color: hsl(0, 100%, 40%);">- output = ""</span><br><span style="color: hsl(0, 100%, 40%);">- output += "Channel Location State Application(Data)\n"</span><br><span style="color: hsl(0, 100%, 40%);">- output += "Local/123@default-00 (None) Down ()\n"</span><br><span style="color: hsl(0, 100%, 40%);">- output += "0 active channels\n"</span><br><span style="color: hsl(0, 100%, 40%);">- output += "0 active calls\n"</span><br><span style="color: hsl(0, 100%, 40%);">- output += "2 calls processed\n"</span><br><span style="color: hsl(0, 100%, 40%);">- output += "Asterisk ending (0).\n"</span><br><span style="color: hsl(0, 100%, 40%);">- return self.MockDefer(output)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-class TestConfig(object):</span><br><span style="color: hsl(0, 100%, 40%);">- """Fake TestConfig object for unittest"""</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def __init__(self):</span><br><span style="color: hsl(0, 100%, 40%);">- self.class_type_name = "bogus"</span><br><span style="color: hsl(0, 100%, 40%);">- self.config = {}</span><br><span style="color: hsl(0, 100%, 40%);">- self.enabled = True</span><br><span style="color: hsl(0, 100%, 40%);">- self.pass_expected = True</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-class ChannelTestConditionUnitTest(unittest.TestCase):</span><br><span style="color: hsl(0, 100%, 40%);">- """Unit Tests for ChannelTestCondition"""</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_evaluate_inactive(self):</span><br><span style="color: hsl(0, 100%, 40%);">- """test inactive channel condition"""</span><br><span style="color: hsl(0, 100%, 40%);">- obj = ChannelTestCondition(TestConfig())</span><br><span style="color: hsl(0, 100%, 40%);">- obj.register_asterisk_instance(AstMockObjectInactive())</span><br><span style="color: hsl(0, 100%, 40%);">- obj.evaluate()</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.get_status(), 'Passed')</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_evaluate_multiple_fail(self):</span><br><span style="color: hsl(0, 100%, 40%);">- """test multiple channel condition"""</span><br><span style="color: hsl(0, 100%, 40%);">- obj = ChannelTestCondition(TestConfig())</span><br><span style="color: hsl(0, 100%, 40%);">- obj.register_asterisk_instance(AstMockObjectMultiple())</span><br><span style="color: hsl(0, 100%, 40%);">- obj.evaluate()</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.get_status(), 'Failed')</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_evaluate_multiple_fail2(self):</span><br><span style="color: hsl(0, 100%, 40%);">- """test multiple channel condition"""</span><br><span style="color: hsl(0, 100%, 40%);">- obj = ChannelTestCondition(TestConfig())</span><br><span style="color: hsl(0, 100%, 40%);">- obj.allowed_channels = 2</span><br><span style="color: hsl(0, 100%, 40%);">- obj.register_asterisk_instance(AstMockObjectMultiple())</span><br><span style="color: hsl(0, 100%, 40%);">- obj.evaluate()</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.get_status(), 'Failed')</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_evaluate_multiple_pass(self):</span><br><span style="color: hsl(0, 100%, 40%);">- """test multiple channel condition"""</span><br><span style="color: hsl(0, 100%, 40%);">- obj = ChannelTestCondition(TestConfig())</span><br><span style="color: hsl(0, 100%, 40%);">- obj.allowed_channels = 3</span><br><span style="color: hsl(0, 100%, 40%);">- obj.register_asterisk_instance(AstMockObjectMultiple())</span><br><span style="color: hsl(0, 100%, 40%);">- obj.evaluate()</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.get_status(), 'Passed')</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_evaluate_single_fail(self):</span><br><span style="color: hsl(0, 100%, 40%);">- """test single channel condition"""</span><br><span style="color: hsl(0, 100%, 40%);">- obj = ChannelTestCondition(TestConfig())</span><br><span style="color: hsl(0, 100%, 40%);">- obj.register_asterisk_instance(AstMockObjectSingle())</span><br><span style="color: hsl(0, 100%, 40%);">- obj.evaluate()</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.get_status(), 'Failed')</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_evaluate_single_pass(self):</span><br><span style="color: hsl(0, 100%, 40%);">- """test single channel condition"""</span><br><span style="color: hsl(0, 100%, 40%);">- obj = ChannelTestCondition(TestConfig())</span><br><span style="color: hsl(0, 100%, 40%);">- obj.allowed_channels = 1</span><br><span style="color: hsl(0, 100%, 40%);">- obj.register_asterisk_instance(AstMockObjectSingle())</span><br><span style="color: hsl(0, 100%, 40%);">- obj.evaluate()</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.get_status(), 'Passed')</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_evaluate_leaked(self):</span><br><span style="color: hsl(0, 100%, 40%);">- """test leaked channel condition"""</span><br><span style="color: hsl(0, 100%, 40%);">- obj = ChannelTestCondition(TestConfig())</span><br><span style="color: hsl(0, 100%, 40%);">- obj.register_asterisk_instance(AstMockObjectLeaked())</span><br><span style="color: hsl(0, 100%, 40%);">- obj.evaluate()</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.get_status(), 'Failed')</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-def main():</span><br><span style="color: hsl(0, 100%, 40%);">- """Run the unit tests"""</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- logging.basicConfig(level=logging.DEBUG)</span><br><span style="color: hsl(0, 100%, 40%);">- unittest.main()</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-if __name__ == "__main__":</span><br><span style="color: hsl(0, 100%, 40%);">- main()</span><br><span>diff --git a/lib/python/asterisk/confbridge.py b/lib/python/asterisk/confbridge.py</span><br><span>index acca1e7..0ca364d 100644</span><br><span>--- a/lib/python/asterisk/confbridge.py</span><br><span>+++ b/lib/python/asterisk/confbridge.py</span><br><span>@@ -14,7 +14,7 @@</span><br><span> import sys</span><br><span> import logging</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-from test_state import TestState</span><br><span style="color: hsl(120, 100%, 40%);">+from .test_state import TestState</span><br><span> from twisted.internet import reactor</span><br><span> </span><br><span> sys.path.append("lib/python")</span><br><span>diff --git a/lib/python/asterisk/config.py b/lib/python/asterisk/config.py</span><br><span>old mode 100755</span><br><span>new mode 100644</span><br><span>index e26b156..c5662d2</span><br><span>--- a/lib/python/asterisk/config.py</span><br><span>+++ b/lib/python/asterisk/config.py</span><br><span>@@ -1,4 +1,3 @@</span><br><span style="color: hsl(0, 100%, 40%);">-#!/usr/bin/env python</span><br><span> """Asterisk Configuration File Handling.</span><br><span> </span><br><span> This module implements interfaces for dealing with Asterisk configuration</span><br><span>@@ -18,7 +17,6 @@</span><br><span> </span><br><span> import sys</span><br><span> import re</span><br><span style="color: hsl(0, 100%, 40%);">-import unittest</span><br><span> import logging</span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span>@@ -54,7 +52,7 @@</span><br><span> match = self.varval_re.match(line)</span><br><span> if match is None:</span><br><span> if not is_blank_line(line):</span><br><span style="color: hsl(0, 100%, 40%);">- LOGGER.warn("Invalid line: '%s'" % line.strip())</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGGER.warning("Invalid line: '%s'" % line.strip())</span><br><span> return</span><br><span> self.options.append((match.group("name"), match.group("value").strip()))</span><br><span> </span><br><span>@@ -109,94 +107,6 @@</span><br><span> )</span><br><span> elif len(self.categories) == 0:</span><br><span> if not is_blank_line(line):</span><br><span style="color: hsl(0, 100%, 40%);">- LOGGER.warn("Invalid line: '%s'" % line.strip())</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGGER.warning("Invalid line: '%s'" % line.strip())</span><br><span> else:</span><br><span> self.categories[-1].parse_line(line)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-class ConfigFileTests(unittest.TestCase):</span><br><span style="color: hsl(0, 100%, 40%);">- """Unit tests for ConfigFile"""</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_conf(self):</span><br><span style="color: hsl(0, 100%, 40%);">- """Test parsing a blob of config data"""</span><br><span style="color: hsl(0, 100%, 40%);">- test = \</span><br><span style="color: hsl(0, 100%, 40%);">- "; stuff\n" \</span><br><span style="color: hsl(0, 100%, 40%);">- "this line is invalid on purpose\n" \</span><br><span style="color: hsl(0, 100%, 40%);">- "[this is] also invalid]\n" \</span><br><span style="color: hsl(0, 100%, 40%);">- ";-- comment --;\n" \</span><br><span style="color: hsl(0, 100%, 40%);">- ";-- \n" \</span><br><span style="color: hsl(0, 100%, 40%);">- "[this is commented out]\n" \</span><br><span style="color: hsl(0, 100%, 40%);">- " --;\n" \</span><br><span style="color: hsl(0, 100%, 40%);">- "[foo]\n" \</span><br><span style="color: hsl(0, 100%, 40%);">- "a = b\n" \</span><br><span style="color: hsl(0, 100%, 40%);">- " b = a \n" \</span><br><span style="color: hsl(0, 100%, 40%);">- "this line is invalid on purpose\n" \</span><br><span style="color: hsl(0, 100%, 40%);">- ";moo\n" \</span><br><span style="color: hsl(0, 100%, 40%);">- "c = d;asdadf;adfads;adsfasdf\n" \</span><br><span style="color: hsl(0, 100%, 40%);">- " [bar] ;asdfasdf\n" \</span><br><span style="color: hsl(0, 100%, 40%);">- "a-b=c-d\n" \</span><br><span style="color: hsl(0, 100%, 40%);">- "xyz=x|y|z\n" \</span><br><span style="color: hsl(0, 100%, 40%);">- "1234 => 4242,Example Mailbox,root@localhost,,var=val\n" \</span><br><span style="color: hsl(0, 100%, 40%);">- "\n" \</span><br><span style="color: hsl(0, 100%, 40%);">- "[template](!)\n" \</span><br><span style="color: hsl(0, 100%, 40%);">- "foo=bar\n" \</span><br><span style="color: hsl(0, 100%, 40%);">- "exten => _NXX.,n,Wait(1)\n" \</span><br><span style="color: hsl(0, 100%, 40%);">- "astetcdir => /etc/asterisk\n"</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- conf = ConfigFile(fn=None, config_str=test)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(len(conf.categories), 3)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(conf.categories[0].name, "foo")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertFalse(conf.categories[0].template)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(len(conf.categories[0].options), 3)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(conf.categories[0].options[0][0], "a")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(conf.categories[0].options[0][1], "b")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(conf.categories[0].options[1][0], "b")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(conf.categories[0].options[1][1], "a")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(conf.categories[0].options[2][0], "c")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(conf.categories[0].options[2][1], "d")</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(conf.categories[1].name, "bar")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertFalse(conf.categories[1].template)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(len(conf.categories[1].options), 3)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(conf.categories[1].options[0][0], "a-b")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(conf.categories[1].options[0][1], "c-d")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(conf.categories[1].options[1][0], "xyz")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(conf.categories[1].options[1][1], "x|y|z")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(conf.categories[1].options[2][0], "1234")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(conf.categories[1].options[2][1],</span><br><span style="color: hsl(0, 100%, 40%);">- "4242,Example Mailbox,root@localhost,,var=val")</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(conf.categories[2].name, "template")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(conf.categories[2].template)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(len(conf.categories[2].options), 3)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(conf.categories[2].options[0][0], "foo")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(conf.categories[2].options[0][1], "bar")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(conf.categories[2].options[1][0], "exten")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(conf.categories[2].options[1][1],</span><br><span style="color: hsl(0, 100%, 40%);">- "_NXX.,n,Wait(1)")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(conf.categories[2].options[2][0], "astetcdir")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(conf.categories[2].options[2][1], "/etc/asterisk")</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-def main(argv=None):</span><br><span style="color: hsl(0, 100%, 40%);">- """Read in and show a config file, or run unit tests"""</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if argv is None:</span><br><span style="color: hsl(0, 100%, 40%);">- argv = sys.argv</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- if len(argv) == 2:</span><br><span style="color: hsl(0, 100%, 40%);">- conf = ConfigFile(argv[1])</span><br><span style="color: hsl(0, 100%, 40%);">- for cat in conf.categories:</span><br><span style="color: hsl(0, 100%, 40%);">- LOGGER.debug("[%s]" % cat.name)</span><br><span style="color: hsl(0, 100%, 40%);">- for (var, val) in cat.options:</span><br><span style="color: hsl(0, 100%, 40%);">- LOGGER.debug("%s = %s" % (var, val))</span><br><span style="color: hsl(0, 100%, 40%);">- else:</span><br><span style="color: hsl(0, 100%, 40%);">- return unittest.main()</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return 0</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-if __name__ == "__main__":</span><br><span style="color: hsl(0, 100%, 40%);">- sys.exit(main() or 0)</span><br><span>diff --git a/lib/python/asterisk/fd_test_condition.py b/lib/python/asterisk/fd_test_condition.py</span><br><span>index 4a8f869..234af28 100644</span><br><span>--- a/lib/python/asterisk/fd_test_condition.py</span><br><span>+++ b/lib/python/asterisk/fd_test_condition.py</span><br><span>@@ -11,7 +11,7 @@</span><br><span> import logging</span><br><span> </span><br><span> from twisted.internet import defer</span><br><span style="color: hsl(0, 100%, 40%);">-from test_conditions import TestCondition</span><br><span style="color: hsl(120, 100%, 40%);">+from .test_conditions import TestCondition</span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span> </span><br><span>diff --git a/lib/python/asterisk/lock_test_condition.py b/lib/python/asterisk/lock_test_condition.py</span><br><span>index 0296693..805e2ff 100644</span><br><span>--- a/lib/python/asterisk/lock_test_condition.py</span><br><span>+++ b/lib/python/asterisk/lock_test_condition.py</span><br><span>@@ -1,4 +1,3 @@</span><br><span style="color: hsl(0, 100%, 40%);">-#!/usr/bin/env python</span><br><span> """Held locks test condition</span><br><span> </span><br><span> Copyright (C) 2011-2012, Digium, Inc.</span><br><span>@@ -10,10 +9,9 @@</span><br><span> </span><br><span> import logging</span><br><span> import logging.config</span><br><span style="color: hsl(0, 100%, 40%);">-import unittest</span><br><span> </span><br><span> from twisted.internet import defer</span><br><span style="color: hsl(0, 100%, 40%);">-from test_conditions import TestCondition</span><br><span style="color: hsl(120, 100%, 40%);">+from .test_conditions import TestCondition</span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span> </span><br><span>@@ -199,7 +197,7 @@</span><br><span> def evaluate(self, related_test_condition=None):</span><br><span> """Evaluate the condition"""</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- def __lock_info_obtained(finished_deferred):</span><br><span style="color: hsl(120, 100%, 40%);">+ def __lock_info_obtained(lst, finished_deferred):</span><br><span> """Callback when lock information has been obtained"""</span><br><span> if (len(self.locks) > 0):</span><br><span> #Sometimes, a lock will be held at the end of a test run</span><br><span>@@ -229,314 +227,3 @@</span><br><span> finished_deferred)</span><br><span> return finished_deferred</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-class AstMockObjectPassed(object):</span><br><span style="color: hsl(0, 100%, 40%);">- """A lock output that passed"""</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def __init__(self):</span><br><span style="color: hsl(0, 100%, 40%);">- """Constructor"""</span><br><span style="color: hsl(0, 100%, 40%);">- self.host = "127.0.0.2"</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def cli_exec(self, command, sync):</span><br><span style="color: hsl(0, 100%, 40%);">- """Fake out a CLI command execution"""</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines = "=======================================================================\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "=== Currently Held Locks ==============================================\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "=======================================================================\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "===\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "=== <pending> <lock#> (<file>): <lock type> <line num> <function> <lock name> <lock addr> (times locked)\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "===\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "===\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "=======================================================================\n"</span><br><span style="color: hsl(0, 100%, 40%);">- return lock_lines</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-class AstMockObjectFailure(object):</span><br><span style="color: hsl(0, 100%, 40%);">- """A lock object that failed"""</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def __init__(self):</span><br><span style="color: hsl(0, 100%, 40%);">- """Constructor"""</span><br><span style="color: hsl(0, 100%, 40%);">- self.host = "127.0.0.1"</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def cli_exec(self, command, sync):</span><br><span style="color: hsl(0, 100%, 40%);">- """Fake out a CLI command execution"""</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines = "=======================================================================\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "=== Currently Held Locks ==============================================\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "=======================================================================\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "===\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "=== <pending> <lock#> (<file>): <lock type> <line num> <function> <lock name> <lock addr> (times locked)\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "===\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "=== Thread ID: 0x402c6940 (do_monitor started at [25114] chan_sip.c restart_monitor())\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "=== ---> Lock #0 (chan_sip.c): MUTEX 24629 handle_request_do &netlock 0x2aaabe671a40 (1)\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk(ast_bt_get_addresses+0x1a) [0x4e9679]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk(__ast_pthread_mutex_lock+0xf6) [0x4e22d9]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/lib/asterisk/modules/chan_sip.so [0x2aaabe423ee8]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "=== ---> Lock #1 (chan_sip.c): MUTEX 24629 handle_request_do &netlock 0x2aaabe671a40 (1)\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "=== --- ---> Locked Here: channel.c line 4304 (ast_indicate_data)\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "=== -------------------------------------------------------------------\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "===\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "=== Thread ID: 0x449ec940 (netconsole started at [ 1351] asterisk.c listener())\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "=== ---> Waiting for Lock #0 (astobj2.c): MUTEX 842 internal_ao2_iterator_next a->c 0x2aaaac491f50 (1)\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk(ast_bt_get_addresses+0x1a) [0x4e9679]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk(__ast_pthread_mutex_lock+0xf6) [0x4e22d9]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk(__ao2_lock+0x53) [0x4456fc]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk [0x446cec]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk(__ao2_iterator_next+0x29) [0x447134]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk(ast_channel_iterator_next+0x19) [0x46cf7d]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk [0x489e43]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk(ast_cli_command_full+0x222) [0x48eec4]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk(ast_cli_command_multiple_full+0x92) [0x48f035]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk [0x43d129]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk [0x5661c6]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/lib64/libpthread.so.0 [0x3d1d80673d]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/lib64/libc.so.6(clone+0x6d) [0x3d1ccd44bd]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "=== --- ---> Locked Here: astobj2.c line 657 (internal_ao2_callback)\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "=== -------------------------------------------------------------------\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "===\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "=== Thread ID: 0x44a68940 (netconsole started at [ 1351] asterisk.c listener())\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "=== ---> Waiting for Lock #0 (astobj2.c): MUTEX 842 internal_ao2_iterator_next a->c 0x2aaaac491f50 (1)\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk(ast_bt_get_addresses+0x1a) [0x4e9679]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk(__ast_pthread_mutex_lock+0xf6) [0x4e22d9]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk(__ao2_lock+0x53) [0x4456fc]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk [0x446cec]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk(__ao2_iterator_next+0x29) [0x447134]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk(ast_channel_iterator_next+0x19) [0x46cf7d]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk [0x489e43]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk(ast_cli_command_full+0x222) [0x48eec4]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk(ast_cli_command_multiple_full+0x92) [0x48f035]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk [0x43d129]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk [0x5661c6]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/lib64/libpthread.so.0 [0x3d1d80673d]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/lib64/libc.so.6(clone+0x6d) [0x3d1ccd44bd]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "=== --- ---> Locked Here: astobj2.c line 657 (internal_ao2_callback)\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "=== -------------------------------------------------------------------\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "===\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "=======================================================================\n"</span><br><span style="color: hsl(0, 100%, 40%);">- return lock_lines</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-class TestConfig(object):</span><br><span style="color: hsl(0, 100%, 40%);">- """Fake TestConfig object"""</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def __init__(self):</span><br><span style="color: hsl(0, 100%, 40%);">- """ Values here don't matter much - we just need to have something """</span><br><span style="color: hsl(0, 100%, 40%);">- self.class_type_name = "asterisk.LockTestCondition.LockTestCondition"</span><br><span style="color: hsl(0, 100%, 40%);">- self.pass_expected = True</span><br><span style="color: hsl(0, 100%, 40%);">- self.type = "Post"</span><br><span style="color: hsl(0, 100%, 40%);">- self.related_condition = ""</span><br><span style="color: hsl(0, 100%, 40%);">- self.config = {}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-class LockTestConditionUnitTest(unittest.TestCase):</span><br><span style="color: hsl(0, 100%, 40%);">- """Unit tests for LockTestCondition"""</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_evaluate_failed(self):</span><br><span style="color: hsl(0, 100%, 40%);">- """Test a failed locking condition"""</span><br><span style="color: hsl(0, 100%, 40%);">- ast = AstMockObjectFailure()</span><br><span style="color: hsl(0, 100%, 40%);">- obj = LockTestCondition(TestConfig())</span><br><span style="color: hsl(0, 100%, 40%);">- obj.register_asterisk_instance(ast)</span><br><span style="color: hsl(0, 100%, 40%);">- obj.evaluate()</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.get_status(), 'Failed')</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_evaluate_pass(self):</span><br><span style="color: hsl(0, 100%, 40%);">- """Test a passed locking condition"""</span><br><span style="color: hsl(0, 100%, 40%);">- ast = AstMockObjectPassed()</span><br><span style="color: hsl(0, 100%, 40%);">- obj = LockTestCondition(TestConfig())</span><br><span style="color: hsl(0, 100%, 40%);">- obj.register_asterisk_instance(ast)</span><br><span style="color: hsl(0, 100%, 40%);">- obj.evaluate()</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.get_status(), 'Passed')</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_evaluate_multiple(self):</span><br><span style="color: hsl(0, 100%, 40%);">- """Test multiple results"""</span><br><span style="color: hsl(0, 100%, 40%);">- ast1 = AstMockObjectPassed()</span><br><span style="color: hsl(0, 100%, 40%);">- ast2 = AstMockObjectFailure()</span><br><span style="color: hsl(0, 100%, 40%);">- obj = LockTestCondition(TestConfig())</span><br><span style="color: hsl(0, 100%, 40%);">- obj.register_asterisk_instance(ast1)</span><br><span style="color: hsl(0, 100%, 40%);">- obj.register_asterisk_instance(ast2)</span><br><span style="color: hsl(0, 100%, 40%);">- obj.evaluate()</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.get_status(), 'Failed')</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-class LockSequenceUnitTest(unittest.TestCase):</span><br><span style="color: hsl(0, 100%, 40%);">- """Tests for parsing a lock sequence"""</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_single_object_no_held_info(self):</span><br><span style="color: hsl(0, 100%, 40%);">- """Test a lock sequence with no waiting lock"""</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines = "=== Thread ID: 0x7f668c142700 (do_monitor started at [25915] chan_sip.c restart_monitor())\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "=== ---> Lock #0 (chan_sip.c): MUTEX 25390 handle_request_do &netlock 0x7f6652193900 (1)\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "main/logger.c:1302 ast_bt_get_addresses() (0x505e53+1D)\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "main/lock.c:193 __ast_pthread_mutex_lock() (0x4fe55c+D9)\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "channels/chan_sip.c:25393 handle_request_do()\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "channels/chan_sip.c:25352 sipsock_read()\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "main/io.c:288 ast_io_wait() (0x4f8228+19C)\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "channels/chan_sip.c:25882 do_monitor()\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "main/utils.c:1010 dummy_start()\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "libpthread.so.0 <unknown>()\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "libc.so.6 clone() (0x31be0e0bc0+6D)\n"</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- obj = LockSequence()</span><br><span style="color: hsl(0, 100%, 40%);">- obj.parse_lock_sequence(lock_lines)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_large_multiple_object(self):</span><br><span style="color: hsl(0, 100%, 40%);">- """Test with a waiting lock"""</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines = "=== Thread ID: 0x449ec940 (netconsole started at [ 1351] asterisk.c listener())\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "=== ---> Waiting for Lock #0 (astobj2.c): MUTEX 842 internal_ao2_iterator_next a->c 0x2aaaac491f50 (1)\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk(ast_bt_get_addresses+0x1a) [0x4e9679]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk(__ast_pthread_mutex_lock+0xf6) [0x4e22d9]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk(__ao2_lock+0x53) [0x4456fc]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk [0x446cec]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk(__ao2_iterator_next+0x29) [0x447134]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk(ast_channel_iterator_next+0x19) [0x46cf7d]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk [0x489e43]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk(ast_cli_command_full+0x222) [0x48eec4]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk(ast_cli_command_multiple_full+0x92) [0x48f035]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk [0x43d129]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk [0x5661c6]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/lib64/libpthread.so.0 [0x3d1d80673d]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/lib64/libc.so.6(clone+0x6d) [0x3d1ccd44bd]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "=== --- ---> Locked Here: astobj2.c line 657 (internal_ao2_callback)\n"</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- obj = LockSequence()</span><br><span style="color: hsl(0, 100%, 40%);">- obj.parse_lock_sequence(lock_lines)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.thread_id, "0x449ec940")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.thread_name, "netconsole")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.thread_line, 1351)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.thread_file, "asterisk.c")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.thread_func, "listener")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(len(obj.locks) == 1)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.locks[0].locked_file, "astobj2.c")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.locks[0].locked_line, 657)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.locks[0].locked_func, "internal_ao2_callback")</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_single_object(self):</span><br><span style="color: hsl(0, 100%, 40%);">- """Test a lock held somewhere else"""</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines = "=== Thread ID: 0x402c6940 (do_monitor started at [25114] chan_sip.c restart_monitor())\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "=== ---> Lock #0 (chan_sip.c): MUTEX 24629 handle_request_do &netlock 0x2aaabe671a40 (1)\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk(ast_bt_get_addresses+0x1a) [0x4e9679]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk(__ast_pthread_mutex_lock+0xf6) [0x4e22d9]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/lib/asterisk/modules/chan_sip.so [0x2aaabe423ee8]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "=== --- ---> Locked Here: channel.c line 4304 (ast_indicate_data)\n"</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- obj = LockSequence()</span><br><span style="color: hsl(0, 100%, 40%);">- obj.parse_lock_sequence(lock_lines)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.thread_id, "0x402c6940")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.thread_name, "do_monitor")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.thread_line, 25114)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.thread_file, "chan_sip.c")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.thread_func, "restart_monitor")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(len(obj.locks) == 1)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.locks[0].locked_file, "channel.c")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.locks[0].locked_line, 4304)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.locks[0].locked_func, "ast_indicate_data")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.locks[0].id, 0)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.locks[0].type, "MUTEX")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.locks[0].file, "chan_sip.c")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.locks[0].line_number, 24629)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.locks[0].func, "handle_request_do")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.locks[0].name, "&netlock")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.locks[0].addr, "0x2aaabe671a40")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.locks[0].lock_count, 1)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(obj.locks[0].held)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(len(obj.locks[0].backtrace) == 3)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_multiple_objects_no_backtrace(self):</span><br><span style="color: hsl(0, 100%, 40%);">- """Test multiple locks with no backtrace"""</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines = "=== Thread ID: 0x402c6940 (do_monitor started at [25114] chan_sip.c restart_monitor())\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "=== ---> Lock #0 (chan_sip.c): MUTEX 24629 handle_request_do &netlock 0x2aaabe671a40 (1)\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "=== ---> Lock #1 (astobj2.c): MUTEX 657 internal_ao2_callback c 0x2aaaac491f50 (1)\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "=== ---> Waiting for Lock #2 (channel.c): MUTEX 1691 ast_channel_cmp_cb chan 0x2aaaacd3a4e0 (1)\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "=== --- ---> Locked Here: channel.c line 4304 (ast_indicate_data)\n"</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- obj = LockSequence()</span><br><span style="color: hsl(0, 100%, 40%);">- obj.parse_lock_sequence(lock_lines)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.thread_id, "0x402c6940")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.thread_name, "do_monitor")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.thread_line, 25114)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.thread_file, "chan_sip.c")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.thread_func, "restart_monitor")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(len(obj.locks) == 3)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.locks[2].locked_file, "channel.c")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.locks[2].locked_line, 4304)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.locks[2].locked_func, "ast_indicate_data")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.locks[0].id, 0)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.locks[0].type, "MUTEX")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.locks[0].file, "chan_sip.c")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.locks[0].line_number, 24629)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.locks[0].func, "handle_request_do")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.locks[0].name, "&netlock")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.locks[0].addr, "0x2aaabe671a40")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.locks[0].lock_count, 1)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(obj.locks[0].held)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(len(obj.locks[0].backtrace) == 0)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-class LockObjectUnitTest(unittest.TestCase):</span><br><span style="color: hsl(0, 100%, 40%);">- """Unit tests for LockObject"""</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_no_backtrace(self):</span><br><span style="color: hsl(0, 100%, 40%);">- """Test creating a lock object with no thread backtrace"""</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- lock_line = "=== ---> Waiting for Lock #0 (sig_ss7.c): MUTEX 636 ss7_linkset &linkset->lock 0x2aaab8a6b588 (1)"</span><br><span style="color: hsl(0, 100%, 40%);">- obj = LockObject()</span><br><span style="color: hsl(0, 100%, 40%);">- obj.parse_lock_information(lock_line)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.id, 0)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.type, "MUTEX")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.file, "sig_ss7.c")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.line_number, 636)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.func, "ss7_linkset")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.name, "&linkset->lock")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.addr, "0x2aaab8a6b588")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.lock_count, 1)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertFalse(obj.held)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(len(obj.backtrace) == 0)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_with_backtrace(self):</span><br><span style="color: hsl(0, 100%, 40%);">- """Test creating a lock object with a thread backtrace"""</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines = "=== ---> Lock #1 (astobj2.c): MUTEX 657 internal_ao2_callback c 0x2aaaac491f50 (1)\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk(ast_bt_get_addresses+0x1a) [0x4e9679]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk(__ast_pthread_mutex_lock+0xf6) [0x4e22d9]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk(__ao2_lock+0x53) [0x4456fc]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk [0x4464be]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk(__ao2_callback+0x59) [0x446a4e]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk(__ao2_find+0x2b) [0x446ba7]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk [0x46d3a7]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk(ast_channel_get_by_name+0x24) [0x46d3e3]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/lib/asterisk/modules/func_channel.so [0x2aaabfba2468]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk(ast_func_write+0x16a) [0x50aacd]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk(pbx_builtin_setvar_helper+0x10e) [0x51fff4]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/lib/asterisk/modules/chan_sip.so [0x2aaabe422d09]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/lib/asterisk/modules/chan_sip.so [0x2aaabe4240a0]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/lib/asterisk/modules/chan_sip.so [0x2aaabe423cf1]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk(ast_io_wait+0x1ba) [0x4dc2e4]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/lib/asterisk/modules/chan_sip.so [0x2aaabe425722]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/usr/local/asterisk-1.8.6.0/sbin/asterisk [0x5661c6]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/lib64/libpthread.so.0 [0x3d1d80673d]\n"</span><br><span style="color: hsl(0, 100%, 40%);">- lock_lines += "/lib64/libc.so.6(clone+0x6d) [0x3d1ccd44bd]\n"</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- obj = LockObject()</span><br><span style="color: hsl(0, 100%, 40%);">- obj.parse_lock_information(lock_lines)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.id, 1)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.type, "MUTEX")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.file, "astobj2.c")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.line_number, 657)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.func, "internal_ao2_callback")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.name, "c")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.addr, "0x2aaaac491f50")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.lock_count, 1)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(obj.held)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(len(obj.backtrace) == 19)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-def main():</span><br><span style="color: hsl(0, 100%, 40%);">- """Run the unit tests"""</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- logging.basicConfig(level=logging.DEBUG)</span><br><span style="color: hsl(0, 100%, 40%);">- unittest.main()</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-if __name__ == "__main__":</span><br><span style="color: hsl(0, 100%, 40%);">- main()</span><br><span>diff --git a/lib/python/asterisk/matcher.py b/lib/python/asterisk/matcher.py</span><br><span>index 3ab9c24..8ef575e 100644</span><br><span>--- a/lib/python/asterisk/matcher.py</span><br><span>+++ b/lib/python/asterisk/matcher.py</span><br><span>@@ -9,14 +9,18 @@</span><br><span> """</span><br><span> </span><br><span> import logging</span><br><span style="color: hsl(120, 100%, 40%);">+import sys</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-from test_suite_utils import all_match</span><br><span style="color: hsl(0, 100%, 40%);">-from pluggable_registry import PLUGGABLE_EVENT_REGISTRY,\</span><br><span style="color: hsl(0, 100%, 40%);">- PLUGGABLE_ACTION_REGISTRY</span><br><span style="color: hsl(120, 100%, 40%);">+from .test_runner import load_and_parse_module</span><br><span style="color: hsl(120, 100%, 40%);">+from .test_suite_utils import all_match</span><br><span style="color: hsl(120, 100%, 40%);">+from .pluggable_registry import PLUGGABLE_EVENT_REGISTRY</span><br><span> </span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+if sys.version_info[0] == 3:</span><br><span style="color: hsl(120, 100%, 40%);">+ unicode = str</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> </span><br><span> class ConditionError(Exception):</span><br><span> """Error raised a condition(s) fail"""</span><br><span>@@ -217,7 +221,6 @@</span><br><span> </span><br><span> matched.append(c)</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> if not matched:</span><br><span> return False</span><br><span> </span><br><span>@@ -315,13 +318,9 @@</span><br><span> </span><br><span> self.triggered_callback = triggered_callback</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- module_name, _, obj_type = config['type'].partition('.')</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- module = __import__(module_name, fromlist=[obj_type])</span><br><span style="color: hsl(0, 100%, 40%);">- if not module:</span><br><span style="color: hsl(0, 100%, 40%);">- raise Exception("Unable to import module '{0}'.".format(module_name))</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- obj = getattr(module, obj_type)</span><br><span style="color: hsl(120, 100%, 40%);">+ obj = load_and_parse_module(config['type'])</span><br><span style="color: hsl(120, 100%, 40%);">+ if not obj:</span><br><span style="color: hsl(120, 100%, 40%);">+ raise Exception("Unable to import module '{0}'.".format(config['type']))</span><br><span> </span><br><span> self.conditions = obj(config, test_object, self.__handle_match)</span><br><span> </span><br><span>diff --git a/lib/python/asterisk/matcher_listener.py b/lib/python/asterisk/matcher_listener.py</span><br><span>index d6b621d..cd2ca5a 100644</span><br><span>--- a/lib/python/asterisk/matcher_listener.py</span><br><span>+++ b/lib/python/asterisk/matcher_listener.py</span><br><span>@@ -13,7 +13,7 @@</span><br><span> from twisted.internet.protocol import DatagramProtocol</span><br><span> from twisted.internet import reactor</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-from matcher import PluggableConditions</span><br><span style="color: hsl(120, 100%, 40%);">+from .matcher import PluggableConditions</span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span> </span><br><span>diff --git a/lib/python/asterisk/opensslversion.py b/lib/python/asterisk/opensslversion.py</span><br><span>index a7377ea..3fa5cd5 100644</span><br><span>--- a/lib/python/asterisk/opensslversion.py</span><br><span>+++ b/lib/python/asterisk/opensslversion.py</span><br><span>@@ -9,11 +9,10 @@</span><br><span> """</span><br><span> </span><br><span> import sys</span><br><span style="color: hsl(0, 100%, 40%);">-import unittest</span><br><span> import re</span><br><span> sys.path.append("lib/python")</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-import test_suite_utils</span><br><span style="color: hsl(120, 100%, 40%);">+from . import test_suite_utils</span><br><span> </span><br><span> class OpenSSLVersion:</span><br><span> """An OpenSSL Version.</span><br><span>diff --git a/lib/python/asterisk/originate.py b/lib/python/asterisk/originate.py</span><br><span>index e6befb5..6c87a57 100644</span><br><span>--- a/lib/python/asterisk/originate.py</span><br><span>+++ b/lib/python/asterisk/originate.py</span><br><span>@@ -16,7 +16,7 @@</span><br><span> import json</span><br><span> import requests</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-import ari</span><br><span style="color: hsl(120, 100%, 40%);">+from . import ari</span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span> </span><br><span>diff --git a/lib/python/asterisk/pcap.py b/lib/python/asterisk/pcap.py</span><br><span>index d39574a..cb5fa5c 100644</span><br><span>--- a/lib/python/asterisk/pcap.py</span><br><span>+++ b/lib/python/asterisk/pcap.py</span><br><span>@@ -739,13 +739,14 @@</span><br><span> self.callbacks = {}</span><br><span> self.traces = {}</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- def process_packet(self, packet, (host, port)):</span><br><span style="color: hsl(120, 100%, 40%);">+ def process_packet(self, packet, addr):</span><br><span> """Store a known packet in our traces and call our callbacks</span><br><span> </span><br><span> Keyword Arguments:</span><br><span> packet A raw packet received from ... something.</span><br><span style="color: hsl(0, 100%, 40%);">- (host, port) Tuple of received host and port</span><br><span style="color: hsl(120, 100%, 40%);">+ addr Tuple of received host and port</span><br><span> """</span><br><span style="color: hsl(120, 100%, 40%);">+ (host, port) = addr</span><br><span> packet = self.packet_factory.interpret_packet(packet)</span><br><span> if packet is None:</span><br><span> return</span><br><span>@@ -812,13 +813,14 @@</span><br><span> self.rules = rules</span><br><span> self.cb = cb</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- def datagramReceived(self, data, (host, port)):</span><br><span style="color: hsl(120, 100%, 40%);">+ def datagramReceived(self, data, addr):</span><br><span> """Callback for when a datagram is received</span><br><span> </span><br><span> Keyword Arguments:</span><br><span> data The actual packet</span><br><span style="color: hsl(0, 100%, 40%);">- (host, port) Tuple of source host and port</span><br><span style="color: hsl(120, 100%, 40%);">+ addr Tuple of received host and port</span><br><span> """</span><br><span style="color: hsl(120, 100%, 40%);">+ (host, port) = addr</span><br><span> LOGGER.debug('Proxy received from {0}:{1}\n{2}'.format(</span><br><span> host, port, data))</span><br><span> </span><br><span>diff --git a/lib/python/asterisk/phones.py b/lib/python/asterisk/phones.py</span><br><span>old mode 100755</span><br><span>new mode 100644</span><br><span>index 6a96b38..4987da5</span><br><span>--- a/lib/python/asterisk/phones.py</span><br><span>+++ b/lib/python/asterisk/phones.py</span><br><span>@@ -1,4 +1,3 @@</span><br><span style="color: hsl(0, 100%, 40%);">-#!/usr/bin/env python</span><br><span> """Pluggable modules and classes to simulate phones.</span><br><span> </span><br><span> Copyright (C) 2015, Digium, Inc.</span><br><span>@@ -85,7 +84,7 @@</span><br><span> </span><br><span> def __setup_pjsua_acc_cb(self):</span><br><span> """Setup PJSUA account callbacks"""</span><br><span style="color: hsl(0, 100%, 40%);">- for name, phone_obj in self.__pjsua_phones.iteritems():</span><br><span style="color: hsl(120, 100%, 40%);">+ for name, phone_obj in self.__pjsua_phones.items():</span><br><span> acc_cb = AccCallback()</span><br><span> phone_obj.account.set_callback(acc_cb)</span><br><span> LOGGER.info("%s is ready to receive calls." % name)</span><br><span>@@ -106,7 +105,7 @@</span><br><span> if name:</span><br><span> return self.__pjsua_phones.get(name)</span><br><span> if account:</span><br><span style="color: hsl(0, 100%, 40%);">- for name, phone_obj in self.__pjsua_phones.iteritems():</span><br><span style="color: hsl(120, 100%, 40%);">+ for name, phone_obj in self.__pjsua_phones.items():</span><br><span> if account is phone_obj.account:</span><br><span> return phone_obj</span><br><span> </span><br><span>diff --git a/lib/python/asterisk/pjsua_mod.py b/lib/python/asterisk/pjsua_mod.py</span><br><span>index 63add6a..cdf3d18 100644</span><br><span>--- a/lib/python/asterisk/pjsua_mod.py</span><br><span>+++ b/lib/python/asterisk/pjsua_mod.py</span><br><span>@@ -17,6 +17,7 @@</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 .test_runner import load_and_parse_module</span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span> </span><br><span>@@ -147,7 +148,7 @@</span><br><span> self.lib.set_null_snd_dev()</span><br><span> self.__create_accounts()</span><br><span> self.lib.start()</span><br><span style="color: hsl(0, 100%, 40%);">- except pj.Error, exception:</span><br><span style="color: hsl(120, 100%, 40%);">+ except pj.Error as exception:</span><br><span> LOGGER.error("Exception: " + str(exception))</span><br><span> self.lib.destroy()</span><br><span> self.lib = None</span><br><span>@@ -306,6 +307,5 @@</span><br><span> </span><br><span> def do_callback(self):</span><br><span> """Call the configured callback module/method"""</span><br><span style="color: hsl(0, 100%, 40%);">- callback_module = __import__(self.callback_module)</span><br><span style="color: hsl(0, 100%, 40%);">- callback_method = getattr(callback_module, self.callback_method)</span><br><span style="color: hsl(120, 100%, 40%);">+ callback_method = load_and_parse_module(self.callback_module + '.' + self.callback_method)</span><br><span> callback_method(self.test_object, self.pj_accounts)</span><br><span>diff --git a/lib/python/asterisk/pluggable_modules.py b/lib/python/asterisk/pluggable_modules.py</span><br><span>old mode 100755</span><br><span>new mode 100644</span><br><span>index 344f908..dddb036</span><br><span>--- a/lib/python/asterisk/pluggable_modules.py</span><br><span>+++ b/lib/python/asterisk/pluggable_modules.py</span><br><span>@@ -1,4 +1,3 @@</span><br><span style="color: hsl(0, 100%, 40%);">-#!/usr/bin/env python</span><br><span> """Generic pluggable modules</span><br><span> </span><br><span> Copyright (C) 2012, Digium, Inc.</span><br><span>@@ -14,15 +13,15 @@</span><br><span> import re</span><br><span> </span><br><span> sys.path.append("lib/python")</span><br><span style="color: hsl(0, 100%, 40%);">-from ami import AMIEventInstance</span><br><span style="color: hsl(120, 100%, 40%);">+from .ami import AMIEventInstance</span><br><span> from twisted.internet import reactor</span><br><span> from starpy import fastagi</span><br><span style="color: hsl(0, 100%, 40%);">-from test_runner import load_and_parse_module</span><br><span style="color: hsl(0, 100%, 40%);">-from pluggable_registry import PLUGGABLE_ACTION_REGISTRY,\</span><br><span style="color: hsl(120, 100%, 40%);">+from .test_runner import load_and_parse_module</span><br><span style="color: hsl(120, 100%, 40%);">+from .pluggable_registry import PLUGGABLE_ACTION_REGISTRY,\</span><br><span> PLUGGABLE_EVENT_REGISTRY,\</span><br><span> PluggableRegistry</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-import matcher</span><br><span style="color: hsl(120, 100%, 40%);">+from . import matcher</span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span> </span><br><span>@@ -576,7 +575,7 @@</span><br><span> return</span><br><span> </span><br><span> current_trigger = config['trigger']['match']</span><br><span style="color: hsl(0, 100%, 40%);">- for key, value in current_trigger.iteritems():</span><br><span style="color: hsl(120, 100%, 40%);">+ for key, value in current_trigger.items():</span><br><span> if key.lower() not in event:</span><br><span> LOGGER.debug("Condition %s not in event, returning", key)</span><br><span> return</span><br><span>@@ -701,8 +700,7 @@</span><br><span> if self.commands:</span><br><span> return self.execute_command(agi, 0)</span><br><span> else:</span><br><span style="color: hsl(0, 100%, 40%);">- callback_module = __import__(self.callback_module)</span><br><span style="color: hsl(0, 100%, 40%);">- method = getattr(callback_module, self.callback_method)</span><br><span style="color: hsl(120, 100%, 40%);">+ method = load_and_parse_module(self.callback_module + '.' + self.callback_method)</span><br><span> method(self.test_object, agi)</span><br><span> </span><br><span> def on_command_failure(self, reason, agi, idx):</span><br><span>@@ -784,7 +782,7 @@</span><br><span> </span><br><span> def register_modules(config, registry):</span><br><span> """Register pluggable modules into the registry"""</span><br><span style="color: hsl(0, 100%, 40%);">- for key, local_class_path in config.iteritems():</span><br><span style="color: hsl(120, 100%, 40%);">+ for key, local_class_path in config.items():</span><br><span> local_class = load_and_parse_module(local_class_path)</span><br><span> if not local_class:</span><br><span> raise Exception("Unable to load %s for module key %s"</span><br><span>@@ -804,7 +802,7 @@</span><br><span> for e_a_set in config["mapping"]:</span><br><span> plug_set = {"events": [], "actions": []}</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- for plug_name, plug_config in e_a_set.iteritems():</span><br><span style="color: hsl(120, 100%, 40%);">+ for plug_name, plug_config in e_a_set.items():</span><br><span> self.parse_module_config(plug_set, plug_name, plug_config)</span><br><span> </span><br><span> if 0 == len(plug_set["events"]):</span><br><span>@@ -923,8 +921,7 @@</span><br><span> </span><br><span> def run(self, triggered_by, source, extra):</span><br><span> """Call the callback."""</span><br><span style="color: hsl(0, 100%, 40%);">- module = __import__(self.module)</span><br><span style="color: hsl(0, 100%, 40%);">- method = getattr(module, self.method)</span><br><span style="color: hsl(120, 100%, 40%);">+ method = load_and_parse_module(self.module + '.' + self.method)</span><br><span> self.test_object.set_passed(method(self.test_object, triggered_by,</span><br><span> source, extra))</span><br><span> PLUGGABLE_ACTION_REGISTRY.register("callback", CallbackActionModule)</span><br><span>@@ -960,12 +957,12 @@</span><br><span> def __init__(self, test_object, config):</span><br><span> """Setup the test start observer"""</span><br><span> self.test_object = test_object</span><br><span style="color: hsl(0, 100%, 40%);">- self.module = __import__("phones")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.module = "phones"</span><br><span> self.method = config["action"]</span><br><span> self.config = config</span><br><span> </span><br><span> def run(self, triggered_by, source, extra):</span><br><span> """Instruct phone to perform action"""</span><br><span style="color: hsl(0, 100%, 40%);">- method = getattr(self.module, self.method)</span><br><span style="color: hsl(120, 100%, 40%);">+ method = load_and_parse_module(self.module + "." + self.method)</span><br><span> method(self.test_object, triggered_by, source, extra, self.config)</span><br><span> PLUGGABLE_ACTION_REGISTRY.register("pjsua_phone", PjsuaPhoneActionModule)</span><br><span>diff --git a/lib/python/asterisk/pluggable_registry.py b/lib/python/asterisk/pluggable_registry.py</span><br><span>old mode 100755</span><br><span>new mode 100644</span><br><span>index 8169795..9a50a26</span><br><span>--- a/lib/python/asterisk/pluggable_registry.py</span><br><span>+++ b/lib/python/asterisk/pluggable_registry.py</span><br><span>@@ -1,4 +1,3 @@</span><br><span style="color: hsl(0, 100%, 40%);">-#!/usr/bin/env python</span><br><span> """Pluggable module registries</span><br><span> </span><br><span> Copyright (C) 2014, Digium, Inc.</span><br><span>diff --git a/lib/python/asterisk/realtime_converter.py b/lib/python/asterisk/realtime_converter.py</span><br><span>index 3f50b5f..95ae579 100644</span><br><span>--- a/lib/python/asterisk/realtime_converter.py</span><br><span>+++ b/lib/python/asterisk/realtime_converter.py</span><br><span>@@ -9,7 +9,7 @@</span><br><span> import os</span><br><span> from sqlalchemy import create_engine, MetaData, Table</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-import astconfigparser</span><br><span style="color: hsl(120, 100%, 40%);">+from . import astconfigparser</span><br><span> import logging</span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span>@@ -83,8 +83,8 @@</span><br><span> self.filename = filename</span><br><span> self.sections = sections</span><br><span> # All affected database tables in list form. Used for convenience</span><br><span style="color: hsl(0, 100%, 40%);">- self.tables = [table for section in sections.itervalues() for table in</span><br><span style="color: hsl(0, 100%, 40%);">- section.itervalues()]</span><br><span style="color: hsl(120, 100%, 40%);">+ self.tables = [table for section in sections.values() for table in</span><br><span style="color: hsl(120, 100%, 40%);">+ section.values()]</span><br><span> self.sorcery = None</span><br><span> self.extconfig = None</span><br><span> </span><br><span>@@ -111,9 +111,9 @@</span><br><span> config_dir: The directory where Asterisk configuration can be found</span><br><span> """</span><br><span> with open(self.sorcery.file, 'a') as sorcery:</span><br><span style="color: hsl(0, 100%, 40%);">- for section, items in self.sections.iteritems():</span><br><span style="color: hsl(120, 100%, 40%);">+ for section, items in self.sections.items():</span><br><span> sorcery.write('[{0}]\n'.format(section))</span><br><span style="color: hsl(0, 100%, 40%);">- for obj, table in items.iteritems():</span><br><span style="color: hsl(120, 100%, 40%);">+ for obj, table in items.items():</span><br><span> sorcery.write('{0} = realtime,{1}\n'.format(obj, table))</span><br><span> </span><br><span> def write_extconfig_conf(self):</span><br><span>@@ -141,7 +141,7 @@</span><br><span> """</span><br><span> conf = astconfigparser.MultiOrderedConfigParser()</span><br><span> conf.read(os.path.join(config_dir, self.filename))</span><br><span style="color: hsl(0, 100%, 40%);">- for title, sections in conf.sections().iteritems():</span><br><span style="color: hsl(120, 100%, 40%);">+ for title, sections in conf.sections().items():</span><br><span> LOGGER.info("Inspecting objects with title {0}".format(title))</span><br><span> for section in sections:</span><br><span> obj_type = section.get('type')[0]</span><br><span>@@ -165,7 +165,7 @@</span><br><span> Keyword Arguments:</span><br><span> obj_type: The object type to find the section for</span><br><span> """</span><br><span style="color: hsl(0, 100%, 40%);">- for section, contents in self.sections.iteritems():</span><br><span style="color: hsl(120, 100%, 40%);">+ for section, contents in self.sections.items():</span><br><span> if obj_type in contents:</span><br><span> return section</span><br><span> </span><br><span>diff --git a/lib/python/asterisk/realtime_odbc_module.py b/lib/python/asterisk/realtime_odbc_module.py</span><br><span>index 3653553..bbd8a8e 100644</span><br><span>--- a/lib/python/asterisk/realtime_odbc_module.py</span><br><span>+++ b/lib/python/asterisk/realtime_odbc_module.py</span><br><span>@@ -53,7 +53,7 @@</span><br><span> self.res_odbc = {}</span><br><span> </span><br><span> # generate configuration for each dsn</span><br><span style="color: hsl(0, 100%, 40%);">- for dsn, config in module_config.iteritems():</span><br><span style="color: hsl(120, 100%, 40%);">+ for dsn, config in module_config.items():</span><br><span> self._configure(dsn, config)</span><br><span> </span><br><span> # set the odbc and conf files</span><br><span>@@ -109,7 +109,7 @@</span><br><span> with open(filepath, 'w') as filehandle:</span><br><span> for section in contents:</span><br><span> filehandle.write('[' + section + ']\n')</span><br><span style="color: hsl(0, 100%, 40%);">- for name, value in contents[section].iteritems():</span><br><span style="color: hsl(120, 100%, 40%);">+ for name, value in contents[section].items():</span><br><span> filehandle.write(name + '=' + value + '\n')</span><br><span> </span><br><span> def _read_ini_file(self, filepath):</span><br><span>diff --git a/lib/python/asterisk/realtime_test_module.py b/lib/python/asterisk/realtime_test_module.py</span><br><span>index fd38aa9..da97422 100644</span><br><span>--- a/lib/python/asterisk/realtime_test_module.py</span><br><span>+++ b/lib/python/asterisk/realtime_test_module.py</span><br><span>@@ -91,7 +91,7 @@</span><br><span> </span><br><span> return [row for row in table</span><br><span> if all(key in row and re.match(value, row[key])</span><br><span style="color: hsl(0, 100%, 40%);">- for key, value in where.iteritems())]</span><br><span style="color: hsl(120, 100%, 40%);">+ for key, value in where.items())]</span><br><span> </span><br><span> def retrieve_rows(self, table_name, where):</span><br><span> """Retrieve multiple rows from a table.</span><br><span>@@ -239,7 +239,7 @@</span><br><span> since we could use a dict comprehension.</span><br><span> """</span><br><span> filtered_args = {}</span><br><span style="color: hsl(0, 100%, 40%);">- for key, values in args.iteritems():</span><br><span style="color: hsl(120, 100%, 40%);">+ for key, values in args.items():</span><br><span> if " LIKE" in key:</span><br><span> # Strip away " LIKE" and % from values</span><br><span> filtered_args[key[:-5]] = [val.replace('%', '.*')</span><br><span>@@ -250,7 +250,7 @@</span><br><span> LOGGER.debug('filtered args is %s' % filtered_args)</span><br><span> </span><br><span> return dict((key, values[0] if values else '.*') for key, values in</span><br><span style="color: hsl(0, 100%, 40%);">- filtered_args.iteritems())</span><br><span style="color: hsl(120, 100%, 40%);">+ filtered_args.items())</span><br><span> </span><br><span> def encode_row(self, row):</span><br><span> """Encode a retrieved row for an HTTP response.</span><br><span>@@ -261,7 +261,7 @@</span><br><span> Example output: 'foo=cat&bar=dog&baz=donkey'</span><br><span> """</span><br><span> string = '&'.join(['{0}={1}'.format(cgi.escape(key), cgi.escape(val))</span><br><span style="color: hsl(0, 100%, 40%);">- for key, val in row.iteritems()])</span><br><span style="color: hsl(120, 100%, 40%);">+ for key, val in row.items()])</span><br><span> LOGGER.debug("Returning response %s" % string)</span><br><span> return string</span><br><span> </span><br><span>@@ -481,7 +481,7 @@</span><br><span> if not data:</span><br><span> return</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- for table_name, rows in data.iteritems():</span><br><span style="color: hsl(120, 100%, 40%);">+ for table_name, rows in data.items():</span><br><span> self.rt_data.add_rows(table_name, rows)</span><br><span> </span><br><span> def setup_http(self):</span><br><span>diff --git a/lib/python/asterisk/self_test/harness_shared.py b/lib/python/asterisk/self_test/harness_shared.py</span><br><span>new file mode 100644</span><br><span>index 0000000..91449ac</span><br><span>--- /dev/null</span><br><span>+++ b/lib/python/asterisk/self_test/harness_shared.py</span><br><span>@@ -0,0 +1,54 @@</span><br><span style="color: hsl(120, 100%, 40%);">+"""Unit test harness</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+This module provides the entry-point for tests</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Copyright (C) 2018, CFWare, LLC.</span><br><span style="color: hsl(120, 100%, 40%);">+Corey Farrell <git@cfware.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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+import logging</span><br><span style="color: hsl(120, 100%, 40%);">+import os</span><br><span style="color: hsl(120, 100%, 40%);">+import sys</span><br><span style="color: hsl(120, 100%, 40%);">+from twisted.internet import defer</span><br><span style="color: hsl(120, 100%, 40%);">+import unittest</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+# Add directory where the modules to test can be found</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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+def ReadTestFile(filename, basepath="lib/python/asterisk/self_test"):</span><br><span style="color: hsl(120, 100%, 40%);">+ fd = open(os.path.join(basepath, filename), "r")</span><br><span style="color: hsl(120, 100%, 40%);">+ output = fd.read()</span><br><span style="color: hsl(120, 100%, 40%);">+ fd.close()</span><br><span style="color: hsl(120, 100%, 40%);">+ return output</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 AstMockOutput(object):</span><br><span style="color: hsl(120, 100%, 40%);">+ """mock cli output base class"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def __init__(self, host="127.0.0.1"):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Constructor"""</span><br><span style="color: hsl(120, 100%, 40%);">+ self.host = host</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def MockDeferFile(self, filename):</span><br><span style="color: hsl(120, 100%, 40%);">+ return self.MockDefer(ReadTestFile(filename))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def MockDefer(self, output):</span><br><span style="color: hsl(120, 100%, 40%);">+ """use real defer to mock deferred output"""</span><br><span style="color: hsl(120, 100%, 40%);">+ self.output = output</span><br><span style="color: hsl(120, 100%, 40%);">+ deferred = defer.Deferred()</span><br><span style="color: hsl(120, 100%, 40%);">+ deferred.callback(self)</span><br><span style="color: hsl(120, 100%, 40%);">+ return deferred</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%);">+def main():</span><br><span style="color: hsl(120, 100%, 40%);">+ """Run the unit tests"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ logging.basicConfig()</span><br><span style="color: hsl(120, 100%, 40%);">+ unittest.main()</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%);">+__all__ = ["main", "AstMockOutput", "ReadTestFile"]</span><br><span>diff --git a/lib/python/asterisk/self_test/locks-backtrace.txt b/lib/python/asterisk/self_test/locks-backtrace.txt</span><br><span>new file mode 100644</span><br><span>index 0000000..0de89a4</span><br><span>--- /dev/null</span><br><span>+++ b/lib/python/asterisk/self_test/locks-backtrace.txt</span><br><span>@@ -0,0 +1,20 @@</span><br><span style="color: hsl(120, 100%, 40%);">+=== ---> Lock #1 (astobj2.c): MUTEX 657 internal_ao2_callback c 0x2aaaac491f50 (1)</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk(ast_bt_get_addresses+0x1a) [0x4e9679]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk(__ast_pthread_mutex_lock+0xf6) [0x4e22d9]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk(__ao2_lock+0x53) [0x4456fc]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk [0x4464be]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk(__ao2_callback+0x59) [0x446a4e]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk(__ao2_find+0x2b) [0x446ba7]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk [0x46d3a7]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk(ast_channel_get_by_name+0x24) [0x46d3e3]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/lib/asterisk/modules/func_channel.so [0x2aaabfba2468]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk(ast_func_write+0x16a) [0x50aacd]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk(pbx_builtin_setvar_helper+0x10e) [0x51fff4]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/lib/asterisk/modules/chan_sip.so [0x2aaabe422d09]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/lib/asterisk/modules/chan_sip.so [0x2aaabe4240a0]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/lib/asterisk/modules/chan_sip.so [0x2aaabe423cf1]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk(ast_io_wait+0x1ba) [0x4dc2e4]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/lib/asterisk/modules/chan_sip.so [0x2aaabe425722]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk [0x5661c6]</span><br><span style="color: hsl(120, 100%, 40%);">+/lib64/libpthread.so.0 [0x3d1d80673d]</span><br><span style="color: hsl(120, 100%, 40%);">+/lib64/libc.so.6(clone+0x6d) [0x3d1ccd44bd]</span><br><span>diff --git a/lib/python/asterisk/self_test/locks-fail.txt b/lib/python/asterisk/self_test/locks-fail.txt</span><br><span>new file mode 100644</span><br><span>index 0000000..fb50ca8</span><br><span>--- /dev/null</span><br><span>+++ b/lib/python/asterisk/self_test/locks-fail.txt</span><br><span>@@ -0,0 +1,52 @@</span><br><span style="color: hsl(120, 100%, 40%);">+=======================================================================</span><br><span style="color: hsl(120, 100%, 40%);">+=== Currently Held Locks ==============================================</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%);">+=== <pending> <lock#> (<file>): <lock type> <line num> <function> <lock name> <lock addr> (times locked)</span><br><span style="color: hsl(120, 100%, 40%);">+===</span><br><span style="color: hsl(120, 100%, 40%);">+=== Thread ID: 0x402c6940 (do_monitor started at [25114] chan_sip.c restart_monitor())</span><br><span style="color: hsl(120, 100%, 40%);">+=== ---> Lock #0 (chan_sip.c): MUTEX 24629 handle_request_do &netlock 0x2aaabe671a40 (1)</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk(ast_bt_get_addresses+0x1a) [0x4e9679]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk(__ast_pthread_mutex_lock+0xf6) [0x4e22d9]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/lib/asterisk/modules/chan_sip.so [0x2aaabe423ee8]</span><br><span style="color: hsl(120, 100%, 40%);">+=== ---> Lock #1 (chan_sip.c): MUTEX 24629 handle_request_do &netlock 0x2aaabe671a40 (1)</span><br><span style="color: hsl(120, 100%, 40%);">+=== --- ---> Locked Here: channel.c line 4304 (ast_indicate_data)</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%);">+=== Thread ID: 0x449ec940 (netconsole started at [ 1351] asterisk.c listener())</span><br><span style="color: hsl(120, 100%, 40%);">+=== ---> Waiting for Lock #0 (astobj2.c): MUTEX 842 internal_ao2_iterator_next a->c 0x2aaaac491f50 (1)</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk(ast_bt_get_addresses+0x1a) [0x4e9679]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk(__ast_pthread_mutex_lock+0xf6) [0x4e22d9]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk(__ao2_lock+0x53) [0x4456fc]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk [0x446cec]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk(__ao2_iterator_next+0x29) [0x447134]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk(ast_channel_iterator_next+0x19) [0x46cf7d]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk [0x489e43]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk(ast_cli_command_full+0x222) [0x48eec4]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk(ast_cli_command_multiple_full+0x92) [0x48f035]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk [0x43d129]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk [0x5661c6]</span><br><span style="color: hsl(120, 100%, 40%);">+/lib64/libpthread.so.0 [0x3d1d80673d]</span><br><span style="color: hsl(120, 100%, 40%);">+/lib64/libc.so.6(clone+0x6d) [0x3d1ccd44bd]</span><br><span style="color: hsl(120, 100%, 40%);">+=== --- ---> Locked Here: astobj2.c line 657 (internal_ao2_callback)</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%);">+=== Thread ID: 0x44a68940 (netconsole started at [ 1351] asterisk.c listener())</span><br><span style="color: hsl(120, 100%, 40%);">+=== ---> Waiting for Lock #0 (astobj2.c): MUTEX 842 internal_ao2_iterator_next a->c 0x2aaaac491f50 (1)</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk(ast_bt_get_addresses+0x1a) [0x4e9679]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk(__ast_pthread_mutex_lock+0xf6) [0x4e22d9]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk(__ao2_lock+0x53) [0x4456fc]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk [0x446cec]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk(__ao2_iterator_next+0x29) [0x447134]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk(ast_channel_iterator_next+0x19) [0x46cf7d]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk [0x489e43]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk(ast_cli_command_full+0x222) [0x48eec4]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk(ast_cli_command_multiple_full+0x92) [0x48f035]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk [0x43d129]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk [0x5661c6]</span><br><span style="color: hsl(120, 100%, 40%);">+/lib64/libpthread.so.0 [0x3d1d80673d]</span><br><span style="color: hsl(120, 100%, 40%);">+/lib64/libc.so.6(clone+0x6d) [0x3d1ccd44bd]</span><br><span style="color: hsl(120, 100%, 40%);">+=== --- ---> Locked Here: astobj2.c line 657 (internal_ao2_callback)</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%);">+=======================================================================</span><br><span>diff --git a/lib/python/asterisk/self_test/locks-large-multiple-object.txt b/lib/python/asterisk/self_test/locks-large-multiple-object.txt</span><br><span>new file mode 100644</span><br><span>index 0000000..ea657b6</span><br><span>--- /dev/null</span><br><span>+++ b/lib/python/asterisk/self_test/locks-large-multiple-object.txt</span><br><span>@@ -0,0 +1,16 @@</span><br><span style="color: hsl(120, 100%, 40%);">+=== Thread ID: 0x449ec940 (netconsole started at [ 1351] asterisk.c listener())</span><br><span style="color: hsl(120, 100%, 40%);">+=== ---> Waiting for Lock #0 (astobj2.c): MUTEX 842 internal_ao2_iterator_next a->c 0x2aaaac491f50 (1)</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk(ast_bt_get_addresses+0x1a) [0x4e9679]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk(__ast_pthread_mutex_lock+0xf6) [0x4e22d9]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk(__ao2_lock+0x53) [0x4456fc]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk [0x446cec]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk(__ao2_iterator_next+0x29) [0x447134]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk(ast_channel_iterator_next+0x19) [0x46cf7d]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk [0x489e43]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk(ast_cli_command_full+0x222) [0x48eec4]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk(ast_cli_command_multiple_full+0x92) [0x48f035]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk [0x43d129]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk [0x5661c6]</span><br><span style="color: hsl(120, 100%, 40%);">+/lib64/libpthread.so.0 [0x3d1d80673d]</span><br><span style="color: hsl(120, 100%, 40%);">+/lib64/libc.so.6(clone+0x6d) [0x3d1ccd44bd]</span><br><span style="color: hsl(120, 100%, 40%);">+=== --- ---> Locked Here: astobj2.c line 657 (internal_ao2_callback)</span><br><span>diff --git a/lib/python/asterisk/self_test/locks-multiple-objects-no-backtrace.txt b/lib/python/asterisk/self_test/locks-multiple-objects-no-backtrace.txt</span><br><span>new file mode 100644</span><br><span>index 0000000..3ed0ca5</span><br><span>--- /dev/null</span><br><span>+++ b/lib/python/asterisk/self_test/locks-multiple-objects-no-backtrace.txt</span><br><span>@@ -0,0 +1,5 @@</span><br><span style="color: hsl(120, 100%, 40%);">+=== Thread ID: 0x402c6940 (do_monitor started at [25114] chan_sip.c restart_monitor())</span><br><span style="color: hsl(120, 100%, 40%);">+=== ---> Lock #0 (chan_sip.c): MUTEX 24629 handle_request_do &netlock 0x2aaabe671a40 (1)</span><br><span style="color: hsl(120, 100%, 40%);">+=== ---> Lock #1 (astobj2.c): MUTEX 657 internal_ao2_callback c 0x2aaaac491f50 (1)</span><br><span style="color: hsl(120, 100%, 40%);">+=== ---> Waiting for Lock #2 (channel.c): MUTEX 1691 ast_channel_cmp_cb chan 0x2aaaacd3a4e0 (1)</span><br><span style="color: hsl(120, 100%, 40%);">+=== --- ---> Locked Here: channel.c line 4304 (ast_indicate_data)</span><br><span>diff --git a/lib/python/asterisk/self_test/locks-pass.txt b/lib/python/asterisk/self_test/locks-pass.txt</span><br><span>new file mode 100644</span><br><span>index 0000000..bbb3b92</span><br><span>--- /dev/null</span><br><span>+++ b/lib/python/asterisk/self_test/locks-pass.txt</span><br><span>@@ -0,0 +1,8 @@</span><br><span style="color: hsl(120, 100%, 40%);">+=======================================================================</span><br><span style="color: hsl(120, 100%, 40%);">+=== Currently Held Locks ==============================================</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%);">+=== <pending> <lock#> (<file>): <lock type> <line num> <function> <lock name> <lock addr> (times locked)</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%);">+=======================================================================</span><br><span>diff --git a/lib/python/asterisk/self_test/locks-single-object-no-held-info.txt b/lib/python/asterisk/self_test/locks-single-object-no-held-info.txt</span><br><span>new file mode 100644</span><br><span>index 0000000..e1bf47a</span><br><span>--- /dev/null</span><br><span>+++ b/lib/python/asterisk/self_test/locks-single-object-no-held-info.txt</span><br><span>@@ -0,0 +1,11 @@</span><br><span style="color: hsl(120, 100%, 40%);">+=== Thread ID: 0x7f668c142700 (do_monitor started at [25915] chan_sip.c restart_monitor())</span><br><span style="color: hsl(120, 100%, 40%);">+=== ---> Lock #0 (chan_sip.c): MUTEX 25390 handle_request_do &netlock 0x7f6652193900 (1)</span><br><span style="color: hsl(120, 100%, 40%);">+main/logger.c:1302 ast_bt_get_addresses() (0x505e53+1D)</span><br><span style="color: hsl(120, 100%, 40%);">+main/lock.c:193 __ast_pthread_mutex_lock() (0x4fe55c+D9)</span><br><span style="color: hsl(120, 100%, 40%);">+channels/chan_sip.c:25393 handle_request_do()</span><br><span style="color: hsl(120, 100%, 40%);">+channels/chan_sip.c:25352 sipsock_read()</span><br><span style="color: hsl(120, 100%, 40%);">+main/io.c:288 ast_io_wait() (0x4f8228+19C)</span><br><span style="color: hsl(120, 100%, 40%);">+channels/chan_sip.c:25882 do_monitor()</span><br><span style="color: hsl(120, 100%, 40%);">+main/utils.c:1010 dummy_start()</span><br><span style="color: hsl(120, 100%, 40%);">+libpthread.so.0 <unknown>()</span><br><span style="color: hsl(120, 100%, 40%);">+libc.so.6 clone() (0x31be0e0bc0+6D)</span><br><span>diff --git a/lib/python/asterisk/self_test/locks-single-object.txt b/lib/python/asterisk/self_test/locks-single-object.txt</span><br><span>new file mode 100644</span><br><span>index 0000000..db356ed</span><br><span>--- /dev/null</span><br><span>+++ b/lib/python/asterisk/self_test/locks-single-object.txt</span><br><span>@@ -0,0 +1,6 @@</span><br><span style="color: hsl(120, 100%, 40%);">+=== Thread ID: 0x402c6940 (do_monitor started at [25114] chan_sip.c restart_monitor())</span><br><span style="color: hsl(120, 100%, 40%);">+=== ---> Lock #0 (chan_sip.c): MUTEX 24629 handle_request_do &netlock 0x2aaabe671a40 (1)</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk(ast_bt_get_addresses+0x1a) [0x4e9679]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/sbin/asterisk(__ast_pthread_mutex_lock+0xf6) [0x4e22d9]</span><br><span style="color: hsl(120, 100%, 40%);">+/usr/local/asterisk-1.8.6.0/lib/asterisk/modules/chan_sip.so [0x2aaabe423ee8]</span><br><span style="color: hsl(120, 100%, 40%);">+=== --- ---> Locked Here: channel.c line 4304 (ast_indicate_data)</span><br><span>diff --git a/lib/python/asterisk/self_test/test_buildoptions.py b/lib/python/asterisk/self_test/test_buildoptions.py</span><br><span>new file mode 100755</span><br><span>index 0000000..1f4ca77</span><br><span>--- /dev/null</span><br><span>+++ b/lib/python/asterisk/self_test/test_buildoptions.py</span><br><span>@@ -0,0 +1,26 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#!/usr/bin/env python</span><br><span style="color: hsl(120, 100%, 40%);">+"""Asterisk Build Options Handling Unit Test</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Copyright (C) 2011-2012, Digium, Inc.</span><br><span style="color: hsl(120, 100%, 40%);">+Matt Jordan <mjordan@digium.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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+from harness_shared import main</span><br><span style="color: hsl(120, 100%, 40%);">+import unittest</span><br><span style="color: hsl(120, 100%, 40%);">+from asterisk.buildoptions import AsteriskBuildOptions</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 AsteriskBuildOptionsTests(unittest.TestCase):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Unit tests for AsteriskBuildOptions"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_1(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Test the defaults paths"""</span><br><span style="color: hsl(120, 100%, 40%);">+ build_options = AsteriskBuildOptions()</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(build_options)</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%);">+if __name__ == "__main__":</span><br><span style="color: hsl(120, 100%, 40%);">+ main()</span><br><span>diff --git a/lib/python/asterisk/self_test/test_cdr.py b/lib/python/asterisk/self_test/test_cdr.py</span><br><span>new file mode 100755</span><br><span>index 0000000..251530b</span><br><span>--- /dev/null</span><br><span>+++ b/lib/python/asterisk/self_test/test_cdr.py</span><br><span>@@ -0,0 +1,44 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#!/usr/bin/env python</span><br><span style="color: hsl(120, 100%, 40%);">+"""Asterisk call detail record unit tests</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+This module implements an Asterisk CDR parser.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Copyright (C) 2010, Digium, Inc.</span><br><span style="color: hsl(120, 100%, 40%);">+Terry Wilson<twilson@digium.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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+from harness_shared import main</span><br><span style="color: hsl(120, 100%, 40%);">+import unittest</span><br><span style="color: hsl(120, 100%, 40%);">+from asterisk.cdr import AsteriskCSVCDR, AsteriskCSVCDRLine</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 AsteriskCSVCDRTests(unittest.TestCase):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Unit tests for AsteriskCSVCDR"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_cdr(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Test the self_test/Master.csv record"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ cdr = AsteriskCSVCDR("lib/python/asterisk/self_test/Master.csv")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(len(cdr), 2)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(</span><br><span style="color: hsl(120, 100%, 40%);">+ AsteriskCSVCDRLine(duration=7, lastapp="hangup").match(</span><br><span style="color: hsl(120, 100%, 40%);">+ cdr[0],</span><br><span style="color: hsl(120, 100%, 40%);">+ exact=(True, True)))</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(cdr[0].match(</span><br><span style="color: hsl(120, 100%, 40%);">+ AsteriskCSVCDRLine(duration=7, lastapp="hangup"),</span><br><span style="color: hsl(120, 100%, 40%);">+ exact=(True, True)))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertFalse(cdr[1].match(cdr[0], silent=True, exact=(True, True)))</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertFalse(cdr[0].match(cdr[1], silent=True, exact=(True, True)))</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(cdr[0].billsec, "7")</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(cdr.match(cdr))</span><br><span style="color: hsl(120, 100%, 40%);">+ cdr2 = AsteriskCSVCDR("lib/python/asterisk/self_test/Master2.csv")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertFalse(cdr.match(cdr2))</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%);">+if __name__ == '__main__':</span><br><span style="color: hsl(120, 100%, 40%);">+ main()</span><br><span>diff --git a/lib/python/asterisk/self_test/test_cel.py b/lib/python/asterisk/self_test/test_cel.py</span><br><span>new file mode 100755</span><br><span>index 0000000..3ea8aa9</span><br><span>--- /dev/null</span><br><span>+++ b/lib/python/asterisk/self_test/test_cel.py</span><br><span>@@ -0,0 +1,47 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#!/usr/bin/env python</span><br><span style="color: hsl(120, 100%, 40%);">+"""Asterisk call detail record unit tests</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+This module implements an Asterisk CDR parser.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Copyright (C) 2010, Digium, Inc.</span><br><span style="color: hsl(120, 100%, 40%);">+Terry Wilson<twilson@digium.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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+from harness_shared import main</span><br><span style="color: hsl(120, 100%, 40%);">+import unittest</span><br><span style="color: hsl(120, 100%, 40%);">+from asterisk.cel import AsteriskCSVCEL, AsteriskCSVCELLine</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 AsteriskCSVCELTests(unittest.TestCase):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Unit tests for AsteriskCSVCEL"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_cel(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Test CEL using self_test/CELMaster1.csv"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ cel = AsteriskCSVCEL("lib/python/asterisk/self_test/CELMaster1.csv")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(len(cel), 16)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(AsteriskCSVCELLine(</span><br><span style="color: hsl(120, 100%, 40%);">+ eventtype="LINKEDID_END",</span><br><span style="color: hsl(120, 100%, 40%);">+ channel="TinCan/string").match(cel[-1],</span><br><span style="color: hsl(120, 100%, 40%);">+ silent=True,</span><br><span style="color: hsl(120, 100%, 40%);">+ exact=(True, True)))</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(cel[-1].match(</span><br><span style="color: hsl(120, 100%, 40%);">+ AsteriskCSVCELLine(eventtype="LINKEDID_END",</span><br><span style="color: hsl(120, 100%, 40%);">+ channel="TinCan/string"),</span><br><span style="color: hsl(120, 100%, 40%);">+ silent=True,</span><br><span style="color: hsl(120, 100%, 40%);">+ exact=(True, True)))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertFalse(cel[1].match(cel[0], silent=True, exact=(True, True)))</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertFalse(cel[0].match(cel[1], silent=True, exact=(True, True)))</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(cel[-1].channel, "TinCan/string")</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(cel.match(cel))</span><br><span style="color: hsl(120, 100%, 40%);">+ cel2 = AsteriskCSVCEL("lib/python/asterisk/self_test/CELMaster2.csv")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertFalse(cel.match(cel2))</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%);">+if __name__ == '__main__':</span><br><span style="color: hsl(120, 100%, 40%);">+ main()</span><br><span>diff --git a/lib/python/asterisk/self_test/test_channel_test_condition.py b/lib/python/asterisk/self_test/test_channel_test_condition.py</span><br><span>new file mode 100755</span><br><span>index 0000000..e32d883</span><br><span>--- /dev/null</span><br><span>+++ b/lib/python/asterisk/self_test/test_channel_test_condition.py</span><br><span>@@ -0,0 +1,144 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#!/usr/bin/env python</span><br><span style="color: hsl(120, 100%, 40%);">+"""Tests for test condition for channels</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Copyright (C) 2011-2012, Digium, Inc.</span><br><span style="color: hsl(120, 100%, 40%);">+Matt Jordan <mjordan@digium.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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+from harness_shared import AstMockOutput, main</span><br><span style="color: hsl(120, 100%, 40%);">+import unittest</span><br><span style="color: hsl(120, 100%, 40%);">+from asterisk.channel_test_condition import ChannelTestCondition</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 AstMockObjectInactive(AstMockOutput):</span><br><span style="color: hsl(120, 100%, 40%);">+ """mock cli output showing no active channels"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def cli_exec(self, command):</span><br><span style="color: hsl(120, 100%, 40%);">+ """presume command is core show channels and generate output"""</span><br><span style="color: hsl(120, 100%, 40%);">+ output = ""</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "Channel Location State Application(Data)\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "0 active channels\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "0 active calls\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "2 calls processed\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "Asterisk ending (0).\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ return self.MockDefer(output)</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 AstMockObjectSingle(AstMockOutput):</span><br><span style="color: hsl(120, 100%, 40%);">+ """mock cli output showing single active channel"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def cli_exec(self, command):</span><br><span style="color: hsl(120, 100%, 40%);">+ """presume command is core show channels and generate output"""</span><br><span style="color: hsl(120, 100%, 40%);">+ output = ""</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "Channel Location State Application(Data)\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "Local/123@default-00 (None) Down ()\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "1 active channels\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "0 active calls\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "2 calls processed\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "Asterisk ending (0).\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ return self.MockDefer(output)</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 AstMockObjectMultiple(AstMockOutput):</span><br><span style="color: hsl(120, 100%, 40%);">+ """mock cli output showing multiple active channels"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def cli_exec(self, command):</span><br><span style="color: hsl(120, 100%, 40%);">+ """presume command is core show channels and generate output"""</span><br><span style="color: hsl(120, 100%, 40%);">+ output = ""</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "Channel Location State Application(Data)\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "PJSIP/123@default-00 (None) Down ()\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "Local/123@default-00 (None) Down ()\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "SIP/alice@default-00 (None) Down ()\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "3 active channels\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "0 active calls\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "2 calls processed\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "Asterisk ending (0).\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ return self.MockDefer(output)</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 AstMockObjectLeaked(AstMockOutput):</span><br><span style="color: hsl(120, 100%, 40%);">+ """mock cli output showing leaked channel"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def cli_exec(self, command):</span><br><span style="color: hsl(120, 100%, 40%);">+ """presume command is core show channels and generate output"""</span><br><span style="color: hsl(120, 100%, 40%);">+ output = ""</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "Channel Location State Application(Data)\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "Local/123@default-00 (None) Down ()\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "0 active channels\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "0 active calls\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "2 calls processed\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "Asterisk ending (0).\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ return self.MockDefer(output)</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 TestConfig(object):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Fake TestConfig object for unittest"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def __init__(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ self.class_type_name = "bogus"</span><br><span style="color: hsl(120, 100%, 40%);">+ self.config = {}</span><br><span style="color: hsl(120, 100%, 40%);">+ self.enabled = True</span><br><span style="color: hsl(120, 100%, 40%);">+ self.pass_expected = True</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 ChannelTestConditionUnitTest(unittest.TestCase):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Unit Tests for ChannelTestCondition"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_evaluate_inactive(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ """test inactive channel condition"""</span><br><span style="color: hsl(120, 100%, 40%);">+ obj = ChannelTestCondition(TestConfig())</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.register_asterisk_instance(AstMockObjectInactive())</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.evaluate()</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.get_status(), 'Passed')</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_evaluate_multiple_fail(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ """test multiple channel condition"""</span><br><span style="color: hsl(120, 100%, 40%);">+ obj = ChannelTestCondition(TestConfig())</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.register_asterisk_instance(AstMockObjectMultiple())</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.evaluate()</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.get_status(), 'Failed')</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_evaluate_multiple_fail2(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ """test multiple channel condition"""</span><br><span style="color: hsl(120, 100%, 40%);">+ obj = ChannelTestCondition(TestConfig())</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.allowed_channels = 2</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.register_asterisk_instance(AstMockObjectMultiple())</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.evaluate()</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.get_status(), 'Failed')</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_evaluate_multiple_pass(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ """test multiple channel condition"""</span><br><span style="color: hsl(120, 100%, 40%);">+ obj = ChannelTestCondition(TestConfig())</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.allowed_channels = 3</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.register_asterisk_instance(AstMockObjectMultiple())</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.evaluate()</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.get_status(), 'Passed')</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_evaluate_single_fail(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ """test single channel condition"""</span><br><span style="color: hsl(120, 100%, 40%);">+ obj = ChannelTestCondition(TestConfig())</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.register_asterisk_instance(AstMockObjectSingle())</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.evaluate()</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.get_status(), 'Failed')</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_evaluate_single_pass(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ """test single channel condition"""</span><br><span style="color: hsl(120, 100%, 40%);">+ obj = ChannelTestCondition(TestConfig())</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.allowed_channels = 1</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.register_asterisk_instance(AstMockObjectSingle())</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.evaluate()</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.get_status(), 'Passed')</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_evaluate_leaked(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ """test leaked channel condition"""</span><br><span style="color: hsl(120, 100%, 40%);">+ obj = ChannelTestCondition(TestConfig())</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.register_asterisk_instance(AstMockObjectLeaked())</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.evaluate()</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.get_status(), 'Failed')</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%);">+if __name__ == "__main__":</span><br><span style="color: hsl(120, 100%, 40%);">+ main()</span><br><span>diff --git a/lib/python/asterisk/self_test/test_config.py b/lib/python/asterisk/self_test/test_config.py</span><br><span>new file mode 100755</span><br><span>index 0000000..cc88636</span><br><span>--- /dev/null</span><br><span>+++ b/lib/python/asterisk/self_test/test_config.py</span><br><span>@@ -0,0 +1,83 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#!/usr/bin/env python</span><br><span style="color: hsl(120, 100%, 40%);">+"""Asterisk Configuration File Handling Unit Tests.</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Copyright (C) 2010, Digium, Inc.</span><br><span style="color: hsl(120, 100%, 40%);">+Russell Bryant <russell@digium.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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+from harness_shared import main</span><br><span style="color: hsl(120, 100%, 40%);">+import unittest</span><br><span style="color: hsl(120, 100%, 40%);">+from asterisk.config import ConfigFile</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 ConfigFileTests(unittest.TestCase):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Unit tests for ConfigFile"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_conf(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Test parsing a blob of config data"""</span><br><span style="color: hsl(120, 100%, 40%);">+ test = \</span><br><span style="color: hsl(120, 100%, 40%);">+ "; stuff\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+ "this line is invalid on purpose\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+ "[this is] also invalid]\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+ ";-- comment --;\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+ ";-- \n" \</span><br><span style="color: hsl(120, 100%, 40%);">+ "[this is commented out]\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+ " --;\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+ "[foo]\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+ "a = b\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+ " b = a \n" \</span><br><span style="color: hsl(120, 100%, 40%);">+ "this line is invalid on purpose\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+ ";moo\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+ "c = d;asdadf;adfads;adsfasdf\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+ " [bar] ;asdfasdf\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+ "a-b=c-d\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+ "xyz=x|y|z\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+ "1234 => 4242,Example Mailbox,root@localhost,,var=val\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+ "\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+ "[template](!)\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+ "foo=bar\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+ "exten => _NXX.,n,Wait(1)\n" \</span><br><span style="color: hsl(120, 100%, 40%);">+ "astetcdir => /etc/asterisk\n"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ conf = ConfigFile(filename=None, config_str=test)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(len(conf.categories), 3)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(conf.categories[0].name, "foo")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertFalse(conf.categories[0].template)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(len(conf.categories[0].options), 3)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(conf.categories[0].options[0][0], "a")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(conf.categories[0].options[0][1], "b")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(conf.categories[0].options[1][0], "b")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(conf.categories[0].options[1][1], "a")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(conf.categories[0].options[2][0], "c")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(conf.categories[0].options[2][1], "d")</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(conf.categories[1].name, "bar")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertFalse(conf.categories[1].template)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(len(conf.categories[1].options), 3)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(conf.categories[1].options[0][0], "a-b")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(conf.categories[1].options[0][1], "c-d")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(conf.categories[1].options[1][0], "xyz")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(conf.categories[1].options[1][1], "x|y|z")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(conf.categories[1].options[2][0], "1234")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(conf.categories[1].options[2][1],</span><br><span style="color: hsl(120, 100%, 40%);">+ "4242,Example Mailbox,root@localhost,,var=val")</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(conf.categories[2].name, "template")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(conf.categories[2].template)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(len(conf.categories[2].options), 3)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(conf.categories[2].options[0][0], "foo")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(conf.categories[2].options[0][1], "bar")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(conf.categories[2].options[1][0], "exten")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(conf.categories[2].options[1][1],</span><br><span style="color: hsl(120, 100%, 40%);">+ "_NXX.,n,Wait(1)")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(conf.categories[2].options[2][0], "astetcdir")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(conf.categories[2].options[2][1], "/etc/asterisk")</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%);">+if __name__ == "__main__":</span><br><span style="color: hsl(120, 100%, 40%);">+ main()</span><br><span>diff --git a/lib/python/asterisk/self_test/test_lock_test_condition.py b/lib/python/asterisk/self_test/test_lock_test_condition.py</span><br><span>new file mode 100755</span><br><span>index 0000000..6cda06a</span><br><span>--- /dev/null</span><br><span>+++ b/lib/python/asterisk/self_test/test_lock_test_condition.py</span><br><span>@@ -0,0 +1,193 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#!/usr/bin/env python</span><br><span style="color: hsl(120, 100%, 40%);">+"""Held locks test condition unit tests</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Copyright (C) 2011-2012, Digium, Inc.</span><br><span style="color: hsl(120, 100%, 40%);">+Matt Jordan <mjordan@digium.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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+from harness_shared import AstMockOutput, ReadTestFile, main</span><br><span style="color: hsl(120, 100%, 40%);">+import unittest</span><br><span style="color: hsl(120, 100%, 40%);">+from asterisk.lock_test_condition import LockSequence, LockObject, LockTestCondition</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 AstMockObjectPassed(AstMockOutput):</span><br><span style="color: hsl(120, 100%, 40%);">+ """A lock output that passed"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def __init__(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Constructor"""</span><br><span style="color: hsl(120, 100%, 40%);">+ self.host = "127.0.0.2"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def cli_exec(self, command):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Fake out a CLI command execution"""</span><br><span style="color: hsl(120, 100%, 40%);">+ return self.MockDeferFile("locks-pass.txt")</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 AstMockObjectFailure(AstMockOutput):</span><br><span style="color: hsl(120, 100%, 40%);">+ """A lock object that failed"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def cli_exec(self, command):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Fake out a CLI command execution"""</span><br><span style="color: hsl(120, 100%, 40%);">+ return self.MockDeferFile("locks-fail.txt")</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 TestConfig(object):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Fake TestConfig object"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def __init__(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ """ Values here don't matter much - we just need to have something """</span><br><span style="color: hsl(120, 100%, 40%);">+ self.class_type_name = "asterisk.LockTestCondition.LockTestCondition"</span><br><span style="color: hsl(120, 100%, 40%);">+ self.pass_expected = True</span><br><span style="color: hsl(120, 100%, 40%);">+ self.type = "Post"</span><br><span style="color: hsl(120, 100%, 40%);">+ self.related_condition = ""</span><br><span style="color: hsl(120, 100%, 40%);">+ self.config = {}</span><br><span style="color: hsl(120, 100%, 40%);">+ self.enabled = True</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 LockTestConditionUnitTest(unittest.TestCase):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Unit tests for LockTestCondition"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_evaluate_failed(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Test a failed locking condition"""</span><br><span style="color: hsl(120, 100%, 40%);">+ ast = AstMockObjectFailure()</span><br><span style="color: hsl(120, 100%, 40%);">+ obj = LockTestCondition(TestConfig())</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.register_asterisk_instance(ast)</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.evaluate()</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.get_status(), 'Failed')</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_evaluate_pass(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Test a passed locking condition"""</span><br><span style="color: hsl(120, 100%, 40%);">+ ast = AstMockObjectPassed()</span><br><span style="color: hsl(120, 100%, 40%);">+ obj = LockTestCondition(TestConfig())</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.register_asterisk_instance(ast)</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.evaluate()</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.get_status(), 'Passed')</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_evaluate_multiple(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Test multiple results"""</span><br><span style="color: hsl(120, 100%, 40%);">+ ast1 = AstMockObjectPassed()</span><br><span style="color: hsl(120, 100%, 40%);">+ ast2 = AstMockObjectFailure()</span><br><span style="color: hsl(120, 100%, 40%);">+ obj = LockTestCondition(TestConfig())</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.register_asterisk_instance(ast1)</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.register_asterisk_instance(ast2)</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.evaluate()</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.get_status(), 'Failed')</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 LockSequenceUnitTest(unittest.TestCase):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Tests for parsing a lock sequence"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_single_object_no_held_info(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Test a lock sequence with no waiting lock"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ obj = LockSequence()</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.parse_lock_sequence(ReadTestFile("locks-single-object-no-held-info.txt"))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_large_multiple_object(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Test with a waiting lock"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ obj = LockSequence()</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.parse_lock_sequence(ReadTestFile("locks-large-multiple-object.txt"))</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.thread_id, "0x449ec940")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.thread_name, "netconsole")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.thread_line, 1351)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.thread_file, "asterisk.c")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.thread_func, "listener")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(len(obj.locks) == 1)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.locks[0].locked_file, "astobj2.c")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.locks[0].locked_line, 657)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.locks[0].locked_func, "internal_ao2_callback")</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_single_object(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Test a lock held somewhere else"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ obj = LockSequence()</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.parse_lock_sequence(ReadTestFile("locks-single-object.txt"))</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.thread_id, "0x402c6940")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.thread_name, "do_monitor")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.thread_line, 25114)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.thread_file, "chan_sip.c")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.thread_func, "restart_monitor")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(len(obj.locks) == 1)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.locks[0].locked_file, "channel.c")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.locks[0].locked_line, 4304)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.locks[0].locked_func, "ast_indicate_data")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.locks[0].id, 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.locks[0].type, "MUTEX")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.locks[0].file, "chan_sip.c")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.locks[0].line_number, 24629)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.locks[0].func, "handle_request_do")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.locks[0].name, "&netlock")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.locks[0].addr, "0x2aaabe671a40")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.locks[0].lock_count, 1)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(obj.locks[0].held)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(len(obj.locks[0].backtrace) == 3)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_multiple_objects_no_backtrace(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Test multiple locks with no backtrace"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ obj = LockSequence()</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.parse_lock_sequence(ReadTestFile("locks-multiple-objects-no-backtrace.txt"))</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.thread_id, "0x402c6940")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.thread_name, "do_monitor")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.thread_line, 25114)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.thread_file, "chan_sip.c")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.thread_func, "restart_monitor")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(len(obj.locks) == 3)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.locks[2].locked_file, "channel.c")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.locks[2].locked_line, 4304)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.locks[2].locked_func, "ast_indicate_data")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.locks[0].id, 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.locks[0].type, "MUTEX")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.locks[0].file, "chan_sip.c")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.locks[0].line_number, 24629)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.locks[0].func, "handle_request_do")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.locks[0].name, "&netlock")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.locks[0].addr, "0x2aaabe671a40")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.locks[0].lock_count, 1)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(obj.locks[0].held)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(len(obj.locks[0].backtrace) == 0)</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 LockObjectUnitTest(unittest.TestCase):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Unit tests for LockObject"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_no_backtrace(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Test creating a lock object with no thread backtrace"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ lock_line = "=== ---> Waiting for Lock #0 (sig_ss7.c): " + \</span><br><span style="color: hsl(120, 100%, 40%);">+ "MUTEX 636 ss7_linkset &linkset->lock 0x2aaab8a6b588 (1)"</span><br><span style="color: hsl(120, 100%, 40%);">+ obj = LockObject()</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.parse_lock_information(lock_line)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.id, 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.type, "MUTEX")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.file, "sig_ss7.c")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.line_number, 636)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.func, "ss7_linkset")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.name, "&linkset->lock")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.addr, "0x2aaab8a6b588")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.lock_count, 1)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertFalse(obj.held)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(len(obj.backtrace) == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_with_backtrace(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Test creating a lock object with a thread backtrace"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ obj = LockObject()</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.parse_lock_information(ReadTestFile("locks-backtrace.txt"))</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.id, 1)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.type, "MUTEX")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.file, "astobj2.c")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.line_number, 657)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.func, "internal_ao2_callback")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.name, "c")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.addr, "0x2aaaac491f50")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.lock_count, 1)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(obj.held)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(len(obj.backtrace) == 19)</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%);">+if __name__ == "__main__":</span><br><span style="color: hsl(120, 100%, 40%);">+ main()</span><br><span>diff --git a/lib/python/asterisk/self_test/test2_matcher.py b/lib/python/asterisk/self_test/test_matcher.py</span><br><span>similarity index 100%</span><br><span>rename from lib/python/asterisk/self_test/test2_matcher.py</span><br><span>rename to lib/python/asterisk/self_test/test_matcher.py</span><br><span>diff --git a/lib/python/asterisk/self_test/test_sip_dialog_test_condition.py.txt b/lib/python/asterisk/self_test/test_sip_dialog_test_condition.py.txt</span><br><span>new file mode 100644</span><br><span>index 0000000..717e183</span><br><span>--- /dev/null</span><br><span>+++ b/lib/python/asterisk/self_test/test_sip_dialog_test_condition.py.txt</span><br><span>@@ -0,0 +1,426 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#!/usr/bin/env python</span><br><span style="color: hsl(120, 100%, 40%);">+"""Test condition for verifying SIP dialogs unit tests</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Copyright (C) 2011-2012, Digium, Inc.</span><br><span style="color: hsl(120, 100%, 40%);">+Matt Jordan <mjordan@digium.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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+from harness_shared import AstMockOutput, main</span><br><span style="color: hsl(120, 100%, 40%);">+import unittest</span><br><span style="color: hsl(120, 100%, 40%);">+from asterisk.sip_dialog_test_condition import SipDialogPreTestCondition, \</span><br><span style="color: hsl(120, 100%, 40%);">+ SipDialogPostTestCondition</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 TestConfig(object):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Mock TestConfig object"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def __init__(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Constructor</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ Values here don't matter much - we just need to have something"""</span><br><span style="color: hsl(120, 100%, 40%);">+ self.type_name = ("asterisk.sip_dialog_test_condition." +</span><br><span style="color: hsl(120, 100%, 40%);">+ "SipDialogPostTestCondition")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.pass_expected = True</span><br><span style="color: hsl(120, 100%, 40%);">+ self.type = "Post"</span><br><span style="color: hsl(120, 100%, 40%);">+ self.related_condition = ""</span><br><span style="color: hsl(120, 100%, 40%);">+ self.class_type_name = "sip_dialog_test_condition"</span><br><span style="color: hsl(120, 100%, 40%);">+ self.config = {}</span><br><span style="color: hsl(120, 100%, 40%);">+ self.enabled = True</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 TestConfigWithHistory(TestConfig):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Mock TestConfig object with history requirements"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def __init__(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Constructor"""</span><br><span style="color: hsl(120, 100%, 40%);">+ super(TestConfigWithHistory, self).__init__()</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ self.config['history_requirements'] = []</span><br><span style="color: hsl(120, 100%, 40%);">+ self.config['history_requirements'].append('Hangup')</span><br><span style="color: hsl(120, 100%, 40%);">+ self.config['history_requirements'].append('NewChan')</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 AstMockObjectPostTestNoDestructionFail(AstMockOutput):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Mock out CLI execution from Asterisk instance</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ This mock object makes it appear as if a dialog failed to be destroyed</span><br><span style="color: hsl(120, 100%, 40%);">+ """</span><br><span style="color: hsl(120, 100%, 40%);">+ def __init__(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Constructor"""</span><br><span style="color: hsl(120, 100%, 40%);">+ self.host = "127.0.0.6"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def cli_exec(self, command):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Mock CLI execution/response"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ output = ""</span><br><span style="color: hsl(120, 100%, 40%);">+ if command == "sip show objects":</span><br><span style="color: hsl(120, 100%, 40%);">+ output = "-= Peer objects: 4 static, 0 realtime, 0 autocreate =-\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: audio\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: 7002\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: 7001\ntype: peer\nobjflags: 0\nrefcount: 1\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: zoiper_01\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "-= Peer objects by IP =-\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: zoiper_01\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: audio\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: 7002\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "-= Registry objects: 0 =-\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "-= Dialog objects:\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: 2ec048aa4ed1239664f6408f0c5044c4@127.0.0.2:5060\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "type: dialog\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "objflags: 0\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "refcount: 2\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: 2ec048aa4ed1239664f6408f0c5044c5@127.0.0.2:5060\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "type: dialog\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "objflags: 0\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "refcount: 2\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ elif command == "sip show history 2ec048aa4ed1239664f6408f0c5044c4@127.0.0.2:5060":</span><br><span style="color: hsl(120, 100%, 40%);">+ output = "* SIP Call\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "1. NewChan Channel SIP/ast1-00000002 - from 2ec048aa4ed1239664f6408f0c5044\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "2. TxReqRel INVITE / 102 INVITE - INVITE\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "3. Rx SIP/2.0 / 102 INVITE / 100 Trying\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "4. Rx SIP/2.0 / 102 INVITE / 200 OK\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "5. TxReq ACK / 102 ACK - ACK\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "6. Rx BYE / 102 BYE / sip:ast2@127.0.0.2:5060\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "7. RTCPaudio Quality:ssrc=28249381;themssrc=485141946;lp=0;rxjitter=0.000029\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "8. RTCPaudioJitter Quality:minrxjitter=0.000000;maxrxjitter=0.000000;avgrxjitter=0\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "9. RTCPaudioLoss Quality:minrxlost=0.000000;maxrxlost=0.000000;avgrxlost=0.00000\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "10. RTCPaudioRTT Quality:minrtt=0.000000;maxrtt=0.000000;avgrtt=0.000000;stdevrt\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "11. SchedDestroy 32000 ms\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "12. TxResp SIP/2.0 / 102 BYE - 200 OK\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "13. Hangup Cause Normal Clearing\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ elif command == "sip show history 2ec048aa4ed1239664f6408f0c5044c5@127.0.0.2:5060":</span><br><span style="color: hsl(120, 100%, 40%);">+ output = "* SIP Call\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "1. NewChan Channel SIP/ast1-00000002 - from 2ec048aa4ed1239664f6408f0c5044\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "2. TxReqRel INVITE / 102 INVITE - INVITE\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "3. Rx SIP/2.0 / 102 INVITE / 100 Trying\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "4. Rx SIP/2.0 / 102 INVITE / 200 OK\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "5. TxReq ACK / 102 ACK - ACK\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "6. Rx BYE / 102 BYE / sip:ast2@127.0.0.2:5060\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "7. RTCPaudio Quality:ssrc=28249381;themssrc=485141946;lp=0;rxjitter=0.000029\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "8. RTCPaudioJitter Quality:minrxjitter=0.000000;maxrxjitter=0.000000;avgrxjitter=0\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "9. RTCPaudioLoss Quality:minrxlost=0.000000;maxrxlost=0.000000;avgrxlost=0.00000\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "10. RTCPaudioRTT Quality:minrtt=0.000000;maxrtt=0.000000;avgrtt=0.000000;stdevrt\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "11. TxResp SIP/2.0 / 102 BYE - 200 OK\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "12. Hangup Cause Normal Clearing\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ return self.MockDefer(output)</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 AstMockObjectPostTestNoHangupFail(AstMockOutput):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Mock out CLI execution from Asterisk instance</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ This mock object makes it appear as if a channel failed to hangup</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%);">+ def __init__(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Constructor"""</span><br><span style="color: hsl(120, 100%, 40%);">+ self.host = "127.0.0.5"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def cli_exec(self, command):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Mock CLI execution/response"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ output = ""</span><br><span style="color: hsl(120, 100%, 40%);">+ if command == "sip show objects":</span><br><span style="color: hsl(120, 100%, 40%);">+ output = "-= Peer objects: 4 static, 0 realtime, 0 autocreate =-\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: audio\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: 7002\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: 7001\ntype: peer\nobjflags: 0\nrefcount: 1\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: zoiper_01\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "-= Peer objects by IP =-\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: zoiper_01\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: audio\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: 7002\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "-= Registry objects: 0 =-\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "-= Dialog objects:\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: 2ec048aa4ed1239664f6408f0c5044c4@127.0.0.2:5060\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "type: dialog\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "objflags: 0\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "refcount: 2\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: 2ec048aa4ed1239664f6408f0c5044c5@127.0.0.2:5060\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "type: dialog\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "objflags: 0\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "refcount: 2\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ elif command == "sip show history 2ec048aa4ed1239664f6408f0c5044c4@127.0.0.2:5060":</span><br><span style="color: hsl(120, 100%, 40%);">+ output = "* SIP Call\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "1. NewChan Channel SIP/ast1-00000002 - from 2ec048aa4ed1239664f6408f0c5044\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "2. TxReqRel INVITE / 102 INVITE - INVITE\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "3. Rx SIP/2.0 / 102 INVITE / 100 Trying\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "4. Rx SIP/2.0 / 102 INVITE / 200 OK\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "5. TxReq ACK / 102 ACK - ACK\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "6. Rx BYE / 102 BYE / sip:ast2@127.0.0.2:5060\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "7. RTCPaudio Quality:ssrc=28249381;themssrc=485141946;lp=0;rxjitter=0.000029\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "8. RTCPaudioJitter Quality:minrxjitter=0.000000;maxrxjitter=0.000000;avgrxjitter=0\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "9. RTCPaudioLoss Quality:minrxlost=0.000000;maxrxlost=0.000000;avgrxlost=0.00000\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "10. RTCPaudioRTT Quality:minrtt=0.000000;maxrtt=0.000000;avgrtt=0.000000;stdevrt\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "11. SchedDestroy 32000 ms\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "12. TxResp SIP/2.0 / 102 BYE - 200 OK\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ elif command == "sip show history 2ec048aa4ed1239664f6408f0c5044c5@127.0.0.2:5060":</span><br><span style="color: hsl(120, 100%, 40%);">+ output = "* SIP Call\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "1. NewChan Channel SIP/ast1-00000002 - from 2ec048aa4ed1239664f6408f0c5044\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "2. TxReqRel INVITE / 102 INVITE - INVITE\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "3. Rx SIP/2.0 / 102 INVITE / 100 Trying\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "4. Rx SIP/2.0 / 102 INVITE / 200 OK\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "5. TxReq ACK / 102 ACK - ACK\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "6. Rx BYE / 102 BYE / sip:ast2@127.0.0.2:5060\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "7. RTCPaudio Quality:ssrc=28249381;themssrc=485141946;lp=0;rxjitter=0.000029\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "8. RTCPaudioJitter Quality:minrxjitter=0.000000;maxrxjitter=0.000000;avgrxjitter=0\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "9. RTCPaudioLoss Quality:minrxlost=0.000000;maxrxlost=0.000000;avgrxlost=0.00000\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "10. RTCPaudioRTT Quality:minrtt=0.000000;maxrtt=0.000000;avgrtt=0.000000;stdevrt\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "11. SchedDestroy 32000 ms\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "12. TxResp SIP/2.0 / 102 BYE - 200 OK\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "13. Hangup Cause Normal Clearing\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ return self.MockDefer(output)</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 AstMockObjectPostTestNoDialogsPass(AstMockOutput):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Mock out CLI execution from Asterisk instance</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ This mock object makes it appear as if there were no dialogs, which is okay</span><br><span style="color: hsl(120, 100%, 40%);">+ """</span><br><span style="color: hsl(120, 100%, 40%);">+ def __init__(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Constructor"""</span><br><span style="color: hsl(120, 100%, 40%);">+ self.host = "127.0.0.4"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def cli_exec(self, command):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Mock CLI execution/response"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ output = ""</span><br><span style="color: hsl(120, 100%, 40%);">+ if command == "sip show objects":</span><br><span style="color: hsl(120, 100%, 40%);">+ output = "-= Peer objects: 4 static, 0 realtime, 0 autocreate =-\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: audio\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: 7002\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: 7001\ntype: peer\nobjflags: 0\nrefcount: 1\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: zoiper_01\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "-= Peer objects by IP =-\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: zoiper_01\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: audio\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: 7002\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "-= Registry objects: 0 =-\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "-= Dialog objects:\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return self.MockDefer(output)</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 AstMockObjectPostTestPass(AstMockOutput):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Mock out CLI execution from Asterisk instance</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ This mock object provides two dialogs with acceptable history</span><br><span style="color: hsl(120, 100%, 40%);">+ """</span><br><span style="color: hsl(120, 100%, 40%);">+ def __init__(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Constructor"""</span><br><span style="color: hsl(120, 100%, 40%);">+ self.host = "127.0.0.3"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def cli_exec(self, command):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Mock CLI execution/response"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ output = ""</span><br><span style="color: hsl(120, 100%, 40%);">+ if command == "sip show objects":</span><br><span style="color: hsl(120, 100%, 40%);">+ output = "-= Peer objects: 4 static, 0 realtime, 0 autocreate =-\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: audio\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: 7002\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: 7001\ntype: peer\nobjflags: 0\nrefcount: 1\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: zoiper_01\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "-= Peer objects by IP =-\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: zoiper_01\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: audio\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: 7002\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "-= Registry objects: 0 =-\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "-= Dialog objects:\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: 2ec048aa4ed1239664f6408f0c5044c4@127.0.0.2:5060\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "type: dialog\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "objflags: 0\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "refcount: 2\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: 2ec048aa4ed1239664f6408f0c5044c5@127.0.0.2:5060\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "type: dialog\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "objflags: 0\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "refcount: 2\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ elif command == "sip show history 2ec048aa4ed1239664f6408f0c5044c4@127.0.0.2:5060":</span><br><span style="color: hsl(120, 100%, 40%);">+ output = "* SIP Call\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "1. NewChan Channel SIP/ast1-00000002 - from 2ec048aa4ed1239664f6408f0c5044\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "2. TxReqRel INVITE / 102 INVITE - INVITE\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "3. Rx SIP/2.0 / 102 INVITE / 100 Trying\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "4. Rx SIP/2.0 / 102 INVITE / 200 OK\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "5. TxReq ACK / 102 ACK - ACK\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "6. Rx BYE / 102 BYE / sip:ast2@127.0.0.2:5060\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "7. RTCPaudio Quality:ssrc=28249381;themssrc=485141946;lp=0;rxjitter=0.000029\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "8. RTCPaudioJitter Quality:minrxjitter=0.000000;maxrxjitter=0.000000;avgrxjitter=0\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "9. RTCPaudioLoss Quality:minrxlost=0.000000;maxrxlost=0.000000;avgrxlost=0.00000\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "10. RTCPaudioRTT Quality:minrtt=0.000000;maxrtt=0.000000;avgrtt=0.000000;stdevrt\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "11. SchedDestroy 32000 ms\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "12. TxResp SIP/2.0 / 102 BYE - 200 OK\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "13. Hangup Cause Normal Clearing\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ elif command == "sip show history 2ec048aa4ed1239664f6408f0c5044c5@127.0.0.2:5060":</span><br><span style="color: hsl(120, 100%, 40%);">+ output = "* SIP Call\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "1. NewChan Channel SIP/ast1-00000002 - from 2ec048aa4ed1239664f6408f0c5044\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "2. TxReqRel INVITE / 102 INVITE - INVITE\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "3. Rx SIP/2.0 / 102 INVITE / 100 Trying\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "4. Rx SIP/2.0 / 102 INVITE / 200 OK\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "5. TxReq ACK / 102 ACK - ACK\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "6. Rx BYE / 102 BYE / sip:ast2@127.0.0.2:5060\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "7. RTCPaudio Quality:ssrc=28249381;themssrc=485141946;lp=0;rxjitter=0.000029\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "8. RTCPaudioJitter Quality:minrxjitter=0.000000;maxrxjitter=0.000000;avgrxjitter=0\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "9. RTCPaudioLoss Quality:minrxlost=0.000000;maxrxlost=0.000000;avgrxlost=0.00000\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "10. RTCPaudioRTT Quality:minrtt=0.000000;maxrtt=0.000000;avgrtt=0.000000;stdevrt\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "11. SchedDestroy 32000 ms\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "12. TxResp SIP/2.0 / 102 BYE - 200 OK\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "13. Hangup Cause Normal Clearing\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ return self.MockDefer(output)</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 AstMockObjectPreTestFail(AstMockOutput):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Mock out CLI execution from Asterisk instance</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ This mock object provides history during a pre-test call, which is wrong</span><br><span style="color: hsl(120, 100%, 40%);">+ """</span><br><span style="color: hsl(120, 100%, 40%);">+ def __init__(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Constructor"""</span><br><span style="color: hsl(120, 100%, 40%);">+ self.host = "127.0.0.2"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def cli_exec(self, command):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Mock CLI execution/response"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ output = ""</span><br><span style="color: hsl(120, 100%, 40%);">+ if command == "sip show objects":</span><br><span style="color: hsl(120, 100%, 40%);">+ output = "-= Peer objects: 4 static, 0 realtime, 0 autocreate =-\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: audio\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: 7002\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: 7001\ntype: peer\nobjflags: 0\nrefcount: 1\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: zoiper_01\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "-= Peer objects by IP =-\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: zoiper_01\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: audio\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: 7002\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "-= Registry objects: 0 =-\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "-= Dialog objects:\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: 2ec048aa4ed1239664f6408f0c5044c4@127.0.0.2:5060\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "type: dialog\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "objflags: 0\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "refcount: 2\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ elif command == "sip show history 2ec048aa4ed1239664f6408f0c5044c4@127.0.0.2:5060":</span><br><span style="color: hsl(120, 100%, 40%);">+ output = "* SIP Call\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "1. NewChan Channel SIP/ast1-00000002 - from 2ec048aa4ed1239664f6408f0c5044\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "2. TxReqRel INVITE / 102 INVITE - INVITE\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "3. Rx SIP/2.0 / 102 INVITE / 100 Trying\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "4. Rx SIP/2.0 / 102 INVITE / 200 OK\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "5. TxReq ACK / 102 ACK - ACK\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "6. Rx BYE / 102 BYE / sip:ast2@127.0.0.2:5060\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "7. RTCPaudio Quality:ssrc=28249381;themssrc=485141946;lp=0;rxjitter=0.000029\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "8. RTCPaudioJitter Quality:minrxjitter=0.000000;maxrxjitter=0.000000;avgrxjitter=0\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "9. RTCPaudioLoss Quality:minrxlost=0.000000;maxrxlost=0.000000;avgrxlost=0.00000\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "10. RTCPaudioRTT Quality:minrtt=0.000000;maxrtt=0.000000;avgrtt=0.000000;stdevrt\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "11. SchedDestroy 32000 ms\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "12. TxResp SIP/2.0 / 102 BYE - 200 OK\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "13. Hangup Cause Normal Clearing\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ return self.MockDefer(output)</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 AstMockObjectPreTestPass(AstMockOutput):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Mock out CLI execution from Asterisk instance</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ This mock object provides no history during a pre-test call, which is the</span><br><span style="color: hsl(120, 100%, 40%);">+ expected state</span><br><span style="color: hsl(120, 100%, 40%);">+ """</span><br><span style="color: hsl(120, 100%, 40%);">+ def cli_exec(self, command):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Mock CLI execution/response"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ output = ""</span><br><span style="color: hsl(120, 100%, 40%);">+ if command == "sip show objects":</span><br><span style="color: hsl(120, 100%, 40%);">+ output = "-= Peer objects: 4 static, 0 realtime, 0 autocreate =-\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: audio\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: 7002\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: 7001\ntype: peer\nobjflags: 0\nrefcount: 1\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: zoiper_01\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "-= Peer objects by IP =-\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: zoiper_01\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: audio\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "name: 7002\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "-= Registry objects: 0 =-\n\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ output += "-= Dialog objects:\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ elif command == "sip show history":</span><br><span style="color: hsl(120, 100%, 40%);">+ output = "\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ return self.MockDefer(output)</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%);">+@unittest.skip("sip_dialog_test_condition.py is broken")</span><br><span style="color: hsl(120, 100%, 40%);">+class SipDialogTestConditionUnitTest(unittest.TestCase):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Unit tests for SipDialogTestCondition objects"""</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_pre_test_pass(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Verify that acceptable pre-test output passes"""</span><br><span style="color: hsl(120, 100%, 40%);">+ ast = AstMockObjectPreTestPass()</span><br><span style="color: hsl(120, 100%, 40%);">+ obj = SipDialogPreTestCondition(TestConfig())</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.register_asterisk_instance(ast)</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.evaluate()</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.get_status(), 'Passed')</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_pre_test_fail(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Verify that unacceptable pre-test output fails"""</span><br><span style="color: hsl(120, 100%, 40%);">+ ast = AstMockObjectPreTestFail()</span><br><span style="color: hsl(120, 100%, 40%);">+ obj = SipDialogPreTestCondition(TestConfig())</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.register_asterisk_instance(ast)</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.evaluate()</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.get_status(), 'Failed')</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_pre_test_fail_multi_asterisk(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Verify that pre-test output from multiple sources fails when one</span><br><span style="color: hsl(120, 100%, 40%);">+ of those sources is bad"""</span><br><span style="color: hsl(120, 100%, 40%);">+ ast1 = AstMockObjectPreTestFail()</span><br><span style="color: hsl(120, 100%, 40%);">+ ast2 = AstMockObjectPreTestPass()</span><br><span style="color: hsl(120, 100%, 40%);">+ obj = SipDialogPreTestCondition(TestConfig())</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.register_asterisk_instance(ast1)</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.register_asterisk_instance(ast2)</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.evaluate()</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.get_status(), 'Failed')</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_post_test_pass(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Verify nominal post-test output"""</span><br><span style="color: hsl(120, 100%, 40%);">+ ast = AstMockObjectPostTestPass()</span><br><span style="color: hsl(120, 100%, 40%);">+ obj = SipDialogPostTestCondition(TestConfigWithHistory())</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.register_asterisk_instance(ast)</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.evaluate()</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.get_status(), 'Passed')</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_post_test_no_dialog_pass(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Verify nominal post-test output with no dialogs passes"""</span><br><span style="color: hsl(120, 100%, 40%);">+ ast = AstMockObjectPostTestNoDialogsPass()</span><br><span style="color: hsl(120, 100%, 40%);">+ obj = SipDialogPostTestCondition(TestConfig())</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.register_asterisk_instance(ast)</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.evaluate()</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.get_status(), 'Passed')</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_post_test_no_hangup_fail(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Verify no hangup detection is caught and results in a failure"""</span><br><span style="color: hsl(120, 100%, 40%);">+ ast = AstMockObjectPostTestNoHangupFail()</span><br><span style="color: hsl(120, 100%, 40%);">+ obj = SipDialogPostTestCondition(TestConfigWithHistory())</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.register_asterisk_instance(ast)</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.evaluate()</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.get_status(), 'Failed')</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_post_test_no_destruction_fail(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Verify no destruction is caught and results in a failure"""</span><br><span style="color: hsl(120, 100%, 40%);">+ ast = AstMockObjectPostTestNoDestructionFail()</span><br><span style="color: hsl(120, 100%, 40%);">+ obj = SipDialogPostTestCondition(TestConfigWithHistory())</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.register_asterisk_instance(ast)</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.evaluate()</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.get_status(), 'Failed')</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_post_test_multi_asterisk_fail(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Test multiple instances of Asterisk where a single failure causes</span><br><span style="color: hsl(120, 100%, 40%);">+ a failure in the overall result"""</span><br><span style="color: hsl(120, 100%, 40%);">+ ast1 = AstMockObjectPostTestNoHangupFail()</span><br><span style="color: hsl(120, 100%, 40%);">+ ast2 = AstMockObjectPostTestNoDestructionFail()</span><br><span style="color: hsl(120, 100%, 40%);">+ ast3 = AstMockObjectPostTestNoDialogsPass()</span><br><span style="color: hsl(120, 100%, 40%);">+ ast4 = AstMockObjectPostTestPass()</span><br><span style="color: hsl(120, 100%, 40%);">+ obj = SipDialogPostTestCondition(TestConfigWithHistory())</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.register_asterisk_instance(ast1)</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.register_asterisk_instance(ast2)</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.register_asterisk_instance(ast3)</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.register_asterisk_instance(ast4)</span><br><span style="color: hsl(120, 100%, 40%);">+ obj.evaluate()</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(obj.get_status(), 'Failed')</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%);">+if __name__ == "__main__":</span><br><span style="color: hsl(120, 100%, 40%);">+ main()</span><br><span>diff --git a/lib/python/asterisk/self_test/test_sippversion.py b/lib/python/asterisk/self_test/test_sippversion.py</span><br><span>new file mode 100755</span><br><span>index 0000000..8c3d933</span><br><span>--- /dev/null</span><br><span>+++ b/lib/python/asterisk/self_test/test_sippversion.py</span><br><span>@@ -0,0 +1,221 @@</span><br><span style="color: hsl(120, 100%, 40%);">+#!/usr/bin/env python</span><br><span style="color: hsl(120, 100%, 40%);">+"""SIPp Version String Handling Tests</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Copyright (C) 2010, Digium, Inc.</span><br><span style="color: hsl(120, 100%, 40%);">+Paul Belanger <pabelanger@digium.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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+from harness_shared import main</span><br><span style="color: hsl(120, 100%, 40%);">+import unittest</span><br><span style="color: hsl(120, 100%, 40%);">+from asterisk.sippversion import SIPpVersion</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 SIPpVersionTests(unittest.TestCase):</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_version(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ v = SIPpVersion("v3.2", None)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(str(v), "v3.2")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(v.concept, "v3")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(v.major, "2")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(v.minor, None)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertFalse(v.tls)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertFalse(v.pcap)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_version2(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ v = SIPpVersion("v2.0.1", None)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(str(v), "v2.0.1")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(v.concept, "v2")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(v.major, "0")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(v.minor, "1")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertFalse(v.tls)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertFalse(v.pcap)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_version3(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ v = SIPpVersion("v3.1", "TLS")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(str(v), "v3.1-TLS")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(v.concept, "v3")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(v.major, "1")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(v.minor, None)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(v.tls)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertFalse(v.pcap)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_version4(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ v = SIPpVersion("v2.0.1", "TLS-PCAP")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(str(v), "v2.0.1-TLS-PCAP")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(v.concept, "v2")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(v.major, "0")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(v.minor, "1")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(v.tls)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(v.pcap)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_version5(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ v = SIPpVersion("v3.2", "PCAP")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(str(v), "v3.2-PCAP")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(v.concept, "v3")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(v.major, "2")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(v.minor, None)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertFalse(v.tls)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(v.pcap)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_version6(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ v = SIPpVersion(None, "PCAP")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(str(v), "PCAP")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(v.concept, None)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(v.major, None)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(v.minor, None)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertFalse(v.tls)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(v.pcap)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_version7(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ v = SIPpVersion(None, "TLS")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(str(v), "TLS")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(v.concept, None)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(v.major, None)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(v.minor, None)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(v.tls)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertFalse(v.pcap)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_version8(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ v = SIPpVersion(None, "TLS-PCAP")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(str(v), "TLS-PCAP")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(v.concept, None)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(v.major, None)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertEqual(v.minor, None)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(v.tls)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(v.pcap)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_cmp(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ v1 = SIPpVersion("v3.2", None)</span><br><span style="color: hsl(120, 100%, 40%);">+ v2 = SIPpVersion("v3.1", None)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(v1 > v2)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_cmp2(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ v1 = SIPpVersion("v2.0.1", None)</span><br><span style="color: hsl(120, 100%, 40%);">+ v2 = SIPpVersion("v3.1", None)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(v1 < v2)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_cmp3(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ v1 = SIPpVersion("v3.1", None)</span><br><span style="color: hsl(120, 100%, 40%);">+ v2 = SIPpVersion("v3.1", None)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(v1 == v2)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_cmp4(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ v1 = SIPpVersion("v3.1", None)</span><br><span style="color: hsl(120, 100%, 40%);">+ v2 = SIPpVersion("v3.1", None)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertFalse(v1 != v2)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_cmp5(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ v1 = SIPpVersion("v3.1", "TLS")</span><br><span style="color: hsl(120, 100%, 40%);">+ v2 = SIPpVersion("v3.1", "TLS")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(v1 == v2)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_cmp6(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ v1 = SIPpVersion(None, "TLS")</span><br><span style="color: hsl(120, 100%, 40%);">+ v2 = SIPpVersion(None, "TLS")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(v1 == v2)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_cmp7(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ v1 = SIPpVersion("v2.0.1", None)</span><br><span style="color: hsl(120, 100%, 40%);">+ v2 = SIPpVersion("v2.0.1", None)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(v1 == v2)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_cmp8(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ v1 = SIPpVersion("v3.2", "TLS")</span><br><span style="color: hsl(120, 100%, 40%);">+ v2 = SIPpVersion("v3.2", "PCAP")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(v1 != v2)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_cmp9(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ v1 = SIPpVersion(None, "TLS")</span><br><span style="color: hsl(120, 100%, 40%);">+ v2 = SIPpVersion(None, "PCAP")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(v1 != v2)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_cmp10(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ v1 = SIPpVersion("v3.2", "TLS")</span><br><span style="color: hsl(120, 100%, 40%);">+ v2 = SIPpVersion("v3.2", "PCAP")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertFalse(v1 == v2)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_cmp11(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ v1 = SIPpVersion(None, "TLS")</span><br><span style="color: hsl(120, 100%, 40%);">+ v2 = SIPpVersion(None, "PCAP")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertFalse(v1 == v2)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_cmp12(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ v1 = SIPpVersion("v3.2", "TLS-PCAP")</span><br><span style="color: hsl(120, 100%, 40%);">+ v2 = SIPpVersion("v3.2", "TLS")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(v1 >= v2)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_cmp13(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ v1 = SIPpVersion("v3.2", "TLS-PCAP")</span><br><span style="color: hsl(120, 100%, 40%);">+ v2 = SIPpVersion(None, "TLS")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(v1 >= v2)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_cmp14(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ v1 = SIPpVersion("v3.2", "TLS-PCAP")</span><br><span style="color: hsl(120, 100%, 40%);">+ v2 = SIPpVersion("v3.2", "PCAP")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(v1 >= v2)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_cmp15(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ v1 = SIPpVersion("v3.2", "TLS-PCAP")</span><br><span style="color: hsl(120, 100%, 40%);">+ v2 = SIPpVersion(None, "PCAP")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(v1 >= v2)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_cmp16(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ v1 = SIPpVersion("v3.2", "TLS-PCAP")</span><br><span style="color: hsl(120, 100%, 40%);">+ v2 = SIPpVersion("v3.2", "TLS")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(v1 != v2)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_cmp17(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ v1 = SIPpVersion("v3.2", "TLS-PCAP")</span><br><span style="color: hsl(120, 100%, 40%);">+ v2 = SIPpVersion(None, "TLS")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(v1 != v2)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_cmp18(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ v1 = SIPpVersion("v3.2", "TLS-PCAP")</span><br><span style="color: hsl(120, 100%, 40%);">+ v2 = SIPpVersion("v3.2", "TLS")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertFalse(v1 == v2)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_cmp19(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ v1 = SIPpVersion("v3.2", "TLS-PCAP")</span><br><span style="color: hsl(120, 100%, 40%);">+ v2 = SIPpVersion(None, "TLS")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertFalse(v1 == v2)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_cmp20(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ v1 = SIPpVersion("v3.1", "PCAP")</span><br><span style="color: hsl(120, 100%, 40%);">+ v2 = SIPpVersion("v3.0", "TLS")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(v1 > v2)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_cmp21(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ v1 = SIPpVersion("v3.2", "TLS-PCAP")</span><br><span style="color: hsl(120, 100%, 40%);">+ v2 = SIPpVersion("v2.0.1", "PCAP")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(v1 >= v2)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_cmp22(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ v1 = SIPpVersion("v3.1", "TLS")</span><br><span style="color: hsl(120, 100%, 40%);">+ v2 = SIPpVersion("v3.1", "PCAP")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertFalse(v1 > v2)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_cmp23(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ v1 = SIPpVersion("v3.1", "TLS")</span><br><span style="color: hsl(120, 100%, 40%);">+ v2 = SIPpVersion("v3.1", "PCAP")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertFalse(v1 < v2)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_cmp24(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ v1 = SIPpVersion("v3.2", "TLS")</span><br><span style="color: hsl(120, 100%, 40%);">+ v2 = SIPpVersion("v3.1", "TLS-PCAP")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(v1 >= v2)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_cmp25(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ v1 = SIPpVersion("v3.1", "TLS-PCAP")</span><br><span style="color: hsl(120, 100%, 40%);">+ v2 = SIPpVersion("v3.2", "PCAP")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertTrue(v1 <= v2)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def test_cmp26(self):</span><br><span style="color: hsl(120, 100%, 40%);">+ v1 = SIPpVersion("v2.0.1", "TLS-PCAP")</span><br><span style="color: hsl(120, 100%, 40%);">+ v2 = SIPpVersion("v3.0", "TLS")</span><br><span style="color: hsl(120, 100%, 40%);">+ self.assertFalse(v1 >= v2)</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%);">+if __name__ == "__main__":</span><br><span style="color: hsl(120, 100%, 40%);">+ main()</span><br><span>diff --git a/lib/python/asterisk/self_test/test_utils_socket.py b/lib/python/asterisk/self_test/test_utils_socket.py</span><br><span>index 3a0c33d..34672c6 100755</span><br><span>--- a/lib/python/asterisk/self_test/test_utils_socket.py</span><br><span>+++ b/lib/python/asterisk/self_test/test_utils_socket.py</span><br><span>@@ -10,19 +10,12 @@</span><br><span> the GNU General Public License Version 2.</span><br><span> """</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-import logging</span><br><span style="color: hsl(0, 100%, 40%);">-import sys</span><br><span style="color: hsl(120, 100%, 40%);">+from harness_shared import main</span><br><span> import unittest</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> from socket import SOCK_STREAM, SOCK_DGRAM, AF_INET, AF_INET6</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-sys.path.append('lib/python') # noqa</span><br><span> from asterisk.utils_socket import Ports, PortError, get_available_port, MIN_PORT</span><br><span> </span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-LOGGER = logging.getLogger(__name__)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> class PortTests(unittest.TestCase):</span><br><span> """Unit tests for port availability and reservations."""</span><br><span> </span><br><span>@@ -169,7 +162,4 @@</span><br><span> </span><br><span> if __name__ == "__main__":</span><br><span> """Run the unit tests"""</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- logging.basicConfig(stream=sys.stdout, level=logging.DEBUG,</span><br><span style="color: hsl(0, 100%, 40%);">- format="%(module)s:%(lineno)d - %(message)s")</span><br><span style="color: hsl(0, 100%, 40%);">- unittest.main()</span><br><span style="color: hsl(120, 100%, 40%);">+ main()</span><br><span>diff --git a/lib/python/asterisk/sip_channel_test_condition.py b/lib/python/asterisk/sip_channel_test_condition.py</span><br><span>index 150d90f..0f265f0 100644</span><br><span>--- a/lib/python/asterisk/sip_channel_test_condition.py</span><br><span>+++ b/lib/python/asterisk/sip_channel_test_condition.py</span><br><span>@@ -10,7 +10,7 @@</span><br><span> """</span><br><span> </span><br><span> from twisted.internet import defer</span><br><span style="color: hsl(0, 100%, 40%);">-from test_conditions import TestCondition</span><br><span style="color: hsl(120, 100%, 40%);">+from .test_conditions import TestCondition</span><br><span> </span><br><span> </span><br><span> class SipChannelTestCondition(TestCondition):</span><br><span>diff --git a/lib/python/asterisk/sip_dialog_test_condition.py b/lib/python/asterisk/sip_dialog_test_condition.py</span><br><span>index 4c75710..619a388 100644</span><br><span>--- a/lib/python/asterisk/sip_dialog_test_condition.py</span><br><span>+++ b/lib/python/asterisk/sip_dialog_test_condition.py</span><br><span>@@ -10,9 +10,8 @@</span><br><span> </span><br><span> import logging</span><br><span> import logging.config</span><br><span style="color: hsl(0, 100%, 40%);">-import unittest</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-from test_conditions import TestCondition</span><br><span style="color: hsl(120, 100%, 40%);">+from .test_conditions import TestCondition</span><br><span> from twisted.internet import defer</span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span>@@ -227,422 +226,3 @@</span><br><span> self._counter = -1</span><br><span> __get_dialogs()</span><br><span> return self._finished_deferred</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-class TestConfig(object):</span><br><span style="color: hsl(0, 100%, 40%);">- """Mock TestConfig object"""</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def __init__(self):</span><br><span style="color: hsl(0, 100%, 40%);">- """Constructor</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- Values here don't matter much - we just need to have something"""</span><br><span style="color: hsl(0, 100%, 40%);">- self.type_name = ("asterisk.sip_dialog_test_condition." +</span><br><span style="color: hsl(0, 100%, 40%);">- "SipDialogPostTestCondition")</span><br><span style="color: hsl(0, 100%, 40%);">- self.pass_expected = True</span><br><span style="color: hsl(0, 100%, 40%);">- self.type = "Post"</span><br><span style="color: hsl(0, 100%, 40%);">- self.related_condition = ""</span><br><span style="color: hsl(0, 100%, 40%);">- self.config = {}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-class TestConfigWithHistory(TestConfig):</span><br><span style="color: hsl(0, 100%, 40%);">- """Mock TestConfig object with history requirements"""</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def __init__(self):</span><br><span style="color: hsl(0, 100%, 40%);">- """Constructor"""</span><br><span style="color: hsl(0, 100%, 40%);">- super(TestConfigWithHistory, self).__init__()</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- self.config['history_requirements'] = []</span><br><span style="color: hsl(0, 100%, 40%);">- self.config['history_requirements'].append('Hangup')</span><br><span style="color: hsl(0, 100%, 40%);">- self.config['history_requirements'].append('NewChan')</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-class AstMockObjectPostTestNoDestructionFail(object):</span><br><span style="color: hsl(0, 100%, 40%);">- """Mock out CLI execution from Asterisk instance</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- This mock object makes it appear as if a dialog failed to be destroyed</span><br><span style="color: hsl(0, 100%, 40%);">- """</span><br><span style="color: hsl(0, 100%, 40%);">- def __init__(self):</span><br><span style="color: hsl(0, 100%, 40%);">- """Constructor"""</span><br><span style="color: hsl(0, 100%, 40%);">- self.host = "127.0.0.6"</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def cli_exec(self, command):</span><br><span style="color: hsl(0, 100%, 40%);">- """Mock CLI execution/response"""</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string = ""</span><br><span style="color: hsl(0, 100%, 40%);">- if command == "sip show objects":</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string = "-= Peer objects: 4 static, 0 realtime, 0 autocreate =-\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: audio\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: 7002\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: 7001\ntype: peer\nobjflags: 0\nrefcount: 1\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: zoiper_01\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "-= Peer objects by IP =-\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: zoiper_01\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: audio\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: 7002\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "-= Registry objects: 0 =-\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "-= Dialog objects:\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: 2ec048aa4ed1239664f6408f0c5044c4@127.0.0.2:5060\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "type: dialog\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "objflags: 0\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "refcount: 2\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: 2ec048aa4ed1239664f6408f0c5044c5@127.0.0.2:5060\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "type: dialog\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "objflags: 0\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "refcount: 2\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- elif command == "sip show history 2ec048aa4ed1239664f6408f0c5044c4@127.0.0.2:5060":</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string = "* SIP Call\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "1. NewChan Channel SIP/ast1-00000002 - from 2ec048aa4ed1239664f6408f0c5044\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "2. TxReqRel INVITE / 102 INVITE - INVITE\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "3. Rx SIP/2.0 / 102 INVITE / 100 Trying\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "4. Rx SIP/2.0 / 102 INVITE / 200 OK\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "5. TxReq ACK / 102 ACK - ACK\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "6. Rx BYE / 102 BYE / sip:ast2@127.0.0.2:5060\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "7. RTCPaudio Quality:ssrc=28249381;themssrc=485141946;lp=0;rxjitter=0.000029\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "8. RTCPaudioJitter Quality:minrxjitter=0.000000;maxrxjitter=0.000000;avgrxjitter=0\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "9. RTCPaudioLoss Quality:minrxlost=0.000000;maxrxlost=0.000000;avgrxlost=0.00000\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "10. RTCPaudioRTT Quality:minrtt=0.000000;maxrtt=0.000000;avgrtt=0.000000;stdevrt\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "11. SchedDestroy 32000 ms\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "12. TxResp SIP/2.0 / 102 BYE - 200 OK\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "13. Hangup Cause Normal Clearing\n"</span><br><span style="color: hsl(0, 100%, 40%);">- elif command == "sip show history 2ec048aa4ed1239664f6408f0c5044c5@127.0.0.2:5060":</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string = "* SIP Call\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "1. NewChan Channel SIP/ast1-00000002 - from 2ec048aa4ed1239664f6408f0c5044\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "2. TxReqRel INVITE / 102 INVITE - INVITE\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "3. Rx SIP/2.0 / 102 INVITE / 100 Trying\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "4. Rx SIP/2.0 / 102 INVITE / 200 OK\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "5. TxReq ACK / 102 ACK - ACK\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "6. Rx BYE / 102 BYE / sip:ast2@127.0.0.2:5060\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "7. RTCPaudio Quality:ssrc=28249381;themssrc=485141946;lp=0;rxjitter=0.000029\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "8. RTCPaudioJitter Quality:minrxjitter=0.000000;maxrxjitter=0.000000;avgrxjitter=0\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "9. RTCPaudioLoss Quality:minrxlost=0.000000;maxrxlost=0.000000;avgrxlost=0.00000\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "10. RTCPaudioRTT Quality:minrtt=0.000000;maxrtt=0.000000;avgrtt=0.000000;stdevrt\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "11. TxResp SIP/2.0 / 102 BYE - 200 OK\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "12. Hangup Cause Normal Clearing\n"</span><br><span style="color: hsl(0, 100%, 40%);">- return ret_string</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-class AstMockObjectPostTestNoHangupFail(object):</span><br><span style="color: hsl(0, 100%, 40%);">- """Mock out CLI execution from Asterisk instance</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- This mock object makes it appear as if a channel failed to hangup</span><br><span style="color: hsl(0, 100%, 40%);">- """</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def __init__(self):</span><br><span style="color: hsl(0, 100%, 40%);">- """Constructor"""</span><br><span style="color: hsl(0, 100%, 40%);">- self.host = "127.0.0.5"</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def cli_exec(self, command):</span><br><span style="color: hsl(0, 100%, 40%);">- """Mock CLI execution/response"""</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string = ""</span><br><span style="color: hsl(0, 100%, 40%);">- if command == "sip show objects":</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string = "-= Peer objects: 4 static, 0 realtime, 0 autocreate =-\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: audio\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: 7002\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: 7001\ntype: peer\nobjflags: 0\nrefcount: 1\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: zoiper_01\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "-= Peer objects by IP =-\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: zoiper_01\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: audio\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: 7002\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "-= Registry objects: 0 =-\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "-= Dialog objects:\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: 2ec048aa4ed1239664f6408f0c5044c4@127.0.0.2:5060\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "type: dialog\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "objflags: 0\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "refcount: 2\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: 2ec048aa4ed1239664f6408f0c5044c5@127.0.0.2:5060\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "type: dialog\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "objflags: 0\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "refcount: 2\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- elif command == "sip show history 2ec048aa4ed1239664f6408f0c5044c4@127.0.0.2:5060":</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string = "* SIP Call\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "1. NewChan Channel SIP/ast1-00000002 - from 2ec048aa4ed1239664f6408f0c5044\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "2. TxReqRel INVITE / 102 INVITE - INVITE\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "3. Rx SIP/2.0 / 102 INVITE / 100 Trying\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "4. Rx SIP/2.0 / 102 INVITE / 200 OK\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "5. TxReq ACK / 102 ACK - ACK\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "6. Rx BYE / 102 BYE / sip:ast2@127.0.0.2:5060\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "7. RTCPaudio Quality:ssrc=28249381;themssrc=485141946;lp=0;rxjitter=0.000029\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "8. RTCPaudioJitter Quality:minrxjitter=0.000000;maxrxjitter=0.000000;avgrxjitter=0\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "9. RTCPaudioLoss Quality:minrxlost=0.000000;maxrxlost=0.000000;avgrxlost=0.00000\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "10. RTCPaudioRTT Quality:minrtt=0.000000;maxrtt=0.000000;avgrtt=0.000000;stdevrt\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "11. SchedDestroy 32000 ms\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "12. TxResp SIP/2.0 / 102 BYE - 200 OK\n"</span><br><span style="color: hsl(0, 100%, 40%);">- elif command == "sip show history 2ec048aa4ed1239664f6408f0c5044c5@127.0.0.2:5060":</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string = "* SIP Call\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "1. NewChan Channel SIP/ast1-00000002 - from 2ec048aa4ed1239664f6408f0c5044\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "2. TxReqRel INVITE / 102 INVITE - INVITE\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "3. Rx SIP/2.0 / 102 INVITE / 100 Trying\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "4. Rx SIP/2.0 / 102 INVITE / 200 OK\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "5. TxReq ACK / 102 ACK - ACK\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "6. Rx BYE / 102 BYE / sip:ast2@127.0.0.2:5060\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "7. RTCPaudio Quality:ssrc=28249381;themssrc=485141946;lp=0;rxjitter=0.000029\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "8. RTCPaudioJitter Quality:minrxjitter=0.000000;maxrxjitter=0.000000;avgrxjitter=0\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "9. RTCPaudioLoss Quality:minrxlost=0.000000;maxrxlost=0.000000;avgrxlost=0.00000\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "10. RTCPaudioRTT Quality:minrtt=0.000000;maxrtt=0.000000;avgrtt=0.000000;stdevrt\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "11. SchedDestroy 32000 ms\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "12. TxResp SIP/2.0 / 102 BYE - 200 OK\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "13. Hangup Cause Normal Clearing\n"</span><br><span style="color: hsl(0, 100%, 40%);">- return ret_string</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-class AstMockObjectPostTestNoDialogsPass(object):</span><br><span style="color: hsl(0, 100%, 40%);">- """Mock out CLI execution from Asterisk instance</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- This mock object makes it appear as if there were no dialogs, which is okay</span><br><span style="color: hsl(0, 100%, 40%);">- """</span><br><span style="color: hsl(0, 100%, 40%);">- def __init__(self):</span><br><span style="color: hsl(0, 100%, 40%);">- """Constructor"""</span><br><span style="color: hsl(0, 100%, 40%);">- self.host = "127.0.0.4"</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def cli_exec(self, command):</span><br><span style="color: hsl(0, 100%, 40%);">- """Mock CLI execution/response"""</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string = ""</span><br><span style="color: hsl(0, 100%, 40%);">- if command == "sip show objects":</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string = "-= Peer objects: 4 static, 0 realtime, 0 autocreate =-\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: audio\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: 7002\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: 7001\ntype: peer\nobjflags: 0\nrefcount: 1\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: zoiper_01\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "-= Peer objects by IP =-\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: zoiper_01\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: audio\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: 7002\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "-= Registry objects: 0 =-\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "-= Dialog objects:\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- return ret_string</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-class AstMockObjectPostTestPass(object):</span><br><span style="color: hsl(0, 100%, 40%);">- """Mock out CLI execution from Asterisk instance</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- This mock object provides two dialogs with acceptable history</span><br><span style="color: hsl(0, 100%, 40%);">- """</span><br><span style="color: hsl(0, 100%, 40%);">- def __init__(self):</span><br><span style="color: hsl(0, 100%, 40%);">- """Constructor"""</span><br><span style="color: hsl(0, 100%, 40%);">- self.host = "127.0.0.3"</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def cli_exec(self, command):</span><br><span style="color: hsl(0, 100%, 40%);">- """Mock CLI execution/response"""</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string = ""</span><br><span style="color: hsl(0, 100%, 40%);">- if command == "sip show objects":</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string = "-= Peer objects: 4 static, 0 realtime, 0 autocreate =-\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: audio\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: 7002\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: 7001\ntype: peer\nobjflags: 0\nrefcount: 1\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: zoiper_01\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "-= Peer objects by IP =-\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: zoiper_01\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: audio\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: 7002\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "-= Registry objects: 0 =-\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "-= Dialog objects:\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: 2ec048aa4ed1239664f6408f0c5044c4@127.0.0.2:5060\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "type: dialog\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "objflags: 0\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "refcount: 2\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: 2ec048aa4ed1239664f6408f0c5044c5@127.0.0.2:5060\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "type: dialog\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "objflags: 0\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "refcount: 2\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- elif command == "sip show history 2ec048aa4ed1239664f6408f0c5044c4@127.0.0.2:5060":</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string = "* SIP Call\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "1. NewChan Channel SIP/ast1-00000002 - from 2ec048aa4ed1239664f6408f0c5044\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "2. TxReqRel INVITE / 102 INVITE - INVITE\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "3. Rx SIP/2.0 / 102 INVITE / 100 Trying\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "4. Rx SIP/2.0 / 102 INVITE / 200 OK\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "5. TxReq ACK / 102 ACK - ACK\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "6. Rx BYE / 102 BYE / sip:ast2@127.0.0.2:5060\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "7. RTCPaudio Quality:ssrc=28249381;themssrc=485141946;lp=0;rxjitter=0.000029\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "8. RTCPaudioJitter Quality:minrxjitter=0.000000;maxrxjitter=0.000000;avgrxjitter=0\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "9. RTCPaudioLoss Quality:minrxlost=0.000000;maxrxlost=0.000000;avgrxlost=0.00000\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "10. RTCPaudioRTT Quality:minrtt=0.000000;maxrtt=0.000000;avgrtt=0.000000;stdevrt\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "11. SchedDestroy 32000 ms\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "12. TxResp SIP/2.0 / 102 BYE - 200 OK\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "13. Hangup Cause Normal Clearing\n"</span><br><span style="color: hsl(0, 100%, 40%);">- elif command == "sip show history 2ec048aa4ed1239664f6408f0c5044c5@127.0.0.2:5060":</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string = "* SIP Call\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "1. NewChan Channel SIP/ast1-00000002 - from 2ec048aa4ed1239664f6408f0c5044\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "2. TxReqRel INVITE / 102 INVITE - INVITE\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "3. Rx SIP/2.0 / 102 INVITE / 100 Trying\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "4. Rx SIP/2.0 / 102 INVITE / 200 OK\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "5. TxReq ACK / 102 ACK - ACK\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "6. Rx BYE / 102 BYE / sip:ast2@127.0.0.2:5060\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "7. RTCPaudio Quality:ssrc=28249381;themssrc=485141946;lp=0;rxjitter=0.000029\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "8. RTCPaudioJitter Quality:minrxjitter=0.000000;maxrxjitter=0.000000;avgrxjitter=0\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "9. RTCPaudioLoss Quality:minrxlost=0.000000;maxrxlost=0.000000;avgrxlost=0.00000\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "10. RTCPaudioRTT Quality:minrtt=0.000000;maxrtt=0.000000;avgrtt=0.000000;stdevrt\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "11. SchedDestroy 32000 ms\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "12. TxResp SIP/2.0 / 102 BYE - 200 OK\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "13. Hangup Cause Normal Clearing\n"</span><br><span style="color: hsl(0, 100%, 40%);">- return ret_string</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-class AstMockObjectPreTestFail(object):</span><br><span style="color: hsl(0, 100%, 40%);">- """Mock out CLI execution from Asterisk instance</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- This mock object provides history during a pre-test call, which is wrong</span><br><span style="color: hsl(0, 100%, 40%);">- """</span><br><span style="color: hsl(0, 100%, 40%);">- def __init__(self):</span><br><span style="color: hsl(0, 100%, 40%);">- """Constructor"""</span><br><span style="color: hsl(0, 100%, 40%);">- self.host = "127.0.0.2"</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def cli_exec(self, command):</span><br><span style="color: hsl(0, 100%, 40%);">- """Mock CLI execution/response"""</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string = ""</span><br><span style="color: hsl(0, 100%, 40%);">- if command == "sip show objects":</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string = "-= Peer objects: 4 static, 0 realtime, 0 autocreate =-\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: audio\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: 7002\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: 7001\ntype: peer\nobjflags: 0\nrefcount: 1\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: zoiper_01\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "-= Peer objects by IP =-\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: zoiper_01\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: audio\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: 7002\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "-= Registry objects: 0 =-\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "-= Dialog objects:\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: 2ec048aa4ed1239664f6408f0c5044c4@127.0.0.2:5060\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "type: dialog\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "objflags: 0\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "refcount: 2\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- elif command == "sip show history 2ec048aa4ed1239664f6408f0c5044c4@127.0.0.2:5060":</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string = "* SIP Call\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "1. NewChan Channel SIP/ast1-00000002 - from 2ec048aa4ed1239664f6408f0c5044\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "2. TxReqRel INVITE / 102 INVITE - INVITE\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "3. Rx SIP/2.0 / 102 INVITE / 100 Trying\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "4. Rx SIP/2.0 / 102 INVITE / 200 OK\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "5. TxReq ACK / 102 ACK - ACK\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "6. Rx BYE / 102 BYE / sip:ast2@127.0.0.2:5060\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "7. RTCPaudio Quality:ssrc=28249381;themssrc=485141946;lp=0;rxjitter=0.000029\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "8. RTCPaudioJitter Quality:minrxjitter=0.000000;maxrxjitter=0.000000;avgrxjitter=0\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "9. RTCPaudioLoss Quality:minrxlost=0.000000;maxrxlost=0.000000;avgrxlost=0.00000\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "10. RTCPaudioRTT Quality:minrtt=0.000000;maxrtt=0.000000;avgrtt=0.000000;stdevrt\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "11. SchedDestroy 32000 ms\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "12. TxResp SIP/2.0 / 102 BYE - 200 OK\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "13. Hangup Cause Normal Clearing\n"</span><br><span style="color: hsl(0, 100%, 40%);">- return ret_string</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-class AstMockObjectPreTestPass(object):</span><br><span style="color: hsl(0, 100%, 40%);">- """Mock out CLI execution from Asterisk instance</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- This mock object provides no history during a pre-test call, which is the</span><br><span style="color: hsl(0, 100%, 40%);">- expected state</span><br><span style="color: hsl(0, 100%, 40%);">- """</span><br><span style="color: hsl(0, 100%, 40%);">- def __init__(self):</span><br><span style="color: hsl(0, 100%, 40%);">- """Constructor"""</span><br><span style="color: hsl(0, 100%, 40%);">- self.host = "127.0.0.1"</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def cli_exec(self, command):</span><br><span style="color: hsl(0, 100%, 40%);">- """Mock CLI execution/response"""</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string = ""</span><br><span style="color: hsl(0, 100%, 40%);">- if command == "sip show objects":</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string = "-= Peer objects: 4 static, 0 realtime, 0 autocreate =-\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: audio\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: 7002\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: 7001\ntype: peer\nobjflags: 0\nrefcount: 1\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: zoiper_01\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "-= Peer objects by IP =-\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: zoiper_01\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: audio\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "name: 7002\ntype: peer\nobjflags: 0\nrefcount: 3\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "-= Registry objects: 0 =-\n\n"</span><br><span style="color: hsl(0, 100%, 40%);">- ret_string += "-= Dialog objects:\n"</span><br><span style="color: hsl(0, 100%, 40%);">- elif command == "sip show history":</span><br><span style="color: hsl(0, 100%, 40%);">- return "\n"</span><br><span style="color: hsl(0, 100%, 40%);">- return ret_string</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-class SipDialogTestConditionUnitTest(unittest.TestCase):</span><br><span style="color: hsl(0, 100%, 40%);">- """Unit tests for SipDialogTestCondition objects"""</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_pre_test_pass(self):</span><br><span style="color: hsl(0, 100%, 40%);">- """Verify that acceptable pre-test output passes"""</span><br><span style="color: hsl(0, 100%, 40%);">- ast = AstMockObjectPreTestPass()</span><br><span style="color: hsl(0, 100%, 40%);">- obj = SipDialogPreTestCondition(TestConfig())</span><br><span style="color: hsl(0, 100%, 40%);">- obj.register_asterisk_instance(ast)</span><br><span style="color: hsl(0, 100%, 40%);">- obj.evaluate()</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.get_status(), 'Passed')</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_pre_test_fail(self):</span><br><span style="color: hsl(0, 100%, 40%);">- """Verify that unacceptable pre-test output fails"""</span><br><span style="color: hsl(0, 100%, 40%);">- ast = AstMockObjectPreTestFail()</span><br><span style="color: hsl(0, 100%, 40%);">- obj = SipDialogPreTestCondition(TestConfig())</span><br><span style="color: hsl(0, 100%, 40%);">- obj.register_asterisk_instance(ast)</span><br><span style="color: hsl(0, 100%, 40%);">- obj.evaluate()</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.get_status(), 'Failed')</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_pre_test_fail_multi_asterisk(self):</span><br><span style="color: hsl(0, 100%, 40%);">- """Verify that pre-test output from multiple sources fails when one</span><br><span style="color: hsl(0, 100%, 40%);">- of those sources is bad"""</span><br><span style="color: hsl(0, 100%, 40%);">- ast1 = AstMockObjectPreTestFail()</span><br><span style="color: hsl(0, 100%, 40%);">- ast2 = AstMockObjectPreTestPass()</span><br><span style="color: hsl(0, 100%, 40%);">- obj = SipDialogPreTestCondition(TestConfig())</span><br><span style="color: hsl(0, 100%, 40%);">- obj.register_asterisk_instance(ast1)</span><br><span style="color: hsl(0, 100%, 40%);">- obj.register_asterisk_instance(ast2)</span><br><span style="color: hsl(0, 100%, 40%);">- obj.evaluate()</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.get_status(), 'Failed')</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_post_test_pass(self):</span><br><span style="color: hsl(0, 100%, 40%);">- """Verify nominal post-test output"""</span><br><span style="color: hsl(0, 100%, 40%);">- ast = AstMockObjectPostTestPass()</span><br><span style="color: hsl(0, 100%, 40%);">- obj = SipDialogPostTestCondition(TestConfigWithHistory())</span><br><span style="color: hsl(0, 100%, 40%);">- obj.register_asterisk_instance(ast)</span><br><span style="color: hsl(0, 100%, 40%);">- obj.evaluate()</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.get_status(), 'Passed')</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_post_test_no_dialog_pass(self):</span><br><span style="color: hsl(0, 100%, 40%);">- """Verify nominal post-test output with no dialogs passes"""</span><br><span style="color: hsl(0, 100%, 40%);">- ast = AstMockObjectPostTestNoDialogsPass()</span><br><span style="color: hsl(0, 100%, 40%);">- obj = SipDialogPostTestCondition(TestConfig())</span><br><span style="color: hsl(0, 100%, 40%);">- obj.register_asterisk_instance(ast)</span><br><span style="color: hsl(0, 100%, 40%);">- obj.evaluate()</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.get_status(), 'Passed')</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_post_test_no_hangup_fail(self):</span><br><span style="color: hsl(0, 100%, 40%);">- """Verify no hangup detection is caught and results in a failure"""</span><br><span style="color: hsl(0, 100%, 40%);">- ast = AstMockObjectPostTestNoHangupFail()</span><br><span style="color: hsl(0, 100%, 40%);">- obj = SipDialogPostTestCondition(TestConfigWithHistory())</span><br><span style="color: hsl(0, 100%, 40%);">- obj.register_asterisk_instance(ast)</span><br><span style="color: hsl(0, 100%, 40%);">- obj.evaluate()</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.get_status(), 'Failed')</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_post_test_no_destruction_fail(self):</span><br><span style="color: hsl(0, 100%, 40%);">- """Verify no destruction is caught and results in a failure"""</span><br><span style="color: hsl(0, 100%, 40%);">- ast = AstMockObjectPostTestNoDestructionFail()</span><br><span style="color: hsl(0, 100%, 40%);">- obj = SipDialogPostTestCondition(TestConfigWithHistory())</span><br><span style="color: hsl(0, 100%, 40%);">- obj.register_asterisk_instance(ast)</span><br><span style="color: hsl(0, 100%, 40%);">- obj.evaluate()</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.get_status(), 'Failed')</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_post_test_multi_asterisk_fail(self):</span><br><span style="color: hsl(0, 100%, 40%);">- """Test multiple instances of Asterisk where a single failure causes</span><br><span style="color: hsl(0, 100%, 40%);">- a failure in the overall result"""</span><br><span style="color: hsl(0, 100%, 40%);">- ast1 = AstMockObjectPostTestNoHangupFail()</span><br><span style="color: hsl(0, 100%, 40%);">- ast2 = AstMockObjectPostTestNoDestructionFail()</span><br><span style="color: hsl(0, 100%, 40%);">- ast3 = AstMockObjectPostTestNoDialogsPass()</span><br><span style="color: hsl(0, 100%, 40%);">- ast4 = AstMockObjectPostTestPass()</span><br><span style="color: hsl(0, 100%, 40%);">- obj = SipDialogPostTestCondition(TestConfigWithHistory())</span><br><span style="color: hsl(0, 100%, 40%);">- obj.register_asterisk_instance(ast1)</span><br><span style="color: hsl(0, 100%, 40%);">- obj.register_asterisk_instance(ast2)</span><br><span style="color: hsl(0, 100%, 40%);">- obj.register_asterisk_instance(ast3)</span><br><span style="color: hsl(0, 100%, 40%);">- obj.register_asterisk_instance(ast4)</span><br><span style="color: hsl(0, 100%, 40%);">- obj.evaluate()</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(obj.get_status(), 'Failed')</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-def main():</span><br><span style="color: hsl(0, 100%, 40%);">- """Execute the unit tests"""</span><br><span style="color: hsl(0, 100%, 40%);">- logging.basicConfig(level=logging.DEBUG)</span><br><span style="color: hsl(0, 100%, 40%);">- unittest.main()</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-if __name__ == "__main__":</span><br><span style="color: hsl(0, 100%, 40%);">- main()</span><br><span>diff --git a/lib/python/asterisk/sipp.py b/lib/python/asterisk/sipp.py</span><br><span>index b84965e..540a544 100644</span><br><span>--- a/lib/python/asterisk/sipp.py</span><br><span>+++ b/lib/python/asterisk/sipp.py</span><br><span>@@ -10,12 +10,12 @@</span><br><span> """</span><br><span> </span><br><span> import logging</span><br><span style="color: hsl(0, 100%, 40%);">-import test_suite_utils</span><br><span style="color: hsl(120, 100%, 40%);">+from . import test_suite_utils</span><br><span> </span><br><span> from abc import ABCMeta, abstractmethod</span><br><span> from twisted.internet import reactor, defer, protocol, error</span><br><span style="color: hsl(0, 100%, 40%);">-from test_case import TestCase</span><br><span style="color: hsl(0, 100%, 40%);">-from utils_socket import get_available_port</span><br><span style="color: hsl(120, 100%, 40%);">+from .test_case import TestCase</span><br><span style="color: hsl(120, 100%, 40%);">+from .utils_socket import get_available_port</span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span> </span><br><span>@@ -495,7 +495,7 @@</span><br><span> def outReceived(self, data):</span><br><span> """Override of ProcessProtocol.outReceived"""</span><br><span> LOGGER.debug("Received from SIPp scenario %s: %s" % (self._name, data))</span><br><span style="color: hsl(0, 100%, 40%);">- self.output += data</span><br><span style="color: hsl(120, 100%, 40%);">+ self.output += data.decode('utf-8', 'ignore')</span><br><span> </span><br><span> def connectionMade(self):</span><br><span> """Override of ProcessProtocol.connectionMade"""</span><br><span>diff --git a/lib/python/asterisk/sippversion.py b/lib/python/asterisk/sippversion.py</span><br><span>index b1110fc..f942e9c 100644</span><br><span>--- a/lib/python/asterisk/sippversion.py</span><br><span>+++ b/lib/python/asterisk/sippversion.py</span><br><span>@@ -1,4 +1,3 @@</span><br><span style="color: hsl(0, 100%, 40%);">-#!/usr/bin/env python</span><br><span> """SIPp Version String Handling</span><br><span> </span><br><span> Copyright (C) 2010, Digium, Inc.</span><br><span>@@ -9,11 +8,7 @@</span><br><span> """</span><br><span> </span><br><span> import subprocess</span><br><span style="color: hsl(0, 100%, 40%);">-import sys</span><br><span style="color: hsl(0, 100%, 40%);">-import unittest</span><br><span style="color: hsl(0, 100%, 40%);">-sys.path.append("lib/python")</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-import test_suite_utils</span><br><span style="color: hsl(120, 100%, 40%);">+from . import test_suite_utils</span><br><span> </span><br><span> </span><br><span> class SIPpVersion:</span><br><span>@@ -48,8 +43,9 @@</span><br><span> except OSError:</span><br><span> return</span><br><span> for line in sipp_process.stdout:</span><br><span style="color: hsl(0, 100%, 40%);">- if line.strip().startswith('SIPp '):</span><br><span style="color: hsl(0, 100%, 40%);">- sipp = line.strip()[5:]</span><br><span style="color: hsl(120, 100%, 40%);">+ line = line.decode('utf-8').strip()</span><br><span style="color: hsl(120, 100%, 40%);">+ if line.startswith('SIPp '):</span><br><span style="color: hsl(120, 100%, 40%);">+ sipp = line[5:]</span><br><span> sipp = sipp.split(',', 1)</span><br><span> sipp = sipp[0].split('-', 1)</span><br><span> version = sipp[0]</span><br><span>@@ -88,7 +84,7 @@</span><br><span> </span><br><span> def __cmp__(self, other):</span><br><span> """Compare two SIPpVersion instances against each other"""</span><br><span style="color: hsl(0, 100%, 40%);">- return cmp(int(self), int(other))</span><br><span style="color: hsl(120, 100%, 40%);">+ return (int(self) > int(other)) - (int(self) < int(other))</span><br><span> </span><br><span> def __ne__(self, other):</span><br><span> """Determine if this SIPpVersion instance is not equal to another"""</span><br><span>@@ -106,6 +102,14 @@</span><br><span> return True</span><br><span> return False</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ def __le__(self, other):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Determine if this SIPpVersion instance is less than or equal to another"""</span><br><span style="color: hsl(120, 100%, 40%);">+ return int(self) <= int(other)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ def __lt__(self, other):</span><br><span style="color: hsl(120, 100%, 40%);">+ """Determine if this SIPpVersion instance is less than another"""</span><br><span style="color: hsl(120, 100%, 40%);">+ return int(self) < int(other)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> def __parse_version(self, version):</span><br><span> """Parse the version string returned from SIPp"""</span><br><span> self.version_str = version</span><br><span>@@ -124,215 +128,3 @@</span><br><span> self.tls = True</span><br><span> if value.find("PCAP") > -1:</span><br><span> self.pcap = True</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-class SIPpVersionTests(unittest.TestCase):</span><br><span style="color: hsl(0, 100%, 40%);">- def test_version(self):</span><br><span style="color: hsl(0, 100%, 40%);">- v = SIPpVersion("v3.2", None)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(str(v), "v3.2")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(v.concept, "v3")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(v.major, "2")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(v.minor, None)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertFalse(v.tls)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertFalse(v.pcap)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_version2(self):</span><br><span style="color: hsl(0, 100%, 40%);">- v = SIPpVersion("v2.0.1", None)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(str(v), "v2.0.1")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(v.concept, "v2")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(v.major, "0")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(v.minor, "1")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertFalse(v.tls)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertFalse(v.pcap)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_version3(self):</span><br><span style="color: hsl(0, 100%, 40%);">- v = SIPpVersion("v3.1", "TLS")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(str(v), "v3.1-TLS")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(v.concept, "v3")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(v.major, "1")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(v.minor, None)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(v.tls)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertFalse(v.pcap)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_version4(self):</span><br><span style="color: hsl(0, 100%, 40%);">- v = SIPpVersion("v2.0.1", "TLS-PCAP")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(str(v), "v2.0.1-TLS-PCAP")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(v.concept, "v2")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(v.major, "0")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(v.minor, "1")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(v.tls)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(v.pcap)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_version5(self):</span><br><span style="color: hsl(0, 100%, 40%);">- v = SIPpVersion("v3.2", "PCAP")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(str(v), "v3.2-PCAP")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(v.concept, "v3")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(v.major, "2")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(v.minor, None)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertFalse(v.tls)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(v.pcap)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_version6(self):</span><br><span style="color: hsl(0, 100%, 40%);">- v = SIPpVersion(None, "PCAP")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(str(v), "PCAP")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(v.concept, None)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(v.major, None)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(v.minor, None)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertFalse(v.tls)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(v.pcap)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_version7(self):</span><br><span style="color: hsl(0, 100%, 40%);">- v = SIPpVersion(None, "TLS")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(str(v), "TLS")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(v.concept, None)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(v.major, None)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(v.minor, None)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(v.tls)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertFalse(v.pcap)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_version8(self):</span><br><span style="color: hsl(0, 100%, 40%);">- v = SIPpVersion(None, "TLS-PCAP")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(str(v), "TLS-PCAP")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(v.concept, None)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(v.major, None)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertEqual(v.minor, None)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(v.tls)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(v.pcap)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_cmp(self):</span><br><span style="color: hsl(0, 100%, 40%);">- v1 = SIPpVersion("v3.2", None)</span><br><span style="color: hsl(0, 100%, 40%);">- v2 = SIPpVersion("v3.1", None)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(v1 > v2)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_cmp2(self):</span><br><span style="color: hsl(0, 100%, 40%);">- v1 = SIPpVersion("v2.0.1", None)</span><br><span style="color: hsl(0, 100%, 40%);">- v2 = SIPpVersion("v3.1", None)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(v1 < v2)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_cmp3(self):</span><br><span style="color: hsl(0, 100%, 40%);">- v1 = SIPpVersion("v3.1", None)</span><br><span style="color: hsl(0, 100%, 40%);">- v2 = SIPpVersion("v3.1", None)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(v1 == v2)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_cmp4(self):</span><br><span style="color: hsl(0, 100%, 40%);">- v1 = SIPpVersion("v3.1", None)</span><br><span style="color: hsl(0, 100%, 40%);">- v2 = SIPpVersion("v3.1", None)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertFalse(v1 != v2)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_cmp5(self):</span><br><span style="color: hsl(0, 100%, 40%);">- v1 = SIPpVersion("v3.1", "TLS")</span><br><span style="color: hsl(0, 100%, 40%);">- v2 = SIPpVersion("v3.1", "TLS")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(v1 == v2)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_cmp6(self):</span><br><span style="color: hsl(0, 100%, 40%);">- v1 = SIPpVersion(None, "TLS")</span><br><span style="color: hsl(0, 100%, 40%);">- v2 = SIPpVersion(None, "TLS")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(v1 == v2)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_cmp7(self):</span><br><span style="color: hsl(0, 100%, 40%);">- v1 = SIPpVersion("v2.0.1", None)</span><br><span style="color: hsl(0, 100%, 40%);">- v2 = SIPpVersion("v2.0.1", None)</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(v1 == v2)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_cmp8(self):</span><br><span style="color: hsl(0, 100%, 40%);">- v1 = SIPpVersion("v3.2", "TLS")</span><br><span style="color: hsl(0, 100%, 40%);">- v2 = SIPpVersion("v3.2", "PCAP")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(v1 != v2)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_cmp9(self):</span><br><span style="color: hsl(0, 100%, 40%);">- v1 = SIPpVersion(None, "TLS")</span><br><span style="color: hsl(0, 100%, 40%);">- v2 = SIPpVersion(None, "PCAP")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(v1 != v2)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_cmp10(self):</span><br><span style="color: hsl(0, 100%, 40%);">- v1 = SIPpVersion("v3.2", "TLS")</span><br><span style="color: hsl(0, 100%, 40%);">- v2 = SIPpVersion("v3.2", "PCAP")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertFalse(v1 == v2)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_cmp11(self):</span><br><span style="color: hsl(0, 100%, 40%);">- v1 = SIPpVersion(None, "TLS")</span><br><span style="color: hsl(0, 100%, 40%);">- v2 = SIPpVersion(None, "PCAP")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertFalse(v1 == v2)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_cmp12(self):</span><br><span style="color: hsl(0, 100%, 40%);">- v1 = SIPpVersion("v3.2", "TLS-PCAP")</span><br><span style="color: hsl(0, 100%, 40%);">- v2 = SIPpVersion("v3.2", "TLS")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(v1 >= v2)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_cmp13(self):</span><br><span style="color: hsl(0, 100%, 40%);">- v1 = SIPpVersion("v3.2", "TLS-PCAP")</span><br><span style="color: hsl(0, 100%, 40%);">- v2 = SIPpVersion(None, "TLS")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(v1 >= v2)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_cmp14(self):</span><br><span style="color: hsl(0, 100%, 40%);">- v1 = SIPpVersion("v3.2", "TLS-PCAP")</span><br><span style="color: hsl(0, 100%, 40%);">- v2 = SIPpVersion("v3.2", "PCAP")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(v1 >= v2)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_cmp15(self):</span><br><span style="color: hsl(0, 100%, 40%);">- v1 = SIPpVersion("v3.2", "TLS-PCAP")</span><br><span style="color: hsl(0, 100%, 40%);">- v2 = SIPpVersion(None, "PCAP")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(v1 >= v2)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_cmp16(self):</span><br><span style="color: hsl(0, 100%, 40%);">- v1 = SIPpVersion("v3.2", "TLS-PCAP")</span><br><span style="color: hsl(0, 100%, 40%);">- v2 = SIPpVersion("v3.2", "TLS")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(v1 != v2)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_cmp17(self):</span><br><span style="color: hsl(0, 100%, 40%);">- v1 = SIPpVersion("v3.2", "TLS-PCAP")</span><br><span style="color: hsl(0, 100%, 40%);">- v2 = SIPpVersion(None, "TLS")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(v1 != v2)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_cmp18(self):</span><br><span style="color: hsl(0, 100%, 40%);">- v1 = SIPpVersion("v3.2", "TLS-PCAP")</span><br><span style="color: hsl(0, 100%, 40%);">- v2 = SIPpVersion("v3.2", "TLS")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertFalse(v1 == v2)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_cmp19(self):</span><br><span style="color: hsl(0, 100%, 40%);">- v1 = SIPpVersion("v3.2", "TLS-PCAP")</span><br><span style="color: hsl(0, 100%, 40%);">- v2 = SIPpVersion(None, "TLS")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertFalse(v1 == v2)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_cmp20(self):</span><br><span style="color: hsl(0, 100%, 40%);">- v1 = SIPpVersion("v3.1", "PCAP")</span><br><span style="color: hsl(0, 100%, 40%);">- v2 = SIPpVersion("v3.0", "TLS")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(v1 > v2)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_cmp21(self):</span><br><span style="color: hsl(0, 100%, 40%);">- v1 = SIPpVersion("v3.2", "TLS-PCAP")</span><br><span style="color: hsl(0, 100%, 40%);">- v2 = SIPpVersion("v2.0.1", "PCAP")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(v1 >= v2)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_cmp22(self):</span><br><span style="color: hsl(0, 100%, 40%);">- v1 = SIPpVersion("v3.1", "TLS")</span><br><span style="color: hsl(0, 100%, 40%);">- v2 = SIPpVersion("v3.1", "PCAP")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertFalse(v1 > v2)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_cmp23(self):</span><br><span style="color: hsl(0, 100%, 40%);">- v1 = SIPpVersion("v3.1", "TLS")</span><br><span style="color: hsl(0, 100%, 40%);">- v2 = SIPpVersion("v3.1", "PCAP")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertFalse(v1 < v2)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_cmp24(self):</span><br><span style="color: hsl(0, 100%, 40%);">- v1 = SIPpVersion("v3.2", "TLS")</span><br><span style="color: hsl(0, 100%, 40%);">- v2 = SIPpVersion("v3.1", "TLS-PCAP")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(v1 >= v2)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_cmp25(self):</span><br><span style="color: hsl(0, 100%, 40%);">- v1 = SIPpVersion("v3.1", "TLS-PCAP")</span><br><span style="color: hsl(0, 100%, 40%);">- v2 = SIPpVersion("v3.2", "PCAP")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertTrue(v1 <= v2)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- def test_cmp26(self):</span><br><span style="color: hsl(0, 100%, 40%);">- v1 = SIPpVersion("v2.0.1", "TLS-PCAP")</span><br><span style="color: hsl(0, 100%, 40%);">- v2 = SIPpVersion("v3.0", "TLS")</span><br><span style="color: hsl(0, 100%, 40%);">- self.assertFalse(v1 >= v2)</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-def main():</span><br><span style="color: hsl(0, 100%, 40%);">- unittest.main()</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-if __name__ == "__main__":</span><br><span style="color: hsl(0, 100%, 40%);">- main()</span><br><span>diff --git a/lib/python/asterisk/syncami.py b/lib/python/asterisk/syncami.py</span><br><span>index 031ae99..5482400 100644</span><br><span>--- a/lib/python/asterisk/syncami.py</span><br><span>+++ b/lib/python/asterisk/syncami.py</span><br><span>@@ -8,7 +8,13 @@</span><br><span> the GNU General Public License Version 2.</span><br><span> """</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-from urllib import urlencode</span><br><span style="color: hsl(120, 100%, 40%);">+try:</span><br><span style="color: hsl(120, 100%, 40%);">+ # python 2 import</span><br><span style="color: hsl(120, 100%, 40%);">+ from urllib import urlencode</span><br><span style="color: hsl(120, 100%, 40%);">+except:</span><br><span style="color: hsl(120, 100%, 40%);">+ # python 3 import</span><br><span style="color: hsl(120, 100%, 40%);">+ from urllib.parse import urlencode</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> from email.parser import HeaderParser</span><br><span> try:</span><br><span> from httplib import *</span><br><span>@@ -87,7 +93,7 @@</span><br><span> if res.status != 200:</span><br><span> raise InvalidAMIResponse(res)</span><br><span> self.cookie = res.getheader('set-cookie', None)</span><br><span style="color: hsl(0, 100%, 40%);">- data = res.read()</span><br><span style="color: hsl(120, 100%, 40%);">+ data = res.read().decode('utf-8')</span><br><span> parser = HeaderParser()</span><br><span> </span><br><span> return parser.parsestr(data)</span><br><span>diff --git a/lib/python/asterisk/test_case.py b/lib/python/asterisk/test_case.py</span><br><span>index 80321f7..7bf6d16 100644</span><br><span>--- a/lib/python/asterisk/test_case.py</span><br><span>+++ b/lib/python/asterisk/test_case.py</span><br><span>@@ -19,9 +19,9 @@</span><br><span> from twisted.python import log</span><br><span> from starpy import manager, fastagi</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-from asterisk import Asterisk</span><br><span style="color: hsl(0, 100%, 40%);">-from test_config import TestConfig</span><br><span style="color: hsl(0, 100%, 40%);">-from test_conditions import TestConditionController</span><br><span style="color: hsl(120, 100%, 40%);">+from .asterisk import Asterisk</span><br><span style="color: hsl(120, 100%, 40%);">+from .test_config import TestConfig</span><br><span style="color: hsl(120, 100%, 40%);">+from .test_conditions import TestConditionController</span><br><span> </span><br><span> </span><br><span> try:</span><br><span>@@ -45,12 +45,12 @@</span><br><span> except:</span><br><span> msg = ("WARNING: failed to preserve existing loggers - some "</span><br><span> "logging statements may be missing")</span><br><span style="color: hsl(0, 100%, 40%);">- print msg</span><br><span style="color: hsl(120, 100%, 40%);">+ print(msg)</span><br><span> logging.config.fileConfig(config_file)</span><br><span> else:</span><br><span> msg = ("WARNING: no logging.conf file found; using default "</span><br><span> "configuration")</span><br><span style="color: hsl(0, 100%, 40%);">- print msg</span><br><span style="color: hsl(120, 100%, 40%);">+ print(msg)</span><br><span> logging.basicConfig(level=logging.DEBUG)</span><br><span> </span><br><span> root_logger = logging.getLogger()</span><br><span>@@ -102,7 +102,7 @@</span><br><span> # for the rasterisk CLI connection. As a quick fix, we hash the path</span><br><span> # using md5, to make it unique enough.</span><br><span> self.realbase = self.test_name.replace("tests/", "", 1)</span><br><span style="color: hsl(0, 100%, 40%);">- self.base = md5(self.realbase).hexdigest()</span><br><span style="color: hsl(120, 100%, 40%);">+ self.base = md5(self.realbase.encode()).hexdigest()</span><br><span> # We provide a symlink to it from a named path.</span><br><span> named_dir = os.path.join(Asterisk.test_suite_root, self.realbase)</span><br><span> try:</span><br><span>diff --git a/lib/python/asterisk/test_conditions.py b/lib/python/asterisk/test_conditions.py</span><br><span>index dbf36a7..7053465 100644</span><br><span>--- a/lib/python/asterisk/test_conditions.py</span><br><span>+++ b/lib/python/asterisk/test_conditions.py</span><br><span>@@ -19,7 +19,7 @@</span><br><span> import logging</span><br><span> import logging.config</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-from buildoptions import AsteriskBuildOptions</span><br><span style="color: hsl(120, 100%, 40%);">+from .buildoptions import AsteriskBuildOptions</span><br><span> from twisted.internet import defer</span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span>diff --git a/lib/python/asterisk/test_config.py b/lib/python/asterisk/test_config.py</span><br><span>index 8fdb884..6d2318d 100644</span><br><span>--- a/lib/python/asterisk/test_config.py</span><br><span>+++ b/lib/python/asterisk/test_config.py</span><br><span>@@ -18,12 +18,13 @@</span><br><span> </span><br><span> sys.path.append("lib/python")</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-import test_suite_utils</span><br><span style="color: hsl(120, 100%, 40%);">+from . import test_suite_utils</span><br><span style="color: hsl(120, 100%, 40%);">+from .test_runner import load_and_parse_module</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-from asterisk import Asterisk</span><br><span style="color: hsl(0, 100%, 40%);">-from buildoptions import AsteriskBuildOptions</span><br><span style="color: hsl(0, 100%, 40%);">-from sippversion import SIPpVersion</span><br><span style="color: hsl(0, 100%, 40%);">-from opensslversion import OpenSSLVersion</span><br><span style="color: hsl(120, 100%, 40%);">+from .asterisk import Asterisk</span><br><span style="color: hsl(120, 100%, 40%);">+from .buildoptions import AsteriskBuildOptions</span><br><span style="color: hsl(120, 100%, 40%);">+from .sippversion import SIPpVersion</span><br><span style="color: hsl(120, 100%, 40%);">+from .opensslversion import OpenSSLVersion</span><br><span> </span><br><span> </span><br><span> class TestConditionConfig(object):</span><br><span>@@ -70,14 +71,9 @@</span><br><span> </span><br><span> def make_condition(self):</span><br><span> """Build and return the condition object defined by this config"""</span><br><span style="color: hsl(0, 100%, 40%);">- parts = self.class_type_name.split('.')</span><br><span style="color: hsl(0, 100%, 40%);">- module = '.'.join(parts[:-1])</span><br><span style="color: hsl(0, 100%, 40%);">- if module != '':</span><br><span style="color: hsl(0, 100%, 40%);">- mod = __import__(module)</span><br><span style="color: hsl(0, 100%, 40%);">- for comp in parts[1:]:</span><br><span style="color: hsl(0, 100%, 40%);">- mod = getattr(mod, comp)</span><br><span style="color: hsl(0, 100%, 40%);">- obj = mod(self)</span><br><span style="color: hsl(0, 100%, 40%);">- return obj</span><br><span style="color: hsl(120, 100%, 40%);">+ mod = load_and_parse_module(self.class_type_name)</span><br><span style="color: hsl(120, 100%, 40%);">+ if mod is not None:</span><br><span style="color: hsl(120, 100%, 40%);">+ return mod(self)</span><br><span> return None</span><br><span> </span><br><span> </span><br><span>@@ -147,7 +143,7 @@</span><br><span> self.met = getattr(self, dir_method)()</span><br><span> found = True</span><br><span> if not found:</span><br><span style="color: hsl(0, 100%, 40%);">- print "Unknown custom dependency - '%s'" % self.name</span><br><span style="color: hsl(120, 100%, 40%);">+ print("Unknown custom dependency - '%s'" % self.name)</span><br><span> elif "asterisk" in dep:</span><br><span> if self.ast:</span><br><span> self.name = dep["asterisk"]</span><br><span>@@ -167,9 +163,9 @@</span><br><span> from test_case import PCAP_AVAILABLE</span><br><span> self.met = PCAP_AVAILABLE</span><br><span> else:</span><br><span style="color: hsl(0, 100%, 40%);">- print "Unknown dependency type specified:"</span><br><span style="color: hsl(120, 100%, 40%);">+ print("Unknown dependency type specified:")</span><br><span> for key in dep.keys():</span><br><span style="color: hsl(0, 100%, 40%);">- print key</span><br><span style="color: hsl(120, 100%, 40%);">+ print(key)</span><br><span> </span><br><span> def depend_remote(self):</span><br><span> """Check to see if we run against a remote instance of Asterisk"""</span><br><span>@@ -256,13 +252,13 @@</span><br><span> if self.asterisk_build_options:</span><br><span> return (self.asterisk_build_options.check_option(name))</span><br><span> else:</span><br><span style="color: hsl(0, 100%, 40%);">- print "Unable to evaluate build options: no build options found"</span><br><span style="color: hsl(120, 100%, 40%);">+ print("Unable to evaluate build options: no build options found")</span><br><span> return False</span><br><span> </span><br><span> def _find_asterisk_module(self, name):</span><br><span> """Determine if an Asterisk module exists"""</span><br><span> if not Dependency.ast:</span><br><span style="color: hsl(0, 100%, 40%);">- print "Unable to evaluate Asterisk modules: Asterisk not found"</span><br><span style="color: hsl(120, 100%, 40%);">+ print("Unable to evaluate Asterisk modules: Asterisk not found")</span><br><span> return False</span><br><span> </span><br><span> if Dependency.ast.original_astmoddir == "":</span><br><span>@@ -333,8 +329,8 @@</span><br><span> if self.config is not None and 'exclude-tests' in self.config:</span><br><span> self.excluded_tests = self.config['exclude-tests']</span><br><span> else:</span><br><span style="color: hsl(0, 100%, 40%);">- print ("WARNING - test configuration [%s] not found in "</span><br><span style="color: hsl(0, 100%, 40%);">- "config file" % self.test_configuration)</span><br><span style="color: hsl(120, 100%, 40%);">+ print("WARNING - test configuration [%s] not found in "</span><br><span style="color: hsl(120, 100%, 40%);">+ "config file" % self.test_configuration)</span><br><span> </span><br><span> def _process_testinfo(self):</span><br><span> """Process the test information block"""</span><br><span>@@ -381,8 +377,8 @@</span><br><span> self.config = yaml.load(config_file)</span><br><span> </span><br><span> if not self.config:</span><br><span style="color: hsl(0, 100%, 40%);">- print "ERROR: Failed to load configuration for test '%s'" % \</span><br><span style="color: hsl(0, 100%, 40%);">- self.test_name</span><br><span style="color: hsl(120, 100%, 40%);">+ print("ERROR: Failed to load configuration for test '%s'" %</span><br><span style="color: hsl(120, 100%, 40%);">+ self.test_name)</span><br><span> return</span><br><span> </span><br><span> self._process_global_settings()</span><br><span>@@ -408,8 +404,8 @@</span><br><span> matches = [cond_def for cond_def in self.condition_definitions</span><br><span> if cond_def['name'] == conf['name']]</span><br><span> if len(matches) != 1:</span><br><span style="color: hsl(0, 100%, 40%);">- print ("Unknown or too many matches for condition: " +</span><br><span style="color: hsl(0, 100%, 40%);">- conf['name'])</span><br><span style="color: hsl(120, 100%, 40%);">+ print("Unknown or too many matches for condition: " +</span><br><span style="color: hsl(120, 100%, 40%);">+ conf['name'])</span><br><span> else:</span><br><span> pre_cond = TestConditionConfig(conf, matches[0], "Pre")</span><br><span> post_cond = TestConditionConfig(conf, matches[0], "Post")</span><br><span>diff --git a/lib/python/asterisk/test_runner.py b/lib/python/asterisk/test_runner.py</span><br><span>old mode 100755</span><br><span>new mode 100644</span><br><span>index 644d117..d278e02</span><br><span>--- a/lib/python/asterisk/test_runner.py</span><br><span>+++ b/lib/python/asterisk/test_runner.py</span><br><span>@@ -1,4 +1,3 @@</span><br><span style="color: hsl(0, 100%, 40%);">-#!/usr/bin/env python</span><br><span> """Module that spawns and manages running a test</span><br><span> </span><br><span> This module provides an entry point, loading, and teardown of test</span><br><span>@@ -23,8 +22,6 @@</span><br><span> LOGGER = logging.getLogger('test_runner')</span><br><span> logging.basicConfig()</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-sys.path.append('lib/python')</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span> </span><br><span> class TestModuleFinder(object):</span><br><span> """Determines if a module is a test module that can be loaded"""</span><br><span>@@ -144,9 +141,18 @@</span><br><span> module_name = ".".join(parts[:-1])</span><br><span> </span><br><span> if not len(module_name):</span><br><span style="color: hsl(0, 100%, 40%);">- LOGGER.error("No module specified: %s" % module_name)</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGGER.error("No module specified: %s" % typename)</span><br><span> return None</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ if os.path.exists('lib/python/asterisk/%s.py' % module_name):</span><br><span style="color: hsl(120, 100%, 40%);">+ # This is convoluted but required. lib/python/asterisk packages</span><br><span style="color: hsl(120, 100%, 40%);">+ # must be loaded using absolute package names and 'asterisk' must</span><br><span style="color: hsl(120, 100%, 40%);">+ # be included in the list of parts. We cannot simply prepend</span><br><span style="color: hsl(120, 100%, 40%);">+ # type_name from the start because this blocks load of modules</span><br><span style="color: hsl(120, 100%, 40%);">+ # that are local to the test (add-test-to-search-path: 'True').</span><br><span style="color: hsl(120, 100%, 40%);">+ module_name = 'asterisk.' + module_name</span><br><span style="color: hsl(120, 100%, 40%);">+ parts = ['asterisk'] + parts</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> module = __import__(module_name)</span><br><span> for comp in parts[1:]:</span><br><span> module = getattr(module, comp)</span><br><span>diff --git a/lib/python/asterisk/test_suite_utils.py b/lib/python/asterisk/test_suite_utils.py</span><br><span>index d8ef541..84f54f5 100644</span><br><span>--- a/lib/python/asterisk/test_suite_utils.py</span><br><span>+++ b/lib/python/asterisk/test_suite_utils.py</span><br><span>@@ -1,4 +1,3 @@</span><br><span style="color: hsl(0, 100%, 40%);">-#! /usr/bin/env python</span><br><span> """Asterisk testsuite utils</span><br><span> </span><br><span> This module provides access to Asterisk testsuite utility</span><br><span>@@ -14,16 +13,20 @@</span><br><span> import os</span><br><span> import logging</span><br><span> import re</span><br><span style="color: hsl(120, 100%, 40%);">+import sys</span><br><span> </span><br><span> from os import close</span><br><span> from os import remove</span><br><span> from shutil import move</span><br><span> from tempfile import mkstemp</span><br><span style="color: hsl(0, 100%, 40%);">-from config import ConfigFile</span><br><span style="color: hsl(120, 100%, 40%);">+from .config import ConfigFile</span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span> </span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+if sys.version_info[0] == 3:</span><br><span style="color: hsl(120, 100%, 40%);">+ unicode = str</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> def which(program):</span><br><span> """Find the executable for a specified program</span><br><span> </span><br><span>@@ -100,7 +103,7 @@</span><br><span> elif isinstance(pattern, dict):</span><br><span> # Dict should match for every field in the pattern.</span><br><span> # extra fields in the message are fine.</span><br><span style="color: hsl(0, 100%, 40%);">- for key, value in pattern.iteritems():</span><br><span style="color: hsl(120, 100%, 40%);">+ for key, value in pattern.items():</span><br><span> to_check = message.get(key)</span><br><span> if to_check is None or not all_match(value, to_check):</span><br><span> return False</span><br><span>diff --git a/lib/python/asterisk/thread_test_condition.py b/lib/python/asterisk/thread_test_condition.py</span><br><span>index 595e3ce..c12321f 100644</span><br><span>--- a/lib/python/asterisk/thread_test_condition.py</span><br><span>+++ b/lib/python/asterisk/thread_test_condition.py</span><br><span>@@ -9,7 +9,7 @@</span><br><span> """</span><br><span> </span><br><span> import logging</span><br><span style="color: hsl(0, 100%, 40%);">-from test_conditions import TestCondition</span><br><span style="color: hsl(120, 100%, 40%);">+from .test_conditions import TestCondition</span><br><span> from twisted.internet import defer</span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span>diff --git a/lib/python/asterisk/voicemail.py b/lib/python/asterisk/voicemail.py</span><br><span>index 283650b..3c4c7d5 100644</span><br><span>--- a/lib/python/asterisk/voicemail.py</span><br><span>+++ b/lib/python/asterisk/voicemail.py</span><br><span>@@ -20,9 +20,9 @@</span><br><span> import time</span><br><span> import random</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-from config import ConfigFile</span><br><span style="color: hsl(0, 100%, 40%);">-from test_case import TestCase</span><br><span style="color: hsl(0, 100%, 40%);">-from test_state import TestState, TestStateController, FailureTestState</span><br><span style="color: hsl(120, 100%, 40%);">+from .config import ConfigFile</span><br><span style="color: hsl(120, 100%, 40%);">+from .test_case import TestCase</span><br><span style="color: hsl(120, 100%, 40%);">+from .test_state import TestState, TestStateController, FailureTestState</span><br><span> </span><br><span> sys.path.append("lib/python")</span><br><span> </span><br><span>diff --git a/lib/python/rlmi.py b/lib/python/rlmi.py</span><br><span>index 5e662a0..2abf19e 100644</span><br><span>--- a/lib/python/rlmi.py</span><br><span>+++ b/lib/python/rlmi.py</span><br><span>@@ -343,7 +343,7 @@</span><br><span> return None</span><br><span> @classmethod</span><br><span> def gds_reverse_node_mapping(cls, mapping):</span><br><span style="color: hsl(0, 100%, 40%);">- return dict(((v, k) for k, v in mapping.iteritems()))</span><br><span style="color: hsl(120, 100%, 40%);">+ return dict(((v, k) for k, v in mapping.items()))</span><br><span> </span><br><span> </span><br><span> #</span><br><span>diff --git a/lib/python/sip_message.py b/lib/python/sip_message.py</span><br><span>index 85cd9fd..087c760 100644</span><br><span>--- a/lib/python/sip_message.py</span><br><span>+++ b/lib/python/sip_message.py</span><br><span>@@ -118,7 +118,7 @@</span><br><span> def main():</span><br><span> msg = """INVITE sip:123@example.com SIP/2.0\r\nContact : \tTerry Wilson\r\n <terry@example.com>\r\nCall-ID:\r\n Whatever\r\nContact: New Contact\r\n\r\nData!!!!!"""</span><br><span> sipmsg = SIPMessage(msg)</span><br><span style="color: hsl(0, 100%, 40%);">- print sipmsg</span><br><span style="color: hsl(120, 100%, 40%);">+ print(sipmsg)</span><br><span> if sipmsg.get_header('CoNtact') is None:</span><br><span> return -1</span><br><span> if len(sipmsg.get_header_all('contact')) != 2:</span><br><span>diff --git a/run-local b/run-local</span><br><span>index 026a063..326ac50 100755</span><br><span>--- a/run-local</span><br><span>+++ b/run-local</span><br><span>@@ -75,7 +75,12 @@</span><br><span> LIBDIR=`dirname $HERE/astroot/usr/lib*/libasteriskssl.so`</span><br><span> export LD_LIBRARY_PATH="${LIBDIR}${LD_LIBRARY_PATH}"</span><br><span> set +e</span><br><span style="color: hsl(0, 100%, 40%);">- ./runtests.py "$@"</span><br><span style="color: hsl(120, 100%, 40%);">+ if test -n "$PYTHON"; then</span><br><span style="color: hsl(120, 100%, 40%);">+ # Use specific interpreter</span><br><span style="color: hsl(120, 100%, 40%);">+ $PYTHON ./runtests.py "$@"</span><br><span style="color: hsl(120, 100%, 40%);">+ else</span><br><span style="color: hsl(120, 100%, 40%);">+ ./runtests.py "$@"</span><br><span style="color: hsl(120, 100%, 40%);">+ fi</span><br><span> status=$?</span><br><span> rm "$AST_TEST_ROOT"</span><br><span> set -e</span><br><span>diff --git a/runtests.py b/runtests.py</span><br><span>index 1351a3c..eac88a1 100755</span><br><span>--- a/runtests.py</span><br><span>+++ b/runtests.py</span><br><span>@@ -111,7 +111,7 @@</span><br><span> </span><br><span> def stdout_print(self, msg):</span><br><span> self.stdout += msg + "\n"</span><br><span style="color: hsl(0, 100%, 40%);">- print msg</span><br><span style="color: hsl(120, 100%, 40%);">+ print(msg)</span><br><span> </span><br><span> def run(self):</span><br><span> self.passed = False</span><br><span>@@ -124,13 +124,14 @@</span><br><span> ]</span><br><span> </span><br><span> if not os.path.exists(cmd[0]):</span><br><span style="color: hsl(0, 100%, 40%);">- cmd = ["./lib/python/asterisk/test_runner.py",</span><br><span style="color: hsl(120, 100%, 40%);">+ cmd = [sys.executable,</span><br><span style="color: hsl(120, 100%, 40%);">+ "-m", "asterisk.test_runner",</span><br><span> "%s" % self.test_name]</span><br><span> if os.path.exists(cmd[0]) and os.access(cmd[0], os.X_OK):</span><br><span> if self.options.pcap:</span><br><span> os.environ['PCAP'] = "yes"</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- self.stdout_print("Running %s ..." % cmd)</span><br><span style="color: hsl(120, 100%, 40%);">+ self.stdout_print("Running %s ..." % self.test_name)</span><br><span> p = subprocess.Popen(cmd, stdout=subprocess.PIPE,</span><br><span> stderr=subprocess.STDOUT)</span><br><span> self.pid = p.pid</span><br><span>@@ -139,6 +140,7 @@</span><br><span> poll.register(p.stdout, select.POLLIN)</span><br><span> </span><br><span> timedout = False</span><br><span style="color: hsl(120, 100%, 40%);">+ has_unicode_error = False</span><br><span> try:</span><br><span> while (not abandon_test):</span><br><span> try:</span><br><span>@@ -148,20 +150,24 @@</span><br><span> except select.error as v:</span><br><span> if v[0] != errno.EINTR:</span><br><span> raise</span><br><span style="color: hsl(0, 100%, 40%);">- l = p.stdout.readline()</span><br><span style="color: hsl(120, 100%, 40%);">+ l = p.stdout.readline().decode('ascii', 'ignore').strip()</span><br><span> if not l:</span><br><span> break</span><br><span> self.stdout_print(l)</span><br><span style="color: hsl(120, 100%, 40%);">+ except UnicodeEncodeError:</span><br><span style="color: hsl(120, 100%, 40%);">+ self.stdout_print('Unicode error reading output from test!')</span><br><span style="color: hsl(120, 100%, 40%);">+ has_unicode_error = True</span><br><span style="color: hsl(120, 100%, 40%);">+ pass</span><br><span> except IOError:</span><br><span> pass</span><br><span> p.wait()</span><br><span> </span><br><span> # Sanitize p.returncode so it's always a boolean.</span><br><span style="color: hsl(0, 100%, 40%);">- did_pass = (p.returncode == 0 and not abandon_test)</span><br><span style="color: hsl(120, 100%, 40%);">+ did_pass = (p.returncode == 0 and not abandon_test and not has_unicode_error)</span><br><span> if did_pass and not self.test_config.expect_pass:</span><br><span> self.stdout_print("Test passed but was expected to fail.")</span><br><span> if not did_pass and not self.test_config.expect_pass:</span><br><span style="color: hsl(0, 100%, 40%);">- print "Test failed as expected."</span><br><span style="color: hsl(120, 100%, 40%);">+ print("Test failed as expected.")</span><br><span> </span><br><span> self.passed = (did_pass == self.test_config.expect_pass)</span><br><span> if abandon_test:</span><br><span>@@ -190,8 +196,8 @@</span><br><span> shutil.rmtree(absolute_dir)</span><br><span> os.remove(symlink_dir)</span><br><span> except:</span><br><span style="color: hsl(0, 100%, 40%);">- print "Unable to clean up directory for" \</span><br><span style="color: hsl(0, 100%, 40%);">- "test %s (non-fatal)" % self.test_name</span><br><span style="color: hsl(120, 100%, 40%);">+ print("Unable to clean up directory for"</span><br><span style="color: hsl(120, 100%, 40%);">+ "test %s (non-fatal)" % self.test_name)</span><br><span> </span><br><span> self.__parse_run_output(self.stdout)</span><br><span> if timedout:</span><br><span>@@ -202,13 +208,13 @@</span><br><span> status = 'passed'</span><br><span> else:</span><br><span> status = 'failed'</span><br><span style="color: hsl(0, 100%, 40%);">- pass_str = 'Test %s %s\n' % (cmd, status)</span><br><span style="color: hsl(0, 100%, 40%);">- print pass_str</span><br><span style="color: hsl(120, 100%, 40%);">+ pass_str = 'Test %s %s\n' % (self.test_name, status)</span><br><span style="color: hsl(120, 100%, 40%);">+ print(pass_str)</span><br><span> if self.options.syslog:</span><br><span> syslog.syslog(pass_str)</span><br><span> </span><br><span> else:</span><br><span style="color: hsl(0, 100%, 40%);">- print "FAILED TO EXECUTE %s, it must exist and be executable" % cmd</span><br><span style="color: hsl(120, 100%, 40%);">+ print("FAILED TO EXECUTE %s, it must exist and be executable" % cmd)</span><br><span> self.time = time.time() - start_time</span><br><span> </span><br><span> def _check_for_core(self):</span><br><span>@@ -237,7 +243,7 @@</span><br><span> debug_level = email_config.get('debug', 0)</span><br><span> </span><br><span> if not sender or len(recipients) == 0:</span><br><span style="color: hsl(0, 100%, 40%);">- print "--email-on-crash requires sender and 1+ recipients"</span><br><span style="color: hsl(120, 100%, 40%);">+ print("--email-on-crash requires sender and 1+ recipients")</span><br><span> return</span><br><span> </span><br><span> with open(dest_file_name, 'r') as bt_file:</span><br><span>@@ -255,12 +261,12 @@</span><br><span> send_email(smtp_server, sender, recipients, message,</span><br><span> debug=debug_level)</span><br><span> except Exception as exception:</span><br><span style="color: hsl(0, 100%, 40%);">- print "Failed to send email\nError: {0}".format(exception)</span><br><span style="color: hsl(120, 100%, 40%);">+ print("Failed to send email\nError: {0}".format(exception))</span><br><span> </span><br><span> def _archive_core_dumps(self, core_dumps):</span><br><span> for core in core_dumps:</span><br><span> if not os.path.exists(core):</span><br><span style="color: hsl(0, 100%, 40%);">- print "Unable to find core dump file %s, skipping" % core</span><br><span style="color: hsl(120, 100%, 40%);">+ print("Unable to find core dump file %s, skipping" % core)</span><br><span> continue</span><br><span> random_num = random.randint(0, 16000)</span><br><span> dest_dir = "./logs/%s" % self.test_relpath</span><br><span>@@ -275,36 +281,36 @@</span><br><span> "-ex", "thread apply all bt",</span><br><span> "--batch",</span><br><span> "-c", core]</span><br><span style="color: hsl(0, 100%, 40%);">- print "Running %s" % (" ".join(gdb_cmd),)</span><br><span style="color: hsl(120, 100%, 40%);">+ print("Running %s" % (" ".join(gdb_cmd),))</span><br><span> try:</span><br><span> res = subprocess.call(gdb_cmd, stdout=dest_file, stderr=subprocess.STDOUT)</span><br><span> if res != 0:</span><br><span style="color: hsl(0, 100%, 40%);">- print "error analyzing core dump; gdb exited with %d" % res</span><br><span style="color: hsl(120, 100%, 40%);">+ print("error analyzing core dump; gdb exited with %d" % res)</span><br><span> # Copy the backtrace over to the logs</span><br><span style="color: hsl(0, 100%, 40%);">- print "Archived backtrace: {0}".format(dest_file_name)</span><br><span style="color: hsl(120, 100%, 40%);">+ print("Archived backtrace: {0}".format(dest_file_name))</span><br><span> </span><br><span> if self.options.email_on_crash:</span><br><span> self._email_crash_report(dest_file_name)</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- except OSError, ose:</span><br><span style="color: hsl(0, 100%, 40%);">- print "OSError ([%d]: %s) occurred while executing %r" % \</span><br><span style="color: hsl(0, 100%, 40%);">- (ose.errno, ose.strerror, gdb_cmd)</span><br><span style="color: hsl(120, 100%, 40%);">+ except OSError as ose:</span><br><span style="color: hsl(120, 100%, 40%);">+ print("OSError ([%d]: %s) occurred while executing %r" %</span><br><span style="color: hsl(120, 100%, 40%);">+ (ose.errno, ose.strerror, gdb_cmd))</span><br><span> except:</span><br><span style="color: hsl(0, 100%, 40%);">- print "Unknown exception occurred while executing %r" % (gdb_cmd,)</span><br><span style="color: hsl(120, 100%, 40%);">+ print("Unknown exception occurred while executing %r" % (gdb_cmd,))</span><br><span> finally:</span><br><span> dest_file.close()</span><br><span> if self.options.keep_core:</span><br><span> try:</span><br><span> dst_core = os.path.join(dest_dir, "core_{0}".format(random_num))</span><br><span> shutil.copy(core, dst_core)</span><br><span style="color: hsl(0, 100%, 40%);">- print "Archived core file: {0}".format(dst_core)</span><br><span style="color: hsl(120, 100%, 40%);">+ print("Archived core file: {0}".format(dst_core))</span><br><span> except Exception as e:</span><br><span style="color: hsl(0, 100%, 40%);">- print "Error occurred while copying core: {0}".format(e)</span><br><span style="color: hsl(120, 100%, 40%);">+ print("Error occurred while copying core: {0}".format(e))</span><br><span> try:</span><br><span> os.unlink(core)</span><br><span style="color: hsl(0, 100%, 40%);">- except OSError, e:</span><br><span style="color: hsl(0, 100%, 40%);">- print "Error removing core file: %s: " \</span><br><span style="color: hsl(0, 100%, 40%);">- "Beware of the stale core file in CWD!" % (e,)</span><br><span style="color: hsl(120, 100%, 40%);">+ except OSError as e:</span><br><span style="color: hsl(120, 100%, 40%);">+ print("Error removing core file: %s: "</span><br><span style="color: hsl(120, 100%, 40%);">+ "Beware of the stale core file in CWD!" % (e,))</span><br><span> </span><br><span> def _find_run_dirs(self):</span><br><span> test_run_dir = os.path.join(Asterisk.test_suite_root,</span><br><span>@@ -387,7 +393,7 @@</span><br><span> res = subprocess.call(refcounter,</span><br><span> stdout=dest_file,</span><br><span> stderr=subprocess.STDOUT)</span><br><span style="color: hsl(0, 100%, 40%);">- except Exception, e:</span><br><span style="color: hsl(120, 100%, 40%);">+ except Exception as e:</span><br><span> self.stdout_print("Exception occurred while processing REF_DEBUG")</span><br><span> finally:</span><br><span> dest_file.close()</span><br><span>@@ -415,10 +421,10 @@</span><br><span> srcfile = os.path.join(src_dir, filename)</span><br><span> if os.path.exists(srcfile):</span><br><span> hardlink_or_copy(srcfile, os.path.join(dest_dir, filename))</span><br><span style="color: hsl(0, 100%, 40%);">- except Exception, e:</span><br><span style="color: hsl(0, 100%, 40%);">- print "Exception occurred while archiving file '%s' to %s: %s" % (</span><br><span style="color: hsl(120, 100%, 40%);">+ except Exception as e:</span><br><span style="color: hsl(120, 100%, 40%);">+ print("Exception occurred while archiving file '%s' to %s: %s" % (</span><br><span> srcfile, dest_dir, e</span><br><span style="color: hsl(0, 100%, 40%);">- )</span><br><span style="color: hsl(120, 100%, 40%);">+ ))</span><br><span> </span><br><span> def _archive_logs(self):</span><br><span> (run_num, run_dir, archive_dir) = self._find_run_dirs()</span><br><span>@@ -519,35 +525,35 @@</span><br><span> tags.sort(key=str.lower)</span><br><span> maxwidth = max(len(t) for t in tags)</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- print "Available test tags:"</span><br><span style="color: hsl(120, 100%, 40%);">+ print("Available test tags:")</span><br><span> tags = chunks(tags, 3)</span><br><span> for tag in tags:</span><br><span style="color: hsl(0, 100%, 40%);">- print "\t%-*s %-*s %-*s" % (</span><br><span style="color: hsl(120, 100%, 40%);">+ print("\t%-*s %-*s %-*s" % (</span><br><span> maxwidth, tag[0],</span><br><span> maxwidth, len(tag) > 1 and tag[1] or '',</span><br><span style="color: hsl(0, 100%, 40%);">- maxwidth, len(tag) > 2 and tag[2] or '')</span><br><span style="color: hsl(120, 100%, 40%);">+ maxwidth, len(tag) > 2 and tag[2] or ''))</span><br><span> </span><br><span> def list_tests(self):</span><br><span style="color: hsl(0, 100%, 40%);">- print "Configured tests:"</span><br><span style="color: hsl(120, 100%, 40%);">+ print("Configured tests:")</span><br><span> i = 1</span><br><span> for t in self.tests:</span><br><span style="color: hsl(0, 100%, 40%);">- print "%.3d) %s" % (i, t.test_config.test_name)</span><br><span style="color: hsl(0, 100%, 40%);">- print " --> Summary: %s" % t.test_config.summary</span><br><span style="color: hsl(120, 100%, 40%);">+ print("%.3d) %s" % (i, t.test_config.test_name))</span><br><span style="color: hsl(120, 100%, 40%);">+ print(" --> Summary: %s" % t.test_config.summary)</span><br><span> if t.test_config.skip is not None:</span><br><span style="color: hsl(0, 100%, 40%);">- print " --> Skip: %s" % t.test_config.skip</span><br><span style="color: hsl(120, 100%, 40%);">+ print(" --> Skip: %s" % t.test_config.skip)</span><br><span> if t.test_config.features:</span><br><span style="color: hsl(0, 100%, 40%);">- print " --> Features:"</span><br><span style="color: hsl(120, 100%, 40%);">+ print(" --> Features:")</span><br><span> for feature_name in t.test_config.features:</span><br><span style="color: hsl(0, 100%, 40%);">- print " --> %s: -- Met: %s" % \</span><br><span style="color: hsl(0, 100%, 40%);">- (feature_name, str(t.test_config.feature_check[feature_name]))</span><br><span style="color: hsl(120, 100%, 40%);">+ print(" --> %s: -- Met: %s" %</span><br><span style="color: hsl(120, 100%, 40%);">+ (feature_name, str(t.test_config.feature_check[feature_name])))</span><br><span> if t.test_config.tags:</span><br><span style="color: hsl(0, 100%, 40%);">- print " --> Tags: %s" % str(t.test_config.tags)</span><br><span style="color: hsl(120, 100%, 40%);">+ print(" --> Tags: %s" % str(t.test_config.tags))</span><br><span> for d in t.test_config.deps:</span><br><span> if d.version:</span><br><span style="color: hsl(0, 100%, 40%);">- print " --> Dependency: %s" % (d.name)</span><br><span style="color: hsl(0, 100%, 40%);">- print " --> Version: %s -- Met: %s" % (d.version, str(d.met))</span><br><span style="color: hsl(120, 100%, 40%);">+ print(" --> Dependency: %s" % (d.name))</span><br><span style="color: hsl(120, 100%, 40%);">+ print(" --> Version: %s -- Met: %s" % (d.version, str(d.met)))</span><br><span> else:</span><br><span style="color: hsl(0, 100%, 40%);">- print " --> Dependency: %s -- Met: %s" % (d.name, str(d.met))</span><br><span style="color: hsl(120, 100%, 40%);">+ print(" --> Dependency: %s -- Met: %s" % (d.name, str(d.met)))</span><br><span> </span><br><span> i += 1</span><br><span> </span><br><span>@@ -571,7 +577,7 @@</span><br><span> else:</span><br><span> deps += ("%s" % d.name)</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- print "%04d %s %s%s" % (i, flag, t.test_config.test_name, deps)</span><br><span style="color: hsl(120, 100%, 40%);">+ print("%04d %s %s%s" % (i, flag, t.test_config.test_name, deps))</span><br><span> i += 1</span><br><span> </span><br><span> def run(self):</span><br><span>@@ -587,8 +593,8 @@</span><br><span> if excluded in t.test_name:</span><br><span> continue</span><br><span> i += 1</span><br><span style="color: hsl(0, 100%, 40%);">- print "Tests to run: %d * %d time(s) = %d Maximum test inactivity time: %d sec." % \</span><br><span style="color: hsl(0, 100%, 40%);">- (i, self.options.number, i * self.options.number, (self.options.timeout / 1000))</span><br><span style="color: hsl(120, 100%, 40%);">+ print("Tests to run: %d * %d time(s) = %d Maximum test inactivity time: %d sec." %</span><br><span style="color: hsl(120, 100%, 40%);">+ (i, self.options.number, i * self.options.number, (self.options.timeout / 1000)))</span><br><span> </span><br><span> for t in self.tests:</span><br><span> if abandon_test_suite:</span><br><span>@@ -596,18 +602,18 @@</span><br><span> </span><br><span> if t.can_run is False:</span><br><span> if t.test_config.skip is not None:</span><br><span style="color: hsl(0, 100%, 40%);">- print "--> %s ... skipped '%s'" % (t.test_name, t.test_config.skip)</span><br><span style="color: hsl(120, 100%, 40%);">+ print("--> %s ... skipped '%s'" % (t.test_name, t.test_config.skip))</span><br><span> t.skipped_reason = t.test_config.skip</span><br><span> self.total_skipped += 1</span><br><span> continue</span><br><span style="color: hsl(0, 100%, 40%);">- print "--> Cannot run test '%s'" % t.test_name</span><br><span style="color: hsl(120, 100%, 40%);">+ print("--> Cannot run test '%s'" % t.test_name)</span><br><span> for f in t.test_config.features:</span><br><span style="color: hsl(0, 100%, 40%);">- print "--- --> Version Feature: %s - %s" % (</span><br><span style="color: hsl(0, 100%, 40%);">- f, str(t.test_config.feature_check[f]))</span><br><span style="color: hsl(0, 100%, 40%);">- print "--- --> Tags: %s" % (t.test_config.tags)</span><br><span style="color: hsl(120, 100%, 40%);">+ print("--- --> Version Feature: %s - %s" % (</span><br><span style="color: hsl(120, 100%, 40%);">+ f, str(t.test_config.feature_check[f])))</span><br><span style="color: hsl(120, 100%, 40%);">+ print("--- --> Tags: %s" % (t.test_config.tags))</span><br><span> for d in t.test_config.deps:</span><br><span style="color: hsl(0, 100%, 40%);">- print "--- --> Dependency: %s - %s" % (d.name, str(d.met))</span><br><span style="color: hsl(0, 100%, 40%);">- print</span><br><span style="color: hsl(120, 100%, 40%);">+ print("--- --> Dependency: %s - %s" % (d.name, str(d.met)))</span><br><span style="color: hsl(120, 100%, 40%);">+ print("")</span><br><span> self.total_skipped += 1</span><br><span> t.skipped_reason = "Failed dependency"</span><br><span> continue</span><br><span>@@ -615,14 +621,14 @@</span><br><span> exclude = False</span><br><span> for excluded in self.global_config.excluded_tests:</span><br><span> if excluded in t.test_name:</span><br><span style="color: hsl(0, 100%, 40%);">- print "--- ---> Excluded test: %s" % excluded</span><br><span style="color: hsl(120, 100%, 40%);">+ print("--- ---> Excluded test: %s" % excluded)</span><br><span> exclude = True</span><br><span> if exclude:</span><br><span> self.total_skipped += 1</span><br><span> continue</span><br><span> </span><br><span> running_str = "--> Running test '%s' ..." % t.test_name</span><br><span style="color: hsl(0, 100%, 40%);">- print running_str</span><br><span style="color: hsl(120, 100%, 40%);">+ print(running_str)</span><br><span> if self.options.syslog:</span><br><span> syslog.syslog(running_str)</span><br><span> </span><br><span>@@ -630,16 +636,16 @@</span><br><span> t.passed = True</span><br><span> else:</span><br><span> # Establish Preconditions</span><br><span style="color: hsl(0, 100%, 40%);">- print "Making sure Asterisk isn't running ..."</span><br><span style="color: hsl(120, 100%, 40%);">+ print("Making sure Asterisk isn't running ...")</span><br><span> if os.system("if pidof asterisk >/dev/null; then "</span><br><span> "killall -9 asterisk >/dev/null 2>&1; "</span><br><span> "sleep 1; ! pidof asterisk >/dev/null; fi"):</span><br><span style="color: hsl(0, 100%, 40%);">- print "Could not kill asterisk."</span><br><span style="color: hsl(0, 100%, 40%);">- print "Making sure SIPp isn't running..."</span><br><span style="color: hsl(120, 100%, 40%);">+ print("Could not kill asterisk.")</span><br><span style="color: hsl(120, 100%, 40%);">+ print("Making sure SIPp isn't running...")</span><br><span> if os.system("if pidof sipp >/dev/null; then "</span><br><span> "killall -9 sipp >/dev/null 2>&1; "</span><br><span> "sleep 1; ! pidof sipp >/dev/null; fi"):</span><br><span style="color: hsl(0, 100%, 40%);">- print "Could not kill sipp."</span><br><span style="color: hsl(120, 100%, 40%);">+ print("Could not kill sipp.")</span><br><span> # XXX TODO Hard coded path, gross.</span><br><span> os.system("rm -f /var/run/asterisk/asterisk.ctl")</span><br><span> os.system("rm -f /var/run/asterisk/asterisk.pid")</span><br><span>@@ -668,12 +674,12 @@</span><br><span> (0x86, 0x9f),</span><br><span> ]</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- char_list = []</span><br><span style="color: hsl(120, 100%, 40%);">+ tbl = {}</span><br><span> for r in bad_chars:</span><br><span> # we do +1 here to include the last item</span><br><span> for i in range(r[0], r[1] + 1):</span><br><span style="color: hsl(0, 100%, 40%);">- char_list.append(chr(i))</span><br><span style="color: hsl(0, 100%, 40%);">- return data.translate(None, ''.join(char_list))</span><br><span style="color: hsl(120, 100%, 40%);">+ tbl[chr(i)] = None</span><br><span style="color: hsl(120, 100%, 40%);">+ return data.translate(tbl)</span><br><span> </span><br><span> def write_results_xml(self, doc, root):</span><br><span> </span><br><span>@@ -728,10 +734,10 @@</span><br><span> except IOError:</span><br><span> # Ignore errors for the optional tests/custom folder.</span><br><span> if path != "tests/custom/tests.yaml":</span><br><span style="color: hsl(0, 100%, 40%);">- print "Failed to open %s" % path</span><br><span style="color: hsl(120, 100%, 40%);">+ print("Failed to open %s" % path)</span><br><span> return None</span><br><span> except:</span><br><span style="color: hsl(0, 100%, 40%);">- print "Unexpected error: %s" % sys.exc_info()[0]</span><br><span style="color: hsl(120, 100%, 40%);">+ print("Unexpected error: %s" % sys.exc_info()[0])</span><br><span> return None</span><br><span> </span><br><span> config = yaml.load(f)</span><br><span>@@ -747,7 +753,7 @@</span><br><span> """</span><br><span> global abandon_test_suite</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- print "SIGUSR1 received; stopping test suite after current test..."</span><br><span style="color: hsl(120, 100%, 40%);">+ print("SIGUSR1 received; stopping test suite after current test...")</span><br><span> abandon_test_suite = True</span><br><span> </span><br><span> </span><br><span>@@ -760,7 +766,7 @@</span><br><span> global abandon_test</span><br><span> global abandon_test_suite</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- print "SIGTREM received; abandoning current test and stopping..."</span><br><span style="color: hsl(120, 100%, 40%);">+ print("SIGTREM received; abandoning current test and stopping...")</span><br><span> abandon_test = True</span><br><span> abandon_test_suite = True</span><br><span> </span><br><span>@@ -877,8 +883,8 @@</span><br><span> </span><br><span> if options.valgrind:</span><br><span> if not ET:</span><br><span style="color: hsl(0, 100%, 40%);">- print "python lxml module not loaded, text summaries " \</span><br><span style="color: hsl(0, 100%, 40%);">- "from valgrind will not be produced.\n"</span><br><span style="color: hsl(120, 100%, 40%);">+ print("python lxml module not loaded, text summaries "</span><br><span style="color: hsl(120, 100%, 40%);">+ "from valgrind will not be produced.\n")</span><br><span> os.environ["VALGRIND_ENABLE"] = "true"</span><br><span> </span><br><span> dom = xml.dom.getDOMImplementation()</span><br><span>@@ -894,7 +900,7 @@</span><br><span> </span><br><span> running_str = "Running tests for Asterisk (run {0} of {1})...\n".format(</span><br><span> iteration + 1, options.number)</span><br><span style="color: hsl(0, 100%, 40%);">- print running_str</span><br><span style="color: hsl(120, 100%, 40%);">+ print(running_str)</span><br><span> if options.syslog:</span><br><span> syslog.syslog(running_str)</span><br><span> </span><br><span>@@ -903,22 +909,22 @@</span><br><span> </span><br><span> # If exactly one test was requested, then skip the summary.</span><br><span> if len(test_suite.tests) != 1:</span><br><span style="color: hsl(0, 100%, 40%);">- print "\n=== TEST RESULTS ===\n"</span><br><span style="color: hsl(0, 100%, 40%);">- print "PATH: %s\n" % os.getenv("PATH")</span><br><span style="color: hsl(120, 100%, 40%);">+ print("\n=== TEST RESULTS ===\n")</span><br><span style="color: hsl(120, 100%, 40%);">+ print("PATH: %s\n" % os.getenv("PATH"))</span><br><span> for t in test_suite.tests:</span><br><span> sys.stdout.write("--> %s --- " % t.test_name)</span><br><span> if t.did_run is False:</span><br><span style="color: hsl(0, 100%, 40%);">- print "SKIPPED"</span><br><span style="color: hsl(120, 100%, 40%);">+ print("SKIPPED")</span><br><span> for d in t.test_config.deps:</span><br><span style="color: hsl(0, 100%, 40%);">- print " --> Dependency: %s -- Met: %s" % (d.name, str(d.met))</span><br><span style="color: hsl(120, 100%, 40%);">+ print(" --> Dependency: %s -- Met: %s" % (d.name, str(d.met)))</span><br><span> if options.tags:</span><br><span> for t in t.test_config.tags:</span><br><span style="color: hsl(0, 100%, 40%);">- print " --> Tag: %s -- Met: %s" % (t, str(t in options.tags))</span><br><span style="color: hsl(120, 100%, 40%);">+ print(" --> Tag: %s -- Met: %s" % (t, str(t in options.tags)))</span><br><span> continue</span><br><span> if t.passed is True:</span><br><span style="color: hsl(0, 100%, 40%);">- print "PASSED"</span><br><span style="color: hsl(120, 100%, 40%);">+ print("PASSED")</span><br><span> else:</span><br><span style="color: hsl(0, 100%, 40%);">- print "FAILED"</span><br><span style="color: hsl(120, 100%, 40%);">+ print("FAILED")</span><br><span> </span><br><span> iteration += 1</span><br><span> </span><br><span>@@ -929,11 +935,11 @@</span><br><span> with open(TEST_RESULTS, "w") as f:</span><br><span> doc.writexml(f, addindent=" ", newl="\n", encoding="utf-8")</span><br><span> except IOError:</span><br><span style="color: hsl(0, 100%, 40%);">- print "Failed to open test results output file: %s" % TEST_RESULTS</span><br><span style="color: hsl(120, 100%, 40%);">+ print("Failed to open test results output file: %s" % TEST_RESULTS)</span><br><span> except:</span><br><span style="color: hsl(0, 100%, 40%);">- print "Unexpected error: %s" % sys.exc_info()[0]</span><br><span style="color: hsl(0, 100%, 40%);">- print "\n"</span><br><span style="color: hsl(0, 100%, 40%);">- print doc.toprettyxml(" ", encoding="utf-8")</span><br><span style="color: hsl(120, 100%, 40%);">+ print("Unexpected error: %s" % sys.exc_info()[0])</span><br><span style="color: hsl(120, 100%, 40%);">+ print("\n")</span><br><span style="color: hsl(120, 100%, 40%);">+ print(doc.toprettyxml(" ", encoding="utf-8").decode('utf-8', 'ignore'))</span><br><span> </span><br><span> if options.syslog:</span><br><span> syslog.syslog("All tests concluded")</span><br><span>@@ -954,7 +960,7 @@</span><br><span> </span><br><span> try:</span><br><span> os.link(source, destination)</span><br><span style="color: hsl(0, 100%, 40%);">- except OSError, e:</span><br><span style="color: hsl(120, 100%, 40%);">+ except OSError as e:</span><br><span> # Different partitions can cause hard links to fail (error 18),</span><br><span> # if there's a different error, bail out immediately.</span><br><span> if e.args[0] != errno.EXDEV:</span><br><span>diff --git a/self_test b/self_test</span><br><span>index 1936014..045c090 100755</span><br><span>--- a/self_test</span><br><span>+++ b/self_test</span><br><span>@@ -28,17 +28,3 @@</span><br><span> run_test $i python2 $PYTHON2</span><br><span> [ "${i#test2}" = "${i}" ] && run_test $i python3 $PYTHON3</span><br><span> done</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-# Temporary code for running unit tests that are not compatible with python3</span><br><span style="color: hsl(0, 100%, 40%);">-run_legacy_test() {</span><br><span style="color: hsl(0, 100%, 40%);">- # Arguments: test_name python_name python_bin</span><br><span style="color: hsl(0, 100%, 40%);">- if test -n "$3"; then</span><br><span style="color: hsl(0, 100%, 40%);">- echo " ==> Executing $1 ($2)"</span><br><span style="color: hsl(0, 100%, 40%);">- $3 lib/python/asterisk/${1}.py</span><br><span style="color: hsl(0, 100%, 40%);">- fi</span><br><span style="color: hsl(0, 100%, 40%);">-}</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-for i in buildoptions channel_test_condition sippversion; do</span><br><span style="color: hsl(0, 100%, 40%);">- run_legacy_test $i python $PYTHON</span><br><span style="color: hsl(0, 100%, 40%);">- run_legacy_test $i python2 $PYTHON2</span><br><span style="color: hsl(0, 100%, 40%);">-done</span><br><span>diff --git a/tests/cdr/cdr-tests.py b/tests/cdr/cdr-tests.py</span><br><span>index a284673..9090045 100644</span><br><span>--- a/tests/cdr/cdr-tests.py</span><br><span>+++ b/tests/cdr/cdr-tests.py</span><br><span>@@ -13,8 +13,8 @@</span><br><span> import time</span><br><span> </span><br><span> sys.path.append("lib/python")</span><br><span style="color: hsl(0, 100%, 40%);">-from cdr import CDRModule</span><br><span style="color: hsl(0, 100%, 40%);">-from cdr import AsteriskCSVCDR</span><br><span style="color: hsl(120, 100%, 40%);">+from asterisk.cdr import CDRModule</span><br><span style="color: hsl(120, 100%, 40%);">+from asterisk.cdr import AsteriskCSVCDR</span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span> </span><br><span>diff --git a/tests/cdr/sqlite3/cdr_sqlite3.py b/tests/cdr/sqlite3/cdr_sqlite3.py</span><br><span>index 1def05e..32ed786 100644</span><br><span>--- a/tests/cdr/sqlite3/cdr_sqlite3.py</span><br><span>+++ b/tests/cdr/sqlite3/cdr_sqlite3.py</span><br><span>@@ -14,7 +14,7 @@</span><br><span> import re</span><br><span> </span><br><span> sys.path.append("lib/python")</span><br><span style="color: hsl(0, 100%, 40%);">-from config import ConfigFile</span><br><span style="color: hsl(120, 100%, 40%);">+from asterisk.config import ConfigFile</span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span> </span><br><span>diff --git a/tests/channels/SIP/tcpauthlimit/sipp_scenario.py b/tests/channels/SIP/tcpauthlimit/sipp_scenario.py</span><br><span>index 76a21aa..55a26f5 100644</span><br><span>--- a/tests/channels/SIP/tcpauthlimit/sipp_scenario.py</span><br><span>+++ b/tests/channels/SIP/tcpauthlimit/sipp_scenario.py</span><br><span>@@ -9,7 +9,7 @@</span><br><span> </span><br><span> import logging</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-from sipp import SIPpScenario</span><br><span style="color: hsl(120, 100%, 40%);">+from asterisk.sipp import SIPpScenario</span><br><span> from twisted.internet import defer</span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span>diff --git a/tests/channels/pjsip/registration/inbound/nominal/contact_acl/ipv4/scenario_generator.py b/tests/channels/pjsip/registration/inbound/nominal/contact_acl/ipv4/scenario_generator.py</span><br><span>index 2e2357a..4fcb67a 100755</span><br><span>--- a/tests/channels/pjsip/registration/inbound/nominal/contact_acl/ipv4/scenario_generator.py</span><br><span>+++ b/tests/channels/pjsip/registration/inbound/nominal/contact_acl/ipv4/scenario_generator.py</span><br><span>@@ -12,8 +12,8 @@</span><br><span> </span><br><span> sys.path.append("lib/python")</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-import test_suite_utils</span><br><span style="color: hsl(0, 100%, 40%);">-from sipp import ScenarioGenerator</span><br><span style="color: hsl(120, 100%, 40%);">+from asterisk import test_suite_utils</span><br><span style="color: hsl(120, 100%, 40%);">+from asterisk.sipp import ScenarioGenerator</span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span> </span><br><span>diff --git a/tests/channels/pjsip/registration/inbound/nominal/contact_acl/ipv6/scenario_generator.py b/tests/channels/pjsip/registration/inbound/nominal/contact_acl/ipv6/scenario_generator.py</span><br><span>index 2a52c96..541ba62 100755</span><br><span>--- a/tests/channels/pjsip/registration/inbound/nominal/contact_acl/ipv6/scenario_generator.py</span><br><span>+++ b/tests/channels/pjsip/registration/inbound/nominal/contact_acl/ipv6/scenario_generator.py</span><br><span>@@ -12,8 +12,8 @@</span><br><span> </span><br><span> sys.path.append("lib/python")</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-import test_suite_utils</span><br><span style="color: hsl(0, 100%, 40%);">-from sipp import ScenarioGenerator</span><br><span style="color: hsl(120, 100%, 40%);">+from asterisk import test_suite_utils</span><br><span style="color: hsl(120, 100%, 40%);">+from asterisk.sipp import ScenarioGenerator</span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span> </span><br><span>diff --git a/tests/channels/pjsip/subscriptions/presence/verify_bodies/presence.py b/tests/channels/pjsip/subscriptions/presence/verify_bodies/presence.py</span><br><span>index 143ea42..bbff8f8 100644</span><br><span>--- a/tests/channels/pjsip/subscriptions/presence/verify_bodies/presence.py</span><br><span>+++ b/tests/channels/pjsip/subscriptions/presence/verify_bodies/presence.py</span><br><span>@@ -15,7 +15,7 @@</span><br><span> </span><br><span> sys.path.append('lib/python')</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-from pcap import VOIPListener</span><br><span style="color: hsl(120, 100%, 40%);">+from asterisk.pcap import VOIPListener</span><br><span> from twisted.internet import reactor</span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span>diff --git a/tests/channels/pjsip/subscriptions/rls/rls_test.py b/tests/channels/pjsip/subscriptions/rls/rls_test.py</span><br><span>index 9c4051c..08d0567 100644</span><br><span>--- a/tests/channels/pjsip/subscriptions/rls/rls_test.py</span><br><span>+++ b/tests/channels/pjsip/subscriptions/rls/rls_test.py</span><br><span>@@ -13,7 +13,7 @@</span><br><span> sys.path.append("lib/python")</span><br><span> sys.path.append("tests/channels/pjsip/subscriptions/rls")</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-from pcap import VOIPProxy</span><br><span style="color: hsl(120, 100%, 40%);">+from asterisk.pcap import VOIPProxy</span><br><span> from rls_element import RLSPacket</span><br><span> from rls_validation import ValidationInfo</span><br><span> from twisted.internet import reactor</span><br><span>diff --git a/tests/channels/pjsip/transfers/attended_transfer/nominal/packet_sniffer.py b/tests/channels/pjsip/transfers/attended_transfer/nominal/packet_sniffer.py</span><br><span>index a96a661..b49f268 100755</span><br><span>--- a/tests/channels/pjsip/transfers/attended_transfer/nominal/packet_sniffer.py</span><br><span>+++ b/tests/channels/pjsip/transfers/attended_transfer/nominal/packet_sniffer.py</span><br><span>@@ -35,8 +35,8 @@</span><br><span> </span><br><span> sys.path.append('lib/python')</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-from phones import PjsuaPhoneController</span><br><span style="color: hsl(0, 100%, 40%);">-from pcap import VOIPListener</span><br><span style="color: hsl(120, 100%, 40%);">+from asterisk.phones import PjsuaPhoneController</span><br><span style="color: hsl(120, 100%, 40%);">+from asterisk.pcap import VOIPListener</span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span> </span><br><span>diff --git a/tests/codecs/audio_analyzer.py b/tests/codecs/audio_analyzer.py</span><br><span>index 9903c6d..e656777 100644</span><br><span>--- a/tests/codecs/audio_analyzer.py</span><br><span>+++ b/tests/codecs/audio_analyzer.py</span><br><span>@@ -13,8 +13,8 @@</span><br><span> import logging</span><br><span> from twisted.internet import reactor</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-import ami</span><br><span style="color: hsl(0, 100%, 40%);">-import ari</span><br><span style="color: hsl(120, 100%, 40%);">+from asterisk import ami</span><br><span style="color: hsl(120, 100%, 40%);">+from asterisk import ari</span><br><span> import tonetest</span><br><span> </span><br><span> sys.path.append("lib/python")</span><br><span>diff --git a/tests/codecs/rtp_analyzer.py b/tests/codecs/rtp_analyzer.py</span><br><span>index e20cde3..74f161a 100644</span><br><span>--- a/tests/codecs/rtp_analyzer.py</span><br><span>+++ b/tests/codecs/rtp_analyzer.py</span><br><span>@@ -13,7 +13,7 @@</span><br><span> </span><br><span> sys.path.append("lib/python")</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-import pcap</span><br><span style="color: hsl(120, 100%, 40%);">+from asterisk import pcap</span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span> </span><br><span>diff --git a/tests/hep/hep_capture_node.py b/tests/hep/hep_capture_node.py</span><br><span>index f663056..3e7feae 100644</span><br><span>--- a/tests/hep/hep_capture_node.py</span><br><span>+++ b/tests/hep/hep_capture_node.py</span><br><span>@@ -28,7 +28,7 @@</span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-from test_suite_utils import all_match</span><br><span style="color: hsl(120, 100%, 40%);">+from asterisk.test_suite_utils import all_match</span><br><span> </span><br><span> def enum(**enums):</span><br><span> """Make an enumeration out of the passed in values"""</span><br><span>diff --git a/tests/manager/config/ManagerConfigTest.py b/tests/manager/config/ManagerConfigTest.py</span><br><span>index b7dbd8a..fe2e65f 100644</span><br><span>--- a/tests/manager/config/ManagerConfigTest.py</span><br><span>+++ b/tests/manager/config/ManagerConfigTest.py</span><br><span>@@ -13,8 +13,8 @@</span><br><span> </span><br><span> sys.path.append("lib/python")</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-from test_case import TestCase</span><br><span style="color: hsl(0, 100%, 40%);">-from syncami import SyncAMI</span><br><span style="color: hsl(120, 100%, 40%);">+from asterisk.test_case import TestCase</span><br><span style="color: hsl(120, 100%, 40%);">+from asterisk.syncami import SyncAMI</span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span> </span><br><span>diff --git a/tests/manager/device_state_changed/ami_device_state.py b/tests/manager/device_state_changed/ami_device_state.py</span><br><span>index a3ac5f3..96d8021 100644</span><br><span>--- a/tests/manager/device_state_changed/ami_device_state.py</span><br><span>+++ b/tests/manager/device_state_changed/ami_device_state.py</span><br><span>@@ -8,7 +8,7 @@</span><br><span> '''</span><br><span> </span><br><span> import logging</span><br><span style="color: hsl(0, 100%, 40%);">-from test_case import TestCase</span><br><span style="color: hsl(120, 100%, 40%);">+from asterisk.test_case import TestCase</span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span> </span><br><span>diff --git a/tests/manager/device_state_list/ami_device_state_list.py b/tests/manager/device_state_list/ami_device_state_list.py</span><br><span>index 5abd104..105780e 100755</span><br><span>--- a/tests/manager/device_state_list/ami_device_state_list.py</span><br><span>+++ b/tests/manager/device_state_list/ami_device_state_list.py</span><br><span>@@ -9,7 +9,7 @@</span><br><span> """</span><br><span> </span><br><span> import logging</span><br><span style="color: hsl(0, 100%, 40%);">-from test_case import TestCase</span><br><span style="color: hsl(120, 100%, 40%);">+from asterisk.test_case import TestCase</span><br><span> from twisted.internet import defer</span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span>diff --git a/tests/manager/exten_state_list/ami_exten_state_list.py b/tests/manager/exten_state_list/ami_exten_state_list.py</span><br><span>index c9449f4..90bdc4f 100755</span><br><span>--- a/tests/manager/exten_state_list/ami_exten_state_list.py</span><br><span>+++ b/tests/manager/exten_state_list/ami_exten_state_list.py</span><br><span>@@ -9,7 +9,7 @@</span><br><span> """</span><br><span> </span><br><span> import logging</span><br><span style="color: hsl(0, 100%, 40%);">-from test_case import TestCase</span><br><span style="color: hsl(120, 100%, 40%);">+from asterisk.test_case import TestCase</span><br><span> from twisted.internet import defer</span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span>diff --git a/tests/manager/presence_state_changed/ami_presence_state.py b/tests/manager/presence_state_changed/ami_presence_state.py</span><br><span>index e6861fc..d8ac551 100644</span><br><span>--- a/tests/manager/presence_state_changed/ami_presence_state.py</span><br><span>+++ b/tests/manager/presence_state_changed/ami_presence_state.py</span><br><span>@@ -8,7 +8,7 @@</span><br><span> '''</span><br><span> </span><br><span> import logging</span><br><span style="color: hsl(0, 100%, 40%);">-from test_case import TestCase</span><br><span style="color: hsl(120, 100%, 40%);">+from asterisk.test_case import TestCase</span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span> </span><br><span>diff --git a/tests/manager/presence_state_list/ami_presence_state_list.py b/tests/manager/presence_state_list/ami_presence_state_list.py</span><br><span>index 13c16c7..f67c386 100755</span><br><span>--- a/tests/manager/presence_state_list/ami_presence_state_list.py</span><br><span>+++ b/tests/manager/presence_state_list/ami_presence_state_list.py</span><br><span>@@ -9,7 +9,7 @@</span><br><span> """</span><br><span> </span><br><span> import logging</span><br><span style="color: hsl(0, 100%, 40%);">-from test_case import TestCase</span><br><span style="color: hsl(120, 100%, 40%);">+from asterisk.test_case import TestCase</span><br><span> from twisted.internet import defer</span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span>diff --git a/tests/pbx/manager_extensions/ami_extension_control.py b/tests/pbx/manager_extensions/ami_extension_control.py</span><br><span>index d4ac26c..01e53af 100755</span><br><span>--- a/tests/pbx/manager_extensions/ami_extension_control.py</span><br><span>+++ b/tests/pbx/manager_extensions/ami_extension_control.py</span><br><span>@@ -8,7 +8,7 @@</span><br><span> '''</span><br><span> </span><br><span> import logging</span><br><span style="color: hsl(0, 100%, 40%);">-from test_case import TestCase</span><br><span style="color: hsl(120, 100%, 40%);">+from asterisk.test_case import TestCase</span><br><span> from twisted.internet import defer</span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span>diff --git a/tests/rest_api/external_interaction/attended_transfer/attended_transfer.py b/tests/rest_api/external_interaction/attended_transfer/attended_transfer.py</span><br><span>index d03fbfe..6b7790c 100644</span><br><span>--- a/tests/rest_api/external_interaction/attended_transfer/attended_transfer.py</span><br><span>+++ b/tests/rest_api/external_interaction/attended_transfer/attended_transfer.py</span><br><span>@@ -9,7 +9,7 @@</span><br><span> import logging</span><br><span> from sys import path</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-from sipp import SIPpScenario</span><br><span style="color: hsl(120, 100%, 40%);">+from asterisk.sipp import SIPpScenario</span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span> </span><br><span>diff --git a/tests/rest_api/external_interaction/blind_transfer/call_transfer.py b/tests/rest_api/external_interaction/blind_transfer/call_transfer.py</span><br><span>index 23f1a7b..ddef074 100755</span><br><span>--- a/tests/rest_api/external_interaction/blind_transfer/call_transfer.py</span><br><span>+++ b/tests/rest_api/external_interaction/blind_transfer/call_transfer.py</span><br><span>@@ -16,7 +16,7 @@</span><br><span> import pjsua as pj</span><br><span> from twisted.internet import reactor</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-import pjsua_mod</span><br><span style="color: hsl(120, 100%, 40%);">+from asterisk import pjsua_mod</span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span> THIS_FILE = os.path.basename(__file__)</span><br><span>diff --git a/tests/rest_api/message/message_modules.py b/tests/rest_api/message/message_modules.py</span><br><span>index 2e4cdd4..c2d8f2e 100644</span><br><span>--- a/tests/rest_api/message/message_modules.py</span><br><span>+++ b/tests/rest_api/message/message_modules.py</span><br><span>@@ -14,7 +14,7 @@</span><br><span> </span><br><span> from twisted.internet import defer</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-from sipp import SIPpScenario</span><br><span style="color: hsl(120, 100%, 40%);">+from asterisk.sipp import SIPpScenario</span><br><span> </span><br><span> LOGGER = logging.getLogger(__name__)</span><br><span> </span><br><span>diff --git a/usage.py b/usage.py</span><br><span>index 16dea94..9e7c33f 100755</span><br><span>--- a/usage.py</span><br><span>+++ b/usage.py</span><br><span>@@ -70,7 +70,7 @@</span><br><span> def occurances(self, **kwargs):</span><br><span> match = []</span><br><span> for test in self.tests:</span><br><span style="color: hsl(0, 100%, 40%);">- for key, value in kwargs.iteritems():</span><br><span style="color: hsl(120, 100%, 40%);">+ for key, value in kwargs.items():</span><br><span> if value in getattr(test, key):</span><br><span> match.append(test)</span><br><span> continue</span><br><span>@@ -78,14 +78,14 @@</span><br><span> return len(match)</span><br><span> </span><br><span> def results_for(self, key):</span><br><span style="color: hsl(0, 100%, 40%);">- print key.title() + ":"</span><br><span style="color: hsl(120, 100%, 40%);">+ print(key.title() + ":")</span><br><span> things = self.unique(key)</span><br><span> width = max(len(t) for t in things)</span><br><span> results = [(self.occurances(**{key: t}), t) for t in things]</span><br><span> results.sort(key=lambda tup: tup[0], reverse=True)</span><br><span> for (count, name) in results:</span><br><span style="color: hsl(0, 100%, 40%);">- print "\t%-*s %5d" % (width, name, count)</span><br><span style="color: hsl(0, 100%, 40%);">- print ""</span><br><span style="color: hsl(120, 100%, 40%);">+ print("\t%-*s %5d" % (width, name, count))</span><br><span style="color: hsl(120, 100%, 40%);">+ print("")</span><br><span> </span><br><span> </span><br><span> def load_yaml_config(path):</span><br><span>@@ -95,10 +95,10 @@</span><br><span> except IOError:</span><br><span> # Ignore errors for the optional tests/custom folder.</span><br><span> if path != "tests/custom/tests.yaml":</span><br><span style="color: hsl(0, 100%, 40%);">- print "Failed to open %s" % path</span><br><span style="color: hsl(120, 100%, 40%);">+ print("Failed to open %s" % path)</span><br><span> return None</span><br><span> except:</span><br><span style="color: hsl(0, 100%, 40%);">- print "Unexpected error: %s" % sys.exc_info()[0]</span><br><span style="color: hsl(120, 100%, 40%);">+ print("Unexpected error: %s" % sys.exc_info()[0])</span><br><span> return None</span><br><span> </span><br><span> config = yaml.load(f)</span><br><span>@@ -108,11 +108,11 @@</span><br><span> </span><br><span> </span><br><span> def main(argv=None):</span><br><span style="color: hsl(0, 100%, 40%);">- print "Testsuite Module Usage and Coverage Report"</span><br><span style="color: hsl(0, 100%, 40%);">- print ""</span><br><span style="color: hsl(120, 100%, 40%);">+ print("Testsuite Module Usage and Coverage Report")</span><br><span style="color: hsl(120, 100%, 40%);">+ print("")</span><br><span> test_suite = TestSuite()</span><br><span style="color: hsl(0, 100%, 40%);">- print "Number of tests:", len(test_suite.tests)</span><br><span style="color: hsl(0, 100%, 40%);">- print ""</span><br><span style="color: hsl(120, 100%, 40%);">+ print("Number of tests:", len(test_suite.tests))</span><br><span style="color: hsl(120, 100%, 40%);">+ print("")</span><br><span> test_suite.results_for('tags')</span><br><span> test_suite.results_for('test_objects')</span><br><span> test_suite.results_for('test_modules')</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/9315">change 9315</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/9315"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: testsuite </div>
<div style="display:none"> Gerrit-Branch: 13 </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: If76c2d3e11e4ab4552d0df7841287c8bb2de7918 </div>
<div style="display:none"> Gerrit-Change-Number: 9315 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Corey Farrell <git@cfware.com> </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins2 </div>
<div style="display:none"> Gerrit-Reviewer: Kevin Harwell <kharwell@digium.com> </div>