示例#1
0
  def test_handlers(self):
    """
    Try parsing a document with DocumentHandler.DOCUMENT and
    DocumentHandler.BARE_DOCUMENT.
    """

    # Simple sanity check that they provide the right type, and that the
    # document includes or excludes the router status entries as appropriate.

    entry1 = get_router_status_entry_v3({'s': 'Fast'})
    entry2 = get_router_status_entry_v3({
      'r': 'Nightfae AWt0XNId/OU2xX5xs5hVtDc5Mes 6873oEfM7fFIbxYtwllw9GPDwkA 2013-02-20 11:12:27 85.177.66.233 9001 9030',
      's': 'Valid',
    })

    content = get_network_status_document_v3(routers = (entry1, entry2), content = True)

    descriptors = list(stem.descriptor.parse_file(io.BytesIO(content), 'network-status-consensus-3 1.0', document_handler = stem.descriptor.DocumentHandler.DOCUMENT))
    self.assertEqual(1, len(descriptors))
    self.assertTrue(isinstance(descriptors[0], NetworkStatusDocumentV3))
    self.assertEqual(2, len(descriptors[0].routers))

    descriptors = list(stem.descriptor.parse_file(io.BytesIO(content), 'network-status-consensus-3 1.0', document_handler = stem.descriptor.DocumentHandler.BARE_DOCUMENT))
    self.assertEqual(1, len(descriptors))
    self.assertTrue(isinstance(descriptors[0], NetworkStatusDocumentV3))
    self.assertEqual(0, len(descriptors[0].routers))
示例#2
0
  def test_examples(self):
    """
    Run something similar to the examples in the header pydocs.
    """

    # makes a consensus with a couple routers, both with the same nickname

    entry1 = get_router_status_entry_v3({'s': 'Fast'})
    entry2 = get_router_status_entry_v3({'s': 'Valid'})
    content = get_network_status_document_v3(routers = (entry1, entry2), content = True)

    # first example: parsing via the NetworkStatusDocumentV3 constructor

    consensus_file = io.BytesIO(content)
    consensus = NetworkStatusDocumentV3(consensus_file.read())
    consensus_file.close()

    for router in consensus.routers.values():
      self.assertEqual('caerSidi', router.nickname)

    # second example: using stem.descriptor.parse_file

    with io.BytesIO(content) as consensus_file:
      for router in stem.descriptor.parse_file(consensus_file, 'network-status-consensus-3 1.0'):
        self.assertEqual('caerSidi', router.nickname)
示例#3
0
    def test_flags(self):
        """
    Handles a variety of flag inputs.
    """

        test_values = {
            "": [],
            "Fast": [Flag.FAST],
            "Fast Valid": [Flag.FAST, Flag.VALID],
            "Ugabuga": ["Ugabuga"],
        }

        for s_line, expected in test_values.items():
            entry = get_router_status_entry_v3({'s': s_line})
            self.assertEquals(expected, entry.flags)

        # tries some invalid inputs
        test_values = {
            "Fast   ": [Flag.FAST, "", "", ""],
            "Fast  Valid": [Flag.FAST, "", Flag.VALID],
            "Fast Fast": [Flag.FAST, Flag.FAST],
        }

        for s_line, expected in test_values.items():
            content = get_router_status_entry_v3({'s': s_line}, content=True)
            self._expect_invalid_attr(content, "flags", expected)
示例#4
0
  def test_flags(self):
    """
    Handles a variety of flag inputs.
    """

    test_values = {
      "": [],
      "Fast": [Flag.FAST],
      "Fast Valid": [Flag.FAST, Flag.VALID],
      "Ugabuga": ["Ugabuga"],
    }

    for s_line, expected in test_values.items():
      entry = get_router_status_entry_v3({'s': s_line})
      self.assertEquals(expected, entry.flags)

    # tries some invalid inputs
    test_values = {
      "Fast   ": [Flag.FAST, "", "", ""],
      "Fast  Valid": [Flag.FAST, "", Flag.VALID],
      "Fast Fast": [Flag.FAST, Flag.FAST],
    }

    for s_line, expected in test_values.items():
      content = get_router_status_entry_v3({'s': s_line}, content = True)
      self._expect_invalid_attr(content, "flags", expected)
示例#5
0
  def test_with_router_status_entries(self):
    """
    Includes router status entries within the document. This isn't to test the
    RouterStatusEntry parsing but rather the inclusion of it within the
    document.
    """

    entry1 = get_router_status_entry_v3({'s': "Fast"})
    entry2 = get_router_status_entry_v3({
      'r': "Nightfae AWt0XNId/OU2xX5xs5hVtDc5Mes 6873oEfM7fFIbxYtwllw9GPDwkA 2013-02-20 11:12:27 85.177.66.233 9001 9030",
      's': "Valid",
    })

    document = get_network_status_document_v3(routers = (entry1, entry2))

    self.assertTrue(entry1 in document.routers.values())
    self.assertTrue(entry2 in document.routers.values())

    # try with an invalid RouterStatusEntry

    entry3 = RouterStatusEntryV3(get_router_status_entry_v3({'r': "ugabuga"}, content = True), False)
    content = get_network_status_document_v3(routers = (entry3,), content = True)

    self.assertRaises(ValueError, NetworkStatusDocumentV3, content)
    document = NetworkStatusDocumentV3(content, False)
    self.assertEquals([entry3], document.routers.values())

    # try including with a microdescriptor consensus

    content = get_network_status_document_v3({"network-status-version": "3 microdesc"}, routers = (entry1,), content = True)
    self.assertRaises(ValueError, NetworkStatusDocumentV3, content)

    document = NetworkStatusDocumentV3(content, False)
    self.assertEqual([RouterStatusEntryMicroV3(str(entry1), False)], document.routers.values())
示例#6
0
 def test_bandwidth(self):
   """
   Handles a variety of 'w' lines.
   """
   
   test_values = {
     "Bandwidth=0": (0, None, []),
     "Bandwidth=63138": (63138, None, []),
     "Bandwidth=11111 Measured=482": (11111, 482, []),
     "Bandwidth=11111 Measured=482 Blarg!": (11111, 482, ["Blarg!"]),
   }
   
   for w_line, expected in test_values.items():
     entry = get_router_status_entry_v3({'w': w_line})
     self.assertEquals(expected[0], entry.bandwidth)
     self.assertEquals(expected[1], entry.measured)
     self.assertEquals(expected[2], entry.unrecognized_bandwidth_entries)
   
   # tries some invalid inputs
   test_values = (
     "",
     "blarg",
     "Bandwidth",
     "Bandwidth=",
     "Bandwidth:0",
     "Bandwidth 0",
     "Bandwidth=-10",
     "Bandwidth=10 Measured",
     "Bandwidth=10 Measured=",
     "Bandwidth=10 Measured=-50",
   )
   
   for w_line in test_values:
     content = get_router_status_entry_v3({'w': w_line}, content = True)
     self._expect_invalid_attr(content)
示例#7
0
    def test_handlers(self):
        """
    Try parsing a document with DocumentHandler.DOCUMENT and
    DocumentHandler.BARE_DOCUMENT.
    """

        # Simple sanity check that they provide the right type, and that the
        # document includes or excludes the router status entries as appropriate.

        entry1 = get_router_status_entry_v3({'s': "Fast"})
        entry2 = get_router_status_entry_v3({'s': "Valid"})
        content = get_network_status_document_v3(routers=(entry1, entry2),
                                                 content=True)

        descriptors = list(
            stem.descriptor.parse_file(
                StringIO.StringIO(content),
                'network-status-consensus-3 1.0',
                document_handler=stem.descriptor.DocumentHandler.DOCUMENT))
        self.assertEqual(1, len(descriptors))
        self.assertTrue(isinstance(descriptors[0], NetworkStatusDocumentV3))
        self.assertEqual(2, len(descriptors[0].routers))

        descriptors = list(
            stem.descriptor.parse_file(StringIO.StringIO(content),
                                       'network-status-consensus-3 1.0',
                                       document_handler=stem.descriptor.
                                       DocumentHandler.BARE_DOCUMENT))
        self.assertEqual(1, len(descriptors))
        self.assertTrue(isinstance(descriptors[0], NetworkStatusDocumentV3))
        self.assertEqual(0, len(descriptors[0].routers))
示例#8
0
  def test_handlers(self):
    """
    Try parsing a document with DocumentHandler.DOCUMENT and
    DocumentHandler.BARE_DOCUMENT.
    """

    # Simple sanity check that they provide the right type, and that the
    # document includes or excludes the router status entries as appropriate.

    entry1 = get_router_status_entry_v3({'s': "Fast"})
    entry2 = get_router_status_entry_v3({
      'r': "Nightfae AWt0XNId/OU2xX5xs5hVtDc5Mes 6873oEfM7fFIbxYtwllw9GPDwkA 2013-02-20 11:12:27 85.177.66.233 9001 9030",
      's': "Valid",
    })

    content = get_network_status_document_v3(routers = (entry1, entry2), content = True)

    descriptors = list(stem.descriptor.parse_file(io.BytesIO(content), 'network-status-consensus-3 1.0', document_handler = stem.descriptor.DocumentHandler.DOCUMENT))
    self.assertEqual(1, len(descriptors))
    self.assertTrue(isinstance(descriptors[0], NetworkStatusDocumentV3))
    self.assertEqual(2, len(descriptors[0].routers))

    descriptors = list(stem.descriptor.parse_file(io.BytesIO(content), 'network-status-consensus-3 1.0', document_handler = stem.descriptor.DocumentHandler.BARE_DOCUMENT))
    self.assertEqual(1, len(descriptors))
    self.assertTrue(isinstance(descriptors[0], NetworkStatusDocumentV3))
    self.assertEqual(0, len(descriptors[0].routers))
示例#9
0
    def test_examples(self):
        """
    Run something similar to the examples in the header pydocs.
    """

        # makes a consensus with a couple routers, both with the same nickname

        entry1 = get_router_status_entry_v3({'s': "Fast"})
        entry2 = get_router_status_entry_v3({'s': "Valid"})
        content = get_network_status_document_v3(routers=(entry1, entry2),
                                                 content=True)

        # first example: parsing via the NetworkStatusDocumentV3 constructor

        consensus_file = StringIO.StringIO(content)
        consensus = NetworkStatusDocumentV3(consensus_file.read())
        consensus_file.close()

        for router in consensus.routers:
            self.assertEqual('caerSidi', router.nickname)

        # second example: using stem.descriptor.parse_file

        with support_with(StringIO.StringIO(content)) as consensus_file:
            for router in stem.descriptor.parse_file(
                    consensus_file, 'network-status-consensus-3 1.0'):
                self.assertEqual('caerSidi', router.nickname)
示例#10
0
    def test_flags(self):
        """
    Handles a variety of flag inputs.
    """

        test_values = {
            '': [],
            'Fast': [Flag.FAST],
            'Fast Valid': [Flag.FAST, Flag.VALID],
            'Ugabuga': ['Ugabuga'],
        }

        for s_line, expected in test_values.items():
            entry = get_router_status_entry_v3({'s': s_line})
            self.assertEquals(expected, entry.flags)

        # tries some invalid inputs
        test_values = {
            'Fast   ': [Flag.FAST, '', '', ''],
            'Fast  Valid': [Flag.FAST, '', Flag.VALID],
            'Fast Fast': [Flag.FAST, Flag.FAST],
        }

        for s_line, expected in test_values.items():
            content = get_router_status_entry_v3({'s': s_line}, content=True)
            self._expect_invalid_attr(content, 'flags', expected)
示例#11
0
  def test_exit_policy(self):
    """
    Handles a variety of 'p' lines.
    """

    test_values = {
      'reject 1-65535': MicroExitPolicy('reject 1-65535'),
      'accept 80,110,143,443': MicroExitPolicy('accept 80,110,143,443'),
    }

    for p_line, expected in test_values.items():
      entry = get_router_status_entry_v3({'p': p_line})
      self.assertEqual(expected, entry.exit_policy)

    # tries some invalid inputs
    test_values = (
      '',
      'blarg',
      'reject -50',
      'accept 80,',
    )

    for p_line in test_values:
      content = get_router_status_entry_v3({'p': p_line}, content = True)
      self._expect_invalid_attr(content, 'exit_policy')
示例#12
0
    def test_exit_policy(self):
        """
    Handles a variety of 'p' lines.
    """

        test_values = {
            'reject 1-65535': MicroExitPolicy('reject 1-65535'),
            'accept 80,110,143,443': MicroExitPolicy('accept 80,110,143,443'),
        }

        for p_line, expected in test_values.items():
            entry = get_router_status_entry_v3({'p': p_line})
            self.assertEquals(expected, entry.exit_policy)

        # tries some invalid inputs
        test_values = (
            '',
            'blarg',
            'reject -50',
            'accept 80,',
        )

        for p_line in test_values:
            content = get_router_status_entry_v3({'p': p_line}, content=True)
            self._expect_invalid_attr(content, 'exit_policy')
示例#13
0
  def test_flags(self):
    """
    Handles a variety of flag inputs.
    """

    test_values = {
      '': [],
      'Fast': [Flag.FAST],
      'Fast Valid': [Flag.FAST, Flag.VALID],
      'Ugabuga': ['Ugabuga'],
    }

    for s_line, expected in test_values.items():
      entry = get_router_status_entry_v3({'s': s_line})
      self.assertEqual(expected, entry.flags)

    # tries some invalid inputs
    test_values = {
      'Fast   ': [Flag.FAST, '', '', ''],
      'Fast  Valid': [Flag.FAST, '', Flag.VALID],
      'Fast Fast': [Flag.FAST, Flag.FAST],
    }

    for s_line, expected in test_values.items():
      content = get_router_status_entry_v3({'s': s_line}, content = True)
      self._expect_invalid_attr(content, 'flags', expected)
示例#14
0
  def test_with_router_status_entries(self):
    """
    Includes router status entries within the document. This isn't to test the
    RouterStatusEntry parsing but rather the inclusion of it within the
    document.
    """

    entry1 = get_router_status_entry_v3({'s': 'Fast'})
    entry2 = get_router_status_entry_v3({
      'r': 'Nightfae AWt0XNId/OU2xX5xs5hVtDc5Mes 6873oEfM7fFIbxYtwllw9GPDwkA 2013-02-20 11:12:27 85.177.66.233 9001 9030',
      's': 'Valid',
    })

    document = get_network_status_document_v3(routers = (entry1, entry2))

    self.assertTrue(entry1 in document.routers.values())
    self.assertTrue(entry2 in document.routers.values())

    # try with an invalid RouterStatusEntry

    entry3 = RouterStatusEntryV3(get_router_status_entry_v3({'r': 'ugabuga'}, content = True), False)
    content = get_network_status_document_v3(routers = (entry3,), content = True)

    self.assertRaises(ValueError, NetworkStatusDocumentV3, content, True)
    document = NetworkStatusDocumentV3(content, False)
    self.assertEqual([entry3], list(document.routers.values()))

    # try including with a microdescriptor consensus

    content = get_network_status_document_v3({'network-status-version': '3 microdesc'}, routers = (entry1,), content = True)
    self.assertRaises(ValueError, NetworkStatusDocumentV3, content, True)

    document = NetworkStatusDocumentV3(content, False)
    self.assertEqual([RouterStatusEntryMicroV3(str(entry1), False)], list(document.routers.values()))
示例#15
0
    def test_exit_policy(self):
        """
    Handles a variety of 'p' lines.
    """

        test_values = {
            "reject 1-65535": MicroExitPolicy("reject 1-65535"),
            "accept 80,110,143,443": MicroExitPolicy("accept 80,110,143,443"),
        }

        for p_line, expected in test_values.items():
            entry = get_router_status_entry_v3({'p': p_line})
            self.assertEquals(expected, entry.exit_policy)

        # tries some invalid inputs
        test_values = (
            "",
            "blarg",
            "reject -50",
            "accept 80,",
        )

        for p_line in test_values:
            content = get_router_status_entry_v3({'p': p_line}, content=True)
            self._expect_invalid_attr(content, "exit_policy")
示例#16
0
  def test_votes_by_bandwidth_authorities(self, query_mock, get_authorities_mock, stdout_mock):
    directory_values = [
      DIRECTORY_AUTHORITIES['gabelmoo'],
      DIRECTORY_AUTHORITIES['tor26'],
      DIRECTORY_AUTHORITIES['moria1'],
      DIRECTORY_AUTHORITIES['maatuska'],
    ]

    directory_values[0].address = '131.188.40.189'
    get_authorities_mock().values.return_value = directory_values

    entry_with_measurement = get_router_status_entry_v3({'w': 'Bandwidth=1 Measured=1'})
    entry_without_measurement = get_router_status_entry_v3()

    query1 = Mock()
    query1.download_url = 'http://131.188.40.189:80/tor/status-vote/current/authority'
    query1.run.return_value = [entry_with_measurement] * 5935 + [entry_without_measurement] * 1332

    query2 = Mock()
    query2.download_url = 'http://86.59.21.38:80/tor/status-vote/current/authority'
    query2.run.return_value = [entry_with_measurement] * 5735 + [entry_without_measurement] * 1690

    query3 = Mock()
    query3.download_url = 'http://128.31.0.39:9131/tor/status-vote/current/authority'
    query3.run.return_value = [entry_with_measurement] * 6647 + [entry_without_measurement] * 625

    query4 = Mock()
    query4.download_url = 'http://171.25.193.9:443/tor/status-vote/current/authority'
    query4.run.return_value = [entry_with_measurement] * 6313 + [entry_without_measurement] * 1112

    query_mock.side_effect = [query1, query2, query3, query4]

    exec_documentation_example('votes_by_bandwidth_authorities.py')
    self.assert_equal_unordered(VOTES_BY_BANDWIDTH_AUTHORITIES_OUTPUT, stdout_mock.getvalue())
示例#17
0
  def test_exit_policy(self):
    """
    Handles a variety of 'p' lines.
    """

    test_values = {
      "reject 1-65535": MicroExitPolicy("reject 1-65535"),
      "accept 80,110,143,443": MicroExitPolicy("accept 80,110,143,443"),
    }

    for p_line, expected in test_values.items():
      entry = get_router_status_entry_v3({'p': p_line})
      self.assertEquals(expected, entry.exit_policy)

    # tries some invalid inputs
    test_values = (
      "",
      "blarg",
      "reject -50",
      "accept 80,",
    )

    for p_line in test_values:
      content = get_router_status_entry_v3({'p': p_line}, content = True)
      self._expect_invalid_attr(content, "exit_policy")
示例#18
0
文件: events.py 项目: gsathya/stem
    def test_new_consensus_event(self):
        expected_desc = []

        expected_desc.append(
            mocking.get_router_status_entry_v3(
                {
                    "r": "Beaver /96bKo4soysolMgKn5Hex2nyFSY pAJH9dSBp/CG6sPhhVY/5bLaVPM 2012-12-02 22:02:45 77.223.43.54 9001 0",
                    "s": "Fast Named Running Stable Valid",
                }
            )
        )

        expected_desc.append(
            mocking.get_router_status_entry_v3(
                {
                    "r": "Unnamed /+fJRWjmIGNAL2C5rRZHq3R91tA 7AnpZjfdBpYzXnMNm+w1bTsFF6Y 2012-12-02 17:51:10 91.121.184.87 9001 0",
                    "s": "Fast Guard Running Stable Valid",
                }
            )
        )

        event = _get_event(NEWCONSENSUS_EVENT)

        self.assertTrue(isinstance(event, stem.response.events.NewConsensusEvent))
        self.assertEqual(expected_desc, event.desc)
示例#19
0
  def test_bandwidth(self):
    """
    Handles a variety of 'w' lines.
    """

    test_values = {
      "Bandwidth=0": (0, None, []),
      "Bandwidth=63138": (63138, None, []),
      "Bandwidth=11111 Measured=482": (11111, 482, []),
      "Bandwidth=11111 Measured=482 Blarg!": (11111, 482, ["Blarg!"]),
    }

    for w_line, expected in test_values.items():
      entry = get_router_status_entry_v3({'w': w_line})
      self.assertEquals(expected[0], entry.bandwidth)
      self.assertEquals(expected[1], entry.measured)
      self.assertEquals(expected[2], entry.unrecognized_bandwidth_entries)

    # tries some invalid inputs
    test_values = (
      "",
      "blarg",
      "Bandwidth",
      "Bandwidth=",
      "Bandwidth:0",
      "Bandwidth 0",
      "Bandwidth=-10",
      "Bandwidth=10 Measured",
      "Bandwidth=10 Measured=",
      "Bandwidth=10 Measured=-50",
    )

    for w_line in test_values:
      content = get_router_status_entry_v3({'w': w_line}, content = True)
      self._expect_invalid_attr(content)
示例#20
0
  def test_with_router_status_entries(self):
    """
    Includes router status entries within the document. This isn't to test the
    RouterStatusEntry parsing but rather the inclusion of it within the
    document.
    """

    entry1 = get_router_status_entry_v3({'s': "Fast"})
    entry2 = get_router_status_entry_v3({'s': "Valid"})
    document = get_network_status_document_v3(routers = (entry1, entry2))

    self.assertEquals((entry1, entry2), document.routers)

    # try with an invalid RouterStatusEntry

    entry3 = RouterStatusEntryV3(get_router_status_entry_v3({'r': "ugabuga"}, content = True), False)
    content = get_network_status_document_v3(routers = (entry3,), content = True)

    self.assertRaises(ValueError, NetworkStatusDocumentV3, content)
    document = NetworkStatusDocumentV3(content, False)
    self.assertEquals((entry3,), document.routers)

    # try including with a microdescriptor consensus

    content = get_network_status_document_v3({"network-status-version": "3 microdesc"}, routers = (entry1, entry2), content = True)
    self.assertRaises(ValueError, NetworkStatusDocumentV3, content)

    expected_routers = (
      RouterStatusEntryMicroV3(str(entry1), False),
      RouterStatusEntryMicroV3(str(entry2), False),
    )

    document = NetworkStatusDocumentV3(content, False)
    self.assertEquals(expected_routers, document.routers)
示例#21
0
  def test_examples(self):
    """
    Run something similar to the examples in the header pydocs.
    """

    # makes a consensus with a couple routers, both with the same nickname

    entry1 = get_router_status_entry_v3({'s': "Fast"})
    entry2 = get_router_status_entry_v3({'s': "Valid"})
    content = get_network_status_document_v3(routers = (entry1, entry2), content = True)

    # first example: parsing via the NetworkStatusDocumentV3 constructor

    consensus_file = StringIO.StringIO(content)
    consensus = NetworkStatusDocumentV3(consensus_file.read())
    consensus_file.close()

    for router in consensus.routers:
      self.assertEqual('caerSidi', router.nickname)

    # second example: using parse_file

    with support_with(StringIO.StringIO(content)) as consensus_file:
      for router in parse_file(consensus_file):
        self.assertEqual('caerSidi', router.nickname)
示例#22
0
    def test_microdescriptor_hashes(self):
        """
    Handles a variety of 'm' lines.
    """

        test_values = {
            '8,9,10,11,12': [([8, 9, 10, 11, 12], {})],
            '8,9,10,11,12 sha256=g1vx9si329muxV3tquWIXXySNOIwRGMeAESKs/v4DWs':
            [([8, 9, 10, 11, 12], {
                'sha256': 'g1vx9si329muxV3tquWIXXySNOIwRGMeAESKs/v4DWs'
            })],
            '8,9,10,11,12 sha256=g1vx9si329muxV md5=3tquWIXXySNOIwRGMeAESKs/v4DWs':
            [([8, 9, 10, 11, 12], {
                'sha256': 'g1vx9si329muxV',
                'md5': '3tquWIXXySNOIwRGMeAESKs/v4DWs'
            })],
        }

        for m_line, expected in test_values.items():
            content = get_router_status_entry_v3({'m': m_line}, content=True)
            entry = RouterStatusEntryV3(content, document=vote_document())
            self.assertEqual(expected, entry.microdescriptor_hashes)

        # try with multiple 'm' lines

        content = get_router_status_entry_v3(content=True)
        content += b'\nm 11,12 sha256=g1vx9si329muxV3tquWIXXySNOIwRGMeAESKs/v4DWs'
        content += b'\nm 31,32 sha512=g1vx9si329muxV3tquWIXXySNOIwRGMeAESKs/v4DWs'

        expected = [
            ([11, 12], {
                'sha256': 'g1vx9si329muxV3tquWIXXySNOIwRGMeAESKs/v4DWs'
            }),
            ([31, 32], {
                'sha512': 'g1vx9si329muxV3tquWIXXySNOIwRGMeAESKs/v4DWs'
            }),
        ]

        entry = RouterStatusEntryV3(content, document=vote_document())
        self.assertEqual(expected, entry.microdescriptor_hashes)

        # try without a document
        content = get_router_status_entry_v3({'m': '8,9,10,11,12'},
                                             content=True)
        self._expect_invalid_attr(content,
                                  'microdescriptor_hashes',
                                  expected_value=[])

        # tries some invalid inputs
        test_values = (
            '',
            '4,a,2',
            '1,2,3 stuff',
        )

        for m_line in test_values:
            content = get_router_status_entry_v3({'m': m_line}, content=True)
            self.assertRaises(ValueError, RouterStatusEntryV3, content, True,
                              vote_document())
示例#23
0
  def test_microdescriptor_hashes(self):
    """
    Handles a variety of 'm' lines.
    """

    test_values = {
      '8,9,10,11,12':
        [([8, 9, 10, 11, 12], {})],
      '8,9,10,11,12 sha256=g1vx9si329muxV3tquWIXXySNOIwRGMeAESKs/v4DWs':
        [([8, 9, 10, 11, 12], {'sha256': 'g1vx9si329muxV3tquWIXXySNOIwRGMeAESKs/v4DWs'})],
      '8,9,10,11,12 sha256=g1vx9si329muxV md5=3tquWIXXySNOIwRGMeAESKs/v4DWs':
        [([8, 9, 10, 11, 12], {'sha256': 'g1vx9si329muxV', 'md5': '3tquWIXXySNOIwRGMeAESKs/v4DWs'})],
    }

    # we need a document that's a vote
    mock_document = lambda x: x  # just need anything with a __dict__
    setattr(mock_document, 'is_vote', True)
    setattr(mock_document, 'is_consensus', False)

    for m_line, expected in test_values.items():
      content = get_router_status_entry_v3({'m': m_line}, content = True)
      entry = RouterStatusEntryV3(content, document = mock_document)
      self.assertEqual(expected, entry.microdescriptor_hashes)

    # try with multiple 'm' lines

    content = get_router_status_entry_v3(content = True)
    content += b'\nm 11,12 sha256=g1vx9si329muxV3tquWIXXySNOIwRGMeAESKs/v4DWs'
    content += b'\nm 31,32 sha512=g1vx9si329muxV3tquWIXXySNOIwRGMeAESKs/v4DWs'

    expected = [
      ([11, 12], {'sha256': 'g1vx9si329muxV3tquWIXXySNOIwRGMeAESKs/v4DWs'}),
      ([31, 32], {'sha512': 'g1vx9si329muxV3tquWIXXySNOIwRGMeAESKs/v4DWs'}),
    ]

    entry = RouterStatusEntryV3(content, document = mock_document)
    self.assertEqual(expected, entry.microdescriptor_hashes)

    # try without a document
    content = get_router_status_entry_v3({'m': '8,9,10,11,12'}, content = True)
    self._expect_invalid_attr(content, 'microdescriptor_hashes', expected_value = [])

    # tries some invalid inputs
    test_values = (
      '',
      '4,a,2',
      '1,2,3 stuff',
    )

    for m_line in test_values:
      content = get_router_status_entry_v3({'m': m_line}, content = True)
      self.assertRaises(ValueError, RouterStatusEntryV3, content, True, mock_document)
示例#24
0
  def test_microdescriptor_hashes(self):
    """
    Handles a variety of 'm' lines.
    """

    test_values = {
      "8,9,10,11,12":
        [([8, 9, 10, 11, 12], {})],
      "8,9,10,11,12 sha256=g1vx9si329muxV3tquWIXXySNOIwRGMeAESKs/v4DWs":
        [([8, 9, 10, 11, 12], {"sha256": "g1vx9si329muxV3tquWIXXySNOIwRGMeAESKs/v4DWs"})],
      "8,9,10,11,12 sha256=g1vx9si329muxV md5=3tquWIXXySNOIwRGMeAESKs/v4DWs":
        [([8, 9, 10, 11, 12], {"sha256": "g1vx9si329muxV", "md5": "3tquWIXXySNOIwRGMeAESKs/v4DWs"})],
    }

    # we need a document that's a vote
    mock_document = lambda x: x  # just need anything with a __dict__
    setattr(mock_document, "is_vote", True)
    setattr(mock_document, "is_consensus", False)

    for m_line, expected in test_values.items():
      content = get_router_status_entry_v3({'m': m_line}, content = True)
      entry = RouterStatusEntryV3(content, document = mock_document)
      self.assertEquals(expected, entry.microdescriptor_hashes)

    # try with multiple 'm' lines

    content = get_router_status_entry_v3(content = True)
    content += "\nm 11,12 sha256=g1vx9si329muxV3tquWIXXySNOIwRGMeAESKs/v4DWs"
    content += "\nm 31,32 sha512=g1vx9si329muxV3tquWIXXySNOIwRGMeAESKs/v4DWs"

    expected = [
      ([11, 12], {"sha256": "g1vx9si329muxV3tquWIXXySNOIwRGMeAESKs/v4DWs"}),
      ([31, 32], {"sha512": "g1vx9si329muxV3tquWIXXySNOIwRGMeAESKs/v4DWs"}),
    ]

    entry = RouterStatusEntryV3(content, document = mock_document)
    self.assertEquals(expected, entry.microdescriptor_hashes)

    # try without a document
    content = get_router_status_entry_v3({'m': "8,9,10,11,12"}, content = True)
    self._expect_invalid_attr(content, "microdescriptor_hashes", expected_value = [])

    # tries some invalid inputs
    test_values = (
      "",
      "4,a,2",
      "1,2,3 stuff",
    )

    for m_line in test_values:
      content = get_router_status_entry_v3({'m': m_line}, content = True)
      self.assertRaises(ValueError, RouterStatusEntryV3, content, True, mock_document)
示例#25
0
  def test_microdescriptor_hashes(self):
    """
    Handles a variety of 'm' lines.
    """

    test_values = {
      "8,9,10,11,12":
        [([8, 9, 10, 11, 12], {})],
      "8,9,10,11,12 sha256=g1vx9si329muxV3tquWIXXySNOIwRGMeAESKs/v4DWs":
        [([8, 9, 10, 11, 12], {"sha256": "g1vx9si329muxV3tquWIXXySNOIwRGMeAESKs/v4DWs"})],
      "8,9,10,11,12 sha256=g1vx9si329muxV md5=3tquWIXXySNOIwRGMeAESKs/v4DWs":
        [([8, 9, 10, 11, 12], {"sha256": "g1vx9si329muxV", "md5": "3tquWIXXySNOIwRGMeAESKs/v4DWs"})],
    }

    # we need a document that's a vote
    mock_document = lambda x: x  # just need anything with a __dict__
    setattr(mock_document, "is_vote", True)
    setattr(mock_document, "is_consensus", False)

    for m_line, expected in test_values.items():
      content = get_router_status_entry_v3({'m': m_line}, content = True)
      entry = RouterStatusEntryV3(content, document = mock_document)
      self.assertEquals(expected, entry.microdescriptor_hashes)

    # try with multiple 'm' lines

    content = get_router_status_entry_v3(content = True)
    content += b"\nm 11,12 sha256=g1vx9si329muxV3tquWIXXySNOIwRGMeAESKs/v4DWs"
    content += b"\nm 31,32 sha512=g1vx9si329muxV3tquWIXXySNOIwRGMeAESKs/v4DWs"

    expected = [
      ([11, 12], {"sha256": "g1vx9si329muxV3tquWIXXySNOIwRGMeAESKs/v4DWs"}),
      ([31, 32], {"sha512": "g1vx9si329muxV3tquWIXXySNOIwRGMeAESKs/v4DWs"}),
    ]

    entry = RouterStatusEntryV3(content, document = mock_document)
    self.assertEquals(expected, entry.microdescriptor_hashes)

    # try without a document
    content = get_router_status_entry_v3({'m': "8,9,10,11,12"}, content = True)
    self._expect_invalid_attr(content, "microdescriptor_hashes", expected_value = [])

    # tries some invalid inputs
    test_values = (
      "",
      "4,a,2",
      "1,2,3 stuff",
    )

    for m_line in test_values:
      content = get_router_status_entry_v3({'m': m_line}, content = True)
      self.assertRaises(ValueError, RouterStatusEntryV3, content, True, mock_document)
示例#26
0
    def test_missing_fields(self):
        """
    Parses a router status entry that's missing fields.
    """

        content = get_router_status_entry_v3(exclude=('r', 's'), content=True)
        self._expect_invalid_attr(content, 'address')

        content = get_router_status_entry_v3(exclude=('r', ), content=True)
        self._expect_invalid_attr(content, 'address')

        content = get_router_status_entry_v3(exclude=('s', ), content=True)
        self._expect_invalid_attr(content, 'flags')
示例#27
0
  def test_missing_fields(self):
    """
    Parses a router status entry that's missing fields.
    """

    content = get_router_status_entry_v3(exclude = ('r', 's'), content = True)
    self._expect_invalid_attr(content, "address")

    content = get_router_status_entry_v3(exclude = ('r',), content = True)
    self._expect_invalid_attr(content, "address")

    content = get_router_status_entry_v3(exclude = ('s',), content = True)
    self._expect_invalid_attr(content, "flags")
    def test_ipv6_addresses(self):
        """
    Handles a variety of 'a' lines.
    """

        test_values = {
            "[2607:fcd0:daaa:101::602c:bd62]:443": {
                '2607:fcd0:daaa:101::602c:bd62': [(443, 443)]
            },
            "[2607:fcd0:daaa:101::602c:bd62]:80,443": {
                '2607:fcd0:daaa:101::602c:bd62': [(80, 80), (443, 443)]
            },
            "[2607:fcd0:daaa:101::602c:bd62]:443-512": {
                '2607:fcd0:daaa:101::602c:bd62': [(443, 512)]
            },
        }

        for a_line, expected in test_values.items():
            entry = get_router_status_entry_v3({'a': a_line})
            self.assertEquals(expected, entry.addresses_v6)

        # includes multiple 'a' lines

        content = get_router_status_entry_v3(content=True)
        content += "\na [2607:fcd0:daaa:101::602c:bd62]:80,443"
        content += "\na [2607:fcd0:daaa:101::602c:bd62]:512-600"
        content += "\na [1148:fcd0:daaa:101::602c:bd62]:80"

        expected = {
            '2607:fcd0:daaa:101::602c:bd62': [(80, 80), (443, 443),
                                              (512, 600)],
            '1148:fcd0:daaa:101::602c:bd62': [(80, 80)],
        }

        entry = RouterStatusEntryV3(content)
        self.assertEquals(expected, entry.addresses_v6)

        # tries some invalid inputs

        test_values = (
            "",
            "127.0.0.1:80",
            "[1148:fcd0:daaa:101::602c:bd62]:80000",
        )

        for a_line in test_values:
            content = get_router_status_entry_v3({'a': a_line}, content=True)
            self._expect_invalid_attr(content, expected_value={})
示例#29
0
  def test_persisting_a_consensus(self, query_mock, open_mock, parse_file_mock, stdout_mock):
    def tutorial_example_1():
      from stem.descriptor import DocumentHandler
      from stem.descriptor.remote import DescriptorDownloader

      downloader = DescriptorDownloader()
      consensus = downloader.get_consensus(document_handler = DocumentHandler.DOCUMENT).run()[0]

      with open('/tmp/descriptor_dump', 'w') as descriptor_file:
        descriptor_file.write(str(consensus))

    def tutorial_example_2():
      from stem.descriptor import DocumentHandler, parse_file

      consensus = next(parse_file(
        '/tmp/descriptor_dump',
        descriptor_type = 'network-status-consensus-3 1.0',
        document_handler = DocumentHandler.DOCUMENT,
      ))

      for fingerprint, relay in consensus.routers.items():
        print('%s: %s' % (fingerprint, relay.nickname))

    network_status = get_network_status_document_v3(routers = (get_router_status_entry_v3(),))
    query_mock().run.return_value = [network_status]
    parse_file_mock.return_value = itertools.cycle([network_status])

    tutorial_example_1()
    tutorial_example_2()

    self.assertEqual(PERSISTING_A_CONSENSUS_OUTPUT, stdout_mock.getvalue())
示例#30
0
    def test_minimal_v3(self):
        """
    Parses a minimal v3 router status entry.
    """

        entry = get_router_status_entry_v3()

        expected_flags = set(
            [Flag.FAST, Flag.NAMED, Flag.RUNNING, Flag.STABLE, Flag.VALID])
        self.assertEqual(None, entry.document)
        self.assertEqual('caerSidi', entry.nickname)
        self.assertEqual('A7569A83B5706AB1B1A9CB52EFF7D2D32E4553EB',
                         entry.fingerprint)
        self.assertEqual('A106452D87BD7B803B6CE916291ED368DC5BD091',
                         entry.digest)
        self.assertEqual(datetime.datetime(2012, 8, 6, 11, 19, 31),
                         entry.published)
        self.assertEqual('71.35.150.29', entry.address)
        self.assertEqual(9001, entry.or_port)
        self.assertEqual(None, entry.dir_port)
        self.assertEqual(expected_flags, set(entry.flags))
        self.assertEqual(None, entry.version_line)
        self.assertEqual(None, entry.version)
        self.assertEqual(None, entry.bandwidth)
        self.assertEqual(None, entry.measured)
        self.assertEqual(False, entry.is_unmeasured)
        self.assertEqual([], entry.unrecognized_bandwidth_entries)
        self.assertEqual(None, entry.exit_policy)
        self.assertEqual([], entry.microdescriptor_hashes)
        self.assertEqual([], entry.get_unrecognized_lines())
示例#31
0
  def test_persisting_a_consensus(self, query_mock, open_mock, parse_file_mock, stdout_mock):
    def tutorial_example_1():
      from stem.descriptor import DocumentHandler
      from stem.descriptor.remote import DescriptorDownloader

      downloader = DescriptorDownloader()
      consensus = downloader.get_consensus(document_handler = DocumentHandler.DOCUMENT).run()[0]

      with open('/tmp/descriptor_dump', 'w') as descriptor_file:
        descriptor_file.write(str(consensus))

    def tutorial_example_2():
      from stem.descriptor import DocumentHandler, parse_file

      consensus = next(parse_file(
        '/tmp/descriptor_dump',
        descriptor_type = 'network-status-consensus-3 1.0',
        document_handler = DocumentHandler.DOCUMENT,
      ))

      for fingerprint, relay in consensus.routers.items():
        print("%s: %s" % (fingerprint, relay.nickname))

    network_status = get_network_status_document_v3(routers = (get_router_status_entry_v3(),))
    query_mock().run.return_value = [network_status]
    parse_file_mock.return_value = itertools.cycle([network_status])

    tutorial_example_1()
    tutorial_example_2()

    self.assertEqual(PERSISTING_A_CONSENSUS_OUTPUT, stdout_mock.getvalue())
示例#32
0
    def test_malformed_port(self):
        """
    Parses an 'r' line with a malformed ORPort or DirPort.
    """

        test_values = (
            '',
            '-1',
            '399482',
            'blarg',
        )

        for value in test_values:
            for include_or_port in (False, True):
                for include_dir_port in (False, True):
                    if not include_or_port and not include_dir_port:
                        continue

                    r_line = ROUTER_STATUS_ENTRY_V3_HEADER[0][1]

                    if include_or_port:
                        r_line = r_line.replace(' 9001 ', ' %s ' % value)

                    if include_dir_port:
                        r_line = r_line[:-1] + value

                    attr = 'or_port' if include_or_port else 'dir_port'
                    expected = int(value) if value.isdigit() else None

                    content = get_router_status_entry_v3({'r': r_line},
                                                         content=True)
                    self._expect_invalid_attr(content, attr, expected)
示例#33
0
    def test_persisting_a_consensus(self, query_mock, open_mock,
                                    parse_file_mock, stdout_mock):
        def tutorial_example_2():
            from stem.descriptor import DocumentHandler, parse_file

            consensus = next(
                parse_file(
                    '/tmp/descriptor_dump',
                    descriptor_type='network-status-consensus-3 1.0',
                    document_handler=DocumentHandler.DOCUMENT,
                ))

            for fingerprint, relay in consensus.routers.items():
                print('%s: %s' % (fingerprint, relay.nickname))

        network_status = get_network_status_document_v3(
            routers=(get_router_status_entry_v3(), ))
        query_mock().run.return_value = [network_status]
        parse_file_mock.return_value = itertools.cycle([network_status])

        exec_documentation_example('persisting_a_consensus.py')
        exec_documentation_example('persisting_a_consensus_with_parse_file.py')

        self.assertEqual(PERSISTING_A_CONSENSUS_OUTPUT, stdout_mock.getvalue())

        if os.path.exists('/tmp/descriptor_dump'):
            os.remove('/tmp/descriptor_dump')
示例#34
0
    def test_malformed_nickname(self):
        """
    Parses an 'r' line with a malformed nickname.
    """

        test_values = (
            '',
            'saberrider2008ReallyLongNickname',  # too long
            '$aberrider2008',  # invalid characters
        )

        for value in test_values:
            r_line = ROUTER_STATUS_ENTRY_V3_HEADER[0][1].replace(
                'caerSidi', value)
            content = get_router_status_entry_v3({'r': r_line}, content=True)

            # TODO: Initial whitespace is consumed as part of the keyword/value
            # divider. This is a bug in the case of V3 router status entries, but
            # proper behavior for V2 router status entries and server/extrainfo
            # descriptors.
            #
            # I'm inclined to leave this as-is for the moment since fixing it
            # requires special KEYWORD_LINE handling, and the only result of this bug
            # is that our validation doesn't catch the new SP restriction on V3
            # entries.

            if value == '':
                value = None

            self._expect_invalid_attr(content, 'nickname', value)
示例#35
0
    def test_malformed_published_date(self):
        """
    Parses an 'r' line with a malformed published date.
    """

        test_values = (
            '',
            '2012-08-06 11:19:',
            '2012-08-06 11:19:71',
            '2012-08-06 11::31',
            '2012-08-06 11:79:31',
            '2012-08-06 :19:31',
            '2012-08-06 41:19:31',
            '2012-08- 11:19:31',
            '2012-08-86 11:19:31',
            '2012--06 11:19:31',
            '2012-38-06 11:19:31',
            '-08-06 11:19:31',
            '2012-08-06   11:19:31',
        )

        for value in test_values:
            r_line = ROUTER_STATUS_ENTRY_V3_HEADER[0][1].replace(
                '2012-08-06 11:19:31', value)
            content = get_router_status_entry_v3({'r': r_line}, content=True)
            self._expect_invalid_attr(content, 'published')
示例#36
0
    def test_mirror_mirror_on_the_wall_2(self):
        def tutorial_example():
            from stem.descriptor import parse_file

            for desc in parse_file(open("/home/atagar/.tor/cached-consensus")):
                print "found relay %s (%s)" % (desc.nickname, desc.fingerprint)

        test_file = io.BytesIO(
            mocking.get_network_status_document_v3(
                routers=[mocking.get_router_status_entry_v3()],
                content=True,
            ))

        mocking.support_with(test_file)
        test_file.name = "/home/atagar/.tor/cached-consensus"

        if is_python_3():
            import builtins
            mocking.mock(open,
                         mocking.return_value(test_file),
                         target_module=builtins)
        else:
            mocking.mock(open, mocking.return_value(test_file))

        tutorial_example()
        self.assertEqual(
            "found relay caerSidi (A7569A83B5706AB1B1A9CB52EFF7D2D32E4553EB)\n",
            self.stdout.getvalue())
示例#37
0
  def test_malformed_port(self):
    """
    Parses an 'r' line with a malformed ORPort or DirPort.
    """

    test_values = (
      '',
      '-1',
      '399482',
      'blarg',
    )

    for value in test_values:
      for include_or_port in (False, True):
        for include_dir_port in (False, True):
          if not include_or_port and not include_dir_port:
            continue

          r_line = ROUTER_STATUS_ENTRY_V3_HEADER[0][1]

          if include_or_port:
            r_line = r_line.replace(' 9001 ', ' %s ' % value)

          if include_dir_port:
            r_line = r_line[:-1] + value

          attr = 'or_port' if include_or_port else 'dir_port'

          content = get_router_status_entry_v3({'r': r_line}, content = True)
          self._expect_invalid_attr(content, attr)
示例#38
0
  def test_unrecognized_lines(self):
    """
    Parses a router status entry with new keywords.
    """

    entry = get_router_status_entry_v3({'z': 'New tor feature: sparkly unicorns!'})
    self.assertEquals(['z New tor feature: sparkly unicorns!'], entry.get_unrecognized_lines())
示例#39
0
  def test_proceeding_line(self):
    """
    Includes content prior to the 'r' line.
    """

    content = 'z some stuff\n' + get_router_status_entry_v3(content = True)
    self._expect_invalid_attr(content, "_unrecognized_lines", ['z some stuff'])
    def test_minimal_v3(self):
        """
    Parses a minimal v3 router status entry.
    """

        entry = get_router_status_entry_v3()

        expected_flags = set(
            [Flag.FAST, Flag.NAMED, Flag.RUNNING, Flag.STABLE, Flag.VALID])
        self.assertEqual(None, entry.document)
        self.assertEqual("caerSidi", entry.nickname)
        self.assertEqual("A7569A83B5706AB1B1A9CB52EFF7D2D32E4553EB",
                         entry.fingerprint)
        self.assertEqual("oQZFLYe9e4A7bOkWKR7TaNxb0JE", entry.digest)
        self.assertEqual(datetime.datetime(2012, 8, 6, 11, 19, 31),
                         entry.published)
        self.assertEqual("71.35.150.29", entry.address)
        self.assertEqual(9001, entry.or_port)
        self.assertEqual(None, entry.dir_port)
        self.assertEqual(expected_flags, set(entry.flags))
        self.assertEqual(None, entry.version_line)
        self.assertEqual(None, entry.version)
        self.assertEqual(None, entry.bandwidth)
        self.assertEqual(None, entry.measured)
        self.assertEqual([], entry.unrecognized_bandwidth_entries)
        self.assertEqual(None, entry.exit_policy)
        self.assertEqual([], entry.microdescriptor_hashes)
        self.assertEqual([], entry.get_unrecognized_lines())
示例#41
0
  def test_minimal_v3(self):
    """
    Parses a minimal v3 router status entry.
    """

    entry = get_router_status_entry_v3()

    expected_flags = set([Flag.FAST, Flag.NAMED, Flag.RUNNING, Flag.STABLE, Flag.VALID])
    self.assertEqual(None, entry.document)
    self.assertEqual("caerSidi", entry.nickname)
    self.assertEqual("A7569A83B5706AB1B1A9CB52EFF7D2D32E4553EB", entry.fingerprint)
    self.assertEqual("A106452D87BD7B803B6CE916291ED368DC5BD091", entry.digest)
    self.assertEqual(datetime.datetime(2012, 8, 6, 11, 19, 31), entry.published)
    self.assertEqual("71.35.150.29", entry.address)
    self.assertEqual(9001, entry.or_port)
    self.assertEqual(None, entry.dir_port)
    self.assertEqual(expected_flags, set(entry.flags))
    self.assertEqual(None, entry.version_line)
    self.assertEqual(None, entry.version)
    self.assertEqual(None, entry.bandwidth)
    self.assertEqual(None, entry.measured)
    self.assertEqual(False, entry.is_unmeasured)
    self.assertEqual([], entry.unrecognized_bandwidth_entries)
    self.assertEqual(None, entry.exit_policy)
    self.assertEqual([], entry.microdescriptor_hashes)
    self.assertEqual([], entry.get_unrecognized_lines())
示例#42
0
  def test_malformed_nickname(self):
    """
    Parses an 'r' line with a malformed nickname.
    """

    test_values = (
      "",
      "saberrider2008ReallyLongNickname",  # too long
      "$aberrider2008",  # invalid characters
    )

    for value in test_values:
      r_line = ROUTER_STATUS_ENTRY_V3_HEADER[0][1].replace("caerSidi", value)
      content = get_router_status_entry_v3({'r': r_line}, content = True)

      # TODO: Initial whitespace is consumed as part of the keyword/value
      # divider. This is a bug in the case of V3 router status entries, but
      # proper behavior for V2 router status entries and server/extrainfo
      # descriptors.
      #
      # I'm inclined to leave this as-is for the moment since fixing it
      # requires special KEYWORD_LINE handling, and the only result of this bug
      # is that our validation doesn't catch the new SP restriction on V3
      # entries.

      if value == "":
        value = None

      self._expect_invalid_attr(content, "nickname", value)
示例#43
0
  def test_malformed_published_date(self):
    """
    Parses an 'r' line with a malformed published date.
    """

    test_values = (
      "",
      "2012-08-06 11:19:",
      "2012-08-06 11:19:71",
      "2012-08-06 11::31",
      "2012-08-06 11:79:31",
      "2012-08-06 :19:31",
      "2012-08-06 41:19:31",
      "2012-08- 11:19:31",
      "2012-08-86 11:19:31",
      "2012--06 11:19:31",
      "2012-38-06 11:19:31",
      "-08-06 11:19:31",
      "2012-08-06   11:19:31",
    )

    for value in test_values:
      r_line = ROUTER_STATUS_ENTRY_V3_HEADER[0][1].replace("2012-08-06 11:19:31", value)
      content = get_router_status_entry_v3({'r': r_line}, content = True)
      self._expect_invalid_attr(content, "published")
示例#44
0
  def test_unrecognized_lines(self):
    """
    Parses a router status entry with new keywords.
    """

    entry = get_router_status_entry_v3({'z': 'New tor feature: sparkly unicorns!'})
    self.assertEquals(['z New tor feature: sparkly unicorns!'], entry.get_unrecognized_lines())
示例#45
0
  def test_malformed_port(self):
    """
    Parses an 'r' line with a malformed ORPort or DirPort.
    """

    test_values = (
      "",
      "-1",
      "399482",
      "blarg",
    )

    for value in test_values:
      for include_or_port in (False, True):
        for include_dir_port in (False, True):
          if not include_or_port and not include_dir_port:
            continue

          r_line = ROUTER_STATUS_ENTRY_V3_HEADER[0][1]

          if include_or_port:
            r_line = r_line.replace(" 9001 ", " %s " % value)

          if include_dir_port:
            r_line = r_line[:-1] + value

          attr = "or_port" if include_or_port else "dir_port"
          expected = int(value) if value.isdigit() else None

          content = get_router_status_entry_v3({'r': r_line}, content = True)
          self._expect_invalid_attr(content, attr, expected)
示例#46
0
  def test_proceeding_line(self):
    """
    Includes content prior to the 'r' line.
    """

    content = b'z some stuff\n' + get_router_status_entry_v3(content = True)
    self._expect_invalid_attr(content, "_unrecognized_lines", ['z some stuff'])
示例#47
0
  def test_proceeding_line(self):
    """
    Includes content prior to the 'r' line.
    """

    content = b'z some stuff\n' + get_router_status_entry_v3(content = True)
    self.assertRaises(ValueError, RouterStatusEntryV3, content, True)
    self.assertEqual(['z some stuff'], RouterStatusEntryV3(content, False).get_unrecognized_lines())
示例#48
0
  def test_blank_lines(self):
    """
    Includes blank lines, which should be ignored.
    """

    content = get_router_status_entry_v3(content = True) + b"\n\nv Tor 0.2.2.35\n\n"
    entry = RouterStatusEntryV3(content)
    self.assertEqual("Tor 0.2.2.35", entry.version_line)
示例#49
0
  def test_blank_lines(self):
    """
    Includes blank lines, which should be ignored.
    """

    content = get_router_status_entry_v3(content = True) + "\n\nv Tor 0.2.2.35\n\n"
    entry = RouterStatusEntryV3(content)
    self.assertEqual("Tor 0.2.2.35", entry.version_line)
示例#50
0
  def test_new_consensus_event(self):
    expected_desc = []

    expected_desc.append(mocking.get_router_status_entry_v3({
      "r": "Beaver /96bKo4soysolMgKn5Hex2nyFSY pAJH9dSBp/CG6sPhhVY/5bLaVPM 2012-12-02 22:02:45 77.223.43.54 9001 0",
      "s": "Fast Named Running Stable Valid",
    }))

    expected_desc.append(mocking.get_router_status_entry_v3({
      "r": "Unnamed /+fJRWjmIGNAL2C5rRZHq3R91tA 7AnpZjfdBpYzXnMNm+w1bTsFF6Y 2012-12-02 17:51:10 91.121.184.87 9001 0",
      "s": "Fast Guard Running Stable Valid",
    }))

    event = _get_event(NEWCONSENSUS_EVENT)

    self.assertTrue(isinstance(event, stem.response.events.NewConsensusEvent))
    self.assertEqual(expected_desc, event.desc)
示例#51
0
    def test_bandwidth(self):
        """
    Handles a variety of 'w' lines.
    """

        test_values = {
            'Bandwidth=0': (0, None, False, []),
            'Bandwidth=63138': (63138, None, False, []),
            'Bandwidth=11111 Measured=482': (11111, 482, False, []),
            'Bandwidth=11111 Measured=482 Blarg!':
            (11111, 482, False, ['Blarg!']),
            'Bandwidth=11111 Measured=482 Unmeasured=1 Blarg!':
            (11111, 482, True, ['Blarg!']),
        }

        for w_line, expected in test_values.items():
            entry = get_router_status_entry_v3({'w': w_line})
            self.assertEquals(expected[0], entry.bandwidth)
            self.assertEquals(expected[1], entry.measured)
            self.assertEquals(expected[2], entry.is_unmeasured)
            self.assertEquals(expected[3],
                              entry.unrecognized_bandwidth_entries)

        # tries some invalid inputs
        test_values = (
            '',
            'blarg',
            'Bandwidth',
            'Bandwidth=',
            'Bandwidth:0',
            'Bandwidth 0',
            'Bandwidth=-10',
            'Bandwidth=10 Measured',
            'Bandwidth=10 Measured=',
            'Bandwidth=10 Measured=-50',
            'Bandwidth=10 Measured=482 Unmeasured',
            'Bandwidth=10 Measured=482 Unmeasured=',
            'Bandwidth=10 Measured=482 Unmeasured=0',
            'Bandwidth=10 Measured=482 Unmeasured=842',
            'Bandwidth=10 Measured=482 Unmeasured=-5',
        )

        for w_line in test_values:
            content = get_router_status_entry_v3({'w': w_line}, content=True)
            self._expect_invalid_attr(content)
示例#52
0
 def test_ipv6_addresses(self):
   """
   Handles a variety of 'a' lines.
   """
   
   test_values = {
     "[2607:fcd0:daaa:101::602c:bd62]:443": {
       '2607:fcd0:daaa:101::602c:bd62': [(443, 443)]},
     "[2607:fcd0:daaa:101::602c:bd62]:80,443": {
       '2607:fcd0:daaa:101::602c:bd62': [(80, 80), (443, 443)]},
     "[2607:fcd0:daaa:101::602c:bd62]:443-512": {
       '2607:fcd0:daaa:101::602c:bd62': [(443, 512)]},
   }
   
   for a_line, expected in test_values.items():
     entry = get_router_status_entry_v3({'a': a_line})
     self.assertEquals(expected, entry.addresses_v6)
   
   # includes multiple 'a' lines
   
   content = get_router_status_entry_v3(content = True)
   content += "\na [2607:fcd0:daaa:101::602c:bd62]:80,443"
   content += "\na [2607:fcd0:daaa:101::602c:bd62]:512-600"
   content += "\na [1148:fcd0:daaa:101::602c:bd62]:80"
   
   expected = {
     '2607:fcd0:daaa:101::602c:bd62': [(80, 80), (443, 443), (512, 600)],
     '1148:fcd0:daaa:101::602c:bd62': [(80, 80)],
   }
   
   entry = RouterStatusEntryV3(content)
   self.assertEquals(expected, entry.addresses_v6)
   
   # tries some invalid inputs
   
   test_values = (
     "",
     "127.0.0.1:80",
     "[1148:fcd0:daaa:101::602c:bd62]:80000",
   )
   
   for a_line in test_values:
     content = get_router_status_entry_v3({'a': a_line}, content = True)
     self._expect_invalid_attr(content, expected_value = {})
示例#53
0
def _get_router_status(address = None, port = None, nickname = None, fingerprint_base64 = None, s_line = None):
  r_line = ROUTER_STATUS_ENTRY_V3_HEADER[0][1]

  if address:
    r_line = r_line.replace('71.35.150.29', address)

  if port:
    r_line = r_line.replace('9001', port)

  if nickname:
    r_line = r_line.replace('caerSidi', nickname)

  if fingerprint_base64:
    r_line = r_line.replace('p1aag7VwarGxqctS7/fS0y5FU+s', fingerprint_base64)

  if s_line:
    return get_router_status_entry_v3({'r': r_line, 's': s_line})
  else:
    return get_router_status_entry_v3({'r': r_line})
示例#54
0
  def test_ns_event(self):
    expected_desc = mocking.get_router_status_entry_v3({
      "r": "whnetz dbBxYcJriTTrcxsuy4PUZcMRwCA VStM7KAIH/mXXoGDUpoGB1OXufg 2012-12-02 21:03:56 141.70.120.13 9001 9030",
      "s": "Fast HSDir Named Stable V2Dir Valid",
    })

    event = _get_event(NS_EVENT)

    self.assertTrue(isinstance(event, stem.response.events.NetworkStatusEvent))
    self.assertEqual([expected_desc], event.desc)
示例#55
0
    def test_proceeding_line(self):
        """
    Includes content prior to the 'r' line.
    """

        content = b'z some stuff\n' + get_router_status_entry_v3(content=True)
        self.assertRaises(ValueError, RouterStatusEntryV3, content, True)
        self.assertEqual(['z some stuff'],
                         RouterStatusEntryV3(content,
                                             False).get_unrecognized_lines())
示例#56
0
def _get_router_status(address = None, port = None, nickname = None, fingerprint_base64 = None, s_line = None):
  r_line = ROUTER_STATUS_ENTRY_V3_HEADER[0][1]

  if address:
    r_line = r_line.replace('71.35.150.29', address)

  if port:
    r_line = r_line.replace('9001', port)

  if nickname:
    r_line = r_line.replace('caerSidi', nickname)

  if fingerprint_base64:
    r_line = r_line.replace('p1aag7VwarGxqctS7/fS0y5FU+s', fingerprint_base64)

  if s_line:
    return get_router_status_entry_v3({'r': r_line, 's': s_line})
  else:
    return get_router_status_entry_v3({'r': r_line})
示例#57
0
  def test_ns_event(self):
    expected_desc = mocking.get_router_status_entry_v3({
      "r": "whnetz dbBxYcJriTTrcxsuy4PUZcMRwCA VStM7KAIH/mXXoGDUpoGB1OXufg 2012-12-02 21:03:56 141.70.120.13 9001 9030",
      "s": "Fast HSDir Named Stable V2Dir Valid",
    })

    event = _get_event(NS_EVENT)

    self.assertTrue(isinstance(event, stem.response.events.NetworkStatusEvent))
    self.assertEqual([expected_desc], event.desc)
示例#58
0
  def test_bandwidth(self):
    """
    Handles a variety of 'w' lines.
    """

    test_values = {
      'Bandwidth=0': (0, None, False, []),
      'Bandwidth=63138': (63138, None, False, []),
      'Bandwidth=11111 Measured=482': (11111, 482, False, []),
      'Bandwidth=11111 Measured=482 Blarg!': (11111, 482, False, ['Blarg!']),
      'Bandwidth=11111 Measured=482 Unmeasured=1 Blarg!': (11111, 482, True, ['Blarg!']),
    }

    for w_line, expected in test_values.items():
      entry = get_router_status_entry_v3({'w': w_line})
      self.assertEqual(expected[0], entry.bandwidth)
      self.assertEqual(expected[1], entry.measured)
      self.assertEqual(expected[2], entry.is_unmeasured)
      self.assertEqual(expected[3], entry.unrecognized_bandwidth_entries)

    # tries some invalid inputs
    test_values = (
      '',
      'blarg',
      'Bandwidth',
      'Bandwidth=',
      'Bandwidth:0',
      'Bandwidth 0',
      'Bandwidth=-10',
      'Bandwidth=10 Measured',
      'Bandwidth=10 Measured=',
      'Bandwidth=10 Measured=-50',
      'Bandwidth=10 Measured=482 Unmeasured',
      'Bandwidth=10 Measured=482 Unmeasured=',
      'Bandwidth=10 Measured=482 Unmeasured=0',
      'Bandwidth=10 Measured=482 Unmeasured=842',
      'Bandwidth=10 Measured=482 Unmeasured=-5',
    )

    for w_line in test_values:
      content = get_router_status_entry_v3({'w': w_line}, content = True)
      self._expect_invalid_attr(content)
示例#59
0
  def test_versions(self):
    """
    Handles a variety of version inputs.
    """

    test_values = {
      "Tor 0.2.2.35": Version("0.2.2.35"),
      "Tor 0.1.2": Version("0.1.2"),
      "Torr new_stuff": None,
      "new_stuff and stuff": None,
    }

    for v_line, expected in test_values.items():
      entry = get_router_status_entry_v3({'v': v_line})
      self.assertEquals(expected, entry.version)
      self.assertEquals(v_line, entry.version_line)

    # tries an invalid input
    content = get_router_status_entry_v3({'v': "Tor ugabuga"}, content = True)
    self._expect_invalid_attr(content, "version")
示例#60
0
  def test_parse_file(self):
    """
    Try parsing a document via the _parse_file() function.
    """

    entry1 = get_router_status_entry_v3({'s': "Fast"})
    entry2 = get_router_status_entry_v3({'s': "Valid"})
    content = get_network_status_document_v3(routers = (entry1, entry2), content = True)

    # the document that the entries refer to should actually be the minimal
    # descriptor (ie, without the entries)

    expected_document = get_network_status_document_v3()

    descriptor_file = io.BytesIO(content)
    entries = list(_parse_file(descriptor_file))

    self.assertEquals(entry1, entries[0])
    self.assertEquals(entry2, entries[1])
    self.assertEquals(expected_document, entries[0].document)