tor-commits
Threads by month
- ----- 2025 -----
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
May 2017
- 16 participants
- 1135 discussions

[tor-browser/tor-browser-52.1.1esr-7.0-1] Bug 16285: Exclude ClearKey system for now
by gk@torproject.org 22 May '17
by gk@torproject.org 22 May '17
22 May '17
commit e948ae5d404321a1ed0316ffb97baf45ee0163a5
Author: Georg Koppen <gk(a)torproject.org>
Date: Mon May 22 12:44:40 2017 +0000
Bug 16285: Exclude ClearKey system for now
In the past the ClearKey system had not been compiled when specifying
--disable-eme. But that changed and it is even bundled nowadays (see:
Mozilla's bug 1300654). We don't want to ship it right now as the use
case for it is not really visible while the code had security
vulnerabilities in the past.
---
browser/installer/package-manifest.in | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/browser/installer/package-manifest.in b/browser/installer/package-manifest.in
index 43c89a9..1233249 100644
--- a/browser/installer/package-manifest.in
+++ b/browser/installer/package-manifest.in
@@ -814,8 +814,8 @@ bin/libfreebl_32int64_3.so
; media
-@RESPATH@/gmp-clearkey/0.1/@DLL_PREFIX@clearkey@DLL_SUFFIX@
-@RESPATH@/gmp-clearkey/0.1/clearkey.info
+;@RESPATH@/gmp-clearkey/0.1/@DLL_PREFIX@clearkey@DLL_SUFFIX@
+;@RESPATH@/gmp-clearkey/0.1/clearkey.info
; gfx
#ifdef XP_WIN
1
0

[tor-browser/tor-browser-52.1.1esr-7.0-1] fixup! TB4: Tor Browser's Firefox preference overrides.
by gk@torproject.org 22 May '17
by gk@torproject.org 22 May '17
22 May '17
commit ba7cbd186c5692267ba80eb6a998c7abab2a76a9
Author: Georg Koppen <gk(a)torproject.org>
Date: Mon May 22 12:52:09 2017 +0000
fixup! TB4: Tor Browser's Firefox preference overrides.
Adapt preferences to take new EME related ones into account.
---
browser/app/profile/000-tor-browser.js | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/browser/app/profile/000-tor-browser.js b/browser/app/profile/000-tor-browser.js
index 7b0ad71..53d1ac2 100644
--- a/browser/app/profile/000-tor-browser.js
+++ b/browser/app/profile/000-tor-browser.js
@@ -228,12 +228,15 @@ pref("media.gmp-manager.url.override", "data:text/plain,");
// server. There is a local fallback that must be blocked now as well. See:
// https://bugzilla.mozilla.org/show_bug.cgi?id=1267495.
pref("media.gmp-manager.updateEnabled", false);
-// EME prefs: Strictly speaking these prefs don't need to be set as we are
-// using the --disable-eme compile flag. However, in order to not confuse users,
-// who might stumble upon them while looking into about:config, we set them to
-// 'false' communicating that EME is really disabled.
+// Mozilla is relying on preferences to make sure no DRM blob is downloaded and
+// run. Even though those prefs should be set correctly by specifying
+// --disable-eme (which we do), we disable all of them here as well for defense
+// in depth.
pref("browser.eme.ui.enabled", false);
+pref("media.gmp-eme-adobe.visible", false);
pref("media.gmp-eme-adobe.enabled", false);
+pref("media.gmp-widevinecdm.visible", false);
+pref("media.gmp-widevinecdm.enabled", false);
pref("media.eme.enabled", false);
pref("media.eme.apiVisible", false);
// WebIDE can bypass proxy settings for remote debugging. It also downloads
1
0

22 May '17
commit 08c290474d9f78c87016420458e2f4e517975c16
Author: Damian Johnson <atagar(a)torproject.org>
Date: Tue May 9 10:51:22 2017 -0700
Drop unused run_target from test runner
Our Runner class provided a run_target attribute but nothing used it. This is
because testing requirements are against the torrc instead.
---
run_tests.py | 2 +-
test/runner.py | 5 +----
2 files changed, 2 insertions(+), 5 deletions(-)
diff --git a/run_tests.py b/run_tests.py
index fc6d906..f4f49c0 100755
--- a/run_tests.py
+++ b/run_tests.py
@@ -233,7 +233,7 @@ def main():
error_tracker.set_category(target)
try:
- integ_runner.start(target, args.attribute_targets, args.tor_path, extra_torrc_opts = test.util.get_torrc_entries(target))
+ integ_runner.start(args.attribute_targets, args.tor_path, extra_torrc_opts = test.util.get_torrc_entries(target))
println('Running tests...\n', STATUS)
diff --git a/test/runner.py b/test/runner.py
index 69af65d..4b4d29d 100644
--- a/test/runner.py
+++ b/test/runner.py
@@ -147,7 +147,6 @@ class _MockChrootFile(object):
class Runner(object):
def __init__(self):
- self.run_target = None
self.attribute_targets = []
self._runner_lock = threading.RLock()
@@ -166,12 +165,11 @@ class Runner(object):
self._original_recv_message = None
- def start(self, run_target, attribute_targets, tor_cmd, extra_torrc_opts):
+ def start(self, attribute_targets, tor_cmd, extra_torrc_opts):
"""
Makes temporary testing resources and starts tor, blocking until it
completes.
- :param Target run_target: configuration we're running with
:param list attribute_targets: **Targets** for our non-configuration attributes
:param str tor_cmd: command to start tor with
:param list extra_torrc_opts: additional torrc options for our test instance
@@ -180,7 +178,6 @@ class Runner(object):
"""
with self._runner_lock:
- self.run_target = run_target
self.attribute_targets = attribute_targets
# if we're holding on to a tor process (running or not) then clean up after
1
0

22 May '17
commit 1b7cb4ff2ba853ee5021d8d5eb137f5922a06431
Author: Damian Johnson <atagar(a)torproject.org>
Date: Fri May 12 17:34:02 2017 -0700
Drop test runner's is_ptraceable() method
This method is effectively only used in one spot, and the caller can do this.
---
test/integ/util/connection.py | 5 ++---
test/runner.py | 18 +-----------------
test/util.py | 22 ++++++++++++++++++++--
3 files changed, 23 insertions(+), 22 deletions(-)
diff --git a/test/integ/util/connection.py b/test/integ/util/connection.py
index 63f62ff..f641a37 100644
--- a/test/integ/util/connection.py
+++ b/test/integ/util/connection.py
@@ -8,18 +8,17 @@ import unittest
import test.runner
from stem.util.connection import Resolver, get_connections, system_resolvers
+from test.util import require_ptrace
class TestConnection(unittest.TestCase):
+ @require_ptrace
def check_resolver(self, resolver):
runner = test.runner.get_runner()
if test.runner.Torrc.PORT not in runner.get_options():
self.skipTest('(no control port)')
return
- elif not runner.is_ptraceable():
- self.skipTest('(DisableDebuggerAttachment set)')
- return
elif resolver not in system_resolvers():
self.skipTest('(resolver unavailable on this platform)')
return
diff --git a/test/runner.py b/test/runner.py
index 4b4d29d..0f5a1d0 100644
--- a/test/runner.py
+++ b/test/runner.py
@@ -19,7 +19,6 @@ about the tor test instance they're running against.
|- stop - stops our tor instance and cleans up any temporary files
|- is_running - checks if our tor test instance is running
|- is_accessible - checks if our tor instance can be connected to
- |- is_ptraceable - checks if DisableDebuggerAttachment is set
|- get_options - custom torrc options used for our test instance
|- get_test_dir - testing directory path
|- get_torrc_path - path to our tor instance's torrc
@@ -48,10 +47,9 @@ import stem.process
import stem.socket
import stem.util.conf
import stem.util.enum
-import stem.version
from test.output import println, STATUS, ERROR, SUBSTATUS, NO_NL
-from test.util import Target, STEM_BASE, tor_version
+from test.util import Target, STEM_BASE
CONFIG = stem.util.conf.config_dict('test', {
'integ.test_directory': './test/data',
@@ -312,20 +310,6 @@ class Runner(object):
return Torrc.PORT in self._custom_opts or Torrc.SOCKET in self._custom_opts
- def is_ptraceable(self):
- """
- Checks if tor's 'DisableDebuggerAttachment' option is set. This feature has
- a lot of adverse side effects (:trac:`3313`).
-
- :returns: True if debugger attachment is allowed, False otherwise
- """
-
- # If we're running a tor version where ptrace is disabled and we didn't
- # set 'DisableDebuggerAttachment=1' then we can infer that it's disabled.
-
- has_option = tor_version() >= stem.version.Requirement.TORRC_DISABLE_DEBUGGER_ATTACHMENT
- return not has_option or Torrc.PTRACE in self.get_options()
-
def get_options(self):
"""
Provides the custom torrc options our tor instance is running with.
diff --git a/test/util.py b/test/util.py
index 7b6f312..99de3a6 100644
--- a/test/util.py
+++ b/test/util.py
@@ -303,6 +303,26 @@ def require_version(req_version):
return require(lambda: tor_version() >= req_version, 'requires %s' % req_version)
+def require_ptrace(func):
+ """
+ Skips the test unless 'DisableDebuggerAttachment' is set. This feature has a
+ lot of adverse side effects (:trac:`3313`).
+ """
+
+ def wrapped(self, *args, **kwargs):
+ # If we're running a tor version where ptrace is disabled and we didn't
+ # set 'DisableDebuggerAttachment=1' then we can infer that it's disabled.
+
+ has_option = tor_version() >= stem.version.Requirement.TORRC_DISABLE_DEBUGGER_ATTACHMENT
+
+ if not has_option or test.runner.Torrc.PTRACE in test.runner.get_runner().get_options():
+ return func(self, *args, **kwargs)
+ else:
+ self.skipTest('(DisableDebuggerAttachment is set)')
+
+ return wrapped
+
+
def require_online(func):
"""
Skips the test if we weren't started with the ONLINE target, which indicates
@@ -636,5 +656,3 @@ class Task(object):
import test.runner # needs to be imported at the end to avoid a circular dependency
-
-require_ptrace = require(test.runner.get_runner().is_ptraceable, 'DisableDebuggerAttachment is set')
1
0

[stem/master] Add normalize argument to ControlMessage.from_str()
by atagar@torproject.org 22 May '17
by atagar@torproject.org 22 May '17
22 May '17
commit 144692cb801bd421b107db142e6e1e034961518e
Author: Damian Johnson <atagar(a)torproject.org>
Date: Sun May 21 18:16:47 2017 -0700
Add normalize argument to ControlMessage.from_str()
Our get_message() testing helper just did a little normalization. Adding this
to ControlMessage.from_str() so callers don't need to do the whole carriage
return stuff.
---
stem/response/__init__.py | 13 ++++++++++++-
test/unit/doctest.py | 6 +++---
test/unit/interpreter/commands.py | 17 +++++-----------
test/unit/response/add_onion.py | 21 +++++++-------------
test/unit/response/authchallenge.py | 7 +++----
test/unit/response/events.py | 7 ++-----
test/unit/response/getconf.py | 25 ++++++++----------------
test/unit/response/getinfo.py | 27 +++++++++----------------
test/unit/response/mapaddress.py | 23 ++++++++--------------
test/unit/response/protocolinfo.py | 39 ++++++++++++-------------------------
test/unit/response/singleline.py | 23 +++++++---------------
test/unit/tutorial_examples.py | 9 +++------
test/util.py | 27 +------------------------
13 files changed, 80 insertions(+), 164 deletions(-)
diff --git a/stem/response/__init__.py b/stem/response/__init__.py
index a84654c..eadb25c 100644
--- a/stem/response/__init__.py
+++ b/stem/response/__init__.py
@@ -132,19 +132,30 @@ class ControlMessage(object):
"""
@staticmethod
- def from_str(content, msg_type = None, **kwargs):
+ def from_str(content, msg_type = None, normalize = False, **kwargs):
"""
Provides a ControlMessage for the given content.
.. versionadded:: 1.1.0
+ .. versionchanged:: 1.6.0
+ Added the normalize argument.
+
:param str content: message to construct the message from
:param str msg_type: type of tor reply to parse the content as
+ :param bool normalize: ensures expected carriage return and ending newline
+ are present
:param kwargs: optional keyword arguments to be passed to the parser method
:returns: stem.response.ControlMessage instance
"""
+ if normalize:
+ if not content.endswith('\n'):
+ content += '\n'
+
+ content = re.sub('([\r]?)\n', '\r\n', content)
+
msg = stem.socket.recv_message(io.StringIO(stem.util.str_tools._to_unicode(content)))
if msg_type is not None:
diff --git a/test/unit/doctest.py b/test/unit/doctest.py
index 06a6eaa..1240324 100644
--- a/test/unit/doctest.py
+++ b/test/unit/doctest.py
@@ -13,9 +13,10 @@ import stem.util.connection
import stem.util.str_tools
import stem.util.system
import stem.version
-
import test.util
+from stem.response import ControlMessage
+
try:
# added in python 3.3
from unittest.mock import Mock, patch
@@ -83,8 +84,7 @@ class TestDocumentation(unittest.TestCase):
'circuit-status': EXPECTED_CIRCUIT_STATUS,
}[arg]
- response = test.util.get_message(ADD_ONION_RESPONSE)
- stem.response.convert('ADD_ONION', response)
+ response = ControlMessage.from_str(ADD_ONION_RESPONSE, 'ADD_ONION', normalize = True)
controller.create_ephemeral_hidden_service.return_value = response
args['globs'] = {'controller': controller}
diff --git a/test/unit/interpreter/commands.py b/test/unit/interpreter/commands.py
index c8cbc09..020b14b 100644
--- a/test/unit/interpreter/commands.py
+++ b/test/unit/interpreter/commands.py
@@ -5,10 +5,8 @@ import stem
import stem.response
import stem.version
-import test.util
-
from stem.interpreter.commands import ControlInterpreter, _get_fingerprint
-
+from stem.response import ControlMessage
from test.unit.interpreter import CONTROLLER
try:
@@ -126,8 +124,7 @@ class TestInterpreterCommands(unittest.TestCase):
)
for content in event_contents:
- event = test.util.get_message(content)
- stem.response.convert('EVENT', event)
+ event = ControlMessage.from_str(content, 'EVENT', normalize = True)
interpreter._received_events.append(event)
self.assertEqual(EXPECTED_EVENTS_RESPONSE, interpreter.run_command('/events'))
@@ -168,10 +165,8 @@ class TestInterpreterCommands(unittest.TestCase):
self.assertEqual(expected, interpreter.run_command('/unrecognized'))
def test_getinfo(self):
- response = '250-version=0.2.5.1-alpha-dev (git-245ecfff36c0cecc)\r\n250 OK'
-
controller = Mock()
- controller.msg.return_value = test.util.get_message(response)
+ controller.msg.return_value = ControlMessage.from_str('250-version=0.2.5.1-alpha-dev (git-245ecfff36c0cecc)\r\n250 OK\r\n')
interpreter = ControlInterpreter(controller)
@@ -183,10 +178,8 @@ class TestInterpreterCommands(unittest.TestCase):
self.assertEqual('\x1b[1;31mkaboom!\x1b[0m\n', interpreter.run_command('getinfo process/user'))
def test_getconf(self):
- response = '250-Log=notice stdout\r\n250 Address'
-
controller = Mock()
- controller.msg.return_value = test.util.get_message(response)
+ controller.msg.return_value = ControlMessage.from_str('250-Log=notice stdout\r\n250 Address\r\n')
interpreter = ControlInterpreter(controller)
@@ -195,7 +188,7 @@ class TestInterpreterCommands(unittest.TestCase):
def test_setevents(self):
controller = Mock()
- controller.msg.return_value = test.util.get_message('250 OK')
+ controller.msg.return_value = ControlMessage.from_str('250 OK\r\n')
interpreter = ControlInterpreter(controller)
diff --git a/test/unit/response/add_onion.py b/test/unit/response/add_onion.py
index 048ca67..9430250 100644
--- a/test/unit/response/add_onion.py
+++ b/test/unit/response/add_onion.py
@@ -8,7 +8,7 @@ import stem
import stem.response
import stem.response.add_onion
-import test.util
+from stem.response import ControlMessage
WITH_PRIVATE_KEY = """250-ServiceID=gfzprpioee3hoppz
250-PrivateKey=RSA1024:MIICXgIBAAKBgQDZvYVxvKPTWhId/8Ss9fVxjAoFDsrJ3pk6HjHrEFRm3ypkK/vArbG9BrupzzYcyms+lO06O8b/iOSHuZI5mUEGkrYqQ+hpB2SkPUEzW7vcp8SQQivna3+LfkWH4JDqfiwZutU6MMEvU6g1OqK4Hll6uHbLpsfxkS/mGjyu1C9a9wIDAQABAoGBAJxsC3a25xZJqaRFfxwmIiptSTFy+/nj4T4gPQo6k/fHMKP/+P7liT9bm+uUwbITNNIjmPzxvrcKt+pNRR/92fizxr8QXr8l0ciVOLerbvdqvVUaQ/K1IVsblOLbactMvXcHactmqqLFUaZU9PPSDla7YkzikLDIUtHXQBEt4HEhAkEA/c4n+kpwi4odCaF49ESPbZC/Qejh7U9Tq10vAHzfrrGgQjnLw2UGDxJQXc9P12fGTvD2q3Q3VaMI8TKKFqZXsQJBANufh1zfP+xX/UfxJ4QzDUCHCu2gnyTDj3nG9Bc80E5g7NwR2VBXF1R+QQCK9GZcXd2y6vBYgrHOSUiLbVjGrycCQQDpOcs0zbjUEUuTsQUT+fiO50dJSrZpus6ZFxz85sMppeItWSzsVeYWbW7adYnZ2Gu72OPjM/0xPYsXEakhHSRRAkAxlVauNQjthv/72god4pi/VL224GiNmEkwKSa6iFRPHbrcBHuXk9IElWx/ft+mrHvUraw1DwaStgv9gNzzCghJAkEA08RegCRnIzuGvgeejLk4suIeCMD/11AvmSvxbRWS5rq1leSVo7uGLSnqDbwlzE4dGb5kH15NNAp14/l2Fu/yZg==
@@ -40,8 +40,7 @@ class TestAddOnionResponse(unittest.TestCase):
"""
# working case
- response = test.util.get_message(WITH_PRIVATE_KEY)
- stem.response.convert('ADD_ONION', response)
+ response = ControlMessage.from_str(WITH_PRIVATE_KEY, 'ADD_ONION', normalize = True)
# now this should be a AddOnionResponse (ControlMessage subclass)
self.assertTrue(isinstance(response, stem.response.ControlMessage))
@@ -57,9 +56,7 @@ class TestAddOnionResponse(unittest.TestCase):
Checks a response when there's a private key.
"""
- response = test.util.get_message(WITH_PRIVATE_KEY)
- stem.response.convert('ADD_ONION', response)
-
+ response = ControlMessage.from_str(WITH_PRIVATE_KEY, 'ADD_ONION', normalize = True)
self.assertEqual('gfzprpioee3hoppz', response.service_id)
self.assertTrue(response.private_key.startswith('MIICXgIBAAKB'))
self.assertEqual('RSA1024', response.private_key_type)
@@ -70,9 +67,7 @@ class TestAddOnionResponse(unittest.TestCase):
Checks a response when there's client credentials.
"""
- response = test.util.get_message(WITH_CLIENT_AUTH)
- stem.response.convert('ADD_ONION', response)
-
+ response = ControlMessage.from_str(WITH_CLIENT_AUTH, 'ADD_ONION', normalize = True)
self.assertEqual('oekn5sqrvcu4wote', response.service_id)
self.assertEqual(None, response.private_key)
self.assertEqual(None, response.private_key_type)
@@ -83,9 +78,7 @@ class TestAddOnionResponse(unittest.TestCase):
Checks a response without a private key.
"""
- response = test.util.get_message(WITHOUT_PRIVATE_KEY)
- stem.response.convert('ADD_ONION', response)
-
+ response = ControlMessage.from_str(WITHOUT_PRIVATE_KEY, 'ADD_ONION', normalize = True)
self.assertEqual('gfzprpioee3hoppz', response.service_id)
self.assertEqual(None, response.private_key)
self.assertEqual(None, response.private_key_type)
@@ -95,7 +88,7 @@ class TestAddOnionResponse(unittest.TestCase):
Checks a response that lack an initial service id.
"""
- response = test.util.get_message(WRONG_FIRST_KEY)
+ response = ControlMessage.from_str(WRONG_FIRST_KEY, normalize = True)
self.assertRaisesRegexp(stem.ProtocolError, 'ADD_ONION response should start with', stem.response.convert, 'ADD_ONION', response)
def test_no_key_type(self):
@@ -103,5 +96,5 @@ class TestAddOnionResponse(unittest.TestCase):
Checks a response that's missing the private key type.
"""
- response = test.util.get_message(MISSING_KEY_TYPE)
+ response = ControlMessage.from_str(MISSING_KEY_TYPE, normalize = True)
self.assertRaisesRegexp(stem.ProtocolError, 'ADD_ONION PrivateKey lines should be of the form', stem.response.convert, 'ADD_ONION', response)
diff --git a/test/unit/response/authchallenge.py b/test/unit/response/authchallenge.py
index 6a6533c..da195e1 100644
--- a/test/unit/response/authchallenge.py
+++ b/test/unit/response/authchallenge.py
@@ -8,7 +8,7 @@ import stem.response
import stem.response.authchallenge
import stem.socket
-import test.util
+from stem.response import ControlMessage
VALID_RESPONSE = '250 AUTHCHALLENGE \
SERVERHASH=B16F72DACD4B5ED1531F3FCC04B593D46A1E30267E636EA7C7F8DD7A2B7BAA05 \
@@ -27,8 +27,7 @@ class TestAuthChallengeResponse(unittest.TestCase):
Parses valid AUTHCHALLENGE responses.
"""
- control_message = test.util.get_message(VALID_RESPONSE)
- stem.response.convert('AUTHCHALLENGE', control_message)
+ control_message = ControlMessage.from_str(VALID_RESPONSE, 'AUTHCHALLENGE', normalize = True)
# now this should be a AuthChallengeResponse (ControlMessage subclass)
self.assertTrue(isinstance(control_message, stem.response.ControlMessage))
@@ -51,5 +50,5 @@ class TestAuthChallengeResponse(unittest.TestCase):
# constructed.
remaining_comp = auth_challenge_comp[:index] + auth_challenge_comp[index + 1:]
- control_message = test.util.get_message(' '.join(remaining_comp))
+ control_message = ControlMessage.from_str(' '.join(remaining_comp), normalize = True)
self.assertRaises(stem.ProtocolError, stem.response.convert, 'AUTHCHALLENGE', control_message)
diff --git a/test/unit/response/events.py b/test/unit/response/events.py
index b14b739..9031463 100644
--- a/test/unit/response/events.py
+++ b/test/unit/response/events.py
@@ -10,9 +10,8 @@ import stem.response
import stem.response.events
import stem.util.log
-import test.util
-
from stem import * # enums and exceptions
+from stem.response import ControlMessage
from stem.descriptor.router_status_entry import RouterStatusEntryV3
try:
@@ -457,9 +456,7 @@ TB_EMPTY_BAD_2 = '650 TB_EMPTY GLOBAL READ=93 WRITTEN=93 LAST=-100'
def _get_event(content):
- controller_event = test.util.get_message(content)
- stem.response.convert('EVENT', controller_event)
- return controller_event
+ return ControlMessage.from_str(content, 'EVENT', normalize = True)
class TestEvents(unittest.TestCase):
diff --git a/test/unit/response/getconf.py b/test/unit/response/getconf.py
index fb72ffc..c9765fc 100644
--- a/test/unit/response/getconf.py
+++ b/test/unit/response/getconf.py
@@ -8,9 +8,7 @@ import stem.response
import stem.response.getconf
import stem.socket
-import test.util
-
-EMPTY_RESPONSE = '250 OK'
+from stem.response import ControlMessage
SINGLE_RESPONSE = """\
250 DataDirectory=/home/neena/.tor"""
@@ -42,8 +40,7 @@ class TestGetConfResponse(unittest.TestCase):
Parses a GETCONF reply without options (just calling "GETCONF").
"""
- control_message = test.util.get_message(EMPTY_RESPONSE)
- stem.response.convert('GETCONF', control_message)
+ control_message = ControlMessage.from_str('250 OK\r\n', 'GETCONF')
# now this should be a GetConfResponse (ControlMessage subclass)
self.assertTrue(isinstance(control_message, stem.response.ControlMessage))
@@ -56,8 +53,7 @@ class TestGetConfResponse(unittest.TestCase):
Parses a GETCONF reply response for a single parameter.
"""
- control_message = test.util.get_message(SINGLE_RESPONSE)
- stem.response.convert('GETCONF', control_message)
+ control_message = ControlMessage.from_str(SINGLE_RESPONSE, 'GETCONF', normalize = True)
self.assertEqual({'DataDirectory': ['/home/neena/.tor']}, control_message.entries)
def test_batch_response(self):
@@ -65,9 +61,6 @@ class TestGetConfResponse(unittest.TestCase):
Parses a GETCONF reply for muiltiple parameters.
"""
- control_message = test.util.get_message(BATCH_RESPONSE)
- stem.response.convert('GETCONF', control_message)
-
expected = {
'CookieAuthentication': ['0'],
'ControlPort': ['9100'],
@@ -75,6 +68,7 @@ class TestGetConfResponse(unittest.TestCase):
'DirPort': [],
}
+ control_message = ControlMessage.from_str(BATCH_RESPONSE, 'GETCONF', normalize = True)
self.assertEqual(expected, control_message.entries)
def test_multivalue_response(self):
@@ -82,14 +76,12 @@ class TestGetConfResponse(unittest.TestCase):
Parses a GETCONF reply containing a single key with multiple parameters.
"""
- control_message = test.util.get_message(MULTIVALUE_RESPONSE)
- stem.response.convert('GETCONF', control_message)
-
expected = {
'ControlPort': ['9100'],
'ExitPolicy': ['accept 34.3.4.5', 'accept 3.4.53.3', 'accept 3.4.53.3', 'reject 23.245.54.3']
}
+ control_message = ControlMessage.from_str(MULTIVALUE_RESPONSE, 'GETCONF', normalize = True)
self.assertEqual(expected, control_message.entries)
def test_unrecognized_key_response(self):
@@ -97,11 +89,10 @@ class TestGetConfResponse(unittest.TestCase):
Parses a GETCONF reply that contains an error code with an unrecognized key.
"""
- control_message = test.util.get_message(UNRECOGNIZED_KEY_RESPONSE)
- self.assertRaises(stem.InvalidArguments, stem.response.convert, 'GETCONF', control_message)
-
try:
+ control_message = ControlMessage.from_str(UNRECOGNIZED_KEY_RESPONSE, normalize = True)
stem.response.convert('GETCONF', control_message)
+ self.fail('expected a stem.InvalidArguments to be raised')
except stem.InvalidArguments as exc:
self.assertEqual(exc.arguments, ['brickroad', 'submarine'])
@@ -112,5 +103,5 @@ class TestGetConfResponse(unittest.TestCase):
GETCONF's spec.
"""
- control_message = test.util.get_message(INVALID_RESPONSE)
+ control_message = ControlMessage.from_str(INVALID_RESPONSE, normalize = True)
self.assertRaises(stem.ProtocolError, stem.response.convert, 'GETCONF', control_message)
diff --git a/test/unit/response/getinfo.py b/test/unit/response/getinfo.py
index 2054a03..b08e311 100644
--- a/test/unit/response/getinfo.py
+++ b/test/unit/response/getinfo.py
@@ -9,9 +9,7 @@ import stem.response.getinfo
import stem.socket
import stem.util.str_tools
-import test.util
-
-EMPTY_RESPONSE = '250 OK'
+from stem.response import ControlMessage
SINGLE_RESPONSE = """\
250-version=0.2.3.11-alpha-dev
@@ -57,8 +55,7 @@ class TestGetInfoResponse(unittest.TestCase):
Parses a GETINFO reply without options (just calling "GETINFO").
"""
- control_message = test.util.get_message(EMPTY_RESPONSE)
- stem.response.convert('GETINFO', control_message)
+ control_message = ControlMessage.from_str('250 OK\r\n', 'GETINFO')
# now this should be a GetInfoResponse (ControlMessage subclass)
self.assertTrue(isinstance(control_message, stem.response.ControlMessage))
@@ -71,8 +68,7 @@ class TestGetInfoResponse(unittest.TestCase):
Parses a GETINFO reply response for a single parameter.
"""
- control_message = test.util.get_message(SINGLE_RESPONSE)
- stem.response.convert('GETINFO', control_message)
+ control_message = ControlMessage.from_str(SINGLE_RESPONSE, 'GETINFO', normalize = True)
self.assertEqual({'version': b'0.2.3.11-alpha-dev'}, control_message.entries)
def test_batch_response(self):
@@ -80,15 +76,13 @@ class TestGetInfoResponse(unittest.TestCase):
Parses a GETINFO reply for muiltiple parameters.
"""
- control_message = test.util.get_message(BATCH_RESPONSE)
- stem.response.convert('GETINFO', control_message)
-
expected = {
'version': b'0.2.3.11-alpha-dev',
'address': b'67.137.76.214',
'fingerprint': b'5FDE0422045DF0E1879A3738D09099EB4A0C5BA0',
}
+ control_message = ControlMessage.from_str(BATCH_RESPONSE, 'GETINFO', normalize = True)
self.assertEqual(expected, control_message.entries)
def test_multiline_response(self):
@@ -97,14 +91,12 @@ class TestGetInfoResponse(unittest.TestCase):
value.
"""
- control_message = test.util.get_message(MULTILINE_RESPONSE)
- stem.response.convert('GETINFO', control_message)
-
expected = {
'version': b'0.2.3.11-alpha-dev (git-ef0bc7f8f26a917c)',
'config-text': b'\n'.join(stem.util.str_tools._to_bytes(MULTILINE_RESPONSE).splitlines()[2:8]),
}
+ control_message = ControlMessage.from_str(MULTILINE_RESPONSE, 'GETINFO', normalize = True)
self.assertEqual(expected, control_message.entries)
def test_invalid_non_mapping_content(self):
@@ -113,7 +105,7 @@ class TestGetInfoResponse(unittest.TestCase):
entry.
"""
- control_message = test.util.get_message(NON_KEY_VALUE_ENTRY)
+ control_message = ControlMessage.from_str(NON_KEY_VALUE_ENTRY, normalize = True)
self.assertRaises(stem.ProtocolError, stem.response.convert, 'GETINFO', control_message)
def test_unrecognized_key_response(self):
@@ -121,11 +113,10 @@ class TestGetInfoResponse(unittest.TestCase):
Parses a GETCONF reply that contains an error code with an unrecognized key.
"""
- control_message = test.util.get_message(UNRECOGNIZED_KEY_ENTRY)
- self.assertRaises(stem.InvalidArguments, stem.response.convert, 'GETINFO', control_message)
-
try:
+ control_message = ControlMessage.from_str(UNRECOGNIZED_KEY_ENTRY, normalize = True)
stem.response.convert('GETINFO', control_message)
+ self.fail('expected a stem.InvalidArguments to be raised')
except stem.InvalidArguments as exc:
self.assertEqual(exc.arguments, ['blackhole'])
@@ -136,5 +127,5 @@ class TestGetInfoResponse(unittest.TestCase):
malformed according to the GETINFO's spec.
"""
- control_message = test.util.get_message(MISSING_MULTILINE_NEWLINE)
+ control_message = ControlMessage.from_str(MISSING_MULTILINE_NEWLINE, normalize = True)
self.assertRaises(stem.ProtocolError, stem.response.convert, 'GETINFO', control_message)
diff --git a/test/unit/response/mapaddress.py b/test/unit/response/mapaddress.py
index 63813d4..7482507 100644
--- a/test/unit/response/mapaddress.py
+++ b/test/unit/response/mapaddress.py
@@ -8,9 +8,7 @@ import stem.response
import stem.response.mapaddress
import stem.socket
-import test.util
-
-SINGLE_RESPONSE = """250 foo=bar"""
+from stem.response import ControlMessage
BATCH_RESPONSE = """\
250-foo=bar
@@ -36,8 +34,7 @@ class TestMapAddressResponse(unittest.TestCase):
Parses a MAPADDRESS reply response with a single address mapping.
"""
- control_message = test.util.get_message(SINGLE_RESPONSE)
- stem.response.convert('MAPADDRESS', control_message)
+ control_message = ControlMessage.from_str('250 foo=bar\r\n', 'MAPADDRESS')
self.assertEqual({'foo': 'bar'}, control_message.entries)
def test_batch_response(self):
@@ -45,9 +42,6 @@ class TestMapAddressResponse(unittest.TestCase):
Parses a MAPADDRESS reply with multiple address mappings
"""
- control_message = test.util.get_message(BATCH_RESPONSE)
- stem.response.convert('MAPADDRESS', control_message)
-
expected = {
'foo': 'bar',
'baz': 'quux',
@@ -55,6 +49,7 @@ class TestMapAddressResponse(unittest.TestCase):
'120.23.23.2': 'torproject.org'
}
+ control_message = ControlMessage.from_str(BATCH_RESPONSE, 'MAPADDRESS', normalize = True)
self.assertEqual(expected, control_message.entries)
def test_invalid_requests(self):
@@ -62,13 +57,11 @@ class TestMapAddressResponse(unittest.TestCase):
Parses a MAPADDRESS replies that contain an error code due to hostname syntax errors.
"""
- control_message = test.util.get_message(UNRECOGNIZED_KEYS_RESPONSE)
+ control_message = ControlMessage.from_str(UNRECOGNIZED_KEYS_RESPONSE, normalize = True)
self.assertRaises(stem.InvalidRequest, stem.response.convert, 'MAPADDRESS', control_message)
- expected = {'23': '324'}
- control_message = test.util.get_message(PARTIAL_FAILURE_RESPONSE)
- stem.response.convert('MAPADDRESS', control_message)
- self.assertEqual(expected, control_message.entries)
+ control_message = ControlMessage.from_str(PARTIAL_FAILURE_RESPONSE, 'MAPADDRESS', normalize = True)
+ self.assertEqual({'23': '324'}, control_message.entries)
def test_invalid_response(self):
"""
@@ -77,8 +70,8 @@ class TestMapAddressResponse(unittest.TestCase):
MAPADDRESS's spec.
"""
- control_message = test.util.get_message(INVALID_EMPTY_RESPONSE)
+ control_message = ControlMessage.from_str(INVALID_EMPTY_RESPONSE, normalize = True)
self.assertRaises(stem.ProtocolError, stem.response.convert, 'MAPADDRESS', control_message)
- control_message = test.util.get_message(INVALID_RESPONSE)
+ control_message = ControlMessage.from_str(INVALID_RESPONSE, normalize = True)
self.assertRaises(stem.ProtocolError, stem.response.convert, 'MAPADDRESS', control_message)
diff --git a/test/unit/response/protocolinfo.py b/test/unit/response/protocolinfo.py
index d8fb762..9b2c9b1 100644
--- a/test/unit/response/protocolinfo.py
+++ b/test/unit/response/protocolinfo.py
@@ -12,8 +12,7 @@ import stem.util.proc
import stem.util.system
import stem.version
-import test.util
-
+from stem.response import ControlMessage
from stem.response.protocolinfo import AuthMethod
try:
@@ -71,8 +70,7 @@ class TestProtocolInfoResponse(unittest.TestCase):
"""
# working case
- control_message = test.util.get_message(NO_AUTH)
- stem.response.convert('PROTOCOLINFO', control_message)
+ control_message = ControlMessage.from_str(NO_AUTH, 'PROTOCOLINFO', normalize = True)
# now this should be a ProtocolInfoResponse (ControlMessage subclass)
self.assertTrue(isinstance(control_message, stem.response.ControlMessage))
@@ -87,17 +85,14 @@ class TestProtocolInfoResponse(unittest.TestCase):
self.assertRaises(TypeError, stem.response.convert, 'PROTOCOLINFO', 'hello world')
# attempt to convert a different message type
- bw_event_control_message = test.util.get_message('650 BW 32326 2856')
- self.assertRaises(stem.ProtocolError, stem.response.convert, 'PROTOCOLINFO', bw_event_control_message)
+ self.assertRaises(stem.ProtocolError, ControlMessage.from_str, '650 BW 32326 2856\r\n', 'PROTOCOLINFO')
def test_no_auth(self):
"""
Checks a response when there's no authentication.
"""
- control_message = test.util.get_message(NO_AUTH)
- stem.response.convert('PROTOCOLINFO', control_message)
-
+ control_message = ControlMessage.from_str(NO_AUTH, 'PROTOCOLINFO', normalize = True)
self.assertEqual(1, control_message.protocol_version)
self.assertEqual(stem.version.Version('0.2.1.30'), control_message.tor_version)
self.assertEqual((AuthMethod.NONE, ), control_message.auth_methods)
@@ -109,8 +104,7 @@ class TestProtocolInfoResponse(unittest.TestCase):
Checks a response with password authentication.
"""
- control_message = test.util.get_message(PASSWORD_AUTH)
- stem.response.convert('PROTOCOLINFO', control_message)
+ control_message = ControlMessage.from_str(PASSWORD_AUTH, 'PROTOCOLINFO', normalize = True)
self.assertEqual((AuthMethod.PASSWORD, ), control_message.auth_methods)
def test_cookie_auth(self):
@@ -119,8 +113,7 @@ class TestProtocolInfoResponse(unittest.TestCase):
characters.
"""
- control_message = test.util.get_message(COOKIE_AUTH)
- stem.response.convert('PROTOCOLINFO', control_message)
+ control_message = ControlMessage.from_str(COOKIE_AUTH, 'PROTOCOLINFO', normalize = True)
self.assertEqual((AuthMethod.COOKIE, ), control_message.auth_methods)
self.assertEqual('/tmp/my data\\"dir//control_auth_cookie', control_message.cookie_path)
@@ -129,8 +122,7 @@ class TestProtocolInfoResponse(unittest.TestCase):
Checks a response with multiple authentication methods.
"""
- control_message = test.util.get_message(MULTIPLE_AUTH)
- stem.response.convert('PROTOCOLINFO', control_message)
+ control_message = ControlMessage.from_str(MULTIPLE_AUTH, 'PROTOCOLINFO', normalize = True)
self.assertEqual((AuthMethod.COOKIE, AuthMethod.PASSWORD), control_message.auth_methods)
self.assertEqual('/home/atagar/.tor/control_auth_cookie', control_message.cookie_path)
@@ -139,8 +131,7 @@ class TestProtocolInfoResponse(unittest.TestCase):
Checks a response with an unrecognized authtentication method.
"""
- control_message = test.util.get_message(UNKNOWN_AUTH)
- stem.response.convert('PROTOCOLINFO', control_message)
+ control_message = ControlMessage.from_str(UNKNOWN_AUTH, 'PROTOCOLINFO', normalize = True)
self.assertEqual((AuthMethod.UNKNOWN, AuthMethod.PASSWORD), control_message.auth_methods)
self.assertEqual(('MAGIC', 'PIXIE_DUST'), control_message.unknown_auth_methods)
@@ -150,9 +141,7 @@ class TestProtocolInfoResponse(unittest.TestCase):
information to be a valid response.
"""
- control_message = test.util.get_message(MINIMUM_RESPONSE)
- stem.response.convert('PROTOCOLINFO', control_message)
-
+ control_message = ControlMessage.from_str(MINIMUM_RESPONSE, 'PROTOCOLINFO', normalize = True)
self.assertEqual(5, control_message.protocol_version)
self.assertEqual(None, control_message.tor_version)
self.assertEqual((), control_message.auth_methods)
@@ -165,8 +154,7 @@ class TestProtocolInfoResponse(unittest.TestCase):
Checks an authentication cookie with a unicode path.
"""
- control_message = test.util.get_message(UNICODE_COOKIE_PATH)
- stem.response.convert('PROTOCOLINFO', control_message)
+ control_message = ControlMessage.from_str(UNICODE_COOKIE_PATH, 'PROTOCOLINFO', normalize = True)
self.assertEqual(EXPECTED_UNICODE_PATH, control_message.cookie_path)
@patch('stem.util.proc.is_available', Mock(return_value = False))
@@ -191,9 +179,7 @@ class TestProtocolInfoResponse(unittest.TestCase):
with patch('stem.util.system.call') as call_mock:
call_mock.side_effect = call_function
- control_message = test.util.get_message(RELATIVE_COOKIE_PATH)
- stem.response.convert('PROTOCOLINFO', control_message)
-
+ control_message = ControlMessage.from_str(RELATIVE_COOKIE_PATH, 'PROTOCOLINFO', normalize = True)
stem.connection._expand_cookie_path(control_message, stem.util.system.pid_by_name, 'tor')
self.assertEqual(os.path.join('/tmp/foo', 'tor-browser_en-US', 'Data', 'control_auth_cookie'), control_message.cookie_path)
@@ -202,6 +188,5 @@ class TestProtocolInfoResponse(unittest.TestCase):
# leaving the path unexpanded)
with patch('stem.util.system.call', Mock(return_value = None)):
- control_message = test.util.get_message(RELATIVE_COOKIE_PATH)
- stem.response.convert('PROTOCOLINFO', control_message)
+ control_message = ControlMessage.from_str(RELATIVE_COOKIE_PATH, 'PROTOCOLINFO', normalize = True)
self.assertEqual('./tor-browser_en-US/Data/control_auth_cookie', control_message.cookie_path)
diff --git a/test/unit/response/singleline.py b/test/unit/response/singleline.py
index 1c05aa5..76b252d 100644
--- a/test/unit/response/singleline.py
+++ b/test/unit/response/singleline.py
@@ -4,33 +4,24 @@ Unit tests for the stem.response.SingleLineResponse class.
import unittest
-import stem.response
-import stem.socket
+import stem
-import test.util
-
-MULTILINE_RESPONSE = """250-MULTI
-250 LINE"""
+from stem.response import ControlMessage
class TestSingleLineResponse(unittest.TestCase):
def test_single_line_response(self):
- message = test.util.get_message('552 NOTOK')
- stem.response.convert('SINGLELINE', message)
+ message = ControlMessage.from_str('552 NOTOK\r\n', 'SINGLELINE')
self.assertEqual(False, message.is_ok())
- message = test.util.get_message('250 KK')
- stem.response.convert('SINGLELINE', message)
+ message = ControlMessage.from_str('250 KK\r\n', 'SINGLELINE')
self.assertEqual(True, message.is_ok())
- message = test.util.get_message('250 OK')
- stem.response.convert('SINGLELINE', message)
+ message = ControlMessage.from_str('250 OK\r\n', 'SINGLELINE')
self.assertEqual(True, message.is_ok(True))
- message = test.util.get_message('250 HMM')
- stem.response.convert('SINGLELINE', message)
+ message = ControlMessage.from_str('250 HMM\r\n', 'SINGLELINE')
self.assertEqual(False, message.is_ok(True))
def test_multi_line_response(self):
- message = test.util.get_message(MULTILINE_RESPONSE)
- self.assertRaises(stem.ProtocolError, stem.response.convert, 'SINGLELINE', message)
+ self.assertRaises(stem.ProtocolError, ControlMessage.from_str, '250-MULTI\r\n250 LINE\r\n', 'SINGLELINE')
diff --git a/test/unit/tutorial_examples.py b/test/unit/tutorial_examples.py
index 2075bdf..50e766d 100644
--- a/test/unit/tutorial_examples.py
+++ b/test/unit/tutorial_examples.py
@@ -15,14 +15,13 @@ import stem.response
import stem.descriptor.remote
import stem.prereq
-import test.util
-
from stem.control import Controller
-from stem.util import str_type
from stem.descriptor.networkstatus import NetworkStatusDocumentV3
from stem.descriptor.remote import DIRECTORY_AUTHORITIES
from stem.descriptor.router_status_entry import ROUTER_STATUS_ENTRY_V3_HEADER, RouterStatusEntryV3
from stem.descriptor.server_descriptor import RelayDescriptor
+from stem.response import ControlMessage
+from stem.util import str_type
from test.unit import exec_documentation_example
@@ -100,9 +99,7 @@ A7569A83B5706AB1B1A9CB52EFF7D2D32E4553EB: caerSidi
def _get_event(content):
- controller_event = test.util.get_message(content)
- stem.response.convert('EVENT', controller_event)
- return controller_event
+ return ControlMessage.from_str(content, 'EVENT', normalize = True)
def _get_circ_event(id, status, hop1, hop2, hop3, purpose):
diff --git a/test/util.py b/test/util.py
index 47d90fd..7ad309d 100644
--- a/test/util.py
+++ b/test/util.py
@@ -12,7 +12,6 @@ Helper functions for our test framework.
get_prereq - provides the tor version required to run the given target
get_torrc_entries - provides the torrc entries for a given target
- get_message - provides a ControlMessage instance
get_protocolinfo_response - provides a ProtocolInfoResponse instance
get_all_combinations - provides all combinations of attributes
random_fingerprint - provides a random relay fingerprint
@@ -21,7 +20,6 @@ Helper functions for our test framework.
import hashlib
import itertools
-import re
import os
import stem
@@ -250,29 +248,6 @@ def random_fingerprint():
return hashlib.sha1(os.urandom(20)).hexdigest().upper()
-def get_message(content, reformat = True):
- """
- Provides a ControlMessage with content modified to be parsable. This makes
- the following changes unless 'reformat' is false...
-
- * ensures the content ends with a newline
- * newlines are replaced with a carriage return and newline pair
-
- :param str content: base content for the controller message
- :param str reformat: modifies content to be more accommodating to being parsed
-
- :returns: stem.response.ControlMessage instance
- """
-
- if reformat:
- if not content.endswith('\n'):
- content += '\n'
-
- content = re.sub('([\r]?)\n', '\r\n', content)
-
- return stem.response.ControlMessage.from_str(content)
-
-
def get_protocolinfo_response(**attributes):
"""
Provides a ProtocolInfoResponse, customized with the given attributes. The
@@ -284,7 +259,7 @@ def get_protocolinfo_response(**attributes):
:returns: stem.response.protocolinfo.ProtocolInfoResponse instance
"""
- protocolinfo_response = get_message('250-PROTOCOLINFO 1\n250 OK')
+ protocolinfo_response = stem.response.ControlMessage.from_str('250-PROTOCOLINFO 1\r\n250 OK\r\n', 'PROTOCOLINFO')
stem.response.convert('PROTOCOLINFO', protocolinfo_response)
for attr in attributes:
1
0
commit dfeb747947f5974e7d0fac9e55671685bc84629d
Author: Damian Johnson <atagar(a)torproject.org>
Date: Sun May 21 18:32:19 2017 -0700
Drop random_fingerprint() helper
We don't actually need a random fingerprint. Just filling in a value.
---
test/integ/control/base_controller.py | 3 +--
test/integ/control/controller.py | 10 +++++-----
test/integ/socket/control_message.py | 4 +---
test/util.py | 10 ----------
4 files changed, 7 insertions(+), 20 deletions(-)
diff --git a/test/integ/control/base_controller.py b/test/integ/control/base_controller.py
index 4c618e3..9f2fc44 100644
--- a/test/integ/control/base_controller.py
+++ b/test/integ/control/base_controller.py
@@ -12,7 +12,6 @@ import stem.socket
import stem.util.system
import test.require
import test.runner
-import test.util
class StateObserver(object):
@@ -152,7 +151,7 @@ class TestBaseController(unittest.TestCase):
controller.msg('SETEVENTS CONF_CHANGED')
for i in range(10):
- controller.msg('SETCONF NodeFamily=%s' % test.util.random_fingerprint())
+ controller.msg('SETCONF NodeFamily=FD4CC275C5AA4D27A487C6CA29097900F85E2C33')
test.runner.exercise_controller(self, controller)
controller.msg('SETEVENTS')
diff --git a/test/integ/control/controller.py b/test/integ/control/controller.py
index 32ce047..2125242 100644
--- a/test/integ/control/controller.py
+++ b/test/integ/control/controller.py
@@ -27,7 +27,7 @@ from stem.control import EventType, Listener, State
from stem.exit_policy import ExitPolicy
from stem.version import Requirement
-from test.util import register_new_capability, random_fingerprint, tor_version
+from test.util import register_new_capability, tor_version
# Router status entry for a relay with a nickname other than 'Unnamed'. This is
# used for a few tests that need to look up a relay.
@@ -143,7 +143,7 @@ class TestController(unittest.TestCase):
controller.add_event_listener(listener2, EventType.CONF_CHANGED, EventType.DEBUG)
# The NodeFamily is a harmless option we can toggle
- controller.set_conf('NodeFamily', random_fingerprint())
+ controller.set_conf('NodeFamily', 'FD4CC275C5AA4D27A487C6CA29097900F85E2C33')
# Wait for the event. Assert that we get it within 10 seconds
event_notice1.wait(10)
@@ -160,7 +160,7 @@ class TestController(unittest.TestCase):
buffer2_size = len(event_buffer2)
- controller.set_conf('NodeFamily', random_fingerprint())
+ controller.set_conf('NodeFamily', 'FD4CC275C5AA4D27A487C6CA29097900F85E2C33')
event_notice1.wait(10)
self.assertEqual(len(event_buffer1), 2)
event_notice1.clear()
@@ -197,7 +197,7 @@ class TestController(unittest.TestCase):
# trigger an event
- controller.set_conf('NodeFamily', random_fingerprint())
+ controller.set_conf('NodeFamily', 'FD4CC275C5AA4D27A487C6CA29097900F85E2C33')
event_notice.wait(4)
self.assertTrue(len(event_buffer) >= 1)
@@ -210,7 +210,7 @@ class TestController(unittest.TestCase):
controller.connect()
controller.authenticate(password = test.runner.CONTROL_PASSWORD)
self.assertTrue(len(event_buffer) == 0)
- controller.set_conf('NodeFamily', random_fingerprint())
+ controller.set_conf('NodeFamily', 'FD4CC275C5AA4D27A487C6CA29097900F85E2C33')
event_notice.wait(4)
self.assertTrue(len(event_buffer) >= 1)
diff --git a/test/integ/socket/control_message.py b/test/integ/socket/control_message.py
index 6d16f48..6c04464 100644
--- a/test/integ/socket/control_message.py
+++ b/test/integ/socket/control_message.py
@@ -10,8 +10,6 @@ import stem.version
import test.require
import test.runner
-from test.util import random_fingerprint
-
class TestControlMessage(unittest.TestCase):
@test.require.controller
@@ -159,7 +157,7 @@ class TestControlMessage(unittest.TestCase):
# We'll receive both a CONF_CHANGED event and 'OK' response for the
# SETCONF, but not necessarily in any specific order.
- control_socket.send('SETCONF NodeFamily=%s' % random_fingerprint())
+ control_socket.send('SETCONF NodeFamily=FD4CC275C5AA4D27A487C6CA29097900F85E2C33')
msg1 = control_socket.recv()
msg2 = control_socket.recv()
diff --git a/test/util.py b/test/util.py
index adadfe4..56bf975 100644
--- a/test/util.py
+++ b/test/util.py
@@ -13,11 +13,9 @@ Helper functions for our test framework.
get_torrc_entries - provides the torrc entries for a given target
get_all_combinations - provides all combinations of attributes
- random_fingerprint - provides a random relay fingerprint
tor_version - provides the version of tor we're testing against
"""
-import hashlib
import itertools
import os
@@ -239,14 +237,6 @@ def get_all_combinations(attr, include_empty = False):
yield item
-def random_fingerprint():
- """
- Provides a random relay fingerprint.
- """
-
- return hashlib.sha1(os.urandom(20)).hexdigest().upper()
-
-
def tor_version(tor_path = None):
"""
Provides the version of tor we're testing against.
1
0

22 May '17
commit a29627184ea7d50dc4072dfc4115e68372c52d5f
Author: Damian Johnson <atagar(a)torproject.org>
Date: Thu May 18 15:35:32 2017 -0700
Move test requirements to its own module
Moving the @require_* annotations to its own dedicated module. Besides the
obvious breakup of test.util this provides namespacing so we can truncate the
function names and use a standard import.
---
test/integ/connection/authentication.py | 25 ++--
test/integ/connection/connect.py | 9 +-
test/integ/control/base_controller.py | 20 ++-
test/integ/control/controller.py | 153 +++++++++++-----------
test/integ/descriptor/extrainfo_descriptor.py | 8 +-
test/integ/descriptor/microdescriptor.py | 8 +-
test/integ/descriptor/networkstatus.py | 18 +--
test/integ/descriptor/remote.py | 46 +++----
test/integ/descriptor/server_descriptor.py | 9 +-
test/integ/installation.py | 8 +-
test/integ/interpreter.py | 8 +-
test/integ/process.py | 37 +++---
test/integ/response/protocolinfo.py | 11 +-
test/integ/socket/control_message.py | 21 ++-
test/integ/socket/control_socket.py | 17 +--
test/integ/util/connection.py | 4 +-
test/integ/util/proc.py | 20 ++-
test/integ/util/system.py | 64 ++++-----
test/integ/version.py | 10 +-
test/require.py | 106 +++++++++++++++
test/unit/descriptor/certificate.py | 8 +-
test/unit/descriptor/hidden_service_descriptor.py | 7 +-
test/unit/manual.py | 9 +-
test/util.py | 101 +-------------
24 files changed, 341 insertions(+), 386 deletions(-)
diff --git a/test/integ/connection/authentication.py b/test/integ/connection/authentication.py
index 007042f..f43a61d 100644
--- a/test/integ/connection/authentication.py
+++ b/test/integ/connection/authentication.py
@@ -9,9 +9,10 @@ import unittest
import stem.connection
import stem.socket
import stem.version
+import test.require
import test.runner
-from test.util import require_controller, tor_version
+from test.util import tor_version
# Responses given by tor for various authentication failures. These may change
# in the future and if they do then this test should be updated.
@@ -106,7 +107,7 @@ class TestAuthenticate(unittest.TestCase):
if tor_version() >= stem.version.Requirement.AUTH_SAFECOOKIE:
self.cookie_auth_methods.append(stem.connection.AuthMethod.SAFECOOKIE)
- @require_controller
+ @test.require.controller
def test_authenticate_general_socket(self):
"""
Tests that the authenticate function can authenticate to our socket.
@@ -118,7 +119,7 @@ class TestAuthenticate(unittest.TestCase):
stem.connection.authenticate(control_socket, test.runner.CONTROL_PASSWORD, runner.get_chroot())
test.runner.exercise_controller(self, control_socket)
- @require_controller
+ @test.require.controller
def test_authenticate_general_controller(self):
"""
Tests that the authenticate function can authenticate via a Controller.
@@ -130,7 +131,7 @@ class TestAuthenticate(unittest.TestCase):
stem.connection.authenticate(controller, test.runner.CONTROL_PASSWORD, runner.get_chroot())
test.runner.exercise_controller(self, controller)
- @require_controller
+ @test.require.controller
def test_authenticate_general_example(self):
"""
Tests the authenticate function with something like its pydoc example.
@@ -166,7 +167,7 @@ class TestAuthenticate(unittest.TestCase):
finally:
control_socket.close()
- @require_controller
+ @test.require.controller
def test_authenticate_general_password(self):
"""
Tests the authenticate function's password argument.
@@ -201,7 +202,7 @@ class TestAuthenticate(unittest.TestCase):
stem.connection.authenticate(control_socket, test.runner.CONTROL_PASSWORD, runner.get_chroot())
test.runner.exercise_controller(self, control_socket)
- @require_controller
+ @test.require.controller
def test_authenticate_general_cookie(self):
"""
Tests the authenticate function with only cookie authentication methods.
@@ -226,7 +227,7 @@ class TestAuthenticate(unittest.TestCase):
protocolinfo_response.auth_methods = (method, )
stem.connection.authenticate(control_socket, chroot_path = runner.get_chroot(), protocolinfo_response = protocolinfo_response)
- @require_controller
+ @test.require.controller
def test_authenticate_none(self):
"""
Tests the authenticate_none function.
@@ -239,7 +240,7 @@ class TestAuthenticate(unittest.TestCase):
else:
self.assertRaises(stem.connection.OpenAuthRejected, self._check_auth, auth_type)
- @require_controller
+ @test.require.controller
def test_authenticate_password(self):
"""
Tests the authenticate_password function.
@@ -267,7 +268,7 @@ class TestAuthenticate(unittest.TestCase):
self.assertRaises(exc_type, self._check_auth, auth_type, auth_value)
- @require_controller
+ @test.require.controller
def test_authenticate_cookie(self):
"""
Tests the authenticate_cookie function.
@@ -289,7 +290,7 @@ class TestAuthenticate(unittest.TestCase):
else:
self.assertRaises(stem.connection.CookieAuthRejected, self._check_auth, auth_type, auth_value, False)
- @require_controller
+ @test.require.controller
def test_authenticate_cookie_invalid(self):
"""
Tests the authenticate_cookie function with a properly sized but incorrect
@@ -326,7 +327,7 @@ class TestAuthenticate(unittest.TestCase):
os.remove(auth_value)
- @require_controller
+ @test.require.controller
def test_authenticate_cookie_missing(self):
"""
Tests the authenticate_cookie function with a path that really, really
@@ -337,7 +338,7 @@ class TestAuthenticate(unittest.TestCase):
auth_value = "/if/this/exists/then/they're/asking/for/a/failure"
self.assertRaises(stem.connection.UnreadableCookieFile, self._check_auth, auth_type, auth_value, False)
- @require_controller
+ @test.require.controller
def test_authenticate_cookie_wrong_size(self):
"""
Tests the authenticate_cookie function with our torrc as an auth cookie.
diff --git a/test/integ/connection/connect.py b/test/integ/connection/connect.py
index d50b3af..fd08742 100644
--- a/test/integ/connection/connect.py
+++ b/test/integ/connection/connect.py
@@ -11,10 +11,9 @@ except ImportError:
from io import StringIO
import stem.connection
+import test.require
import test.runner
-from test.util import require_controller
-
class TestConnect(unittest.TestCase):
def setUp(self):
@@ -25,7 +24,7 @@ class TestConnect(unittest.TestCase):
def tearDown(self):
sys.stdout = self.original_stdout
- @require_controller
+ @test.require.controller
def test_connect(self):
"""
Basic sanity checks for the connect function.
@@ -42,7 +41,7 @@ class TestConnect(unittest.TestCase):
test.runner.exercise_controller(self, control_socket)
- @require_controller
+ @test.require.controller
def test_connect_port(self):
"""
Basic sanity checks for the connect_port function.
@@ -62,7 +61,7 @@ class TestConnect(unittest.TestCase):
else:
self.assertEqual(control_socket, None)
- @require_controller
+ @test.require.controller
def test_connect_socket_file(self):
"""
Basic sanity checks for the connect_socket_file function.
diff --git a/test/integ/control/base_controller.py b/test/integ/control/base_controller.py
index 1e64445..4c618e3 100644
--- a/test/integ/control/base_controller.py
+++ b/test/integ/control/base_controller.py
@@ -10,12 +10,10 @@ import unittest
import stem.control
import stem.socket
import stem.util.system
-
+import test.require
import test.runner
import test.util
-from test.util import require_controller
-
class StateObserver(object):
"""
@@ -39,7 +37,7 @@ class StateObserver(object):
class TestBaseController(unittest.TestCase):
- @require_controller
+ @test.require.controller
def test_connect_repeatedly(self):
"""
Connects and closes the socket repeatedly. This is a simple attempt to
@@ -57,7 +55,7 @@ class TestBaseController(unittest.TestCase):
controller.connect()
controller.close()
- @require_controller
+ @test.require.controller
def test_msg(self):
"""
Tests a basic query with the msg() method.
@@ -67,7 +65,7 @@ class TestBaseController(unittest.TestCase):
controller = stem.control.BaseController(control_socket)
test.runner.exercise_controller(self, controller)
- @require_controller
+ @test.require.controller
def test_msg_invalid(self):
"""
Tests the msg() method against an invalid controller command.
@@ -78,7 +76,7 @@ class TestBaseController(unittest.TestCase):
response = controller.msg('invalid')
self.assertEqual('Unrecognized command "invalid"', str(response))
- @require_controller
+ @test.require.controller
def test_msg_invalid_getinfo(self):
"""
Tests the msg() method against a non-existant GETINFO option.
@@ -89,7 +87,7 @@ class TestBaseController(unittest.TestCase):
response = controller.msg('GETINFO blarg')
self.assertEqual('Unrecognized key "blarg"', str(response))
- @require_controller
+ @test.require.controller
def test_msg_repeatedly(self):
"""
Connects, sends a burst of messages, and closes the socket repeatedly. This
@@ -127,7 +125,7 @@ class TestBaseController(unittest.TestCase):
for msg_thread in message_threads:
msg_thread.join()
- @require_controller
+ @test.require.controller
def test_asynchronous_event_handling(self):
"""
Check that we can both receive asynchronous events while hammering our
@@ -181,7 +179,7 @@ class TestBaseController(unittest.TestCase):
self.assertTrue(conf_changed_event.raw_content().startswith('650-CONF_CHANGED\r\n650-NodeFamily='))
self.assertEqual(('650', '-'), conf_changed_event.content()[0][:2])
- @require_controller
+ @test.require.controller
def test_get_latest_heartbeat(self):
"""
Basic check for get_latest_heartbeat().
@@ -193,7 +191,7 @@ class TestBaseController(unittest.TestCase):
controller.msg('GETINFO version')
self.assertTrue((time.time() - controller.get_latest_heartbeat()) < 5)
- @require_controller
+ @test.require.controller
def test_status_notifications(self):
"""
Checks basic functionality of the add_status_listener() and
diff --git a/test/integ/control/controller.py b/test/integ/control/controller.py
index 2445221..32ce047 100644
--- a/test/integ/control/controller.py
+++ b/test/integ/control/controller.py
@@ -19,6 +19,7 @@ import stem.socket
import stem.util.str_tools
import stem.version
import test.network
+import test.require
import test.runner
from stem import Flag, Signal
@@ -26,15 +27,7 @@ from stem.control import EventType, Listener, State
from stem.exit_policy import ExitPolicy
from stem.version import Requirement
-from test.util import (
- register_new_capability,
- random_fingerprint,
- tor_version,
- only_run_once,
- require_controller,
- require_version,
- require_online,
-)
+from test.util import register_new_capability, random_fingerprint, tor_version
# Router status entry for a relay with a nickname other than 'Unnamed'. This is
# used for a few tests that need to look up a relay.
@@ -43,8 +36,8 @@ TEST_ROUTER_STATUS_ENTRY = None
class TestController(unittest.TestCase):
- @only_run_once
- @require_controller
+ @test.require.only_run_once
+ @test.require.controller
def test_missing_capabilities(self):
"""
Check to see if tor supports any events, signals, or features that we
@@ -88,8 +81,8 @@ class TestController(unittest.TestCase):
else:
self.assertRaises(stem.SocketError, stem.control.Controller.from_socket_file, test.runner.CONTROL_SOCKET_PATH)
- @require_controller
- @require_version(Requirement.EVENT_SIGNAL)
+ @test.require.controller
+ @test.require.version(Requirement.EVENT_SIGNAL)
def test_reset_notification(self):
"""
Checks that a notificiation listener is... well, notified of SIGHUPs.
@@ -125,7 +118,7 @@ class TestController(unittest.TestCase):
controller.reset_conf('__OwningControllerProcess')
- @require_controller
+ @test.require.controller
def test_event_handling(self):
"""
Add a couple listeners for various events and make sure that they receive
@@ -183,7 +176,7 @@ class TestController(unittest.TestCase):
controller.reset_conf('NodeFamily')
- @require_controller
+ @test.require.controller
def test_reattaching_listeners(self):
"""
Checks that event listeners are re-attached when a controller disconnects
@@ -224,7 +217,7 @@ class TestController(unittest.TestCase):
controller.reset_conf('NodeFamily')
- @require_controller
+ @test.require.controller
def test_getinfo(self):
"""
Exercises GETINFO with valid and invalid queries.
@@ -262,7 +255,7 @@ class TestController(unittest.TestCase):
self.assertEqual({}, controller.get_info([]))
self.assertEqual({}, controller.get_info([], {}))
- @require_controller
+ @test.require.controller
def test_get_version(self):
"""
Test that the convenient method get_version() works.
@@ -275,7 +268,7 @@ class TestController(unittest.TestCase):
self.assertTrue(isinstance(version, stem.version.Version))
self.assertEqual(version, tor_version())
- @require_controller
+ @test.require.controller
def test_get_exit_policy(self):
"""
Sanity test for get_exit_policy(). We have the default policy (no
@@ -318,7 +311,7 @@ class TestController(unittest.TestCase):
policy_str = policy_str[:public_addr_start] + policy_str[public_addr_end:]
self.assertEqual(str(expected), policy_str)
- @require_controller
+ @test.require.controller
def test_authenticate(self):
"""
Test that the convenient method authenticate() works.
@@ -330,7 +323,7 @@ class TestController(unittest.TestCase):
controller.authenticate(test.runner.CONTROL_PASSWORD)
test.runner.exercise_controller(self, controller)
- @require_controller
+ @test.require.controller
def test_protocolinfo(self):
"""
Test that the convenient method protocolinfo() works.
@@ -360,7 +353,7 @@ class TestController(unittest.TestCase):
self.assertEqual(tuple(auth_methods), protocolinfo.auth_methods)
- @require_controller
+ @test.require.controller
def test_getconf(self):
"""
Exercises GETCONF with valid and invalid queries.
@@ -423,7 +416,7 @@ class TestController(unittest.TestCase):
self.assertEqual({}, controller.get_conf_map('', 'la-di-dah'))
self.assertEqual({}, controller.get_conf_map([], 'la-di-dah'))
- @require_controller
+ @test.require.controller
def test_is_set(self):
"""
Exercises our is_set() method.
@@ -450,7 +443,7 @@ class TestController(unittest.TestCase):
controller.reset_conf('ConnLimit')
self.assertFalse(controller.is_set('ConnLimit'))
- @require_controller
+ @test.require.controller
def test_hidden_services_conf(self):
"""
Exercises the hidden service family of methods (get_hidden_service_conf,
@@ -557,8 +550,8 @@ class TestController(unittest.TestCase):
except:
pass
- @require_controller
- @require_version(Requirement.ADD_ONION)
+ @test.require.controller
+ @test.require.version(Requirement.ADD_ONION)
def test_without_ephemeral_hidden_services(self):
"""
Exercises ephemeral hidden service methods when none are present.
@@ -569,8 +562,8 @@ class TestController(unittest.TestCase):
self.assertEqual([], controller.list_ephemeral_hidden_services(detached = True))
self.assertEqual(False, controller.remove_ephemeral_hidden_service('gfzprpioee3hoppz'))
- @require_controller
- @require_version(Requirement.ADD_ONION)
+ @test.require.controller
+ @test.require.version(Requirement.ADD_ONION)
def test_with_ephemeral_hidden_services(self):
"""
Exercises creating ephemeral hidden services and methods when they're
@@ -620,8 +613,8 @@ class TestController(unittest.TestCase):
self.assertEqual(2, len(controller.list_ephemeral_hidden_services()))
self.assertEqual(0, len(second_controller.list_ephemeral_hidden_services()))
- @require_controller
- @require_version(Requirement.ADD_ONION_BASIC_AUTH)
+ @test.require.controller
+ @test.require.version(Requirement.ADD_ONION_BASIC_AUTH)
def test_with_ephemeral_hidden_services_basic_auth(self):
"""
Exercises creating ephemeral hidden services that uses basic authentication.
@@ -640,8 +633,8 @@ class TestController(unittest.TestCase):
self.assertEqual(True, controller.remove_ephemeral_hidden_service(response.service_id))
self.assertEqual([], controller.list_ephemeral_hidden_services())
- @require_controller
- @require_version(Requirement.ADD_ONION_BASIC_AUTH)
+ @test.require.controller
+ @test.require.version(Requirement.ADD_ONION_BASIC_AUTH)
def test_with_ephemeral_hidden_services_basic_auth_no_credentials(self):
"""
Exercises creating ephemeral hidden services when attempting to use basic
@@ -654,8 +647,8 @@ class TestController(unittest.TestCase):
exc_msg = "ADD_ONION response didn't have an OK status: No auth clients specified"
self.assertRaisesRegexp(stem.ProtocolError, exc_msg, controller.create_ephemeral_hidden_service, 4567, basic_auth = {})
- @require_controller
- @require_version(Requirement.ADD_ONION)
+ @test.require.controller
+ @test.require.version(Requirement.ADD_ONION)
def test_with_detached_ephemeral_hidden_services(self):
"""
Exercises creating detached ephemeral hidden services and methods when
@@ -690,7 +683,7 @@ class TestController(unittest.TestCase):
self.assertEqual([response.service_id], controller.list_ephemeral_hidden_services(detached = True))
controller.remove_ephemeral_hidden_service(response.service_id)
- @require_controller
+ @test.require.controller
def test_set_conf(self):
"""
Exercises set_conf(), reset_conf(), and set_options() methods with valid
@@ -763,8 +756,8 @@ class TestController(unittest.TestCase):
shutil.rmtree(tmpdir)
- @require_controller
- @require_version(Requirement.LOADCONF)
+ @test.require.controller
+ @test.require.version(Requirement.LOADCONF)
def test_loadconf(self):
"""
Exercises Controller.load_conf with valid and invalid requests.
@@ -801,7 +794,7 @@ class TestController(unittest.TestCase):
controller.load_conf(oldconf)
controller.reset_conf('__OwningControllerProcess')
- @require_controller
+ @test.require.controller
def test_saveconf(self):
runner = test.runner.get_runner()
@@ -821,7 +814,7 @@ class TestController(unittest.TestCase):
controller.save_conf()
controller.reset_conf('__OwningControllerProcess')
- @require_controller
+ @test.require.controller
def test_get_ports(self):
"""
Test Controller.get_ports against a running tor instance.
@@ -842,7 +835,7 @@ class TestController(unittest.TestCase):
else:
self.assertEqual([], controller.get_ports(Listener.CONTROL))
- @require_controller
+ @test.require.controller
def test_get_listeners(self):
"""
Test Controller.get_listeners against a running tor instance.
@@ -863,7 +856,7 @@ class TestController(unittest.TestCase):
else:
self.assertEqual([], controller.get_listeners(Listener.CONTROL))
- @require_controller
+ @test.require.controller
def test_get_socks_listeners(self):
"""
Test Controller.get_socks_listeners against a running tor instance.
@@ -872,9 +865,9 @@ class TestController(unittest.TestCase):
with test.runner.get_runner().get_tor_controller() as controller:
self.assertEqual([('127.0.0.1', 1112)], controller.get_socks_listeners())
- @require_controller
- @require_online
- @require_version(stem.version.Version('0.1.2.2-alpha'))
+ @test.require.controller
+ @test.require.online
+ @test.require.version(stem.version.Version('0.1.2.2-alpha'))
def test_enable_feature(self):
"""
Test Controller.enable_feature with valid and invalid inputs.
@@ -895,7 +888,7 @@ class TestController(unittest.TestCase):
else:
self.fail()
- @require_controller
+ @test.require.controller
def test_signal(self):
"""
Test controller.signal with valid and invalid signals.
@@ -908,7 +901,7 @@ class TestController(unittest.TestCase):
# invalid signals
self.assertRaises(stem.InvalidArguments, controller.signal, 'FOOBAR')
- @require_controller
+ @test.require.controller
def test_newnym_availability(self):
"""
Test the is_newnym_available and get_newnym_wait methods.
@@ -923,9 +916,9 @@ class TestController(unittest.TestCase):
self.assertEqual(False, controller.is_newnym_available())
self.assertTrue(controller.get_newnym_wait() > 9.0)
- @require_controller
- @require_online
- @require_version(Requirement.EXTENDCIRCUIT_PATH_OPTIONAL)
+ @test.require.controller
+ @test.require.online
+ @test.require.version(Requirement.EXTENDCIRCUIT_PATH_OPTIONAL)
def test_extendcircuit(self):
with test.runner.get_runner().get_tor_controller() as controller:
circuit_id = controller.extend_circuit('0')
@@ -939,9 +932,9 @@ class TestController(unittest.TestCase):
self.assertRaises(stem.InvalidRequest, controller.extend_circuit, '0', 'thisroutershouldntexistbecausestemexists!@##$%#')
self.assertRaises(stem.InvalidRequest, controller.extend_circuit, '0', 'thisroutershouldntexistbecausestemexists!@##$%#', 'foo')
- @require_controller
- @require_online
- @require_version(Requirement.EXTENDCIRCUIT_PATH_OPTIONAL)
+ @test.require.controller
+ @test.require.online
+ @test.require.version(Requirement.EXTENDCIRCUIT_PATH_OPTIONAL)
def test_repurpose_circuit(self):
"""
Tests Controller.repurpose_circuit with valid and invalid input.
@@ -962,9 +955,9 @@ class TestController(unittest.TestCase):
self.assertRaises(stem.InvalidRequest, controller.repurpose_circuit, 'f934h9f3h4', 'fooo')
self.assertRaises(stem.InvalidRequest, controller.repurpose_circuit, '4', 'fooo')
- @require_controller
- @require_online
- @require_version(Requirement.EXTENDCIRCUIT_PATH_OPTIONAL)
+ @test.require.controller
+ @test.require.online
+ @test.require.version(Requirement.EXTENDCIRCUIT_PATH_OPTIONAL)
def test_close_circuit(self):
"""
Tests Controller.close_circuit with valid and invalid input.
@@ -989,8 +982,8 @@ class TestController(unittest.TestCase):
self.assertRaises(stem.InvalidArguments, controller.close_circuit, circuit_id + '1024')
self.assertRaises(stem.InvalidRequest, controller.close_circuit, '')
- @require_controller
- @require_online
+ @test.require.controller
+ @test.require.online
def test_get_streams(self):
"""
Tests Controller.get_streams().
@@ -1014,8 +1007,8 @@ class TestController(unittest.TestCase):
self.assertTrue('%s:%s' % (host, port) in [stream.target for stream in streams])
- @require_controller
- @require_online
+ @test.require.controller
+ @test.require.online
def test_close_stream(self):
"""
Tests Controller.close_stream with valid and invalid input.
@@ -1053,8 +1046,8 @@ class TestController(unittest.TestCase):
self.assertRaises(stem.InvalidArguments, controller.close_stream, 'blarg')
- @require_controller
- @require_online
+ @test.require.controller
+ @test.require.online
def test_mapaddress(self):
runner = test.runner.get_runner()
@@ -1091,9 +1084,9 @@ class TestController(unittest.TestCase):
ip_addr = response[response.find(b'\r\n\r\n'):].strip()
self.assertTrue(stem.util.connection.is_valid_ipv4_address(stem.util.str_tools._to_unicode(ip_addr)), "'%s' isn't an address" % ip_addr)
- @require_controller
- @require_online
- @require_version(Requirement.MICRODESCRIPTOR_IS_DEFAULT)
+ @test.require.controller
+ @test.require.online
+ @test.require.version(Requirement.MICRODESCRIPTOR_IS_DEFAULT)
def test_get_microdescriptor(self):
"""
Basic checks for get_microdescriptor().
@@ -1116,7 +1109,7 @@ class TestController(unittest.TestCase):
self.assertEqual(md_by_fingerprint, md_by_nickname)
- @require_controller
+ @test.require.controller
def test_get_microdescriptors(self):
"""
Fetches a few descriptors via the get_microdescriptors() method.
@@ -1138,7 +1131,7 @@ class TestController(unittest.TestCase):
if count > 10:
break
- @require_controller
+ @test.require.controller
def test_get_server_descriptor(self):
"""
Basic checks for get_server_descriptor().
@@ -1168,7 +1161,7 @@ class TestController(unittest.TestCase):
self.assertEqual(desc_by_fingerprint, desc_by_nickname)
- @require_controller
+ @test.require.controller
def test_get_server_descriptors(self):
"""
Fetches a few descriptors via the get_server_descriptors() method.
@@ -1195,8 +1188,8 @@ class TestController(unittest.TestCase):
if count > 10:
break
- @require_controller
- @require_online
+ @test.require.controller
+ @test.require.online
def test_get_network_status(self):
"""
Basic checks for get_network_status().
@@ -1219,8 +1212,8 @@ class TestController(unittest.TestCase):
self.assertEqual(desc_by_fingerprint, desc_by_nickname)
- @require_controller
- @require_online
+ @test.require.controller
+ @test.require.online
def test_get_network_statuses(self):
"""
Fetches a few descriptors via the get_network_statuses() method.
@@ -1242,9 +1235,9 @@ class TestController(unittest.TestCase):
if count > 10:
break
- @require_controller
- @require_online
- @require_version(Requirement.HSFETCH)
+ @test.require.controller
+ @test.require.online
+ @test.require.version(Requirement.HSFETCH)
def test_get_hidden_service_descriptor(self):
"""
Fetches a few descriptors via the get_hidden_service_descriptor() method.
@@ -1268,9 +1261,9 @@ class TestController(unittest.TestCase):
self.assertEqual('pop goes the weasel', controller.get_hidden_service_descriptor('m4cfuk6qp4lpu2g5', 'pop goes the weasel'))
self.assertEqual(None, controller.get_hidden_service_descriptor('m4cfuk6qp4lpu2g5', await_result = False))
- @require_controller
- @require_online
- @require_version(Requirement.EXTENDCIRCUIT_PATH_OPTIONAL)
+ @test.require.controller
+ @test.require.online
+ @test.require.version(Requirement.EXTENDCIRCUIT_PATH_OPTIONAL)
def test_attachstream(self):
host = socket.gethostbyname('www.torproject.org')
port = 80
@@ -1309,9 +1302,9 @@ class TestController(unittest.TestCase):
self.assertEqual(our_stream.circ_id, circuit_id)
- @require_controller
- @require_online
- @require_version(Requirement.EXTENDCIRCUIT_PATH_OPTIONAL)
+ @test.require.controller
+ @test.require.online
+ @test.require.version(Requirement.EXTENDCIRCUIT_PATH_OPTIONAL)
def test_get_circuits(self):
"""
Fetches circuits via the get_circuits() method.
@@ -1322,7 +1315,7 @@ class TestController(unittest.TestCase):
circuits = controller.get_circuits()
self.assertTrue(new_circ in [circ.id for circ in circuits])
- @require_controller
+ @test.require.controller
def test_transition_to_relay(self):
"""
Transitions Tor to turn into a relay, then back to a client. This helps to
diff --git a/test/integ/descriptor/extrainfo_descriptor.py b/test/integ/descriptor/extrainfo_descriptor.py
index 6ea2b16..205b917 100644
--- a/test/integ/descriptor/extrainfo_descriptor.py
+++ b/test/integ/descriptor/extrainfo_descriptor.py
@@ -6,16 +6,14 @@ import os
import unittest
import stem.descriptor
+import test.require
import test.runner
-from test.util import (
- register_new_capability,
- only_run_once,
-)
+from test.util import register_new_capability
class TestExtraInfoDescriptor(unittest.TestCase):
- @only_run_once
+ @test.require.only_run_once
def test_cached_descriptor(self):
"""
Parses the cached descriptor file in our data directory, checking that it
diff --git a/test/integ/descriptor/microdescriptor.py b/test/integ/descriptor/microdescriptor.py
index 97127d6..c6fa80e 100644
--- a/test/integ/descriptor/microdescriptor.py
+++ b/test/integ/descriptor/microdescriptor.py
@@ -6,16 +6,14 @@ import os
import unittest
import stem.descriptor
+import test.require
import test.runner
-from test.util import (
- register_new_capability,
- only_run_once,
-)
+from test.util import register_new_capability
class TestMicrodescriptor(unittest.TestCase):
- @only_run_once
+ @test.require.only_run_once
def test_cached_microdescriptors(self):
"""
Parses the cached microdescriptor file in our data directory, checking that
diff --git a/test/integ/descriptor/networkstatus.py b/test/integ/descriptor/networkstatus.py
index 59dca00..96fec77 100644
--- a/test/integ/descriptor/networkstatus.py
+++ b/test/integ/descriptor/networkstatus.py
@@ -9,20 +9,16 @@ import stem
import stem.descriptor
import stem.descriptor.remote
import stem.version
+import test.require
import test.runner
-from test.util import (
- register_new_capability,
- only_run_once,
- require_cryptography,
- require_online,
-)
+from test.util import register_new_capability
class TestNetworkStatus(unittest.TestCase):
- @require_online
- @require_cryptography
- @only_run_once
+ @test.require.only_run_once
+ @test.require.online
+ @test.require.cryptography
def test_signature_validation(self):
"""
The full consensus is pretty sizable so rather than storing a copy of it
@@ -31,7 +27,7 @@ class TestNetworkStatus(unittest.TestCase):
stem.descriptor.remote.get_consensus(document_handler = stem.descriptor.DocumentHandler.DOCUMENT, validate = True).run()
- @only_run_once
+ @test.require.only_run_once
def test_cached_consensus(self):
"""
Parses the cached-consensus file in our data directory.
@@ -68,7 +64,7 @@ class TestNetworkStatus(unittest.TestCase):
self.assertTrue(count > 100)
- @only_run_once
+ @test.require.only_run_once
def test_cached_microdesc_consensus(self):
"""
Parses the cached-microdesc-consensus file in our data directory.
diff --git a/test/integ/descriptor/remote.py b/test/integ/descriptor/remote.py
index b873b96..3123ef0 100644
--- a/test/integ/descriptor/remote.py
+++ b/test/integ/descriptor/remote.py
@@ -10,16 +10,12 @@ import stem.descriptor.networkstatus
import stem.descriptor.remote
import stem.descriptor.router_status_entry
import stem.descriptor.server_descriptor
-
-from test.util import (
- only_run_once,
- require_online,
-)
+import test.require
class TestDescriptorDownloader(unittest.TestCase):
- @require_online
- @only_run_once
+ @test.require.only_run_once
+ @test.require.online
def test_shorthand_aliases(self):
"""
Quick sanity test that we can call our shorthand aliases for getting
@@ -35,8 +31,8 @@ class TestDescriptorDownloader(unittest.TestCase):
consensus = list(stem.descriptor.remote.get_consensus())
self.assertTrue(len(consensus) > 50)
- @require_online
- @only_run_once
+ @test.require.only_run_once
+ @test.require.online
def test_authorities_are_up_to_date(self):
"""
Check that our hardcoded directory authority data matches the present
@@ -62,8 +58,8 @@ class TestDescriptorDownloader(unittest.TestCase):
if getattr(auth, attr) != getattr(stem_auth, attr):
self.fail('%s has %s %s, but we expected %s' % (auth.nickname, attr, getattr(auth, attr), getattr(stem_auth, attr)))
- @require_online
- @only_run_once
+ @test.require.only_run_once
+ @test.require.online
def test_using_authorities(self):
"""
Fetches a descriptor from each of the directory authorities. This is
@@ -94,8 +90,8 @@ class TestDescriptorDownloader(unittest.TestCase):
self.assertEqual(1, len(descriptors))
self.assertEqual('moria1', descriptors[0].nickname)
- @require_online
- @only_run_once
+ @test.require.only_run_once
+ @test.require.online
def test_use_directory_mirrors(self):
"""
Checks that we can fetch and use a list of directory mirrors.
@@ -105,8 +101,8 @@ class TestDescriptorDownloader(unittest.TestCase):
downloader.use_directory_mirrors()
self.assertTrue(len(downloader._endpoints) > 50)
- @require_online
- @only_run_once
+ @test.require.only_run_once
+ @test.require.online
def test_get_server_descriptors(self):
"""
Exercises the downloader's get_server_descriptors() method.
@@ -138,8 +134,8 @@ class TestDescriptorDownloader(unittest.TestCase):
self.assertEqual(2, len(list(multiple_query)))
- @require_online
- @only_run_once
+ @test.require.only_run_once
+ @test.require.online
def test_get_extrainfo_descriptors(self):
"""
Exercises the downloader's get_extrainfo_descriptors() method.
@@ -164,8 +160,8 @@ class TestDescriptorDownloader(unittest.TestCase):
self.assertEqual(2, len(list(multiple_query)))
- @require_online
- @only_run_once
+ @test.require.only_run_once
+ @test.require.online
def test_get_consensus(self):
"""
Exercises the downloader's get_consensus() method.
@@ -180,8 +176,8 @@ class TestDescriptorDownloader(unittest.TestCase):
self.assertTrue(len(consensus) > 50)
self.assertTrue(isinstance(consensus[0], stem.descriptor.router_status_entry.RouterStatusEntryV3))
- @require_online
- @only_run_once
+ @test.require.only_run_once
+ @test.require.online
def test_get_microdescriptor_consensus(self):
"""
Exercises the downloader's get_consensus() method for fetching a
@@ -197,8 +193,8 @@ class TestDescriptorDownloader(unittest.TestCase):
self.assertTrue(len(consensus) > 50)
self.assertTrue(isinstance(consensus[0], stem.descriptor.router_status_entry.RouterStatusEntryMicroV3))
- @require_online
- @only_run_once
+ @test.require.only_run_once
+ @test.require.online
def test_get_key_certificates(self):
"""
Exercises the downloader's get_key_certificates() method.
@@ -223,7 +219,7 @@ class TestDescriptorDownloader(unittest.TestCase):
self.assertEqual(2, len(list(multiple_query)))
- @require_online
+ @test.require.online
def test_that_cache_is_up_to_date(self):
"""
Check if the cached fallback directories bundled with Stem are up to date
@@ -236,7 +232,7 @@ class TestDescriptorDownloader(unittest.TestCase):
if cached_fallback_directories != latest_fallback_directories:
self.fail("Stem's cached fallback directories are out of date. Please run 'cache_fallback_directories.py'...\n\n%s" % stem.descriptor.remote._fallback_directory_differences(cached_fallback_directories, latest_fallback_directories))
- @require_online
+ @test.require.online
def test_fallback_directory_reachability(self):
"""
Fetch information from each fallback directory to confirm that it's
diff --git a/test/integ/descriptor/server_descriptor.py b/test/integ/descriptor/server_descriptor.py
index bd61e70..2a3d897 100644
--- a/test/integ/descriptor/server_descriptor.py
+++ b/test/integ/descriptor/server_descriptor.py
@@ -6,17 +6,14 @@ import os
import unittest
import stem.descriptor
-
+import test.require
import test.runner
-from test.util import (
- register_new_capability,
- only_run_once,
-)
+from test.util import register_new_capability
class TestServerDescriptor(unittest.TestCase):
- @only_run_once
+ @test.require.only_run_once
def test_cached_descriptor(self):
"""
Parses the cached descriptor file in our data directory, checking that it
diff --git a/test/integ/installation.py b/test/integ/installation.py
index 4d68988..3f37df3 100644
--- a/test/integ/installation.py
+++ b/test/integ/installation.py
@@ -12,11 +12,9 @@ import unittest
import stem
import stem.util.system
-
+import test.require
import test.util
-from test.util import only_run_once
-
INSTALL_MISMATCH_MSG = "Running 'python setup.py sdist' doesn't match our git contents in the following way. The manifest in our setup.py may need to be updated...\n\n"
BASE_INSTALL_PATH = '/tmp/stem_test'
@@ -110,7 +108,7 @@ def _assert_has_all_files(path):
class TestInstallation(unittest.TestCase):
- @only_run_once
+ @test.require.only_run_once
def test_install(self):
"""
Installs with 'python setup.py install' and checks we can use what we
@@ -126,7 +124,7 @@ class TestInstallation(unittest.TestCase):
self.assertEqual(stem.__version__, stem.util.system.call([sys.executable, '-c', "import sys;sys.path.insert(0, '%s');import stem;print(stem.__version__)" % INSTALL_PATH])[0])
_assert_has_all_files(INSTALL_PATH)
- @only_run_once
+ @test.require.only_run_once
def test_sdist(self):
"""
Creates a source distribution tarball with 'python setup.py sdist' and
diff --git a/test/integ/interpreter.py b/test/integ/interpreter.py
index 5e7c94b..42dd01a 100644
--- a/test/integ/interpreter.py
+++ b/test/integ/interpreter.py
@@ -7,12 +7,10 @@ import tempfile
import unittest
import stem.util.system
-
+import test.require
import test.runner
import test.util
-from test.util import require_controller
-
PROMPT_CMD = os.path.join(test.util.STEM_BASE, 'tor-prompt')
@@ -24,7 +22,7 @@ def _run_prompt(*args):
class TestInterpreter(unittest.TestCase):
- @require_controller
+ @test.require.controller
def test_running_command(self):
# We'd need to provide the password to stdin. Fine test to add later but
# not gonna hassle for now.
@@ -36,7 +34,7 @@ class TestInterpreter(unittest.TestCase):
expected = ['250-config-file=%s' % test.runner.get_runner().get_torrc_path(), '250 OK']
self.assertEqual(expected, _run_prompt('--run', 'GETINFO config-file'))
- @require_controller
+ @test.require.controller
def test_running_file(self):
if test.runner.Torrc.PASSWORD in test.runner.get_runner().get_options():
self.skipTest('password auth unsupported')
diff --git a/test/integ/process.py b/test/integ/process.py
index 79797ac..1ca0f70 100644
--- a/test/integ/process.py
+++ b/test/integ/process.py
@@ -20,16 +20,9 @@ import stem.util.str_tools
import stem.util.system
import stem.util.tor_tools
import stem.version
+import test.require
import test.runner
-from test.util import (
- require_command,
- require_controller,
- require_version,
-)
-
-from test.util import only_run_once
-
try:
# added in python 3.3
from unittest.mock import patch, Mock
@@ -53,7 +46,7 @@ class TestProcess(unittest.TestCase):
def tearDown(self):
shutil.rmtree(self.data_directory)
- @require_controller
+ @test.require.controller
def test_version_argument(self):
"""
Check that 'tor --version' matches 'GETINFO version'.
@@ -199,7 +192,7 @@ class TestProcess(unittest.TestCase):
self.assertTrue('UseBridges' in output)
self.assertTrue('SocksPort' in output)
- @require_command('sleep')
+ @test.require.command('sleep')
@patch('re.compile', Mock(side_effect = KeyboardInterrupt('nope')))
def test_no_orphaned_process(self):
"""
@@ -255,7 +248,7 @@ class TestProcess(unittest.TestCase):
self.assertEqual(expected, result)
- @require_version(stem.version.Requirement.TORRC_VIA_STDIN)
+ @test.require.version(stem.version.Requirement.TORRC_VIA_STDIN)
def test_torrc_arguments_via_stdin(self):
"""
Pass configuration options via stdin.
@@ -278,7 +271,7 @@ class TestProcess(unittest.TestCase):
self.assertTrue('[notice] Configuration file "/path/that/really/shouldnt/exist" not present, using reasonable defaults.' in output)
self.assertTrue('Configuration was valid' in output)
- @only_run_once
+ @test.require.only_run_once
def test_can_run_multithreaded(self):
"""
Our launch_tor() function uses signal to support its timeout argument.
@@ -321,7 +314,7 @@ class TestProcess(unittest.TestCase):
self.assertEqual(None, launch_async_with_timeout(None))
self.assertEqual(None, launch_async_with_timeout(stem.process.DEFAULT_INIT_TIMEOUT))
- @only_run_once
+ @test.require.only_run_once
@patch('stem.version.get_system_tor_version', Mock(return_value = stem.version.Version('0.0.0.1')))
def test_launch_tor_with_config_via_file(self):
"""
@@ -359,8 +352,8 @@ class TestProcess(unittest.TestCase):
tor_process.kill()
tor_process.wait()
- @only_run_once
- @require_version(stem.version.Requirement.TORRC_VIA_STDIN)
+ @test.require.only_run_once
+ @test.require.version(stem.version.Requirement.TORRC_VIA_STDIN)
def test_launch_tor_with_config_via_stdin(self):
"""
Exercises launch_tor_with_config when we provide our torrc via stdin.
@@ -394,7 +387,7 @@ class TestProcess(unittest.TestCase):
tor_process.kill()
tor_process.wait()
- @only_run_once
+ @test.require.only_run_once
def test_with_invalid_config(self):
"""
Spawn a tor process with a configuration that should make it dead on arrival.
@@ -417,7 +410,7 @@ class TestProcess(unittest.TestCase):
},
)
- @only_run_once
+ @test.require.only_run_once
def test_launch_tor_with_timeout(self):
"""
Runs launch_tor where it times out before completing.
@@ -432,9 +425,9 @@ class TestProcess(unittest.TestCase):
if not (runtime > 0.05 and runtime < 1):
self.fail('Test should have taken 0.05-1 seconds, took %0.1f instead' % runtime)
- @require_command('sleep')
- @require_version(stem.version.Requirement.TAKEOWNERSHIP)
- @only_run_once
+ @test.require.only_run_once
+ @test.require.command('sleep')
+ @test.require.version(stem.version.Requirement.TAKEOWNERSHIP)
@patch('os.getpid')
def test_take_ownership_via_pid(self, getpid_mock):
"""
@@ -476,8 +469,8 @@ class TestProcess(unittest.TestCase):
self.fail("tor didn't quit after the process that owned it terminated")
- @require_version(stem.version.Requirement.TAKEOWNERSHIP)
- @only_run_once
+ @test.require.only_run_once
+ @test.require.version(stem.version.Requirement.TAKEOWNERSHIP)
def test_take_ownership_via_controller(self):
"""
Checks that the tor process quits after the controller that owns it
diff --git a/test/integ/response/protocolinfo.py b/test/integ/response/protocolinfo.py
index 8563cf0..1a00671 100644
--- a/test/integ/response/protocolinfo.py
+++ b/test/integ/response/protocolinfo.py
@@ -9,10 +9,11 @@ import stem.connection
import stem.socket
import stem.util.system
import stem.version
+import test.require
import test.runner
from test.integ.util.system import filter_system_call
-from test.util import require_controller, tor_version
+from test.util import tor_version
try:
# added in python 3.3
@@ -22,7 +23,7 @@ except ImportError:
class TestProtocolInfo(unittest.TestCase):
- @require_controller
+ @test.require.controller
def test_parsing(self):
"""
Makes a PROTOCOLINFO query and processes the response for our control
@@ -44,7 +45,7 @@ class TestProtocolInfo(unittest.TestCase):
self.assert_matches_test_config(protocolinfo_response)
- @require_controller
+ @test.require.controller
@patch('stem.util.proc.is_available', Mock(return_value = False))
@patch('stem.util.system.is_available', Mock(return_value = True))
def test_get_protocolinfo_path_expansion(self):
@@ -87,7 +88,7 @@ class TestProtocolInfo(unittest.TestCase):
self.assertTrue(control_socket.is_alive())
control_socket.close()
- @require_controller
+ @test.require.controller
def test_multiple_protocolinfo_calls(self):
"""
Tests making repeated PROTOCOLINFO queries. This use case is interesting
@@ -100,7 +101,7 @@ class TestProtocolInfo(unittest.TestCase):
protocolinfo_response = stem.connection.get_protocolinfo(control_socket)
self.assert_matches_test_config(protocolinfo_response)
- @require_controller
+ @test.require.controller
def test_pre_disconnected_query(self):
"""
Tests making a PROTOCOLINFO query when previous use of the socket had
diff --git a/test/integ/socket/control_message.py b/test/integ/socket/control_message.py
index 646f732..6d16f48 100644
--- a/test/integ/socket/control_message.py
+++ b/test/integ/socket/control_message.py
@@ -7,17 +7,14 @@ import unittest
import stem.socket
import stem.version
+import test.require
import test.runner
-from test.util import (
- require_controller,
- require_version,
- random_fingerprint,
-)
+from test.util import random_fingerprint
class TestControlMessage(unittest.TestCase):
- @require_controller
+ @test.require.controller
def test_unestablished_socket(self):
"""
Checks message parsing when we have a valid but unauthenticated socket.
@@ -58,7 +55,7 @@ class TestControlMessage(unittest.TestCase):
self.assertRaises(stem.SocketClosed, control_socket.send, 'GETINFO version')
self.assertRaises(stem.SocketClosed, control_socket.recv)
- @require_controller
+ @test.require.controller
def test_invalid_command(self):
"""
Parses the response for a command which doesn't exist.
@@ -72,7 +69,7 @@ class TestControlMessage(unittest.TestCase):
self.assertEqual('510 Unrecognized command "blarg"\r\n', unrecognized_command_response.raw_content())
self.assertEqual([('510', ' ', 'Unrecognized command "blarg"')], unrecognized_command_response.content())
- @require_controller
+ @test.require.controller
def test_invalid_getinfo(self):
"""
Parses the response for a GETINFO query which doesn't exist.
@@ -86,7 +83,7 @@ class TestControlMessage(unittest.TestCase):
self.assertEqual('552 Unrecognized key "blarg"\r\n', unrecognized_key_response.raw_content())
self.assertEqual([('552', ' ', 'Unrecognized key "blarg"')], unrecognized_key_response.content())
- @require_controller
+ @test.require.controller
def test_getinfo_config_file(self):
"""
Parses the 'GETINFO config-file' response.
@@ -103,8 +100,8 @@ class TestControlMessage(unittest.TestCase):
self.assertEqual('250-config-file=%s\r\n250 OK\r\n' % torrc_dst, config_file_response.raw_content())
self.assertEqual([('250', '-', 'config-file=%s' % torrc_dst), ('250', ' ', 'OK')], config_file_response.content())
- @require_controller
- @require_version(stem.version.Requirement.GETINFO_CONFIG_TEXT)
+ @test.require.controller
+ @test.require.version(stem.version.Requirement.GETINFO_CONFIG_TEXT)
def test_getinfo_config_text(self):
"""
Parses the 'GETINFO config-text' response.
@@ -145,7 +142,7 @@ class TestControlMessage(unittest.TestCase):
self.assertTrue('%s\r\n' % torrc_entry in config_text_response.raw_content())
self.assertTrue('%s' % torrc_entry in config_text_response.content()[0][2])
- @require_controller
+ @test.require.controller
def test_setconf_event(self):
"""
Issues 'SETEVENTS CONF_CHANGED' and parses an events.
diff --git a/test/integ/socket/control_socket.py b/test/integ/socket/control_socket.py
index a4da321..8e2658a 100644
--- a/test/integ/socket/control_socket.py
+++ b/test/integ/socket/control_socket.py
@@ -14,13 +14,14 @@ import unittest
import stem.connection
import stem.control
import stem.socket
+import test.require
import test.runner
-from test.util import require_controller, tor_version
+from test.util import tor_version
class TestControlSocket(unittest.TestCase):
- @require_controller
+ @test.require.controller
def test_connection_time(self):
"""
Checks that our connection_time method tracks when our state's changed.
@@ -54,7 +55,7 @@ class TestControlSocket(unittest.TestCase):
reconnection_time = control_socket.connection_time()
self.assertTrue(disconnection_time < reconnection_time <= time.time())
- @require_controller
+ @test.require.controller
def test_send_buffered(self):
"""
Sends multiple requests before receiving back any of the replies.
@@ -71,7 +72,7 @@ class TestControlSocket(unittest.TestCase):
self.assertTrue(str(response).startswith('version=%s' % tor_version()))
self.assertTrue(str(response).endswith('\nOK'))
- @require_controller
+ @test.require.controller
def test_send_closed(self):
"""
Sends a message after we've closed the connection.
@@ -84,7 +85,7 @@ class TestControlSocket(unittest.TestCase):
self.assertRaises(stem.SocketClosed, control_socket.send, 'blarg')
- @require_controller
+ @test.require.controller
def test_send_disconnected(self):
"""
Sends a message to a socket that has been disconnected by the other end.
@@ -110,7 +111,7 @@ class TestControlSocket(unittest.TestCase):
self.assertRaises(stem.SocketClosed, control_socket.send, 'blarg')
self.assertFalse(control_socket.is_alive())
- @require_controller
+ @test.require.controller
def test_recv_closed(self):
"""
Receives a message after we've closed the connection.
@@ -123,7 +124,7 @@ class TestControlSocket(unittest.TestCase):
self.assertRaises(stem.SocketClosed, control_socket.recv)
- @require_controller
+ @test.require.controller
def test_recv_disconnected(self):
"""
Receives a message from a socket that has been disconnected by the other
@@ -142,7 +143,7 @@ class TestControlSocket(unittest.TestCase):
self.assertRaises(stem.SocketClosed, control_socket.recv)
self.assertFalse(control_socket.is_alive())
- @require_controller
+ @test.require.controller
def test_connect_repeatedly(self):
"""
Checks that we can reconnect, use, and disconnect a socket repeatedly.
diff --git a/test/integ/util/connection.py b/test/integ/util/connection.py
index f641a37..1fc08c4 100644
--- a/test/integ/util/connection.py
+++ b/test/integ/util/connection.py
@@ -5,14 +5,14 @@ that we're running.
import unittest
+import test.require
import test.runner
from stem.util.connection import Resolver, get_connections, system_resolvers
-from test.util import require_ptrace
class TestConnection(unittest.TestCase):
- @require_ptrace
+ @test.require.ptrace
def check_resolver(self, resolver):
runner = test.runner.get_runner()
diff --git a/test/integ/util/proc.py b/test/integ/util/proc.py
index ef3a7c0..da4d6ef 100644
--- a/test/integ/util/proc.py
+++ b/test/integ/util/proc.py
@@ -6,19 +6,15 @@ we're running.
import os
import unittest
+import test.require
import test.runner
from stem.util import proc
-from test.util import (
- require_proc,
- require_ptrace,
-)
-
class TestProc(unittest.TestCase):
- @require_proc
- @require_ptrace
+ @test.require.proc
+ @test.require.ptrace
def test_cwd(self):
"""
Checks that stem.util.proc.cwd matches our tor instance's cwd.
@@ -28,7 +24,7 @@ class TestProc(unittest.TestCase):
runner_pid, tor_cwd = runner.get_pid(), runner.get_tor_cwd()
self.assertEqual(tor_cwd, proc.cwd(runner_pid))
- @require_proc
+ @test.require.proc
def test_uid(self):
"""
Checks that stem.util.proc.uid matches our tor instance's uid.
@@ -37,7 +33,7 @@ class TestProc(unittest.TestCase):
tor_pid = test.runner.get_runner().get_pid()
self.assertEqual(os.geteuid(), proc.uid(tor_pid))
- @require_proc
+ @test.require.proc
def test_memory_usage(self):
"""
Checks that stem.util.proc.memory_usage looks somewhat reasonable.
@@ -50,7 +46,7 @@ class TestProc(unittest.TestCase):
self.assertTrue(res_size > 1024)
self.assertTrue(vir_size > 1024)
- @require_proc
+ @test.require.proc
def test_stats(self):
"""
Checks that stem.util.proc.stats looks somewhat reasonable.
@@ -65,8 +61,8 @@ class TestProc(unittest.TestCase):
self.assertTrue(float(stime) >= 0)
self.assertTrue(float(start_time) > proc.system_start_time())
- @require_proc
- @require_ptrace
+ @test.require.proc
+ @test.require.ptrace
def test_connections(self):
"""
Checks for our control port in the stem.util.proc.connections output if
diff --git a/test/integ/util/system.py b/test/integ/util/system.py
index 88a5529..912251b 100644
--- a/test/integ/util/system.py
+++ b/test/integ/util/system.py
@@ -10,15 +10,9 @@ import unittest
import stem.util.proc
import stem.util.system
+import test.require
import test.runner
-from test.util import (
- require,
- require_command,
- require_proc,
- require_ptrace,
-)
-
try:
# added in python 3.3
from unittest.mock import Mock, patch
@@ -68,10 +62,10 @@ def _has_port():
return test.runner.Torrc.PORT in test.runner.get_runner().get_options()
-require_single_tor_instance = require(_is_single_tor_running, 'multiple tor instances')
-require_control_port = require(_has_port, 'test instance has no port')
-require_linux = require(_is_linux, 'linux only')
-require_bsd = require(stem.util.system.is_bsd, 'bsd only')
+require_single_tor_instance = test.require.needs(_is_single_tor_running, 'multiple tor instances')
+require_control_port = test.require.needs(_has_port, 'test instance has no port')
+require_linux = test.require.needs(_is_linux, 'linux only')
+require_bsd = test.require.needs(stem.util.system.is_bsd, 'bsd only')
class TestSystem(unittest.TestCase):
@@ -91,7 +85,7 @@ class TestSystem(unittest.TestCase):
self.assertFalse(stem.util.system.is_available('blarg_and_stuff'))
- @require_command('ps')
+ @test.require.command('ps')
def test_is_running(self):
"""
Checks the stem.util.system.is_running function.
@@ -117,8 +111,8 @@ class TestSystem(unittest.TestCase):
self.assertEqual(tor_pid, stem.util.system.pid_by_name(tor_cmd))
self.assertEqual(None, stem.util.system.pid_by_name('blarg_and_stuff'))
- @require_command('pgrep')
@require_single_tor_instance
+ @test.require.command('pgrep')
def test_pid_by_name_pgrep(self):
"""
Tests the pid_by_name function with a pgrep response.
@@ -134,8 +128,8 @@ class TestSystem(unittest.TestCase):
tor_cmd = test.runner.get_runner().get_tor_command(True)
self.assertEqual(tor_pid, stem.util.system.pid_by_name(tor_cmd))
- @require_command('pidof')
@require_single_tor_instance
+ @test.require.command('pidof')
def test_pid_by_name_pidof(self):
"""
Tests the pid_by_name function with a pidof response.
@@ -152,8 +146,8 @@ class TestSystem(unittest.TestCase):
self.assertEqual(tor_pid, stem.util.system.pid_by_name(tor_cmd))
@require_linux
- @require_command('ps')
@require_single_tor_instance
+ @test.require.command('ps')
def test_pid_by_name_ps_linux(self):
"""
Tests the pid_by_name function with the linux variant of ps.
@@ -170,8 +164,8 @@ class TestSystem(unittest.TestCase):
self.assertEqual(tor_pid, stem.util.system.pid_by_name(tor_cmd))
@require_bsd
- @require_command('ps')
@require_single_tor_instance
+ @test.require.command('ps')
def test_pid_by_name_ps_bsd(self):
"""
Tests the pid_by_name function with the bsd variant of ps.
@@ -187,9 +181,9 @@ class TestSystem(unittest.TestCase):
tor_cmd = test.runner.get_runner().get_tor_command(True)
self.assertEqual(tor_pid, stem.util.system.pid_by_name(tor_cmd))
- @require_ptrace
- @require_command('lsof')
@require_single_tor_instance
+ @test.require.ptrace
+ @test.require.command('lsof')
def test_pid_by_name_lsof(self):
"""
Tests the pid_by_name function with a lsof response.
@@ -208,8 +202,8 @@ class TestSystem(unittest.TestCase):
if len(all_tor_pids) == 1:
self.assertEqual(our_tor_pid, all_tor_pids[0])
- @require_command('tasklist')
@require_single_tor_instance
+ @test.require.command('tasklist')
def test_pid_by_name_tasklist(self):
"""
Tests the pid_by_name function with a tasklist response.
@@ -218,8 +212,8 @@ class TestSystem(unittest.TestCase):
runner = test.runner.get_runner()
self.assertEqual(runner.get_pid(), stem.util.system.pid_by_name(runner.get_tor_command(True)))
- @require_ptrace
@require_control_port
+ @test.require.ptrace
def test_pid_by_port(self):
"""
Checks general usage of the stem.util.system.pid_by_port function.
@@ -243,9 +237,9 @@ class TestSystem(unittest.TestCase):
self.assertEqual(None, stem.util.system.pid_by_port(99999))
@require_linux
- @require_ptrace
@require_control_port
- @require_command('netstat')
+ @test.require.ptrace
+ @test.require.command('netstat')
def test_pid_by_port_netstat(self):
"""
Tests the pid_by_port function with a netstat response.
@@ -266,9 +260,9 @@ class TestSystem(unittest.TestCase):
self.assertEqual(tor_pid, stem.util.system.pid_by_port(test.runner.CONTROL_PORT))
@require_bsd
- @require_ptrace
@require_control_port
- @require_command('sockstat')
+ @test.require.ptrace
+ @test.require.command('sockstat')
def test_pid_by_port_sockstat(self):
"""
Tests the pid_by_port function with a sockstat response.
@@ -283,9 +277,9 @@ class TestSystem(unittest.TestCase):
tor_pid = test.runner.get_runner().get_pid()
self.assertEqual(tor_pid, stem.util.system.pid_by_port(test.runner.CONTROL_PORT))
- @require_ptrace
@require_control_port
- @require_command('lsof')
+ @test.require.ptrace
+ @test.require.command('lsof')
def test_pid_by_port_lsof(self):
"""
Tests the pid_by_port function with a lsof response.
@@ -328,7 +322,7 @@ class TestSystem(unittest.TestCase):
pids = stem.util.system.pids_by_user(getpass.getuser())
self.assertTrue(os.getpid() in pids)
- @require_ptrace
+ @test.require.ptrace
def test_cwd(self):
"""
Checks general usage of the stem.util.system.cwd function.
@@ -343,8 +337,8 @@ class TestSystem(unittest.TestCase):
self.assertEqual(tor_cwd, stem.util.system.cwd(runner_pid))
self.assertEqual(None, stem.util.system.cwd(99999))
- @require_ptrace
- @require_command('pwdx')
+ @test.require.ptrace
+ @test.require.command('pwdx')
def test_cwd_pwdx(self):
"""
Tests the pid_by_cwd function with a pwdx response.
@@ -363,8 +357,8 @@ class TestSystem(unittest.TestCase):
runner_pid, tor_cwd = runner.get_pid(), runner.get_tor_cwd()
self.assertEqual(tor_cwd, stem.util.system.cwd(runner_pid))
- @require_ptrace
- @require_command('lsof')
+ @test.require.ptrace
+ @test.require.command('lsof')
def test_cwd_lsof(self):
"""
Tests the pid_by_cwd function with a lsof response.
@@ -392,7 +386,7 @@ class TestSystem(unittest.TestCase):
self.assertEqual(None, stem.util.system.user(-5))
self.assertEqual(None, stem.util.system.start_time(98765))
- @require_proc
+ @test.require.proc
def test_user_proc(self):
"""
Tests the user function with a proc response.
@@ -408,7 +402,7 @@ class TestSystem(unittest.TestCase):
pid = test.runner.get_runner().get_pid()
self.assertTrue(getpass.getuser(), stem.util.system.user(pid))
- @require_command('ps')
+ @test.require.command('ps')
@patch('stem.util.proc.is_available', Mock(return_value = False))
def test_user_ps(self):
"""
@@ -427,7 +421,7 @@ class TestSystem(unittest.TestCase):
self.assertEqual(None, stem.util.system.start_time(-5))
self.assertEqual(None, stem.util.system.start_time(98765))
- @require_proc
+ @test.require.proc
def test_start_time_proc(self):
"""
Tests the start_time function with a proc response.
@@ -441,7 +435,7 @@ class TestSystem(unittest.TestCase):
pid = test.runner.get_runner().get_pid()
self.assertTrue(stem.util.system.start_time(pid) >= 0)
- @require_command('ps')
+ @test.require.command('ps')
@patch('stem.util.proc.is_available', Mock(return_value = False))
def test_start_time_ps(self):
"""
diff --git a/test/integ/version.py b/test/integ/version.py
index 3cef9b2..b28ee86 100644
--- a/test/integ/version.py
+++ b/test/integ/version.py
@@ -7,16 +7,12 @@ import unittest
import stem.prereq
import stem.version
+import test.require
import test.runner
-from test.util import (
- require_command,
- require_controller,
-)
-
class TestVersion(unittest.TestCase):
- @require_command('tor')
+ @test.require.command('tor')
def test_get_system_tor_version(self):
"""
Basic verification checks for the get_system_tor_version() function.
@@ -34,7 +30,7 @@ class TestVersion(unittest.TestCase):
# try running against a command that doesn't exist
self.assertRaises(IOError, stem.version.get_system_tor_version, 'blarg')
- @require_controller
+ @test.require.controller
def test_getinfo_version_parsing(self):
"""
Issues a 'GETINFO version' query to our test instance and makes sure that
diff --git a/test/require.py b/test/require.py
new file mode 100644
index 0000000..a0735d8
--- /dev/null
+++ b/test/require.py
@@ -0,0 +1,106 @@
+# Copyright 2012-2017, Damian Johnson and The Tor Project
+# See LICENSE for licensing information
+
+"""
+Testing requirements. This provides annotations to skip tests that shouldn't be
+run.
+
+::
+
+ Test Requirements
+ |- only_run_once - skip test if it has been ran before
+ |- needs - skips the test unless a requirement is met
+ |
+ |- cryptography - skips test unless the cryptography module is present
+ |- pynacl - skips test unless the pynacl module is present
+ |- command - requires a command to be on the path
+ |- proc - requires the platform to have recognized /proc contents
+ |
+ |- controller - skips test unless tor provides a controller endpoint
+ |- version - skips test unless we meet a tor version requirement
+ |- ptrace - requires 'DisableDebuggerAttachment' to be set
+ +- online - skips unless targets allow for online tests
+"""
+
+import stem.util.system
+import stem.version
+import test.runner
+import test.util
+
+RAN_TESTS = []
+
+
+def only_run_once(func):
+ """
+ Skips the test if it has ran before. If it hasn't then flags it as being ran.
+ This is useful to prevent lengthy tests that are independent of integ targets
+ from being run repeatedly with ``RUN_ALL``.
+ """
+
+ def wrapped(self, *args, **kwargs):
+ if self.id() not in RAN_TESTS:
+ RAN_TESTS.append(self.id())
+ return func(self, *args, **kwargs)
+ else:
+ self.skipTest('(already ran)')
+
+ return wrapped
+
+
+def needs(condition, message):
+ """
+ Skips teh test unless the conditional evaluates to 'true'.
+ """
+
+ def decorator(func):
+ def wrapped(self, *args, **kwargs):
+ if condition():
+ return func(self, *args, **kwargs)
+ else:
+ self.skipTest('(%s)' % message)
+
+ return wrapped
+
+ return decorator
+
+
+def _can_access_controller():
+ return test.runner.get_runner().is_accessible()
+
+
+def _can_ptrace():
+ # If we're running a tor version where ptrace is disabled and we didn't
+ # set 'DisableDebuggerAttachment=1' then we can infer that it's disabled.
+
+ has_option = test.util.tor_version() >= stem.version.Requirement.TORRC_DISABLE_DEBUGGER_ATTACHMENT
+ return not has_option or test.runner.Torrc.PTRACE in test.runner.get_runner().get_options()
+
+
+def _is_online():
+ return test.util.Target.ONLINE in test.runner.get_runner().attribute_targets
+
+
+def command(cmd):
+ """
+ Skips the test unless a command is available on the path.
+ """
+
+ return needs(lambda: stem.util.system.is_available(cmd), '%s unavailable' % cmd)
+
+
+def version(req_version):
+ """
+ Skips the test unless we meet the required version.
+
+ :param stem.version.Version req_version: required tor version for the test
+ """
+
+ return needs(lambda: test.util.tor_version() >= req_version, 'requires %s' % req_version)
+
+
+cryptography = needs(stem.prereq.is_crypto_available, 'requires cryptography')
+pynacl = needs(stem.prereq._is_pynacl_available, 'requires pynacl module')
+proc = needs(stem.util.proc.is_available, 'proc unavailable')
+controller = needs(_can_access_controller, 'no connection')
+ptrace = needs(_can_ptrace, 'DisableDebuggerAttachment is set')
+online = needs(_is_online, 'requires online target')
diff --git a/test/unit/descriptor/certificate.py b/test/unit/descriptor/certificate.py
index 0cef45a..19d7c64 100644
--- a/test/unit/descriptor/certificate.py
+++ b/test/unit/descriptor/certificate.py
@@ -10,10 +10,10 @@ import unittest
import stem.descriptor.certificate
import stem.util.str_tools
import stem.prereq
+import test.require
from stem.descriptor.certificate import ED25519_SIGNATURE_LENGTH, CertType, ExtensionType, ExtensionFlag, Ed25519Certificate, Ed25519CertificateV1, Ed25519Extension
from test.unit.descriptor import get_resource
-from test.util import require_pynacl
ED25519_CERT = """
AQQABhtZAaW2GoBED1IjY3A6f6GNqBEl5A83fD2Za9upGke51JGqAQAgBABnprVR
@@ -147,7 +147,7 @@ class TestEd25519Certificate(unittest.TestCase):
self.assert_raises(certificate(extension_data = [b'\x00\x02\x04\x07\11\12']), "Ed25519 HAS_SIGNING_KEY extension must be 32 bytes, but was 2.")
- @require_pynacl
+ @test.require.pynacl
def test_validation_with_descriptor_key(self):
"""
Validate a descriptor signature using the ed25519 master key within the
@@ -159,7 +159,7 @@ class TestEd25519Certificate(unittest.TestCase):
desc.certificate.validate(desc)
- @require_pynacl
+ @test.require.pynacl
def test_validation_with_embedded_key(self):
"""
Validate a descriptor signature using the signing key within the ed25519
@@ -172,7 +172,7 @@ class TestEd25519Certificate(unittest.TestCase):
desc.ed25519_master_key = None
desc.certificate.validate(desc)
- @require_pynacl
+ @test.require.pynacl
def test_validation_with_invalid_descriptor(self):
"""
Validate a descriptor without a valid signature.
diff --git a/test/unit/descriptor/hidden_service_descriptor.py b/test/unit/descriptor/hidden_service_descriptor.py
index 48f1d29..2f8427f 100644
--- a/test/unit/descriptor/hidden_service_descriptor.py
+++ b/test/unit/descriptor/hidden_service_descriptor.py
@@ -8,8 +8,7 @@ import unittest
import stem.descriptor
import stem.prereq
-
-from test.util import require_cryptography
+import test.require
from stem.descriptor.hidden_service_descriptor import (
REQUIRED_FIELDS,
@@ -274,7 +273,7 @@ class TestHiddenServiceDescriptor(unittest.TestCase):
self.assertEqual(datetime.datetime(2014, 10, 31, 23, 0, 0), desc.published)
self.assertEqual([2, 3], desc.protocol_versions)
- @require_cryptography
+ @test.require.cryptography
def test_with_basic_auth(self):
"""
Parse a descriptor with introduction-points encrypted with basic auth.
@@ -321,7 +320,7 @@ class TestHiddenServiceDescriptor(unittest.TestCase):
self.assertTrue('MIGJAoGBAM7B/cymp' in point.service_key)
self.assertEqual([], point.intro_authentication)
- @require_cryptography
+ @test.require.cryptography
def test_with_stealth_auth(self):
"""
Parse a descriptor with introduction-points encrypted with stealth auth.
diff --git a/test/unit/manual.py b/test/unit/manual.py
index 6bfcbe7..28a8a8b 100644
--- a/test/unit/manual.py
+++ b/test/unit/manual.py
@@ -11,8 +11,7 @@ import unittest
import stem.prereq
import stem.manual
import stem.util.system
-
-from test.util import require_command
+import test.require
try:
# account for urllib's change between python 2.x and 3.x
@@ -138,7 +137,7 @@ class TestManual(unittest.TestCase):
self.assertEqual('', blank.summary)
self.assertEqual('', blank.description)
- @require_command('man')
+ @test.require.command('man')
def test_parsing_with_example(self):
"""
Read a trimmed copy of tor's man page. This gives a good exercise of our
@@ -160,7 +159,7 @@ class TestManual(unittest.TestCase):
self.assertEqual(EXPECTED_FILES, manual.files)
self.assertEqual(EXPECTED_CONFIG_OPTIONS, manual.config_options)
- @require_command('man')
+ @test.require.command('man')
def test_parsing_with_unknown_options(self):
"""
Check that we can read a local mock man page that contains unrecognized
@@ -189,7 +188,7 @@ class TestManual(unittest.TestCase):
self.assertEqual('', option.summary)
self.assertEqual('Description of this new option.', option.description)
- @require_command('man')
+ @test.require.command('man')
def test_saving_manual(self):
"""
Check that we can save and reload manuals.
diff --git a/test/util.py b/test/util.py
index e8af8e1..47d90fd 100644
--- a/test/util.py
+++ b/test/util.py
@@ -12,24 +12,6 @@ Helper functions for our test framework.
get_prereq - provides the tor version required to run the given target
get_torrc_entries - provides the torrc entries for a given target
-This module also provides generally useful test helpers...
-
-::
-
- Test Requirements
- |- only_run_once - skip test if it has been ran before
- |- require - skips the test unless a requirement is met
- |
- |- require_cryptography - skips test unless the cryptography module is present
- |- require_pynacl - skips test unless the pynacl module is present
- |- require_command - requires a command to be on the path
- |- require_proc - requires the platform to have recognized /proc contents
- |
- |- require_controller - skips test unless tor provides a controller endpoint
- |- require_version - skips test unless we meet a tor version requirement
- |- require_ptrace - requires 'DisableDebuggerAttachment' to be set
- +- require_online - skips unless targets allow for online tests
-
get_message - provides a ControlMessage instance
get_protocolinfo_response - provides a ProtocolInfoResponse instance
get_all_combinations - provides all combinations of attributes
@@ -43,14 +25,10 @@ import re
import os
import stem
-import stem.prereq
import stem.util.conf
-import stem.util.system
-import stem.util.test_tools
+import stem.util.enum
import stem.version
-import test.output
-
CONFIG = stem.util.conf.config_dict('test', {
'target.prereq': {},
'target.torrc': {},
@@ -83,7 +61,6 @@ Target = stem.util.enum.UppercaseEnum(
'RUN_ALL',
)
-RAN_TESTS = []
TOR_VERSION = None
# We make some paths relative to stem's base directory (the one above us)
@@ -211,82 +188,6 @@ def get_new_capabilities():
return NEW_CAPABILITIES
-def only_run_once(func):
- """
- Skips the test if it has ran before. If it hasn't then flags it as being ran.
- This is useful to prevent lengthy tests that are independent of integ targets
- from being run repeatedly with ``RUN_ALL``.
- """
-
- def wrapped(self, *args, **kwargs):
- if self.id() not in RAN_TESTS:
- RAN_TESTS.append(self.id())
- return func(self, *args, **kwargs)
- else:
- self.skipTest('(already ran)')
-
- return wrapped
-
-
-def require(condition, message):
- """
- Skips teh test unless the conditional evaluates to 'true'.
- """
-
- def decorator(func):
- def wrapped(self, *args, **kwargs):
- if condition():
- return func(self, *args, **kwargs)
- else:
- self.skipTest('(%s)' % message)
-
- return wrapped
-
- return decorator
-
-
-def _can_access_controller():
- return test.runner.get_runner().is_accessible()
-
-
-def _can_ptrace():
- # If we're running a tor version where ptrace is disabled and we didn't
- # set 'DisableDebuggerAttachment=1' then we can infer that it's disabled.
-
- has_option = tor_version() >= stem.version.Requirement.TORRC_DISABLE_DEBUGGER_ATTACHMENT
- return not has_option or test.runner.Torrc.PTRACE in test.runner.get_runner().get_options()
-
-
-def _is_online():
- return Target.ONLINE in test.runner.get_runner().attribute_targets
-
-
-require_cryptography = require(stem.prereq.is_crypto_available, 'requires cryptography')
-require_pynacl = require(stem.prereq._is_pynacl_available, 'requires pynacl module')
-require_proc = require(stem.util.proc.is_available, 'proc unavailable')
-require_controller = require(_can_access_controller, 'no connection')
-require_ptrace = require(_can_ptrace, 'DisableDebuggerAttachment is set')
-require_online = require(_is_online, 'requires online target')
-
-
-def require_command(cmd):
- """
- Skips the test unless a command is available on the path.
- """
-
- return require(lambda: stem.util.system.is_available(cmd), '%s unavailable' % cmd)
-
-
-def require_version(req_version):
- """
- Skips the test unless we meet the required version.
-
- :param stem.version.Version req_version: required tor version for the test
- """
-
- return require(lambda: tor_version() >= req_version, 'requires %s' % req_version)
-
-
def register_new_capability(capability_type, msg, suppression_token = None):
"""
Register new capability found during the tests.
1
0
commit bf94336ecec090a27f47fe4754c8bf13bc8b023e
Author: Damian Johnson <atagar(a)torproject.org>
Date: Sun May 21 18:41:54 2017 -0700
Drop get_prereq() helper
Huh. Not sure why we even had this. Only caller is run_tests.py and it can do
this just as well itself.
---
run_tests.py | 13 +++++++------
test/util.py | 22 ----------------------
2 files changed, 7 insertions(+), 28 deletions(-)
diff --git a/run_tests.py b/run_tests.py
index 026e09c..f3eabf4 100755
--- a/run_tests.py
+++ b/run_tests.py
@@ -24,6 +24,7 @@ import stem.util.enum
import stem.util.log
import stem.util.system
import stem.util.test_tools
+import stem.version
import test.arguments
import test.integ.installation
@@ -37,6 +38,7 @@ from test.util import STEM_BASE
CONFIG = stem.util.conf.config_dict('test', {
'integ.test_directory': './test/data',
+ 'target.prereq': {},
})
MOCK_UNAVAILABLE_MSG = """\
@@ -185,7 +187,7 @@ def main():
# these at the end of the test run so they're more noticeable.
our_version = stem.version.get_system_tor_version(args.tor_path)
- skipped_targets = []
+ skipped_targets = {}
integ_setup_thread = None
if not args.specific_test or 'test.integ.installation'.startswith(args.specific_test):
@@ -194,10 +196,10 @@ def main():
for target in args.run_targets:
# check if we meet this target's tor version prerequisites
- target_prereq = test.util.get_prereq(target)
+ target_prereq = CONFIG['target.prereq'].get(target)
- if target_prereq and our_version < target_prereq:
- skipped_targets.append(target)
+ if target_prereq and our_version < stem.version.Requirement(target_prereq):
+ skipped_targets[target] = target_prereq
continue
error_tracker.set_category(target)
@@ -254,8 +256,7 @@ def main():
if skipped_targets:
println()
- for target in skipped_targets:
- req_version = test.util.get_prereq(target)
+ for target, req_version in skipped_targets.items():
println('Unable to run target %s, this requires tor version %s' % (target, req_version), ERROR)
println()
diff --git a/test/util.py b/test/util.py
index 56bf975..2731f63 100644
--- a/test/util.py
+++ b/test/util.py
@@ -9,9 +9,7 @@ Helper functions for our test framework.
get_unit_tests - provides our unit tests
get_integ_tests - provides our integration tests
- get_prereq - provides the tor version required to run the given target
get_torrc_entries - provides the torrc entries for a given target
-
get_all_combinations - provides all combinations of attributes
tor_version - provides the version of tor we're testing against
"""
@@ -25,7 +23,6 @@ import stem.util.enum
import stem.version
CONFIG = stem.util.conf.config_dict('test', {
- 'target.prereq': {},
'target.torrc': {},
'integ.test_directory': './test/data',
'test.unit_tests': '',
@@ -124,25 +121,6 @@ def _get_tests(modules, module_prefix):
yield '%s.%s' % (import_name, test_module)
-def get_prereq(target):
- """
- Provides the tor version required to run the given target. If the target
- doesn't have any prerequisite then this provides **None**.
-
- :param Target target: target to provide the prerequisite for
-
- :returns: :class:`~stem.version.Version` required to run the given target, or
- **None** if there is no prerequisite
- """
-
- target_prereq = CONFIG['target.prereq'].get(target)
-
- if target_prereq:
- return stem.version.Requirement[target_prereq]
- else:
- return None
-
-
def get_torrc_entries(target):
"""
Provides the torrc entries used to run the given target.
1
0

22 May '17
commit 2170254997d5a3e44bc12898a0c3acb94f70f7c7
Author: Damian Johnson <atagar(a)torproject.org>
Date: Sun May 21 19:26:52 2017 -0700
Merge remaining test.util into base test module
Now that we got this down to a small size we can merge what remains into
test/__init__.py.
---
run_tests.py | 7 +-
test/__init__.py | 145 ++++++++++++++++++++++++-
test/arguments.py | 17 ++-
test/integ/connection/authentication.py | 7 +-
test/integ/control/controller.py | 19 ++--
test/integ/descriptor/extrainfo_descriptor.py | 5 +-
test/integ/descriptor/microdescriptor.py | 5 +-
test/integ/descriptor/networkstatus.py | 11 +-
test/integ/descriptor/server_descriptor.py | 5 +-
test/integ/installation.py | 14 +--
test/integ/interpreter.py | 6 +-
test/integ/manual.py | 3 +-
test/integ/response/protocolinfo.py | 9 +-
test/integ/socket/control_socket.py | 5 +-
test/require.py | 8 +-
test/runner.py | 14 +--
test/settings.cfg | 3 +-
test/task.py | 15 ++-
test/unit/__init__.py | 4 +-
test/unit/connection/authentication.py | 4 +-
test/unit/doctest.py | 4 +-
test/unit/installation.py | 14 +--
test/unit/util/proc.py | 4 +-
test/util.py | 146 --------------------------
24 files changed, 229 insertions(+), 245 deletions(-)
diff --git a/run_tests.py b/run_tests.py
index 6beb659..725dd5a 100755
--- a/run_tests.py
+++ b/run_tests.py
@@ -26,15 +26,14 @@ import stem.util.system
import stem.util.test_tools
import stem.version
+import test
import test.arguments
import test.integ.installation
import test.output
import test.runner
import test.task
-import test.util
from test.output import STATUS, SUCCESS, ERROR, NO_NL, STDERR, println
-from test.util import STEM_BASE
CONFIG = stem.util.conf.config_dict('test', {
'test.unit_tests': '',
@@ -158,7 +157,7 @@ def main():
sys.exit(1)
test_config = stem.util.conf.get_config('test')
- test_config.load(os.path.join(STEM_BASE, 'test', 'settings.cfg'))
+ test_config.load(os.path.join(test.STEM_BASE, 'test', 'settings.cfg'))
try:
args = test.arguments.parse(sys.argv[1:])
@@ -377,7 +376,7 @@ def main():
println('TESTING PASSED %s\n' % runtime_label, SUCCESS)
- new_capabilities = test.util.get_new_capabilities()
+ new_capabilities = test.get_new_capabilities()
if new_capabilities:
println(NEW_CAPABILITIES_FOUND, ERROR)
diff --git a/test/__init__.py b/test/__init__.py
index 8ea70d2..355497c 100644
--- a/test/__init__.py
+++ b/test/__init__.py
@@ -2,7 +2,15 @@
# See LICENSE for licensing information
"""
-Unit and integration tests for the stem library.
+Unit and integration tests for the stem library. Helpers include...
+
+::
+
+ get_new_capabilities - missing capabilities found while testing
+ register_new_capability - note that tor feature stem lacks
+
+ get_all_combinations - provides all combinations of attributes
+ tor_version - provides the version of tor we're testing against
"""
__all__ = [
@@ -10,5 +18,138 @@ __all__ = [
'output',
'prompt',
'runner',
- 'util',
]
+
+import itertools
+import os
+
+import stem.util.enum
+import stem.version
+
+# Integration targets fall into two categories:
+#
+# * Run Targets (like RUN_COOKIE and RUN_PTRACE) which customize our torrc.
+# We do an integration test run for each run target we get.
+#
+# * Attribute Target (like CHROOT and ONLINE) which indicates
+# non-configuration changes to your test runs. These are applied to all
+# integration runs that we perform.
+
+Target = stem.util.enum.UppercaseEnum(
+ 'ONLINE',
+ 'RELATIVE',
+ 'CHROOT',
+ 'RUN_NONE',
+ 'RUN_OPEN',
+ 'RUN_PASSWORD',
+ 'RUN_COOKIE',
+ 'RUN_MULTIPLE',
+ 'RUN_SOCKET',
+ 'RUN_SCOOKIE',
+ 'RUN_PTRACE',
+ 'RUN_ALL',
+)
+
+TOR_VERSION = None
+
+# We make some paths relative to stem's base directory (the one above us)
+# rather than the process' cwd. This doesn't end with a slash.
+
+STEM_BASE = os.path.sep.join(__file__.split(os.path.sep)[:-2])
+
+# Store new capabilities (events, descriptor entries, etc.)
+
+NEW_CAPABILITIES = []
+NEW_CAPABILITIES_SUPPRESSION_TOKENS = set()
+
+# File extensions of contents that should be ignored.
+
+IGNORED_FILE_TYPES = []
+
+with open(os.path.join(STEM_BASE, '.gitignore')) as ignore_file:
+ for line in ignore_file:
+ if line.startswith('*.'):
+ IGNORED_FILE_TYPES.append(line[2:].strip())
+
+
+def get_new_capabilities():
+ """
+ Provides a list of capabilities tor supports but stem doesn't, as discovered
+ while running our tests.
+
+ :returns: **list** of (type, message) tuples for the capabilities
+ """
+
+ return NEW_CAPABILITIES
+
+
+def register_new_capability(capability_type, msg, suppression_token = None):
+ """
+ Register new capability found during the tests.
+
+ :param str capability_type: type of capability this is
+ :param str msg: description of what we found
+ :param str suppression_token: skip registration if this token's already been
+ provided
+ """
+
+ if suppression_token not in NEW_CAPABILITIES_SUPPRESSION_TOKENS:
+ NEW_CAPABILITIES.append((capability_type, msg))
+
+ if suppression_token:
+ NEW_CAPABILITIES_SUPPRESSION_TOKENS.add(suppression_token)
+
+
+def get_all_combinations(attr, include_empty = False):
+ """
+ Provides an iterator for all combinations of a set of attributes. For
+ instance...
+
+ ::
+
+ >>> list(test.get_all_combinations(['a', 'b', 'c']))
+ [('a',), ('b',), ('c',), ('a', 'b'), ('a', 'c'), ('b', 'c'), ('a', 'b', 'c')]
+
+ :param list attr: attributes to provide combinations for
+ :param bool include_empty: includes an entry with zero items if True
+ :returns: iterator for all combinations
+ """
+
+ # Makes an itertools.product() call for 'i' copies of attr...
+ #
+ # * itertools.product(attr) => all one-element combinations
+ # * itertools.product(attr, attr) => all two-element combinations
+ # * ... etc
+
+ if include_empty:
+ yield ()
+
+ seen = set()
+ for index in range(1, len(attr) + 1):
+ product_arg = [attr for _ in range(index)]
+
+ for item in itertools.product(*product_arg):
+ # deduplicate, sort, and only provide if we haven't seen it yet
+ item = tuple(sorted(set(item)))
+
+ if item not in seen:
+ seen.add(item)
+ yield item
+
+
+def tor_version(tor_path = None):
+ """
+ Provides the version of tor we're testing against.
+
+ :param str tor_path: location of tor executable to cehck the version of
+
+ :returns: :class:`~stem.version.Version` of tor invoked by our integration
+ tests
+ """
+
+ global TOR_VERSION
+
+ if TOR_VERSION is None or tor_path:
+ TOR_VERSION = stem.version.get_system_tor_version(tor_path)
+
+ return TOR_VERSION
diff --git a/test/arguments.py b/test/arguments.py
index 4ecd3bb..83197a7 100644
--- a/test/arguments.py
+++ b/test/arguments.py
@@ -10,8 +10,7 @@ import getopt
import stem.util.conf
import stem.util.log
-
-from test.util import Target
+import test
LOG_TYPE_ERROR = """\
'%s' isn't a logging runlevel, use one of the following instead:
@@ -30,7 +29,7 @@ DEFAULT_ARGS = {
'specific_test': None,
'logging_runlevel': None,
'tor_path': 'tor',
- 'run_targets': [Target.RUN_OPEN],
+ 'run_targets': [test.Target.RUN_OPEN],
'attribute_targets': [],
'quiet': False,
'verbose': False,
@@ -75,7 +74,7 @@ def parse(argv):
run_targets, attribute_targets = [], []
integ_targets = arg.split(',')
- all_run_targets = [t for t in Target if CONFIG['target.torrc'].get(t) is not None]
+ all_run_targets = [t for t in test.Target if CONFIG['target.torrc'].get(t) is not None]
# validates the targets and split them into run and attribute targets
@@ -83,7 +82,7 @@ def parse(argv):
raise ValueError('No targets provided')
for target in integ_targets:
- if target not in Target:
+ if target not in test.Target:
raise ValueError('Invalid integration target: %s' % target)
elif target in all_run_targets:
run_targets.append(target)
@@ -92,8 +91,8 @@ def parse(argv):
# check if we were told to use all run targets
- if Target.RUN_ALL in attribute_targets:
- attribute_targets.remove(Target.RUN_ALL)
+ if test.Target.RUN_ALL in attribute_targets:
+ attribute_targets.remove(test.Target.RUN_ALL)
run_targets = all_run_targets
# if no RUN_* targets are provided then keep the default (otherwise we
@@ -138,10 +137,10 @@ def get_help():
help_msg = CONFIG['msg.help']
# gets the longest target length so we can show the entries in columns
- target_name_length = max(map(len, Target))
+ target_name_length = max(map(len, test.Target))
description_format = '\n %%-%is - %%s' % target_name_length
- for target in Target:
+ for target in test.Target:
help_msg += description_format % (target, CONFIG['target.description'].get(target, ''))
help_msg += '\n'
diff --git a/test/integ/connection/authentication.py b/test/integ/connection/authentication.py
index f43a61d..3a2fcb0 100644
--- a/test/integ/connection/authentication.py
+++ b/test/integ/connection/authentication.py
@@ -9,11 +9,10 @@ import unittest
import stem.connection
import stem.socket
import stem.version
+import test
import test.require
import test.runner
-from test.util import tor_version
-
# Responses given by tor for various authentication failures. These may change
# in the future and if they do then this test should be updated.
@@ -44,7 +43,7 @@ def _can_authenticate(auth_type):
tor_options = runner.get_options()
password_auth = test.runner.Torrc.PASSWORD in tor_options
cookie_auth = test.runner.Torrc.COOKIE in tor_options
- safecookie_auth = cookie_auth and tor_version() >= stem.version.Requirement.AUTH_SAFECOOKIE
+ safecookie_auth = cookie_auth and test.tor_version() >= stem.version.Requirement.AUTH_SAFECOOKIE
if not password_auth and not cookie_auth:
# open socket, anything but safecookie will work
@@ -104,7 +103,7 @@ class TestAuthenticate(unittest.TestCase):
def setUp(self):
self.cookie_auth_methods = [stem.connection.AuthMethod.COOKIE]
- if tor_version() >= stem.version.Requirement.AUTH_SAFECOOKIE:
+ if test.tor_version() >= stem.version.Requirement.AUTH_SAFECOOKIE:
self.cookie_auth_methods.append(stem.connection.AuthMethod.SAFECOOKIE)
@test.require.controller
diff --git a/test/integ/control/controller.py b/test/integ/control/controller.py
index 2125242..1e4e8e8 100644
--- a/test/integ/control/controller.py
+++ b/test/integ/control/controller.py
@@ -18,6 +18,7 @@ import stem.response.protocolinfo
import stem.socket
import stem.util.str_tools
import stem.version
+import test
import test.network
import test.require
import test.runner
@@ -27,8 +28,6 @@ from stem.control import EventType, Listener, State
from stem.exit_policy import ExitPolicy
from stem.version import Requirement
-from test.util import register_new_capability, tor_version
-
# Router status entry for a relay with a nickname other than 'Unnamed'. This is
# used for a few tests that need to look up a relay.
@@ -47,17 +46,17 @@ class TestController(unittest.TestCase):
with test.runner.get_runner().get_tor_controller() as controller:
for event in controller.get_info('events/names').split():
if event not in EventType:
- register_new_capability('Event', event)
+ test.register_new_capability('Event', event)
for signal in controller.get_info('signal/names').split():
if signal not in Signal:
- register_new_capability('Signal', signal)
+ test.register_new_capability('Signal', signal)
# new features should simply be added to enable_feature()'s docs
for feature in controller.get_info('features/names').split():
if feature not in ('EXTENDED_EVENTS', 'VERBOSE_NAMES'):
- register_new_capability('Feature', feature)
+ test.register_new_capability('Feature', feature)
def test_from_port(self):
"""
@@ -266,7 +265,7 @@ class TestController(unittest.TestCase):
with runner.get_tor_controller() as controller:
version = controller.get_version()
self.assertTrue(isinstance(version, stem.version.Version))
- self.assertEqual(version, tor_version())
+ self.assertEqual(version, test.tor_version())
@test.require.controller
def test_get_exit_policy(self):
@@ -342,7 +341,7 @@ class TestController(unittest.TestCase):
if test.runner.Torrc.COOKIE in tor_options:
auth_methods.append(stem.response.protocolinfo.AuthMethod.COOKIE)
- if tor_version() >= stem.version.Requirement.AUTH_SAFECOOKIE:
+ if test.tor_version() >= stem.version.Requirement.AUTH_SAFECOOKIE:
auth_methods.append(stem.response.protocolinfo.AuthMethod.SAFECOOKIE)
if test.runner.Torrc.PASSWORD in tor_options:
@@ -1139,7 +1138,7 @@ class TestController(unittest.TestCase):
runner = test.runner.get_runner()
- if tor_version() >= Requirement.MICRODESCRIPTOR_IS_DEFAULT:
+ if test.tor_version() >= Requirement.MICRODESCRIPTOR_IS_DEFAULT:
self.skipTest('(requires server descriptors)')
return
@@ -1169,7 +1168,7 @@ class TestController(unittest.TestCase):
runner = test.runner.get_runner()
- if tor_version() >= Requirement.MICRODESCRIPTOR_IS_DEFAULT:
+ if test.tor_version() >= Requirement.MICRODESCRIPTOR_IS_DEFAULT:
self.skipTest('(requires server descriptors)')
return
@@ -1229,7 +1228,7 @@ class TestController(unittest.TestCase):
self.assertTrue(desc.nickname is not None)
for line in desc.get_unrecognized_lines():
- register_new_capability('Consensus Line', line)
+ test.register_new_capability('Consensus Line', line)
count += 1
if count > 10:
diff --git a/test/integ/descriptor/extrainfo_descriptor.py b/test/integ/descriptor/extrainfo_descriptor.py
index 205b917..eada1d7 100644
--- a/test/integ/descriptor/extrainfo_descriptor.py
+++ b/test/integ/descriptor/extrainfo_descriptor.py
@@ -6,11 +6,10 @@ import os
import unittest
import stem.descriptor
+import test
import test.require
import test.runner
-from test.util import register_new_capability
-
class TestExtraInfoDescriptor(unittest.TestCase):
@test.require.only_run_once
@@ -30,7 +29,7 @@ class TestExtraInfoDescriptor(unittest.TestCase):
with open(descriptor_path, 'rb') as descriptor_file:
for desc in stem.descriptor.parse_file(descriptor_file, 'extra-info 1.0', validate = True):
for line in desc.get_unrecognized_lines():
- register_new_capability('Extra-info Line', line)
+ test.register_new_capability('Extra-info Line', line)
if desc.dir_v2_responses_unknown:
self.fail('Unrecognized statuses on dirreq-v2-resp lines: %s' % desc.dir_v2_responses_unknown)
diff --git a/test/integ/descriptor/microdescriptor.py b/test/integ/descriptor/microdescriptor.py
index c6fa80e..a38917a 100644
--- a/test/integ/descriptor/microdescriptor.py
+++ b/test/integ/descriptor/microdescriptor.py
@@ -6,11 +6,10 @@ import os
import unittest
import stem.descriptor
+import test
import test.require
import test.runner
-from test.util import register_new_capability
-
class TestMicrodescriptor(unittest.TestCase):
@test.require.only_run_once
@@ -30,4 +29,4 @@ class TestMicrodescriptor(unittest.TestCase):
with open(descriptor_path, 'rb') as descriptor_file:
for desc in stem.descriptor.parse_file(descriptor_file, 'microdescriptor 1.0', validate = True):
for line in desc.get_unrecognized_lines():
- register_new_capability('Microdescriptor Line', line)
+ test.register_new_capability('Microdescriptor Line', line)
diff --git a/test/integ/descriptor/networkstatus.py b/test/integ/descriptor/networkstatus.py
index 96fec77..83383fd 100644
--- a/test/integ/descriptor/networkstatus.py
+++ b/test/integ/descriptor/networkstatus.py
@@ -9,11 +9,10 @@ import stem
import stem.descriptor
import stem.descriptor.remote
import stem.version
+import test
import test.require
import test.runner
-from test.util import register_new_capability
-
class TestNetworkStatus(unittest.TestCase):
@test.require.only_run_once
@@ -53,11 +52,11 @@ class TestNetworkStatus(unittest.TestCase):
for flag in router.flags:
if flag not in stem.Flag and flag not in reported_flags:
- register_new_capability('Flag', flag)
+ test.register_new_capability('Flag', flag)
reported_flags.append(flag)
for line in router.get_unrecognized_lines():
- register_new_capability('Consensus Line', line, suppression_token = line.split()[0])
+ test.register_new_capability('Consensus Line', line, suppression_token = line.split()[0])
# Sanity test that there's at least a hundred relays. If that's not the
# case then this probably isn't a real, complete tor consensus.
@@ -87,10 +86,10 @@ class TestNetworkStatus(unittest.TestCase):
for flag in router.flags:
if flag not in stem.Flag:
- register_new_capability('Flag (microdescriptor)', flag)
+ test.register_new_capability('Flag (microdescriptor)', flag)
reported_flags.append(flag)
for line in router.get_unrecognized_lines():
- register_new_capability('Microdescriptor Consensus Line', line, suppression_token = line.split()[0])
+ test.register_new_capability('Microdescriptor Consensus Line', line, suppression_token = line.split()[0])
self.assertTrue(count > 100)
diff --git a/test/integ/descriptor/server_descriptor.py b/test/integ/descriptor/server_descriptor.py
index 2a3d897..7a234e3 100644
--- a/test/integ/descriptor/server_descriptor.py
+++ b/test/integ/descriptor/server_descriptor.py
@@ -6,11 +6,10 @@ import os
import unittest
import stem.descriptor
+import test
import test.require
import test.runner
-from test.util import register_new_capability
-
class TestServerDescriptor(unittest.TestCase):
@test.require.only_run_once
@@ -36,4 +35,4 @@ class TestServerDescriptor(unittest.TestCase):
self.assertEqual(None, desc.socks_port)
for line in desc.get_unrecognized_lines():
- register_new_capability('Server Descriptor Line', line)
+ test.register_new_capability('Server Descriptor Line', line)
diff --git a/test/integ/installation.py b/test/integ/installation.py
index 3f37df3..1cb9471 100644
--- a/test/integ/installation.py
+++ b/test/integ/installation.py
@@ -12,13 +12,13 @@ import unittest
import stem
import stem.util.system
+import test
import test.require
-import test.util
INSTALL_MISMATCH_MSG = "Running 'python setup.py sdist' doesn't match our git contents in the following way. The manifest in our setup.py may need to be updated...\n\n"
BASE_INSTALL_PATH = '/tmp/stem_test'
-DIST_PATH = os.path.join(test.util.STEM_BASE, 'dist')
+DIST_PATH = os.path.join(test.STEM_BASE, 'dist')
SETUP_THREAD, INSTALL_FAILURE, INSTALL_PATH, SDIST_FAILURE = None, None, None, None
@@ -35,10 +35,10 @@ def setup():
original_cwd = os.getcwd()
try:
- os.chdir(test.util.STEM_BASE)
+ os.chdir(test.STEM_BASE)
try:
- os.chdir(test.util.STEM_BASE)
+ os.chdir(test.STEM_BASE)
stem.util.system.call('%s setup.py install --prefix %s' % (sys.executable, BASE_INSTALL_PATH), timeout = 60)
stem.util.system.call('%s setup.py clean --all' % sys.executable, timeout = 60) # tidy up the build directory
site_packages_paths = glob.glob('%s/lib*/*/site-packages' % BASE_INSTALL_PATH)
@@ -86,12 +86,12 @@ def _assert_has_all_files(path):
expected, installed = set(), set()
- for root, dirnames, filenames in os.walk(os.path.join(test.util.STEM_BASE, 'stem')):
+ for root, dirnames, filenames in os.walk(os.path.join(test.STEM_BASE, 'stem')):
for filename in filenames:
file_format = filename.split('.')[-1]
- if file_format not in test.util.IGNORED_FILE_TYPES:
- expected.add(os.path.join(root, filename)[len(test.util.STEM_BASE) + 1:])
+ if file_format not in test.IGNORED_FILE_TYPES:
+ expected.add(os.path.join(root, filename)[len(test.STEM_BASE) + 1:])
for root, dirnames, filenames in os.walk(path):
for filename in filenames:
diff --git a/test/integ/interpreter.py b/test/integ/interpreter.py
index 42dd01a..5cef051 100644
--- a/test/integ/interpreter.py
+++ b/test/integ/interpreter.py
@@ -7,11 +7,11 @@ import tempfile
import unittest
import stem.util.system
+import test
import test.require
import test.runner
-import test.util
-PROMPT_CMD = os.path.join(test.util.STEM_BASE, 'tor-prompt')
+PROMPT_CMD = os.path.join(test.STEM_BASE, 'tor-prompt')
def _run_prompt(*args):
@@ -44,7 +44,7 @@ class TestInterpreter(unittest.TestCase):
'250-config-file=%s' % test.runner.get_runner().get_torrc_path(),
'250 OK',
'',
- '250-version=%s' % test.util.tor_version(),
+ '250-version=%s' % test.tor_version(),
'250 OK',
]
diff --git a/test/integ/manual.py b/test/integ/manual.py
index 5c73914..846b1b6 100644
--- a/test/integ/manual.py
+++ b/test/integ/manual.py
@@ -10,6 +10,7 @@ import unittest
import stem.manual
import stem.util.system
+import test
import test.runner
from stem.manual import Category
@@ -96,7 +97,7 @@ class TestManual(unittest.TestCase):
if stem.util.system.is_windows():
self.skip_reason = '(unavailable on windows)'
- elif test.runner.Target.ONLINE not in test.runner.get_runner().attribute_targets:
+ elif test.Target.ONLINE not in test.runner.get_runner().attribute_targets:
self.skip_reason = '(requires online target)'
elif not stem.util.system.is_available('a2x'):
self.skip_reason = '(requires asciidoc)'
diff --git a/test/integ/response/protocolinfo.py b/test/integ/response/protocolinfo.py
index 1a00671..5d8c74f 100644
--- a/test/integ/response/protocolinfo.py
+++ b/test/integ/response/protocolinfo.py
@@ -9,12 +9,11 @@ import stem.connection
import stem.socket
import stem.util.system
import stem.version
+import test
+import test.integ.util.system
import test.require
import test.runner
-from test.integ.util.system import filter_system_call
-from test.util import tor_version
-
try:
# added in python 3.3
from unittest.mock import Mock, patch
@@ -76,7 +75,7 @@ class TestProtocolInfo(unittest.TestCase):
control_socket = stem.socket.ControlSocketFile(test.runner.CONTROL_SOCKET_PATH)
- call_replacement = filter_system_call(lookup_prefixes)
+ call_replacement = test.integ.util.system.filter_system_call(lookup_prefixes)
with patch('stem.util.system.call') as call_mock:
call_mock.side_effect = call_replacement
@@ -132,7 +131,7 @@ class TestProtocolInfo(unittest.TestCase):
if test.runner.Torrc.COOKIE in tor_options:
auth_methods.append(stem.response.protocolinfo.AuthMethod.COOKIE)
- if tor_version() >= stem.version.Requirement.AUTH_SAFECOOKIE:
+ if test.tor_version() >= stem.version.Requirement.AUTH_SAFECOOKIE:
auth_methods.append(stem.response.protocolinfo.AuthMethod.SAFECOOKIE)
chroot_path = runner.get_chroot()
diff --git a/test/integ/socket/control_socket.py b/test/integ/socket/control_socket.py
index 8e2658a..f479892 100644
--- a/test/integ/socket/control_socket.py
+++ b/test/integ/socket/control_socket.py
@@ -14,11 +14,10 @@ import unittest
import stem.connection
import stem.control
import stem.socket
+import test
import test.require
import test.runner
-from test.util import tor_version
-
class TestControlSocket(unittest.TestCase):
@test.require.controller
@@ -69,7 +68,7 @@ class TestControlSocket(unittest.TestCase):
for _ in range(100):
response = control_socket.recv()
- self.assertTrue(str(response).startswith('version=%s' % tor_version()))
+ self.assertTrue(str(response).startswith('version=%s' % test.tor_version()))
self.assertTrue(str(response).endswith('\nOK'))
@test.require.controller
diff --git a/test/require.py b/test/require.py
index a0735d8..774e5f4 100644
--- a/test/require.py
+++ b/test/require.py
@@ -24,8 +24,8 @@ run.
import stem.util.system
import stem.version
+import test
import test.runner
-import test.util
RAN_TESTS = []
@@ -72,12 +72,12 @@ def _can_ptrace():
# If we're running a tor version where ptrace is disabled and we didn't
# set 'DisableDebuggerAttachment=1' then we can infer that it's disabled.
- has_option = test.util.tor_version() >= stem.version.Requirement.TORRC_DISABLE_DEBUGGER_ATTACHMENT
+ has_option = test.tor_version() >= stem.version.Requirement.TORRC_DISABLE_DEBUGGER_ATTACHMENT
return not has_option or test.runner.Torrc.PTRACE in test.runner.get_runner().get_options()
def _is_online():
- return test.util.Target.ONLINE in test.runner.get_runner().attribute_targets
+ return test.Target.ONLINE in test.runner.get_runner().attribute_targets
def command(cmd):
@@ -95,7 +95,7 @@ def version(req_version):
:param stem.version.Version req_version: required tor version for the test
"""
- return needs(lambda: test.util.tor_version() >= req_version, 'requires %s' % req_version)
+ return needs(lambda: test.tor_version() >= req_version, 'requires %s' % req_version)
cryptography = needs(stem.prereq.is_crypto_available, 'requires cryptography')
diff --git a/test/runner.py b/test/runner.py
index 0f5a1d0..5686b4c 100644
--- a/test/runner.py
+++ b/test/runner.py
@@ -47,9 +47,9 @@ import stem.process
import stem.socket
import stem.util.conf
import stem.util.enum
+import test
from test.output import println, STATUS, ERROR, SUBSTATUS, NO_NL
-from test.util import Target, STEM_BASE
CONFIG = stem.util.conf.config_dict('test', {
'integ.test_directory': './test/data',
@@ -192,13 +192,13 @@ class Runner(object):
config_test_dir = CONFIG['integ.test_directory']
if config_test_dir:
- self._test_dir = stem.util.system.expand_path(config_test_dir, STEM_BASE)
+ self._test_dir = stem.util.system.expand_path(config_test_dir, test.STEM_BASE)
else:
self._test_dir = tempfile.mktemp('-stem-integ')
original_cwd, data_dir_path = os.getcwd(), self._test_dir
- if Target.RELATIVE in self.attribute_targets:
+ if test.Target.RELATIVE in self.attribute_targets:
tor_cwd = os.path.dirname(self._test_dir)
if not os.path.exists(tor_cwd):
@@ -222,7 +222,7 @@ class Runner(object):
# strip the testing directory from recv_message responses if we're
# simulating a chroot setup
- if Target.CHROOT in self.attribute_targets and not self._original_recv_message:
+ if test.Target.CHROOT in self.attribute_targets and not self._original_recv_message:
# TODO: when we have a function for telling stem the chroot we'll
# need to set that too
@@ -235,7 +235,7 @@ class Runner(object):
stem.socket.recv_message = _chroot_recv_message
# revert our cwd back to normal
- if Target.RELATIVE in self.attribute_targets:
+ if test.Target.RELATIVE in self.attribute_targets:
os.chdir(original_cwd)
except OSError as exc:
raise exc
@@ -523,7 +523,7 @@ class Runner(object):
logging_path = CONFIG['integ.log']
if logging_path:
- logging_path = stem.util.system.expand_path(logging_path, STEM_BASE)
+ logging_path = stem.util.system.expand_path(logging_path, test.STEM_BASE)
println(' configuring logger (%s)... ' % logging_path, STATUS, NO_NL)
# delete the old log
@@ -578,7 +578,7 @@ class Runner(object):
self._tor_process = stem.process.launch_tor(
tor_cmd = tor_cmd,
torrc_path = os.path.join(self._test_dir, 'torrc'),
- completion_percent = 100 if Target.ONLINE in self.attribute_targets else 5,
+ completion_percent = 100 if test.Target.ONLINE in self.attribute_targets else 5,
init_msg_handler = lambda line: println(' %s' % line, SUBSTATUS),
take_ownership = True,
)
diff --git a/test/settings.cfg b/test/settings.cfg
index 2b5fafc..b65ee37 100644
--- a/test/settings.cfg
+++ b/test/settings.cfg
@@ -135,7 +135,6 @@ pycodestyle.ignore stem/descriptor/__init__.py => E402: import stem.descriptor.n
pycodestyle.ignore stem/descriptor/__init__.py => E402: import stem.descriptor.microdescriptor
pycodestyle.ignore stem/descriptor/__init__.py => E402: import stem.descriptor.tordnsel
pycodestyle.ignore stem/descriptor/__init__.py => E402: import stem.descriptor.hidden_service_descriptor
-pycodestyle.ignore test/util.py => E402: import test.runner
# False positives from pyflakes. These are mappings between the path and the
# issue.
@@ -163,7 +162,7 @@ pyflakes.ignore stem/util/test_tools.py => 'pyflakes' imported but unused
pyflakes.ignore stem/util/test_tools.py => 'pycodestyle' imported but unused
pyflakes.ignore test/unit/response/events.py => 'from stem import *' used; unable to detect undefined names
pyflakes.ignore test/unit/response/events.py => *may be undefined, or defined from star imports: stem
-pyflakes.ignore test/util.py => undefined name 'test'
+pyflakes.ignore test/__init__.py => undefined name 'test'
# Test modules we want to run. Modules are roughly ordered by the dependencies
# so the lowest level tests come first. This is because a problem in say,
diff --git a/test/task.py b/test/task.py
index b2c8ba8..1089cba 100644
--- a/test/task.py
+++ b/test/task.py
@@ -32,9 +32,8 @@ import stem.util.conf
import stem.util.system
import stem.util.test_tools
import stem.version
-
+import test
import test.output
-import test.util
from test.output import STATUS, ERROR, NO_NL, println
@@ -44,7 +43,7 @@ CONFIG = stem.util.conf.config_dict('test', {
'test.integ_tests': '',
})
-SRC_PATHS = [os.path.join(test.util.STEM_BASE, path) for path in (
+SRC_PATHS = [os.path.join(test.STEM_BASE, path) for path in (
'stem',
'test',
'run_tests.py',
@@ -58,7 +57,7 @@ SRC_PATHS = [os.path.join(test.util.STEM_BASE, path) for path in (
def _check_tor_version(tor_path):
- return str(test.util.tor_version(tor_path)).split()[0]
+ return str(test.tor_version(tor_path)).split()[0]
def _clean_orphaned_pyc(paths):
@@ -98,7 +97,7 @@ def _check_for_unused_tests(paths):
if test_match:
class_name = test_match.groups()[0]
- module_name = py_path.replace(os.path.sep, '.')[len(test.util.STEM_BASE) + 1:-3] + '.' + class_name
+ module_name = py_path.replace(os.path.sep, '.')[len(test.STEM_BASE) + 1:-3] + '.' + class_name
if not (module_name in CONFIG['test.unit_tests'] or module_name in CONFIG['test.integ_tests']):
unused_tests.append(module_name)
@@ -109,7 +108,7 @@ def _check_for_unused_tests(paths):
def run(category, *tasks):
"""
- Runs a series of :class:`test.util.Task` instances. This simply prints 'done'
+ Runs a series of :class:`test.Task` instances. This simply prints 'done'
or 'failed' for each unless we fail one that is marked as being required. If
that happens then we print its error message and call sys.exit().
@@ -215,8 +214,8 @@ PYCODESTYLE_VERSION = ModuleVersion('checking pycodestyle version', ['pycodestyl
CLEAN_PYC = Task('checking for orphaned .pyc files', _clean_orphaned_pyc, (SRC_PATHS,))
UNUSED_TESTS = Task('checking for unused tests', _check_for_unused_tests, [(
- os.path.join(test.util.STEM_BASE, 'test', 'unit'),
- os.path.join(test.util.STEM_BASE, 'test', 'integ'),
+ os.path.join(test.STEM_BASE, 'test', 'unit'),
+ os.path.join(test.STEM_BASE, 'test', 'integ'),
)])
PYFLAKES_TASK = Task(
diff --git a/test/unit/__init__.py b/test/unit/__init__.py
index 94cd059..6cdbe98 100644
--- a/test/unit/__init__.py
+++ b/test/unit/__init__.py
@@ -3,7 +3,7 @@ Unit tests for the stem library.
"""
import os
-import test.util
+import test
__all__ = [
'connection',
@@ -17,7 +17,7 @@ __all__ = [
def exec_documentation_example(filename):
- path = os.path.join(test.util.STEM_BASE, 'docs', '_static', 'example', filename)
+ path = os.path.join(test.STEM_BASE, 'docs', '_static', 'example', filename)
with open(path) as f:
code = compile(f.read(), path, 'exec')
diff --git a/test/unit/connection/authentication.py b/test/unit/connection/authentication.py
index b50f97b..117b39d 100644
--- a/test/unit/connection/authentication.py
+++ b/test/unit/connection/authentication.py
@@ -12,7 +12,7 @@ various error conditions, and make sure that the right exception is raised.
import unittest
import stem.connection
-import test.util
+import test
from stem.response import ControlMessage
from stem.util import log
@@ -86,7 +86,7 @@ class TestAuthenticate(unittest.TestCase):
stem.connection.AuthChallengeFailed(None, None),
stem.ControllerError(None))
- auth_method_combinations = test.util.get_all_combinations([
+ auth_method_combinations = test.get_all_combinations([
stem.connection.AuthMethod.NONE,
stem.connection.AuthMethod.PASSWORD,
stem.connection.AuthMethod.COOKIE,
diff --git a/test/unit/doctest.py b/test/unit/doctest.py
index 1240324..fb74d92 100644
--- a/test/unit/doctest.py
+++ b/test/unit/doctest.py
@@ -13,7 +13,7 @@ import stem.util.connection
import stem.util.str_tools
import stem.util.system
import stem.version
-import test.util
+import test
from stem.response import ControlMessage
@@ -37,7 +37,7 @@ ADD_ONION_RESPONSE = """\
class TestDocumentation(unittest.TestCase):
def test_examples(self):
- stem_dir = os.path.join(test.util.STEM_BASE, 'stem')
+ stem_dir = os.path.join(test.STEM_BASE, 'stem')
is_failed = False
for path in stem.util.system.files_with_suffix(stem_dir, '.py'):
diff --git a/test/unit/installation.py b/test/unit/installation.py
index 73881de..15d9fe8 100644
--- a/test/unit/installation.py
+++ b/test/unit/installation.py
@@ -3,7 +3,7 @@ import os
import re
import unittest
-import test.util
+import test
class TestInstallation(unittest.TestCase):
@@ -12,7 +12,7 @@ class TestInstallation(unittest.TestCase):
@classmethod
def setUpClass(self):
- setup_path = os.path.join(test.util.STEM_BASE, 'setup.py')
+ setup_path = os.path.join(test.STEM_BASE, 'setup.py')
self.skip_reason = None
self.setup_contents = False
@@ -32,13 +32,13 @@ class TestInstallation(unittest.TestCase):
# packages = ['stem', 'stem.descriptor', 'stem.util'],
modules = json.loads(re.search('packages = (\[.*\])', self.setup_contents).group(1).replace("'", '"'))
- module_paths = dict([(m, os.path.join(test.util.STEM_BASE, m.replace('.', os.path.sep))) for m in modules])
+ module_paths = dict([(m, os.path.join(test.STEM_BASE, m.replace('.', os.path.sep))) for m in modules])
for module, path in module_paths.items():
if not os.path.exists(path):
self.fail("setup.py's module %s doesn't exist at %s" % (module, path))
- for entry in os.walk(os.path.join(test.util.STEM_BASE, 'stem')):
+ for entry in os.walk(os.path.join(test.STEM_BASE, 'stem')):
directory = entry[0]
if directory.endswith('__pycache__'):
@@ -72,13 +72,13 @@ class TestInstallation(unittest.TestCase):
for module, files in package_data.items():
for module_file in files:
- data_files.append(os.path.join(test.util.STEM_BASE, module.replace('.', os.path.sep), module_file))
+ data_files.append(os.path.join(test.STEM_BASE, module.replace('.', os.path.sep), module_file))
for path in data_files:
if not os.path.exists(path):
self.fail("setup.py installs a data file that doesn't exist: %s" % path)
- for entry in os.walk(os.path.join(test.util.STEM_BASE, 'stem')):
+ for entry in os.walk(os.path.join(test.STEM_BASE, 'stem')):
directory = entry[0]
if directory.endswith('__pycache__'):
@@ -88,7 +88,7 @@ class TestInstallation(unittest.TestCase):
path = os.path.join(directory, filename)
file_type = path.split('.')[-1]
- if file_type in (['py'] + test.util.IGNORED_FILE_TYPES):
+ if file_type in (['py'] + test.IGNORED_FILE_TYPES):
continue
elif path not in data_files:
self.fail("setup.py doesn't install %s" % path)
diff --git a/test/unit/util/proc.py b/test/unit/util/proc.py
index 00f2af0..b4e3aab 100644
--- a/test/unit/util/proc.py
+++ b/test/unit/util/proc.py
@@ -6,7 +6,7 @@ import io
import re
import unittest
-import test.util
+import test
from stem.util import proc
from stem.util.connection import Connection
@@ -106,7 +106,7 @@ class TestProc(unittest.TestCase):
"""
# list of all combinations of args with respective return values
- stat_combinations = test.util.get_all_combinations([
+ stat_combinations = test.get_all_combinations([
('command', 'test_program'),
('utime', '0.13'),
('stime', '0.14'),
diff --git a/test/util.py b/test/util.py
deleted file mode 100644
index 3decb89..0000000
--- a/test/util.py
+++ /dev/null
@@ -1,146 +0,0 @@
-# Copyright 2012-2017, Damian Johnson and The Tor Project
-# See LICENSE for licensing information
-
-"""
-Helper functions for our test framework.
-
-::
-
- get_all_combinations - provides all combinations of attributes
- tor_version - provides the version of tor we're testing against
-"""
-
-import itertools
-import os
-
-import stem
-import stem.util.enum
-import stem.version
-
-# Integration targets fall into two categories:
-#
-# * Run Targets (like RUN_COOKIE and RUN_PTRACE) which customize our torrc.
-# We do an integration test run for each run target we get.
-#
-# * Attribute Target (like CHROOT and ONLINE) which indicates
-# non-configuration changes to your test runs. These are applied to all
-# integration runs that we perform.
-
-Target = stem.util.enum.UppercaseEnum(
- 'ONLINE',
- 'RELATIVE',
- 'CHROOT',
- 'RUN_NONE',
- 'RUN_OPEN',
- 'RUN_PASSWORD',
- 'RUN_COOKIE',
- 'RUN_MULTIPLE',
- 'RUN_SOCKET',
- 'RUN_SCOOKIE',
- 'RUN_PTRACE',
- 'RUN_ALL',
-)
-
-TOR_VERSION = None
-
-# We make some paths relative to stem's base directory (the one above us)
-# rather than the process' cwd. This doesn't end with a slash.
-
-STEM_BASE = os.path.sep.join(__file__.split(os.path.sep)[:-2])
-
-# Store new capabilities (events, descriptor entries, etc.)
-
-NEW_CAPABILITIES = []
-NEW_CAPABILITIES_SUPPRESSION_TOKENS = set()
-
-# File extensions of contents that should be ignored.
-
-IGNORED_FILE_TYPES = []
-
-with open(os.path.join(STEM_BASE, '.gitignore')) as ignore_file:
- for line in ignore_file:
- if line.startswith('*.'):
- IGNORED_FILE_TYPES.append(line[2:].strip())
-
-
-def get_new_capabilities():
- """
- Provides a list of capabilities tor supports but stem doesn't, as discovered
- while running our tests.
-
- :returns: **list** of (type, message) tuples for the capabilities
- """
-
- return NEW_CAPABILITIES
-
-
-def register_new_capability(capability_type, msg, suppression_token = None):
- """
- Register new capability found during the tests.
-
- :param str capability_type: type of capability this is
- :param str msg: description of what we found
- :param str suppression_token: skip registration if this token's already been
- provided
- """
-
- if suppression_token not in NEW_CAPABILITIES_SUPPRESSION_TOKENS:
- NEW_CAPABILITIES.append((capability_type, msg))
-
- if suppression_token:
- NEW_CAPABILITIES_SUPPRESSION_TOKENS.add(suppression_token)
-
-
-def get_all_combinations(attr, include_empty = False):
- """
- Provides an iterator for all combinations of a set of attributes. For
- instance...
-
- ::
-
- >>> list(test.util.get_all_combinations(['a', 'b', 'c']))
- [('a',), ('b',), ('c',), ('a', 'b'), ('a', 'c'), ('b', 'c'), ('a', 'b', 'c')]
-
- :param list attr: attributes to provide combinations for
- :param bool include_empty: includes an entry with zero items if True
- :returns: iterator for all combinations
- """
-
- # Makes an itertools.product() call for 'i' copies of attr...
- #
- # * itertools.product(attr) => all one-element combinations
- # * itertools.product(attr, attr) => all two-element combinations
- # * ... etc
-
- if include_empty:
- yield ()
-
- seen = set()
- for index in range(1, len(attr) + 1):
- product_arg = [attr for _ in range(index)]
-
- for item in itertools.product(*product_arg):
- # deduplicate, sort, and only provide if we haven't seen it yet
- item = tuple(sorted(set(item)))
-
- if item not in seen:
- seen.add(item)
- yield item
-
-
-def tor_version(tor_path = None):
- """
- Provides the version of tor we're testing against.
-
- :param str tor_path: location of tor executable to cehck the version of
-
- :returns: :class:`~stem.version.Version` of tor invoked by our integration
- tests
- """
-
- global TOR_VERSION
-
- if TOR_VERSION is None or tor_path:
- TOR_VERSION = stem.version.get_system_tor_version(tor_path)
-
- return TOR_VERSION
1
0
commit 7ae6e853a9bfe8566b0e3d9d79e859854644f61d
Merge: 157d9a8 2170254
Author: Damian Johnson <atagar(a)torproject.org>
Date: Sun May 21 19:32:37 2017 -0700
Replace test/util.py
Everything is miscellaneous. Moving or replacing the utilities this module
held.
run_tests.py | 165 ++++--
stem/response/__init__.py | 13 +-
test/__init__.py | 145 ++++-
test/arguments.py | 17 +-
test/integ/connection/authentication.py | 30 +-
test/integ/connection/connect.py | 9 +-
test/integ/control/base_controller.py | 23 +-
test/integ/control/controller.py | 178 +++---
test/integ/descriptor/extrainfo_descriptor.py | 11 +-
test/integ/descriptor/microdescriptor.py | 11 +-
test/integ/descriptor/networkstatus.py | 27 +-
test/integ/descriptor/remote.py | 46 +-
test/integ/descriptor/server_descriptor.py | 12 +-
test/integ/installation.py | 22 +-
test/integ/interpreter.py | 14 +-
test/integ/manual.py | 3 +-
test/integ/process.py | 37 +-
test/integ/response/protocolinfo.py | 18 +-
test/integ/socket/control_message.py | 23 +-
test/integ/socket/control_socket.py | 20 +-
test/integ/util/connection.py | 5 +-
test/integ/util/proc.py | 20 +-
test/integ/util/system.py | 64 +--
test/integ/version.py | 10 +-
test/require.py | 106 ++++
test/runner.py | 35 +-
test/settings.cfg | 3 +-
test/task.py | 237 ++++++++
test/unit/__init__.py | 4 +-
test/unit/connection/authentication.py | 15 +-
test/unit/control/controller.py | 8 +-
test/unit/descriptor/certificate.py | 8 +-
test/unit/descriptor/hidden_service_descriptor.py | 7 +-
test/unit/doctest.py | 8 +-
test/unit/installation.py | 14 +-
test/unit/interpreter/commands.py | 17 +-
test/unit/manual.py | 9 +-
test/unit/response/add_onion.py | 21 +-
test/unit/response/authchallenge.py | 7 +-
test/unit/response/events.py | 7 +-
test/unit/response/getconf.py | 25 +-
test/unit/response/getinfo.py | 27 +-
test/unit/response/mapaddress.py | 23 +-
test/unit/response/protocolinfo.py | 39 +-
test/unit/response/singleline.py | 23 +-
test/unit/tutorial_examples.py | 9 +-
test/unit/util/proc.py | 4 +-
test/util.py | 640 ----------------------
48 files changed, 984 insertions(+), 1235 deletions(-)
1
0