def testing_tub(config_data=''): """ Creates a 'main' Tub for testing purposes, from config data """ from twisted.internet import reactor basedir = 'dummy_basedir' config = config_from_string(basedir, 'DEFAULT_PORTNUMFILE_BLANK', config_data) fileutil.make_dirs(os.path.join(basedir, 'private')) i2p_provider = create_i2p_provider(reactor, config) tor_provider = create_tor_provider(reactor, config) handlers = create_connection_handlers(reactor, config, i2p_provider, tor_provider) default_connection_handlers, foolscap_connection_handlers = handlers tub_options = create_tub_options(config) main_tub = create_main_tub(config, tub_options, default_connection_handlers, foolscap_connection_handlers, i2p_provider, tor_provider, cert_filename='DEFAULT_CERTFILE_BLANK') return main_tub
def test_private_config(self): basedir = u"test_node/test_private_config" privdir = os.path.join(basedir, "private") fileutil.make_dirs(privdir) f = open(os.path.join(privdir, 'already'), 'wt') f.write("secret") f.close() basedir = fileutil.abspath_expanduser_unicode(basedir) config = config_from_string(basedir, "", "") self.assertEqual(config.get_private_config("already"), "secret") self.assertEqual(config.get_private_config("not", "default"), "default") self.assertRaises(MissingConfigEntry, config.get_private_config, "not") value = config.get_or_create_private_config("new", "start") self.assertEqual(value, "start") self.assertEqual(config.get_private_config("new"), "start") counter = [] def make_newer(): counter.append("called") return "newer" value = config.get_or_create_private_config("newer", make_newer) self.assertEqual(len(counter), 1) self.assertEqual(value, "newer") self.assertEqual(config.get_private_config("newer"), "newer") value = config.get_or_create_private_config("newer", make_newer) self.assertEqual(len(counter), 1) # don't call unless necessary self.assertEqual(value, "newer")
def __init__(self, config_str): from allmydata.node import config_from_string self.config = config_from_string(config_str, "fake.port") self.basedir = "BASEDIR" self._reveal_ip = True self.services = [] self.create_i2p_provider() self.create_tor_provider()
def test_listen_on_zero_with_host(self): """ ``_tub_portlocation`` raises ``PortAssignmentRequired`` called with a listen address including port 0 and an interface. """ config_data = ("[node]\n" "tub.port = tcp:0:interface=127.0.0.1\n") config = config_from_string(self.basedir, "portnum", config_data) with self.assertRaises(PortAssignmentRequired): _tub_portlocation(config, None, None)
def test_set_config_new_section(self): """ ``_Config.set_config`` can be called with the name of a section that does not already exist to create that section and set an item in it. """ basedir = self.mktemp() new_config = config_from_string(basedir, "", "", ValidConfiguration.everything()) new_config.set_config("foo", "bar", "value1") self.assertEqual(new_config.get_config("foo", "bar"), "value1")
def test_empty_tub_location(self): """ location povided, but empty is an error """ config_data = ("[node]\n" "tub.location = \n") config = config_from_string(self.basedir, "portnum", config_data) with self.assertRaises(ValueError) as ctx: _tub_portlocation(config) self.assertIn("tub.location must not be empty", str(ctx.exception))
def test_invalid_introducer_furl(self): """ An introducer.furl of 'None' is invalid and causes create_introducer_clients to fail. """ cfg = ("[client]\n" "introducer.furl = None\n") config = config_from_string("basedir", "client.port", cfg) with self.assertRaises(ValueError) as ctx: client.create_introducer_clients(config, main_tub=None) self.assertIn("invalid 'introducer.furl = None'", str(ctx.exception))
def test_set_config_replace(self): """ ``_Config.set_config`` can be called with a section and item that already exists to change an existing value to a new one. """ basedir = self.mktemp() new_config = config_from_string(basedir, "", "", ValidConfiguration.everything()) new_config.set_config("foo", "bar", "value1") new_config.set_config("foo", "bar", "value2") self.assertEqual(new_config.get_config("foo", "bar"), "value2")
def test_set_config_unescaped_furl_hash(self): """ ``_Config.set_config`` raises ``UnescapedHashError`` if the item being set is a furl and the value includes ``"#"`` and does not set the value. """ basedir = self.mktemp() new_config = config_from_string(basedir, "", "") with self.assertRaises(UnescapedHashError): new_config.set_config("foo", "bar.furl", "value#1") with self.assertRaises(MissingConfigEntry): new_config.get_config("foo", "bar.furl")
def test_set_config_rejects_invalid_config(self): """ ``_Config.set_config`` raises ``UnknownConfigError`` if the section or item is not recognized by the validation object and does not set the value. """ # Make everything invalid. valid_config = ValidConfiguration.nothing() new_config = config_from_string(self.mktemp(), "", "", valid_config) with self.assertRaises(UnknownConfigError): new_config.set_config("foo", "bar", "baz") with self.assertRaises(MissingConfigEntry): new_config.get_config("foo", "bar")
def test_disabled_tub_not_port(self): """ error to disable location but not port """ config_data = ("[node]\n" "tub.port = not_disabled\n" "tub.location = disabled\n") config = config_from_string(self.basedir, "portnum", config_data) with self.assertRaises(ValueError) as ctx: _tub_portlocation(config) self.assertIn("tub.location is disabled, but not tub.port", str(ctx.exception))
def test_parsing_location_complex(self): """ location with two options (including defaults) """ config_data = ("[node]\n" "tub.location = tcp:HOST:888,AUTO\n") config = config_from_string(self.basedir, "portnum", config_data) tubport, tublocation = _tub_portlocation( config, _stub_get_local_addresses_sync, _stub_allocate_tcp_port, ) self.assertEqual(tubport, "tcp:999") self.assertEqual(tublocation, b"tcp:HOST:888,tcp:LOCAL:999")
def test_parsing_defaults(self): """ parse empty config, check defaults """ config_data = ("[node]\n") config = config_from_string(self.basedir, "portnum", config_data) tubport, tublocation = _tub_portlocation( config, _stub_get_local_addresses_sync, _stub_allocate_tcp_port, ) self.assertEqual(tubport, "tcp:999") self.assertEqual(tublocation, b"tcp:LOCAL:999")
def test_empty_tub_port(self): """ port povided, but empty is an error """ config_data = ("[node]\n" "tub.port = \n") config = config_from_string(self.basedir, "portnum", config_data) with self.assertRaises(ValueError) as ctx: _tub_portlocation( config, _stub_get_local_addresses_sync, _stub_allocate_tcp_port, ) self.assertIn("tub.port must not be empty", str(ctx.exception))
def test_tcp_disabled(self): """ If tcp is set to disabled, no TCP handler is set. """ config = config_from_string( "", "", dedent(""" [connections] tcp = disabled """)) reactor = object() # it's not actually used?! provider = FakeProvider() default_handlers, _ = create_connection_handlers( reactor, config, provider, provider) self.assertIs(default_handlers["tcp"], None)
def test_tcp_disabled(self): """ If tcp is set to disabled, no TCP handler is set. """ config = config_from_string( "", "", dedent(""" [connections] tcp = disabled """)) default_handlers = create_default_connection_handlers( config, {}, ) self.assertIs(default_handlers["tcp"], None)
def test_parsing_all_disabled(self): """ parse config with both port + location disabled """ config_data = ("[node]\n" "tub.port = disabled\n" "tub.location = disabled\n") config = config_from_string(self.basedir, "portnum", config_data) res = _tub_portlocation( config, _stub_get_local_addresses_sync, _stub_allocate_tcp_port, ) self.assertTrue(res is None)
def test_empty_tub_location(self): """ location povided, but empty is an error """ config_data = ( "[node]\n" "tub.location = \n" ) config = config_from_string(self.basedir, "portnum", config_data) with self.assertRaises(ValueError) as ctx: _tub_portlocation(config) self.assertIn( "tub.location must not be empty", str(ctx.exception) )
def test_write_config_unwritable_file(self): """ Existing behavior merely logs any errors upon writing configuration files; this bad behavior should probably be fixed to do something better (like fail entirely). See #2905 """ basedir = "test_node/configdir" fileutil.make_dirs(basedir) config = config_from_string(basedir, "", "") with open(os.path.join(basedir, "bad"), "w") as f: f.write("bad") os.chmod(os.path.join(basedir, "bad"), 0o000) config.write_config_file("bad", "some value") errs = self.flushLoggedErrors(IOError) self.assertEqual(1, len(errs))
def test_disabled_tub_not_port(self): """ error to disable location but not port """ config_data = ( "[node]\n" "tub.port = not_disabled\n" "tub.location = disabled\n" ) config = config_from_string(self.basedir, "portnum", config_data) with self.assertRaises(ValueError) as ctx: _tub_portlocation(config) self.assertIn( "tub.location is disabled, but not tub.port", str(ctx.exception) )
def test_disabled_port_not_tub(self): """ error to disable port but not location """ config_data = ("[node]\n" "tub.port = disabled\n" "tub.location = not_disabled\n") config = config_from_string(self.basedir, "portnum", config_data) with self.assertRaises(ValueError) as ctx: _tub_portlocation( config, _stub_get_local_addresses_sync, _stub_allocate_tcp_port, ) self.assertIn("tub.port is disabled, but not tub.location", str(ctx.exception))
def test_invalid_introducer_furl(self): """ An introducer.furl of 'None' is invalid and causes create_introducer_clients to fail. """ cfg = ( "[client]\n" "introducer.furl = None\n" ) config = config_from_string("basedir", "client.port", cfg) with self.assertRaises(ValueError) as ctx: client.create_introducer_clients(config, main_tub=None) self.assertIn( "invalid 'introducer.furl = None'", str(ctx.exception) )
def test_json(self): """ The JSON response includes totals for the number of subscriptions and announcements of each service type. """ config = node.config_from_string(self.mktemp(), "", "") config.get_private_path = lambda ignored: self.mktemp() main_tub = Tub() main_tub.listenOn(b"tcp:0") main_tub.setLocation(b"tcp:127.0.0.1:1") introducer_node = _IntroducerNode(config, main_tub, None, None, None) introducer_service = introducer_node.getServiceNamed("introducer") for n in range(2): introducer_service.add_subscriber( FakeCanary(), "arbitrary", {"info": "info"}, ) # It would be nice to use the publish method but then we have to # generate a correctly signed message which I don't feel like doing. ann_t = ("msg", "sig", "key") ann = {"service-name": "arbitrary"} introducer_service._announcements[("arbitrary", "key")] = ( ann_t, FakeCanary(), ann, 0, ) resource = IntroducerRoot(introducer_node) response = json.loads( self.successResultOf(render(resource, {"t": [b"json"]}), ), ) self.assertEqual( response, { u"subscription_summary": { "arbitrary": 2 }, u"announcement_summary": { "arbitrary": 1 }, }, )
def test_welcome(self): config = ("[node]\n" "tub.location = 127.0.0.1:1\n" "web.port = tcp:0\n") from allmydata.node import config_from_string self.node = IntroducerNode( config_from_string(config, portnumfile="introducer.port"), ) self.ws = self.node.getServiceNamed("webish") yield fireEventually(None) self.node.startService() url = "http://localhost:%d/" % self.ws.getPortnum() res = yield do_http("get", url) self.failUnlessIn('Welcome to the Tahoe-LAFS Introducer', res) self.failUnlessIn(FAVICON_MARKUP, res) self.failUnlessIn('Page rendered at', res) self.failUnlessIn('Tahoe-LAFS code imported from:', res)
def test_parsing_tcp(self): """ When ``tub.port`` is given and ``tub.location`` is **AUTO** the port number from ``tub.port`` is used as the port number for the value constructed for ``tub.location``. """ config_data = ("[node]\n" "tub.port = tcp:777\n" "tub.location = AUTO\n") config = config_from_string(self.basedir, "portnum", config_data) tubport, tublocation = _tub_portlocation( config, _stub_get_local_addresses_sync, _stub_allocate_tcp_port, ) self.assertEqual(tubport, "tcp:777") self.assertEqual(tublocation, b"tcp:LOCAL:777")
def test_parsing_defaults(self): """ parse empty config, check defaults """ get_addr = mock.patch( "allmydata.util.iputil.get_local_addresses_sync", return_value=["LOCAL"], ) alloc_port = mock.patch( "allmydata.util.iputil.allocate_tcp_port", return_value=999, ) config_data = ("[node]\n") config = config_from_string(self.basedir, "portnum", config_data) with get_addr, alloc_port: tubport, tublocation = _tub_portlocation(config) self.assertEqual(tubport, "tcp:999") self.assertEqual(tublocation, b"tcp:LOCAL:999")
def test_parsing_location_complex(self): """ location with two options (including defaults) """ get_addr = mock.patch( "allmydata.util.iputil.get_local_addresses_sync", return_value=["LOCAL"], ) alloc_port = mock.patch( "allmydata.util.iputil.allocate_tcp_port", return_value=999, ) config_data = ("[node]\n" "tub.location = tcp:HOST:888,AUTO\n") config = config_from_string(self.basedir, "portnum", config_data) with get_addr, alloc_port: tubport, tublocation = _tub_portlocation(config) self.assertEqual(tubport, "tcp:999") self.assertEqual(tublocation, b"tcp:HOST:888,tcp:LOCAL:999")
def test_parsing_all_disabled(self): """ parse config with both port + location disabled """ get_addr = mock.patch( "allmydata.util.iputil.get_local_addresses_sync", return_value=["LOCAL"], ) alloc_port = mock.patch( "allmydata.util.iputil.allocate_tcp_port", return_value=999, ) config_data = ("[node]\n" "tub.port = disabled\n" "tub.location = disabled\n") config = config_from_string(self.basedir, "portnum", config_data) with get_addr, alloc_port: res = _tub_portlocation(config) self.assertTrue(res is None)
def test_parsing_defaults(self): """ parse empty config, check defaults """ get_addr = mock.patch( "allmydata.util.iputil.get_local_addresses_sync", return_value=["LOCAL"], ) alloc_port = mock.patch( "allmydata.util.iputil.allocate_tcp_port", return_value=999, ) config_data = ( "[node]\n" ) config = config_from_string(self.basedir, "portnum", config_data) with get_addr, alloc_port: tubport, tublocation = _tub_portlocation(config) self.assertEqual(tubport, "tcp:999") self.assertEqual(tublocation, "tcp:LOCAL:999")
def testing_tub(config_data=''): """ Creates a 'main' Tub for testing purposes, from config data """ from twisted.internet import reactor basedir = 'dummy_basedir' config = config_from_string(basedir, 'DEFAULT_PORTNUMFILE_BLANK', config_data) fileutil.make_dirs(os.path.join(basedir, 'private')) i2p_provider = create_i2p_provider(reactor, config) tor_provider = create_tor_provider(reactor, config) handlers = create_connection_handlers(reactor, config, i2p_provider, tor_provider) default_connection_handlers, foolscap_connection_handlers = handlers tub_options = create_tub_options(config) main_tub = create_main_tub( config, tub_options, default_connection_handlers, foolscap_connection_handlers, i2p_provider, tor_provider, cert_filename='DEFAULT_CERTFILE_BLANK' ) return main_tub
def test_tub_location_tcp(self): """ If ``reveal-IP-address`` is set to false and ``tub.location`` includes a **tcp** hint then ``_tub_portlocation`` raises `PrivacyError`` because TCP leaks IP addresses. """ config = config_from_string( "fake.port", "no-basedir", "[node]\nreveal-IP-address = false\ntub.location=tcp:hostname:1234\n", ) with self.assertRaises(PrivacyError) as ctx: _tub_portlocation( config, _stub_get_local_addresses_sync, _stub_allocate_tcp_port, ) self.assertEqual( str(ctx.exception), "tub.location includes tcp: hint", )
def test_parsing_tcp(self): """ parse explicit tub.port with explicitly-default tub.location """ get_addr = mock.patch( "allmydata.util.iputil.get_local_addresses_sync", return_value=["LOCAL"], ) alloc_port = mock.patch( "allmydata.util.iputil.allocate_tcp_port", return_value=999, ) config_data = ("[node]\n" "tub.port = tcp:777\n" "tub.location = AUTO\n") config = config_from_string(self.basedir, "portnum", config_data) with get_addr, alloc_port: tubport, tublocation = _tub_portlocation(config) self.assertEqual(tubport, "tcp:777") self.assertEqual(tublocation, b"tcp:LOCAL:777")
def test_parsing_location_complex(self): """ location with two options (including defaults) """ get_addr = mock.patch( "allmydata.util.iputil.get_local_addresses_sync", return_value=["LOCAL"], ) alloc_port = mock.patch( "allmydata.util.iputil.allocate_tcp_port", return_value=999, ) config_data = ( "[node]\n" "tub.location = tcp:HOST:888,AUTO\n" ) config = config_from_string(self.basedir, "portnum", config_data) with get_addr, alloc_port: tubport, tublocation = _tub_portlocation(config) self.assertEqual(tubport, "tcp:999") self.assertEqual(tublocation, "tcp:HOST:888,tcp:LOCAL:999")
def test_parsing_all_disabled(self): """ parse config with both port + location disabled """ get_addr = mock.patch( "allmydata.util.iputil.get_local_addresses_sync", return_value=["LOCAL"], ) alloc_port = mock.patch( "allmydata.util.iputil.allocate_tcp_port", return_value=999, ) config_data = ( "[node]\n" "tub.port = disabled\n" "tub.location = disabled\n" ) config = config_from_string(self.basedir, "portnum", config_data) with get_addr, alloc_port: res = _tub_portlocation(config) self.assertTrue(res is None)
def test_parsing_tcp(self): """ parse explicit tub.port with explicitly-default tub.location """ get_addr = mock.patch( "allmydata.util.iputil.get_local_addresses_sync", return_value=["LOCAL"], ) alloc_port = mock.patch( "allmydata.util.iputil.allocate_tcp_port", return_value=999, ) config_data = ( "[node]\n" "tub.port = tcp:777\n" "tub.location = AUTO\n" ) config = config_from_string(self.basedir, "portnum", config_data) with get_addr, alloc_port: tubport, tublocation = _tub_portlocation(config) self.assertEqual(tubport, "tcp:777") self.assertEqual(tublocation, "tcp:LOCAL:777")
def test_tub_location_legacy_tcp(self): """ If ``reveal-IP-address`` is set to false and ``tub.location`` includes a "legacy" hint with no explicit type (which means it is a **tcp** hint) then the behavior is the same as for an explicit **tcp** hint. """ config = config_from_string( "fake.port", "no-basedir", "[node]\nreveal-IP-address = false\ntub.location=hostname:1234\n", ) with self.assertRaises(PrivacyError) as ctx: _tub_portlocation( config, _stub_get_local_addresses_sync, _stub_allocate_tcp_port, ) self.assertEqual( str(ctx.exception), "tub.location includes tcp: hint", )
def __init__(self): config = config_from_string("", "no portfile") Node.__init__(self, config, 'no basedir')