commit e7ac9808ac51ac0e06f8ef8091b83c1e30e7c9e5 Author: Arturo Filastò art@fuffa.org Date: Mon Mar 10 18:47:00 2014 +0100
Add support for displaying a summary of the test results to bridge reachability test. --- ooni/nettest.py | 27 ++++++++++++- ooni/nettests/blocking/bridge_reachability.py | 54 ++++++++++++++++++++++++- 2 files changed, 78 insertions(+), 3 deletions(-)
diff --git a/ooni/nettest.py b/ooni/nettest.py index 235ad85..520fcf8 100644 --- a/ooni/nettest.py +++ b/ooni/nettest.py @@ -388,6 +388,9 @@ class NetTestLoader(object): self.testVersion = test_class.version self.testName = test_class_name_to_name(test_class.name) self.testCases = test_cases + self.testClasses = set([]) + for test_class, test_method in self.testCases: + self.testClasses.add(test_class)
def checkOptions(self): """ @@ -397,7 +400,7 @@ class NetTestLoader(object): for test_class, test_method in self.testCases: test_classes.add(test_class)
- for klass in test_classes: + for klass in self.testClasses: options = self.usageOptions() options.parseOptions(self.options)
@@ -488,13 +491,25 @@ class NetTest(object): """ self.report = report self.testCases = net_test_loader.testCases + self.testClasses = net_test_loader.testClasses + self.testDetails = net_test_loader.testDetails + + self.summary = {}
# This will fire when all the measurements have been completed and # all the reports are done. Done means that they have either completed # successfully or all the possible retries have been reached. self.done = defer.Deferred() + self.done.addCallback(self.doneNetTest)
self.state = NetTestState(self.done) + + def doneNetTest(self, result): + print "Summary for %s" % self.testDetails['test_name'] + print "------------" + "-"*len(self.testDetails['test_name']) + for test_class in self.testClasses: + test_instance = test_class() + test_instance.displaySummary(self.summary)
def doneReport(self, report_results): """ @@ -556,6 +571,7 @@ class NetTest(object): for input in test_class.inputs: measurements = [] test_instance = test_class() + test_instance.summary = self.summary for method in test_methods: log.debug("Running %s %s" % (test_class, method)) measurement = self.makeMeasurement(test_instance, method, input) @@ -674,9 +690,18 @@ class NetTestCase(object): postProcessing works exactly like test methods, in the sense that anything that gets written to the object self.report[] will be added to the final test report. + You should also place in this method any logic that is required for + generating the summary. """ raise e.NoPostProcessor
+ def displaySummary(self): + """ + This gets called after the test has run to allow printing out of a + summary of the test run. + """ + pass + def inputProcessor(self, filename): """ You may replace this with your own custom input processor. It takes as diff --git a/ooni/nettests/blocking/bridge_reachability.py b/ooni/nettests/blocking/bridge_reachability.py index 7c519ec..98d7e9a 100644 --- a/ooni/nettests/blocking/bridge_reachability.py +++ b/ooni/nettests/blocking/bridge_reachability.py @@ -34,12 +34,59 @@ class BridgeReachability(nettest.NetTestCase): def setUp(self): self.tor_progress = 0 self.timeout = int(self.localOptions['timeout']) + self.report['timeout'] = self.timeout + self.report['transport_name'] = 'vanilla' + self.report['tor_progress'] = None + self.report['tor_progress_tag'] = None + self.report['tor_progress_summary'] = None + self.report['bridge_address'] = None + self.bridge = self.input if self.input.startswith('Bridge'): self.bridge = self.input.replace('Bridge ', '') self.pyobfsproxy_bin = find_executable('obfsproxy')
+ def postProcessor(self, measurements): + if 'successes' not in self.summary: + self.summary['successes'] = [] + if 'failures' not in self.summary: + self.summary['failures'] = [] + + details = { + 'address': self.report['bridge_address'], + 'transport_name': self.report['transport_name'] + } + if self.report['success']: + self.summary['successes'].append(details) + else: + self.summary['failures'].append(details) + + def displaySummary(self, summary): + successful_count = {} + failure_count = {} + def count(results, counter): + for result in results: + if result['transport_name'] not in counter: + counter[result['transport_name']] = 0 + counter[result['transport_name']] += 1 + count(summary['successes'], successful_count) + count(summary['failures'], failure_count) + + working_bridges = ', '.join([x['address'] for x in summary['successes']]) + failing_bridges = ', '.join([x['address'] for x in summary['failures']]) + + print "Total successes: %d" % len(summary['successes']) + print "Total failures: %d" % len(summary['failures']) + + for transport, count in successful_count.items(): + print "%s successes: %d" % (transport.title(), count) + for transport, count in failure_count.items(): + print "%s failures: %d" % (transport.title(), count) + + print "Working bridges: %s" % working_bridges + print "Failing bridges: %s" % failing_bridges + def test_full_tor_connection(self): def getTransport(address): """ @@ -59,22 +106,25 @@ class BridgeReachability(nettest.NetTestCase): config = txtorcon.TorConfig() config.ControlPort = random.randint(2**14, 2**16) config.SocksPort = random.randint(2**14, 2**16) - + transport_name = getTransport(self.bridge) if transport_name and self.pyobfsproxy_bin: config.ClientTransportPlugin = "%s exec %s managed" % (transport_name, self.pyobfsproxy_bin) self.report['transport_name'] = transport_name + self.report['bridge_address'] = self.bridge.split(' ')[1] elif transport_name and not self.pyobfsproxy_bin: log.err("Unable to test bridge because pyobfsproxy is not installed") self.report['success'] = None return + else: + self.report['bridge_address'] = self.bridge.split(' ')[0]
config.Bridge = self.bridge config.UseBridges = 1 config.save()
def updates(prog, tag, summary): - log.msg("Tor progress: %s%%" % prog) + log.msg("%s: %s%%" % (self.bridge, prog)) self.report['tor_progress'] = int(prog) self.report['tor_progress_tag'] = tag self.report['tor_progress_summary'] = summary