commit 9f09874c8313245bfc4da3ed7d2d9d266f36bf1f Author: aagbsn aagbsn@extc.org Date: Wed Sep 18 16:22:33 2013 +0200
Add postProcessor support to NetTest
If a NetTestCase has multiple test_ methods, then the report write shall not occur until all of the individual Measurements have completed.
This also changes the postProcessor API slightly; postProcessors are now expected to return a report instance. If a postProcessor is not supplied, then the report object from the instanced NetTestCase class is passed to Report.write() --- ooni/nettest.py | 34 ++++++++++++++++++++++++---------- ooni/tasks.py | 6 +++--- 2 files changed, 27 insertions(+), 13 deletions(-)
diff --git a/ooni/nettest.py b/ooni/nettest.py index f68148b..eb68182 100644 --- a/ooni/nettest.py +++ b/ooni/nettest.py @@ -537,13 +537,6 @@ class NetTest(object): measurement.done.addCallback(self.director.measurementSucceeded) measurement.done.addErrback(self.director.measurementFailed, measurement) - - if self.report: - measurement.done.addBoth(self.report.write) - - if self.report and self.director: - measurement.done.addBoth(self.doneReport) - return measurement
@defer.inlineCallbacks @@ -562,12 +555,33 @@ class NetTest(object): for test_class, test_methods in self.testCases: # load the input processor as late as possible for input in test_class.inputs: + klass = test_class() + measurements = [] for method in test_methods: log.debug("Running %s %s" % (test_class, method)) - measurement = self.makeMeasurement(test_class, method, input) + measurement = self.makeMeasurement(klass, method, input) + measurements.append(measurement.done) self.state.taskCreated() yield measurement
+ # When the measurement.done callbacks have all fired + # call the postProcessor before writing the report + if self.report: + post = defer.DeferredList(measurements) + + # Call the postProcessor, which must return a single report + # or a deferred + post.addCallback(klass.postProcessor) + def noPostProcessor(failure, report): + failure.trap(NoPostProcessor) + return report + post.addErrback(noPostProcessor, klass.report) + post.addCallback(self.report.write) + + if self.report and self.director: + #ghetto hax to keep NetTestState counts are accurate + [post.addBoth(self.doneReport) for _ in measurements] + self.state.allTasksScheduled()
class NetTestCase(object): @@ -654,10 +668,10 @@ class NetTestCase(object): """ pass
- def postProcessor(self, report): + def postProcessor(self, measurements): """ Subclass this to do post processing tasks that are to occur once all - the test methods have been called. Once per input. + the test methods have been called once per input. 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. diff --git a/ooni/tasks.py b/ooni/tasks.py index 52e9164..0c7f34e 100644 --- a/ooni/tasks.py +++ b/ooni/tasks.py @@ -110,9 +110,9 @@ class Measurement(TaskWithTimeout): self.testInstance.input = test_input if not self.testInstance.report: self.testInstance.report = {'input': test_input} - self.testInstance._start_time = time.time() - self.testInstance._setUp() - self.testInstance.setUp() + self.testInstance._setUp() + self.testInstance._start_time = time.time() + self.testInstance.setUp()
self.netTestMethod = getattr(self.testInstance, test_method)