[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[bridgedb/master] Move bridgedb.Tests → bridgedb.test.legacy_Tests.
commit e6ebfaa1c70f89bee6b5c6f59ab457bc97217b88
Author: Isis Lovecruft <isis@xxxxxxxxxxxxxx>
Date: Fri Dec 5 23:20:55 2014 +0000
Move bridgedb.Tests â?? bridgedb.test.legacy_Tests.
* MOVE bridgedb.Tests to bridgedb.test.legacy_Tests.
* CHANGE bridgedb.test.test_Tests to import the moved module.
---
lib/bridgedb/Tests.py | 780 ------------------------------------
lib/bridgedb/test/legacy_Tests.py | 785 +++++++++++++++++++++++++++++++++++++
lib/bridgedb/test/test_Tests.py | 9 +-
3 files changed, 790 insertions(+), 784 deletions(-)
diff --git a/lib/bridgedb/Tests.py b/lib/bridgedb/Tests.py
deleted file mode 100644
index 93ee4f2..0000000
--- a/lib/bridgedb/Tests.py
+++ /dev/null
@@ -1,780 +0,0 @@
-# BridgeDB by Nick Mathewson.
-# Copyright (c) 2007-2009, The Tor Project, Inc.
-# See LICENSE for licensing information
-
-from __future__ import print_function
-
-import doctest
-import os
-import random
-import sqlite3
-import tempfile
-import unittest
-import warnings
-import time
-from datetime import datetime
-
-import bridgedb.Bridges
-import bridgedb.Main
-import bridgedb.Dist
-import bridgedb.schedule
-import bridgedb.Storage
-import re
-import ipaddr
-
-from bridgedb.Filters import filterBridgesByIP4
-from bridgedb.Filters import filterBridgesByIP6
-from bridgedb.Filters import filterBridgesByOnlyIP4
-from bridgedb.Filters import filterBridgesByOnlyIP6
-from bridgedb.Filters import filterBridgesByTransport
-from bridgedb.Filters import filterBridgesByNotBlockedIn
-
-from bridgedb.Stability import BridgeHistory
-
-from bridgedb.parse import addr
-from bridgedb.parse import networkstatus
-
-from math import log
-
-def suppressWarnings():
- warnings.filterwarnings('ignore', '.*tmpnam.*')
-
-def randomIP():
- if random.choice(xrange(2)):
- return randomIP4()
- return randomIP6()
-
-def randomIP4():
- return ipaddr.IPv4Address(random.getrandbits(32))
-
-def randomIP4String():
- return randomIP4().compressed
-
-def randomIP6():
- return ipaddr.IPv6Address(random.getrandbits(128))
-
-def randomIP6String():
- return bracketIP6(randomIP6().compressed)
-
-def randomIPString():
- if random.choice(xrange(2)):
- return randomIP4String()
- return randomIP6String()
-
-def bracketIP6(ip):
- """Put brackets around an IPv6 address, just as tor does."""
- return "[%s]" % ip
-
-def random16IP():
- upper = "123.123." # same 16
- lower = ".".join([str(random.randrange(1,256)) for _ in xrange(2)])
- return upper+lower
-
-def randomPort():
- return random.randint(1,65535)
-
-def randomPortSpec():
- """
- returns a random list of ports
- """
- ports = []
- for i in range(0,24):
- ports.append(random.randint(1,65535))
- ports.sort(reverse=True)
-
- portspec = ""
- for i in range(0,16):
- portspec += "%d," % random.choice(ports)
- portspec = portspec.rstrip(',') #remove trailing ,
- return portspec
-
-def randomCountry():
- countries = ['us', 'nl', 'de', 'cz', 'sk', 'as', 'si', 'it']
- #XXX: load from geoip
- return random.choice(countries)
-
-def randomCountrySpec():
- countries = ['us', 'nl', 'de', 'cz', 'sk', 'as', 'si', 'it']
- #XXX: load from geoip
- spec = ""
- choices = []
- for i in xrange(10):
- choices.append(random.choice(countries))
- choices = set(choices) #dedupe
- choices = list(choices)
- spec += ",".join(choices)
- return spec
-
-def fakeBridge(orport=8080, running=True, stable=True, or_addresses=False,
- transports=False):
- nn = "bridge-%s"%random.randrange(0,1000000)
- ip = ipaddr.IPAddress(randomIP4())
- fp = "".join([random.choice("0123456789ABCDEF") for _ in xrange(40)])
- b = bridgedb.Bridges.Bridge(nn,ip,orport,fingerprint=fp)
- b.setStatus(running, stable)
-
- oraddrs = []
- if or_addresses:
- for i in xrange(8):
- # Only add or_addresses if they are valid. Otherwise, the test
- # will randomly fail if an invalid address is chosen:
- address = randomIP4String()
- portlist = addr.PortList(randomPortSpec())
- if addr.isValidIP(address):
- oraddrs.append((address, portlist,))
-
- for address, portlist in oraddrs:
- networkstatus.parseALine("{0}:{1}".format(address, portlist))
- try:
- portlist.add(b.or_addresses[address])
- except KeyError:
- pass
- finally:
- b.or_addresses[address] = portlist
-
- if transports:
- for i in xrange(0,8):
- b.transports.append(bridgedb.Bridges.PluggableTransport(b,
- random.choice(["obfs", "obfs2", "pt1"]),
- randomIP(), randomPort()))
- return b
-
-def fakeBridge6(orport=8080, running=True, stable=True, or_addresses=False,
- transports=False):
- nn = "bridge-%s"%random.randrange(0,1000000)
- ip = ipaddr.IPAddress(randomIP6())
- fp = "".join([random.choice("0123456789ABCDEF") for _ in xrange(40)])
- b = bridgedb.Bridges.Bridge(nn,ip,orport,fingerprint=fp)
- b.setStatus(running, stable)
-
- oraddrs = []
- if or_addresses:
- for i in xrange(8):
- # Only add or_addresses if they are valid. Otherwise, the test
- # will randomly fail if an invalid address is chosen:
- address = randomIP6()
- portlist = addr.PortList(randomPortSpec())
- if addr.isValidIP(address):
- address = bracketIP6(address)
- oraddrs.append((address, portlist,))
-
- for address, portlist in oraddrs:
- networkstatus.parseALine("{0}:{1}".format(address, portlist))
- try:
- portlist.add(b.or_addresses[address])
- except KeyError:
- pass
- finally:
- b.or_addresses[address] = portlist
-
- try:
- portlist.add(b.or_addresses[address])
- except KeyError:
- pass
- finally:
- b.or_addresses[address] = portlist
-
- if transports:
- for i in xrange(0,8):
- b.transports.append(bridgedb.Bridges.PluggableTransport(b,
- random.choice(["obfs", "obfs2", "pt1"]),
- randomIP(), randomPort()))
-
- return b
-
-def fake16Bridge(orport=8080, running=True, stable=True):
- nn = "bridge-%s"%random.randrange(0,1000000)
- ip = random16IP()
- fp = "".join([random.choice("0123456789ABCDEF") for _ in xrange(40)])
- b = bridgedb.Bridges.Bridge(nn,ip,orport,fingerprint=fp)
- b.setStatus(running, stable)
- return b
-
-simpleDesc = "router Unnamed %s %s 0 9030\n"\
-"opt fingerprint DEAD BEEF F00F DEAD BEEF F00F DEAD BEEF F00F DEAD\n"\
-"opt @purpose bridge\n"
-orAddress = "or-address %s:%s\n"
-def gettimestamp():
- ts = time.strftime("%Y-%m-%d %H:%M:%S")
- return "opt published %s\n" % ts
-
-class RhymesWith255Category:
- def contains(self, ip):
- return ip.endswith(".255")
-
-class EmailBridgeDistTests(unittest.TestCase):
- def setUp(self):
- self.fd, self.fname = tempfile.mkstemp()
- self.db = bridgedb.Storage.Database(self.fname)
- bridgedb.Storage.setDB(self.db)
- self.cur = self.db._conn.cursor()
-
- def tearDown(self):
- self.db.close()
- os.close(self.fd)
- os.unlink(self.fname)
-
- def testEmailRateLimit(self):
- db = self.db
- EMAIL_DOMAIN_MAP = {'example.com':'example.com'}
- d = bridgedb.Dist.EmailBasedDistributor(
- "Foo",
- {'example.com': 'example.com',
- 'dkim.example.com': 'dkim.example.com'},
- {'example.com': [], 'dkim.example.com': ['dkim']})
- for _ in xrange(256):
- d.insert(fakeBridge())
- d.getBridgesForEmail('abc@xxxxxxxxxxx', 1, 3)
- self.assertRaises(bridgedb.Dist.TooSoonEmail,
- d.getBridgesForEmail, 'abc@xxxxxxxxxxx', 1, 3)
- self.assertRaises(bridgedb.Dist.IgnoreEmail,
- d.getBridgesForEmail, 'abc@xxxxxxxxxxx', 1, 3)
-
- def testUnsupportedDomain(self):
- db = self.db
- self.assertRaises(bridgedb.parse.addr.UnsupportedDomain,
- bridgedb.parse.addr.normalizeEmail,
- 'bad@xxxxxxxxx',
- {'example.com':'example.com'},
- {'example.com':[]})
-
-class IPBridgeDistTests(unittest.TestCase):
- def dumbAreaMapper(self, ip):
- return ip
- def testBasicDist(self):
- d = bridgedb.Dist.IPBasedDistributor(self.dumbAreaMapper, 3, "Foo")
- for _ in xrange(256):
- d.insert(fakeBridge())
- n = d.getBridgesForIP("1.2.3.4", "x", 2)
- n2 = d.getBridgesForIP("1.2.3.4", "x", 2)
- self.assertEquals(n, n2)
-
- def testDistWithCategories(self):
- d = bridgedb.Dist.IPBasedDistributor(self.dumbAreaMapper, 3, "Foo",
- [RhymesWith255Category()])
- assert len(d.categories) == 1
- for _ in xrange(256):
- d.insert(fakeBridge())
-
- for _ in xrange(256):
- # Make sure that the categories do not overlap
- f = lambda: ".".join([str(random.randrange(1,255)) for _ in xrange(4)])
- g = lambda: ".".join([str(random.randrange(1,255)) for _ in xrange(3)] + ['255'])
- n = d.getBridgesForIP(g(), "x", 10)
- n2 = d.getBridgesForIP(f(), "x", 10)
-
- assert(len(n) > 0)
- assert(len(n2) > 0)
-
- for b in n:
- assert (b not in n2)
-
- for b in n2:
- assert (b not in n)
-
- #XXX: #6175 breaks this test!
- #def testDistWithPortRestrictions(self):
- # param = bridgedb.Bridges.BridgeRingParameters(needPorts=[(443, 1)])
- # d = bridgedb.Dist.IPBasedDistributor(self.dumbAreaMapper, 3, "Baz",
- # answerParameters=param)
- # for _ in xrange(32):
- # d.insert(fakeBridge(443))
- # for _ in range(256):
- # d.insert(fakeBridge())
- # for _ in xrange(32):
- # i = randomIP()
- # n = d.getBridgesForIP(i, "x", 5)
- # count = 0
- # fps = {}
- # for b in n:
- # fps[b.getID()] = 1
- # if b.orport == 443:
- # count += 1
- # self.assertEquals(len(fps), len(n))
- # self.assertEquals(len(fps), 5)
- # self.assertTrue(count >= 1)
-
- #def testDistWithFilter16(self):
- # d = bridgedb.Dist.IPBasedDistributor(self.dumbAreaMapper, 3, "Foo")
- # for _ in xrange(256):
- # d.insert(fake16Bridge())
- # n = d.getBridgesForIP("1.2.3.4", "x", 10)
-
- # slash16s = dict()
- # for bridge in n:
- # m = re.match(r'(\d+\.\d+)\.\d+\.\d+', bridge.ip)
- # upper16 = m.group(1)
- # self.assertTrue(upper16 not in slash16s)
- # slash16s[upper16] = True
-
- def testDistWithFilterIP6(self):
- d = bridgedb.Dist.IPBasedDistributor(self.dumbAreaMapper, 3, "Foo")
- for _ in xrange(250):
- d.insert(fakeBridge6(or_addresses=True))
- d.insert(fakeBridge(or_addresses=True))
-
- for i in xrange(500):
- bridges = d.getBridgesForIP(randomIP4String(),
- "faketimestamp",
- bridgeFilterRules=[filterBridgesByIP6])
- bridge = random.choice(bridges)
- bridge_line = bridge.getConfigLine(addressClass=ipaddr.IPv6Address)
- address, portlist = networkstatus.parseALine(bridge_line)
- assert type(ipaddr.IPAddress(address)) is ipaddr.IPv6Address
- assert filterBridgesByIP6(random.choice(bridges))
-
- def testDistWithFilterIP4(self):
- d = bridgedb.Dist.IPBasedDistributor(self.dumbAreaMapper, 3, "Foo")
- for _ in xrange(250):
- d.insert(fakeBridge6(or_addresses=True))
- d.insert(fakeBridge(or_addresses=True))
-
- for i in xrange(500):
- bridges = d.getBridgesForIP(randomIP4String(),
- "faketimestamp",
- bridgeFilterRules=[filterBridgesByIP4])
- bridge = random.choice(bridges)
- bridge_line = bridge.getConfigLine(addressClass=ipaddr.IPv4Address)
- address, portlist = networkstatus.parseALine(bridge_line)
- assert type(ipaddr.IPAddress(address)) is ipaddr.IPv4Address
- assert filterBridgesByIP4(random.choice(bridges))
-
- def testDistWithFilterBoth(self):
- d = bridgedb.Dist.IPBasedDistributor(self.dumbAreaMapper, 3, "Foo")
- for _ in xrange(250):
- d.insert(fakeBridge6(or_addresses=True))
- d.insert(fakeBridge(or_addresses=True))
-
- for i in xrange(50):
- bridges = d.getBridgesForIP(randomIP4String(),
- "faketimestamp", 1,
- bridgeFilterRules=[
- filterBridgesByIP4,
- filterBridgesByIP6])
- if bridges:
- t = bridges.pop()
- assert filterBridgesByIP4(t)
- assert filterBridgesByIP6(t)
- address, portlist = networkstatus.parseALine(
- t.getConfigLine(addressClass=ipaddr.IPv4Address))
- assert type(address) is ipaddr.IPv4Address
- address, portlist = networkstatus.parseALine(
- t.getConfigLine(addressClass=ipaddr.IPv6Address))
- assert type(address) is ipaddr.IPv6Address
-
-
- def testDistWithFilterAll(self):
- d = bridgedb.Dist.IPBasedDistributor(self.dumbAreaMapper, 3, "Foo")
- for _ in xrange(250):
- d.insert(fakeBridge6(or_addresses=True))
- d.insert(fakeBridge(or_addresses=True))
-
- for i in xrange(5):
- b = d.getBridgesForIP(randomIP4String(), "x", 1, bridgeFilterRules=[
- filterBridgesByOnlyIP4, filterBridgesByOnlyIP6])
- assert len(b) == 0
-
- def testDistWithFilterBlockedCountries(self):
- d = bridgedb.Dist.IPBasedDistributor(self.dumbAreaMapper, 3, "Foo")
- for _ in xrange(250):
- d.insert(fakeBridge6(or_addresses=True))
- d.insert(fakeBridge(or_addresses=True))
-
- for b in d.splitter.bridges:
- # china blocks all :-(
- for pt in b.transports:
- key = "%s:%s" % (pt.address, pt.port)
- b.blockingCountries[key] = set(['cn'])
- for address, portlist in b.or_addresses.items():
- for port in portlist:
- key = "%s:%s" % (address, port)
- b.blockingCountries[key] = set(['cn'])
- key = "%s:%s" % (b.ip, b.orport)
- b.blockingCountries[key] = set(['cn'])
-
- for i in xrange(5):
- b = d.getBridgesForIP(randomIP4String(), "x", 1, bridgeFilterRules=[
- filterBridgesByNotBlockedIn("cn")])
- assert len(b) == 0
- b = d.getBridgesForIP(randomIP4String(), "x", 1, bridgeFilterRules=[
- filterBridgesByNotBlockedIn("us")])
- assert len(b) > 0
-
- def testDistWithFilterBlockedCountriesAdvanced(self):
- d = bridgedb.Dist.IPBasedDistributor(self.dumbAreaMapper, 3, "Foo")
- for _ in xrange(250):
- d.insert(fakeBridge6(or_addresses=True, transports=True))
- d.insert(fakeBridge(or_addresses=True, transports=True))
-
- for b in d.splitter.bridges:
- # china blocks some transports
- for pt in b.transports:
- if random.choice(xrange(2)) > 0:
- key = "%s:%s" % (pt.address, pt.port)
- b.blockingCountries[key] = set(['cn'])
- for address, portlist in b.or_addresses.items():
- # china blocks some transports
- for port in portlist:
- if random.choice(xrange(2)) > 0:
- key = "%s:%s" % (address, port)
- b.blockingCountries[key] = set(['cn'])
- key = "%s:%s" % (b.ip, b.orport)
- b.blockingCountries[key] = set(['cn'])
-
- # we probably will get at least one bridge back!
- # it's pretty unlikely to lose a coin flip 250 times in a row
- for i in xrange(5):
- b = d.getBridgesForIP(randomIPString(), "x", 1,
- bridgeFilterRules=[
- filterBridgesByNotBlockedIn("cn", methodname='obfs2'),
- filterBridgesByTransport('obfs2'),
- ])
- try: assert len(b) > 0
- except AssertionError:
- print("epic fail")
- b = d.getBridgesForIP(randomIPString(), "x", 1, bridgeFilterRules=[
- filterBridgesByNotBlockedIn("us")])
- assert len(b) > 0
-
-
-class SQLStorageTests(unittest.TestCase):
- def setUp(self):
- self.fd, self.fname = tempfile.mkstemp()
- self.db = bridgedb.Storage.Database(self.fname)
- self.cur = self.db._conn.cursor()
-
- def tearDown(self):
- self.db.close()
- os.close(self.fd)
- os.unlink(self.fname)
-
- def assertCloseTo(self, a, b, delta=60):
- self.assertTrue(abs(a-b) <= delta)
-
- def testBridgeStorage(self):
- db = self.db
- B = bridgedb.Bridges.Bridge
- t = time.time()
- cur = self.cur
-
- k1 = "aaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbb"
- k2 = "abababababababababababababababababababab"
- k3 = "cccccccccccccccccccccccccccccccccccccccc"
- b1 = B("serv1", "1.2.3.4", 999, fingerprint=k1)
- b1_v2 = B("serv1", "1.2.3.5", 9099, fingerprint=k1)
- b2 = B("serv2", "2.3.4.5", 9990, fingerprint=k2)
- b3 = B("serv3", "2.3.4.6", 9008, fingerprint=k3)
- validRings = ["ring1", "ring2", "ring3"]
-
- r = db.insertBridgeAndGetRing(b1, "ring1", t, validRings)
- self.assertEquals(r, "ring1")
- r = db.insertBridgeAndGetRing(b1, "ring10", t+500, validRings)
- self.assertEquals(r, "ring1")
-
- cur.execute("SELECT distributor, address, or_port, first_seen, "
- "last_seen FROM Bridges WHERE hex_key = ?", (k1,))
- v = cur.fetchone()
- self.assertEquals(v,
- ("ring1", "1.2.3.4", 999,
- bridgedb.Storage.timeToStr(t),
- bridgedb.Storage.timeToStr(t+500)))
-
- r = db.insertBridgeAndGetRing(b1_v2, "ring99", t+800, validRings)
- self.assertEquals(r, "ring1")
- cur.execute("SELECT distributor, address, or_port, first_seen, "
- "last_seen FROM Bridges WHERE hex_key = ?", (k1,))
- v = cur.fetchone()
- self.assertEquals(v,
- ("ring1", "1.2.3.5", 9099,
- bridgedb.Storage.timeToStr(t),
- bridgedb.Storage.timeToStr(t+800)))
-
- db.insertBridgeAndGetRing(b2, "ring2", t, validRings)
- db.insertBridgeAndGetRing(b3, "ring3", t, validRings)
-
- cur.execute("SELECT COUNT(distributor) FROM Bridges")
- v = cur.fetchone()
- self.assertEquals(v, (3,))
-
- r = db.getEmailTime("abc@xxxxxxxxxxx")
- self.assertEquals(r, None)
- db.setEmailTime("abc@xxxxxxxxxxx", t)
- db.setEmailTime("def@xxxxxxxxxxx", t+1000)
- r = db.getEmailTime("abc@xxxxxxxxxxx")
- self.assertCloseTo(r, t)
- r = db.getEmailTime("def@xxxxxxxxxxx")
- self.assertCloseTo(r, t+1000)
- r = db.getEmailTime("ghi@xxxxxxxxxxx")
- self.assertEquals(r, None)
-
- db.cleanEmailedBridges(t+200)
- db.setEmailTime("def@xxxxxxxxxxx", t+5000)
- r = db.getEmailTime("abc@xxxxxxxxxxx")
- self.assertEquals(r, None)
- r = db.getEmailTime("def@xxxxxxxxxxx")
- self.assertCloseTo(r, t+5000)
- cur.execute("SELECT * FROM EmailedBridges")
- self.assertEquals(len(cur.fetchall()), 1)
-
- db.addBridgeBlock(b2.fingerprint, 'us')
- self.assertEquals(db.isBlocked(b2.fingerprint, 'us'), True)
- db.delBridgeBlock(b2.fingerprint, 'us')
- self.assertEquals(db.isBlocked(b2.fingerprint, 'us'), False)
- db.addBridgeBlock(b2.fingerprint, 'uk')
- db.addBridgeBlock(b3.fingerprint, 'uk')
- self.assertEquals(set([b2.fingerprint, b3.fingerprint]),
- set(db.getBlockedBridges('uk')))
-
- db.addBridgeBlock(b2.fingerprint, 'cn')
- db.addBridgeBlock(b2.fingerprint, 'de')
- db.addBridgeBlock(b2.fingerprint, 'jp')
- db.addBridgeBlock(b2.fingerprint, 'se')
- db.addBridgeBlock(b2.fingerprint, 'kr')
-
- self.assertEquals(set(db.getBlockingCountries(b2.fingerprint)),
- set(['uk', 'cn', 'de', 'jp', 'se', 'kr']))
- self.assertEquals(db.getWarnedEmail("def@xxxxxxxxxxx"), False)
- db.setWarnedEmail("def@xxxxxxxxxxx")
- self.assertEquals(db.getWarnedEmail("def@xxxxxxxxxxx"), True)
- db.setWarnedEmail("def@xxxxxxxxxxx", False)
- self.assertEquals(db.getWarnedEmail("def@xxxxxxxxxxx"), False)
-
- db.setWarnedEmail("def@xxxxxxxxxxx")
- self.assertEquals(db.getWarnedEmail("def@xxxxxxxxxxx"), True)
- db.cleanWarnedEmails(t+200)
- self.assertEquals(db.getWarnedEmail("def@xxxxxxxxxxx"), False)
-
-class ParseDescFileTests(unittest.TestCase):
- def testSimpleDesc(self):
- test = ""
-
- for i in range(100):
- test+= "".join(simpleDesc % (randomIP(), randomPort()))
- test+=gettimestamp()
- test+="router-signature\n"
-
- bs = [b for b in bridgedb.Bridges.parseDescFile(test.split('\n'))]
- self.assertEquals(len(bs), 100)
-
- for b in bs:
- b.assertOK()
-
- def testSingleOrAddress(self):
- test = ""
-
- for i in range(100):
- test+= simpleDesc % (randomIP(), randomPort())
- test+= orAddress % (randomIP(),randomPort())
- test+=gettimestamp()
- test+= "router-signature\n"
-
- bs = [b for b in bridgedb.Bridges.parseDescFile(test.split('\n'))]
- self.assertEquals(len(bs), 100)
-
- for b in bs:
- b.assertOK()
-
- def testMultipleOrAddress(self):
- test = ""
- for i in range(100):
- test+= simpleDesc % (randomIPString(), randomPort())
- for i in xrange(8):
- test+= orAddress % (randomIPString(),randomPortSpec())
- test+=gettimestamp()
- test+= "router-signature\n"
-
- bs = [b for b in bridgedb.Bridges.parseDescFile(test.split('\n'))]
- self.assertEquals(len(bs), 100)
-
- for b in bs:
- b.assertOK()
-
- def testConvolutedOrAddress(self):
- test = ""
- for i in range(100):
- test+= simpleDesc % (randomIPString(), randomPort())
- for i in xrange(8):
- test+= orAddress % (randomIPString(),randomPortSpec())
- test+=gettimestamp()
- test+= "router-signature\n"
-
- bs = [b for b in bridgedb.Bridges.parseDescFile(test.split('\n'))]
- self.assertEquals(len(bs), 100)
-
- for b in bs:
- b.assertOK()
-
- def testParseCountryBlockFile(self):
- simpleBlock = "%s:%s %s\n"
- countries = ['us', 'nl', 'de', 'cz', 'sk', 'as', 'si', 'it']
- test = str()
- for i in range(100):
- test += simpleBlock % (randomIPString(), randomPort(),
- randomCountrySpec())
- test+=gettimestamp()
-
- for a,p,c in bridgedb.Bridges.parseCountryBlockFile(test.split('\n')):
- assert type(a) in (ipaddr.IPv6Address, ipaddr.IPv4Address)
- assert isinstance(p, addr.PortList)
- assert isinstance(c, list)
- assert len(c) > 0
- for y in c:
- assert y in countries
- #print "address: %s" % a
- #print "portlist: %s" % p
- #print "countries: %s" % c
-
-class BridgeStabilityTests(unittest.TestCase):
- def setUp(self):
- self.fd, self.fname = tempfile.mkstemp()
- self.db = bridgedb.Storage.Database(self.fname)
- bridgedb.Storage.setDB(self.db)
- self.cur = self.db._conn.cursor()
-
- def tearDown(self):
- self.db.close()
- os.close(self.fd)
- os.unlink(self.fname)
-
- def testAddOrUpdateSingleBridgeHistory(self):
- db = self.db
- b = fakeBridge()
- timestamp = time.time()
- bhe = bridgedb.Stability.addOrUpdateBridgeHistory(b, timestamp)
- assert isinstance(bhe, BridgeHistory)
- assert isinstance(db.getBridgeHistory(b.fingerprint), BridgeHistory)
- assert len([y for y in db.getAllBridgeHistory()]) == 1
-
- def testDeletingSingleBridgeHistory(self):
- db = self.db
- b = fakeBridge()
- timestamp = time.time()
- bhe = bridgedb.Stability.addOrUpdateBridgeHistory(b, timestamp)
- assert isinstance(bhe, BridgeHistory)
- assert isinstance(db.getBridgeHistory(b.fingerprint), BridgeHistory)
- db.delBridgeHistory(b.fingerprint)
- assert db.getBridgeHistory(b.fingerprint) is None
- assert len([y for y in db.getAllBridgeHistory()]) == 0
-
- def testTOSA(self):
- db = self.db
- b = random.choice([fakeBridge,fakeBridge6])()
- def timestampSeries(x):
- for i in xrange(61):
- yield (i+1)*60*30 + x # 30 minute intervals
- now = time.time()
- time_on_address = long(60*30*60) # 30 hours
- downtime = 60*60*random.randint(0,4) # random hours of downtime
-
- for t in timestampSeries(now):
- bridgedb.Stability.addOrUpdateBridgeHistory(b,t)
- assert db.getBridgeHistory(b.fingerprint).tosa == time_on_address
-
- b.orport += 1
-
- for t in timestampSeries(now + time_on_address + downtime):
- bhe = bridgedb.Stability.addOrUpdateBridgeHistory(b,t)
- assert db.getBridgeHistory(b.fingerprint).tosa == time_on_address + downtime
-
- def testLastSeenWithDifferentAddressAndPort(self):
- db = self.db
- for i in xrange(10):
- num_desc = 30
- time_start = time.time()
- ts = [ 60*30*(i+1) + time_start for i in xrange(num_desc) ]
- b = random.choice([fakeBridge(), fakeBridge6()])
- [ bridgedb.Stability.addOrUpdateBridgeHistory(b, t) for t in ts ]
-
- # change the port
- b.orport = b.orport+1
- last_seen = ts[-1]
- ts = [ 60*30*(i+1) + last_seen for i in xrange(num_desc) ]
- [ bridgedb.Stability.addOrUpdateBridgeHistory(b, t) for t in ts ]
- b = db.getBridgeHistory(b.fingerprint)
- assert b.tosa == ts[-1] - last_seen
- assert (long(last_seen*1000) == b.lastSeenWithDifferentAddressAndPort)
- assert (long(ts[-1]*1000) == b.lastSeenWithThisAddressAndPort)
-
- def testFamiliar(self):
- # create some bridges
- # XXX: slow
- num_bridges = 10
- num_desc = 4*48 # 30m intervals, 48 per day
- time_start = time.time()
- bridges = [ fakeBridge() for x in xrange(num_bridges) ]
- t = time.time()
- ts = [ (i+1)*60*30+t for i in xrange(num_bridges) ]
- for b in bridges:
- time_series = [ 60*30*(i+1) + time_start for i in xrange(num_desc) ]
- [ bridgedb.Stability.addOrUpdateBridgeHistory(b, i) for i in time_series ]
- assert None not in bridges
- # +1 to avoid rounding errors
- assert bridges[-(num_bridges/8 + 1)].familiar == True
-
- def testDiscountAndPruneBridgeHistory(self):
- """ Test pruning of old Bridge History """
- if os.environ.get('TRAVIS'):
- self.skipTest("Hangs on Travis-CI.")
-
- db = self.db
-
- # make a bunch of bridges
- num_bridges = 20
- time_start = time.time()
- bridges = [random.choice([fakeBridge, fakeBridge6])()
- for i in xrange(num_bridges)]
-
- # run some of the bridges for the full time series
- running = bridges[:num_bridges/2]
- # and some that are not
- expired = bridges[num_bridges/2:]
-
- for b in running: assert b not in expired
-
- # Solving:
- # 1 discount event per 12 hours, 24 descriptors 30m apart
- num_successful = random.randint(2,60)
- # figure out how many intervals it will take for weightedUptime to
- # decay to < 1
- num_desc = int(30*log(1/float(num_successful*30*60))/(-0.05))
- timeseries = [ 60*30*(i+1) + time_start for i in xrange(num_desc) ]
-
- for i in timeseries:
- for b in running:
- bridgedb.Stability.addOrUpdateBridgeHistory(b, i)
-
- if num_successful > 0:
- for b in expired:
- bridgedb.Stability.addOrUpdateBridgeHistory(b, i)
- num_successful -= 1
-
- # now we expect to see the bridge has been removed from history
- for bridge in expired:
- b = db.getBridgeHistory(bridge.fingerprint)
- assert b is None
- # and make sure none of the others have
- for bridge in running:
- b = db.getBridgeHistory(bridge.fingerprint)
- assert b is not None
-
-def testSuite():
- suite = unittest.TestSuite()
- loader = unittest.TestLoader()
-
- for klass in [IPBridgeDistTests, SQLStorageTests, EmailBridgeDistTests,
- ParseDescFileTests, BridgeStabilityTests]:
- suite.addTest(loader.loadTestsFromTestCase(klass))
-
- for module in [ bridgedb.Bridges,
- bridgedb.Main,
- bridgedb.Dist,
- bridgedb.schedule ]:
- suite.addTest(doctest.DocTestSuite(module))
-
- return suite
-
-def main():
- suppressWarnings()
-
- unittest.TextTestRunner(verbosity=1).run(testSuite())
-
diff --git a/lib/bridgedb/test/legacy_Tests.py b/lib/bridgedb/test/legacy_Tests.py
new file mode 100644
index 0000000..fa7a13c
--- /dev/null
+++ b/lib/bridgedb/test/legacy_Tests.py
@@ -0,0 +1,785 @@
+# BridgeDB by Nick Mathewson.
+# Copyright (c) 2007-2009, The Tor Project, Inc.
+# See LICENSE for licensing information
+
+"""These are legacy integration and unittests which historically lived at
+``lib/bridgedb/Tests.py``. They have been moved here to keep the test code
+separate from the production codebase.
+"""
+
+from __future__ import print_function
+
+import doctest
+import os
+import random
+import sqlite3
+import tempfile
+import unittest
+import warnings
+import time
+from datetime import datetime
+
+import bridgedb.Bridges
+import bridgedb.Main
+import bridgedb.Dist
+import bridgedb.schedule
+import bridgedb.Storage
+import re
+import ipaddr
+
+from bridgedb.Filters import filterBridgesByIP4
+from bridgedb.Filters import filterBridgesByIP6
+from bridgedb.Filters import filterBridgesByOnlyIP4
+from bridgedb.Filters import filterBridgesByOnlyIP6
+from bridgedb.Filters import filterBridgesByTransport
+from bridgedb.Filters import filterBridgesByNotBlockedIn
+
+from bridgedb.Stability import BridgeHistory
+
+from bridgedb.parse import addr
+from bridgedb.parse import networkstatus
+
+from math import log
+
+def suppressWarnings():
+ warnings.filterwarnings('ignore', '.*tmpnam.*')
+
+def randomIP():
+ if random.choice(xrange(2)):
+ return randomIP4()
+ return randomIP6()
+
+def randomIP4():
+ return ipaddr.IPv4Address(random.getrandbits(32))
+
+def randomIP4String():
+ return randomIP4().compressed
+
+def randomIP6():
+ return ipaddr.IPv6Address(random.getrandbits(128))
+
+def randomIP6String():
+ return bracketIP6(randomIP6().compressed)
+
+def randomIPString():
+ if random.choice(xrange(2)):
+ return randomIP4String()
+ return randomIP6String()
+
+def bracketIP6(ip):
+ """Put brackets around an IPv6 address, just as tor does."""
+ return "[%s]" % ip
+
+def random16IP():
+ upper = "123.123." # same 16
+ lower = ".".join([str(random.randrange(1,256)) for _ in xrange(2)])
+ return upper+lower
+
+def randomPort():
+ return random.randint(1,65535)
+
+def randomPortSpec():
+ """
+ returns a random list of ports
+ """
+ ports = []
+ for i in range(0,24):
+ ports.append(random.randint(1,65535))
+ ports.sort(reverse=True)
+
+ portspec = ""
+ for i in range(0,16):
+ portspec += "%d," % random.choice(ports)
+ portspec = portspec.rstrip(',') #remove trailing ,
+ return portspec
+
+def randomCountry():
+ countries = ['us', 'nl', 'de', 'cz', 'sk', 'as', 'si', 'it']
+ #XXX: load from geoip
+ return random.choice(countries)
+
+def randomCountrySpec():
+ countries = ['us', 'nl', 'de', 'cz', 'sk', 'as', 'si', 'it']
+ #XXX: load from geoip
+ spec = ""
+ choices = []
+ for i in xrange(10):
+ choices.append(random.choice(countries))
+ choices = set(choices) #dedupe
+ choices = list(choices)
+ spec += ",".join(choices)
+ return spec
+
+def fakeBridge(orport=8080, running=True, stable=True, or_addresses=False,
+ transports=False):
+ nn = "bridge-%s"%random.randrange(0,1000000)
+ ip = ipaddr.IPAddress(randomIP4())
+ fp = "".join([random.choice("0123456789ABCDEF") for _ in xrange(40)])
+ b = bridgedb.Bridges.Bridge(nn,ip,orport,fingerprint=fp)
+ b.setStatus(running, stable)
+
+ oraddrs = []
+ if or_addresses:
+ for i in xrange(8):
+ # Only add or_addresses if they are valid. Otherwise, the test
+ # will randomly fail if an invalid address is chosen:
+ address = randomIP4String()
+ portlist = addr.PortList(randomPortSpec())
+ if addr.isValidIP(address):
+ oraddrs.append((address, portlist,))
+
+ for address, portlist in oraddrs:
+ networkstatus.parseALine("{0}:{1}".format(address, portlist))
+ try:
+ portlist.add(b.or_addresses[address])
+ except KeyError:
+ pass
+ finally:
+ b.or_addresses[address] = portlist
+
+ if transports:
+ for i in xrange(0,8):
+ b.transports.append(bridgedb.Bridges.PluggableTransport(b,
+ random.choice(["obfs", "obfs2", "pt1"]),
+ randomIP(), randomPort()))
+ return b
+
+def fakeBridge6(orport=8080, running=True, stable=True, or_addresses=False,
+ transports=False):
+ nn = "bridge-%s"%random.randrange(0,1000000)
+ ip = ipaddr.IPAddress(randomIP6())
+ fp = "".join([random.choice("0123456789ABCDEF") for _ in xrange(40)])
+ b = bridgedb.Bridges.Bridge(nn,ip,orport,fingerprint=fp)
+ b.setStatus(running, stable)
+
+ oraddrs = []
+ if or_addresses:
+ for i in xrange(8):
+ # Only add or_addresses if they are valid. Otherwise, the test
+ # will randomly fail if an invalid address is chosen:
+ address = randomIP6()
+ portlist = addr.PortList(randomPortSpec())
+ if addr.isValidIP(address):
+ address = bracketIP6(address)
+ oraddrs.append((address, portlist,))
+
+ for address, portlist in oraddrs:
+ networkstatus.parseALine("{0}:{1}".format(address, portlist))
+ try:
+ portlist.add(b.or_addresses[address])
+ except KeyError:
+ pass
+ finally:
+ b.or_addresses[address] = portlist
+
+ try:
+ portlist.add(b.or_addresses[address])
+ except KeyError:
+ pass
+ finally:
+ b.or_addresses[address] = portlist
+
+ if transports:
+ for i in xrange(0,8):
+ b.transports.append(bridgedb.Bridges.PluggableTransport(b,
+ random.choice(["obfs", "obfs2", "pt1"]),
+ randomIP(), randomPort()))
+
+ return b
+
+def fake16Bridge(orport=8080, running=True, stable=True):
+ nn = "bridge-%s"%random.randrange(0,1000000)
+ ip = random16IP()
+ fp = "".join([random.choice("0123456789ABCDEF") for _ in xrange(40)])
+ b = bridgedb.Bridges.Bridge(nn,ip,orport,fingerprint=fp)
+ b.setStatus(running, stable)
+ return b
+
+simpleDesc = "router Unnamed %s %s 0 9030\n"\
+"opt fingerprint DEAD BEEF F00F DEAD BEEF F00F DEAD BEEF F00F DEAD\n"\
+"opt @purpose bridge\n"
+orAddress = "or-address %s:%s\n"
+def gettimestamp():
+ ts = time.strftime("%Y-%m-%d %H:%M:%S")
+ return "opt published %s\n" % ts
+
+class RhymesWith255Category:
+ def contains(self, ip):
+ return ip.endswith(".255")
+
+class EmailBridgeDistTests(unittest.TestCase):
+ def setUp(self):
+ self.fd, self.fname = tempfile.mkstemp()
+ self.db = bridgedb.Storage.Database(self.fname)
+ bridgedb.Storage.setDB(self.db)
+ self.cur = self.db._conn.cursor()
+
+ def tearDown(self):
+ self.db.close()
+ os.close(self.fd)
+ os.unlink(self.fname)
+
+ def testEmailRateLimit(self):
+ db = self.db
+ EMAIL_DOMAIN_MAP = {'example.com':'example.com'}
+ d = bridgedb.Dist.EmailBasedDistributor(
+ "Foo",
+ {'example.com': 'example.com',
+ 'dkim.example.com': 'dkim.example.com'},
+ {'example.com': [], 'dkim.example.com': ['dkim']})
+ for _ in xrange(256):
+ d.insert(fakeBridge())
+ d.getBridgesForEmail('abc@xxxxxxxxxxx', 1, 3)
+ self.assertRaises(bridgedb.Dist.TooSoonEmail,
+ d.getBridgesForEmail, 'abc@xxxxxxxxxxx', 1, 3)
+ self.assertRaises(bridgedb.Dist.IgnoreEmail,
+ d.getBridgesForEmail, 'abc@xxxxxxxxxxx', 1, 3)
+
+ def testUnsupportedDomain(self):
+ db = self.db
+ self.assertRaises(bridgedb.parse.addr.UnsupportedDomain,
+ bridgedb.parse.addr.normalizeEmail,
+ 'bad@xxxxxxxxx',
+ {'example.com':'example.com'},
+ {'example.com':[]})
+
+class IPBridgeDistTests(unittest.TestCase):
+ def dumbAreaMapper(self, ip):
+ return ip
+ def testBasicDist(self):
+ d = bridgedb.Dist.IPBasedDistributor(self.dumbAreaMapper, 3, "Foo")
+ for _ in xrange(256):
+ d.insert(fakeBridge())
+ n = d.getBridgesForIP("1.2.3.4", "x", 2)
+ n2 = d.getBridgesForIP("1.2.3.4", "x", 2)
+ self.assertEquals(n, n2)
+
+ def testDistWithCategories(self):
+ d = bridgedb.Dist.IPBasedDistributor(self.dumbAreaMapper, 3, "Foo",
+ [RhymesWith255Category()])
+ assert len(d.categories) == 1
+ for _ in xrange(256):
+ d.insert(fakeBridge())
+
+ for _ in xrange(256):
+ # Make sure that the categories do not overlap
+ f = lambda: ".".join([str(random.randrange(1,255)) for _ in xrange(4)])
+ g = lambda: ".".join([str(random.randrange(1,255)) for _ in xrange(3)] + ['255'])
+ n = d.getBridgesForIP(g(), "x", 10)
+ n2 = d.getBridgesForIP(f(), "x", 10)
+
+ assert(len(n) > 0)
+ assert(len(n2) > 0)
+
+ for b in n:
+ assert (b not in n2)
+
+ for b in n2:
+ assert (b not in n)
+
+ #XXX: #6175 breaks this test!
+ #def testDistWithPortRestrictions(self):
+ # param = bridgedb.Bridges.BridgeRingParameters(needPorts=[(443, 1)])
+ # d = bridgedb.Dist.IPBasedDistributor(self.dumbAreaMapper, 3, "Baz",
+ # answerParameters=param)
+ # for _ in xrange(32):
+ # d.insert(fakeBridge(443))
+ # for _ in range(256):
+ # d.insert(fakeBridge())
+ # for _ in xrange(32):
+ # i = randomIP()
+ # n = d.getBridgesForIP(i, "x", 5)
+ # count = 0
+ # fps = {}
+ # for b in n:
+ # fps[b.getID()] = 1
+ # if b.orport == 443:
+ # count += 1
+ # self.assertEquals(len(fps), len(n))
+ # self.assertEquals(len(fps), 5)
+ # self.assertTrue(count >= 1)
+
+ #def testDistWithFilter16(self):
+ # d = bridgedb.Dist.IPBasedDistributor(self.dumbAreaMapper, 3, "Foo")
+ # for _ in xrange(256):
+ # d.insert(fake16Bridge())
+ # n = d.getBridgesForIP("1.2.3.4", "x", 10)
+
+ # slash16s = dict()
+ # for bridge in n:
+ # m = re.match(r'(\d+\.\d+)\.\d+\.\d+', bridge.ip)
+ # upper16 = m.group(1)
+ # self.assertTrue(upper16 not in slash16s)
+ # slash16s[upper16] = True
+
+ def testDistWithFilterIP6(self):
+ d = bridgedb.Dist.IPBasedDistributor(self.dumbAreaMapper, 3, "Foo")
+ for _ in xrange(250):
+ d.insert(fakeBridge6(or_addresses=True))
+ d.insert(fakeBridge(or_addresses=True))
+
+ for i in xrange(500):
+ bridges = d.getBridgesForIP(randomIP4String(),
+ "faketimestamp",
+ bridgeFilterRules=[filterBridgesByIP6])
+ bridge = random.choice(bridges)
+ bridge_line = bridge.getConfigLine(addressClass=ipaddr.IPv6Address)
+ address, portlist = networkstatus.parseALine(bridge_line)
+ assert type(ipaddr.IPAddress(address)) is ipaddr.IPv6Address
+ assert filterBridgesByIP6(random.choice(bridges))
+
+ def testDistWithFilterIP4(self):
+ d = bridgedb.Dist.IPBasedDistributor(self.dumbAreaMapper, 3, "Foo")
+ for _ in xrange(250):
+ d.insert(fakeBridge6(or_addresses=True))
+ d.insert(fakeBridge(or_addresses=True))
+
+ for i in xrange(500):
+ bridges = d.getBridgesForIP(randomIP4String(),
+ "faketimestamp",
+ bridgeFilterRules=[filterBridgesByIP4])
+ bridge = random.choice(bridges)
+ bridge_line = bridge.getConfigLine(addressClass=ipaddr.IPv4Address)
+ address, portlist = networkstatus.parseALine(bridge_line)
+ assert type(ipaddr.IPAddress(address)) is ipaddr.IPv4Address
+ assert filterBridgesByIP4(random.choice(bridges))
+
+ def testDistWithFilterBoth(self):
+ d = bridgedb.Dist.IPBasedDistributor(self.dumbAreaMapper, 3, "Foo")
+ for _ in xrange(250):
+ d.insert(fakeBridge6(or_addresses=True))
+ d.insert(fakeBridge(or_addresses=True))
+
+ for i in xrange(50):
+ bridges = d.getBridgesForIP(randomIP4String(),
+ "faketimestamp", 1,
+ bridgeFilterRules=[
+ filterBridgesByIP4,
+ filterBridgesByIP6])
+ if bridges:
+ t = bridges.pop()
+ assert filterBridgesByIP4(t)
+ assert filterBridgesByIP6(t)
+ address, portlist = networkstatus.parseALine(
+ t.getConfigLine(addressClass=ipaddr.IPv4Address))
+ assert type(address) is ipaddr.IPv4Address
+ address, portlist = networkstatus.parseALine(
+ t.getConfigLine(addressClass=ipaddr.IPv6Address))
+ assert type(address) is ipaddr.IPv6Address
+
+
+ def testDistWithFilterAll(self):
+ d = bridgedb.Dist.IPBasedDistributor(self.dumbAreaMapper, 3, "Foo")
+ for _ in xrange(250):
+ d.insert(fakeBridge6(or_addresses=True))
+ d.insert(fakeBridge(or_addresses=True))
+
+ for i in xrange(5):
+ b = d.getBridgesForIP(randomIP4String(), "x", 1, bridgeFilterRules=[
+ filterBridgesByOnlyIP4, filterBridgesByOnlyIP6])
+ assert len(b) == 0
+
+ def testDistWithFilterBlockedCountries(self):
+ d = bridgedb.Dist.IPBasedDistributor(self.dumbAreaMapper, 3, "Foo")
+ for _ in xrange(250):
+ d.insert(fakeBridge6(or_addresses=True))
+ d.insert(fakeBridge(or_addresses=True))
+
+ for b in d.splitter.bridges:
+ # china blocks all :-(
+ for pt in b.transports:
+ key = "%s:%s" % (pt.address, pt.port)
+ b.blockingCountries[key] = set(['cn'])
+ for address, portlist in b.or_addresses.items():
+ for port in portlist:
+ key = "%s:%s" % (address, port)
+ b.blockingCountries[key] = set(['cn'])
+ key = "%s:%s" % (b.ip, b.orport)
+ b.blockingCountries[key] = set(['cn'])
+
+ for i in xrange(5):
+ b = d.getBridgesForIP(randomIP4String(), "x", 1, bridgeFilterRules=[
+ filterBridgesByNotBlockedIn("cn")])
+ assert len(b) == 0
+ b = d.getBridgesForIP(randomIP4String(), "x", 1, bridgeFilterRules=[
+ filterBridgesByNotBlockedIn("us")])
+ assert len(b) > 0
+
+ def testDistWithFilterBlockedCountriesAdvanced(self):
+ d = bridgedb.Dist.IPBasedDistributor(self.dumbAreaMapper, 3, "Foo")
+ for _ in xrange(250):
+ d.insert(fakeBridge6(or_addresses=True, transports=True))
+ d.insert(fakeBridge(or_addresses=True, transports=True))
+
+ for b in d.splitter.bridges:
+ # china blocks some transports
+ for pt in b.transports:
+ if random.choice(xrange(2)) > 0:
+ key = "%s:%s" % (pt.address, pt.port)
+ b.blockingCountries[key] = set(['cn'])
+ for address, portlist in b.or_addresses.items():
+ # china blocks some transports
+ for port in portlist:
+ if random.choice(xrange(2)) > 0:
+ key = "%s:%s" % (address, port)
+ b.blockingCountries[key] = set(['cn'])
+ key = "%s:%s" % (b.ip, b.orport)
+ b.blockingCountries[key] = set(['cn'])
+
+ # we probably will get at least one bridge back!
+ # it's pretty unlikely to lose a coin flip 250 times in a row
+ for i in xrange(5):
+ b = d.getBridgesForIP(randomIPString(), "x", 1,
+ bridgeFilterRules=[
+ filterBridgesByNotBlockedIn("cn", methodname='obfs2'),
+ filterBridgesByTransport('obfs2'),
+ ])
+ try: assert len(b) > 0
+ except AssertionError:
+ print("epic fail")
+ b = d.getBridgesForIP(randomIPString(), "x", 1, bridgeFilterRules=[
+ filterBridgesByNotBlockedIn("us")])
+ assert len(b) > 0
+
+
+class SQLStorageTests(unittest.TestCase):
+ def setUp(self):
+ self.fd, self.fname = tempfile.mkstemp()
+ self.db = bridgedb.Storage.Database(self.fname)
+ self.cur = self.db._conn.cursor()
+
+ def tearDown(self):
+ self.db.close()
+ os.close(self.fd)
+ os.unlink(self.fname)
+
+ def assertCloseTo(self, a, b, delta=60):
+ self.assertTrue(abs(a-b) <= delta)
+
+ def testBridgeStorage(self):
+ db = self.db
+ B = bridgedb.Bridges.Bridge
+ t = time.time()
+ cur = self.cur
+
+ k1 = "aaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbb"
+ k2 = "abababababababababababababababababababab"
+ k3 = "cccccccccccccccccccccccccccccccccccccccc"
+ b1 = B("serv1", "1.2.3.4", 999, fingerprint=k1)
+ b1_v2 = B("serv1", "1.2.3.5", 9099, fingerprint=k1)
+ b2 = B("serv2", "2.3.4.5", 9990, fingerprint=k2)
+ b3 = B("serv3", "2.3.4.6", 9008, fingerprint=k3)
+ validRings = ["ring1", "ring2", "ring3"]
+
+ r = db.insertBridgeAndGetRing(b1, "ring1", t, validRings)
+ self.assertEquals(r, "ring1")
+ r = db.insertBridgeAndGetRing(b1, "ring10", t+500, validRings)
+ self.assertEquals(r, "ring1")
+
+ cur.execute("SELECT distributor, address, or_port, first_seen, "
+ "last_seen FROM Bridges WHERE hex_key = ?", (k1,))
+ v = cur.fetchone()
+ self.assertEquals(v,
+ ("ring1", "1.2.3.4", 999,
+ bridgedb.Storage.timeToStr(t),
+ bridgedb.Storage.timeToStr(t+500)))
+
+ r = db.insertBridgeAndGetRing(b1_v2, "ring99", t+800, validRings)
+ self.assertEquals(r, "ring1")
+ cur.execute("SELECT distributor, address, or_port, first_seen, "
+ "last_seen FROM Bridges WHERE hex_key = ?", (k1,))
+ v = cur.fetchone()
+ self.assertEquals(v,
+ ("ring1", "1.2.3.5", 9099,
+ bridgedb.Storage.timeToStr(t),
+ bridgedb.Storage.timeToStr(t+800)))
+
+ db.insertBridgeAndGetRing(b2, "ring2", t, validRings)
+ db.insertBridgeAndGetRing(b3, "ring3", t, validRings)
+
+ cur.execute("SELECT COUNT(distributor) FROM Bridges")
+ v = cur.fetchone()
+ self.assertEquals(v, (3,))
+
+ r = db.getEmailTime("abc@xxxxxxxxxxx")
+ self.assertEquals(r, None)
+ db.setEmailTime("abc@xxxxxxxxxxx", t)
+ db.setEmailTime("def@xxxxxxxxxxx", t+1000)
+ r = db.getEmailTime("abc@xxxxxxxxxxx")
+ self.assertCloseTo(r, t)
+ r = db.getEmailTime("def@xxxxxxxxxxx")
+ self.assertCloseTo(r, t+1000)
+ r = db.getEmailTime("ghi@xxxxxxxxxxx")
+ self.assertEquals(r, None)
+
+ db.cleanEmailedBridges(t+200)
+ db.setEmailTime("def@xxxxxxxxxxx", t+5000)
+ r = db.getEmailTime("abc@xxxxxxxxxxx")
+ self.assertEquals(r, None)
+ r = db.getEmailTime("def@xxxxxxxxxxx")
+ self.assertCloseTo(r, t+5000)
+ cur.execute("SELECT * FROM EmailedBridges")
+ self.assertEquals(len(cur.fetchall()), 1)
+
+ db.addBridgeBlock(b2.fingerprint, 'us')
+ self.assertEquals(db.isBlocked(b2.fingerprint, 'us'), True)
+ db.delBridgeBlock(b2.fingerprint, 'us')
+ self.assertEquals(db.isBlocked(b2.fingerprint, 'us'), False)
+ db.addBridgeBlock(b2.fingerprint, 'uk')
+ db.addBridgeBlock(b3.fingerprint, 'uk')
+ self.assertEquals(set([b2.fingerprint, b3.fingerprint]),
+ set(db.getBlockedBridges('uk')))
+
+ db.addBridgeBlock(b2.fingerprint, 'cn')
+ db.addBridgeBlock(b2.fingerprint, 'de')
+ db.addBridgeBlock(b2.fingerprint, 'jp')
+ db.addBridgeBlock(b2.fingerprint, 'se')
+ db.addBridgeBlock(b2.fingerprint, 'kr')
+
+ self.assertEquals(set(db.getBlockingCountries(b2.fingerprint)),
+ set(['uk', 'cn', 'de', 'jp', 'se', 'kr']))
+ self.assertEquals(db.getWarnedEmail("def@xxxxxxxxxxx"), False)
+ db.setWarnedEmail("def@xxxxxxxxxxx")
+ self.assertEquals(db.getWarnedEmail("def@xxxxxxxxxxx"), True)
+ db.setWarnedEmail("def@xxxxxxxxxxx", False)
+ self.assertEquals(db.getWarnedEmail("def@xxxxxxxxxxx"), False)
+
+ db.setWarnedEmail("def@xxxxxxxxxxx")
+ self.assertEquals(db.getWarnedEmail("def@xxxxxxxxxxx"), True)
+ db.cleanWarnedEmails(t+200)
+ self.assertEquals(db.getWarnedEmail("def@xxxxxxxxxxx"), False)
+
+class ParseDescFileTests(unittest.TestCase):
+ def testSimpleDesc(self):
+ test = ""
+
+ for i in range(100):
+ test+= "".join(simpleDesc % (randomIP(), randomPort()))
+ test+=gettimestamp()
+ test+="router-signature\n"
+
+ bs = [b for b in bridgedb.Bridges.parseDescFile(test.split('\n'))]
+ self.assertEquals(len(bs), 100)
+
+ for b in bs:
+ b.assertOK()
+
+ def testSingleOrAddress(self):
+ test = ""
+
+ for i in range(100):
+ test+= simpleDesc % (randomIP(), randomPort())
+ test+= orAddress % (randomIP(),randomPort())
+ test+=gettimestamp()
+ test+= "router-signature\n"
+
+ bs = [b for b in bridgedb.Bridges.parseDescFile(test.split('\n'))]
+ self.assertEquals(len(bs), 100)
+
+ for b in bs:
+ b.assertOK()
+
+ def testMultipleOrAddress(self):
+ test = ""
+ for i in range(100):
+ test+= simpleDesc % (randomIPString(), randomPort())
+ for i in xrange(8):
+ test+= orAddress % (randomIPString(),randomPortSpec())
+ test+=gettimestamp()
+ test+= "router-signature\n"
+
+ bs = [b for b in bridgedb.Bridges.parseDescFile(test.split('\n'))]
+ self.assertEquals(len(bs), 100)
+
+ for b in bs:
+ b.assertOK()
+
+ def testConvolutedOrAddress(self):
+ test = ""
+ for i in range(100):
+ test+= simpleDesc % (randomIPString(), randomPort())
+ for i in xrange(8):
+ test+= orAddress % (randomIPString(),randomPortSpec())
+ test+=gettimestamp()
+ test+= "router-signature\n"
+
+ bs = [b for b in bridgedb.Bridges.parseDescFile(test.split('\n'))]
+ self.assertEquals(len(bs), 100)
+
+ for b in bs:
+ b.assertOK()
+
+ def testParseCountryBlockFile(self):
+ simpleBlock = "%s:%s %s\n"
+ countries = ['us', 'nl', 'de', 'cz', 'sk', 'as', 'si', 'it']
+ test = str()
+ for i in range(100):
+ test += simpleBlock % (randomIPString(), randomPort(),
+ randomCountrySpec())
+ test+=gettimestamp()
+
+ for a,p,c in bridgedb.Bridges.parseCountryBlockFile(test.split('\n')):
+ assert type(a) in (ipaddr.IPv6Address, ipaddr.IPv4Address)
+ assert isinstance(p, addr.PortList)
+ assert isinstance(c, list)
+ assert len(c) > 0
+ for y in c:
+ assert y in countries
+ #print "address: %s" % a
+ #print "portlist: %s" % p
+ #print "countries: %s" % c
+
+class BridgeStabilityTests(unittest.TestCase):
+ def setUp(self):
+ self.fd, self.fname = tempfile.mkstemp()
+ self.db = bridgedb.Storage.Database(self.fname)
+ bridgedb.Storage.setDB(self.db)
+ self.cur = self.db._conn.cursor()
+
+ def tearDown(self):
+ self.db.close()
+ os.close(self.fd)
+ os.unlink(self.fname)
+
+ def testAddOrUpdateSingleBridgeHistory(self):
+ db = self.db
+ b = fakeBridge()
+ timestamp = time.time()
+ bhe = bridgedb.Stability.addOrUpdateBridgeHistory(b, timestamp)
+ assert isinstance(bhe, BridgeHistory)
+ assert isinstance(db.getBridgeHistory(b.fingerprint), BridgeHistory)
+ assert len([y for y in db.getAllBridgeHistory()]) == 1
+
+ def testDeletingSingleBridgeHistory(self):
+ db = self.db
+ b = fakeBridge()
+ timestamp = time.time()
+ bhe = bridgedb.Stability.addOrUpdateBridgeHistory(b, timestamp)
+ assert isinstance(bhe, BridgeHistory)
+ assert isinstance(db.getBridgeHistory(b.fingerprint), BridgeHistory)
+ db.delBridgeHistory(b.fingerprint)
+ assert db.getBridgeHistory(b.fingerprint) is None
+ assert len([y for y in db.getAllBridgeHistory()]) == 0
+
+ def testTOSA(self):
+ db = self.db
+ b = random.choice([fakeBridge,fakeBridge6])()
+ def timestampSeries(x):
+ for i in xrange(61):
+ yield (i+1)*60*30 + x # 30 minute intervals
+ now = time.time()
+ time_on_address = long(60*30*60) # 30 hours
+ downtime = 60*60*random.randint(0,4) # random hours of downtime
+
+ for t in timestampSeries(now):
+ bridgedb.Stability.addOrUpdateBridgeHistory(b,t)
+ assert db.getBridgeHistory(b.fingerprint).tosa == time_on_address
+
+ b.orport += 1
+
+ for t in timestampSeries(now + time_on_address + downtime):
+ bhe = bridgedb.Stability.addOrUpdateBridgeHistory(b,t)
+ assert db.getBridgeHistory(b.fingerprint).tosa == time_on_address + downtime
+
+ def testLastSeenWithDifferentAddressAndPort(self):
+ db = self.db
+ for i in xrange(10):
+ num_desc = 30
+ time_start = time.time()
+ ts = [ 60*30*(i+1) + time_start for i in xrange(num_desc) ]
+ b = random.choice([fakeBridge(), fakeBridge6()])
+ [ bridgedb.Stability.addOrUpdateBridgeHistory(b, t) for t in ts ]
+
+ # change the port
+ b.orport = b.orport+1
+ last_seen = ts[-1]
+ ts = [ 60*30*(i+1) + last_seen for i in xrange(num_desc) ]
+ [ bridgedb.Stability.addOrUpdateBridgeHistory(b, t) for t in ts ]
+ b = db.getBridgeHistory(b.fingerprint)
+ assert b.tosa == ts[-1] - last_seen
+ assert (long(last_seen*1000) == b.lastSeenWithDifferentAddressAndPort)
+ assert (long(ts[-1]*1000) == b.lastSeenWithThisAddressAndPort)
+
+ def testFamiliar(self):
+ # create some bridges
+ # XXX: slow
+ num_bridges = 10
+ num_desc = 4*48 # 30m intervals, 48 per day
+ time_start = time.time()
+ bridges = [ fakeBridge() for x in xrange(num_bridges) ]
+ t = time.time()
+ ts = [ (i+1)*60*30+t for i in xrange(num_bridges) ]
+ for b in bridges:
+ time_series = [ 60*30*(i+1) + time_start for i in xrange(num_desc) ]
+ [ bridgedb.Stability.addOrUpdateBridgeHistory(b, i) for i in time_series ]
+ assert None not in bridges
+ # +1 to avoid rounding errors
+ assert bridges[-(num_bridges/8 + 1)].familiar == True
+
+ def testDiscountAndPruneBridgeHistory(self):
+ """ Test pruning of old Bridge History """
+ if os.environ.get('TRAVIS'):
+ self.skipTest("Hangs on Travis-CI.")
+
+ db = self.db
+
+ # make a bunch of bridges
+ num_bridges = 20
+ time_start = time.time()
+ bridges = [random.choice([fakeBridge, fakeBridge6])()
+ for i in xrange(num_bridges)]
+
+ # run some of the bridges for the full time series
+ running = bridges[:num_bridges/2]
+ # and some that are not
+ expired = bridges[num_bridges/2:]
+
+ for b in running: assert b not in expired
+
+ # Solving:
+ # 1 discount event per 12 hours, 24 descriptors 30m apart
+ num_successful = random.randint(2,60)
+ # figure out how many intervals it will take for weightedUptime to
+ # decay to < 1
+ num_desc = int(30*log(1/float(num_successful*30*60))/(-0.05))
+ timeseries = [ 60*30*(i+1) + time_start for i in xrange(num_desc) ]
+
+ for i in timeseries:
+ for b in running:
+ bridgedb.Stability.addOrUpdateBridgeHistory(b, i)
+
+ if num_successful > 0:
+ for b in expired:
+ bridgedb.Stability.addOrUpdateBridgeHistory(b, i)
+ num_successful -= 1
+
+ # now we expect to see the bridge has been removed from history
+ for bridge in expired:
+ b = db.getBridgeHistory(bridge.fingerprint)
+ assert b is None
+ # and make sure none of the others have
+ for bridge in running:
+ b = db.getBridgeHistory(bridge.fingerprint)
+ assert b is not None
+
+def testSuite():
+ suite = unittest.TestSuite()
+ loader = unittest.TestLoader()
+
+ for klass in [IPBridgeDistTests, SQLStorageTests, EmailBridgeDistTests,
+ ParseDescFileTests, BridgeStabilityTests]:
+ suite.addTest(loader.loadTestsFromTestCase(klass))
+
+ for module in [ bridgedb.Bridges,
+ bridgedb.Main,
+ bridgedb.Dist,
+ bridgedb.schedule ]:
+ suite.addTest(doctest.DocTestSuite(module))
+
+ return suite
+
+def main():
+ suppressWarnings()
+
+ unittest.TextTestRunner(verbosity=1).run(testSuite())
+
diff --git a/lib/bridgedb/test/test_Tests.py b/lib/bridgedb/test/test_Tests.py
index e57f4a1..53d0e81 100644
--- a/lib/bridgedb/test/test_Tests.py
+++ b/lib/bridgedb/test/test_Tests.py
@@ -9,8 +9,9 @@
# (c) 2007-2013, all entities within the AUTHORS file
# :license: 3-Clause BSD, see LICENSE for licensing information
-"""Class wrappers to adapt BridgeDB old unittests in :mod:`bridgedb.Tests` to
-be compatible with the newer :api:`twisted.trial` unittests in this directory.
+"""Class wrappers to adapt BridgeDB old unittests in :mod:`bridgedb.Tests`
+(now kept in :mod:`bridgedb.test.legacy_Tests`) to be compatible with the
+newer :api:`twisted.trial` unittests in this directory.
"""
from __future__ import print_function
@@ -26,11 +27,11 @@ import warnings
from twisted.python import monkey
from twisted.trial import unittest
-from bridgedb import Tests
+from bridgedb.test import legacy_Tests as Tests
from bridgedb.test import deprecated
-warnings.filterwarnings('ignore', module="bridgedb\.Tests")
+warnings.filterwarnings('ignore', module="bridgedb\.test\.legacy_Tests")
pyunit = __import__('unittest')
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits