[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [ooni-probe/master] Import basic stuff from Twisted trial
commit c4ad2411046deb08f17902320cb8dd21cc25f367
Author: Arturo Filastò <arturo@xxxxxxxxxxx>
Date: Tue Sep 11 10:38:35 2012 +0000
Import basic stuff from Twisted trial
---
.gitignore | 1 +
README.md | 10 +
bin/ooniprobe | 16 ++-
ooni/oonicli.py | 397 +++++++++++++++++++++++++++++++++++++++++++
ooni/oonitests/bridget.py | 373 ----------------------------------------
ooni/plugins/new_bridget.py | 2 +-
ooni/protocols/http.py | 13 +-
ooni/reporter.py | 13 ++
ooni/runner.py | 7 +
9 files changed, 448 insertions(+), 384 deletions(-)
diff --git a/.gitignore b/.gitignore
index 7f270bb..6b1b9ce 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,4 @@ proxy-lists/italy-http-ips.txt
private/*
/ooni/plugins/dropin.cache
oonib/oonibackend.conf
+ooni/assets/*
diff --git a/README.md b/README.md
index b39cb2b..123d837 100644
--- a/README.md
+++ b/README.md
@@ -28,6 +28,16 @@ To list the help for a specific test:
python ooniprobe.py httpt --help
+## Virtualenv way (Recommended)
+
+ virtualenv2 ENV/
+ source ENV/bin/activate
+ pip install twisted Scapy
+
+To install the most up to date scapy version (requires mercurial):
+
+ pip install hg+http://hg.secdev.org/scapy
+
# More details
diff --git a/bin/ooniprobe b/bin/ooniprobe
index 5c87831..1f0c26d 100755
--- a/bin/ooniprobe
+++ b/bin/ooniprobe
@@ -1,5 +1,11 @@
-#!/bin/sh
-ROOT="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-echo $ROOT
-export PYTHONPATH=$PYTHONPATH:$ROOT
-python $ROOT/ooni/ooniprobe.py $1
+#!/usr/bin/python2
+# startup script based on twisted trial
+# See http://twistedmatrix.com/
+import os, sys
+
+sys.path[:] = map(os.path.abspath, sys.path)
+
+sys.path.insert(0, os.path.abspath(os.getcwd()))
+
+from ooni.oonicli import run
+run()
diff --git a/ooni/oonicli.py b/ooni/oonicli.py
new file mode 100644
index 0000000..8ace160
--- /dev/null
+++ b/ooni/oonicli.py
@@ -0,0 +1,397 @@
+#!/usr/bin/env python
+# -*- coding: UTF-8
+#
+# oonicli
+# *********
+#
+# oonicli is the next generation ooniprober. It based off of twisted's trial
+# unit testing framework.
+#
+# :copyright: (c) 2012 by Arturo Filastò
+# :license: see LICENSE for more details.
+#
+# original copyright (c) by Twisted Matrix Laboratories.
+
+
+import sys, os, random, gc, time, warnings
+
+from twisted.internet import defer
+from twisted.application import app
+from twisted.python import usage, reflect, failure
+from twisted.python.filepath import FilePath
+from twisted import plugin
+from twisted.python.util import spewer
+from twisted.python.compat import set
+from twisted.trial import runner, itrial, reporter
+
+
+# Yea, this is stupid. Leave it for for command-line compatibility for a
+# while, though.
+TBFORMAT_MAP = {
+ 'plain': 'default',
+ 'default': 'default',
+ 'emacs': 'brief',
+ 'brief': 'brief',
+ 'cgitb': 'verbose',
+ 'verbose': 'verbose'
+ }
+
+
+def _parseLocalVariables(line):
+ """
+ Accepts a single line in Emacs local variable declaration format and
+ returns a dict of all the variables {name: value}.
+ Raises ValueError if 'line' is in the wrong format.
+
+ See http://www.gnu.org/software/emacs/manual/html_node/File-Variables.html
+ """
+ paren = '-*-'
+ start = line.find(paren) + len(paren)
+ end = line.rfind(paren)
+ if start == -1 or end == -1:
+ raise ValueError("%r not a valid local variable declaration" % (line,))
+ items = line[start:end].split(';')
+ localVars = {}
+ for item in items:
+ if len(item.strip()) == 0:
+ continue
+ split = item.split(':')
+ if len(split) != 2:
+ raise ValueError("%r contains invalid declaration %r"
+ % (line, item))
+ localVars[split[0].strip()] = split[1].strip()
+ return localVars
+
+
+def loadLocalVariables(filename):
+ """
+ Accepts a filename and attempts to load the Emacs variable declarations
+ from that file, simulating what Emacs does.
+
+ See http://www.gnu.org/software/emacs/manual/html_node/File-Variables.html
+ """
+ f = file(filename, "r")
+ lines = [f.readline(), f.readline()]
+ f.close()
+ for line in lines:
+ try:
+ return _parseLocalVariables(line)
+ except ValueError:
+ pass
+ return {}
+
+
+def getTestModules(filename):
+ testCaseVar = loadLocalVariables(filename).get('test-case-name', None)
+ if testCaseVar is None:
+ return []
+ return testCaseVar.split(',')
+
+
+def isTestFile(filename):
+ """
+ Returns true if 'filename' looks like a file containing unit tests.
+ False otherwise. Doesn't care whether filename exists.
+ """
+ basename = os.path.basename(filename)
+ return (basename.startswith('test_')
+ and os.path.splitext(basename)[1] == ('.py'))
+
+
+def _reporterAction():
+ return usage.CompleteList([p.longOpt for p in
+ plugin.getPlugins(itrial.IReporter)])
+
+class Options(usage.Options):
+
+ optParameters = [
+ ['parallelism', 'n', 10, "Specify the number of parallel tests to run"],
+ ['output', 'o', 'report.log', "Specify output report file"],
+ ['log', 'l', 'oonicli.log', "Specify output log file"]
+ ]
+
+ def opt_version(self):
+ """
+ Display OONI version and exit.
+ """
+ print "OONI version:", __version__
+ sys.exit(0)
+
+
+class Options(usage.Options, app.ReactorSelectionMixin):
+ synopsis = """%s [options] [[file|package|module|TestCase|testmethod]...]
+ """ % (os.path.basename(sys.argv[0]),)
+
+ longdesc = ("ooniprobe loads and executes a suite or a set of suites of"
+ "network tests. These are loaded from modules, packages and"
+ "files listed on the command line")
+
+ optFlags = [["help", "h"],
+ ["rterrors", "e", "realtime errors, print out tracebacks as "
+ "soon as they occur"],
+ ["debug", "b", "Run tests in the Python debugger. Will load "
+ "'.pdbrc' from current directory if it exists."],
+ ["debug-stacktraces", "B", "Report Deferred creation and "
+ "callback stack traces"],
+ ["nopm", None, "don't automatically jump into debugger for "
+ "postmorteming of exceptions"],
+ ["dry-run", 'n', "do everything but run the tests"],
+ ["force-gc", None, "Have Trial run gc.collect() before and "
+ "after each test case."],
+ ["profile", None, "Run tests under the Python profiler"],
+ ["unclean-warnings", None,
+ "Turn dirty reactor errors into warnings"],
+ ["until-failure", "u", "Repeat test until it fails"],
+ ["no-recurse", "N", "Don't recurse into packages"],
+ ['help-reporters', None,
+ "Help on available output plugins (reporters)"]
+ ]
+
+ optParameters = [
+ ["logfile", "l", "test.log", "log file name"],
+ ["random", "z", None,
+ "Run tests in random order using the specified seed"],
+ ['temp-directory', None, '_trial_temp',
+ 'Path to use as working directory for tests.'],
+ ['reporter', None, 'verbose',
+ 'The reporter to use for this test run. See --help-reporters for '
+ 'more info.']]
+
+ compData = usage.Completions(
+ optActions={"tbformat": usage.CompleteList(["plain", "emacs", "cgitb"]),
+ "reporter": _reporterAction,
+ "logfile": usage.CompleteFiles(descr="log file name"),
+ "random": usage.Completer(descr="random seed")},
+ extraActions=[usage.CompleteFiles(
+ "*.py", descr="file | module | package | TestCase | testMethod",
+ repeat=True)],
+ )
+
+ fallbackReporter = reporter.TreeReporter
+ tracer = None
+
+ def __init__(self):
+ self['tests'] = set()
+ usage.Options.__init__(self)
+
+
+ def coverdir(self):
+ """
+ Return a L{FilePath} representing the directory into which coverage
+ results should be written.
+ """
+ coverdir = 'coverage'
+ result = FilePath(self['temp-directory']).child(coverdir)
+ print "Setting coverage directory to %s." % (result.path,)
+ return result
+
+
+ def opt_coverage(self):
+ """
+ Generate coverage information in the I{coverage} file in the
+ directory specified by the I{trial-temp} option.
+ """
+ import trace
+ self.tracer = trace.Trace(count=1, trace=0)
+ sys.settrace(self.tracer.globaltrace)
+
+
+ def opt_testmodule(self, filename):
+ """
+ Filename to grep for test cases (-*- test-case-name)
+ """
+ # If the filename passed to this parameter looks like a test module
+ # we just add that to the test suite.
+ #
+ # If not, we inspect it for an Emacs buffer local variable called
+ # 'test-case-name'. If that variable is declared, we try to add its
+ # value to the test suite as a module.
+ #
+ # This parameter allows automated processes (like Buildbot) to pass
+ # a list of files to Trial with the general expectation of "these files,
+ # whatever they are, will get tested"
+ if not os.path.isfile(filename):
+ sys.stderr.write("File %r doesn't exist\n" % (filename,))
+ return
+ filename = os.path.abspath(filename)
+ if isTestFile(filename):
+ self['tests'].add(filename)
+ else:
+ self['tests'].update(getTestModules(filename))
+
+
+ def opt_spew(self):
+ """
+ Print an insanely verbose log of everything that happens. Useful
+ when debugging freezes or locks in complex code.
+ """
+ sys.settrace(spewer)
+
+
+ def opt_help_reporters(self):
+ synopsis = ("OONI's output can be customized using plugins called "
+ "Reporters. You can\nselect any of the following "
+ "reporters using --reporter=<foo>\n")
+ print synopsis
+ for p in plugin.getPlugins(itrial.IReporter):
+ print ' ', p.longOpt, '\t', p.description
+ print
+ sys.exit(0)
+
+
+ def opt_disablegc(self):
+ """
+ Disable the garbage collector
+ """
+ gc.disable()
+
+
+ def opt_tbformat(self, opt):
+ """
+ Specify the format to display tracebacks with. Valid formats are
+ 'plain', 'emacs', and 'cgitb' which uses the nicely verbose stdlib
+ cgitb.text function
+ """
+ try:
+ self['tbformat'] = TBFORMAT_MAP[opt]
+ except KeyError:
+ raise usage.UsageError(
+ "tbformat must be 'plain', 'emacs', or 'cgitb'.")
+
+
+ def opt_recursionlimit(self, arg):
+ """
+ see sys.setrecursionlimit()
+ """
+ try:
+ sys.setrecursionlimit(int(arg))
+ except (TypeError, ValueError):
+ raise usage.UsageError(
+ "argument to recursionlimit must be an integer")
+
+
+ def opt_random(self, option):
+ try:
+ self['random'] = long(option)
+ except ValueError:
+ raise usage.UsageError(
+ "Argument to --random must be a positive integer")
+ else:
+ if self['random'] < 0:
+ raise usage.UsageError(
+ "Argument to --random must be a positive integer")
+ elif self['random'] == 0:
+ self['random'] = long(time.time() * 100)
+
+
+ def opt_without_module(self, option):
+ """
+ Fake the lack of the specified modules, separated with commas.
+ """
+ for module in option.split(","):
+ if module in sys.modules:
+ warnings.warn("Module '%s' already imported, "
+ "disabling anyway." % (module,),
+ category=RuntimeWarning)
+ sys.modules[module] = None
+
+
+ def parseArgs(self, *args):
+ self['tests'].update(args)
+
+
+ def _loadReporterByName(self, name):
+ for p in plugin.getPlugins(itrial.IReporter):
+ qual = "%s.%s" % (p.module, p.klass)
+ if p.longOpt == name:
+ return reflect.namedAny(qual)
+ raise usage.UsageError("Only pass names of Reporter plugins to "
+ "--reporter. See --help-reporters for "
+ "more info.")
+
+
+ def postOptions(self):
+ # Only load reporters now, as opposed to any earlier, to avoid letting
+ # application-defined plugins muck up reactor selecting by importing
+ # t.i.reactor and causing the default to be installed.
+ self['reporter'] = self._loadReporterByName(self['reporter'])
+
+ if 'tbformat' not in self:
+ self['tbformat'] = 'default'
+ if self['nopm']:
+ if not self['debug']:
+ raise usage.UsageError("you must specify --debug when using "
+ "--nopm ")
+ failure.DO_POST_MORTEM = False
+
+
+
+def _initialDebugSetup(config):
+ # do this part of debug setup first for easy debugging of import failures
+ if config['debug']:
+ failure.startDebugMode()
+ if config['debug'] or config['debug-stacktraces']:
+ defer.setDebugging(True)
+
+
+
+def _getSuite(config):
+ loader = _getLoader(config)
+ recurse = not config['no-recurse']
+ return loader.loadByNames(config['tests'], recurse)
+
+
+
+def _getLoader(config):
+ loader = runner.TestLoader()
+ if config['random']:
+ randomer = random.Random()
+ randomer.seed(config['random'])
+ loader.sorter = lambda x : randomer.random()
+ print 'Running tests shuffled with seed %d\n' % config['random']
+ if not config['until-failure']:
+ loader.suiteFactory = runner.DestructiveTestSuite
+ return loader
+
+
+
+def _makeRunner(config):
+ mode = None
+ if config['debug']:
+ mode = runner.TrialRunner.DEBUG
+ if config['dry-run']:
+ mode = runner.TrialRunner.DRY_RUN
+ return runner.TrialRunner(config['reporter'],
+ mode=mode,
+ profile=config['profile'],
+ logfile=config['logfile'],
+ tracebackFormat=config['tbformat'],
+ realTimeErrors=config['rterrors'],
+ uncleanWarnings=config['unclean-warnings'],
+ workingDirectory=config['temp-directory'],
+ forceGarbageCollection=config['force-gc'])
+
+
+
+def run():
+ if len(sys.argv) == 1:
+ sys.argv.append("--help")
+ config = Options()
+ try:
+ config.parseOptions()
+ except usage.error, ue:
+ raise SystemExit, "%s: %s" % (sys.argv[0], ue)
+ _initialDebugSetup(config)
+ trialRunner = _makeRunner(config)
+ suite = _getSuite(config)
+ if config['until-failure']:
+ test_result = trialRunner.runUntilFailure(suite)
+ else:
+ test_result = trialRunner.run(suite)
+ if config.tracer:
+ sys.settrace(None)
+ results = config.tracer.results()
+ results.write_results(show_missing=1, summary=False,
+ coverdir=config.coverdir().path)
+ sys.exit(not test_result.wasSuccessful())
+
diff --git a/ooni/oonitests/bridget.py b/ooni/oonitests/bridget.py
deleted file mode 100644
index a613f61..0000000
--- a/ooni/oonitests/bridget.py
+++ /dev/null
@@ -1,373 +0,0 @@
-# -*- coding: UTF-8
-"""
- bridgeT
- *******
-
- an OONI test (we call them Plugoos :P) aimed
- at detecting if a set of Tor bridges are working or not.
-
- :copyright: (c) 2012 by Arturo Filastò
- :license: BSD, see LICENSE for more details.
-"""
-import os
-import sys
-import errno
-import time
-import random
-import re
-import glob
-import socks
-import socket
-from shutil import rmtree
-from subprocess import Popen, PIPE
-from datetime import datetime
-
-import shutil
-import gevent
-from gevent import socket
-import fcntl
-from plugoo.assets import Asset
-from plugoo.tests import Test
-import urllib2
-import httplib
-import json
-
-try:
- from TorCtl import TorCtl
-except:
- print "Error TorCtl not installed!"
-
-__plugoo__ = "BridgeT"
-__desc__ = "BridgeT, for testing Tor Bridge reachability"
-ONIONOO_URL="http://85.214.195.203/summary/search/"
-
-class SocksiPyConnection(httplib.HTTPConnection):
- def __init__(self, proxytype, proxyaddr, proxyport = None, rdns = True,
- username = None, password = None, *args, **kwargs):
- self.proxyargs = (proxytype, proxyaddr, proxyport, rdns, username, password)
- httplib.HTTPConnection.__init__(self, *args, **kwargs)
-
- def connect(self):
- self.sock = socks.socksocket()
- self.sock.setproxy(*self.proxyargs)
- if isinstance(self.timeout, float):
- self.sock.settimeout(self.timeout)
- self.sock.connect((self.host, self.port))
-
-class SocksiPyHandler(urllib2.HTTPHandler):
- def __init__(self, *args, **kwargs):
- self.args = args
- self.kw = kwargs
- urllib2.HTTPHandler.__init__(self)
-
- def http_open(self, req):
- def build(host, port=None, strict=None, timeout=0):
- conn = SocksiPyConnection(*self.args, host=host, port=port,
- strict=strict, timeout=timeout, **self.kw)
- return conn
- return self.do_open(build, req)
-
-class BridgeTAsset(Asset):
- def __init__(self, file=None):
- self = Asset.__init__(self, file)
-
-class BridgeT(Test):
- # This is the timeout value after which
- # we will give up
- timeout = 20
- # These are the modules that should be torified
- modules = [urllib2]
-
- def tor_greater_than(self, version):
- """
- Checks if the currently installed version of Tor is greater
- than the required version.
-
- :version The version of Tor to check against for greater than or equal
- """
- fullstring = os.popen("tor --version").read().split('\n')[-2]
- v_array = fullstring.split(' ')[2].split('-')
- minor = v_array[1:]
- v_array = v_array[0].split('.')
- minor_p = version.split('-')[1:]
- v_array_p = version.split('-')[0].split('.')
-
- for i, x in enumerate(v_array):
- try:
- if i > len(v_array_p):
- break
-
- if int(x) > int(v_array_p[i]):
- self.logger.debug("The Tor version is greater than %s" % version)
- return True
- elif int(x) == int(v_array_p[i]):
- self.logger.debug("The Tor version is greater than %s" % version)
- continue
- else:
- self.logger.debug("You run an outdated version of Tor: %s (< %s)" % (fullstring, version))
- return False
- except:
- self.logger.error("Error in parsing your Tor version string: %s" % fullstring)
- return False
-
- self.logger.debug("The Tor version is equal to %s" % version)
- return True
- # XXX currently don't consider the minor parts of the version
- # (alpha, dev, beta, etc.)
-
- def free_port(self, port):
- s = socket.socket()
- try:
- s.bind(('127.0.0.1', port))
- s.close()
- return True
- except:
- self.logger.warn("The randomly chosen port was already taken!")
- s.close()
- return False
-
- def writetorrc(self, bridge):
- """
- Write the torrc file for the tor process to be used
- to test the bridge.
-
- :bridge the bridge to be tested
- """
- self.failures = []
- prange = (49152, 65535)
-
- # register Tor to an ephemeral port
- socksport = random.randint(prange[0], prange[1])
- # Keep on trying to get a new port if the chosen one is already
- # taken.
- while not self.free_port(socksport):
- socksport = random.randint(prange[0], prange[1])
- controlport = random.randint(prange[0], prange[1])
- while not self.free_port(controlport):
- controlport = random.randint(prange[0], prange[1])
-
- randomname = "tor_"+str(random.randint(0, 424242424242))
- datadir = "/tmp/" + randomname
- if bridge.startswith("obfs://"):
- obfsbridge = bridge.split("//")[1]
-
- self.logger.debug("Genearting torrc file for obfs bridge")
- torrc = """SocksPort %s
-UseBridges 1
-Bridge obfs2 %s
-DataDirectory %s
-ClientTransportPlugin obfs2 exec /usr/local/bin/obfsproxy --managed
-ControlPort %s
-Log info file %s
-""" % (socksport, obfsbridge, datadir, controlport, os.path.join(datadir,'tor.log'))
- else:
- self.logger.debug("Generating torrc file for bridge")
- if self.tor_greater_than('0.2.3.2'):
-
- torrc = """SocksPort %s
-UseBridges 1
-bridge %s
-DataDirectory %s
-usemicrodescriptors 0
-ControlPort %s
-Log info file %s
-""" % (socksport, bridge, datadir, controlport, os.path.join(datadir,'tor.log'))
- else:
- torrc = """SocksPort %s
-UseBridges 1
-bridge %s
-DataDirectory %s
-ControlPort %s
-Log info file %s
-""" % (socksport, bridge, datadir, controlport, os.path.join(datadir,'tor.log'))
-
- with open(randomname, "wb") as f:
- f.write(torrc)
-
- os.mkdir(datadir)
- return (randomname, datadir, controlport, socksport)
-
- def parsebridgeinfo(self, output):
- ret = {}
- fields = ['router', 'platform', 'opt', 'published', 'uptime', 'bandwidth']
-
- for x in output.split("\n"):
- cfield = x.split(' ')
- if cfield[0] in fields:
- #not sure if hellais did this on purpose, but this overwrites
- #the previous entries. For ex, 'opt' has multiple entries and
- #only the last value is stored
- ret[cfield[0]] = ' '.join(cfield[1:])
- if cfield[1] == 'fingerprint':
- ret['fingerprint'] = ''.join(cfield[2:])
- return ret
-
- #Can't use @torify as it doesn't support concurrency right now
- def download_file(self, socksport):
- opener = urllib2.build_opener(SocksiPyHandler(socks.PROXY_TYPE_SOCKS5,
- '127.0.0.1', int(socksport)))
-
- time_start=time.time()
- f = opener.open('http://38.229.72.16/bwauth.torproject.org/256k')
- f.read()
- time_end = time.time()
- print (time_end-time_start)
- return str(256/(time_end-time_start)) + " KB/s"
-
- def is_public(self, fp, socksport):
- opener = urllib2.build_opener(SocksiPyHandler(socks.PROXY_TYPE_SOCKS5,'127.0.0.1',int(socksport)))
- response = opener.open(str(ONIONOO_URL)+str(fp))
- reply = json.loads(response.read())
- if reply['bridges'] or reply['relays']:
- return True
- return False
-
- def connect(self, bridge, timeout=None):
- bridgeinfo = None
- bandwidth = None
- public = None
- if not timeout:
- if self.config.tests.tor_bridges_timeout:
- self.timeout = self.config.tests.tor_bridges_timeout
- timeout = self.timeout
- torrc, tordir, controlport, socksport = self.writetorrc(bridge)
- cmd = ["tor", "-f", torrc]
-
- tupdate = time.time()
- debugupdate = time.time()
-
- try:
- p = Popen(cmd, stdout=PIPE)
- except:
- self.logger.error("Error in starting Tor (do you have tor installed?)")
-
- self.logger.info("Testing bridge: %s" % bridge)
- while True:
- o = ""
- try:
- o = p.stdout.read(4096)
- if o:
- self.logger.debug(str(o))
- if re.search("100%", o):
- self.logger.info("Success in connecting to %s" % bridge)
-
- print "%s bridge works" % bridge
- # print "%s controlport" % controlport
- try:
- c = TorCtl.connect('127.0.0.1', controlport)
- bridgeinfo = self.parsebridgeinfo(c.get_info('dir/server/all')['dir/server/all'])
- c.close()
- except:
- self.logger.error("Error in connecting to Tor Control port")
-
- # XXX disable the public checking
- #public = self.is_public(bridgeinfo['fingerprint'], socksport)
- #self.logger.info("Public: %s" % public)
-
- bandwidth = self.download_file(socksport)
- self.logger.info("Bandwidth: %s" % bandwidth)
-
- try:
- p.stdout.close()
- except:
- self.logger.error("Error in closing stdout FD.")
-
- try:
- os.unlink(os.path.join(os.getcwd(), torrc))
- rmtree(tordir)
- except:
- self.logger.error("Error in unlinking files.")
-
- p.terminate()
- return {
- 'Time': datetime.now(),
- 'Bridge': bridge,
- 'Working': True,
- 'Descriptor': bridgeinfo,
- 'Calculated bandwidth': bandwidth,
- 'Public': public
- }
-
- if re.search("%", o):
- # Keep updating the timeout if there is progress
- self.logger.debug("Updating time...")
- tupdate = time.time()
- #print o
- continue
-
- except IOError:
- ex = sys.exc_info()[1]
- if ex[0] != errno.EAGAIN:
- self.logger.error("Error IOError: EAGAIN")
- raise
- sys.exc_clear()
- print "In this exception 1"
-
- try:
- # Set the timeout for the socket wait
- ct = timeout-(time.time() - tupdate)
- socket.wait_read(p.stdout.fileno(), timeout=ct)
-
- except:
- lfh = open(os.path.join(tordir, 'tor.log'), 'r')
- log = lfh.readlines()
- lfh.close()
- self.logger.info("%s bridge does not work (%s s timeout)" % (bridge, timeout))
- print "%s bridge does not work (%s s timeout)" % (bridge, timeout)
- self.failures.append(bridge)
- p.stdout.close()
- os.unlink(os.path.join(os.getcwd(), torrc))
- rmtree(tordir)
- p.terminate()
- return {
- 'Time': datetime.now(),
- 'Bridge': bridge,
- 'Working': False,
- 'Descriptor': {},
- 'Log': log
- }
-
- def experiment(self, *a, **kw):
- # this is just a dirty hack
- bridge = kw['data']
- print "Experiment"
- config = self.config
-
- return self.connect(bridge)
-
- def clean(self):
- for infile in glob.glob('tor_*'):
- os.remove(infile)
-
- def print_failures(self):
- if self.failures:
- for item in self.failures:
- print "Offline : %s" % item
- else:
- print "All online"
-
- # For logging TorCtl event msgs
- #class LogHandler:
- #def msg(self, severity, message):
- # print "[%s] %s"%(severity, message)
-
-def run(ooni, assets=None):
- """
- Run the test
- """
-
- config = ooni.config
- urls = []
-
- bridges = BridgeTAsset(os.path.join(config.main.assetdir, \
- config.tests.tor_bridges))
-
- bridgelist = [bridges]
-
- bridget = BridgeT(ooni)
- ooni.logger.info("Starting bridget test")
- bridget.run(bridgelist)
- bridget.print_failures()
- bridget.clean()
- ooni.logger.info("Testing completed!")
-
diff --git a/ooni/plugins/new_bridget.py b/ooni/plugins/new_bridget.py
index 3e4db56..b26455e 100644
--- a/ooni/plugins/new_bridget.py
+++ b/ooni/plugins/new_bridget.py
@@ -27,7 +27,7 @@ class bridgetArgs(usage.Options):
class bridgetTest(OONITest):
implements(IPlugin, ITest)
- shortName = "bridget"
+ shortName = "newbridget"
description = "bridget"
requirements = None
options = bridgetArgs
diff --git a/ooni/protocols/http.py b/ooni/protocols/http.py
index 2b38f28..09bb9b9 100644
--- a/ooni/protocols/http.py
+++ b/ooni/protocols/http.py
@@ -84,11 +84,7 @@ class HTTPTest(OONITest):
"""
pass
-
- def experiment(self, args):
- log.msg("Running experiment")
- url = self.local_options['url'] if 'url' not in args else args['url']
-
+ def doRequest(self, url):
d = self.build_request(url)
def finished(data):
return data
@@ -97,6 +93,13 @@ class HTTPTest(OONITest):
d.addCallback(finished)
return d
+ def experiment(self, args):
+ log.msg("Running experiment")
+ url = self.local_options['url'] if 'url' not in args else args['url']
+
+ d = self.doRequest(url)
+ return d
+
def _cbResponse(self, response):
self.response['headers'] = list(response.headers.getAllRawHeaders())
self.response['code'] = response.code
diff --git a/ooni/reporter.py b/ooni/reporter.py
new file mode 100644
index 0000000..0ecf2ea
--- /dev/null
+++ b/ooni/reporter.py
@@ -0,0 +1,13 @@
+from twisted.trial import reporter
+
+class TestResult(reporter.TestResult):
+ """
+ Accumulates the results of several ooni.nettest.TestCases.
+
+ The output format of a TestResult is YAML and it will contain all the basic
+ information that a test result should contain.
+ """
+ def __init__(self):
+ super(TestResult, self).__init__()
+
+
diff --git a/ooni/runner.py b/ooni/runner.py
new file mode 100644
index 0000000..d7caa9d
--- /dev/null
+++ b/ooni/runner.py
@@ -0,0 +1,7 @@
+from twisted.trial import runner
+
+
+class TestLoader(runner.TestLoader):
+ pass
+
+
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits