[tor-commits] [ooni-probe/master] Make nettest and runner support test relative options.
art at torproject.org
art at torproject.org
Sat Oct 6 10:47:27 UTC 2012
commit c99b1657c35a2c83126001282fe01ecaee57b66f
Author: Arturo Filastò <arturo at filasto.net>
Date: Sat Oct 6 10:21:20 2012 +0000
Make nettest and runner support test relative options.
---
nettests/httphost.py | 124 ++++++++++++++++++++++++++++++++++++++++++++++
ooni/nettest.py | 2 +
ooni/plugins/httphost.py | 124 ----------------------------------------------
ooni/runner.py | 17 +++++-
4 files changed, 140 insertions(+), 127 deletions(-)
diff --git a/nettests/httphost.py b/nettests/httphost.py
new file mode 100644
index 0000000..b57a50d
--- /dev/null
+++ b/nettests/httphost.py
@@ -0,0 +1,124 @@
+"""
+ HTTP Host based filtering
+ *************************
+
+ This test detect HTTP Host field
+ based filtering.
+"""
+import os
+from datetime import datetime
+
+import urllib2
+import httplib
+try:
+ from BeautifulSoup import BeautifulSoup
+except:
+ print "Beautiful Soup not installed. HTTPHost may not work"
+
+# XXX reduce boilerplating.
+from zope.interface import implements
+from twisted.python import usage
+from twisted.plugin import IPlugin
+
+from ooni.plugoo.assets import Asset
+from ooni.plugoo.tests import ITest, OONITest
+
+class HTTPHostArgs(usage.Options):
+ optParameters = [['asset', 'a', None, 'Asset file'],
+ ['controlserver', 'c', 'google.com', 'Specify the control server'],
+ ['resume', 'r', 0, 'Resume at this index'],
+ ['other', 'o', None, 'Other arguments']]
+ def control(self, experiment_result, args):
+ print "Experiment Result:", experiment_result
+ print "Args", args
+ return experiment_result
+
+ def experiment(self, args):
+ import urllib
+ req = urllib.urlopen(args['asset'])
+ return {'page': req.readlines()}
+
+class HTTPHostAsset(Asset):
+ """
+ This is the asset that should be used by the Test. It will
+ contain all the code responsible for parsing the asset file
+ and should be passed on instantiation to the test.
+ """
+ def __init__(self, file=None):
+ self = Asset.__init__(self, file)
+
+ def parse_line(self, line):
+ return line.split(',')[1].replace('\n','')
+
+
+class HTTPHostTest(OONITest):
+ implements(IPlugin, ITest)
+
+ shortName = "httphost"
+ description = "HTTP Host plugin"
+ requirements = None
+ options = HTTPHostArgs
+ # Tells this to be blocking.
+ blocking = True
+
+ def check_response(self, response):
+ soup = BeautifulSoup(response)
+ if soup.head.title.string == "Blocked":
+ # Response indicates censorship
+ return True
+ else:
+ # Response does not indicate censorship
+ return False
+
+ def is_censored(self, response):
+ if response:
+ soup = BeautifulSoup(response)
+ censored = self.check_response(response)
+ else:
+ censored = "unreachable"
+ return censored
+
+ def urllib2_test(self, control_server, host):
+ req = urllib2.Request(control_server)
+ req.add_header('Host', host)
+ try:
+ r = urllib2.urlopen(req)
+ response = r.read()
+ censored = self.is_censored(response)
+ except Exception, e:
+ censored = "Error! %s" % e
+
+ return censored
+
+ def httplib_test(self, control_server, host):
+ censored = None
+ response = None
+ try:
+ conn = httplib.HTTPConnection(control_server)
+ conn.putrequest("GET", "", skip_host=True, skip_accept_encoding=True)
+ conn.putheader("Host", host)
+ conn.putheader("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.8.1.6")
+ conn.endheaders()
+ r = conn.getresponse()
+ response = r.read()
+ censored = self.is_censored(response)
+ except Exception, e:
+ censored = "Error! %s" % e
+
+ return (censored, response)
+
+ def experiment(self, args):
+ control_server = self.local_options['controlserver']
+ url = 'http://torproject.org/' if not 'asset' in args else args['asset']
+ censored = self.httplib_test(control_server, url)
+ return {'control': control_server,
+ 'host': url,
+ 'censored': censored}
+
+ def load_assets(self):
+ if self.local_options and self.local_options['asset']:
+ return {'asset': Asset(self.local_options['asset'])}
+ else:
+ return {}
+
+httphost = HTTPHostTest(None, None, None)
diff --git a/ooni/nettest.py b/ooni/nettest.py
index d88c044..a01050e 100644
--- a/ooni/nettest.py
+++ b/ooni/nettest.py
@@ -80,6 +80,8 @@ class TestCase(unittest.TestCase):
report = {}
report['errors'] = []
+ optParameters = None
+
def getOptions(self):
if self.inputFile:
fp = open(self.inputFile)
diff --git a/ooni/plugins/httphost.py b/ooni/plugins/httphost.py
deleted file mode 100644
index 7c783a1..0000000
--- a/ooni/plugins/httphost.py
+++ /dev/null
@@ -1,124 +0,0 @@
-"""
- HTTP Host based filtering
- *************************
-
- This test detect HTTP Host field
- based filtering.
-"""
-import os
-from datetime import datetime
-
-import urllib2
-import httplib
-try:
- from BeautifulSoup import BeautifulSoup
-except:
- print "Beautiful Soup not installed. HTTPHost may not work"
-
-# XXX reduce boilerplating.
-from zope.interface import implements
-from twisted.python import usage
-from twisted.plugin import IPlugin
-
-from plugoo.assets import Asset
-from plugoo.tests import ITest, OONITest
-
-class HTTPHostArgs(usage.Options):
- optParameters = [['asset', 'a', None, 'Asset file'],
- ['controlserver', 'c', 'google.com', 'Specify the control server'],
- ['resume', 'r', 0, 'Resume at this index'],
- ['other', 'o', None, 'Other arguments']]
- def control(self, experiment_result, args):
- print "Experiment Result:", experiment_result
- print "Args", args
- return experiment_result
-
- def experiment(self, args):
- import urllib
- req = urllib.urlopen(args['asset'])
- return {'page': req.readlines()}
-
-class HTTPHostAsset(Asset):
- """
- This is the asset that should be used by the Test. It will
- contain all the code responsible for parsing the asset file
- and should be passed on instantiation to the test.
- """
- def __init__(self, file=None):
- self = Asset.__init__(self, file)
-
- def parse_line(self, line):
- return line.split(',')[1].replace('\n','')
-
-
-class HTTPHostTest(OONITest):
- implements(IPlugin, ITest)
-
- shortName = "httphost"
- description = "HTTP Host plugin"
- requirements = None
- options = HTTPHostArgs
- # Tells this to be blocking.
- blocking = True
-
- def check_response(self, response):
- soup = BeautifulSoup(response)
- if soup.head.title.string == "Blocked":
- # Response indicates censorship
- return True
- else:
- # Response does not indicate censorship
- return False
-
- def is_censored(self, response):
- if response:
- soup = BeautifulSoup(response)
- censored = self.check_response(response)
- else:
- censored = "unreachable"
- return censored
-
- def urllib2_test(self, control_server, host):
- req = urllib2.Request(control_server)
- req.add_header('Host', host)
- try:
- r = urllib2.urlopen(req)
- response = r.read()
- censored = self.is_censored(response)
- except Exception, e:
- censored = "Error! %s" % e
-
- return censored
-
- def httplib_test(self, control_server, host):
- censored = None
- response = None
- try:
- conn = httplib.HTTPConnection(control_server)
- conn.putrequest("GET", "", skip_host=True, skip_accept_encoding=True)
- conn.putheader("Host", host)
- conn.putheader("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-GB; rv:1.8.1.6")
- conn.endheaders()
- r = conn.getresponse()
- response = r.read()
- censored = self.is_censored(response)
- except Exception, e:
- censored = "Error! %s" % e
-
- return (censored, response)
-
- def experiment(self, args):
- control_server = self.local_options['controlserver']
- url = 'http://torproject.org/' if not 'asset' in args else args['asset']
- censored = self.httplib_test(control_server, url)
- return {'control': control_server,
- 'host': url,
- 'censored': censored}
-
- def load_assets(self):
- if self.local_options and self.local_options['asset']:
- return {'asset': Asset(self.local_options['asset'])}
- else:
- return {}
-
-httphost = HTTPHostTest(None, None, None)
diff --git a/ooni/runner.py b/ooni/runner.py
index 8ed844d..c6958bc 100644
--- a/ooni/runner.py
+++ b/ooni/runner.py
@@ -5,7 +5,7 @@ import time
import inspect
from twisted.internet import defer, reactor
-from twisted.python import reflect, failure
+from twisted.python import reflect, failure, usage
from twisted.trial import unittest
from twisted.trial.runner import TrialRunner, TestLoader
@@ -91,6 +91,16 @@ def adaptLegacyTest(obj, config):
return LegacyOONITest
+def processTest(obj, config):
+ if obj.optParameters:
+ class Options(usage.Options):
+ optParameters = obj.optParameters
+
+ options = Options()
+ options.parseOptions(config['subArgs'])
+
+ obj.localOptions = options
+ return obj
def findTestClassesFromConfig(config):
"""
@@ -106,7 +116,7 @@ def findTestClassesFromConfig(config):
module = filenameToModule(filename)
for name, val in inspect.getmembers(module):
if isTestCase(val):
- classes.append(val)
+ classes.append(processTest(val, config))
elif isLegacyTest(val):
classes.append(adaptLegacyTest(val, config))
return classes
@@ -135,7 +145,8 @@ def loadTestsAndOptions(classes):
for klass in classes:
try:
k = klass()
- options.append(k.getOptions())
+ opts = k.getOptions()
+ options.append(opts)
except AttributeError:
options.append([])
More information about the tor-commits
mailing list