示例#1
0
    def test_geoip_db_digest(self):
        """
    Parses the geoip-db-digest and geoip6-db-digest lines with valid and
    invalid data.
    """

        geoip_db_digest = '916A3CA8B7DF61473D5AE5B21711F35F301CE9E8'
        desc = RelayExtraInfoDescriptor.create(
            {'geoip-db-digest': geoip_db_digest})
        self.assertEqual(geoip_db_digest, desc.geoip_db_digest)

        desc = RelayExtraInfoDescriptor.create(
            {'geoip6-db-digest': geoip_db_digest})
        self.assertEqual(geoip_db_digest, desc.geoip6_db_digest)

        test_entries = (
            '',
            '916A3CA8B7DF61473D5AE5B21711F35F301CE9E',
            '916A3CA8B7DF61473D5AE5B21711F35F301CE9E88',
            '916A3CA8B7DF61473D5AE5B21711F35F301CE9EG',
            '916A3CA8B7DF61473D5AE5B21711F35F301CE9E-',
        )

        for entry in test_entries:
            expect_invalid_attr(self, {'geoip-db-digest': entry},
                                'geoip_db_digest')
            expect_invalid_attr(self, {'geoip6-db-digest': entry},
                                'geoip6_db_digest')
示例#2
0
 def test_descriptor_signing(self):
     RelayExtraInfoDescriptor.create(sign=True)
     self.assertRaisesWith(
         NotImplementedError,
         'Signing of BridgeExtraInfoDescriptor not implemented',
         BridgeExtraInfoDescriptor.create,
         sign=True)
示例#3
0
    def test_hidden_service_stats(self):
        """
    Check the 'hidserv-rend-relayed-cells' and 'hidserv-dir-onions-seen', which
    share the same format.
    """

        attributes = (
            ('hidserv-rend-relayed-cells', 'hs_rend_cells',
             'hs_rend_cells_attr'),
            ('hidserv-dir-onions-seen', 'hs_dir_onions_seen',
             'hs_dir_onions_seen_attr'),
        )

        test_entries = (
            '',
            'hello',
            ' key=value',
            '40 key',
            '40 key value',
            '40 key key=value',
        )

        for keyword, stat_attr, extra_attr in attributes:
            # just the numeric stat (no extra attributes)

            desc = RelayExtraInfoDescriptor.create({keyword: '345'})
            self.assertEqual(345, getattr(desc, stat_attr))
            self.assertEqual({}, getattr(desc, extra_attr))

            # values can be negative (#15276)

            desc = RelayExtraInfoDescriptor.create({keyword: '-345'})
            self.assertEqual(-345, getattr(desc, stat_attr))
            self.assertEqual({}, getattr(desc, extra_attr))

            # with extra attributes

            desc = RelayExtraInfoDescriptor.create(
                {keyword: '345 spiffy=true snowmen=neat'})
            self.assertEqual(345, getattr(desc, stat_attr))
            self.assertEqual({
                'spiffy': 'true',
                'snowmen': 'neat'
            }, getattr(desc, extra_attr))

            for entry in test_entries:
                expect_invalid_attr(self, {keyword: entry}, stat_attr)
                expect_invalid_attr(self, {keyword: entry}, extra_attr, {})
示例#4
0
  def test_unrecognized_line(self):
    """
    Includes unrecognized content in the descriptor.
    """

    desc = RelayExtraInfoDescriptor.create({'pepperjack': 'is oh so tasty!'})
    self.assertEqual(['pepperjack is oh so tasty!'], desc.get_unrecognized_lines())
示例#5
0
    def test_cell_circuits_per_decile(self):
        """
    Parses the cell-circuits-per-decile line with valid and invalid data.
    """

        test_entries = (
            ('0', 0),
            ('11', 11),
        )

        for entry in ('0', '11', '25'):
            desc = RelayExtraInfoDescriptor.create(
                {'cell-circuits-per-decile': entry})
            self.assertEqual(int(entry), desc.cell_circuits_per_decile)

        test_entries = (
            '',
            ' ',
            '-5',
            'blarg',
        )

        for entry in test_entries:
            expect_invalid_attr(self, {'cell-circuits-per-decile': entry},
                                'cell_circuits_per_decile')
示例#6
0
  def test_timestamp_and_interval_lines(self):
    """
    Uses valid and invalid data to tests lines of the form...
    "<keyword>" YYYY-MM-DD HH:MM:SS (NSEC s)
    """

    for keyword in ('cell-stats-end', 'entry-stats-end', 'exit-stats-end', 'bridge-stats-end', 'dirreq-stats-end'):
      end_attr = keyword.replace('-', '_').replace('dirreq', 'dir')
      interval_attr = end_attr[:-4] + '_interval'

      desc = RelayExtraInfoDescriptor.create({keyword: '2012-05-03 12:07:50 (500 s)'})
      self.assertEqual(datetime.datetime(2012, 5, 3, 12, 7, 50), getattr(desc, end_attr))
      self.assertEqual(500, getattr(desc, interval_attr))

    test_entries = (
      '',
      '2012-05-03 ',
      '2012-05-03',
      '2012-05-03 12:07:60 (500 s)',
      '2012-05-03 12:07:50 (500s)',
      '2012-05-03 12:07:50 (500 s',
      '2012-05-03 12:07:50 (500 )',
    )

    for entry in test_entries:
      desc = expect_invalid_attr(self, {'entry-stats-end': entry})
      self.assertEqual(None, desc.entry_stats_end)
      self.assertEqual(None, desc.entry_stats_interval)
示例#7
0
  def test_number_list_lines(self):
    """
    Uses valid and invalid data to tests lines of the form...
    "<keyword>" num,...,num
    """

    for keyword in ('cell-processed-cells', 'cell-queued-cells', 'cell-time-in-queue'):
      attr = keyword.replace('-', '_')

      test_entries = (
        ('', []),
        (' ', []),
        ('0,0,0', [0.0, 0.0, 0.0]),
        ('2.3,-4.6,8.9,16.12,32.15', [2.3, -4.6, 8.9, 16.12, 32.15]),
      )

      for test_value, expected_value in test_entries:
        desc = RelayExtraInfoDescriptor.create({keyword: test_value})
        self.assertEqual(expected_value, getattr(desc, attr))

      test_entries = (
        (',,11', [11.0]),
        ('abc,5.7,def', [5.7]),
        ('blarg', []),
      )

      for entry, expected in test_entries:
        expect_invalid_attr(self, {keyword: entry}, attr, expected)
示例#8
0
  def test_number_list_lines(self):
    """
    Uses valid and invalid data to tests lines of the form...
    "<keyword>" num,...,num
    """

    for keyword in ('cell-processed-cells', 'cell-queued-cells', 'cell-time-in-queue'):
      attr = keyword.replace('-', '_')

      test_entries = (
        ('', []),
        (' ', []),
        ('0,0,0', [0.0, 0.0, 0.0]),
        ('2.3,-4.6,8.9,16.12,32.15', [2.3, -4.6, 8.9, 16.12, 32.15]),
      )

      for test_value, expected_value in test_entries:
        desc = RelayExtraInfoDescriptor.create({keyword: test_value})
        self.assertEqual(expected_value, getattr(desc, attr))

      test_entries = (
        (',,11', [11.0]),
        ('abc,5.7,def', [5.7]),
        ('blarg', []),
      )

      for entry, expected in test_entries:
        expect_invalid_attr(self, {keyword: entry}, attr, expected)
示例#9
0
  def test_conn_bi_direct(self):
    """
    Parses the conn-bi-direct line with valid and invalid data.
    """

    desc = RelayExtraInfoDescriptor.create({'conn-bi-direct': '2012-05-03 12:07:50 (500 s) 277431,12089,0,2134'})
    self.assertEqual(datetime.datetime(2012, 5, 3, 12, 7, 50), desc.conn_bi_direct_end)
    self.assertEqual(500, desc.conn_bi_direct_interval)
    self.assertEqual(277431, desc.conn_bi_direct_below)
    self.assertEqual(12089, desc.conn_bi_direct_read)
    self.assertEqual(0, desc.conn_bi_direct_write)
    self.assertEqual(2134, desc.conn_bi_direct_both)

    test_entries = (
      '',
      '2012-05-03',
      '2012-05-03 12:07:60 (500 s)',
      '2012-05-03 12:07:50 (500 s',
      '2012-05-03 12:07:50 (500s)',
      '2012-05-03 12:07:50 (500 s)11',
      '2012-05-03 12:07:50 (500 s) 277431,12089,0',
      '2012-05-03 12:07:50 (500 s) 277431,12089,0a,2134',
      '2012-05-03 12:07:50 (500 s) -277431,12089,0,2134',
    )

    for entry in test_entries:
      desc = expect_invalid_attr(self, {'conn-bi-direct': entry})
      self.assertEqual(None, desc.conn_bi_direct_end)
      self.assertEqual(None, desc.conn_bi_direct_interval)
      self.assertEqual(None, desc.conn_bi_direct_below)
      self.assertEqual(None, desc.conn_bi_direct_read)
      self.assertEqual(None, desc.conn_bi_direct_write)
      self.assertEqual(None, desc.conn_bi_direct_both)
示例#10
0
  def test_timestamp_and_interval_lines(self):
    """
    Uses valid and invalid data to tests lines of the form...
    "<keyword>" YYYY-MM-DD HH:MM:SS (NSEC s)
    """

    for keyword in ('cell-stats-end', 'entry-stats-end', 'exit-stats-end', 'bridge-stats-end', 'dirreq-stats-end'):
      end_attr = keyword.replace('-', '_').replace('dirreq', 'dir')
      interval_attr = end_attr[:-4] + '_interval'

      desc = RelayExtraInfoDescriptor.create({keyword: '2012-05-03 12:07:50 (500 s)'})
      self.assertEqual(datetime.datetime(2012, 5, 3, 12, 7, 50), getattr(desc, end_attr))
      self.assertEqual(500, getattr(desc, interval_attr))

    test_entries = (
      '',
      '2012-05-03 ',
      '2012-05-03',
      '2012-05-03 12:07:60 (500 s)',
      '2012-05-03 12:07:50 (500s)',
      '2012-05-03 12:07:50 (500 s',
      '2012-05-03 12:07:50 (500 )',
    )

    for entry in test_entries:
      desc = expect_invalid_attr(self, {'entry-stats-end': entry})
      self.assertEqual(None, desc.entry_stats_end)
      self.assertEqual(None, desc.entry_stats_interval)
示例#11
0
  def test_dir_response_lines(self):
    """
    Parses the dirreq-v2-resp and dirreq-v3-resp lines with valid and invalid
    data.
    """

    for keyword in ('dirreq-v2-resp', 'dirreq-v3-resp'):
      attr = keyword.replace('-', '_').replace('dirreq', 'dir').replace('resp', 'responses')
      unknown_attr = attr + '_unknown'

      test_value = 'ok=0,unavailable=0,not-found=984,not-modified=0,something-new=7'
      desc = RelayExtraInfoDescriptor.create({keyword: test_value})
      self.assertEqual(0, getattr(desc, attr)[DirResponse.OK])
      self.assertEqual(0, getattr(desc, attr)[DirResponse.UNAVAILABLE])
      self.assertEqual(984, getattr(desc, attr)[DirResponse.NOT_FOUND])
      self.assertEqual(0, getattr(desc, attr)[DirResponse.NOT_MODIFIED])
      self.assertEqual(7, getattr(desc, unknown_attr)['something-new'])

      test_entries = (
        'ok=-4',
        'ok:4',
        'ok=4.not-found=3',
      )

      for entry in test_entries:
        desc = expect_invalid_attr(self, {keyword: entry})
        self.assertEqual(None, getattr(desc, attr))
        self.assertEqual(None, getattr(desc, unknown_attr))
示例#12
0
  def test_port_mapping_lines(self):
    """
    Uses valid and invalid data to tests lines of the form...
    "<keyword>" port=N,port=N,...
    """

    for keyword in ('exit-kibibytes-written', 'exit-kibibytes-read', 'exit-streams-opened'):
      attr = keyword.replace('-', '_')

      test_entries = (
        ('', {}),
        ('443=100,other=111', {443: 100, 'other': 111}),
        ('80=115533759,443=1777,995=690', {80: 115533759, 443: 1777, 995: 690}),
      )

      for test_value, expected_value in test_entries:
        desc = RelayExtraInfoDescriptor.create({keyword: test_value})
        self.assertEqual(expected_value, getattr(desc, attr))

      test_entries = (
        '8000000=115533759',
        '-80=115533759',
        '80=-115533759',
        '=115533759',
        '80=',
        '80,115533759',
      )

      for entry in test_entries:
        expect_invalid_attr(self, {keyword: entry}, attr)
示例#13
0
  def test_dir_response_lines(self):
    """
    Parses the dirreq-v2-resp and dirreq-v3-resp lines with valid and invalid
    data.
    """

    for keyword in ('dirreq-v2-resp', 'dirreq-v3-resp'):
      attr = keyword.replace('-', '_').replace('dirreq', 'dir').replace('resp', 'responses')
      unknown_attr = attr + '_unknown'

      test_value = 'ok=0,unavailable=0,not-found=984,not-modified=0,something-new=7'
      desc = RelayExtraInfoDescriptor.create({keyword: test_value})
      self.assertEqual(0, getattr(desc, attr)[DirResponse.OK])
      self.assertEqual(0, getattr(desc, attr)[DirResponse.UNAVAILABLE])
      self.assertEqual(984, getattr(desc, attr)[DirResponse.NOT_FOUND])
      self.assertEqual(0, getattr(desc, attr)[DirResponse.NOT_MODIFIED])
      self.assertEqual(7, getattr(desc, unknown_attr)['something-new'])

      test_entries = (
        'ok=-4',
        'ok:4',
        'ok=4.not-found=3',
      )

      for entry in test_entries:
        desc = expect_invalid_attr(self, {keyword: entry})
        self.assertEqual(None, getattr(desc, attr))
        self.assertEqual(None, getattr(desc, unknown_attr))
示例#14
0
  def test_locale_mapping_lines(self):
    """
    Uses valid and invalid data to tests lines of the form...
    "<keyword>" CC=N,CC=N,...
    """

    for keyword in ('dirreq-v2-ips', 'dirreq-v3-ips', 'dirreq-v2-reqs', 'dirreq-v3-reqs', 'geoip-client-origins', 'entry-ips', 'bridge-ips'):
      attr = keyword.replace('-', '_').replace('dirreq', 'dir').replace('reqs', 'requests')

      test_entries = (
        ('', {}),
        ('uk=5,de=3,jp=2', {'uk': 5, 'de': 3, 'jp': 2}),
      )

      for test_value, expected_value in test_entries:
        desc = RelayExtraInfoDescriptor.create({keyword: test_value})
        self.assertEqual(expected_value, getattr(desc, attr))

      test_entries = (
        'uk=-4',
        'uki=4',
        'uk:4',
        'uk=4.de=3',
      )

      for entry in test_entries:
        expect_invalid_attr(self, {keyword: entry}, attr)
示例#15
0
  def test_unrecognized_line(self):
    """
    Includes unrecognized content in the descriptor.
    """

    desc = RelayExtraInfoDescriptor.create({'pepperjack': 'is oh so tasty!'})
    self.assertEqual(['pepperjack is oh so tasty!'], desc.get_unrecognized_lines())
示例#16
0
  def test_percentage_lines(self):
    """
    Uses valid and invalid data to tests lines of the form...
    "<keyword>" num%
    """

    for keyword in ('dirreq-v2-share', 'dirreq-v3-share'):
      attr = keyword.replace('-', '_').replace('dirreq', 'dir')

      test_entries = (
        ('0.00%', 0.0),
        ('0.01%', 0.0001),
        ('50%', 0.5),
        ('100.0%', 1.0),
      )

      for test_value, expected_value in test_entries:
        desc = RelayExtraInfoDescriptor.create({keyword: test_value})
        self.assertEqual(expected_value, getattr(desc, attr))

      test_entries = (
        (''),
        (' '),
        ('100'),
        ('-5%'),
      )

      for entry in test_entries:
        expect_invalid_attr(self, {keyword: entry}, attr)
示例#17
0
  def test_conn_bi_direct(self):
    """
    Parses the conn-bi-direct line with valid and invalid data.
    """

    desc = RelayExtraInfoDescriptor.create({'conn-bi-direct': '2012-05-03 12:07:50 (500 s) 277431,12089,0,2134'})
    self.assertEqual(datetime.datetime(2012, 5, 3, 12, 7, 50), desc.conn_bi_direct_end)
    self.assertEqual(500, desc.conn_bi_direct_interval)
    self.assertEqual(277431, desc.conn_bi_direct_below)
    self.assertEqual(12089, desc.conn_bi_direct_read)
    self.assertEqual(0, desc.conn_bi_direct_write)
    self.assertEqual(2134, desc.conn_bi_direct_both)

    test_entries = (
      '',
      '2012-05-03',
      '2012-05-03 12:07:60 (500 s)',
      '2012-05-03 12:07:50 (500 s',
      '2012-05-03 12:07:50 (500s)',
      '2012-05-03 12:07:50 (500 s)11',
      '2012-05-03 12:07:50 (500 s) 277431,12089,0',
      '2012-05-03 12:07:50 (500 s) 277431,12089,0a,2134',
      '2012-05-03 12:07:50 (500 s) -277431,12089,0,2134',
    )

    for entry in test_entries:
      desc = expect_invalid_attr(self, {'conn-bi-direct': entry})
      self.assertEqual(None, desc.conn_bi_direct_end)
      self.assertEqual(None, desc.conn_bi_direct_interval)
      self.assertEqual(None, desc.conn_bi_direct_below)
      self.assertEqual(None, desc.conn_bi_direct_read)
      self.assertEqual(None, desc.conn_bi_direct_write)
      self.assertEqual(None, desc.conn_bi_direct_both)
示例#18
0
  def test_percentage_lines(self):
    """
    Uses valid and invalid data to tests lines of the form...
    "<keyword>" num%
    """

    for keyword in ('dirreq-v2-share', 'dirreq-v3-share'):
      attr = keyword.replace('-', '_').replace('dirreq', 'dir')

      test_entries = (
        ('0.00%', 0.0),
        ('0.01%', 0.0001),
        ('50%', 0.5),
        ('100.0%', 1.0),
      )

      for test_value, expected_value in test_entries:
        desc = RelayExtraInfoDescriptor.create({keyword: test_value})
        self.assertEqual(expected_value, getattr(desc, attr))

      test_entries = (
        (''),
        (' '),
        ('100'),
        ('-5%'),
      )

      for entry in test_entries:
        expect_invalid_attr(self, {keyword: entry}, attr)
示例#19
0
  def test_locale_mapping_lines(self):
    """
    Uses valid and invalid data to tests lines of the form...
    "<keyword>" CC=N,CC=N,...
    """

    for keyword in ('dirreq-v2-ips', 'dirreq-v3-ips', 'dirreq-v2-reqs', 'dirreq-v3-reqs', 'geoip-client-origins', 'entry-ips', 'bridge-ips'):
      attr = keyword.replace('-', '_').replace('dirreq', 'dir').replace('reqs', 'requests')

      test_entries = (
        ('', {}),
        ('uk=5,de=3,jp=2', {'uk': 5, 'de': 3, 'jp': 2}),
      )

      for test_value, expected_value in test_entries:
        desc = RelayExtraInfoDescriptor.create({keyword: test_value})
        self.assertEqual(expected_value, getattr(desc, attr))

      test_entries = (
        'uk=-4',
        'uki=4',
        'uk:4',
        'uk=4.de=3',
      )

      for entry in test_entries:
        expect_invalid_attr(self, {keyword: entry}, attr)
示例#20
0
  def test_port_mapping_lines(self):
    """
    Uses valid and invalid data to tests lines of the form...
    "<keyword>" port=N,port=N,...
    """

    for keyword in ('exit-kibibytes-written', 'exit-kibibytes-read', 'exit-streams-opened'):
      attr = keyword.replace('-', '_')

      test_entries = (
        ('', {}),
        ('443=100,other=111', {443: 100, 'other': 111}),
        ('80=115533759,443=1777,995=690', {80: 115533759, 443: 1777, 995: 690}),
      )

      for test_value, expected_value in test_entries:
        desc = RelayExtraInfoDescriptor.create({keyword: test_value})
        self.assertEqual(expected_value, getattr(desc, attr))

      test_entries = (
        '8000000=115533759',
        '-80=115533759',
        '80=-115533759',
        '=115533759',
        '80=',
        '80,115533759',
      )

      for entry in test_entries:
        expect_invalid_attr(self, {keyword: entry}, attr)
示例#21
0
  def test_minimal_extrainfo_descriptor(self):
    """
    Basic sanity check that we can parse an extrainfo descriptor with minimal
    attributes.
    """

    desc = RelayExtraInfoDescriptor.create()
    self.assertTrue(desc.nickname.startswith('Unnamed'))
示例#22
0
  def test_minimal_extrainfo_descriptor(self):
    """
    Basic sanity check that we can parse an extrainfo descriptor with minimal
    attributes.
    """

    desc = RelayExtraInfoDescriptor.create()
    self.assertTrue(desc.nickname.startswith('Unnamed'))
示例#23
0
    def test_proceeding_line(self):
        """
    Includes a line prior to the 'extra-info' entry.
    """

        expect_invalid_attr_for_text(
            self, b'exit-streams-opened port=80\n' +
            RelayExtraInfoDescriptor.content())
示例#24
0
    def test_trailing_line(self):
        """
    Includes a line after the 'router-signature' entry.
    """

        expect_invalid_attr_for_text(
            self,
            RelayExtraInfoDescriptor.content() +
            b'\nexit-streams-opened port=80')
示例#25
0
    def test_timestamp_interval_and_value_lines(self):
        """
    Uses valid and invalid data to tests lines of the form...
    "<keyword>" YYYY-MM-DD HH:MM:SS (NSEC s) NUM,NUM,NUM,NUM,NUM...
    """

        for keyword in ('read-history', 'write-history', 'dirreq-read-history',
                        'dirreq-write-history'):
            base_attr = keyword.replace('-', '_').replace('dirreq', 'dir')
            end_attr = base_attr + '_end'
            interval_attr = base_attr + '_interval'
            values_attr = base_attr + '_values'

            desc = RelayExtraInfoDescriptor.create(
                {keyword: '2012-05-03 12:07:50 (500 s) 50,11,5'})
            self.assertEqual(datetime.datetime(2012, 5, 3, 12, 7, 50),
                             getattr(desc, end_attr))
            self.assertEqual(500, getattr(desc, interval_attr))
            self.assertEqual([50, 11, 5], getattr(desc, values_attr))

        for test_value in ('', ' '):
            desc = RelayExtraInfoDescriptor.create({
                'write-history':
                '2012-05-03 12:07:50 (500 s)%s' % test_value
            })
            self.assertEqual(datetime.datetime(2012, 5, 3, 12, 7, 50),
                             desc.write_history_end)
            self.assertEqual(500, desc.write_history_interval)
            self.assertEqual([], desc.write_history_values)

        test_entries = (
            '',
            '2012-05-03',
            '2012-05-03 12:07:60 (500 s)',
            '2012-05-03 12:07:50 (500s)',
            '2012-05-03 12:07:50 (500 s',
            '2012-05-03 12:07:50 (500 s)11',
        )

        for entry in test_entries:
            desc = expect_invalid_attr(self, {'write-history': entry})
            self.assertEqual(None, desc.write_history_end)
            self.assertEqual(None, desc.write_history_interval)
            self.assertEqual(None, desc.write_history_values)
示例#26
0
  def test_hidden_service_stats(self):
    """
    Check the 'hidserv-rend-relayed-cells' and 'hidserv-dir-onions-seen', which
    share the same format.
    """

    attributes = (
      ('hidserv-rend-relayed-cells', 'hs_rend_cells', 'hs_rend_cells_attr'),
      ('hidserv-dir-onions-seen', 'hs_dir_onions_seen', 'hs_dir_onions_seen_attr'),
    )

    test_entries = (
      '',
      'hello',
      ' key=value',
      '40 key',
      '40 key value',
      '40 key key=value',
    )

    for keyword, stat_attr, extra_attr in attributes:
      # just the numeric stat (no extra attributes)

      desc = RelayExtraInfoDescriptor.create({keyword: '345'})
      self.assertEqual(345, getattr(desc, stat_attr))
      self.assertEqual({}, getattr(desc, extra_attr))

      # values can be negative (#15276)

      desc = RelayExtraInfoDescriptor.create({keyword: '-345'})
      self.assertEqual(-345, getattr(desc, stat_attr))
      self.assertEqual({}, getattr(desc, extra_attr))

      # with extra attributes

      desc = RelayExtraInfoDescriptor.create({keyword: '345 spiffy=true snowmen=neat'})
      self.assertEqual(345, getattr(desc, stat_attr))
      self.assertEqual({'spiffy': 'true', 'snowmen': 'neat'}, getattr(desc, extra_attr))

      for entry in test_entries:
        expect_invalid_attr(self, {keyword: entry}, stat_attr)
        expect_invalid_attr(self, {keyword: entry}, extra_attr, {})
示例#27
0
  def test_timestamp_interval_and_value_lines(self):
    """
    Uses valid and invalid data to tests lines of the form...
    "<keyword>" YYYY-MM-DD HH:MM:SS (NSEC s) NUM,NUM,NUM,NUM,NUM...
    """

    for keyword in ('read-history', 'write-history', 'dirreq-read-history', 'dirreq-write-history'):
      base_attr = keyword.replace('-', '_').replace('dirreq', 'dir')
      end_attr = base_attr + '_end'
      interval_attr = base_attr + '_interval'
      values_attr = base_attr + '_values'

      desc = RelayExtraInfoDescriptor.create({keyword: '2012-05-03 12:07:50 (500 s) 50,11,5'})
      self.assertEqual(datetime.datetime(2012, 5, 3, 12, 7, 50), getattr(desc, end_attr))
      self.assertEqual(500, getattr(desc, interval_attr))
      self.assertEqual([50, 11, 5], getattr(desc, values_attr))

    for test_value in ('', ' '):
      desc = RelayExtraInfoDescriptor.create({'write-history': '2012-05-03 12:07:50 (500 s)%s' % test_value})
      self.assertEqual(datetime.datetime(2012, 5, 3, 12, 7, 50), desc.write_history_end)
      self.assertEqual(500, desc.write_history_interval)
      self.assertEqual([], desc.write_history_values)

    test_entries = (
      '',
      '2012-05-03',
      '2012-05-03 12:07:60 (500 s)',
      '2012-05-03 12:07:50 (500s)',
      '2012-05-03 12:07:50 (500 s',
      '2012-05-03 12:07:50 (500 s)11',
    )

    for entry in test_entries:
      desc = expect_invalid_attr(self, {'write-history': entry})
      self.assertEqual(None, desc.write_history_end)
      self.assertEqual(None, desc.write_history_interval)
      self.assertEqual(None, desc.write_history_values)
示例#28
0
    def test_padding_counts(self):
        """
    Check the 'hidserv-dir-onions-seen' lines.
    """

        desc = RelayExtraInfoDescriptor.create({
            'padding-counts':
            '2017-05-17 11:02:58 (86400 s) bin-size=10000 write-drop=0 write-pad=10000 write-total=10000 read-drop=0 read-pad=10000 read-total=3780000 enabled-read-pad=0 enabled-read-total=0 enabled-write-pad=0 enabled-write-total=0 max-chanpad-timers=0 non-numeric=test'
        })

        self.assertEqual(
            {
                'bin-size': 10000,
                'write-drop': 0,
                'write-pad': 10000,
                'write-total': 10000,
                'read-drop': 0,
                'read-pad': 10000,
                'read-total': 3780000,
                'enabled-read-pad': 0,
                'enabled-read-total': 0,
                'enabled-write-pad': 0,
                'enabled-write-total': 0,
                'max-chanpad-timers': 0,
                'non-numeric':
                'test',  # presently all values are ints but the spec allows for anything
            },
            desc.padding_counts)

        self.assertEqual(datetime.datetime(2017, 5, 17, 11, 2, 58),
                         desc.padding_counts_end)
        self.assertEqual(86400, desc.padding_counts_interval)

        test_entries = (
            '',
            '2012-05-03',
            '2012-05-03 12:07:60 (500 s)',
            '2012-05-03 12:07:50 (500 s',
            '2012-05-03 12:07:50 (500s)',
            '2012-05-03 12:07:50 (500 s)bin-size=10',
            '2012-05-03 12:07:50 (500 s) bin-size',
            '2012-05-03 12:07:50 (500 s) bin-size=',
        )

        for entry in test_entries:
            desc = expect_invalid_attr(self, {'padding-counts': entry})
            self.assertEqual({}, desc.padding_counts)
            self.assertEqual(None, desc.padding_counts_end)
            self.assertEqual(None, desc.padding_counts_interval)
示例#29
0
  def test_geoip_db_digest(self):
    """
    Parses the geoip-db-digest and geoip6-db-digest lines with valid and
    invalid data.
    """

    geoip_db_digest = '916A3CA8B7DF61473D5AE5B21711F35F301CE9E8'
    desc = RelayExtraInfoDescriptor.create({'geoip-db-digest': geoip_db_digest})
    self.assertEqual(geoip_db_digest, desc.geoip_db_digest)

    desc = RelayExtraInfoDescriptor.create({'geoip6-db-digest': geoip_db_digest})
    self.assertEqual(geoip_db_digest, desc.geoip6_db_digest)

    test_entries = (
      '',
      '916A3CA8B7DF61473D5AE5B21711F35F301CE9E',
      '916A3CA8B7DF61473D5AE5B21711F35F301CE9E88',
      '916A3CA8B7DF61473D5AE5B21711F35F301CE9EG',
      '916A3CA8B7DF61473D5AE5B21711F35F301CE9E-',
    )

    for entry in test_entries:
      expect_invalid_attr(self, {'geoip-db-digest': entry}, 'geoip_db_digest')
      expect_invalid_attr(self, {'geoip6-db-digest': entry}, 'geoip6_db_digest')
示例#30
0
  def test_transport(self):
    """
    These lines are only applicable in raw bridge descriptors, which are
    unavailable to the public. That said, misconfigured relays can occasionally
    emit these.
    """

    desc = RelayExtraInfoDescriptor.create({'transport': 'obfs4 [2001:985:e77:5:fd34:f56b:c2d1:e98c]:10394 cert=dJ/a+vnP/WA,iat-mode=0'})

    self.assertEqual({'obfs4': (
      '[2001:985:e77:5:fd34:f56b:c2d1:e98c]',
      10394,
      ['cert=dJ/a+vnP/WA,iat-mode=0'],
    )}, desc.transport)

    expect_invalid_attr(self, {'transport': 'obfs4 invalid_address:123'}, 'transport', {})
示例#31
0
  def test_transport_line(self):
    """
    Basic exercise for both a bridge and relay's transport entry.
    """

    desc = BridgeExtraInfoDescriptor.create({'transport': 'obfs3'})
    self.assertEqual({'obfs3': (None, None, None)}, desc.transport)
    self.assertEqual([], desc.get_unrecognized_lines())

    desc = RelayExtraInfoDescriptor.create({'transport': 'obfs2 83.212.96.201:33570'})
    self.assertEqual({'obfs2': ('83.212.96.201', 33570, [])}, desc.transport)
    self.assertEqual([], desc.get_unrecognized_lines())

    # multiple transport lines
    desc = BridgeExtraInfoDescriptor.create({'transport': 'obfs3\ntransport obfs4'})
    self.assertEqual({'obfs3': (None, None, None), 'obfs4': (None, None, None)}, desc.transport)
    self.assertEqual([], desc.get_unrecognized_lines())
示例#32
0
    def test_check_digests(self):
        import check_digests as module
        fingerprint = 'A7569A83B5706AB1B1A9CB52EFF7D2D32E4553EB'

        extrainfo_desc = RelayExtraInfoDescriptor.create()
        server_desc = RelayDescriptor.create(
            {'extra-info-digest': extrainfo_desc.digest()}, sign=True)

        encoded_digest = base64.b64encode(
            binascii.unhexlify(server_desc.digest())).rstrip(b'=')

        consensus_desc = RouterStatusEntryV3.create({
            'r':
            'caerSidi p1aag7VwarGxqctS7/fS0y5FU+s %s 2012-08-06 11:19:31 71.35.150.29 9001 0'
            % encoded_digest.decode('utf-8'),
        })

        bad_consensus_desc = RouterStatusEntryV3.create({
            'r':
            'caerSidi p1aag7VwarGxqctS7/fS0y5FU+s oQZFLYe9e4A7bOkWKR7TaNxb0JE 2012-08-06 11:19:31 71.35.150.29 9001 0',
        })

        with patch('stem.descriptor.remote.get_server_descriptors',
                   _download_of(server_desc)):
            with patch('stem.descriptor.remote.get_extrainfo_descriptors',
                       _download_of(extrainfo_desc)):
                # correctly signed descriptors

                with patch('stem.descriptor.remote.get_consensus',
                           _download_of(consensus_desc)):
                    with patch('sys.stdout',
                               new_callable=io.StringIO) as stdout_mock:
                        module.validate_relay(fingerprint)
                        self.assertEqual(EXPECTED_CHECK_DIGESTS_OK,
                                         stdout_mock.getvalue())

                # incorrect server descriptor digest

                with patch('stem.descriptor.remote.get_consensus',
                           _download_of(bad_consensus_desc)):
                    with patch('sys.stdout',
                               new_callable=io.StringIO) as stdout_mock:
                        module.validate_relay(fingerprint)
                        self.assertEqual(
                            EXPECTED_CHECK_DIGESTS_BAD % server_desc.digest(),
                            stdout_mock.getvalue())
示例#33
0
  def test_transport_line(self):
    """
    Basic exercise for both a bridge and relay's transport entry.
    """

    desc = BridgeExtraInfoDescriptor.create({'transport': 'obfs3'})
    self.assertEqual({'obfs3': (None, None, None)}, desc.transport)
    self.assertEqual([], desc.get_unrecognized_lines())

    desc = RelayExtraInfoDescriptor.create({'transport': 'obfs2 83.212.96.201:33570'})
    self.assertEqual({'obfs2': ('83.212.96.201', 33570, [])}, desc.transport)
    self.assertEqual([], desc.get_unrecognized_lines())

    # multiple transport lines
    desc = BridgeExtraInfoDescriptor.create({'transport': 'obfs3\ntransport obfs4'})
    self.assertEqual({'obfs3': (None, None, None), 'obfs4': (None, None, None)}, desc.transport)
    self.assertEqual([], desc.get_unrecognized_lines())
示例#34
0
  def test_padding_counts(self):
    """
    Check the 'hidserv-dir-onions-seen' lines.
    """

    desc = RelayExtraInfoDescriptor.create({'padding-counts': '2017-05-17 11:02:58 (86400 s) bin-size=10000 write-drop=0 write-pad=10000 write-total=10000 read-drop=0 read-pad=10000 read-total=3780000 enabled-read-pad=0 enabled-read-total=0 enabled-write-pad=0 enabled-write-total=0 max-chanpad-timers=0 non-numeric=test'})

    self.assertEqual({
      'bin-size': 10000,
      'write-drop': 0,
      'write-pad': 10000,
      'write-total': 10000,
      'read-drop': 0,
      'read-pad': 10000,
      'read-total': 3780000,
      'enabled-read-pad': 0,
      'enabled-read-total': 0,
      'enabled-write-pad': 0,
      'enabled-write-total': 0,
      'max-chanpad-timers': 0,
      'non-numeric': 'test',  # presently all values are ints but the spec allows for anything
    }, desc.padding_counts)

    self.assertEqual(datetime.datetime(2017, 5, 17, 11, 2, 58), desc.padding_counts_end)
    self.assertEqual(86400, desc.padding_counts_interval)

    test_entries = (
      '',
      '2012-05-03',
      '2012-05-03 12:07:60 (500 s)',
      '2012-05-03 12:07:50 (500 s',
      '2012-05-03 12:07:50 (500s)',
      '2012-05-03 12:07:50 (500 s)bin-size=10',
      '2012-05-03 12:07:50 (500 s) bin-size',
      '2012-05-03 12:07:50 (500 s) bin-size=',
    )

    for entry in test_entries:
      desc = expect_invalid_attr(self, {'padding-counts': entry})
      self.assertEqual({}, desc.padding_counts)
      self.assertEqual(None, desc.padding_counts_end)
      self.assertEqual(None, desc.padding_counts_interval)
示例#35
0
    def _expect_invalid_attr(self, desc_text, attr=None, expected_value=None):
        """
    Asserts that construction will fail due to desc_text having a malformed
    attribute. If an attr is provided then we check that it matches an expected
    value when we're constructed without validation.
    """

        self.assertRaises(ValueError, RelayExtraInfoDescriptor, desc_text)
        desc = RelayExtraInfoDescriptor(desc_text, validate=False)

        if attr:
            # check that the invalid attribute matches the expected value when
            # constructed without validation

            self.assertEquals(expected_value, getattr(desc, attr))
        else:
            # check a default attribute
            self.assertEquals("ninja", desc.nickname)

        return desc
示例#36
0
  def test_hidden_service_stats_end(self):
    """
    Exercise the hidserv-stats-end, which should be a simple date.
    """

    desc = RelayExtraInfoDescriptor.create({'hidserv-stats-end': '2012-05-03 12:07:50'})
    self.assertEqual(datetime.datetime(2012, 5, 3, 12, 7, 50), desc.hs_stats_end)

    test_entries = (
      '',
      '2012',
      '2012-05',
      '2012-05-03',
      '2012-05-03 12',
      '2012-05-03 12:07',
      '2012-05-03 12:07:-50',
    )

    for entry in test_entries:
      expect_invalid_attr(self, {'hidserv-stats-end': entry}, 'hs_stats_end')
示例#37
0
  def test_hidden_service_stats_end(self):
    """
    Exercise the hidserv-stats-end, which should be a simple date.
    """

    desc = RelayExtraInfoDescriptor.create({'hidserv-stats-end': '2012-05-03 12:07:50'})
    self.assertEqual(datetime.datetime(2012, 5, 3, 12, 7, 50), desc.hs_stats_end)

    test_entries = (
      '',
      '2012',
      '2012-05',
      '2012-05-03',
      '2012-05-03 12',
      '2012-05-03 12:07',
      '2012-05-03 12:07:-50',
    )

    for entry in test_entries:
      expect_invalid_attr(self, {'hidserv-stats-end': entry}, 'hs_stats_end')
示例#38
0
    def test_dir_stat_lines(self):
        """
    Parses the dirreq-v2-direct-dl, dirreq-v3-direct-dl, dirreq-v2-tunneled-dl,
    and dirreq-v3-tunneled-dl lines with valid and invalid data.
    """

        for keyword in ('dirreq-v2-direct-dl', 'dirreq-v2-direct-dl',
                        'dirreq-v2-tunneled-dl', 'dirreq-v2-tunneled-dl'):
            attr = keyword.replace('-', '_').replace('dirreq', 'dir')
            unknown_attr = attr + '_unknown'

            test_value = 'complete=2712,timeout=32,running=4,min=741,d1=14507,d2=22702,q1=28881,d3=38277,d4=73729,md=111455,d6=168231,d7=257218,q3=319833,d8=390507,d9=616301,something-new=11,max=29917857'
            desc = RelayExtraInfoDescriptor.create({keyword: test_value})
            self.assertEqual(2712, getattr(desc, attr)[DirStat.COMPLETE])
            self.assertEqual(32, getattr(desc, attr)[DirStat.TIMEOUT])
            self.assertEqual(4, getattr(desc, attr)[DirStat.RUNNING])
            self.assertEqual(741, getattr(desc, attr)[DirStat.MIN])
            self.assertEqual(14507, getattr(desc, attr)[DirStat.D1])
            self.assertEqual(22702, getattr(desc, attr)[DirStat.D2])
            self.assertEqual(28881, getattr(desc, attr)[DirStat.Q1])
            self.assertEqual(38277, getattr(desc, attr)[DirStat.D3])
            self.assertEqual(73729, getattr(desc, attr)[DirStat.D4])
            self.assertEqual(111455, getattr(desc, attr)[DirStat.MD])
            self.assertEqual(168231, getattr(desc, attr)[DirStat.D6])
            self.assertEqual(257218, getattr(desc, attr)[DirStat.D7])
            self.assertEqual(319833, getattr(desc, attr)[DirStat.Q3])
            self.assertEqual(390507, getattr(desc, attr)[DirStat.D8])
            self.assertEqual(616301, getattr(desc, attr)[DirStat.D9])
            self.assertEqual(29917857, getattr(desc, attr)[DirStat.MAX])
            self.assertEqual(11, getattr(desc, unknown_attr)['something-new'])

            test_entries = (
                'complete=-4',
                'complete:4',
                'complete=4.timeout=3',
            )

            for entry in test_entries:
                desc = expect_invalid_attr(self, {keyword: entry})
                self.assertEqual(None, getattr(desc, attr))
                self.assertEqual(None, getattr(desc, unknown_attr))
示例#39
0
  def test_timestamp_lines(self):
    """
    Uses valid and invalid data to tests lines of the form...
    "<keyword>" YYYY-MM-DD HH:MM:SS
    """

    for keyword in ('published', 'geoip-start-time'):
      attr = keyword.replace('-', '_')

      desc = RelayExtraInfoDescriptor.create({keyword: '2012-05-03 12:07:50'})
      self.assertEqual(datetime.datetime(2012, 5, 3, 12, 7, 50), getattr(desc, attr))

      test_entries = (
        '',
        '2012-05-03 12:07:60',
        '2012-05-03 ',
        '2012-05-03',
      )

      for entry in test_entries:
        expect_invalid_attr(self, {keyword: entry}, attr)
示例#40
0
  def test_timestamp_lines(self):
    """
    Uses valid and invalid data to tests lines of the form...
    "<keyword>" YYYY-MM-DD HH:MM:SS
    """

    for keyword in ('published', 'geoip-start-time'):
      attr = keyword.replace('-', '_')

      desc = RelayExtraInfoDescriptor.create({keyword: '2012-05-03 12:07:50'})
      self.assertEqual(datetime.datetime(2012, 5, 3, 12, 7, 50), getattr(desc, attr))

      test_entries = (
        '',
        '2012-05-03 12:07:60',
        '2012-05-03 ',
        '2012-05-03',
      )

      for entry in test_entries:
        expect_invalid_attr(self, {keyword: entry}, attr)
示例#41
0
  def test_dir_stat_lines(self):
    """
    Parses the dirreq-v2-direct-dl, dirreq-v3-direct-dl, dirreq-v2-tunneled-dl,
    and dirreq-v3-tunneled-dl lines with valid and invalid data.
    """

    for keyword in ('dirreq-v2-direct-dl', 'dirreq-v2-direct-dl', 'dirreq-v2-tunneled-dl', 'dirreq-v2-tunneled-dl'):
      attr = keyword.replace('-', '_').replace('dirreq', 'dir')
      unknown_attr = attr + '_unknown'

      test_value = 'complete=2712,timeout=32,running=4,min=741,d1=14507,d2=22702,q1=28881,d3=38277,d4=73729,md=111455,d6=168231,d7=257218,q3=319833,d8=390507,d9=616301,something-new=11,max=29917857'
      desc = RelayExtraInfoDescriptor.create({keyword: test_value})
      self.assertEqual(2712, getattr(desc, attr)[DirStat.COMPLETE])
      self.assertEqual(32, getattr(desc, attr)[DirStat.TIMEOUT])
      self.assertEqual(4, getattr(desc, attr)[DirStat.RUNNING])
      self.assertEqual(741, getattr(desc, attr)[DirStat.MIN])
      self.assertEqual(14507, getattr(desc, attr)[DirStat.D1])
      self.assertEqual(22702, getattr(desc, attr)[DirStat.D2])
      self.assertEqual(28881, getattr(desc, attr)[DirStat.Q1])
      self.assertEqual(38277, getattr(desc, attr)[DirStat.D3])
      self.assertEqual(73729, getattr(desc, attr)[DirStat.D4])
      self.assertEqual(111455, getattr(desc, attr)[DirStat.MD])
      self.assertEqual(168231, getattr(desc, attr)[DirStat.D6])
      self.assertEqual(257218, getattr(desc, attr)[DirStat.D7])
      self.assertEqual(319833, getattr(desc, attr)[DirStat.Q3])
      self.assertEqual(390507, getattr(desc, attr)[DirStat.D8])
      self.assertEqual(616301, getattr(desc, attr)[DirStat.D9])
      self.assertEqual(29917857, getattr(desc, attr)[DirStat.MAX])
      self.assertEqual(11, getattr(desc, unknown_attr)['something-new'])

      test_entries = (
        'complete=-4',
        'complete:4',
        'complete=4.timeout=3',
      )

      for entry in test_entries:
        desc = expect_invalid_attr(self, {keyword: entry})
        self.assertEqual(None, getattr(desc, attr))
        self.assertEqual(None, getattr(desc, unknown_attr))
示例#42
0
  def test_cell_circuits_per_decile(self):
    """
    Parses the cell-circuits-per-decile line with valid and invalid data.
    """

    test_entries = (
      ('0', 0),
      ('11', 11),
    )

    for entry in ('0', '11', '25'):
      desc = RelayExtraInfoDescriptor.create({'cell-circuits-per-decile': entry})
      self.assertEqual(int(entry), desc.cell_circuits_per_decile)

    test_entries = (
      '',
      ' ',
      '-5',
      'blarg',
    )

    for entry in test_entries:
      expect_invalid_attr(self, {'cell-circuits-per-decile': entry}, 'cell_circuits_per_decile')
示例#43
0
 def test_descriptor_signing(self):
   RelayExtraInfoDescriptor.create(sign = True)
   self.assertRaisesRegexp(NotImplementedError, 'Signing of BridgeExtraInfoDescriptor not implemented', BridgeExtraInfoDescriptor.create, sign = True)
示例#44
0
  def test_proceeding_line(self):
    """
    Includes a line prior to the 'extra-info' entry.
    """

    expect_invalid_attr_for_text(self, b'exit-streams-opened port=80\n' + RelayExtraInfoDescriptor.content())
示例#45
0
  def test_trailing_line(self):
    """
    Includes a line after the 'router-signature' entry.
    """

    expect_invalid_attr_for_text(self, RelayExtraInfoDescriptor.content() + b'\nexit-streams-opened port=80')
示例#46
0
 def test_from_str(self):
   sig = RelayExtraInfoDescriptor.create()
   self.assertEqual(sig, RelayExtraInfoDescriptor.from_str(str(sig)))