[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[tor-commits] [bridgedb/develop] Deprecate the bridgedb.parse.networkstatus module.
commit 399552ae06b56c7f703303e9d0c638253657d1bb
Author: Isis Lovecruft <isis@xxxxxxxxxxxxxx>
Date: Wed Feb 11 21:58:51 2015 +0000
Deprecate the bridgedb.parse.networkstatus module.
* MOVE bridgedb.parse.networkstatus to
bridgedb.test.deprecated_networkstatus and wrap all callables within
with @twisted.python.deprecate.deprecated.
* REMOVE the import of bridgedb.parse.networkstatus in bridgedb.Bridges
module.
* CHANGE legacy_Tests.py to import deprecated_networkstatus to continue
to check for regressions in other parts of the codebase.
* REMOVE bridgedb.test.test_parse_networkstatus.py.
---
lib/bridgedb/Bridges.py | 1 -
lib/bridgedb/parse/networkstatus.py | 263 ----------------
lib/bridgedb/test/deprecated_networkstatus.py | 275 ++++++++++++++++
lib/bridgedb/test/legacy_Tests.py | 2 +-
lib/bridgedb/test/test_parse_networkstatus.py | 414 -------------------------
5 files changed, 276 insertions(+), 679 deletions(-)
diff --git a/lib/bridgedb/Bridges.py b/lib/bridgedb/Bridges.py
index 31b7cf6..bdb911a 100644
--- a/lib/bridgedb/Bridges.py
+++ b/lib/bridgedb/Bridges.py
@@ -25,7 +25,6 @@ import bridgedb.Bucket
from bridgedb.bridges import Bridge
from bridgedb.crypto import getHMACFunc
from bridgedb.parse import addr
-from bridgedb.parse import networkstatus
from bridgedb.parse.fingerprint import toHex
from bridgedb.parse.fingerprint import fromHex
from bridgedb.parse.fingerprint import isValidFingerprint
diff --git a/lib/bridgedb/parse/networkstatus.py b/lib/bridgedb/parse/networkstatus.py
deleted file mode 100644
index 8140fe0..0000000
--- a/lib/bridgedb/parse/networkstatus.py
+++ /dev/null
@@ -1,263 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# This file is part of BridgeDB, a Tor bridge distribution system.
-#
-# :authors: Isis Lovecruft 0xA3ADB67A2CDB8B35 <isis@xxxxxxxxxxxxxx>
-# please also see AUTHORS file
-# :copyright: (c) 2013 Isis Lovecruft
-# (c) 2007-2014, The Tor Project, Inc.
-# (c) 2007-2014, all entities within the AUTHORS file
-# :license: 3-clause BSD, see included LICENSE for information
-
-"""Parsers for bridge networkstatus descriptors.
-
-.. py:module:: bridgedb.parse.networkstatus
- :synopsis: Parsers for ``@type bridge-network-status`` descriptors_.
-.. _descriptors: https://metrics.torproject.org/formats.html#descriptortypes
-
-
-bridgedb.parse.networkstatus
-============================
-::
-
- networkstatus
- |_ isValidRouterNickname - Determine if a nickname is according to spec
- |_ parseRLine - Parse an 'r'-line from a networkstatus document
- |_ parseALine - Parse an 'a'-line from a networkstatus document
- \_ parseSLine - Parse an 's'-line from a networkstatus document
-..
-"""
-
-import binascii
-import logging
-import string
-import time
-import warnings
-
-from twisted.python.log import showwarning
-
-from bridgedb.parse import addr
-from bridgedb.parse import parseUnpaddedBase64
-from bridgedb.parse import InvalidBase64
-from bridgedb.parse.nickname import InvalidRouterNickname
-from bridgedb.parse.nickname import isValidRouterNickname
-
-
-class NetworkstatusParsingError(Exception):
- """Unable to parse networkstatus document line."""
-
-class InvalidNetworkstatusRouterIdentity(ValueError):
- """The ID field of a networkstatus document 'r'-line is invalid."""
-
-
-def parseRLine(line):
- """Parse an 'r'-line from a networkstatus document.
-
- From torspec.git/dir-spec.txt, commit 36761c7d553d L1499-1512:
- | "r" SP nickname SP identity SP digest SP publication SP IP SP ORPort
- | SP DirPort NL
- |
- | [At start, exactly once.]
- |
- | "Nickname" is the OR's nickname. "Identity" is a hash of its
- | identity key, encoded in base64, with trailing equals sign(s)
- | removed. "Digest" is a hash of its most recent descriptor as
- | signed (that is, not including the signature), encoded in base64.
- | "Publication" is the
- | publication time of its most recent descriptor, in the form
- | YYYY-MM-DD HH:MM:SS, in UTC. "IP" is its current IP address;
- | ORPort is its current OR port, "DirPort" is its current directory
- | port, or "0" for "none".
-
- :param string line: An 'r'-line from an bridge-network-status descriptor.
- :returns:
- A 7-tuple of::
- (nickname, identityDigest, descriptorDigest, timestamp,
- orAddress, orPort, dirport)
- where each value is set according to the data parsed from the
- **line**, or ``None`` if nothing suitable could be parsed.
- """
- (nickname, ID, descDigest, timestamp,
- ORaddr, ORport, dirport) = (None for x in xrange(7))
-
- try:
- if not line.startswith('r '):
- raise NetworkstatusParsingError(
- "Networkstatus parser received non 'r'-line: %r" % line)
-
- line = line[2:] # Chop off the 'r '
- fields = line.split()
-
- if len(fields) != 8:
- raise NetworkstatusParsingError(
- "Wrong number of fields in networkstatus 'r'-line: %r" % line)
-
- nickname, ID = fields[:2]
-
- try:
- ID = parseUnpaddedBase64(ID)
- except InvalidBase64 as error:
- raise InvalidNetworkstatusRouterIdentity(error)
-
- # Check the nickname validity after parsing the ID, otherwise, if the
- # nickname is invalid, we end up with the nickname being ``None`` and
- # the ID being unparsed, unpadded (meaning it is technically invalid)
- # base64.
- isValidRouterNickname(nickname)
-
- except NetworkstatusParsingError as error:
- logging.error(error)
- nickname, ID = None, None
- except InvalidRouterNickname as error:
- logging.error(error)
- # Assume that we mostly care about obtaining the OR's ID, then it
- # should be okay to set the nickname to ``None``, if it was invalid.
- nickname = None
- except InvalidNetworkstatusRouterIdentity as error:
- logging.error(error)
- ID = None
- else:
- try:
- descDigest = parseUnpaddedBase64(fields[2])
- timestamp = time.mktime(time.strptime(" ".join(fields[3:5]),
- "%Y-%m-%d %H:%M:%S"))
- ORaddr = fields[5]
- ORport = int(fields[6])
- dirport = fields[7]
- except InvalidBase64 as error:
- logging.error(error)
- descDigest = None
- except (AttributeError, ValueError, IndexError) as error:
- logging.error(error)
- timestamp = None
- finally:
- return (nickname, ID, descDigest, timestamp, ORaddr, ORport, dirport)
-
-def parseALine(line, fingerprint=None):
- """Parse an 'a'-line of a bridge networkstatus document.
-
- From torspec.git/dir-spec.txt, commit 36761c7d553d L1499-1512:
- |
- | "a" SP address ":" port NL
- |
- | [Any number.]
- |
- | Present only if the OR has at least one IPv6 address.
- |
- | Address and portlist are as for "or-address" as specified in
- | 2.1.
- |
- | (Only included when the vote or consensus is generated with
- | consensus-method 14 or later.)
-
- :param string line: An 'a'-line from an bridge-network-status descriptor.
- :type fingerprint: string or None
- :param fingerprint: A string which identifies which OR the descriptor
- we're parsing came from (since the 'a'-line doesn't tell us, this can
- help make the log messages clearer).
- :raises: :exc:`NetworkstatusParsingError`
- :rtype: tuple
- :returns: A 2-tuple of a string respresenting the IP address and a
- :class:`bridgedb.parse.addr.PortList`.
- """
- ip = None
- portlist = None
-
- if line.startswith('a '):
- line = line[2:] # Chop off the 'a '
- else:
- logging.warn("Networkstatus parser received non 'a'-line for %r:"\
- " %r" % (fingerprint or 'Unknown', line))
-
- try:
- ip, portlist = line.rsplit(':', 1)
- except ValueError as error:
- logging.error("Bad separator in networkstatus 'a'-line: %r" % line)
- return (None, None)
-
- if ip.startswith('[') and ip.endswith(']'):
- ip = ip.strip('[]')
-
- try:
- if not addr.isIPAddress(ip):
- raise NetworkstatusParsingError(
- "Got invalid IP Address in networkstatus 'a'-line for %r: %r"
- % (fingerprint or 'Unknown', line))
-
- if addr.isIPv4(ip):
- warnings.warn(FutureWarning(
- "Got IPv4 address in networkstatus 'a'-line! "\
- "Networkstatus document format may have changed!"))
- except NetworkstatusParsingError as error:
- logging.error(error)
- ip, portlist = None, None
-
- try:
- portlist = addr.PortList(portlist)
- if not portlist:
- raise NetworkstatusParsingError(
- "Got invalid portlist in 'a'-line for %r!\n Line: %r"
- % (fingerprint or 'Unknown', line))
- except (addr.InvalidPort, NetworkstatusParsingError) as error:
- logging.error(error)
- portlist = None
- else:
- logging.debug("Parsed networkstatus ORAddress line for %r:"\
- "\n Address: %s \tPorts: %s"
- % (fingerprint or 'Unknown', ip, portlist))
- finally:
- return (ip, portlist)
-
-def parseSLine(line):
- """Parse an 's'-line from a bridge networkstatus document.
-
- The 's'-line contains all flags assigned to a bridge. The flags which may
- be assigned to a bridge are as follows:
-
- From torspec.git/dir-spec.txt, commit 36761c7d553d L1526-1554:
- |
- | "s" SP Flags NL
- |
- | [Exactly once.]
- |
- | A series of space-separated status flags, in lexical order (as ASCII
- | byte strings). Currently documented flags are:
- |
- | "BadDirectory" if the router is believed to be useless as a
- | directory cache (because its directory port isn't working,
- | its bandwidth is always throttled, or for some similar
- | reason).
- | "Fast" if the router is suitable for high-bandwidth circuits.
- | "Guard" if the router is suitable for use as an entry guard.
- | "HSDir" if the router is considered a v2 hidden service directory.
- | "Named" if the router's identity-nickname mapping is canonical,
- | and this authority binds names.
- | "Stable" if the router is suitable for long-lived circuits.
- | "Running" if the router is currently usable.
- | "Valid" if the router has been 'validated'.
- | "V2Dir" if the router implements the v2 directory protocol.
-
- :param string line: An 's'-line from an bridge-network-status descriptor.
- :rtype: tuple
- :returns: A 2-tuple of booleans, the first is True if the bridge has the
- "Running" flag, and the second is True if it has the "Stable" flag.
- """
- line = line[2:]
-
- flags = [x.capitalize() for x in line.split()]
- fast = 'Fast' in flags
- running = 'Running' in flags
- stable = 'Stable' in flags
- guard = 'Guard' in flags
- valid = 'Valid' in flags
-
- if (fast or running or stable or guard or valid):
- logging.debug("Parsed Flags: %s%s%s%s%s"
- % ('Fast ' if fast else '',
- 'Running ' if running else '',
- 'Stable ' if stable else '',
- 'Guard ' if guard else '',
- 'Valid ' if valid else ''))
-
- # Right now, we only care about 'Running' and 'Stable'
- return running, stable
diff --git a/lib/bridgedb/test/deprecated_networkstatus.py b/lib/bridgedb/test/deprecated_networkstatus.py
new file mode 100644
index 0000000..7e3b0a4
--- /dev/null
+++ b/lib/bridgedb/test/deprecated_networkstatus.py
@@ -0,0 +1,275 @@
+# -*- coding: utf-8 -*-
+#
+# This file is part of BridgeDB, a Tor bridge distribution system.
+#
+# :authors: Isis Lovecruft 0xA3ADB67A2CDB8B35 <isis@xxxxxxxxxxxxxx>
+# please also see AUTHORS file
+# :copyright: (c) 2013 Isis Lovecruft
+# (c) 2007-2014, The Tor Project, Inc.
+# (c) 2007-2014, all entities within the AUTHORS file
+# :license: 3-clause BSD, see included LICENSE for information
+
+"""Parsers for bridge networkstatus descriptors.
+
+THIS ENTIRE MODULE WAS DEPRECATED (AS PART OF #9380_) AND WAS REPLACED WITH
+THE CORRESPONDING FUNCTIONS IN :mod:`bridgedb.parse.descriptors`.
+
+.. #9380: https://bugs.torproject.org/9380
+
+.. py:module:: bridgedb.parse.networkstatus
+ :synopsis: Parsers for ``@type bridge-network-status`` descriptors_.
+.. _descriptors: https://metrics.torproject.org/formats.html#descriptortypes
+
+
+bridgedb.parse.networkstatus
+============================
+::
+
+ networkstatus
+ |_ isValidRouterNickname - Determine if a nickname is according to spec
+ |_ parseRLine - Parse an 'r'-line from a networkstatus document
+ |_ parseALine - Parse an 'a'-line from a networkstatus document
+ \_ parseSLine - Parse an 's'-line from a networkstatus document
+..
+"""
+
+import binascii
+import logging
+import string
+import time
+import warnings
+
+from twisted.python import deprecate
+from twisted.python.log import showwarning
+from twisted.python.versions import Version
+
+from bridgedb.parse import addr
+from bridgedb.parse import parseUnpaddedBase64
+from bridgedb.parse import InvalidBase64
+from bridgedb.parse.nickname import InvalidRouterNickname
+from bridgedb.parse.nickname import isValidRouterNickname
+
+
+@xxxxxxxxxxxxxxxxxxxx(Version('bridgedb', 0, 2, 5))
+class NetworkstatusParsingError(Exception):
+ """Unable to parse networkstatus document line."""
+
+@xxxxxxxxxxxxxxxxxxxx(Version('bridgedb', 0, 2, 5))
+class InvalidNetworkstatusRouterIdentity(ValueError):
+ """The ID field of a networkstatus document 'r'-line is invalid."""
+
+
+@xxxxxxxxxxxxxxxxxxxx(Version('bridgedb', 0, 2, 5))
+def parseRLine(line):
+ """Parse an 'r'-line from a networkstatus document.
+
+ From torspec.git/dir-spec.txt, commit 36761c7d553d L1499-1512:
+ | "r" SP nickname SP identity SP digest SP publication SP IP SP ORPort
+ | SP DirPort NL
+ |
+ | [At start, exactly once.]
+ |
+ | "Nickname" is the OR's nickname. "Identity" is a hash of its
+ | identity key, encoded in base64, with trailing equals sign(s)
+ | removed. "Digest" is a hash of its most recent descriptor as
+ | signed (that is, not including the signature), encoded in base64.
+ | "Publication" is the
+ | publication time of its most recent descriptor, in the form
+ | YYYY-MM-DD HH:MM:SS, in UTC. "IP" is its current IP address;
+ | ORPort is its current OR port, "DirPort" is its current directory
+ | port, or "0" for "none".
+
+ :param string line: An 'r'-line from an bridge-network-status descriptor.
+ :returns:
+ A 7-tuple of::
+ (nickname, identityDigest, descriptorDigest, timestamp,
+ orAddress, orPort, dirport)
+ where each value is set according to the data parsed from the
+ **line**, or ``None`` if nothing suitable could be parsed.
+ """
+ (nickname, ID, descDigest, timestamp,
+ ORaddr, ORport, dirport) = (None for x in xrange(7))
+
+ try:
+ if not line.startswith('r '):
+ raise NetworkstatusParsingError(
+ "Networkstatus parser received non 'r'-line: %r" % line)
+
+ line = line[2:] # Chop off the 'r '
+ fields = line.split()
+
+ if len(fields) != 8:
+ raise NetworkstatusParsingError(
+ "Wrong number of fields in networkstatus 'r'-line: %r" % line)
+
+ nickname, ID = fields[:2]
+
+ try:
+ ID = parseUnpaddedBase64(ID)
+ except InvalidBase64 as error:
+ raise InvalidNetworkstatusRouterIdentity(error)
+
+ # Check the nickname validity after parsing the ID, otherwise, if the
+ # nickname is invalid, we end up with the nickname being ``None`` and
+ # the ID being unparsed, unpadded (meaning it is technically invalid)
+ # base64.
+ isValidRouterNickname(nickname)
+
+ except NetworkstatusParsingError as error:
+ logging.error(error)
+ nickname, ID = None, None
+ except InvalidRouterNickname as error:
+ logging.error(error)
+ # Assume that we mostly care about obtaining the OR's ID, then it
+ # should be okay to set the nickname to ``None``, if it was invalid.
+ nickname = None
+ except InvalidNetworkstatusRouterIdentity as error:
+ logging.error(error)
+ ID = None
+ else:
+ try:
+ descDigest = parseUnpaddedBase64(fields[2])
+ timestamp = time.mktime(time.strptime(" ".join(fields[3:5]),
+ "%Y-%m-%d %H:%M:%S"))
+ ORaddr = fields[5]
+ ORport = int(fields[6])
+ dirport = fields[7]
+ except InvalidBase64 as error:
+ logging.error(error)
+ descDigest = None
+ except (AttributeError, ValueError, IndexError) as error:
+ logging.error(error)
+ timestamp = None
+ finally:
+ return (nickname, ID, descDigest, timestamp, ORaddr, ORport, dirport)
+
+@xxxxxxxxxxxxxxxxxxxx(Version('bridgedb', 0, 2, 5))
+def parseALine(line, fingerprint=None):
+ """Parse an 'a'-line of a bridge networkstatus document.
+
+ From torspec.git/dir-spec.txt, commit 36761c7d553d L1499-1512:
+ |
+ | "a" SP address ":" port NL
+ |
+ | [Any number.]
+ |
+ | Present only if the OR has at least one IPv6 address.
+ |
+ | Address and portlist are as for "or-address" as specified in
+ | 2.1.
+ |
+ | (Only included when the vote or consensus is generated with
+ | consensus-method 14 or later.)
+
+ :param string line: An 'a'-line from an bridge-network-status descriptor.
+ :type fingerprint: string or None
+ :param fingerprint: A string which identifies which OR the descriptor
+ we're parsing came from (since the 'a'-line doesn't tell us, this can
+ help make the log messages clearer).
+ :raises: :exc:`NetworkstatusParsingError`
+ :rtype: tuple
+ :returns: A 2-tuple of a string respresenting the IP address and a
+ :class:`bridgedb.parse.addr.PortList`.
+ """
+ ip = None
+ portlist = None
+
+ if line.startswith('a '):
+ line = line[2:] # Chop off the 'a '
+ else:
+ logging.warn("Networkstatus parser received non 'a'-line for %r:"\
+ " %r" % (fingerprint or 'Unknown', line))
+
+ try:
+ ip, portlist = line.rsplit(':', 1)
+ except ValueError as error:
+ logging.error("Bad separator in networkstatus 'a'-line: %r" % line)
+ return (None, None)
+
+ if ip.startswith('[') and ip.endswith(']'):
+ ip = ip.strip('[]')
+
+ try:
+ if not addr.isIPAddress(ip):
+ raise NetworkstatusParsingError(
+ "Got invalid IP Address in networkstatus 'a'-line for %r: %r"
+ % (fingerprint or 'Unknown', line))
+
+ if addr.isIPv4(ip):
+ warnings.warn(FutureWarning(
+ "Got IPv4 address in networkstatus 'a'-line! "\
+ "Networkstatus document format may have changed!"))
+ except NetworkstatusParsingError as error:
+ logging.error(error)
+ ip, portlist = None, None
+
+ try:
+ portlist = addr.PortList(portlist)
+ if not portlist:
+ raise NetworkstatusParsingError(
+ "Got invalid portlist in 'a'-line for %r!\n Line: %r"
+ % (fingerprint or 'Unknown', line))
+ except (addr.InvalidPort, NetworkstatusParsingError) as error:
+ logging.error(error)
+ portlist = None
+ else:
+ logging.debug("Parsed networkstatus ORAddress line for %r:"\
+ "\n Address: %s \tPorts: %s"
+ % (fingerprint or 'Unknown', ip, portlist))
+ finally:
+ return (ip, portlist)
+
+@xxxxxxxxxxxxxxxxxxxx(Version('bridgedb', 0, 2, 5))
+def parseSLine(line):
+ """Parse an 's'-line from a bridge networkstatus document.
+
+ The 's'-line contains all flags assigned to a bridge. The flags which may
+ be assigned to a bridge are as follows:
+
+ From torspec.git/dir-spec.txt, commit 36761c7d553d L1526-1554:
+ |
+ | "s" SP Flags NL
+ |
+ | [Exactly once.]
+ |
+ | A series of space-separated status flags, in lexical order (as ASCII
+ | byte strings). Currently documented flags are:
+ |
+ | "BadDirectory" if the router is believed to be useless as a
+ | directory cache (because its directory port isn't working,
+ | its bandwidth is always throttled, or for some similar
+ | reason).
+ | "Fast" if the router is suitable for high-bandwidth circuits.
+ | "Guard" if the router is suitable for use as an entry guard.
+ | "HSDir" if the router is considered a v2 hidden service directory.
+ | "Named" if the router's identity-nickname mapping is canonical,
+ | and this authority binds names.
+ | "Stable" if the router is suitable for long-lived circuits.
+ | "Running" if the router is currently usable.
+ | "Valid" if the router has been 'validated'.
+ | "V2Dir" if the router implements the v2 directory protocol.
+
+ :param string line: An 's'-line from an bridge-network-status descriptor.
+ :rtype: tuple
+ :returns: A 2-tuple of booleans, the first is True if the bridge has the
+ "Running" flag, and the second is True if it has the "Stable" flag.
+ """
+ line = line[2:]
+
+ flags = [x.capitalize() for x in line.split()]
+ fast = 'Fast' in flags
+ running = 'Running' in flags
+ stable = 'Stable' in flags
+ guard = 'Guard' in flags
+ valid = 'Valid' in flags
+
+ if (fast or running or stable or guard or valid):
+ logging.debug("Parsed Flags: %s%s%s%s%s"
+ % ('Fast ' if fast else '',
+ 'Running ' if running else '',
+ 'Stable ' if stable else '',
+ 'Guard ' if guard else '',
+ 'Valid ' if valid else ''))
+
+ # Right now, we only care about 'Running' and 'Stable'
+ return running, stable
diff --git a/lib/bridgedb/test/legacy_Tests.py b/lib/bridgedb/test/legacy_Tests.py
index 7be5270..d416d22 100644
--- a/lib/bridgedb/test/legacy_Tests.py
+++ b/lib/bridgedb/test/legacy_Tests.py
@@ -35,7 +35,7 @@ from bridgedb.Filters import filterBridgesByNotBlockedIn
from bridgedb.Stability import BridgeHistory
from bridgedb.parse import addr
-from bridgedb.parse import networkstatus
+from bridgedb.test import deprecated_networkstatus as networkstatus
from math import log
diff --git a/lib/bridgedb/test/test_parse_networkstatus.py b/lib/bridgedb/test/test_parse_networkstatus.py
deleted file mode 100644
index 6a89c25..0000000
--- a/lib/bridgedb/test/test_parse_networkstatus.py
+++ /dev/null
@@ -1,414 +0,0 @@
-# -*- coding: utf-8 -*-
-#
-# This file is part of BridgeDB, a Tor bridge distribution system.
-#
-# :authors: Isis Lovecruft 0xA3ADB67A2CDB8B35 <isis@xxxxxxxxxxxxxx>
-# :copyright: (c) 2013-2014, Isis Lovecruft
-# (c) 2007-2014, The Tor Project, Inc.
-# :license: 3-Clause BSD, see LICENSE for licensing information
-
-"""Unittests for the :mod:`bridgedb.parse.networkstatus` module.
-
-These tests are meant to ensure that the :mod:`bridgedb.parse.networkstatus`
-module is functioning correctly.
-"""
-
-from __future__ import print_function
-from __future__ import unicode_literals
-
-import binascii
-
-from twisted.python import log
-from twisted.trial import unittest
-from bridgedb.parse import networkstatus
-
-import sure
-from sure import this, these, those, the, it
-
-
-logFormat = "%(created)d [%(levelname)s] %(module)s.%(funcName)s(): "
-logFormat += "%(message)s"
-networkstatus.logging.basicConfig(
- filename='test_parse_networkstatus.log',
- level=networkstatus.logging.DEBUG,
- flags='w', format=logFormat)
-
-
-class ParseNetworkStatusRLineTests(unittest.TestCase):
- """Tests for :func:`bridgedb.parse.networkstatus.parseRLine`.
-
- The documentation for all class variables, e.g. 'pre' or 'ident', refers
- to what said value should be in a *valid* descriptor.
- """
- rawIdent = 'identdigestidentdig'
- rawDesc = 'descdigestdescdiges'
-
- #: The prefix for the 'r'-line. Should be an 'r', unless testing that
- #: lines with unknown prefixes are dropped.
- pre = 'r '
- #: An OR nickname string. To be valid, it should be 1-19 alphanumeric
- #: upper or lower cased characters.
- nick = 'Testing'
- #: A base64-encoded, SHA-1 digest of the DER-formatted, ASN.1-encoded,
- #: public portion of an OR identity key, with any trailing base64 padding
- #: (any '=' characters) removed.
- ident = binascii.b2a_base64(rawIdent).strip().rstrip('==')
- #: A base64-encoded, SHA-1 digest of the OR
- #: `@type-[bridge-]server-descriptor` document (the whole thing, up until
- #: the 'router signature' line, but not including the signature thereafter),
- #: with any trailing base64 padding (any '=' characters) removed.
- desc = binascii.b2a_base64(rawDesc).strip().rstrip('==')
- #: An ISO-8661 formatted timestamp, with a space separator (rather than a
- #: 'T' character).
- ts = '2013-10-31 15:15:15'
- #: An IPv4 address.
- ip = '221.251.0.42'
- #: An ORPort number.
- port = '9001'
- #: A DirPort number.
- dirp = '0'
-
- def makeRLine(self, *args, **kwargs):
- """Concatenate parameters into an 'r'-line and store the result as
- ``self.line``.
-
- :keywords: The keyword arguments may be any of the class variables,
- i.e. 'nick' or 'ident', and the variables should be similar
- to the defaults in the class variables. If not given as
- parameters, the class variables will be used.
- """
- line = []
- for kw in ('pre', 'nick', 'ident', 'desc', 'ts', 'ip', 'port', 'dirp'):
- if kw in kwargs.keys():
- if kwargs[kw]:
- line.append(kwargs[kw])
- elif kwargs[kw] is False:
- pass
- else:
- line.append(getattr(self, kw, ''))
-
- self.line = ' '.join([l for l in line]).strip()
- log.msg("\n Testing networkstatusline:\n %r..." % self.line)
- self.assertTrue(self.line != '')
-
- def tearDown(self):
- self.line = ''
-
- def assertAllFieldsAreNone(self, fields):
- """Assert that every field in the iterable ``fields`` is None."""
- for field in fields:
- self.assertTrue(field is None)
-
- def test_missingPrefix(self):
- """Test a networkstatus 'r'-line that is missing the 'r ' prefix."""
- self.makeRLine(pre=False)
- fields = networkstatus.parseRLine(self.line)
- self.assertAllFieldsAreNone(fields)
-
- def test_wrongNumberOfFields(self):
- """Test a line missing digest, ORPort, and DirPort fields."""
- self.makeRLine(desc=False, port=False, dirp=False)
- fields = networkstatus.parseRLine(self.line)
- self.assertAllFieldsAreNone(fields)
-
- def test_wrongFieldOrder(self):
- """Test a line with the identity and descriptor digests switched."""
- self.makeRLine(desc=self.ident, ident=self.desc)
- fields = networkstatus.parseRLine(self.line)
- nick, others = fields[0], fields[1:]
-
- this(nick).should.be.ok
- this(nick).should.be.a(basestring)
- this(nick).should.equal(self.nick)
-
- the(others).should.be.a(tuple)
- the(others).should.have.length_of(6)
- for other in others:
- the(other).should.be(None)
-
- def test_invalidNicknameNonAlphanumeric(self):
- """Test a line with a non-alphanumeric router nickname."""
- self.makeRLine(nick='abcdef/*comment*/')
- fields = networkstatus.parseRLine(self.line)
- nick, ident, desc = fields[:3]
- this(nick).should.be(None)
- the(ident).should.be.a(basestring)
- the(desc).should.be(None)
-
- def test_invalidNicknameTooLong(self):
- """Test a line with a router nickname which is way too long."""
- self.makeRLine(nick='ThisIsAReallyReallyLongRouterNickname')
- fields = networkstatus.parseRLine(self.line)
- nick, ident, desc = fields[:3]
- this(nick).should.be(None)
- the(ident).should.be.a(basestring)
- the(desc).should.be(None)
-
- def test_invalidIdentBase64(self):
- """Test line with '%$>@,<' for an identity digest."""
- self.makeRLine(ident='%$>#@,<')
- (nick, ident, desc, ts,
- ip, port, dirp) = networkstatus.parseRLine(self.line)
-
- the(nick).should.be.ok
- the(nick).should.be.a(basestring)
- the(nick).should.equal(self.nick)
- the(ident).should.be(None)
- the(desc).should.be(None)
-
- def test_invalidIdentSingleQuoteChar(self):
- """Test a line with a single quote character for the identity digest."""
- self.makeRLine(ident=chr(0x27))
- fields = networkstatus.parseRLine(self.line)
- nick, ident, desc = fields[:3]
-
- the(nick).should.be.ok
- the(nick).should.be.a(basestring)
- the(nick).should.be.equal(self.nick)
- the(ident).should.be.equal(None)
- the(desc).should.be.equal(None)
-
- def test_invalidIdent_withBase64padding(self):
- """Test a line with invalid base64 (no padding) identity digest."""
- self.makeRLine(ident=self.ident + '==')
- fields = networkstatus.parseRLine(self.line)
- nick, ident, desc = fields[:3]
-
- the(nick).should.be.ok
- the(nick).should.be.a(basestring)
- the(nick).should.be.equal(self.nick)
- the(ident).should.be.equal(None)
- the(desc).should.be.equal(None)
-
- def test_invalidDescriptorDigest(self):
- """Test an 'r'-line with invalid base64 descriptor digest."""
- self.makeRLine(desc='æ??å?¸è¥¶')
- fields = networkstatus.parseRLine(self.line)
- nick, ident, desc, ts, ip = fields[:5]
-
- the(nick).should.be.ok
- the(nick).should.be.a(basestring)
- the(nick).should.be.equal(self.nick)
-
- the(ident).should.be.a(basestring)
- the(ident).should.be.equal(self.rawIdent)
-
- the(desc).should.be.equal(None)
- the(ts).should.be.equal(None)
- the(ip).should.be.equal(None)
-
- def test_invalidDescriptorDigest_invalidBase64(self):
- """Test line with '%$>@,<' for an identity digest."""
- self.makeRLine(desc='%$>#@,<')
- fields = networkstatus.parseRLine(self.line)
- nick, ident, desc, ts, ip = fields[:5]
-
- the(nick).should.be.ok
- the(nick).should.be.a(basestring)
- the(nick).should.equal(self.nick)
- the(ident).should.be(None)
- the(desc).should.be(None)
-
- def test_invalidDescriptorDigest_withBase64padding(self):
- """Test a line with invalid base64 (no padding) descriptor digest."""
- self.makeRLine(desc=self.desc + '==')
- fields = networkstatus.parseRLine(self.line)
- nick, ident, desc, ts, ip = fields[:5]
-
- the(nick).should.be.ok
- the(nick).should.be.a(basestring)
- the(nick).should.be.equal(self.nick)
-
- the(ident).should.be.a(basestring)
- the(ident).should.be.equal(self.rawIdent)
-
- the(desc).should.be.equal(None)
- the(ts).should.be.equal(None)
- the(ip).should.be.equal(None)
-
- def test_invalidDescriptorDigest_singleQuoteChar(self):
- """Test with a single quote character for the descriptor digest."""
- self.makeRLine(desc=chr(0x27))
- fields = networkstatus.parseRLine(self.line)
- nick, ident, desc = fields[:3]
-
- the(nick).should.be.ok
- the(nick).should.be.a(basestring)
- the(nick).should.be.equal(self.nick)
- the(ident).should.be.equal(self.rawIdent)
- the(desc).should.be.equal(None)
-
- def test_missingAfterDesc(self):
- """Test a line that has a valid descriptor digest, and is missing
- everything after the descriptor digest, i.e. the timestamp, IP address,
- and DirPort.
- """
- self.makeRLine(nick='missingAfterDesc', ts=False, ip=False, dirp=False)
- fields = networkstatus.parseRLine(self.line)
- self.assertAllFieldsAreNone(fields)
-
- def test_missingAfterIdent(self):
- """Test a line that and is missing the descriptor digest and
- everything after it, i.e. the timestamp, IP address, and DirPort.
- """
- self.makeRLine(nick='noDesc', desc=False, ts=False,
- ip=False, dirp=False)
- fields = networkstatus.parseRLine(self.line)
- self.assertAllFieldsAreNone(fields)
-
- def test_invalidTimestamp(self):
- """Test line with two large integers for the timestamp."""
- self.makeRLine(ts='123456789 987654321')
- fields = networkstatus.parseRLine(self.line)
- nick, ident, desc, ts, ip, port = fields[:6]
-
- the(nick).should.be.equal(self.nick)
- the(ident).should.be.equal(self.rawIdent)
-
- # descDigest is set to `None` if there is an error while parsing:
- the(desc).should.be(None)
- the(ts).should.be(None)
- the(ip).should.be(None)
-
- def test_invalidTimestampMissingDate(self):
- """Test a line where the timestamp is missing the date portion."""
- self.makeRLine(ts='15:15:15')
- fields = networkstatus.parseRLine(self.line)
- self.assertAllFieldsAreNone(fields)
-
- def test_invalidIPAddress(self):
- """Test a line with an invalid IP address."""
- self.makeRLine(ip='0.0.0.0')
- fields = networkstatus.parseRLine(self.line)
- nick, ident, desc, ts, ip, port = fields[:6]
-
- the(nick).should.be.equal(self.nick)
- the(ident).should.be.equal(self.rawIdent)
-
- # descDigest is set to `None` if there is an error while parsing:
- the(desc).should.be(None)
- the(ts).should.be(None)
- the(ip).should.be(None)
-
- def test_valid(self):
- """Test a valid 'r'-line."""
- self.makeRLine()
- fields = networkstatus.parseRLine(self.line)
- nick, ident, desc, ts, ip, port = fields[:6]
- the(nick).should.be.equal(self.nick)
- the(ident).should.be.equal(self.rawIdent)
- the(desc).should.be.equal(self.rawDesc)
- the(ts).should.be.ok
- the(ip).should.be.ok
-
-
-class ParseNetworkStatusALineTests(unittest.TestCase):
- """Tests for :func:`bridgedb.parse.networkstatus.parseALine`.
-
- The documentation for all class variables, e.g. 'pre' or 'oraddr', refers
- to what said value should be in a *valid* descriptor.
- """
- #: The prefix for the 'a'-line. Should be an 'a', unless testing that
- #: lines with unknown prefixes are dropped.
- pre = 'a '
- #: An ORAddress. As of tor-0.2.5.1-alpha, there is only one and it is an
- #: IPv6 address.
- oraddr = '[b8d:48ae:5185:dad:5c2a:4e75:8394:f5f8]'
-
- def tearDown(self):
- self.line = ''
-
- def assertAllFieldsAreNone(self, fields):
- """Assert that every field in the iterable ``fields`` is None."""
- for field in fields:
- self.assertTrue(field is None)
-
- def test_missingPrefix(self):
- """Changed to allow a missing 'a' prefix in branch
- ``hotfix/9462B-netstatus-returns-None``.
- """
- self.line = '%s:1234' % self.oraddr
- ip, port = networkstatus.parseALine(self.line)
- this(ip).should.be.a(basestring)
- this(port).should.be(None)
-
- def test_IPv4(self):
- self.line = 'a 48.32.199.45:9001'
- ip, port = networkstatus.parseALine(self.line)
- ip, port = self.assertWarns(
- FutureWarning,
- "Got IPv4 address in networkstatus 'a'-line! "\
- "Networkstatus document format may have changed!",
- networkstatus.__file__,
- networkstatus.parseALine,
- self.line)
- this(ip).should.be.a(basestring)
- this(port).should.be.ok
- this(port).should.be.a(networkstatus.addr.PortList)
-
- def test_IPv4BadPortSeparator(self):
- self.line = 'a 1.1.1.1 9001'
- fields = networkstatus.parseALine(self.line)
- self.assertAllFieldsAreNone(fields)
-
- def test_IPv6BadPortlist(self):
- self.line = 'a 23.23.23.23:1111,2222,badportlist'
- ip, port = networkstatus.parseALine(self.line)
- this(ip).should.be.a(basestring)
- this(port).should.be(None)
-
- def test_IPv4MissingPort(self):
- self.line = 'a 1.1.1.1'
- fields = networkstatus.parseALine(self.line)
- self.assertAllFieldsAreNone(fields)
-
- def test_IPv4InvalidAddress(self):
- self.line = 'a 127.0.0.1:5555'
- fields = networkstatus.parseALine(self.line)
- self.assertAllFieldsAreNone(fields)
-
- def test_IPv6BadPortSeparator(self):
- self.line = 'a %s missingcolon' % self.oraddr
- fields = networkstatus.parseALine(self.line)
- self.assertAllFieldsAreNone(fields)
-
- def test_IPv6BadPortlist(self):
- self.line = 'a %s:1111,2222,badportlist' % self.oraddr
- ip, port = networkstatus.parseALine(self.line)
- this(ip).should.be.a(basestring)
- this(port).should.be(None)
-
- def test_IPv6(self):
- self.line = 'a %s:6004' % self.oraddr
- ip, port = networkstatus.parseALine(self.line)
- this(ip).should.be.a(basestring)
- this(port).should.be.ok
- this(port).should.be.a(networkstatus.addr.PortList)
-
-
-class ParseNetworkStatusSLineTests(unittest.TestCase):
- """Tests for :func:`bridgedb.parse.networkstatus.parseSLine`."""
-
- def tearDown(self):
- """Automatically called after each test_* method to run cleanups."""
- self.line = ''
-
- def test_missingPrefix(self):
- self.line = 'Stable'
- running, stable = networkstatus.parseSLine(self.line)
- self.assertFalse(running)
- self.assertFalse(stable)
-
- def test_makeBelieveFlag(self):
- """Test that 's'-parser should ignore a 'MakeBelieve' flag."""
- self.line = 's Stable Running MakeBelieve BadExit'
- running, stable = networkstatus.parseSLine(self.line)
- self.assertTrue(running)
- self.assertTrue(stable)
-
- def test_noFlags(self):
- """Test that an 's'-line with no flags returns False for everything."""
- self.line = ''
- running, stable = networkstatus.parseSLine(self.line)
- self.assertFalse(running)
- self.assertFalse(stable)
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits