Fixing tor related tests:

- knownnodes.cleanupKnownNodes() should set knownNodesActual = False
   if there are no nodes in stream 1 (repeated bootstrapping)
 - set socksproxytype before _initiate_bootstrap()
 - wait 5 sec in _initiate_bootstrap() to be sure all connections are closed
 - plugins do not work on travis - use socksproxytype = SOCKS5,
   check tor presence by trying to bind on port 9050
 - successfull connection to 3 onion nodes in 6 minutes is not guaranteed -
   check that bitmessage doesn't try non-onion nodes
This commit is contained in:
Dmitri Bogomolov 2020-02-11 15:07:20 +02:00 committed by Muzahid
parent 9b27e6734a
commit 2a8e91e6a7
Signed by untrusted user: cis-muzahid
GPG Key ID: 1DC85E7D3AB613EA
2 changed files with 38 additions and 28 deletions

View File

@ -1,6 +1,8 @@
""" """
Manipulations with knownNodes dictionary. Manipulations with knownNodes dictionary.
""" """
# TODO: knownnodes object maybe?
# pylint: disable=global-statement
import json import json
import logging import logging
@ -65,7 +67,7 @@ def json_deserialize_knownnodes(source):
""" """
Read JSON from source and make knownnodes dict Read JSON from source and make knownnodes dict
""" """
global knownNodesActual # pylint: disable=global-statement global knownNodesActual
for node in json.load(source): for node in json.load(source):
peer = node['peer'] peer = node['peer']
info = node['info'] info = node['info']
@ -82,7 +84,7 @@ def pickle_deserialize_old_knownnodes(source):
the old format was {Peer:lastseen, ...} the old format was {Peer:lastseen, ...}
the new format is {Peer:{"lastseen":i, "rating":f}} the new format is {Peer:{"lastseen":i, "rating":f}}
""" """
global knownNodes # pylint: disable=global-statement global knownNodes
knownNodes = pickle.load(source) knownNodes = pickle.load(source)
for stream in knownNodes.keys(): for stream in knownNodes.keys():
for node, params in knownNodes[stream].iteritems(): for node, params in knownNodes[stream].iteritems():
@ -230,6 +232,7 @@ def cleanupKnownNodes():
""" """
Cleanup knownnodes: remove old nodes and nodes with low rating Cleanup knownnodes: remove old nodes and nodes with low rating
""" """
global knownNodesActual
now = int(time.time()) now = int(time.time())
needToWriteKnownNodesToDisk = False needToWriteKnownNodesToDisk = False
@ -240,6 +243,8 @@ def cleanupKnownNodes():
keys = knownNodes[stream].keys() keys = knownNodes[stream].keys()
for node in keys: for node in keys:
if len(knownNodes[stream]) <= 1: # leave at least one node if len(knownNodes[stream]) <= 1: # leave at least one node
if stream == 1:
knownNodesActual = False
break break
try: try:
age = now - knownNodes[stream][node]["lastseen"] age = now - knownNodes[stream][node]["lastseen"]

View File

@ -21,7 +21,6 @@ import helper_addressbook
from bmconfigparser import BMConfigParser from bmconfigparser import BMConfigParser
from helper_msgcoding import MsgEncode, MsgDecode from helper_msgcoding import MsgEncode, MsgDecode
from helper_startup import start_proxyconfig
from helper_sql import sqlQuery from helper_sql import sqlQuery
from network import asyncore_pollchoose as asyncore, knownnodes from network import asyncore_pollchoose as asyncore, knownnodes
from network.bmproto import BMProto from network.bmproto import BMProto
@ -34,9 +33,10 @@ from version import softwareVersion
from common import cleanup from common import cleanup
try: try:
import stem.version as stem_version socket.socket().bind(('127.0.0.1', 9050))
except ImportError: tor_port_free = True
stem_version = None except (OSError, socket.error):
tor_port_free = False
knownnodes_file = os.path.join(state.appdata, 'knownnodes.dat') knownnodes_file = os.path.join(state.appdata, 'knownnodes.dat')
@ -159,12 +159,12 @@ class TestCore(unittest.TestCase):
def _initiate_bootstrap(self): def _initiate_bootstrap(self):
BMConfigParser().set('bitmessagesettings', 'dontconnect', 'true') BMConfigParser().set('bitmessagesettings', 'dontconnect', 'true')
self._outdate_knownnodes() self._wipe_knownnodes()
knownnodes.addKnownNode(1, Peer('127.0.0.1', 8444), is_self=True) knownnodes.addKnownNode(1, Peer('127.0.0.1', 8444), is_self=True)
knownnodes.cleanupKnownNodes() knownnodes.cleanupKnownNodes()
time.sleep(2) time.sleep(5)
def _check_connection(self): def _check_connection(self, full=False):
""" """
Check if there is at least one outbound connection to remote host Check if there is at least one outbound connection to remote host
with name not starting with "bootstrap" in 6 minutes at most, with name not starting with "bootstrap" in 6 minutes at most,
@ -185,7 +185,10 @@ class TestCore(unittest.TestCase):
time.sleep(1) time.sleep(1)
c -= 2 c -= 2
for peer, con in BMConnectionPool().outboundConnections.iteritems(): for peer, con in BMConnectionPool().outboundConnections.iteritems():
if peer.host.startswith('bootstrap'): if (
peer.host.startswith('bootstrap')
or peer.host == 'quzwelsuziwqgpt2.onion'
):
if c < 60: if c < 60:
self.fail( self.fail(
'Still connected to bootstrap node %s after % seconds' % 'Still connected to bootstrap node %s after % seconds' %
@ -195,6 +198,8 @@ class TestCore(unittest.TestCase):
else: else:
self.assertIsInstance(con, connection_base) self.assertIsInstance(con, connection_base)
self.assertNotEqual(peer.host, '127.0.0.1') self.assertNotEqual(peer.host, '127.0.0.1')
if full and not con.fullyEstablished:
continue
return return
self.fail( self.fail(
'Failed to connect during %s sec' % (time.time() - _started)) 'Failed to connect during %s sec' % (time.time() - _started))
@ -212,43 +217,43 @@ class TestCore(unittest.TestCase):
continue continue
else: else:
knownnodes.addKnownNode(1, Peer(addr, port)) knownnodes.addKnownNode(1, Peer(addr, port))
self._check_connection() self._check_connection(True)
def test_bootstrap(self): def test_bootstrap(self):
"""test bootstrapping""" """test bootstrapping"""
BMConfigParser().set('bitmessagesettings', 'socksproxytype', 'none')
self._initiate_bootstrap() self._initiate_bootstrap()
self._check_connection() self._check_connection()
@unittest.skipUnless(stem_version, 'No stem, skipping tor dependent test') @unittest.skipIf(tor_port_free, 'no running tor detected')
def test_bootstrap_tor(self): def test_bootstrap_tor(self):
"""test bootstrapping with tor""" """test bootstrapping with tor"""
BMConfigParser().set('bitmessagesettings', 'socksproxytype', 'SOCKS5')
self._initiate_bootstrap() self._initiate_bootstrap()
BMConfigParser().set('bitmessagesettings', 'socksproxytype', 'stem')
start_proxyconfig()
self._check_connection() self._check_connection()
@unittest.skipUnless(stem_version, 'No stem, skipping tor dependent test') @unittest.skipIf(tor_port_free, 'no running tor detected')
def test_onionservicesonly(self): # this should start after bootstrap def test_onionservicesonly(self):
""" """ensure bitmessage doesn't try to connect to non-onion nodes
set onionservicesonly, wait for 3 connections and check them all if onionservicesonly set, wait at least 3 onion nodes
are onions
""" """
BMConfigParser().set('bitmessagesettings', 'socksproxytype', 'SOCKS5') BMConfigParser().set('bitmessagesettings', 'socksproxytype', 'SOCKS5')
BMConfigParser().set('bitmessagesettings', 'onionservicesonly', 'true') BMConfigParser().set('bitmessagesettings', 'onionservicesonly', 'true')
self._initiate_bootstrap() self._initiate_bootstrap()
BMConfigParser().remove_option('bitmessagesettings', 'dontconnect') BMConfigParser().remove_option('bitmessagesettings', 'dontconnect')
tried_hosts = set()
for _ in range(360): for _ in range(360):
time.sleep(1) time.sleep(1)
for n, peer in enumerate(BMConnectionPool().outboundConnections): for peer in BMConnectionPool().outboundConnections:
if n > 2: if peer.host.endswith('.onion'):
tried_hosts.add(peer.host)
else:
if not peer.host.startswith('bootstrap'):
self.fail(
'Found non onion hostname %s in outbound'
'connections!' % peer.host)
if len(tried_hosts) > 2:
return return
if (
not peer.host.endswith('.onion')
and not peer.host.startswith('bootstrap')
):
self.fail(
'Found non onion hostname %s in outbound connections!'
% peer.host)
self.fail('Failed to connect to at least 3 nodes within 360 sec') self.fail('Failed to connect to at least 3 nodes within 360 sec')
@staticmethod @staticmethod