[tor-commits] [ooni-probe/master] Get Director, TaskManager's, NetTest and oonicli to talk

isis at torproject.org isis at torproject.org
Sun Mar 10 01:57:02 UTC 2013


commit a31d54acc5d55e7bda567c37799afc8d6e2644af
Author: Arturo Filastò <art at fuffa.org>
Date:   Wed Jan 16 18:09:39 2013 +0100

    Get Director, TaskManager's, NetTest and oonicli to talk
    
    Tests are scheduled through the MeasurementManager, Reports via the
    ReporterManager and the Director keeps track of everything that is going on.
    
    Configurable retries and timeouts are possible.
    
    As an example, example_simple.py is run and the reports are written.
---
 bin/ooniprobe                       |   14 ++------
 nettests/examples/example_simple.py |    8 +++++
 ooni/director.py                    |    7 +---
 ooni/managers.py                    |    5 ++-
 ooni/nettest.py                     |   58 +++++++++++++++++++++++++++--------
 ooni/reporter.py                    |   20 +++++++-----
 ooni/tasks.py                       |   18 +++++-----
 tests/test_director.py              |    1 -
 tests/test_managers.py              |    2 -
 9 files changed, 83 insertions(+), 50 deletions(-)

diff --git a/bin/ooniprobe b/bin/ooniprobe
index 36f0152..695b137 100755
--- a/bin/ooniprobe
+++ b/bin/ooniprobe
@@ -1,12 +1,4 @@
 #!/usr/bin/env python
-# -*- encoding: utf-8 -*-
-# oonicli
-# -----------
-# Runs ooniprobe tests from command line
-#
-# :authors: Arturo Filastò, Isis Lovecruft
-# :licence: see included LICENSE file
-
 import os, sys
 import copy_reg
 from twisted.internet import reactor
@@ -19,5 +11,7 @@ sys.path.insert(0, os.path.abspath(os.getcwd()))
 from ooni.utils.hacks import patched_reduce_ex
 copy_reg._reduce_ex = patched_reduce_ex
 
-from ooni.oonicli import run
-run()
+# from ooni.oonicli import run
+# run()
+from ooni.oonicli import runWithDirector
+runWithDirector()
diff --git a/nettests/examples/example_simple.py b/nettests/examples/example_simple.py
new file mode 100644
index 0000000..24de5a6
--- /dev/null
+++ b/nettests/examples/example_simple.py
@@ -0,0 +1,8 @@
+from twisted.internet import defer
+from ooni import nettest
+
+class MyIP(nettest.NetTestCase):
+    def test_simple(self):
+        self.report['foobar'] = 'antani'
+        return defer.succeed(42)
+
diff --git a/ooni/director.py b/ooni/director.py
index ac53f5c..6fe3859 100644
--- a/ooni/director.py
+++ b/ooni/director.py
@@ -118,24 +118,21 @@ class Director(object):
 
     def measurementSucceeded(self, measurement):
         self.totalMeasurementRuntime += measurement.runtime
-
         self.successfulMeasurements += 1
-
-        return measurement.report.write(measurement)
+        return measurement.testInstance.report
 
     def measurementFailed(self, failure, measurement):
         self.totalMeasurementRuntime += measurement.runtime
 
         self.failedMeasurements += 1
         self.failures.append((failure, measurement))
+        return failure
 
     def reportEntryFailed(self, failure):
         # XXX add failure handling logic
         return
 
     def netTestDone(self, result, net_test):
-        print result
-        print "Completed %s" % net_test
         self.activeNetTests.remove(net_test)
 
     def startNetTest(self, net_test_loader, options):
diff --git a/ooni/managers.py b/ooni/managers.py
index 818ae5c..533e6b5 100644
--- a/ooni/managers.py
+++ b/ooni/managers.py
@@ -23,10 +23,13 @@ class TaskManager(object):
         self.failures = []
 
     def _failed(self, failure, task):
+        # XXX INFINITE RECURSION LOOP INSIDE OF THIS THING
         """
         The has failed to complete, we append it to the end of the task chain
         to be re-run once all the currently scheduled tasks have run.
         """
+        print "This task has failed"
+        print failure
         self._active_tasks.remove(task)
         self.failures.append((failure, task))
 
@@ -147,8 +150,6 @@ class ReportEntryManager(TaskManager):
     retries = 3
     concurrency = 20
 
-    director = None
-
     def succeeded(self, result, task):
         pass
 
diff --git a/ooni/nettest.py b/ooni/nettest.py
index be1c4b3..f82354b 100644
--- a/ooni/nettest.py
+++ b/ooni/nettest.py
@@ -30,7 +30,7 @@ class NetTestState(object):
         self.completedScheduling = False
         self.allTasksDone = allTasksDone
 
-    def created(self):
+    def taskCreated(self):
         self.tasks += 1
 
     def checkAllTasksDone(self):
@@ -38,7 +38,7 @@ class NetTestState(object):
                 self.doneTasks == self.tasks:
             self.allTasksDone.callback(self.doneTasks)
 
-    def taskDone(self, result):
+    def taskDone(self):
         """
         This is called every time a task has finished running.
         """
@@ -238,22 +238,51 @@ class NetTest(object):
         self.state.taskDone()
         return result
 
+    def makeMeasurement(self, test_class, test_method, test_input=None):
+        """
+        Creates a new instance of :class:ooni.tasks.Measurement and add's it's
+        callbacks and errbacks.
+
+        Args:
+            test_class:
+                a subclass of :class:ooni.nettest.NetTestCase
+
+            test_method:
+                a string that represents the method to be called on test_class
+
+            test_input:
+                optional argument that represents the input to be passed to the
+                NetTestCase
+
+        """
+        measurement = Measurement(test_class, test_method, test_input)
+        measurement.netTest = self
+
+        measurement.done.addCallback(self.director.measurementSucceeded)
+        measurement.done.addErrback(self.director.measurementFailed, measurement)
+
+        measurement.done.addCallback(self.report.write)
+        measurement.done.addErrback(self.director.reportEntryFailed)
+
+        measurement.done.addBoth(self.doneReport)
+        return measurement
+
     def generateMeasurements(self):
         """
         This is a generator that yields measurements and registers the
         callbacks for when a measurement is successful or has failed.
         """
+        self.report.open()
         for test_class, test_method in self.testCases:
-            for test_input in test_class.inputs:
-                measurement = Measurement(test_class, test_method, test_input)
-
-                measurement.done.addCallback(self.director.measurementSucceeded)
-                measurement.done.addErrback(self.director.measurementFailed)
-
-                measurement.done.addCallback(self.report.write)
-                measurement.done.addErrback(self.director.reportEntryFailed)
+            if not test_class.inputs:
+                # XXX this is a bit dirty, refactor me
+                yield self.makeMeasurement(test_class, test_method)
+                self.state.taskCreated()
+                break
 
-                measurement.done.addBoth(self.doneReport)
+            for test_input in test_class.inputs:
+                measurement = self.makeMeasurement(test_class, test_method,
+                        test_input)
 
                 self.state.taskCreated()
                 yield measurement
@@ -277,7 +306,10 @@ class NetTest(object):
             test_instance._checkRequiredOptions()
             test_instance._checkValidOptions()
 
-            klass.inputs = test_instance.getInputProcessor()
+            inputs = test_instance.getInputProcessor()
+            if not inputs:
+                inputs = [None]
+            klass.inputs = inputs
 
 class NetTestCase(object):
     """
@@ -424,7 +456,7 @@ class NetTestCase(object):
 
                 return inputProcessorIterator()
 
-        return iter(())
+        return None
 
     def _checkValidOptions(self):
         for option in self.localOptions:
diff --git a/ooni/reporter.py b/ooni/reporter.py
index 8a39531..7d33bd1 100644
--- a/ooni/reporter.py
+++ b/ooni/reporter.py
@@ -33,7 +33,6 @@ from ooni import config
 
 from ooni.tasks import ReportEntry
 
-
 class ReporterException(Exception):
     pass
 
@@ -204,13 +203,16 @@ class YAMLReporter(OReporter):
         log.debug("Writing report with YAML reporter")
         self._write('---\n')
         self._write(safe_dump(entry))
+        self._write('...\n')
 
     def createReport(self):
         """
         Writes the report header and fire callbacks on self.created
         """
         self._writeln("###########################################")
-        self._writeln("# OONI Probe Report for %s test" % self.test_name)
+
+        self._writeln("# OONI Probe Report for %s (%s)" % (self.testDetails['test_name'],
+                    self.testDetails['test_version']))
         self._writeln("# %s" % otime.prettyDateNow())
         self._writeln("###########################################")
 
@@ -390,7 +392,7 @@ class Report(object):
             a deferred list that will fire once all the report entries have
             been written.
         """
-        dl = []
+        l = []
         for reporter in self.reporters:
             def writeReportEntry(result):
                 report_write_task = ReportEntry(reporter, measurement)
@@ -398,9 +400,10 @@ class Report(object):
                 return report_write_task.done
 
             d = reporter.created.addBoth(writeReportEntry)
-            dl.append(d)
+            l.append(d)
 
-        return defer.DeferredList(dl)
+        dl = defer.DeferredList(l)
+        return dl
 
     def close(self, _):
         """
@@ -411,9 +414,10 @@ class Report(object):
             all the reports have been closed.
 
         """
-        dl = []
+        l = []
         for reporter in self.reporters:
             d = defer.maybeDeferred(reporter.finish)
-            dl.append(d)
-        return defer.DeferredList(dl)
+            l.append(d)
+        dl = defer.DeferredList(l)
+        return dl
 
diff --git a/ooni/tasks.py b/ooni/tasks.py
index bd7e5b8..4f7da4c 100644
--- a/ooni/tasks.py
+++ b/ooni/tasks.py
@@ -103,25 +103,25 @@ class Measurement(TaskWithTimeout):
         net_test:
             a reference to the net_test object such measurement belongs to.
         """
-        self.test_instance = test_class()
-        self.test_instance.input = test_input
-        self.test_instance.report = {}
-        self.test_instance._start_time = time.time()
-        self.test_instance._setUp()
-        self.test_instance.setUp()
+        self.testInstance = test_class()
+        self.testInstance.input = test_input
+        self.testInstance.report = {}
+        self.testInstance._start_time = time.time()
+        self.testInstance._setUp()
+        self.testInstance.setUp()
 
-        self.net_test_method = getattr(self.test_instance, test_method)
+        self.netTestMethod = getattr(self.testInstance, test_method)
 
         TaskWithTimeout.__init__(self)
 
     def succeeded(self, result):
-        return self.netTest.succeeded(self)
+        pass
 
     def failed(self, failure):
         pass
 
     def run(self):
-        d = self.net_test_method()
+        d = self.netTestMethod()
         return d
 
 class ReportEntry(TaskWithTimeout):
diff --git a/tests/test_director.py b/tests/test_director.py
index 409047b..365c11f 100644
--- a/tests/test_director.py
+++ b/tests/test_director.py
@@ -45,7 +45,6 @@ class TestDirector(unittest.TestCase):
 
         @d.addCallback
         def done(result):
-            print "SOMETHING"
             self.assertEqual(self.director.successfulMeasurements, 20)
 
         return d
diff --git a/tests/test_managers.py b/tests/test_managers.py
index 13f1847..601e305 100644
--- a/tests/test_managers.py
+++ b/tests/test_managers.py
@@ -12,8 +12,6 @@ from tests.mocks import MockTaskManager, mockFailure, MockDirector
 from tests.mocks import MockNetTest, MockMeasurement, MockSuccessMeasurement
 from tests.mocks import MockFailMeasurement, MockFailOnceMeasurement
 
-from decotrace import traced
-
 class TestTaskManager(unittest.TestCase):
     timeout = 1
     def setUp(self):





More information about the tor-commits mailing list