[tor-commits] [ooni-probe/master] initial psiphon test. Failure cases doesn't fail propertly

art at torproject.org art at torproject.org
Fri Apr 29 09:42:22 UTC 2016


commit 01bf963445daea590510044ea40269d9762498fe
Author: juga0 <juga>
Date:   Sun Sep 20 21:09:06 2015 +0000

    initial psiphon test. Failure cases doesn't fail propertly
---
 ooni/nettests/third_party/psiphon.py | 141 +++++++++++++++++++++++++++++++++++
 1 file changed, 141 insertions(+)

diff --git a/ooni/nettests/third_party/psiphon.py b/ooni/nettests/third_party/psiphon.py
new file mode 100644
index 0000000..f8cb82a
--- /dev/null
+++ b/ooni/nettests/third_party/psiphon.py
@@ -0,0 +1,141 @@
+import tempfile
+import stat
+import os
+
+from twisted.internet import defer, reactor
+from twisted.internet.endpoints import TCP4ClientEndpoint
+from twisted.web.client import readBody
+from twisted.python import usage
+
+from txsocksx.http import SOCKS5Agent
+
+from ooni.errors import handleAllFailures, TaskTimedOut
+from ooni.utils import log
+from ooni.templates import process, httpt
+from ooni.templates.process import ProcessTest
+
+
+class UsageOptions(usage.Options):
+    log.debug("UsageOptions")
+    optParameters = [
+        ['url', 'u', None, 'Specify a single URL to test.'],
+        ['psiphonpath', 'p', None, 'Specify psiphon python client path.'],
+        ['socksproxy', 's', None, 'Specify psiphon socks proxy ip:port.'],]
+
+
+class PsiphonTest(httpt.HTTPTest,  process.ProcessTest):
+    
+    """
+    This class tests Psiphon python client
+    
+    test_psiphon:
+      Starts a Psiphon, check if it bootstraps successfully
+      (print a line in stdout).
+      Then, perform an HTTP request using the proxy
+    """
+
+    name = "Psiphon Test"
+    description = "Bootstraps Psiphon and \
+                does a HTTP GET for the specified URL"
+    author = "juga"
+    version = "0.0.1"
+    timeout = 20
+    usageOptions = UsageOptions
+
+    def _setUp(self):
+        # it is necessary to do this in _setUp instead of setUp
+        # because it needs to happen before HTTPTest's _setUp.
+        # incidentally, setting this option in setUp results in HTTPTest
+        # *saying* it is using this proxy while not actually using it.
+        log.debug('PiphonTest._setUp: setting socksproxy')
+        self.localOptions['socksproxy'] = '127.0.0.1:1080'
+        super(PsiphonTest, self)._setUp()
+        
+    def setUp(self):
+        log.debug('PsiphonTest.setUp')
+
+        self.bootstrapped = defer.Deferred()
+        if self.localOptions['url']:
+            self.url = self.localOptions['url']
+        else:
+            # FIXME: use http://google.com?
+            # self.url = 'https://wtfismyip.com/text'
+            self.url = 'https://check.torproject.orggg'
+
+        if self.localOptions['psiphonpath']:
+            self.psiphonpath = self.localOptions['psiphonpath']
+        else:
+            # FIXME: search for pyclient path instead of assuming is in the
+            # home?
+            # psiphon is not installable and to run it manually, it has to be 
+            # run from the psiphon directory, so it wouldn't make sense to
+            # nstall it in the PATH
+            from os import path,  getenv
+            self.psiphonpath = path.join(
+                getenv('HOME'), 
+                 'psiphon-circumvention-system/pyclient')
+            log.debug('psiphon path: %s' % self.psiphonpath)
+
+        x = """#!/usr/bin/env python
+from psi_client import connect
+connect(False)
+"""
+        f = tempfile.NamedTemporaryFile(delete=False)
+        f.write(x)
+        f.close()
+        os.chmod(f.name, os.stat(f.name).st_mode | stat.S_IEXEC)
+        self.command = [f.name]
+        log.debug('command: %s' % ''.join(self.command))
+
+    def handleRead(self, stdout, stderr):
+        if 'Press Ctrl-C to terminate.' in self.processDirector.stdout:
+            if not self.bootstrapped.called:
+                log.debug("PsiphonTest.test_psiphon: calling bootstrapped.callback")
+                self.bootstrapped.callback(None)
+
+    def test_psiphon(self):
+        log.debug('PsiphonTest.test_psiphon')
+
+        if not os.path.exists(self.psiphonpath):
+            log.debug('psiphon path does not exists, is it installed?')
+            self.report['success'] = False
+            self.report['psiphon_installed'] = False
+            log.debug("Adding %s to report" % self.report)
+            #FIXME: this completes the test but ooni doesn't stop running, why?
+            return defer.succeed(None)
+
+        self.report['psiphon_installed'] = True
+        log.debug("Adding %s to report" % self.report)
+
+        finished = self.run(self.command,
+                                    env=dict(PYTHONPATH=self.psiphonpath), 
+                                    path=self.psiphonpath,
+                                    usePTY=1)
+
+
+        def addFailureToReport(failure):
+            log.debug("PsiphonTest.test_psiphon.addFailureToReport")
+            log.debug(repr(failure  ))
+            self.report['failure'] = handleAllFailures(failure)
+            self.report['success'] = False
+            log.debug("Adding %s to report" % self.report)
+            # FIXME: these keys are not being wroten in the report
+            # probably because report is being defined in NetTestCase as
+            # a class attribute that is initialized again in NetTescase._setUp
+
+        def callDoRequest(_):
+            return self.doRequest(self.url)
+        self.bootstrapped.addCallback(callDoRequest)
+
+        def cleanup(_):
+            log.debug('PsiphonTest:cleanup')
+            self.processDirector.transport.signalProcess('INT')
+            os.remove(self.command[0])
+            return finished
+            
+        self.bootstrapped.addErrback(addFailureToReport)
+        self.bootstrapped.addBoth(cleanup)
+        return self.bootstrapped
+
+
+





More information about the tor-commits mailing list