[tor-commits] [ooni-probe/master] Basic testing and implementation of reporting task manager

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


commit 725f9ee90fb10997f57a5c1a5313ae7a84b68249
Author: Arturo Filastò <art at fuffa.org>
Date:   Mon Jan 14 20:42:31 2013 +0100

    Basic testing and implementation of reporting task manager
---
 ooni/nettest.py        |    6 ++-
 ooni/reporter.py       |    7 ++-
 ooni/tasks.py          |   27 +++++++++--
 tests/test_reporter.py |  118 ++++++++++++++++++++---------------------------
 4 files changed, 81 insertions(+), 77 deletions(-)

diff --git a/ooni/nettest.py b/ooni/nettest.py
index 67a793d..d6cadc3 100644
--- a/ooni/nettest.py
+++ b/ooni/nettest.py
@@ -144,10 +144,12 @@ class NetTest(object):
                 yield measurement
         task_mediator.allTasksScheduled()
 
-        # Once all the MeasurementsTasks have been completed all the report
-        # tasks will have been scheduled.
         @task_mediator.allTasksDone.addCallback
         def done(result):
+            """
+            Once all the MeasurementsTasks have been completed all the report
+            tasks will have been scheduled.
+            """
             self.report.report_mediator.allTasksScheduled()
 
     def setUpNetTestCases(self):
diff --git a/ooni/reporter.py b/ooni/reporter.py
index 38e83c3..d24edcc 100644
--- a/ooni/reporter.py
+++ b/ooni/reporter.py
@@ -177,6 +177,7 @@ class OReporter(object):
         pass
 
     def testDone(self, test, test_name):
+        # XXX 
         log.msg("Finished running %s" % test_name)
         test_report = dict(test.report)
 
@@ -406,7 +407,8 @@ class Report(object):
         This will create all the reports that need to be created.
         """
         for reporter in self.reporters:
-            reporter.createReport()
+            d = defer.maybeDeferred(reporter.createReport)
+            d.addCallback(reporter.created.callback)
 
     def write(self, measurement):
         """
@@ -424,7 +426,8 @@ class Report(object):
             def cb(result):
                 self.reportEntryManager.schedule(report_write_task)
 
-    def finish(self):
+    def finish(self, result):
+        dl = []
         for reporter in self.reporters:
             d = defer.maybeDeferred(reporter.finish)
             dl.append(d)
diff --git a/ooni/tasks.py b/ooni/tasks.py
index 3fdf083..f2a9bae 100644
--- a/ooni/tasks.py
+++ b/ooni/tasks.py
@@ -35,7 +35,7 @@ class BaseTask(object):
         return result
 
     def start(self):
-        self.running = self.run()
+        self.running = defer.maybeDeferred(self.run)
         self.running.addErrback(self._failed)
         self.running.addCallback(self._succeeded)
         return self.running
@@ -163,19 +163,36 @@ class TaskMediator(object):
         self.tasks = 0
 
         self.completedScheduling = False
-
         self.allTasksDone = allTasksDone
 
     def created(self):
         self.tasks += 1
 
-    def taskDone(self, result):
-        self.doneTasks += 1
+    def checkAllTasksDone(self):
         if self.completedScheduling and \
                 self.doneTasks == self.tasks:
-            self.allTasksDone.callback(None)
+            self.allTasksDone.callback(self.doneTasks)
+
+    def taskDone(self, result):
+        """
+        This is called every time a task has finished running.
+        """
+        self.doneTasks += 1
+        self.checkAllTasksDone()
 
     def allTasksScheduled(self):
+        """
+        This should be called once all the tasks that need to run have been
+        scheduled.
+
+        XXX this is ghetto.
+        The reason for which we are calling allTasksDone inside of the
+        allTasksScheduled method is called after all tasks are done, then we
+        will run into a race condition. The race is that we don't end up
+        checking that all the tasks are complete because no task is to be
+        scheduled.
+        """
         self.completedScheduling = True
+        self.checkAllTasksDone()
 
 
diff --git a/tests/test_reporter.py b/tests/test_reporter.py
index cfa0afd..1754ad0 100644
--- a/tests/test_reporter.py
+++ b/tests/test_reporter.py
@@ -1,76 +1,58 @@
+from twisted.internet import defer
 from twisted.trial import unittest
+
 from ooni.reporter import Report, YAMLReporter, OONIBReporter
-from ooni.managers import ReportEntryManager
+from ooni.managers import ReportEntryManager, TaskManager
 from ooni.nettest import NetTest
-from ooni.tasks import TaskMediator
+
+from ooni.tasks import TaskMediator, TaskWithTimeout
 
 mockReportOptions = {'name':'foo_test', 'version': '0.1'}
 
-class TestYAMLReporter(unittest.TestCase):
-    def setUp(self):
+class MockOReporter(object):
+    def __init__(self):
+        self.created = defer.Deferred()
+
+    def writeReportEntry(self, entry):
+        pass
+
+    def finish(self):
+        pass
+
+    def createReport(self):
+        pass
+
+class MockMeasurement(TaskWithTimeout):
+    def __init__(self):
+        TaskWithTimeout.__init__(self)
+
+    def succeeded(self, result):
         pass
 
-    def test_create_yaml_reporter(self):
-
-        YAMLReporter.reportFilePrefix = "spam"
-        YAMLReporter.options = mockReportOptions
-        report = Report([YAMLReporter])
-        #XXX: calls createReport on init. is that what we want?
-        report.reportEntryManager = ReportEntryManager()
-        allTasksDone = defer.Deferred()
-        report.taskmediator = TaskMediator()
-
-    #def test_create_yaml_report(self):
-    #    # should create a YAML report
-    #    raise NotImplementedError
-
-    def test_write_yaml_report(self):
-        YAMLReporter.reportFilePrefix = "spam"
-        YAMLReporter.options = mockReportOptions
-        report = Report([YAMLReporter])
-        #XXX: fire createReport on init. is that what we want?
-        report.reportEntryManager = ReportEntryManager()
-        report.write("HAI")
-
-    def test_write_yaml_report_before_create(self):
-       # should write to YAML report before it has been created
-       # the write should not occur until after the created callback has fired
-       raise NotImplementedError
-
-    def test_yaml_report_completed(self):
-       # should test that a report will complete successfully
-       # it should fire a callback after the report.finish method is called,
-       # XXX: a report should not be finalized until after all pending
-       # writes have completed
-       raise NotImplementedError
-
-    def test_write_after_completed(self):
-       # try to call write after a report is completed/finalized. it must fail
-       # it should also fail in the sense that as long as the finalize-report has
-       # been called no additional reports entries can be added, but
-       # existing/pending entries should be completed before the report
-       # finalized callback is fired
-       raise NotImplementedError
-
-
-#class OONIBReporter(unittest.TestCase):
-#    def setUp(self):
-#        #XXX set up a dummy OONIB backend
-#        pass
-#
-#    def test_create_oonib_reporter(self):
-#        # should instance a OONIB reporter
-#        raise NotImplementedError
-#
-#    def test_create_oonib_report(self):
-#        # should create a YAML report
-#        raise NotImplementedError
-#
-#    def test_write_oonib_report(self):
-#        # should write to YAML report
-#        raise NotImplementedError
-#
-#    def test_write_oonib_report_before_create(self):
-#        # should write to YAML report before it has been created
-#        # the write should not occur until after the created callback has fired
-#        raise NotImplementedError
+class MockTaskManager(TaskManager):
+    def __init__(self):
+        self.successes = []
+
+    def failed(self, failure, task):
+        pass
+
+    def succeeded(self, result, task):
+        self.successes.append((result, task))
+
+class TestReport(unittest.TestCase):
+    def setUp(self):
+        self.report = Report([MockOReporter])
+        self.report.reportEntryManager = MockTaskManager()
+
+    def test_report_alltasksdone_callback_fires(self):
+        for m in range(10):
+            measurement = MockMeasurement()
+            self.report.write(measurement)
+
+        self.report.report_mediator.allTasksScheduled()
+
+        @self.report.done.addCallback
+        def done(reporters):
+            self.assertEqual(len(reporters), 1)
+
+        return self.report.done





More information about the tor-commits mailing list