commit 6c3fb340a83865f75399c60b4e9201810f60c8ee Author: Damian Johnson atagar@torproject.org Date: Sat Jan 21 15:34:43 2012 -0800
Moving test target attributes to config
Moving the attributes for integration testing targets from a big dictionary in the source to a separate configuration file. Progress! --- run_tests.py | 141 +++++++++++++++-------------------------------------- stem/util/conf.py | 15 ++++-- stem/util/enum.py | 26 +++++++++- test/settings.cfg | 58 ++++++++++++++++++++++ 4 files changed, 131 insertions(+), 109 deletions(-)
diff --git a/run_tests.py b/run_tests.py index 770953d..fdd6901 100755 --- a/run_tests.py +++ b/run_tests.py @@ -32,7 +32,7 @@ import stem.util.enum import stem.util.log as log import stem.util.term as term
-OPT = "uic:t:l:h" +OPT = "uic:l:t:h" OPT_EXPANDED = ["unit", "integ", "config=", "targets=", "log=", "tor=", "help"] DIVIDER = "=" * 70
@@ -64,99 +64,21 @@ INTEG_TESTS = ( # Integration tests above the basic suite. TARGETS = stem.util.enum.Enum(*[(v, v) for v in ("ONLINE", "RELATIVE", "CONN_NONE", "CONN_OPEN", "CONN_PASSWORD", "CONN_COOKIE", "CONN_MULTIPLE", "CONN_SOCKET", "CONN_SCOOKIE", "CONN_PTRACE", "CONN_ALL")])
-# Attributes that integ targets can have are... -# -# config -# Configuration option with which this is synced. If an option is set via -# both the config and '--target' argument then the argument takes precedence. -# -# description -# The '--help' description of the target. -# -# prereq -# Version that we need to run the target. -# -# torrc -# Configuration options for the test instance. For each of these targets that -# we have we make an integration test run. -# -# TODO: This is a very, very long block and it's only gonna get worse. Should -# this be moved to a 'settings.cfg'? It might be problematic due to constants. +CONFIG = { + "target.config": {}, + "target.description": {}, + "target.prereq": {}, + "target.torrc": {}, +}
-TARGET_ATTR = { - TARGETS.ONLINE: { - "config": "test.integ.target.online", - "description": "Includes tests that require network activity.", - }, - TARGETS.RELATIVE: { - "config": "test.integ.target.relative_data_dir", - "description": "Uses a relative path for tor's data directory.", - }, - TARGETS.CONN_NONE: { - "config": "test.integ.target.connection.none", - "description": "Configuration without a way for controllers to connect.", - "torrc": (), - }, - TARGETS.CONN_OPEN: { - "config": "test.integ.target.connection.open", - "description": "Configuration with an open control port (default).", - "torrc": ( - test.runner.OPT_PORT, - ), - }, - TARGETS.CONN_PASSWORD: { - "config": "test.integ.target.connection.password", - "description": "Configuration with password authentication.", - "torrc": ( - test.runner.OPT_PORT, - test.runner.OPT_PASSWORD, - ), - }, - TARGETS.CONN_COOKIE: { - "config": "test.integ.target.connection.cookie", - "description": "Configuration with an authentication cookie.", - "torrc": ( - test.runner.OPT_PORT, - test.runner.OPT_COOKIE, - ), - }, - TARGETS.CONN_MULTIPLE: { - "config": "test.integ.target.connection.multiple", - "description": "Configuration with both password and cookie authentication.", - "torrc": ( - test.runner.OPT_PORT, - test.runner.OPT_PASSWORD, - test.runner.OPT_COOKIE, - ), - }, - TARGETS.CONN_SOCKET: { - "config": "test.integ.target.connection.socket", - "description": "Configuration with a control socket.", - "torrc": ( - test.runner.OPT_SOCKET, - ), - }, - TARGETS.CONN_SCOOKIE: { - "config": "test.integ.target.connection.scookie", - "description": "Configuration with a control socket and authentication cookie.", - "torrc": ( - test.runner.OPT_SOCKET, - test.runner.OPT_COOKIE, - ), - }, - TARGETS.CONN_PTRACE: { - "config": "test.integ.target.connection.ptrace", - "description": "Configuration with an open control port and 'DisableDebuggerAttachment 0'", - "prereq": stem.version.Requirement.DISABLE_DEBUGGER_ATTACHMENT, - "torrc": ( - test.runner.OPT_PORT, - test.runner.OPT_PTRACE, - ), - }, - TARGETS.CONN_ALL: { - "config": "test.integ.target.connection.all", - "description": "Runs integration tests for all connection configurations.", - }, +# mapping between 'target.torrc' options and runner attributes +# TODO: switch OPT_* to enums so this is unnecessary +RUNNER_OPT_MAPPING = { + "PORT": test.runner.OPT_PORT, + "PASSWORD": test.runner.OPT_PASSWORD, + "COOKIE": test.runner.OPT_COOKIE, + "SOCKET": test.runner.OPT_SOCKET, + "PTRACE": test.runner.OPT_PTRACE, }
DEFAULT_RUN_TARGET = TARGETS.CONN_OPEN @@ -202,11 +124,26 @@ def print_logging(logging_buffer): print
if __name__ == '__main__': + # loads the builtin testing configuration + stem_path = os.path.join(*os.path.split(__file__)[:-1]) + stem_path = stem.util.system.expand_path(stem_path) + settings_path = os.path.join(stem_path, "test", "settings.cfg") + + test_config = stem.util.conf.get_config("test") + test_config.load(settings_path) + test_config.update(CONFIG) + + # parses target.torrc as csv values and convert to runner OPT_* values + for target in CONFIG["target.torrc"]: + CONFIG["target.torrc"][target] = [] + + for opt in test_config.get_str_csv("target.torrc", [], sub_key = target): + CONFIG["target.torrc"][target].append(RUNNER_OPT_MAPPING[opt]) + start_time = time.time() run_unit_tests = False run_integ_tests = False config_path = None - test_config = stem.util.conf.get_config("test") override_targets = [] logging_runlevel = None tor_cmd = "tor" @@ -259,7 +196,7 @@ if __name__ == '__main__':
target_lines = [] for target in TARGETS: - target_lines.append(description_format % (target, TARGET_ATTR[target]["description"])) + target_lines.append(description_format % (target, CONFIG["target.description"].get(target, "")))
print HELP_MSG % "\n ".join(target_lines) sys.exit() @@ -294,7 +231,7 @@ if __name__ == '__main__': # override our configuration flags if both set a target.
for target in override_targets: - target_config = TARGET_ATTR[target].get("config") + target_config = CONFIG["target.config"].get(target) if target_config: test_config.set(target_config, "true")
error_tracker = test.output.ErrorTracker() @@ -332,14 +269,14 @@ if __name__ == '__main__': # Queue up all the targets with torrc options we want to run against.
integ_run_targets = [] - all_run_targets = [t for t in TARGETS if "torrc" in TARGET_ATTR[t]] + all_run_targets = [t for t in TARGETS if CONFIG["target.torrc"].get(t)]
if test_config.get("test.integ.target.connection.all", False): # test against everything with torrc options integ_run_targets = all_run_targets else: for target in all_run_targets: - target_config = TARGET_ATTR[target].get("config") + target_config = CONFIG["target.config"].get(target)
if target_config and test_config.get(target_config, False): integ_run_targets.append(target) @@ -354,21 +291,21 @@ if __name__ == '__main__': our_version, skip_targets = None, []
for target in integ_run_targets: - target_prereq = TARGET_ATTR[target].get("prereq") + target_prereq = CONFIG["target.prereq"].get(target)
if target_prereq: # lazy loaded to skip system call if we don't have any prereqs if not our_version: our_version = stem.version.get_system_tor_version(tor_cmd)
- if our_version < target_prereq: + if our_version < stem.version.Requirement[target_prereq]: skip_targets.append(target)
for target in integ_run_targets: if target in skip_targets: continue
try: - integ_runner.start(tor_cmd, extra_torrc_opts = TARGET_ATTR[target].get("torrc", [])) + integ_runner.start(tor_cmd, extra_torrc_opts = CONFIG["target.torrc"].get(target, []))
print term.format("Running tests...", term.Color.BLUE, term.Attr.BOLD) print @@ -392,7 +329,7 @@ if __name__ == '__main__': print
for target in skip_targets: - print term.format("Unable to run target %s, this requires tor version %s" % (target, TARGET_ATTR[target]["prereq"]), term.Color.RED, term.Attr.BOLD) + print term.format("Unable to run target %s, this requires tor version %s" % (target, CONFIG["target.prereq"][target]), term.Color.RED, term.Attr.BOLD)
diff --git a/stem/util/conf.py b/stem/util/conf.py index 199a20c..132dbce 100644 --- a/stem/util/conf.py +++ b/stem/util/conf.py @@ -375,7 +375,7 @@ class Config():
return val
- def get_str_csv(self, key, default = None, count = None): + def get_str_csv(self, key, default = None, count = None, sub_key = None): """ Fetches the given key as a comma separated value.
@@ -385,13 +385,18 @@ class Config(): the count count (int) - if set then the default is returned when the number of elements doesn't match this value + sub_key (str) - handle the configuration entry as a dictionary and use + this key within it
Returns: list with the stripped values """
- conf_value = self.get_value(key) + if sub_key: conf_value = self.get(key, {}).get(sub_key) + else: conf_value = self.get_value(key) + if conf_value == None: return default + elif not conf_value.strip(): return [] # empty string else: conf_comp = [entry.strip() for entry in conf_value.split(",")]
@@ -407,7 +412,7 @@ class Config():
return conf_comp
- def get_int_csv(self, key, default = None, count = None, min_value = None, max_value = None): + def get_int_csv(self, key, default = None, count = None, min_value = None, max_value = None, sub_key = None): """ Fetches the given comma separated value, returning the default if the values aren't integers or don't follow the given constraints. @@ -419,12 +424,14 @@ class Config(): count (int) - checks that the number of values matches this if set min_value (int) - checks that all values are over this if set max_value (int) - checks that all values are under this if set + sub_key (str) - handle the configuration entry as a dictionary and use + this key within it
Returns: list with the stripped values """
- conf_comp = self.get_str_csv(key, default, count) + conf_comp = self.get_str_csv(key, default, count, sub_key) if conf_comp == default: return default
# validates the input, setting the error_msg if there's a problem diff --git a/stem/util/enum.py b/stem/util/enum.py index 6891663..c750352 100644 --- a/stem/util/enum.py +++ b/stem/util/enum.py @@ -80,7 +80,7 @@ class Enum: Provides the index of the given value in the collection.
Arguments: - value - entry to be looked up + value (str) - entry to be looked up
Returns: integer index of the given entry @@ -96,7 +96,7 @@ class Enum: Provides the next enumeration after the given value.
Arguments: - value - enumeration for which to get the next entry + value (str) - enumeration for which to get the next entry
Returns: enum value following the given entry @@ -116,7 +116,7 @@ class Enum: Provides the previous enumeration before the given value.
Arguments: - value - enumeration for which to get the previous entry + value (str) - enumeration for which to get the previous entry
Returns: enum value proceeding the given entry @@ -131,6 +131,26 @@ class Enum: prev_index = (self._values.index(value) - 1) % len(self._values) return self._values[prev_index]
+ def __getitem__(self, item): + """ + Provides the values for the given key. + + Arguments: + item (str) - key to be looked up + + Returns: + str with the value for the given key + + Raises: + ValueError if the key doesn't exist + """ + + if item in self.__dict__: + return self.__dict__[item] + else: + keys = ", ".join(self.keys()) + raise ValueError("'%s' isn't among our enumeration keys, which includes: %s" % (item, keys)) + def __iter__(self): """ Provides an ordered listing of the enums in this set. diff --git a/test/settings.cfg b/test/settings.cfg new file mode 100644 index 0000000..75977d6 --- /dev/null +++ b/test/settings.cfg @@ -0,0 +1,58 @@ +# Testing Configuration +# +# The following are globally accessable configuration attributes used by stem's +# unit and integration tests. Top level configuraion categories are... +# +# target.* - Attributes of the integration testing targets. This helps +# determine what is ran when the user runs with '--target'. + + ################## +# CATEGORY: TARGET # + ################## + +# Configuration option with which the target is synced. If an option is set via +# both the config and '--target' argument then the argument takes precedence. + +target.config ONLINE => test.integ.target.online +target.config RELATIVE => test.integ.target.relative_data_dir +target.config CONN_NONE => test.integ.target.connection.none +target.config CONN_OPEN => test.integ.target.connection.open +target.config CONN_PASSWORD => test.integ.target.connection.password +target.config CONN_COOKIE => test.integ.target.connection.cookie +target.config CONN_MULTIPLE => test.integ.target.connection.multiple +target.config CONN_SOCKET => test.integ.target.connection.socket +target.config CONN_SCOOKIE => test.integ.target.connection.scookie +target.config CONN_PTRACE => test.integ.target.connection.ptrace +target.config CONN_ALL => test.integ.target.connection.all + +# The '--help' description of the target. + +target.description ONLINE => Includes tests that require network activity. +target.description RELATIVE => Uses a relative path for tor's data directory. +target.description CONN_NONE => Configuration without a way for controllers to connect. +target.description CONN_OPEN => Configuration with an open control port (default). +target.description CONN_PASSWORD => Configuration with password authentication. +target.description CONN_COOKIE => Configuration with an authentication cookie. +target.description CONN_MULTIPLE => Configuration with both password and cookie authentication. +target.description CONN_SOCKET => Configuration with a control socket. +target.description CONN_SCOOKIE => Configuration with a control socket and authentication cookie. +target.description CONN_PTRACE => Configuration with an open control port and 'DisableDebuggerAttachment 0' +target.description CONN_ALL => Runs integration tests for all connection configurations. + +# Version that we need to run the target. These need to match an enumeration of +# stem.version.Requirement. + +target.prereq CONN_PTRACE => DISABLE_DEBUGGER_ATTACHMENT + +# Torrc configuration options included with the target. Having this option set +# means that each of these targets will have a dedicated integration test run. + +target.torrc CONN_NONE => +target.torrc CONN_OPEN => PORT +target.torrc CONN_PASSWORD => PORT, PASSWORD +target.torrc CONN_COOKIE => PORT, COOKIE +target.torrc CONN_MULTIPLE => PORT, PASSWORD, COOKIE +target.torrc CONN_SOCKET => SOCKET +target.torrc CONN_SCOOKIE => SOCKET, COOKIE +target.torrc CONN_PTRACE => PORT, PTRACE +
tor-commits@lists.torproject.org