[tor-commits] [ooni-probe/master] Write test that reproduces HTTP test stalling condition.

art at torproject.org art at torproject.org
Thu Feb 6 16:26:03 UTC 2014


commit df8d9b46a3d4e6d258afb49e45b68c2a75abbe13
Author: Arturo Filastò <art at fuffa.org>
Date:   Mon Feb 3 16:29:14 2014 +0100

    Write test that reproduces HTTP test stalling condition.
    
    The condition would happen when a HTTP server would keep the connection open
    without sending any data. The problem lied in the fact that we were not
    properly cancelling tests that should have been cancelled.
    
    This was happening because of 2 reasons:
    1) We should not be checking to see if self._running.called is True since it is
    possible that such deferred has been called, but the it has not yet made it's
    way down the callback chain to the ooni registered callbacks.
    2) We must call the cancel() method after we have called the failed() method.
    Failing to do so will lead to the newly scheduled timer to be cancelled instead
    of the previous one.
---
 ooni/tasks.py              |    5 ++--
 ooni/tests/test_nettest.py |   71 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 73 insertions(+), 3 deletions(-)

diff --git a/ooni/tasks.py b/ooni/tasks.py
index 3e378e9..6e8c507 100644
--- a/ooni/tasks.py
+++ b/ooni/tasks.py
@@ -69,12 +69,11 @@ class TaskWithTimeout(BaseTask):
 
     def _timedOut(self):
         """Internal method for handling timeout failure"""
-        if self._running and not self._running.called:
-            self._running.cancel()
+        if self._running:
             self._failed(TaskTimedOut)
+            self._running.cancel()
 
     def _cancelTimer(self):
-        #import pdb; pdb.set_trace()
         if self._timer.active():
             self._timer.cancel()
 
diff --git a/ooni/tests/test_nettest.py b/ooni/tests/test_nettest.py
index d965735..718fca7 100644
--- a/ooni/tests/test_nettest.py
+++ b/ooni/tests/test_nettest.py
@@ -6,6 +6,7 @@ from twisted.trial import unittest
 from twisted.internet import defer, reactor
 from twisted.python.usage import UsageError
 
+from ooni.settings import config
 from ooni.errors import MissingRequiredOption, InvalidOption, FailureToLoadNetTest
 from ooni.nettest import NetTest, NetTestLoader
 from ooni.tasks import BaseTask
@@ -83,6 +84,28 @@ class DummyTestCase(NetTestCase):
     requiredOptions = ['foo', 'bar']
 """
 
+http_net_test = """
+from twisted.internet import defer
+from twisted.python import usage, failure
+
+from ooni.utils import log
+from ooni.utils.net import userAgents
+from ooni.templates import httpt
+from ooni.errors import failureToString, handleAllFailures
+
+class UsageOptions(usage.Options):
+    optParameters = [
+                     ['url', 'u', None, 'Specify a single URL to test.'],
+                     ['factor', 'f', 0.8, 'What factor should be used for triggering censorship (0.8 == 80%)']
+                    ]
+
+class HTTPBasedTest(httpt.HTTPTest):
+    usageOptions = UsageOptions
+    def test_get(self):
+        return self.doRequest(self.localOptions['url'], method="GET",
+                              use_tor=False)
+"""
+
 dummyInputs = range(1)
 dummyArgs = ('--spam', 'notham')
 dummyOptions = {'spam':'notham'}
@@ -243,3 +266,51 @@ class TestNetTest(unittest.TestCase):
 
         for test_class, method in ntl.testCases:
             self.assertTrue(test_class.requiresRoot)
+
+class TestNettestTimeout(unittest.TestCase):
+    @defer.inlineCallbacks
+    def setUp(self):
+        from twisted.internet.protocol import Protocol, Factory
+        from twisted.internet.endpoints import TCP4ServerEndpoint
+
+        class DummyProtocol(Protocol):
+            def dataReceived(self, data):
+                print data
+
+        class DummyFactory(Factory):
+            def __init__(self):
+                self.protocols = []
+
+            def buildProtocol(self, addr):
+                proto = DummyProtocol()
+                self.protocols.append(proto)
+                return proto
+
+            def stopFactory(self):
+                for proto in self.protocols:
+                    proto.transport.loseConnection()
+
+        self.factory = DummyFactory()
+        endpoint = TCP4ServerEndpoint(reactor, 8007)
+        self.port = yield endpoint.listen(self.factory)
+
+        config.advanced.measurement_timeout = 2
+
+    def tearDown(self):
+        self.factory.stopFactory()
+        self.port.stopListening()
+    
+    def test_nettest_timeout(self):
+        ntl = NetTestLoader(('-u', 'http://localhost:8007/'))
+        ntl.loadNetTestString(http_net_test)
+
+        ntl.checkOptions()
+        director = Director()
+
+        d = director.startNetTest(ntl, [MockReporter()])
+
+        @d.addCallback
+        def complete(result):
+            assert director.failedMeasurements == 1
+
+        return d





More information about the tor-commits mailing list