[tor-commits] [bridgedb/develop] Add tests for bridgedb.Dist module.

isis at torproject.org isis at torproject.org
Thu Jun 25 07:10:54 UTC 2015


commit 6c10de805e607e9c27c1f3ba4d79097c11c76dbb
Author: Isis Lovecruft <isis at torproject.org>
Date:   Sat Apr 18 03:16:31 2015 +0000

    Add tests for bridgedb.Dist module.
---
 lib/bridgedb/test/test_Dist.py |  245 ++++++++++++++++++++++++++++++++++++++++
 1 file changed, 245 insertions(+)

diff --git a/lib/bridgedb/test/test_Dist.py b/lib/bridgedb/test/test_Dist.py
new file mode 100644
index 0000000..a3c8308
--- /dev/null
+++ b/lib/bridgedb/test/test_Dist.py
@@ -0,0 +1,245 @@
+# -*- coding: utf-8 -*-
+#
+# This file is part of BridgeDB, a Tor bridge distribution system.
+#
+# :authors: Isis Lovecruft 0xA3ADB67A2CDB8B35 <isis at torproject.org>
+#           please also see AUTHORS file
+# :copyright: (c) 2013-2015 Isis Lovecruft
+#             (c) 2007-2015, The Tor Project, Inc.
+#             (c) 2007-2015, all entities within the AUTHORS file
+# :license: 3-clause BSD, see included LICENSE for information
+
+"""Tests for :mod:`bridgedb.Dist`."""
+
+from __future__ import print_function
+
+import hashlib
+import ipaddr
+import random
+
+from twisted.trial import unittest
+
+from bridgedb import Dist
+from bridgedb.bridges import Bridge
+from bridgedb.bridges import PluggableTransport
+from bridgedb.Bridges import BridgeRing
+from bridgedb.Filters import filterBridgesByNotBlockedIn
+from bridgedb.https.request import HTTPSBridgeRequest
+from bridgedb.proxy import ProxySet
+from bridgedb.test.util import randomHighPort
+from bridgedb.test.util import randomValidIPv4String
+from bridgedb.test.util import randomValidIPv6
+from bridgedb.test.https_helpers import DummyRequest
+
+
+def _generateFakeBridges(n=500):
+    bridges = []
+
+    for i in range(n):
+        addr = randomValidIPv4String()
+        nick = 'bridge-%d' % i
+        port = randomHighPort()
+        # Real tor currently only supports one extra ORAddress, and it can
+        # only be IPv6.
+        addrs = [(randomValidIPv6(), randomHighPort(), 6)]
+        fpr = "".join(random.choice('abcdef0123456789') for _ in xrange(40))
+
+        # We only support the ones without PT args, because they're easier to fake.
+        supported = ["obfs2", "obfs3", "fte"]
+        transports = []
+        for j, method in zip(range(1, len(supported) + 1), supported):
+            pt = PluggableTransport(fpr, method, addr, port - j, {})
+            transports.append(pt)
+
+        bridge = Bridge(nick, addr, port, fpr)
+        bridge.flags.update("Running Stable")
+        bridge.transports = transports
+        bridge.orAddresses = addrs
+        bridges.append(bridge)
+
+    return bridges
+
+
+BRIDGES = _generateFakeBridges()
+
+
+class GetNumBridgesPerAnswerTests(unittest.TestCase):
+    """Unittests for :func:`bridgedb.Dist.getNumBridgesPerAnswer`."""
+
+    def setUp(self):
+        self.key = 'aQpeOFIj8q20s98awfoiq23rpOIjFaqpEWFoij1X'
+        self.ring = BridgeRing(self.key)
+        self.bridges = _generateFakeBridges()
+
+    def test_Dist_getNumBridgesPerAnswer_120(self):
+        [self.ring.insert(bridge) for bridge in self.bridges[:120]]
+        self.assertEqual(Dist.getNumBridgesPerAnswer(self.ring), 3)
+
+    def test_Dist_getNumBridgesPerAnswer_100(self):
+        [self.ring.insert(bridge) for bridge in self.bridges[:100]]
+        self.assertEqual(Dist.getNumBridgesPerAnswer(self.ring), 3)
+
+    def test_Dist_getNumBridgesPerAnswer_50(self):
+        [self.ring.insert(bridge) for bridge in self.bridges[:60]]
+        self.assertEqual(Dist.getNumBridgesPerAnswer(self.ring), 2)
+
+    def test_Dist_getNumBridgesPerAnswer_15(self):
+        [self.ring.insert(bridge) for bridge in self.bridges[:15]]
+        self.assertEqual(Dist.getNumBridgesPerAnswer(self.ring), 1)
+
+    def test_Dist_getNumBridgesPerAnswer_100_max_5(self):
+        [self.ring.insert(bridge) for bridge in self.bridges[:100]]
+        self.assertEqual(
+            Dist.getNumBridgesPerAnswer(self.ring, max_bridges_per_answer=5),
+            5)
+
+
+class HTTPSDistributorTests(unittest.TestCase):
+    """Tests for :class:`HTTPSDistributor`."""
+
+    def setUp(self):
+        self.key = 'aQpeOFIj8q20s98awfoiq23rpOIjFaqpEWFoij1X'
+        self.bridges = BRIDGES
+
+    def tearDown(self):
+        """Reset all bridge blocks in between test method runs."""
+        for bridge in self.bridges:
+            bridge._blockedIn = {}
+
+    def coinFlip(self):
+        return bool(random.getrandbits(1))
+
+    def randomClientRequest(self):
+        bridgeRequest = HTTPSBridgeRequest(addClientCountryCode=False)
+        bridgeRequest.client = randomValidIPv4String()
+        bridgeRequest.isValid(True)
+        bridgeRequest.generateFilters()
+        return bridgeRequest
+
+    def randomClientRequestForNotBlockedIn(self, cc):
+        httpRequest = DummyRequest([''])
+        httpRequest.args.update({'unblocked': [cc]})
+        bridgeRequest = self.randomClientRequest()
+        bridgeRequest.withoutBlockInCountry(httpRequest)
+        bridgeRequest.generateFilters()
+        return bridgeRequest
+
+    def test_HTTPSDistributor_init_with_proxies(self):
+        """The HTTPSDistributor, when initialised with proxies, should add an
+        extra hashring for proxy users.
+        """
+        dist = Dist.HTTPSDistributor(3, self.key, ProxySet(['1.1.1.1', '2.2.2.2']))
+        self.assertIsNotNone(dist.proxies)
+        self.assertGreater(dist.proxySubring, 0)
+        self.assertEqual(dist.proxySubring, 4)
+        self.assertEqual(dist.totalSubrings, 4)
+
+    def test_HTTPSDistributor_getSubnet_usingProxy(self):
+        """HTTPSDistributor.getSubnet(usingProxy=True) should return a proxy
+        group number.
+        """
+        clientRequest = self.randomClientRequest()
+        expectedGroup = (int(ipaddr.IPAddress(clientRequest.client)) % 4) + 1
+        subnet = Dist.HTTPSDistributor.getSubnet(clientRequest.client, usingProxy=True)
+        self.assertTrue(subnet.startswith('proxy-group-'))
+        self.assertEqual(int(subnet[-1]), expectedGroup)
+
+    def test_HTTPSDistributor_mapSubnetToSubring_usingProxy(self):
+        """HTTPSDistributor.mapSubnetToSubring() when the client was using a
+        proxy should map the client to the proxy subhashring.
+        """
+        dist = Dist.HTTPSDistributor(3, self.key, ProxySet(['1.1.1.1', '2.2.2.2']))
+        subnet = 'proxy-group-3'
+        subring = dist.mapSubnetToSubring(subnet, usingProxy=True)
+        self.assertEqual(subring, dist.proxySubring)
+
+    def test_HTTPSDistributor_mapSubnetToSubring_with_proxies(self):
+        """HTTPSDistributor.mapSubnetToSubring() when the client wasn't using
+        a proxy, but the distributor does have some known proxies and a
+        proxySubring, should not map the client to the proxy subhashring.
+        """
+        dist = Dist.HTTPSDistributor(3, self.key, ProxySet(['1.1.1.1', '2.2.2.2']))
+        # Note that if they were actually from a proxy, their subnet would be
+        # something like "proxy-group-3".
+        subnet = '15.1.0.0/16'
+        subring = dist.mapSubnetToSubring(subnet, usingProxy=False)
+        self.assertNotEqual(subring, dist.proxySubring)
+
+    def test_HTTPSDistributor_prepopulateRings_with_proxies(self):
+        """An HTTPSDistributor with proxies should prepopulate two extra
+        subhashrings (one for each of HTTP-Proxy-IPv4 and HTTP-Proxy-IPv6).
+        """
+        dist = Dist.HTTPSDistributor(3, self.key, ProxySet(['1.1.1.1', '2.2.2.2']))
+        [dist.insert(bridge) for bridge in self.bridges]
+        dist.prepopulateRings()
+        self.assertEqual(len(dist.hashring.filterRings), 8)
+
+    def test_HTTPSDistributor_prepopulateRings_without_proxies(self):
+        """An HTTPSDistributor without proxies should prepopulate
+        totalSubrings * 2 subrings.
+        """
+        dist = Dist.HTTPSDistributor(3, self.key)
+        [dist.insert(bridge) for bridge in self.bridges]
+        dist.prepopulateRings()
+        self.assertEqual(len(dist.hashring.filterRings), 6)
+
+        ipv4subrings = []
+        ipv6subrings = []
+
+        for subringName, (filters, subring) in dist.hashring.filterRings.items():
+            if 'IPv4' in subringName:
+                ipv6subrings.append(subring)
+            if 'IPv6' in subringName:
+                ipv6subrings.append(subring)
+
+        self.assertEqual(len(ipv4subrings), len(ipv6subrings))
+
+    def test_HTTPSDistributor_getBridges_with_blocked_bridges(self):
+        dist = Dist.HTTPSDistributor(1, self.key)
+        bridges = self.bridges[:]
+
+        for bridge in bridges:
+            bridge.setBlockedIn('cn')
+
+        [dist.insert(bridge) for bridge in bridges]
+
+        for _ in range(5):
+            clientRequest1 = self.randomClientRequestForNotBlockedIn('cn')
+            b = dist.getBridges(clientRequest1, 1, 3)
+            self.assertEqual(len(b), 0)
+
+            clientRequest2 = self.randomClientRequestForNotBlockedIn('ir')
+            b = dist.getBridges(clientRequest2, 1, 3)
+            self.assertEqual(len(b), 3)
+
+    def test_HTTPSDistributor_getBridges_with_some_blocked_bridges(self):
+        dist = Dist.HTTPSDistributor(1, self.key)
+        bridges = self.bridges[:]
+
+        blockedCN = []
+        blockedIR = []
+
+        for bridge in bridges:
+            if self.coinFlip():
+                bridge.setBlockedIn('cn')
+                blockedCN.append(bridge.fingerprint)
+
+            if self.coinFlip():
+                bridge.setBlockedIn('ir')
+                blockedIR.append(bridge.fingerprint)
+
+        [dist.insert(bridge) for bridge in bridges]
+
+        for _ in range(5):
+            clientRequest1 = self.randomClientRequestForNotBlockedIn('cn')
+            bridges = dist.getBridges(clientRequest1, 1, 3)
+            for b in bridges:
+                self.assertFalse(b.isBlockedIn('cn'))
+            # The client *should* have gotten some bridges still.
+            self.assertGreater(len(bridges), 0)
+
+            clientRequest2 = self.randomClientRequestForNotBlockedIn('ir')
+            bridges = dist.getBridges(clientRequest2, 1, 3)
+            for b in bridges:
+                self.assertFalse(b.isBlockedIn('ir'))
+            self.assertGreater(len(bridges), 0)





More information about the tor-commits mailing list