commit 74ba2e9db42508a2bc2873dd078ae5bf2cbd140e Author: Damian Johnson atagar@torproject.org Date: Fri Aug 24 12:38:20 2012 -0700
Revisions for EXTENDCIRCUIT addition
Couple minor changes:
* The EXTENDCIRCUIT integ tests fails if we don't have an internet connection. Making it dependent on the ONLINE testing target.
* Revising the pydocs a bit. For instance, there's no point in saying "If the purpose isn't provided, "general" circuits are built." when we can simply provide a default for the argument. ;)
However, there's still a couple mysteries...
* When I was offline I got the following stacktrace...
====================================================================== ERROR: test_extendcircuit ---------------------------------------------------------------------- Traceback: File "/home/atagar/Desktop/stem/test/integ/control/controller.py", line 373, in test_extendcircuit circ_id = controller.extend_circuit(0) File "/home/atagar/Desktop/stem/stem/control.py", line 1109, in extend_circuit raise stem.socket.ProtocolError("EXTENDCIRCUIT returned unexpected response code: %s" % response.code) ProtocolError: EXTENDCIRCUIT returned unexpected response code: 512
----------------------------------------------------------------------
However, according to the control-spec the 512 response code is for "Syntax error in command argument". That doesn't make sense if we're failing because we lack a connection.
* Is the 'path' argument for EXTENDCIRCUIT the circuits that we build through, or the relays to be chosen from when building a single hop? The EXTENDCIRCUIT description doesn't say, which seems to me to be a weakness in the spec. --- stem/control.py | 37 ++++++++++++++++--------------------- test/integ/control/controller.py | 11 ++++------- test/runner.py | 15 +++++++++++++++ 3 files changed, 35 insertions(+), 28 deletions(-)
diff --git a/stem/control.py b/stem/control.py index 2f0c773..ece7f03 100644 --- a/stem/control.py +++ b/stem/control.py @@ -1055,43 +1055,39 @@ class Controller(BaseController):
raise stem.socket.ProtocolError("SIGNAL response contained unrecognized status code: %s" % response.code)
- def new_circuit(self, relays = None, purpose = None): + def new_circuit(self, path = None, purpose = "general"): """ - Requests Tor to build a new circuit. + Requests a new circuit. If the path isn't provided, one is automatically + selected.
- If the path isn't provided, one is automatically selected. If the purpose - isn't provided, "general" circuits are built. - - :param list,str relays: list of relay nicknames/longnames or a single nickname/longname + :param list,str path: one or more relays to make a circuit through :param str purpose: "general" or "controller"
- :returns: Circuit id of the newly created circuit + :returns: int of the circuit id of the newly created circuit """
- return self.extend_circuit(0, relays, purpose) + return self.extend_circuit(0, path, purpose)
- def extend_circuit(self, circuit=0, relays = None, purpose = None): + def extend_circuit(self, circuit = 0, path = None, purpose = "general"): """ - Requests Tor to build a new circuit or extend an existing circuit. + Either requests a new circuit or extend an existing one.
- When called without any arguments, a new general purpose circuit is created. - If circuit is zero, a new circuit is created. If circuit is non-zero, Tor - extends the existing circuit with that id . If the path isn't provided, one - is automatically selected. If the purpose isn't provided, "general" circuits - are built. + When called with a circuit value of zero (the default) a new circuit is + created, and when non-zero the circuit with that id is extended. If the + path isn't provided, one is automatically selected.
- :param int circuit: id of the circuit which needs extending - :param list,str relays: list of relay nicknames/longnames or a single nickname/longname + :param int circuit: id of a circuit to be extended + :param list,str path: one or more relays to make a circuit through :param str purpose: "general" or "controller"
- :returns: Circuit id of the created/extended circuit + :returns: int of the circuit id of the created or extended circuit
:raises: :class:`stem.socket.InvalidRequest` if one of the parameters were invalid """
args = [str(circuit)] - if type(relays) == str: relays = [relays] - if relays: args.append(",".join(relays)) + if type(path) == str: path = [path] + if path: args.append(",".join(path)) if purpose: args.append("purpose=%s" % purpose)
response = self.msg("EXTENDCIRCUIT %s" % " ".join(args)) @@ -1136,4 +1132,3 @@ def _case_insensitive_lookup(entries, key, default = UNDEFINED): if default != UNDEFINED: return default else: raise ValueError("key '%s' doesn't exist in dict: %s" % (key, entries))
- diff --git a/test/integ/control/controller.py b/test/integ/control/controller.py index 9a64d36..e1e24d8 100644 --- a/test/integ/control/controller.py +++ b/test/integ/control/controller.py @@ -336,8 +336,7 @@ class TestController(unittest.TestCase):
# the orconn-status results will be empty if we don't have a connection if orconn_output == '': - test.runner.skip(self, "(no tor connections)") - return + if test.runner.require_online(self): return
self.assertTrue(re.match("$[0-9a-fA-F]{40}[~=].*", controller.get_info('orconn-status').split()[0])) self.assertTrue("VERBOSE_NAMES" in controller.enabled_features) @@ -352,9 +351,8 @@ class TestController(unittest.TestCase): """ Test controller.signal with valid and invalid signals. """ - runner = test.runner.get_runner()
- with runner.get_tor_controller() as controller: + with test.runner.get_runner().get_tor_controller() as controller: # valid signal controller.signal("CLEARDNSCACHE")
@@ -366,10 +364,9 @@ class TestController(unittest.TestCase):
def test_extendcircuit(self): if test.runner.require_control(self): return + elif test.runner.require_online(self): return
- runner = test.runner.get_runner() - - with runner.get_tor_controller() as controller: + with test.runner.get_runner().get_tor_controller() as controller: circ_id = controller.extend_circuit(0) # check if our circuit was created self.assertTrue(filter(lambda x: int(x.split()[0]) == circ_id, controller.get_info('circuit-status').splitlines())) diff --git a/test/runner.py b/test/runner.py index 0d7ba2f..cc8cf7b 100644 --- a/test/runner.py +++ b/test/runner.py @@ -11,6 +11,7 @@ about the tor test instance they're running against. skip - skips the current test if we can require_control - skips the test unless tor provides a controller endpoint require_version - skips the test unless we meet a tor version requirement + require_online - skips unless targets allow for online tests exercise_controller - basic sanity check that a controller connection can be used
get_runner - Singleton for fetching our runtime context. @@ -141,6 +142,20 @@ def require_version(test_case, req_version): skip(test_case, "(requires %s)" % req_version) return True
+def require_online(test_case): + """ + Skips the test if we weren't started with the ONLINE target, which indicates + that tests requiring network connectivity should run. + + :param unittest.TestCase test_case: test being ran + + :returns: True if test should be skipped, False otherwise + """ + + if not CONFIG["integ.target.online"]: + skip(test_case, "(requires online target)") + return True + def only_run_once(test_case, test_name): """ Skips the test if it has ran before. If it hasn't then flags it as being ran.
tor-commits@lists.torproject.org