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
February 2015
- 15 participants
- 2121 discussions

[bridgedb/develop] Add skip coverage pragma to bridgedb.Main code for block files.
by isis@torproject.org 22 Feb '15
by isis@torproject.org 22 Feb '15
22 Feb '15
commit d8495e1ebf08c3aecfba4895598ca0ca7e3f7299
Author: Isis Lovecruft <isis(a)torproject.org>
Date: Sat Feb 21 22:47:21 2015 +0000
Add skip coverage pragma to bridgedb.Main code for block files.
---
lib/bridgedb/Main.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/lib/bridgedb/Main.py b/lib/bridgedb/Main.py
index 83b60a4..d274fcd 100644
--- a/lib/bridgedb/Main.py
+++ b/lib/bridgedb/Main.py
@@ -177,7 +177,7 @@ def load(state, splitter, clear=False):
# XXX TODO refactor the next block according with new parsers for OONI
# bridge-reachability reports:
- if state.COUNTRY_BLOCK_FILE:
+ if state.COUNTRY_BLOCK_FILE: # pragma: no cover
logging.info("Opening Blocking Countries file %s"
% state.COUNTRY_BLOCK_FILE)
f = open(state.COUNTRY_BLOCK_FILE)
1
0

[bridgedb/develop] Change Main.run() to take a reactor as a parameter.
by isis@torproject.org 22 Feb '15
by isis@torproject.org 22 Feb '15
22 Feb '15
commit 88310463af23b403d2a73b082b89508fb134b16e
Author: Isis Lovecruft <isis(a)torproject.org>
Date: Sat Feb 21 22:48:35 2015 +0000
Change Main.run() to take a reactor as a parameter.
This makes unittesting easier, as we can then pass mocked reactors with
less risk of touching the real one. (However, to pass mocked reactors,
we'd probably need to check the code for the EmailDistributor and
IPBasedDistributor in bridgedb.Dist to ensure that neither are touching
the reactor either.)
This also changes the main loop to only call reactor.run() if the
reactor is not already running.
---
lib/bridgedb/Main.py | 77 +++++++++++++++++++++++++++-----------------------
1 file changed, 42 insertions(+), 35 deletions(-)
diff --git a/lib/bridgedb/Main.py b/lib/bridgedb/Main.py
index d274fcd..4fb6338 100644
--- a/lib/bridgedb/Main.py
+++ b/lib/bridgedb/Main.py
@@ -300,7 +300,7 @@ def createBridgeRings(cfg, proxyList, key):
return splitter, emailDistributor, ipDistributor
-def run(options):
+def run(options, reactor=reactor):
"""This is BridgeDB's main entry point and main runtime loop.
Given the parsed commandline options, this function handles locating the
@@ -312,6 +312,11 @@ def run(options):
options given in the commandline we were called with.
:type state: :class:`bridgedb.persistent.State`
:ivar state: A persistent state object which holds config changes.
+ :param reactor: An implementer of
+ :api:`twisted.internet.interfaces.IReactorCore`. This parameter is
+ mainly for testing; the default
+ :api:`twisted.internet.epollreactor.EPollReactor` is fine for normal
+ application runs.
"""
# Change to the directory where we're supposed to run. This must be done
# before parsing the config file, otherwise there will need to be two
@@ -494,43 +499,45 @@ def run(options):
signal.signal(signal.SIGHUP, _handleSIGHUP)
signal.signal(signal.SIGUSR1, _handleSIGUSR1)
- # And actually load it to start parsing. Get back our distributors.
- emailDistributor, ipDistributor = reload(False)
-
- # Configure all servers:
- if config.HTTPS_DIST and config.HTTPS_SHARE:
- #webSchedule = schedule.ScheduledInterval("day", 2)
- webSchedule = schedule.Unscheduled()
- HTTPServer.addWebServer(config, ipDistributor, webSchedule)
- if config.EMAIL_DIST and config.EMAIL_SHARE:
- #emailSchedule = schedule.ScheduledInterval("day", 1)
- emailSchedule = schedule.Unscheduled()
- addSMTPServer(config, emailDistributor, emailSchedule)
-
- tasks = {}
-
- # Setup all our repeating tasks:
- if config.TASKS['GET_TOR_EXIT_LIST']:
- tasks['GET_TOR_EXIT_LIST'] = task.LoopingCall(
- proxy.downloadTorExits,
- proxyList,
- config.SERVER_PUBLIC_EXTERNAL_IP)
-
- # Schedule all configured repeating tasks:
- for name, seconds in config.TASKS.items():
- if seconds:
- try:
- tasks[name].start(abs(seconds))
- except KeyError:
- logging.info("Task %s is disabled and will not run." % name)
- else:
- logging.info("Scheduled task %s to run every %s seconds."
- % (name, seconds))
+ if reactor:
+ # And actually load it to start parsing. Get back our distributors.
+ emailDistributor, ipDistributor = reload(False)
+
+ # Configure all servers:
+ if config.HTTPS_DIST and config.HTTPS_SHARE:
+ #webSchedule = schedule.ScheduledInterval("day", 2)
+ webSchedule = schedule.Unscheduled()
+ HTTPServer.addWebServer(config, ipDistributor, webSchedule)
+ if config.EMAIL_DIST and config.EMAIL_SHARE:
+ #emailSchedule = schedule.ScheduledInterval("day", 1)
+ emailSchedule = schedule.Unscheduled()
+ addSMTPServer(config, emailDistributor, emailSchedule)
+
+ tasks = {}
+
+ # Setup all our repeating tasks:
+ if config.TASKS['GET_TOR_EXIT_LIST']:
+ tasks['GET_TOR_EXIT_LIST'] = task.LoopingCall(
+ proxy.downloadTorExits,
+ proxyList,
+ config.SERVER_PUBLIC_EXTERNAL_IP)
+
+ # Schedule all configured repeating tasks:
+ for name, seconds in config.TASKS.items():
+ if seconds:
+ try:
+ tasks[name].start(abs(seconds))
+ except KeyError:
+ logging.info("Task %s is disabled and will not run." % name)
+ else:
+ logging.info("Scheduled task %s to run every %s seconds."
+ % (name, seconds))
# Actually run the servers.
try:
- logging.info("Starting reactors.")
- reactor.run()
+ if reactor and not reactor.running:
+ logging.info("Starting reactors.")
+ reactor.run()
except KeyboardInterrupt:
logging.fatal("Received keyboard interrupt. Shutting down...")
finally:
1
0

[bridgedb/develop] PEP8 obsessive compulsive whitespace fix in bridgedb.Main.
by isis@torproject.org 22 Feb '15
by isis@torproject.org 22 Feb '15
22 Feb '15
commit 9686f057465eb83fb41367a0381266b0bb8cd52a
Author: Isis Lovecruft <isis(a)torproject.org>
Date: Sat Feb 21 22:51:56 2015 +0000
PEP8 obsessive compulsive whitespace fix in bridgedb.Main.
---
lib/bridgedb/Main.py | 1 -
1 file changed, 1 deletion(-)
diff --git a/lib/bridgedb/Main.py b/lib/bridgedb/Main.py
index 4fb6338..9317760 100644
--- a/lib/bridgedb/Main.py
+++ b/lib/bridgedb/Main.py
@@ -249,7 +249,6 @@ def createBridgeRings(cfg, proxyList, key):
:returns: A BridgeSplitter splitter, an IPBasedDistributor or None,
and an EmailBasedDistributor or None.
"""
-
# Create a BridgeSplitter to assign the bridges to the different
# distributors.
splitter = Bridges.BridgeSplitter(crypto.getHMAC(key, "Splitter-Key"))
1
0

[bridgedb/develop] Fix missing import of addOrUpdateBridgeHistory() in bridgedb.Main.
by isis@torproject.org 22 Feb '15
by isis@torproject.org 22 Feb '15
22 Feb '15
commit 70a90f3c65cb63a6839b75dadd6999b422bd56ec
Author: Isis Lovecruft <isis(a)torproject.org>
Date: Sat Feb 21 22:43:11 2015 +0000
Fix missing import of addOrUpdateBridgeHistory() in bridgedb.Main.
---
lib/bridgedb/Main.py | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/lib/bridgedb/Main.py b/lib/bridgedb/Main.py
index 7bc5cff..440784b 100644
--- a/lib/bridgedb/Main.py
+++ b/lib/bridgedb/Main.py
@@ -46,6 +46,8 @@ import bridgedb.Bridges as Bridges
import bridgedb.Dist as Dist
import bridgedb.Storage
+from bridgedb.Stability import addOrUpdateBridgeHistory
+
def updateBridgeHistory(bridges, timestamps):
"""Process all the timestamps and update the bridge stability statistics in
@@ -76,7 +78,7 @@ def updateBridgeHistory(bridges, timestamps):
("Adding/updating timestamps in BridgeHistory for %s in "
"database: %s") % (fingerprint, timestamp))
timestamp = toUnixSeconds(timestamp.timetuple())
- bridgedb.Stability.addOrUpdateBridgeHistory(bridge, timestamp)
+ addOrUpdateBridgeHistory(bridge, timestamp)
# Replace the timestamps so the next sort is (hopefully) less
# expensive:
sortedTimestamps[fingerprint] = stamps
1
0

[translation/torbutton-torbuttondtd] Update translations for torbutton-torbuttondtd
by translation@torproject.org 21 Feb '15
by translation@torproject.org 21 Feb '15
21 Feb '15
commit bc5fa41bafa225fba633663c4b0488a5f094679c
Author: Translation commit bot <translation(a)torproject.org>
Date: Sat Feb 21 22:15:52 2015 +0000
Update translations for torbutton-torbuttondtd
---
sq/torbutton.dtd | 34 +++++++++++++++++-----------------
1 file changed, 17 insertions(+), 17 deletions(-)
diff --git a/sq/torbutton.dtd b/sq/torbutton.dtd
index 74aaa79..ecf6a6d 100644
--- a/sq/torbutton.dtd
+++ b/sq/torbutton.dtd
@@ -24,29 +24,29 @@
<!ENTITY torbutton.pref_connection_more_info.text "Torbutton-i tani është i aktivizuar. Nëse dëshironi ta ndryshoni konfigurimin që s'lidhet me Tor-in, për proxy-n tuaj, ju lutemi paaftësoni Torbutton-in dhe kthehuni këtu. Nëse do dëshironit të ndryshoni konfigurimin e Tor-it tuaj, ju lutemi të përdorni dritaren e parapëlqimit për Torbutton-in.">
<!ENTITY torbutton.context_menu.new_identity "Identitet i Ri">
<!ENTITY torbutton.context_menu.new_identity_key "I">
-<!ENTITY torbutton.context_menu.new_circuit "New Tor Circuit for this Site">
+<!ENTITY torbutton.context_menu.new_circuit "Një Cirkuit i Ri Tor për këtë Webfaqe">
<!ENTITY torbutton.context_menu.new_circuit_key "C">
-<!ENTITY torbutton.context_menu.toggle "Toggle Tor status">
+<!ENTITY torbutton.context_menu.toggle "Alternoni statusin e Tor-it">
<!ENTITY torbutton.context_menu.toggle.key "T">
-<!ENTITY torbutton.context_menu.preferences "Privacy and Security Settings…">
+<!ENTITY torbutton.context_menu.preferences "Konfigurimi i Privatësisë dhe Sigurisë…">
<!ENTITY torbutton.context_menu.preferences.key "P">
-<!ENTITY torbutton.context_menu.about "About Torbutton...">
+<!ENTITY torbutton.context_menu.about "Rreth Torbutton-it...">
<!ENTITY torbutton.context_menu.about.key "A">
-<!ENTITY torbutton.context_menu.networksettings "Tor Network Settings…">
+<!ENTITY torbutton.context_menu.networksettings "Konfigurimi i Rrjetit Tor…">
<!ENTITY torbutton.context_menu.networksettings.key "S">
-<!ENTITY torbutton.context_menu.downloadUpdate "Check for Tor Browser Update…">
+<!ENTITY torbutton.context_menu.downloadUpdate "Kontrolloni për Përditësime të Shfletuesit Tor...">
<!ENTITY torbutton.context_menu.downloadUpdate.key "U">
-<!ENTITY torbutton.context_menu.cookieProtections "Cookie Protections…">
+<!ENTITY torbutton.context_menu.cookieProtections "Mbrojtjet nga Cookie-t…">
<!ENTITY torbutton.context_menu.cookieProtections.key "C">
-<!ENTITY torbutton.context_menu.copyTor "Copy Tor URL">
+<!ENTITY torbutton.context_menu.copyTor "Kopjojeni URL-në e Tor-it">
<!ENTITY torbutton.context_menu.copyTor.key "p">
-<!ENTITY torbutton.context_menu.openTorTab "Open Tor URL in new Tab">
+<!ENTITY torbutton.context_menu.openTorTab "Hapeni URL-në e Tor-it në një tabelë tjetër">
<!ENTITY torbutton.context_menu.openTorTab.key "r">
-<!ENTITY torbutton.context_menu.openTorWindow "Open Tor URL in new Window">
+<!ENTITY torbutton.context_menu.openTorWindow "Hapeni URL-në e Tor-it në një Dritare të re">
<!ENTITY torbutton.context_menu.openTorWindow.key "d">
<!ENTITY torbutton.button.label "Torbutton">
-<!ENTITY torbutton.button.tooltip "Click to initialize Torbutton">
-<!ENTITY torbutton.prefs.privacy_security_settings "Parametrat e Fshehtësisë dhe Sigurisë">
+<!ENTITY torbutton.button.tooltip "Klikoni që ta nisni Torbutton-in">
+<!ENTITY torbutton.prefs.privacy_security_settings "Konfigurimi i Privatësisë dhe Sigurisë">
<!ENTITY torbutton.prefs.block_thread "Block history reads during Tor (crucial)">
<!ENTITY torbutton.prefs.block_thwrite "Block history writes during Tor (recommended)">
<!ENTITY torbutton.prefs.block_nthread "Block history reads during Non-Tor (optional)">
@@ -65,8 +65,8 @@
<!ENTITY torbutton.prefs.set_uagent "Set user agent for Tor usage (crucial)">
<!ENTITY torbutton.prefs.dynamic "Dynamic Content">
<!ENTITY torbutton.prefs.cookies "Cookies">
-<!ENTITY torbutton.prefs.cache "Cache">
-<!ENTITY torbutton.prefs.history "History">
+<!ENTITY torbutton.prefs.cache "Depozitë">
+<!ENTITY torbutton.prefs.history "Histori">
<!ENTITY torbutton.prefs.no_search "Disable search suggestions during Tor (recommended)">
<!ENTITY torbutton.prefs.shutdown "Shutdown">
<!ENTITY torbutton.prefs.tor_shutdown "Clear Tor cookies during Tor-enabled browser shutdown">
@@ -80,11 +80,11 @@
<!ENTITY torbutton.prefs.smartspoof "Smart referer spoof during Tor usage (spoofs cross domain referers)">
<!ENTITY torbutton.prefs.nospoof "No referer spoof during Tor usage (sends referers as normal)">
<!ENTITY torbutton.prefs.disable_domstorage "Disable DOM Storage during Tor usage (crucial)">
-<!ENTITY torbutton.prefs.forms "Forms">
+<!ENTITY torbutton.prefs.forms "Format">
<!ENTITY torbutton.prefs.block_tforms "Block password+form saving during Tor (recommended)">
<!ENTITY torbutton.prefs.block_ntforms "Block password+form saving during Non-Tor (optional)">
<!ENTITY torbutton.prefs.tor "Tor">
-<!ENTITY torbutton.prefs.non_tor "Non-Tor">
+<!ENTITY torbutton.prefs.non_tor "Jo-Tor">
<!ENTITY torbutton.prefs.restore_tor "On session restored startup, set Tor state to:">
<!ENTITY torbutton.prefs.startup_tor "On browser startup, set Tor state to:">
<!ENTITY torbutton.prefs.reload_crashed_jar "Reload cookie jar/clear cookies on Firefox crash (recommended)">
@@ -157,4 +157,4 @@
<!ENTITY torbutton.prefs.sec_med_high "Mesatare-E lartë">
<!ENTITY torbutton.prefs.sec_high "E lartë">
<!ENTITY torbutton.prefs.sec_custom "Vlera personale">
-<!ENTITY torbutton.circuit_display.title "Tor circuit for this site">
+<!ENTITY torbutton.circuit_display.title "Cirkuiti i Tor-it për këtë webfaqe">
1
0
commit b8c5893617e825b5ff7eed4de9c245921fa60e97
Author: Damian Johnson <atagar(a)torproject.org>
Date: Sat Feb 21 13:21:32 2015 -0800
@require_controller decorator
Replacing our require_control() function with a decorator. Yay, nicer code!
---
test/integ/connection/authentication.py | 48 +++------
test/integ/connection/connect.py | 14 +--
test/integ/control/base_controller.py | 39 +++-----
test/integ/control/controller.py | 164 ++++++++++---------------------
test/integ/process.py | 6 +-
test/integ/response/protocolinfo.py | 17 +---
test/integ/socket/control_message.py | 27 ++---
test/integ/socket/control_socket.py | 30 ++----
test/integ/version.py | 10 +-
test/runner.py | 18 ++--
10 files changed, 126 insertions(+), 247 deletions(-)
diff --git a/test/integ/connection/authentication.py b/test/integ/connection/authentication.py
index 816e671..3687af3 100644
--- a/test/integ/connection/authentication.py
+++ b/test/integ/connection/authentication.py
@@ -11,6 +11,8 @@ import stem.socket
import stem.version
import test.runner
+from test.runner import require_controller
+
# Responses given by tor for various authentication failures. These may change
# in the future and if they do then this test should be updated.
@@ -105,40 +107,36 @@ class TestAuthenticate(unittest.TestCase):
if tor_version >= stem.version.Requirement.AUTH_SAFECOOKIE:
self.cookie_auth_methods.append(stem.connection.AuthMethod.SAFECOOKIE)
+ @require_controller
def test_authenticate_general_socket(self):
"""
Tests that the authenticate function can authenticate to our socket.
"""
- if test.runner.require_control(self):
- return
-
runner = test.runner.get_runner()
+
with runner.get_tor_socket(False) as control_socket:
stem.connection.authenticate(control_socket, test.runner.CONTROL_PASSWORD, runner.get_chroot())
test.runner.exercise_controller(self, control_socket)
+ @require_controller
def test_authenticate_general_controller(self):
"""
Tests that the authenticate function can authenticate via a Controller.
"""
- if test.runner.require_control(self):
- return
-
runner = test.runner.get_runner()
+
with runner.get_tor_controller(False) as controller:
stem.connection.authenticate(controller, test.runner.CONTROL_PASSWORD, runner.get_chroot())
test.runner.exercise_controller(self, controller)
+ @require_controller
def test_authenticate_general_example(self):
"""
Tests the authenticate function with something like its pydoc example.
"""
- if test.runner.require_control(self):
- return
-
runner = test.runner.get_runner()
tor_options = runner.get_options()
@@ -169,14 +167,12 @@ class TestAuthenticate(unittest.TestCase):
finally:
control_socket.close()
+ @require_controller
def test_authenticate_general_password(self):
"""
Tests the authenticate function's password argument.
"""
- if test.runner.require_control(self):
- return
-
# this is a much better test if we're just using password auth, since
# authenticate will work reguardless if there's something else to
# authenticate with
@@ -206,6 +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
def test_authenticate_general_cookie(self):
"""
Tests the authenticate function with only cookie authentication methods.
@@ -213,9 +210,6 @@ class TestAuthenticate(unittest.TestCase):
individually.
"""
- if test.runner.require_control(self):
- return
-
runner = test.runner.get_runner()
tor_options = runner.get_options()
is_cookie_only = test.runner.Torrc.COOKIE in tor_options and test.runner.Torrc.PASSWORD not in tor_options
@@ -233,14 +227,12 @@ 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
def test_authenticate_none(self):
"""
Tests the authenticate_none function.
"""
- if test.runner.require_control(self):
- return
-
auth_type = stem.connection.AuthMethod.NONE
if _can_authenticate(auth_type):
@@ -248,14 +240,12 @@ class TestAuthenticate(unittest.TestCase):
else:
self.assertRaises(stem.connection.OpenAuthRejected, self._check_auth, auth_type)
+ @require_controller
def test_authenticate_password(self):
"""
Tests the authenticate_password function.
"""
- if test.runner.require_control(self):
- return
-
auth_type = stem.connection.AuthMethod.PASSWORD
auth_value = test.runner.CONTROL_PASSWORD
@@ -278,14 +268,12 @@ class TestAuthenticate(unittest.TestCase):
self.assertRaises(exc_type, self._check_auth, auth_type, auth_value)
+ @require_controller
def test_authenticate_cookie(self):
"""
Tests the authenticate_cookie function.
"""
- if test.runner.require_control(self):
- return
-
auth_value = test.runner.get_runner().get_auth_cookie_path()
for auth_type in self.cookie_auth_methods:
@@ -302,15 +290,13 @@ class TestAuthenticate(unittest.TestCase):
else:
self.assertRaises(stem.connection.CookieAuthRejected, self._check_auth, auth_type, auth_value, False)
+ @require_controller
def test_authenticate_cookie_invalid(self):
"""
Tests the authenticate_cookie function with a properly sized but incorrect
value.
"""
- if test.runner.require_control(self):
- return
-
auth_value = test.runner.get_runner().get_test_dir('fake_cookie')
# we need to create a 32 byte cookie file to load from
@@ -341,19 +327,18 @@ class TestAuthenticate(unittest.TestCase):
os.remove(auth_value)
+ @require_controller
def test_authenticate_cookie_missing(self):
"""
Tests the authenticate_cookie function with a path that really, really
shouldn't exist.
"""
- if test.runner.require_control(self):
- return
-
for auth_type in self.cookie_auth_methods:
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
def test_authenticate_cookie_wrong_size(self):
"""
Tests the authenticate_cookie function with our torrc as an auth cookie.
@@ -361,9 +346,6 @@ class TestAuthenticate(unittest.TestCase):
socket.
"""
- if test.runner.require_control(self):
- return
-
auth_value = test.runner.get_runner().get_torrc_path(True)
for auth_type in self.cookie_auth_methods:
diff --git a/test/integ/connection/connect.py b/test/integ/connection/connect.py
index c1785fd..b50fdfc 100644
--- a/test/integ/connection/connect.py
+++ b/test/integ/connection/connect.py
@@ -13,6 +13,8 @@ except ImportError:
import stem.connection
import test.runner
+from test.runner import require_controller
+
class TestConnect(unittest.TestCase):
def setUp(self):
@@ -23,14 +25,12 @@ class TestConnect(unittest.TestCase):
def tearDown(self):
sys.stdout = self.original_stdout
+ @require_controller
def test_connect(self):
"""
Basic sanity checks for the connect function.
"""
- if test.runner.require_control(self):
- return
-
runner = test.runner.get_runner()
control_socket = stem.connection.connect(
@@ -42,14 +42,12 @@ class TestConnect(unittest.TestCase):
test.runner.exercise_controller(self, control_socket)
+ @require_controller
def test_connect_port(self):
"""
Basic sanity checks for the connect_port function.
"""
- if test.runner.require_control(self):
- return
-
runner = test.runner.get_runner()
control_socket = stem.connection.connect_port(
@@ -64,14 +62,12 @@ class TestConnect(unittest.TestCase):
else:
self.assertEqual(control_socket, None)
+ @require_controller
def test_connect_socket_file(self):
"""
Basic sanity checks for the connect_socket_file function.
"""
- if test.runner.require_control(self):
- return
-
runner = test.runner.get_runner()
control_socket = stem.connection.connect_socket_file(
diff --git a/test/integ/control/base_controller.py b/test/integ/control/base_controller.py
index 9f0e2aa..48dd3df 100644
--- a/test/integ/control/base_controller.py
+++ b/test/integ/control/base_controller.py
@@ -8,10 +8,13 @@ import time
import unittest
import stem.control
-import test.runner
import stem.socket
import stem.util.system
+import test.runner
+
+from test.runner import require_controller
+
class StateObserver(object):
"""
@@ -35,15 +38,14 @@ class StateObserver(object):
class TestBaseController(unittest.TestCase):
+ @require_controller
def test_connect_repeatedly(self):
"""
Connects and closes the socket repeatedly. This is a simple attempt to
trigger concurrency issues.
"""
- if test.runner.require_control(self):
- return
- elif stem.util.system.is_mac():
+ if stem.util.system.is_mac():
test.runner.skip(self, '(ticket #6235)')
return
@@ -54,53 +56,46 @@ class TestBaseController(unittest.TestCase):
controller.connect()
controller.close()
+ @require_controller
def test_msg(self):
"""
Tests a basic query with the msg() method.
"""
- if test.runner.require_control(self):
- return
-
with test.runner.get_runner().get_tor_socket() as control_socket:
controller = stem.control.BaseController(control_socket)
test.runner.exercise_controller(self, controller)
+ @require_controller
def test_msg_invalid(self):
"""
Tests the msg() method against an invalid controller command.
"""
- if test.runner.require_control(self):
- return
-
with test.runner.get_runner().get_tor_socket() as control_socket:
controller = stem.control.BaseController(control_socket)
response = controller.msg('invalid')
self.assertEqual('Unrecognized command "invalid"', str(response))
+ @require_controller
def test_msg_invalid_getinfo(self):
"""
Tests the msg() method against a non-existant GETINFO option.
"""
- if test.runner.require_control(self):
- return
-
with test.runner.get_runner().get_tor_socket() as control_socket:
controller = stem.control.BaseController(control_socket)
response = controller.msg('GETINFO blarg')
self.assertEqual('Unrecognized key "blarg"', str(response))
+ @require_controller
def test_msg_repeatedly(self):
"""
Connects, sends a burst of messages, and closes the socket repeatedly. This
is a simple attempt to trigger concurrency issues.
"""
- if test.runner.require_control(self):
- return
- elif stem.util.system.is_mac():
+ if stem.util.system.is_mac():
test.runner.skip(self, '(ticket #6235)')
return
@@ -131,6 +126,7 @@ class TestBaseController(unittest.TestCase):
for msg_thread in message_threads:
msg_thread.join()
+ @require_controller
def test_asynchronous_event_handling(self):
"""
Check that we can both receive asynchronous events while hammering our
@@ -138,9 +134,6 @@ class TestBaseController(unittest.TestCase):
listeners will still receive all of the enqueued events.
"""
- if test.runner.require_control(self):
- return
-
class ControlledListener(stem.control.BaseController):
"""
Controller that blocks event handling until told to do so.
@@ -189,29 +182,25 @@ class TestBaseController(unittest.TestCase):
self.assertTrue(re.match('650 BW [0-9]+ [0-9]+\r\n', bw_event.raw_content()))
self.assertEqual(('650', ' '), bw_event.content()[0][:2])
+ @require_controller
def test_get_latest_heartbeat(self):
"""
Basic check for get_latest_heartbeat().
"""
- if test.runner.require_control(self):
- return
-
# makes a getinfo query, then checks that the heartbeat is close to now
with test.runner.get_runner().get_tor_socket() as control_socket:
controller = stem.control.BaseController(control_socket)
controller.msg('GETINFO version')
self.assertTrue((time.time() - controller.get_latest_heartbeat()) < 5)
+ @require_controller
def test_status_notifications(self):
"""
Checks basic functionality of the add_status_listener() and
remove_status_listener() methods.
"""
- if test.runner.require_control(self):
- return
-
state_observer = StateObserver()
with test.runner.get_runner().get_tor_socket(False) as control_socket:
diff --git a/test/integ/control/controller.py b/test/integ/control/controller.py
index 4b2cbfc..632c002 100644
--- a/test/integ/control/controller.py
+++ b/test/integ/control/controller.py
@@ -26,6 +26,8 @@ from stem.control import EventType, Listener, State
from stem.exit_policy import ExitPolicy
from stem.version import Requirement
+from test.runner import require_controller
+
# 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.
@@ -42,9 +44,6 @@ class TestController(unittest.TestCase):
Basic sanity check for the from_port constructor.
"""
- if test.runner.require_control(self):
- return
-
if test.runner.Torrc.PORT in test.runner.get_runner().get_options():
with stem.control.Controller.from_port(port = test.runner.CONTROL_PORT) as controller:
self.assertTrue(isinstance(controller, stem.control.Controller))
@@ -56,23 +55,19 @@ class TestController(unittest.TestCase):
Basic sanity check for the from_socket_file constructor.
"""
- if test.runner.require_control(self):
- return
-
if test.runner.Torrc.SOCKET in test.runner.get_runner().get_options():
with stem.control.Controller.from_socket_file(path = test.runner.CONTROL_SOCKET_PATH) as controller:
self.assertTrue(isinstance(controller, stem.control.Controller))
else:
self.assertRaises(stem.SocketError, stem.control.Controller.from_socket_file, test.runner.CONTROL_SOCKET_PATH)
+ @require_controller
def test_reset_notification(self):
"""
Checks that a notificiation listener is... well, notified of SIGHUPs.
"""
- if test.runner.require_control(self):
- return
- elif test.runner.require_version(self, stem.version.Requirement.EVENT_SIGNAL):
+ if test.runner.require_version(self, stem.version.Requirement.EVENT_SIGNAL):
return
with test.runner.get_runner().get_tor_controller() as controller:
@@ -105,15 +100,13 @@ class TestController(unittest.TestCase):
controller.reset_conf('__OwningControllerProcess')
+ @require_controller
def test_event_handling(self):
"""
Add a couple listeners for various events and make sure that they receive
them. Then remove the listeners.
"""
- if test.runner.require_control(self):
- return
-
event_notice1, event_notice2 = threading.Event(), threading.Event()
event_buffer1, event_buffer2 = [], []
@@ -163,15 +156,13 @@ class TestController(unittest.TestCase):
self.assertTrue(hasattr(event, 'read'))
self.assertTrue(hasattr(event, 'written'))
+ @require_controller
def test_reattaching_listeners(self):
"""
Checks that event listeners are re-attached when a controller disconnects
then reconnects to tor.
"""
- if test.runner.require_control(self):
- return
-
event_notice = threading.Event()
event_buffer = []
@@ -243,14 +234,12 @@ class TestController(unittest.TestCase):
event_notice.wait(4)
self.assertTrue(len(event_buffer) >= 1)
+ @require_controller
def test_getinfo(self):
"""
Exercises GETINFO with valid and invalid queries.
"""
- if test.runner.require_control(self):
- return
-
runner = test.runner.get_runner()
with runner.get_tor_controller() as controller:
@@ -283,14 +272,12 @@ class TestController(unittest.TestCase):
self.assertEqual({}, controller.get_info([]))
self.assertEqual({}, controller.get_info([], {}))
+ @require_controller
def test_get_version(self):
"""
Test that the convenient method get_version() works.
"""
- if test.runner.require_control(self):
- return
-
runner = test.runner.get_runner()
with runner.get_tor_controller() as controller:
@@ -298,15 +285,13 @@ class TestController(unittest.TestCase):
self.assertTrue(isinstance(version, stem.version.Version))
self.assertEqual(version, runner.get_tor_version())
+ @require_controller
def test_get_exit_policy(self):
"""
Sanity test for get_exit_policy(). We have the default policy (no
ExitPolicy set) which is a little... long due to the boilerplate.
"""
- if test.runner.require_control(self):
- return
-
expected = ExitPolicy(
'reject 0.0.0.0/8:*',
'reject 169.254.0.0/16:*',
@@ -343,28 +328,24 @@ class TestController(unittest.TestCase):
policy_str = policy_str[:public_addr_start] + policy_str[public_addr_end:]
self.assertEqual(str(expected), policy_str)
+ @require_controller
def test_authenticate(self):
"""
Test that the convenient method authenticate() works.
"""
- if test.runner.require_control(self):
- return
-
runner = test.runner.get_runner()
with runner.get_tor_controller(False) as controller:
controller.authenticate(test.runner.CONTROL_PASSWORD)
test.runner.exercise_controller(self, controller)
+ @require_controller
def test_protocolinfo(self):
"""
Test that the convenient method protocolinfo() works.
"""
- if test.runner.require_control(self):
- return
-
runner = test.runner.get_runner()
with runner.get_tor_controller(False) as controller:
@@ -390,14 +371,12 @@ class TestController(unittest.TestCase):
self.assertEqual(tuple(auth_methods), protocolinfo.auth_methods)
+ @require_controller
def test_getconf(self):
"""
Exercises GETCONF with valid and invalid queries.
"""
- if test.runner.require_control(self):
- return
-
runner = test.runner.get_runner()
with runner.get_tor_controller() as controller:
@@ -455,15 +434,13 @@ class TestController(unittest.TestCase):
self.assertEqual({}, controller.get_conf_map('', 'la-di-dah'))
self.assertEqual({}, controller.get_conf_map([], 'la-di-dah'))
+ @require_controller
def test_hidden_services_conf(self):
"""
Exercises the hidden service family of methods (get_hidden_service_conf,
set_hidden_service_conf, create_hidden_service, and remove_hidden_service).
"""
- if test.runner.require_control(self):
- return
-
runner = test.runner.get_runner()
test_dir = runner.get_test_dir()
@@ -548,15 +525,13 @@ class TestController(unittest.TestCase):
except:
pass
+ @require_controller
def test_set_conf(self):
"""
Exercises set_conf(), reset_conf(), and set_options() methods with valid
and invalid requests.
"""
- if test.runner.require_control(self):
- return
-
runner = test.runner.get_runner()
tmpdir = tempfile.mkdtemp()
@@ -623,14 +598,13 @@ class TestController(unittest.TestCase):
shutil.rmtree(tmpdir)
+ @require_controller
def test_loadconf(self):
"""
Exercises Controller.load_conf with valid and invalid requests.
"""
- if test.runner.require_control(self):
- return
- elif test.runner.require_version(self, stem.version.Requirement.LOADCONF):
+ if test.runner.require_version(self, stem.version.Requirement.LOADCONF):
return
runner = test.runner.get_runner()
@@ -664,10 +638,8 @@ class TestController(unittest.TestCase):
controller.load_conf(oldconf)
controller.reset_conf('__OwningControllerProcess')
+ @require_controller
def test_saveconf(self):
- if test.runner.require_control(self):
- return
-
runner = test.runner.get_runner()
# only testing for success, since we need to run out of disk space to test
@@ -686,14 +658,12 @@ class TestController(unittest.TestCase):
controller.save_conf()
controller.reset_conf('__OwningControllerProcess')
+ @require_controller
def test_get_ports(self):
"""
Test Controller.get_ports against a running tor instance.
"""
- if test.runner.require_control(self):
- return
-
runner = test.runner.get_runner()
with runner.get_tor_controller() as controller:
@@ -709,14 +679,12 @@ class TestController(unittest.TestCase):
else:
self.assertEqual([], controller.get_ports(Listener.CONTROL))
+ @require_controller
def test_get_listeners(self):
"""
Test Controller.get_listeners against a running tor instance.
"""
- if test.runner.require_control(self):
- return
-
runner = test.runner.get_runner()
with runner.get_tor_controller() as controller:
@@ -732,27 +700,21 @@ class TestController(unittest.TestCase):
else:
self.assertEqual([], controller.get_listeners(Listener.CONTROL))
+ @require_controller
def test_get_socks_listeners(self):
"""
Test Controller.get_socks_listeners against a running tor instance.
"""
- if test.runner.require_control(self):
- return
-
- runner = test.runner.get_runner()
-
- with runner.get_tor_controller() as controller:
+ with test.runner.get_runner().get_tor_controller() as controller:
self.assertEqual([('127.0.0.1', 1112)], controller.get_socks_listeners())
+ @require_controller
def test_enable_feature(self):
"""
Test Controller.enable_feature with valid and invalid inputs.
"""
- if test.runner.require_control(self):
- return
-
runner = test.runner.get_runner()
with runner.get_tor_controller() as controller:
@@ -778,14 +740,12 @@ class TestController(unittest.TestCase):
else:
self.fail()
+ @require_controller
def test_signal(self):
"""
Test controller.signal with valid and invalid signals.
"""
- if test.runner.require_control(self):
- return
-
with test.runner.get_runner().get_tor_controller() as controller:
# valid signal
controller.signal('CLEARDNSCACHE')
@@ -793,14 +753,12 @@ class TestController(unittest.TestCase):
# invalid signals
self.assertRaises(stem.InvalidArguments, controller.signal, 'FOOBAR')
+ @require_controller
def test_newnym_availability(self):
"""
Test the is_newnym_available and get_newnym_wait methods.
"""
- if test.runner.require_control(self):
- return
-
with test.runner.get_runner().get_tor_controller() as controller:
self.assertEqual(True, controller.is_newnym_available())
self.assertEqual(0.0, controller.get_newnym_wait())
@@ -810,10 +768,9 @@ class TestController(unittest.TestCase):
self.assertEqual(False, controller.is_newnym_available())
self.assertTrue(controller.get_newnym_wait() > 9.0)
+ @require_controller
def test_extendcircuit(self):
- if test.runner.require_control(self):
- return
- elif test.runner.require_online(self):
+ if test.runner.require_online(self):
return
elif test.runner.require_version(self, Requirement.EXTENDCIRCUIT_PATH_OPTIONAL):
return
@@ -830,14 +787,13 @@ 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
def test_repurpose_circuit(self):
"""
Tests Controller.repurpose_circuit with valid and invalid input.
"""
- if test.runner.require_control(self):
- return
- elif test.runner.require_online(self):
+ if test.runner.require_online(self):
return
elif test.runner.require_version(self, Requirement.EXTENDCIRCUIT_PATH_OPTIONAL):
return
@@ -857,14 +813,13 @@ class TestController(unittest.TestCase):
self.assertRaises(stem.InvalidRequest, controller.repurpose_circuit, 'f934h9f3h4', 'fooo')
self.assertRaises(stem.InvalidRequest, controller.repurpose_circuit, '4', 'fooo')
+ @require_controller
def test_close_circuit(self):
"""
Tests Controller.close_circuit with valid and invalid input.
"""
- if test.runner.require_control(self):
- return
- elif test.runner.require_online(self):
+ if test.runner.require_online(self):
return
elif test.runner.require_version(self, Requirement.EXTENDCIRCUIT_PATH_OPTIONAL):
return
@@ -888,14 +843,13 @@ class TestController(unittest.TestCase):
self.assertRaises(stem.InvalidArguments, controller.close_circuit, circuit_id + '1024')
self.assertRaises(stem.InvalidRequest, controller.close_circuit, '')
+ @require_controller
def test_get_streams(self):
"""
Tests Controller.get_streams().
"""
- if test.runner.require_control(self):
- return
- elif test.runner.require_online(self):
+ if test.runner.require_online(self):
return
host = socket.gethostbyname('www.torproject.org')
@@ -916,14 +870,13 @@ class TestController(unittest.TestCase):
self.assertTrue('%s:%s' % (host, port) in [stream.target for stream in streams])
+ @require_controller
def test_close_stream(self):
"""
Tests Controller.close_stream with valid and invalid input.
"""
- if test.runner.require_control(self):
- return
- elif test.runner.require_online(self):
+ if test.runner.require_online(self):
return
runner = test.runner.get_runner()
@@ -958,10 +911,9 @@ class TestController(unittest.TestCase):
self.assertRaises(stem.InvalidArguments, controller.close_stream, 'blarg')
+ @require_controller
def test_mapaddress(self):
- if test.runner.require_control(self):
- return
- elif test.runner.require_online(self):
+ if test.runner.require_online(self):
return
runner = test.runner.get_runner()
@@ -999,14 +951,13 @@ 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)))
+ @require_controller
def test_get_microdescriptor(self):
"""
Basic checks for get_microdescriptor().
"""
- if test.runner.require_control(self):
- return
- elif test.runner.require_version(self, Requirement.MICRODESCRIPTOR_IS_DEFAULT):
+ if test.runner.require_version(self, Requirement.MICRODESCRIPTOR_IS_DEFAULT):
return
elif test.runner.require_online(self):
return
@@ -1028,6 +979,7 @@ class TestController(unittest.TestCase):
self.assertEqual(md_by_fingerprint, md_by_nickname)
+ @require_controller
def test_get_microdescriptors(self):
"""
Fetches a few descriptors via the get_microdescriptors() method.
@@ -1035,9 +987,7 @@ class TestController(unittest.TestCase):
runner = test.runner.get_runner()
- if test.runner.require_control(self):
- return
- elif not os.path.exists(runner.get_test_dir('cached-descriptors')):
+ if not os.path.exists(runner.get_test_dir('cached-descriptors')):
test.runner.skip(self, '(no cached microdescriptors)')
return
@@ -1051,6 +1001,7 @@ class TestController(unittest.TestCase):
if count > 10:
break
+ @require_controller
def test_get_server_descriptor(self):
"""
Basic checks for get_server_descriptor().
@@ -1058,9 +1009,7 @@ class TestController(unittest.TestCase):
runner = test.runner.get_runner()
- if test.runner.require_control(self):
- return
- elif runner.get_tor_version() >= Requirement.MICRODESCRIPTOR_IS_DEFAULT:
+ if runner.get_tor_version() >= Requirement.MICRODESCRIPTOR_IS_DEFAULT:
test.runner.skip(self, '(requires server descriptors)')
return
@@ -1082,6 +1031,7 @@ class TestController(unittest.TestCase):
self.assertEqual(desc_by_fingerprint, desc_by_nickname)
+ @require_controller
def test_get_server_descriptors(self):
"""
Fetches a few descriptors via the get_server_descriptors() method.
@@ -1089,9 +1039,7 @@ class TestController(unittest.TestCase):
runner = test.runner.get_runner()
- if test.runner.require_control(self):
- return
- elif runner.get_tor_version() >= Requirement.MICRODESCRIPTOR_IS_DEFAULT:
+ if runner.get_tor_version() >= Requirement.MICRODESCRIPTOR_IS_DEFAULT:
test.runner.skip(self, '(requires server descriptors)')
return
@@ -1110,14 +1058,13 @@ class TestController(unittest.TestCase):
if count > 10:
break
+ @require_controller
def test_get_network_status(self):
"""
Basic checks for get_network_status().
"""
- if test.runner.require_control(self):
- return
- elif test.runner.require_online(self):
+ if test.runner.require_online(self):
return
with test.runner.get_runner().get_tor_controller() as controller:
@@ -1137,6 +1084,7 @@ class TestController(unittest.TestCase):
self.assertEqual(desc_by_fingerprint, desc_by_nickname)
+ @require_controller
def test_get_network_statuses(self):
"""
Fetches a few descriptors via the get_network_statuses() method.
@@ -1144,9 +1092,7 @@ class TestController(unittest.TestCase):
runner = test.runner.get_runner()
- if test.runner.require_control(self):
- return
- elif test.runner.require_online(self):
+ if test.runner.require_online(self):
return
with runner.get_tor_controller() as controller:
@@ -1165,10 +1111,9 @@ class TestController(unittest.TestCase):
if count > 10:
break
+ @require_controller
def test_attachstream(self):
- if test.runner.require_control(self):
- return
- elif test.runner.require_online(self):
+ if test.runner.require_online(self):
return
elif test.runner.require_version(self, Requirement.EXTENDCIRCUIT_PATH_OPTIONAL):
return
@@ -1210,14 +1155,13 @@ class TestController(unittest.TestCase):
self.assertEqual(our_stream.circ_id, circuit_id)
+ @require_controller
def test_get_circuits(self):
"""
Fetches circuits via the get_circuits() method.
"""
- if test.runner.require_control(self):
- return
- elif test.runner.require_online(self):
+ if test.runner.require_online(self):
return
elif test.runner.require_version(self, Requirement.EXTENDCIRCUIT_PATH_OPTIONAL):
return
@@ -1227,15 +1171,13 @@ class TestController(unittest.TestCase):
circuits = controller.get_circuits()
self.assertTrue(new_circ in [circ.id for circ in circuits])
+ @require_controller
def test_transition_to_relay(self):
"""
Transitions Tor to turn into a relay, then back to a client. This helps to
catch transition issues such as the one cited in :trac:`14901`.
"""
- if test.runner.require_control(self):
- return
-
with test.runner.get_runner().get_tor_controller() as controller:
self.assertEqual(None, controller.get_conf('OrPort'))
diff --git a/test/integ/process.py b/test/integ/process.py
index 6c6be21..7b10828 100644
--- a/test/integ/process.py
+++ b/test/integ/process.py
@@ -21,6 +21,8 @@ import stem.util.tor_tools
import stem.version
import test.runner
+from test.runner import require_controller
+
try:
# added in python 3.3
from unittest.mock import patch
@@ -44,14 +46,12 @@ class TestProcess(unittest.TestCase):
def tearDown(self):
shutil.rmtree(self.data_directory)
+ @require_controller
def test_version_argument(self):
"""
Check that 'tor --version' matches 'GETINFO version'.
"""
- if test.runner.require_control(self):
- return
-
with test.runner.get_runner().get_tor_controller() as controller:
self.assertEqual('Tor version %s.\n' % controller.get_version(), self.run_tor('--version'))
diff --git a/test/integ/response/protocolinfo.py b/test/integ/response/protocolinfo.py
index c9ca97d..b2ecd2c 100644
--- a/test/integ/response/protocolinfo.py
+++ b/test/integ/response/protocolinfo.py
@@ -11,6 +11,7 @@ import stem.util.system
import stem.version
import test.runner
+from test.runner import require_controller
from test.integ.util.system import filter_system_call
try:
@@ -21,15 +22,13 @@ except ImportError:
class TestProtocolInfo(unittest.TestCase):
+ @require_controller
def test_parsing(self):
"""
Makes a PROTOCOLINFO query and processes the response for our control
connection.
"""
- if test.runner.require_control(self):
- return
-
control_socket = test.runner.get_runner().get_tor_socket(False)
control_socket.send('PROTOCOLINFO 1')
protocolinfo_response = control_socket.recv()
@@ -45,6 +44,7 @@ class TestProtocolInfo(unittest.TestCase):
self.assert_matches_test_config(protocolinfo_response)
+ @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):
@@ -58,9 +58,6 @@ class TestProtocolInfo(unittest.TestCase):
with the 'RELATIVE' target.
"""
- if test.runner.require_control(self):
- return
-
if test.runner.Torrc.PORT in test.runner.get_runner().get_options():
lookup_prefixes = (
stem.util.system.GET_PID_BY_PORT_NETSTAT,
@@ -90,6 +87,7 @@ class TestProtocolInfo(unittest.TestCase):
self.assertTrue(control_socket.is_alive())
control_socket.close()
+ @require_controller
def test_multiple_protocolinfo_calls(self):
"""
Tests making repeated PROTOCOLINFO queries. This use case is interesting
@@ -97,23 +95,18 @@ class TestProtocolInfo(unittest.TestCase):
re-establish it.
"""
- if test.runner.require_control(self):
- return
-
with test.runner.get_runner().get_tor_socket(False) as control_socket:
for _ in range(5):
protocolinfo_response = stem.connection.get_protocolinfo(control_socket)
self.assert_matches_test_config(protocolinfo_response)
+ @require_controller
def test_pre_disconnected_query(self):
"""
Tests making a PROTOCOLINFO query when previous use of the socket had
already disconnected it.
"""
- if test.runner.require_control(self):
- return
-
with test.runner.get_runner().get_tor_socket(False) as control_socket:
# makes a couple protocolinfo queries outside of get_protocolinfo first
control_socket.send('PROTOCOLINFO 1')
diff --git a/test/integ/socket/control_message.py b/test/integ/socket/control_message.py
index a2eb6f2..e9faf84 100644
--- a/test/integ/socket/control_message.py
+++ b/test/integ/socket/control_message.py
@@ -9,16 +9,16 @@ import stem.socket
import stem.version
import test.runner
+from test.runner import require_controller
+
class TestControlMessage(unittest.TestCase):
+ @require_controller
def test_unestablished_socket(self):
"""
Checks message parsing when we have a valid but unauthenticated socket.
"""
- if test.runner.require_control(self):
- return
-
# If an unauthenticated connection gets a message besides AUTHENTICATE or
# PROTOCOLINFO then tor will give an 'Authentication required.' message and
# hang up.
@@ -54,14 +54,12 @@ class TestControlMessage(unittest.TestCase):
self.assertRaises(stem.SocketClosed, control_socket.send, 'GETINFO version')
self.assertRaises(stem.SocketClosed, control_socket.recv)
+ @require_controller
def test_invalid_command(self):
"""
Parses the response for a command which doesn't exist.
"""
- if test.runner.require_control(self):
- return
-
with test.runner.get_runner().get_tor_socket() as control_socket:
control_socket.send('blarg')
unrecognized_command_response = control_socket.recv()
@@ -70,14 +68,12 @@ 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
def test_invalid_getinfo(self):
"""
Parses the response for a GETINFO query which doesn't exist.
"""
- if test.runner.require_control(self):
- return
-
with test.runner.get_runner().get_tor_socket() as control_socket:
control_socket.send('GETINFO blarg')
unrecognized_key_response = control_socket.recv()
@@ -86,14 +82,12 @@ 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
def test_getinfo_config_file(self):
"""
Parses the 'GETINFO config-file' response.
"""
- if test.runner.require_control(self):
- return
-
runner = test.runner.get_runner()
torrc_dst = runner.get_torrc_path()
@@ -105,14 +99,13 @@ 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
def test_getinfo_config_text(self):
"""
Parses the 'GETINFO config-text' response.
"""
- if test.runner.require_control(self):
- return
- elif test.runner.require_version(self, stem.version.Requirement.GETINFO_CONFIG_TEXT):
+ if test.runner.require_version(self, stem.version.Requirement.GETINFO_CONFIG_TEXT):
return
runner = test.runner.get_runner()
@@ -150,14 +143,12 @@ 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
def test_bw_event(self):
"""
Issues 'SETEVENTS BW' and parses a couple events.
"""
- if test.runner.require_control(self):
- return
-
with test.runner.get_runner().get_tor_socket() as control_socket:
control_socket.send('SETEVENTS BW')
setevents_response = control_socket.recv()
diff --git a/test/integ/socket/control_socket.py b/test/integ/socket/control_socket.py
index a45c47e..83851be 100644
--- a/test/integ/socket/control_socket.py
+++ b/test/integ/socket/control_socket.py
@@ -16,16 +16,16 @@ import stem.control
import stem.socket
import test.runner
+from test.runner import require_controller
+
class TestControlSocket(unittest.TestCase):
+ @require_controller
def test_connection_time(self):
"""
Checks that our connection_time method tracks when our state's changed.
"""
- if test.runner.require_control(self):
- return
-
test_start = time.time()
runner = test.runner.get_runner()
@@ -54,14 +54,12 @@ class TestControlSocket(unittest.TestCase):
reconnection_time = control_socket.connection_time()
self.assertTrue(disconnection_time < reconnection_time <= time.time())
+ @require_controller
def test_send_buffered(self):
"""
Sends multiple requests before receiving back any of the replies.
"""
- if test.runner.require_control(self):
- return
-
runner = test.runner.get_runner()
tor_version = runner.get_tor_version()
@@ -74,14 +72,12 @@ class TestControlSocket(unittest.TestCase):
self.assertTrue(str(response).startswith('version=%s' % tor_version))
self.assertTrue(str(response).endswith('\nOK'))
+ @require_controller
def test_send_closed(self):
"""
Sends a message after we've closed the connection.
"""
- if test.runner.require_control(self):
- return
-
with test.runner.get_runner().get_tor_socket() as control_socket:
self.assertTrue(control_socket.is_alive())
control_socket.close()
@@ -89,6 +85,7 @@ class TestControlSocket(unittest.TestCase):
self.assertRaises(stem.SocketClosed, control_socket.send, 'blarg')
+ @require_controller
def test_send_disconnected(self):
"""
Sends a message to a socket that has been disconnected by the other end.
@@ -99,9 +96,6 @@ class TestControlSocket(unittest.TestCase):
call. With a file socket, however, we'll also fail when calling send().
"""
- if test.runner.require_control(self):
- return
-
with test.runner.get_runner().get_tor_socket() as control_socket:
control_socket.send('QUIT')
self.assertEqual('closing connection', str(control_socket.recv()))
@@ -117,14 +111,12 @@ class TestControlSocket(unittest.TestCase):
self.assertRaises(stem.SocketClosed, control_socket.send, 'blarg')
self.assertFalse(control_socket.is_alive())
+ @require_controller
def test_recv_closed(self):
"""
Receives a message after we've closed the connection.
"""
- if test.runner.require_control(self):
- return
-
with test.runner.get_runner().get_tor_socket() as control_socket:
self.assertTrue(control_socket.is_alive())
control_socket.close()
@@ -132,15 +124,13 @@ class TestControlSocket(unittest.TestCase):
self.assertRaises(stem.SocketClosed, control_socket.recv)
+ @require_controller
def test_recv_disconnected(self):
"""
Receives a message from a socket that has been disconnected by the other
end.
"""
- if test.runner.require_control(self):
- return
-
with test.runner.get_runner().get_tor_socket() as control_socket:
control_socket.send('QUIT')
self.assertEqual('closing connection', str(control_socket.recv()))
@@ -153,14 +143,12 @@ class TestControlSocket(unittest.TestCase):
self.assertRaises(stem.SocketClosed, control_socket.recv)
self.assertFalse(control_socket.is_alive())
+ @require_controller
def test_connect_repeatedly(self):
"""
Checks that we can reconnect, use, and disconnect a socket repeatedly.
"""
- if test.runner.require_control(self):
- return
-
with test.runner.get_runner().get_tor_socket(False) as control_socket:
for _ in range(10):
# this will raise if the PROTOCOLINFO query fails
diff --git a/test/integ/version.py b/test/integ/version.py
index 0cd15eb..8347b35 100644
--- a/test/integ/version.py
+++ b/test/integ/version.py
@@ -9,6 +9,8 @@ import stem.prereq
import stem.version
import test.runner
+from test.runner import require_controller
+
class TestVersion(unittest.TestCase):
def test_get_system_tor_version(self):
@@ -32,28 +34,24 @@ 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
def test_get_system_tor_version_value(self):
"""
Checks that the get_system_tor_version() provides the same value as our
test instance provides.
"""
- if test.runner.require_control(self):
- return
-
runner = test.runner.get_runner()
system_tor_version = stem.version.get_system_tor_version(runner.get_tor_command())
self.assertEqual(runner.get_tor_version(), system_tor_version)
+ @require_controller
def test_getinfo_version_parsing(self):
"""
Issues a 'GETINFO version' query to our test instance and makes sure that
we can parse it.
"""
- if test.runner.require_control(self):
- return
-
control_socket = test.runner.get_runner().get_tor_socket()
control_socket.send('GETINFO version')
version_response = control_socket.recv()
diff --git a/test/runner.py b/test/runner.py
index 3d0e43b..2f9fbf1 100644
--- a/test/runner.py
+++ b/test/runner.py
@@ -12,7 +12,7 @@ about the tor test instance they're running against.
TorInaccessable - Tor can't be queried for the information
skip - skips the current test if we can
- require_control - skips the test unless tor provides a controller endpoint
+ require_controller - skips the test unless tor provides a controller endpoint
require_version - skips the test unless we meet a tor version requirement
require_online - skips unless targets allow for online tests
only_run_once - skip the test if it has been ran before
@@ -117,18 +117,18 @@ def skip(test_case, message):
test_case.skipTest(message)
-def require_control(test_case):
+def require_controller(func):
"""
Skips the test unless tor provides an endpoint for controllers to attach to.
-
- :param unittest.TestCase test_case: test being ran
-
- :returns: True if test should be skipped, False otherwise
"""
- if not get_runner().is_accessible():
- skip(test_case, '(no connection)')
- return True
+ def wrapped(self, *args, **kwargs):
+ if get_runner().is_accessible():
+ return func(self, *args, **kwargs)
+ else:
+ skip(self, '(no connection)')
+
+ return wrapped
def require_version(test_case, req_version):
1
0
commit da657a915f00456be38b0624275d3150d0a0ffd6
Author: Damian Johnson <atagar(a)torproject.org>
Date: Sat Feb 21 13:30:43 2015 -0800
@require_version decorator
---
test/integ/control/controller.py | 37 +++++++++++++---------------------
test/integ/process.py | 11 +++++-----
test/integ/socket/control_message.py | 9 +++++----
test/runner.py | 18 ++++++++++-------
4 files changed, 36 insertions(+), 39 deletions(-)
diff --git a/test/integ/control/controller.py b/test/integ/control/controller.py
index 632c002..2a7bc69 100644
--- a/test/integ/control/controller.py
+++ b/test/integ/control/controller.py
@@ -26,7 +26,10 @@ from stem.control import EventType, Listener, State
from stem.exit_policy import ExitPolicy
from stem.version import Requirement
-from test.runner import require_controller
+from test.runner import (
+ require_controller,
+ require_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.
@@ -62,14 +65,12 @@ class TestController(unittest.TestCase):
self.assertRaises(stem.SocketError, stem.control.Controller.from_socket_file, test.runner.CONTROL_SOCKET_PATH)
@require_controller
+ @require_version(Requirement.EVENT_SIGNAL)
def test_reset_notification(self):
"""
Checks that a notificiation listener is... well, notified of SIGHUPs.
"""
- if test.runner.require_version(self, stem.version.Requirement.EVENT_SIGNAL):
- return
-
with test.runner.get_runner().get_tor_controller() as controller:
received_events = []
@@ -599,14 +600,12 @@ class TestController(unittest.TestCase):
shutil.rmtree(tmpdir)
@require_controller
+ @require_version(Requirement.LOADCONF)
def test_loadconf(self):
"""
Exercises Controller.load_conf with valid and invalid requests.
"""
- if test.runner.require_version(self, stem.version.Requirement.LOADCONF):
- return
-
runner = test.runner.get_runner()
with runner.get_tor_controller() as controller:
@@ -710,6 +709,7 @@ class TestController(unittest.TestCase):
self.assertEqual([('127.0.0.1', 1112)], controller.get_socks_listeners())
@require_controller
+ @require_version(stem.version.Version('0.1.2.2-alpha'))
def test_enable_feature(self):
"""
Test Controller.enable_feature with valid and invalid inputs.
@@ -718,9 +718,6 @@ class TestController(unittest.TestCase):
runner = test.runner.get_runner()
with runner.get_tor_controller() as controller:
- if not test.runner.require_version(self, stem.version.Version('0.1.2.2-alpha')):
- controller.enable_feature('VERBOSE_NAMES')
-
self.assertTrue(controller.is_feature_enabled('VERBOSE_NAMES'))
orconn_output = controller.get_info('orconn-status')
@@ -769,11 +766,10 @@ class TestController(unittest.TestCase):
self.assertTrue(controller.get_newnym_wait() > 9.0)
@require_controller
+ @require_version(Requirement.EXTENDCIRCUIT_PATH_OPTIONAL)
def test_extendcircuit(self):
if test.runner.require_online(self):
return
- elif test.runner.require_version(self, Requirement.EXTENDCIRCUIT_PATH_OPTIONAL):
- return
with test.runner.get_runner().get_tor_controller() as controller:
circuit_id = controller.extend_circuit('0')
@@ -788,6 +784,7 @@ class TestController(unittest.TestCase):
self.assertRaises(stem.InvalidRequest, controller.extend_circuit, '0', 'thisroutershouldntexistbecausestemexists!@##$%#', 'foo')
@require_controller
+ @require_version(Requirement.EXTENDCIRCUIT_PATH_OPTIONAL)
def test_repurpose_circuit(self):
"""
Tests Controller.repurpose_circuit with valid and invalid input.
@@ -795,8 +792,6 @@ class TestController(unittest.TestCase):
if test.runner.require_online(self):
return
- elif test.runner.require_version(self, Requirement.EXTENDCIRCUIT_PATH_OPTIONAL):
- return
runner = test.runner.get_runner()
@@ -814,6 +809,7 @@ class TestController(unittest.TestCase):
self.assertRaises(stem.InvalidRequest, controller.repurpose_circuit, '4', 'fooo')
@require_controller
+ @require_version(Requirement.EXTENDCIRCUIT_PATH_OPTIONAL)
def test_close_circuit(self):
"""
Tests Controller.close_circuit with valid and invalid input.
@@ -821,8 +817,6 @@ class TestController(unittest.TestCase):
if test.runner.require_online(self):
return
- elif test.runner.require_version(self, Requirement.EXTENDCIRCUIT_PATH_OPTIONAL):
- return
runner = test.runner.get_runner()
@@ -952,14 +946,13 @@ class TestController(unittest.TestCase):
self.assertTrue(stem.util.connection.is_valid_ipv4_address(stem.util.str_tools._to_unicode(ip_addr)))
@require_controller
+ @require_version(Requirement.MICRODESCRIPTOR_IS_DEFAULT)
def test_get_microdescriptor(self):
"""
Basic checks for get_microdescriptor().
"""
- if test.runner.require_version(self, Requirement.MICRODESCRIPTOR_IS_DEFAULT):
- return
- elif test.runner.require_online(self):
+ if test.runner.require_online(self):
return
with test.runner.get_runner().get_tor_controller() as controller:
@@ -1112,11 +1105,10 @@ class TestController(unittest.TestCase):
break
@require_controller
+ @require_version(Requirement.EXTENDCIRCUIT_PATH_OPTIONAL)
def test_attachstream(self):
if test.runner.require_online(self):
return
- elif test.runner.require_version(self, Requirement.EXTENDCIRCUIT_PATH_OPTIONAL):
- return
host = socket.gethostbyname('www.torproject.org')
port = 80
@@ -1156,6 +1148,7 @@ class TestController(unittest.TestCase):
self.assertEqual(our_stream.circ_id, circuit_id)
@require_controller
+ @require_version(Requirement.EXTENDCIRCUIT_PATH_OPTIONAL)
def test_get_circuits(self):
"""
Fetches circuits via the get_circuits() method.
@@ -1163,8 +1156,6 @@ class TestController(unittest.TestCase):
if test.runner.require_online(self):
return
- elif test.runner.require_version(self, Requirement.EXTENDCIRCUIT_PATH_OPTIONAL):
- return
with test.runner.get_runner().get_tor_controller() as controller:
new_circ = controller.new_circuit()
diff --git a/test/integ/process.py b/test/integ/process.py
index 7b10828..f611191 100644
--- a/test/integ/process.py
+++ b/test/integ/process.py
@@ -21,7 +21,10 @@ import stem.util.tor_tools
import stem.version
import test.runner
-from test.runner import require_controller
+from test.runner import (
+ require_controller,
+ require_version,
+)
try:
# added in python 3.3
@@ -328,6 +331,7 @@ class TestProcess(unittest.TestCase):
if not (runtime > 2 and runtime < 3):
self.fail('Test should have taken 2-3 seconds, took %i instead' % runtime)
+ @require_version(stem.version.Requirement.TAKEOWNERSHIP)
@patch('os.getpid')
def test_take_ownership_via_pid(self, getpid_mock):
"""
@@ -340,8 +344,6 @@ class TestProcess(unittest.TestCase):
return
elif test.runner.only_run_once(self):
return
- elif test.runner.require_version(self, stem.version.Requirement.TAKEOWNERSHIP):
- return
sleep_process = subprocess.Popen(['sleep', '60'])
getpid_mock.return_value = str(sleep_process.pid)
@@ -373,6 +375,7 @@ class TestProcess(unittest.TestCase):
self.fail("tor didn't quit after the process that owned it terminated")
+ @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
@@ -381,8 +384,6 @@ class TestProcess(unittest.TestCase):
if test.runner.only_run_once(self):
return
- elif test.runner.require_version(self, stem.version.Requirement.TAKEOWNERSHIP):
- return
tor_process = stem.process.launch_tor_with_config(
tor_cmd = test.runner.get_runner().get_tor_command(),
diff --git a/test/integ/socket/control_message.py b/test/integ/socket/control_message.py
index e9faf84..567a78d 100644
--- a/test/integ/socket/control_message.py
+++ b/test/integ/socket/control_message.py
@@ -9,7 +9,10 @@ import stem.socket
import stem.version
import test.runner
-from test.runner import require_controller
+from test.runner import (
+ require_controller,
+ require_version,
+)
class TestControlMessage(unittest.TestCase):
@@ -100,14 +103,12 @@ class TestControlMessage(unittest.TestCase):
self.assertEqual([('250', '-', 'config-file=%s' % torrc_dst), ('250', ' ', 'OK')], config_file_response.content())
@require_controller
+ @require_version(stem.version.Requirement.GETINFO_CONFIG_TEXT)
def test_getinfo_config_text(self):
"""
Parses the 'GETINFO config-text' response.
"""
- if test.runner.require_version(self, stem.version.Requirement.GETINFO_CONFIG_TEXT):
- return
-
runner = test.runner.get_runner()
# We can't be certain of the order, and there may be extra config-text
diff --git a/test/runner.py b/test/runner.py
index 2f9fbf1..6d637de 100644
--- a/test/runner.py
+++ b/test/runner.py
@@ -131,19 +131,23 @@ def require_controller(func):
return wrapped
-def require_version(test_case, req_version):
+def require_version(req_version):
"""
Skips the test unless we meet the required version.
- :param unittest.TestCase test_case: test being ran
:param stem.version.Version req_version: required tor version for the test
-
- :returns: True if test should be skipped, False otherwise
"""
- if get_runner().get_tor_version() < req_version:
- skip(test_case, '(requires %s)' % req_version)
- return True
+ def decorator(func):
+ def wrapped(self, *args, **kwargs):
+ if get_runner().get_tor_version() >= req_version:
+ return func(self, *args, **kwargs)
+ else:
+ skip(self, '(requires %s)' % req_version)
+
+ return wrapped
+
+ return decorator
def require_online(test_case):
1
0
commit 7232e79de7e0fc0886b836387f7a530627b0c383
Author: Damian Johnson <atagar(a)torproject.org>
Date: Sat Feb 21 13:46:17 2015 -0800
@only_run_once decorator
---
test/integ/descriptor/extrainfo_descriptor.py | 8 ++----
test/integ/descriptor/microdescriptor.py | 6 ++--
test/integ/descriptor/networkstatus.py | 14 +++-------
test/integ/descriptor/remote.py | 37 ++++++++-----------------
test/integ/descriptor/server_descriptor.py | 8 ++----
test/integ/process.py | 20 ++++---------
test/runner.py | 19 ++++++-------
7 files changed, 40 insertions(+), 72 deletions(-)
diff --git a/test/integ/descriptor/extrainfo_descriptor.py b/test/integ/descriptor/extrainfo_descriptor.py
index cfbc1e5..d102fea 100644
--- a/test/integ/descriptor/extrainfo_descriptor.py
+++ b/test/integ/descriptor/extrainfo_descriptor.py
@@ -8,8 +8,11 @@ import unittest
import stem.descriptor
import test.runner
+from test.runner import only_run_once
+
class TestExtraInfoDescriptor(unittest.TestCase):
+ @only_run_once
def test_cached_descriptor(self):
"""
Parses the cached descriptor file in our data directory, checking that it
@@ -17,11 +20,6 @@ class TestExtraInfoDescriptor(unittest.TestCase):
additions.
"""
- # lengthy test and uneffected by targets, so only run once
-
- if test.runner.only_run_once(self):
- return
-
descriptor_path = test.runner.get_runner().get_test_dir('cached-extrainfo')
if not os.path.exists(descriptor_path):
diff --git a/test/integ/descriptor/microdescriptor.py b/test/integ/descriptor/microdescriptor.py
index 0652587..ebd0287 100644
--- a/test/integ/descriptor/microdescriptor.py
+++ b/test/integ/descriptor/microdescriptor.py
@@ -8,8 +8,11 @@ import unittest
import stem.descriptor
import test.runner
+from test.runner import only_run_once
+
class TestMicrodescriptor(unittest.TestCase):
+ @only_run_once
def test_cached_microdescriptors(self):
"""
Parses the cached microdescriptor file in our data directory, checking that
@@ -17,9 +20,6 @@ class TestMicrodescriptor(unittest.TestCase):
descriptor additions.
"""
- if test.runner.only_run_once(self):
- return
-
descriptor_path = test.runner.get_runner().get_test_dir('cached-microdescs')
if not os.path.exists(descriptor_path):
diff --git a/test/integ/descriptor/networkstatus.py b/test/integ/descriptor/networkstatus.py
index 6c29158..8f97b26 100644
--- a/test/integ/descriptor/networkstatus.py
+++ b/test/integ/descriptor/networkstatus.py
@@ -11,18 +11,16 @@ import stem.descriptor.networkstatus
import stem.version
import test.runner
+from test.runner import only_run_once
+
class TestNetworkStatus(unittest.TestCase):
+ @only_run_once
def test_cached_consensus(self):
"""
Parses the cached-consensus file in our data directory.
"""
- # lengthy test and uneffected by targets, so only run once
-
- if test.runner.only_run_once(self):
- return
-
consensus_path = test.runner.get_runner().get_test_dir('cached-consensus')
if not os.path.exists(consensus_path):
@@ -57,16 +55,12 @@ class TestNetworkStatus(unittest.TestCase):
self.assertTrue(count > 100)
+ @only_run_once
def test_cached_microdesc_consensus(self):
"""
Parses the cached-microdesc-consensus file in our data directory.
"""
- # lengthy test and uneffected by targets, so only run once
-
- if test.runner.only_run_once(self):
- return
-
consensus_path = test.runner.get_runner().get_test_dir('cached-microdesc-consensus')
if not os.path.exists(consensus_path):
diff --git a/test/integ/descriptor/remote.py b/test/integ/descriptor/remote.py
index cc7d4cb..78b1add 100644
--- a/test/integ/descriptor/remote.py
+++ b/test/integ/descriptor/remote.py
@@ -13,20 +13,21 @@ import stem.descriptor.router_status_entry
import stem.descriptor.server_descriptor
import test.runner
-from test.runner import require_online
+from test.runner import (
+ require_online,
+ only_run_once,
+)
class TestDescriptorDownloader(unittest.TestCase):
@require_online
+ @only_run_once
def test_authorities_are_up_to_date(self):
"""
Check that our hardcoded directory authority data matches the present
consensus.
"""
- if test.runner.only_run_once(self):
- return
-
downloader = stem.descriptor.remote.DescriptorDownloader()
consensus = downloader.get_consensus(document_handler = stem.descriptor.DocumentHandler.BARE_DOCUMENT).run()[0]
@@ -44,6 +45,7 @@ class TestDescriptorDownloader(unittest.TestCase):
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
def test_using_authorities(self):
"""
Fetches a descriptor from each of the directory authorities. This is
@@ -54,9 +56,6 @@ class TestDescriptorDownloader(unittest.TestCase):
then this test will need to be updated.
"""
- if test.runner.only_run_once(self):
- return
-
queries = []
for nickname, authority in stem.descriptor.remote.get_authorities().items():
@@ -78,27 +77,23 @@ class TestDescriptorDownloader(unittest.TestCase):
self.assertEqual('moria1', descriptors[0].nickname)
@require_online
+ @only_run_once
def test_use_directory_mirrors(self):
"""
Checks that we can fetch and use a list of directory mirrors.
"""
- if test.runner.only_run_once(self):
- return
-
downloader = stem.descriptor.remote.DescriptorDownloader()
downloader.use_directory_mirrors()
self.assertTrue(len(downloader._endpoints) > 50)
@require_online
+ @only_run_once
def test_get_server_descriptors(self):
"""
Exercises the downloader's get_server_descriptors() method.
"""
- if test.runner.only_run_once(self):
- return
-
downloader = stem.descriptor.remote.DescriptorDownloader(validate = True)
# Fetch a single descriptor and a batch. I'd love to also exercise
@@ -126,14 +121,12 @@ class TestDescriptorDownloader(unittest.TestCase):
self.assertEqual(2, len(list(multiple_query)))
@require_online
+ @only_run_once
def test_get_extrainfo_descriptors(self):
"""
Exercises the downloader's get_extrainfo_descriptors() method.
"""
- if test.runner.only_run_once(self):
- return
-
downloader = stem.descriptor.remote.DescriptorDownloader(validate = True)
single_query = downloader.get_extrainfo_descriptors('9695DFC35FFEB861329B9F1AB04C46397020CE31')
@@ -154,6 +147,7 @@ class TestDescriptorDownloader(unittest.TestCase):
self.assertEqual(2, len(list(multiple_query)))
@require_online
+ @only_run_once
def test_get_microdescriptors(self):
"""
Exercises the downloader's get_microdescriptors() method.
@@ -164,9 +158,6 @@ class TestDescriptorDownloader(unittest.TestCase):
test.runner.skip(self, '(test presently broken)')
return
- if test.runner.only_run_once(self):
- return
-
downloader = stem.descriptor.remote.DescriptorDownloader(validate = True)
single_query = downloader.get_microdescriptors('6dCl6ab8CLo0LeMjxi/MZgVJiZgWN8WKTesWPBMtyTo')
@@ -187,14 +178,12 @@ class TestDescriptorDownloader(unittest.TestCase):
self.assertEqual(2, len(list(multiple_query)))
@require_online
+ @only_run_once
def test_get_consensus(self):
"""
Exercises the downloader's get_consensus() method.
"""
- if test.runner.only_run_once(self):
- return
-
downloader = stem.descriptor.remote.DescriptorDownloader(validate = True)
consensus_query = downloader.get_consensus()
@@ -205,14 +194,12 @@ class TestDescriptorDownloader(unittest.TestCase):
self.assertTrue(isinstance(consensus[0], stem.descriptor.router_status_entry.RouterStatusEntryV3))
@require_online
+ @only_run_once
def test_get_key_certificates(self):
"""
Exercises the downloader's get_key_certificates() method.
"""
- if test.runner.only_run_once(self):
- return
-
downloader = stem.descriptor.remote.DescriptorDownloader(validate = True)
single_query = downloader.get_key_certificates('D586D18309DED4CD6D57C18FDB97EFA96D330566')
diff --git a/test/integ/descriptor/server_descriptor.py b/test/integ/descriptor/server_descriptor.py
index 87eba5c..6d5d348 100644
--- a/test/integ/descriptor/server_descriptor.py
+++ b/test/integ/descriptor/server_descriptor.py
@@ -9,8 +9,11 @@ import stem.descriptor
import test.runner
+from test.runner import only_run_once
+
class TestServerDescriptor(unittest.TestCase):
+ @only_run_once
def test_cached_descriptor(self):
"""
Parses the cached descriptor file in our data directory, checking that it
@@ -18,11 +21,6 @@ class TestServerDescriptor(unittest.TestCase):
additions.
"""
- # lengthy test and uneffected by targets, so only run once
-
- if test.runner.only_run_once(self):
- return
-
descriptor_path = test.runner.get_runner().get_test_dir('cached-descriptors')
if not os.path.exists(descriptor_path):
diff --git a/test/integ/process.py b/test/integ/process.py
index f611191..639dba5 100644
--- a/test/integ/process.py
+++ b/test/integ/process.py
@@ -24,6 +24,7 @@ import test.runner
from test.runner import (
require_controller,
require_version,
+ only_run_once,
)
try:
@@ -250,14 +251,12 @@ 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
def test_launch_tor_with_config(self):
"""
Exercises launch_tor_with_config.
"""
- if test.runner.only_run_once(self):
- return
-
# Launch tor without a torrc, but with a control port. Confirms that this
# works by checking that we're still able to access the new instance.
@@ -288,14 +287,12 @@ class TestProcess(unittest.TestCase):
tor_process.kill()
tor_process.wait()
+ @only_run_once
def test_with_invalid_config(self):
"""
Spawn a tor process with a configuration that should make it dead on arrival.
"""
- if test.runner.only_run_once(self):
- return
-
# Set the same SocksPort and ControlPort, this should fail with...
#
# [warn] Failed to parse/validate config: Failed to bind one of the listener ports.
@@ -314,14 +311,12 @@ class TestProcess(unittest.TestCase):
except OSError as exc:
self.assertEqual('Process terminated: Failed to bind one of the listener ports.', str(exc))
+ @only_run_once
def test_launch_tor_with_timeout(self):
"""
Runs launch_tor where it times out before completing.
"""
- if test.runner.only_run_once(self):
- return
-
runner = test.runner.get_runner()
start_time = time.time()
config = {'SocksPort': '2777', 'DataDirectory': self.data_directory}
@@ -332,6 +327,7 @@ class TestProcess(unittest.TestCase):
self.fail('Test should have taken 2-3 seconds, took %i instead' % runtime)
@require_version(stem.version.Requirement.TAKEOWNERSHIP)
+ @only_run_once
@patch('os.getpid')
def test_take_ownership_via_pid(self, getpid_mock):
"""
@@ -342,8 +338,6 @@ class TestProcess(unittest.TestCase):
if not stem.util.system.is_available('sleep'):
test.runner.skip(self, "('sleep' command is unavailable)")
return
- elif test.runner.only_run_once(self):
- return
sleep_process = subprocess.Popen(['sleep', '60'])
getpid_mock.return_value = str(sleep_process.pid)
@@ -376,15 +370,13 @@ 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
def test_take_ownership_via_controller(self):
"""
Checks that the tor process quits after the controller that owns it
connects, then disconnects..
"""
- if test.runner.only_run_once(self):
- return
-
tor_process = stem.process.launch_tor_with_config(
tor_cmd = test.runner.get_runner().get_tor_command(),
config = {
diff --git a/test/runner.py b/test/runner.py
index ecf5fb6..0370abd 100644
--- a/test/runner.py
+++ b/test/runner.py
@@ -165,22 +165,21 @@ def require_online(func):
return wrapped
-def only_run_once(test_case):
+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``.
-
- :param unittest.TestCase test_case: test being ran
-
- :returns: True if test should be skipped, False otherwise
"""
- if (test_case, test_case.id()) in RAN_TESTS:
- skip(test_case, '(already ran)')
- return True
- else:
- RAN_TESTS.append((test_case, test_case.id()))
+ def wrapped(self, *args, **kwargs):
+ if (self, self.id()) not in RAN_TESTS:
+ RAN_TESTS.append((self, self.id()))
+ return func(self, *args, **kwargs)
+ else:
+ skip(self, '(already ran)')
+
+ return wrapped
def exercise_controller(test_case, controller):
1
0
commit 5aec4d5d8abc614c089a95e09b81bf9f1e3c6ce2
Author: Damian Johnson <atagar(a)torproject.org>
Date: Sat Feb 21 13:39:39 2015 -0800
@require_online decorator
---
test/integ/control/controller.py | 53 ++++++++++----------------------------
test/integ/descriptor/remote.py | 42 +++++++++++++-----------------
test/runner.py | 16 ++++++------
3 files changed, 39 insertions(+), 72 deletions(-)
diff --git a/test/integ/control/controller.py b/test/integ/control/controller.py
index 2a7bc69..0a0e112 100644
--- a/test/integ/control/controller.py
+++ b/test/integ/control/controller.py
@@ -29,6 +29,7 @@ from stem.version import Requirement
from test.runner import (
require_controller,
require_version,
+ require_online,
)
# Router status entry for a relay with a nickname other than 'Unnamed'. This is
@@ -709,6 +710,7 @@ class TestController(unittest.TestCase):
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'))
def test_enable_feature(self):
"""
@@ -720,13 +722,6 @@ class TestController(unittest.TestCase):
with runner.get_tor_controller() as controller:
self.assertTrue(controller.is_feature_enabled('VERBOSE_NAMES'))
- orconn_output = controller.get_info('orconn-status')
-
- # the orconn-status results will be empty if we don't have a connection
- if orconn_output == '':
- if test.runner.require_online(self):
- return
-
self.assertTrue('VERBOSE_NAMES' in controller._enabled_features)
self.assertRaises(stem.InvalidArguments, controller.enable_feature, ['NOT', 'A', 'FEATURE'])
@@ -766,11 +761,9 @@ class TestController(unittest.TestCase):
self.assertTrue(controller.get_newnym_wait() > 9.0)
@require_controller
+ @require_online
@require_version(Requirement.EXTENDCIRCUIT_PATH_OPTIONAL)
def test_extendcircuit(self):
- if test.runner.require_online(self):
- return
-
with test.runner.get_runner().get_tor_controller() as controller:
circuit_id = controller.extend_circuit('0')
@@ -784,15 +777,13 @@ class TestController(unittest.TestCase):
self.assertRaises(stem.InvalidRequest, controller.extend_circuit, '0', 'thisroutershouldntexistbecausestemexists!@##$%#', 'foo')
@require_controller
+ @require_online
@require_version(Requirement.EXTENDCIRCUIT_PATH_OPTIONAL)
def test_repurpose_circuit(self):
"""
Tests Controller.repurpose_circuit with valid and invalid input.
"""
- if test.runner.require_online(self):
- return
-
runner = test.runner.get_runner()
with runner.get_tor_controller() as controller:
@@ -809,15 +800,13 @@ class TestController(unittest.TestCase):
self.assertRaises(stem.InvalidRequest, controller.repurpose_circuit, '4', 'fooo')
@require_controller
+ @require_online
@require_version(Requirement.EXTENDCIRCUIT_PATH_OPTIONAL)
def test_close_circuit(self):
"""
Tests Controller.close_circuit with valid and invalid input.
"""
- if test.runner.require_online(self):
- return
-
runner = test.runner.get_runner()
with runner.get_tor_controller() as controller:
@@ -838,14 +827,12 @@ class TestController(unittest.TestCase):
self.assertRaises(stem.InvalidRequest, controller.close_circuit, '')
@require_controller
+ @require_online
def test_get_streams(self):
"""
Tests Controller.get_streams().
"""
- if test.runner.require_online(self):
- return
-
host = socket.gethostbyname('www.torproject.org')
port = 443
@@ -865,14 +852,12 @@ class TestController(unittest.TestCase):
self.assertTrue('%s:%s' % (host, port) in [stream.target for stream in streams])
@require_controller
+ @require_online
def test_close_stream(self):
"""
Tests Controller.close_stream with valid and invalid input.
"""
- if test.runner.require_online(self):
- return
-
runner = test.runner.get_runner()
with runner.get_tor_controller() as controller:
@@ -906,10 +891,8 @@ class TestController(unittest.TestCase):
self.assertRaises(stem.InvalidArguments, controller.close_stream, 'blarg')
@require_controller
+ @require_online
def test_mapaddress(self):
- if test.runner.require_online(self):
- return
-
runner = test.runner.get_runner()
with runner.get_tor_controller() as controller:
@@ -946,15 +929,13 @@ class TestController(unittest.TestCase):
self.assertTrue(stem.util.connection.is_valid_ipv4_address(stem.util.str_tools._to_unicode(ip_addr)))
@require_controller
+ @require_online
@require_version(Requirement.MICRODESCRIPTOR_IS_DEFAULT)
def test_get_microdescriptor(self):
"""
Basic checks for get_microdescriptor().
"""
- if test.runner.require_online(self):
- return
-
with test.runner.get_runner().get_tor_controller() as controller:
# we should balk at invalid content
self.assertRaises(ValueError, controller.get_microdescriptor, '')
@@ -1052,14 +1033,12 @@ class TestController(unittest.TestCase):
break
@require_controller
+ @require_online
def test_get_network_status(self):
"""
Basic checks for get_network_status().
"""
- if test.runner.require_online(self):
- return
-
with test.runner.get_runner().get_tor_controller() as controller:
# we should balk at invalid content
self.assertRaises(ValueError, controller.get_network_status, '')
@@ -1078,6 +1057,7 @@ class TestController(unittest.TestCase):
self.assertEqual(desc_by_fingerprint, desc_by_nickname)
@require_controller
+ @require_online
def test_get_network_statuses(self):
"""
Fetches a few descriptors via the get_network_statuses() method.
@@ -1085,9 +1065,6 @@ class TestController(unittest.TestCase):
runner = test.runner.get_runner()
- if test.runner.require_online(self):
- return
-
with runner.get_tor_controller() as controller:
count = 0
@@ -1105,11 +1082,9 @@ class TestController(unittest.TestCase):
break
@require_controller
+ @require_online
@require_version(Requirement.EXTENDCIRCUIT_PATH_OPTIONAL)
def test_attachstream(self):
- if test.runner.require_online(self):
- return
-
host = socket.gethostbyname('www.torproject.org')
port = 80
@@ -1148,15 +1123,13 @@ class TestController(unittest.TestCase):
self.assertEqual(our_stream.circ_id, circuit_id)
@require_controller
+ @require_online
@require_version(Requirement.EXTENDCIRCUIT_PATH_OPTIONAL)
def test_get_circuits(self):
"""
Fetches circuits via the get_circuits() method.
"""
- if test.runner.require_online(self):
- return
-
with test.runner.get_runner().get_tor_controller() as controller:
new_circ = controller.new_circuit()
circuits = controller.get_circuits()
diff --git a/test/integ/descriptor/remote.py b/test/integ/descriptor/remote.py
index 9450c0e..cc7d4cb 100644
--- a/test/integ/descriptor/remote.py
+++ b/test/integ/descriptor/remote.py
@@ -13,17 +13,18 @@ import stem.descriptor.router_status_entry
import stem.descriptor.server_descriptor
import test.runner
+from test.runner import require_online
+
class TestDescriptorDownloader(unittest.TestCase):
+ @require_online
def test_authorities_are_up_to_date(self):
"""
Check that our hardcoded directory authority data matches the present
consensus.
"""
- if test.runner.require_online(self):
- return
- elif test.runner.only_run_once(self):
+ if test.runner.only_run_once(self):
return
downloader = stem.descriptor.remote.DescriptorDownloader()
@@ -42,6 +43,7 @@ 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
def test_using_authorities(self):
"""
Fetches a descriptor from each of the directory authorities. This is
@@ -52,9 +54,7 @@ class TestDescriptorDownloader(unittest.TestCase):
then this test will need to be updated.
"""
- if test.runner.require_online(self):
- return
- elif test.runner.only_run_once(self):
+ if test.runner.only_run_once(self):
return
queries = []
@@ -77,28 +77,26 @@ class TestDescriptorDownloader(unittest.TestCase):
self.assertEqual(1, len(descriptors))
self.assertEqual('moria1', descriptors[0].nickname)
+ @require_online
def test_use_directory_mirrors(self):
"""
Checks that we can fetch and use a list of directory mirrors.
"""
- if test.runner.require_online(self):
- return
- elif test.runner.only_run_once(self):
+ if test.runner.only_run_once(self):
return
downloader = stem.descriptor.remote.DescriptorDownloader()
downloader.use_directory_mirrors()
self.assertTrue(len(downloader._endpoints) > 50)
+ @require_online
def test_get_server_descriptors(self):
"""
Exercises the downloader's get_server_descriptors() method.
"""
- if test.runner.require_online(self):
- return
- elif test.runner.only_run_once(self):
+ if test.runner.only_run_once(self):
return
downloader = stem.descriptor.remote.DescriptorDownloader(validate = True)
@@ -127,14 +125,13 @@ class TestDescriptorDownloader(unittest.TestCase):
self.assertEqual(2, len(list(multiple_query)))
+ @require_online
def test_get_extrainfo_descriptors(self):
"""
Exercises the downloader's get_extrainfo_descriptors() method.
"""
- if test.runner.require_online(self):
- return
- elif test.runner.only_run_once(self):
+ if test.runner.only_run_once(self):
return
downloader = stem.descriptor.remote.DescriptorDownloader(validate = True)
@@ -156,6 +153,7 @@ class TestDescriptorDownloader(unittest.TestCase):
self.assertEqual(2, len(list(multiple_query)))
+ @require_online
def test_get_microdescriptors(self):
"""
Exercises the downloader's get_microdescriptors() method.
@@ -166,9 +164,7 @@ class TestDescriptorDownloader(unittest.TestCase):
test.runner.skip(self, '(test presently broken)')
return
- if test.runner.require_online(self):
- return
- elif test.runner.only_run_once(self):
+ if test.runner.only_run_once(self):
return
downloader = stem.descriptor.remote.DescriptorDownloader(validate = True)
@@ -190,14 +186,13 @@ class TestDescriptorDownloader(unittest.TestCase):
self.assertEqual(2, len(list(multiple_query)))
+ @require_online
def test_get_consensus(self):
"""
Exercises the downloader's get_consensus() method.
"""
- if test.runner.require_online(self):
- return
- elif test.runner.only_run_once(self):
+ if test.runner.only_run_once(self):
return
downloader = stem.descriptor.remote.DescriptorDownloader(validate = True)
@@ -209,14 +204,13 @@ class TestDescriptorDownloader(unittest.TestCase):
self.assertTrue(len(consensus) > 50)
self.assertTrue(isinstance(consensus[0], stem.descriptor.router_status_entry.RouterStatusEntryV3))
+ @require_online
def test_get_key_certificates(self):
"""
Exercises the downloader's get_key_certificates() method.
"""
- if test.runner.require_online(self):
- return
- elif test.runner.only_run_once(self):
+ if test.runner.only_run_once(self):
return
downloader = stem.descriptor.remote.DescriptorDownloader(validate = True)
diff --git a/test/runner.py b/test/runner.py
index 6d637de..ecf5fb6 100644
--- a/test/runner.py
+++ b/test/runner.py
@@ -150,19 +150,19 @@ def require_version(req_version):
return decorator
-def require_online(test_case):
+def require_online(func):
"""
Skips the test if we weren't started with the ONLINE target, which indicates
that tests requiring network connectivity should run.
-
- :param unittest.TestCase test_case: test being ran
-
- :returns: True if test should be skipped, False otherwise
"""
- if Target.ONLINE not in get_runner().attribute_targets:
- skip(test_case, '(requires online target)')
- return True
+ def wrapped(self, *args, **kwargs):
+ if Target.ONLINE in get_runner().attribute_targets:
+ return func(self, *args, **kwargs)
+ else:
+ skip(self, '(requires online target)')
+
+ return wrapped
def only_run_once(test_case):
1
0
commit 867ddbe86cb278467deeb65938581f9b819af555
Merge: b8edb40 7232e79
Author: Damian Johnson <atagar(a)torproject.org>
Date: Sat Feb 21 14:05:17 2015 -0800
Decorators for skipping tests
Using decorators like @require_controller for skipping our tests rather than
helper functions. This is a perfect use case for decorators, as it lets the
test content just be focused on what it should do.
https://trac.torproject.org/projects/tor/ticket/14945
test/integ/connection/authentication.py | 48 ++----
test/integ/connection/connect.py | 14 +-
test/integ/control/base_controller.py | 39 ++---
test/integ/control/controller.py | 224 +++++++------------------
test/integ/descriptor/extrainfo_descriptor.py | 8 +-
test/integ/descriptor/microdescriptor.py | 6 +-
test/integ/descriptor/networkstatus.py | 14 +-
test/integ/descriptor/remote.py | 61 +++----
test/integ/descriptor/server_descriptor.py | 8 +-
test/integ/process.py | 35 ++--
test/integ/response/protocolinfo.py | 17 +-
test/integ/socket/control_message.py | 32 ++--
test/integ/socket/control_socket.py | 30 +---
test/integ/version.py | 10 +-
test/runner.py | 71 ++++----
15 files changed, 214 insertions(+), 403 deletions(-)
1
0