def __init__(self, dep): """Construct a new dependency Keyword arguments: dep A tuple containing the dependency type name and its subinformation. """ self.name = "" self.version = "" self.met = False if "app" in dep: self.name = dep["app"] self.met = test_suite_utils.which(self.name) is not None elif "python" in dep: self.name = dep["python"] try: __import__(self.name) self.met = True except ImportError: pass elif "sipp" in dep: self.name = "SIPp" version = None feature = None if 'version' in dep['sipp']: version = dep['sipp']['version'] if 'feature' in dep['sipp']: feature = dep['sipp']['feature'] self.sipp_version = SIPpVersion() self.version = SIPpVersion(version, feature) if self.sipp_version >= self.version: self.met = True if self.version.tls and not self.sipp_version.tls: self.met = False if self.version.pcap and not self.sipp_version.pcap: self.met = False elif "custom" in dep: self.name = dep["custom"] method = "depend_%s" % self.name found = False for dir_method in dir(self): if dir_method == method: self.met = getattr(self, dir_method)() found = True if not found: print "Unknown custom dependency - '%s'" % self.name elif "asterisk" in dep: self.name = dep["asterisk"] self.met = self._find_asterisk_module(self.name) elif "buildoption" in dep: self.name = dep["buildoption"] self.met = self._find_build_flag(self.name) elif "pcap" in dep: self.name = "pcap" from test_case import PCAP_AVAILABLE self.met = PCAP_AVAILABLE else: print "Unknown dependency type specified:" for key in dep.keys(): print key
def get_version_from_binary(cls): """Obtain the version from the installed instance of Asterisk This method will invoke Asterisk, get the version, parse the result, and cache it. Once cached, the cached version will always be returned. Returns: The installed Asterisk version """ if not hasattr(cls, "_asterisk_version_from_binary"): version = "" ast_binary = (test_suite_utils.which("asterisk") or "/usr/sbin/asterisk") cmd = [ ast_binary, "-V", ] try: process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=None) version = process.stdout.read() except OSError as o_excep: LOGGER.error("OSError [%d]: %s" % (o_excep.errno, o_excep.strerror)) raise process.wait() cls._asterisk_version_from_binary = version.replace( "Asterisk ", "") return cls._asterisk_version_from_binary
def __init__(self, test_dir, scenario, positional_args=(), target='127.0.0.1'): """ Keyword Arguments: test_dir The path to the directory containing the run-test file. scenario A SIPp scenario to execute. The scenario should be a dictionary with the key 'scenario' being the filename of the SIPp scenario. Any other key-value pairs are treated as arguments to SIPp. For example, specify '-timeout' : '60s' to set the timeout option to SIPp to 60 seconds. If a parameter specified is also one specified by default, the value provided will be used. The default SIPp parameters include: -p <port> - Unless otherwise specified, the port number will be 5060 + <scenario list index, starting at 1>. So, the first SIPp sceario will use port 5061. -m 1 - Stop the test after 1 'call' is processed. -i 127.0.0.1 - Use this as the local IP address for the Contact headers, Via headers, etc. -timeout 20s - Set a global test timeout of 20 seconds. positional_args Certain SIPp parameters can be specified multiple times, or take multiple arguments. Supply those through this iterable. The canonical example being -key: ('-key', 'extra_via_param', ';rport', '-key', 'user_addr', 'sip:myname@myhost') target Overrides the default target address (127.0.0.1) of the SIPp scenario. Be sure to specify IPv6 addresses in brackets ([::1]) """ self.scenario = scenario self.name = scenario['scenario'] # don't allow caller to mangle his own list self.positional_args = tuple(positional_args) self.test_dir = test_dir self.default_port = 5061 self.sipp = test_suite_utils.which("sipp") self.passed = False self.exited = False self._process = None self.target = target self._our_exit_deferred = None self._test_case = None if not self.sipp: raise ValueError("SIPpTestObject requires that sipp is installed")
def depend_pjsuav6(self): """This tests if pjsua was compiled with IPv6 support. To do this, we run pjsua --help and parse the output to determine if --ipv6 is a valid option """ if test_suite_utils.which('pjsua') is None: return False help_output = subprocess.Popen(['pjsua', '--help'], stdout=subprocess.PIPE).communicate()[0] if help_output.find('--ipv6') == -1: return False return True
def __init__(self, version=None, feature=None): """Construct a SIPp Version parser. Keyword Arguments: version The SIPp version string to parse. """ self.version_str = None self.feature_str = None self.concept = None self.major = None self.minor = None self.tls = False self.pcap = False if version is None and feature is None: sipp = test_suite_utils.which("sipp") if sipp is None: return cmd = [ sipp, "-v" ] try: sipp_process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) except OSError: return for line in sipp_process.stdout: if line.strip().startswith('SIPp '): sipp = line.strip()[5:] sipp = sipp.split(',', 1) sipp = sipp[0].split('-', 1) version = sipp[0] if len(sipp) > 1: feature = sipp[1] sipp_process.wait() if version is not None: self.__parse_version(version) if feature is not None: self.__parse_feature(feature)
def __init__(self, version=None, feature=None): """Construct a SIPp Version parser. Keyword Arguments: version The SIPp version string to parse. """ self.version_str = None self.feature_str = None self.concept = None self.major = None self.minor = None self.tls = False self.pcap = False if version is None and feature is None: sipp = test_suite_utils.which("sipp") if sipp is None: return cmd = [ sipp, "-v" ] try: sipp_process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) except OSError: return for line in sipp_process.stdout: if line.strip().startswith('SIPp'): sipp = line.strip().lstrip('SIPp ') sipp = sipp.split(',', 1) sipp = sipp[0].split('-', 1) version = sipp[0] if len(sipp) > 1: feature = sipp[1] sipp_process.wait() if version is not None: self.__parse_version(version) if feature is not None: self.__parse_feature(feature)
def get_version_from_binary(cls): """Obtain the version from Asterisk and return a cached version of it""" if not hasattr(cls, "_asterisk_version_from_binary"): version = "" ast_binary = (test_suite_utils.which("asterisk") or "/usr/sbin/asterisk") cmd = [ ast_binary, "-V", ] try: process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=None) version = process.stdout.read() except OSError as o_excep: LOGGER.error("OSError [%d]: %s" % (o_excep.errno, o_excep.strerror)) raise process.wait() cls._asterisk_version_from_binary = version.replace( "Asterisk ", "") return cls._asterisk_version_from_binary
def start(self, deps=None): """Start this instance of Asterisk. Returns: A deferred object that will be called when Asterisk is fully booted. Example Usage: asterisk.start() Note that calling this will install the default testsuite config files, if they have not already been installed """ def __start_asterisk_callback(cmd): """Begin the Asterisk startup cycle""" self.process_protocol = AsteriskProtocol(self.host, self._stop_deferred) self.process = reactor.spawnProcess(self.process_protocol, cmd[0], cmd, env=os.environ) # Begin the wait fully booted cycle self.__start_asterisk_time = time.time() reactor.callLater(1, __execute_wait_fully_booted) def __execute_wait_fully_booted(): """Send the CLI command waitfullybooted""" cli_deferred = self.cli_exec("core waitfullybooted") cli_deferred.addCallbacks(__wait_fully_booted_callback, __wait_fully_booted_error) def __wait_fully_booted_callback(cli_command): """Callback for CLI command waitfullybooted""" if "Asterisk has fully booted" in cli_command.output: msg = "Successfully started Asterisk %s" % self.host self._start_deferred.callback(msg) else: LOGGER.debug("Asterisk core waitfullybooted failed " + "with output '%s', attempting again..." % cli_command.output) reactor.callLater(1, __execute_wait_fully_booted) return cli_command def __wait_fully_booted_error(cli_command): """Errback for CLI command waitfullybooted""" timeout = 90 if self.valgrind_enabled else 5 if time.time() - self.__start_asterisk_time > timeout: msg = "Asterisk core waitfullybooted for %s failed" % self.host LOGGER.error(msg) self._start_deferred.errback(Exception(msg)) else: msg = "Asterisk core waitfullybooted failed, attempting again" LOGGER.debug(msg) reactor.callLater(1, __execute_wait_fully_booted) return cli_command self.install_configs(os.getcwd() + "/configs", deps) self._setup_configs() cmd_prefix = [] if os.getenv("VALGRIND_ENABLE") == "true": valgrind_path = test_suite_utils.which('valgrind') if valgrind_path: cmd_prefix = [ valgrind_path, '--xml=yes', '--xml-file=%s' % self.get_path("astlogdir", 'valgrind.xml'), '--xml-user-comment=%s (%s)' % ( os.environ['TESTSUITE_ACTIVE_TEST'], self.host)] suppression_file = 'contrib/valgrind/suppressions.txt' if os.path.exists(suppression_file): cmd_prefix.append('--suppressions=%s' % suppression_file) else: LOGGER.error('Valgrind not found') cmd = cmd_prefix + [ self.ast_binary, "-f", "-g", "-q", "-m", "-n", "-C", "%s" % os.path.join(self.astetcdir, "asterisk.conf") ] # Make the start/stop deferreds - this method will return # the start deferred, and pass the stop deferred to the AsteriskProtocol # object. The stop deferred will be raised when the Asterisk process # exits self._start_deferred = defer.Deferred() self._stop_deferred = defer.Deferred() # Asterisk will attempt to use built in configuration information if # it can't find the configuration files that are being installed - which # can happen due to the files being created due to a copy operation. # If that happens, the test will fail - wait a second to give # Asterisk time to come up fully reactor.callLater(0, __start_asterisk_callback, cmd) return self._start_deferred
def __init__(self, base=None, ast_conf_options=None, host="127.0.0.1"): """Construct an Asterisk instance. Keyword Arguments: base -- This is the root of the files associated with this instance of Asterisk. By default, the base is "/tmp/asterisk-testsuite" directory. Given a base, it will be appended to the default base directory. Example Usage: self.asterisk = Asterisk(base="manager/login") """ self._start_deferred = None self._stop_deferred = None self._stop_cancel_tokens = [] self.directories = {} self.ast_version = AsteriskVersion() self.process_protocol = None self.process = None self.astetcdir = "" self.original_astmoddir = "" valgrind_env = os.getenv("VALGRIND_ENABLE") or "" self.valgrind_enabled = True if "true" in valgrind_env else False if base is not None: self.base = base else: self.base = Asterisk.test_suite_root if self.localtest_root: self.ast_binary = self.localtest_root + "/usr/sbin/asterisk" else: ast_binary = test_suite_utils.which("asterisk") self.ast_binary = ast_binary or "/usr/sbin/asterisk" self.host = host self._ast_conf_options = ast_conf_options self._directory_structure_made = False self._configs_installed = False self._configs_set_up = False # Find the system installed asterisk.conf ast_confs = [ os.path.join(self.default_etc_directory, "asterisk.conf"), "/usr/local/etc/asterisk/asterisk.conf", ] self._ast_conf = None for config in ast_confs: if os.path.exists(config): self._ast_conf = ConfigFile(config) break if self._ast_conf is None: msg = "Unable to locate asterisk.conf in any known location" LOGGER.error(msg) raise Exception(msg) # Set which astxxx this instance will be i = 1 while True: if not os.path.isdir("%s/ast%d" % (self.base, i)): self.base = "%s/ast%d" % (self.base, i) break i += 1 # Get the Asterisk directories from the Asterisk config file for cat in self._ast_conf.categories: if cat.name == "directories": for (var, val) in cat.options: self.directories[var] = val # self.original_astmoddir is for dependency checking only if "astmoddir" in self.directories: if self.localtest_root: self.original_astmoddir = "%s%s" % ( self.localtest_root, self.directories["astmoddir"]) else: self.original_astmoddir = self.directories["astmoddir"]
def start(self, deps=None): """Start this instance of Asterisk. Returns: A deferred object that will be called when Asterisk is fully booted. Example Usage: asterisk.start() Note that calling this will install the default testsuite config files, if they have not already been installed """ def __start_asterisk_callback(cmd): """Begin the Asterisk startup cycle""" self.__start_asterisk_time = time.time() if self.remote_config: reactor.callLater(0, __execute_wait_fully_booted) return self.protocol = AsteriskProtocol(self.host, self._stop_deferred) self.process = reactor.spawnProcess(self.protocol, cmd[0], cmd, env=os.environ) # Begin the wait fully booted cycle reactor.callLater(1, __execute_wait_fully_booted) def __execute_wait_fully_booted(): """Send the CLI command waitfullybooted""" cli_deferred = self.cli_exec("core waitfullybooted") cli_deferred.addCallbacks(__wait_fully_booted_callback, __wait_fully_booted_error) def __wait_fully_booted_callback(cli_command): """Callback for CLI command waitfullybooted""" if "Asterisk has fully booted" in cli_command.output: msg = "Successfully started Asterisk %s" % self.host self._start_deferred.callback(msg) else: LOGGER.debug("Asterisk core waitfullybooted failed " + "with output '%s', attempting again..." % cli_command.output) reactor.callLater(1, __execute_wait_fully_booted) return cli_command def __wait_fully_booted_error(cli_command): """Errback for CLI command waitfullybooted""" timeout = 90 if self.valgrind_enabled else 45 if time.time() - self.__start_asterisk_time > timeout: msg = "Asterisk core waitfullybooted for %s failed" % self.host LOGGER.error(msg) self._start_deferred.errback(Exception(msg)) else: msg = "Asterisk core waitfullybooted failed, attempting again" LOGGER.debug(msg) reactor.callLater(1, __execute_wait_fully_booted) return cli_command self.install_configs(os.getcwd() + "/configs", deps) self._setup_configs() cmd_prefix = [] if os.getenv("VALGRIND_ENABLE") == "true": valgrind_path = test_suite_utils.which('valgrind') if valgrind_path: cmd_prefix = [ valgrind_path, '--xml=yes', '--xml-file=%s' % self.get_path("astlogdir", 'valgrind.xml'), '--xml-user-comment=%s (%s)' % ( os.environ['TESTSUITE_ACTIVE_TEST'], self.host)] suppression_file = 'contrib/valgrind/suppressions.txt' if os.path.exists(suppression_file): cmd_prefix.append('--suppressions=%s' % suppression_file) else: LOGGER.error('Valgrind not found') cmd = cmd_prefix + [ self.ast_binary, "-f", "-g", "-q", "-m", "-n", "-C", "%s" % os.path.join(self.astetcdir, "asterisk.conf") ] # Make the start/stop deferreds - this method will return # the start deferred, and pass the stop deferred to the AsteriskProtocol # object. The stop deferred will be raised when the Asterisk process # exits self._start_deferred = defer.Deferred() self._stop_deferred = defer.Deferred() # Asterisk will attempt to use built in configuration information if # it can't find the configuration files that are being installed - which # can happen due to the files being created due to a copy operation. # If that happens, the test will fail - wait a second to give # Asterisk time to come up fully reactor.callLater(0, __start_asterisk_callback, cmd) return self._start_deferred
def __init__(self, base=None, ast_conf_options=None, host="127.0.0.1", remote_config=None): """Construct an Asterisk instance. Keyword Arguments: base -- This is the root of the files associated with this instance of Asterisk. By default, the base is "/tmp/asterisk-testsuite" directory. Given a base, it will be appended to the default base directory. ast_conf_options -- Configuration overrides for asterisk.conf. host -- The IP address the Asterisk instance runs on remote_config -- Configuration section that defines this as a remote Asterisk instance. If provided, base and ast_conf_options are generally ignored, and the Asterisk instance's configuration is treated as immutable on some remote machine defined by 'host' Example Usage: self.asterisk = Asterisk(base="manager/login") """ self._start_deferred = None self._stop_deferred = None self._stop_cancel_tokens = [] self.directories = {} self.protocol = None self.process = None self.astetcdir = "" self.original_astmoddir = "" self.ast_version = None self.remote_config = remote_config # If the process is remote, don't bother if not self.remote_config: self.ast_version = AsteriskVersion() valgrind_env = os.getenv("VALGRIND_ENABLE") or "" self.valgrind_enabled = True if "true" in valgrind_env else False if base is not None: self.base = base else: self.base = Asterisk.test_suite_root if self.localtest_root: self.ast_binary = self.localtest_root + "/usr/sbin/asterisk" else: ast_binary = test_suite_utils.which("asterisk") self.ast_binary = ast_binary or "/usr/sbin/asterisk" self.host = host self._ast_conf_options = ast_conf_options if self.remote_config: # Pretend as if we made the structure self._directory_structure_made = True self._configs_installed = True self._configs_set_up = True # And assume we've got /etc/asterisk/ where we expect it to be self.astetcdir = "/etc/asterisk" else: self._directory_structure_made = False self._configs_installed = False self._configs_set_up = False # Find the system installed asterisk.conf ast_confs = [ os.path.join(self.default_etc_directory, "asterisk.conf"), "/usr/local/etc/asterisk/asterisk.conf", ] self._ast_conf = None for config in ast_confs: if os.path.exists(config): self._ast_conf = ConfigFile(config) break if self._ast_conf is None: msg = "Unable to locate asterisk.conf in any known location" LOGGER.error(msg) raise Exception(msg) # Set which astxxx this instance will be i = 1 while True: if not os.path.isdir("%s/ast%d" % (self.base, i)): self.base = "%s/ast%d" % (self.base, i) break i += 1 # Get the Asterisk directories from the Asterisk config file for cat in self._ast_conf.categories: if cat.name == "directories": for (var, val) in cat.options: self.directories[var] = val # self.original_astmoddir is for dependency checking only if "astmoddir" in self.directories: if self.localtest_root: self.original_astmoddir = "%s%s" % ( self.localtest_root, self.directories["astmoddir"]) else: self.original_astmoddir = self.directories["astmoddir"]
def __init__(self, base=None, ast_conf_options=None, host="127.0.0.1"): """Construct an Asterisk instance. Keyword Arguments: base -- This is the root of the files associated with this instance of Asterisk. By default, the base is "/tmp/asterisk-testsuite" directory. Given a base, it will be appended to the default base directory. Example Usage: self.asterisk = Asterisk(base="manager/login") """ self._start_deferred = None self._stop_deferred = None self._stop_cancel_tokens = [] self.directories = {} self.ast_version = AsteriskVersion() self.process_protocol = None self.process = None self.astetcdir = "" self.original_astmoddir = "" if base is not None: self.base = base else: self.base = Asterisk.test_suite_root if self.localtest_root: self.ast_binary = self.localtest_root + "/usr/sbin/asterisk" else: ast_binary = test_suite_utils.which("asterisk") self.ast_binary = ast_binary or "/usr/sbin/asterisk" self.host = host self._ast_conf_options = ast_conf_options self._directory_structure_made = False self._configs_installed = False self._configs_set_up = False # Find the system installed asterisk.conf ast_confs = [ os.path.join(self.default_etc_directory, "asterisk.conf"), "/usr/local/etc/asterisk/asterisk.conf", ] self._ast_conf = None for config in ast_confs: if os.path.exists(config): self._ast_conf = ConfigFile(config) break if self._ast_conf is None: msg = "Unable to locate asterisk.conf in any known location" LOGGER.error(msg) raise Exception(msg) # Set which astxxx this instance will be i = 1 while True: if not os.path.isdir("%s/ast%d" % (self.base, i)): self.base = "%s/ast%d" % (self.base, i) break i += 1 # Get the Asterisk directories from the Asterisk config file for cat in self._ast_conf.categories: if cat.name == "directories": for (var, val) in cat.options: self.directories[var] = val # self.original_astmoddir is for dependency checking only if "astmoddir" in self.directories: if self.localtest_root: self.original_astmoddir = "%s%s" % ( self.localtest_root, self.directories["astmoddir"]) else: self.original_astmoddir = self.directories["astmoddir"]