lbry-sdk/tests/unit/test_conf.py

334 lines
14 KiB
Python
Raw Permalink Normal View History

2016-11-30 22:12:14 +01:00
import os
2018-06-13 20:04:14 +02:00
import sys
2019-01-20 10:06:55 +01:00
import types
import tempfile
2019-01-20 10:06:55 +01:00
import unittest
import argparse
2019-12-31 21:45:23 +01:00
import lbry.wallet
from lbry.conf import Config, BaseConfig, String, Integer, Toggle, Servers, Strings, StringChoice, NOT_SET
from lbry.error import InvalidCurrencyError
2016-11-30 22:12:14 +01:00
2018-06-13 20:04:14 +02:00
2019-01-21 21:55:50 +01:00
class TestConfig(BaseConfig):
test_str = String('str help', 'the default', previous_names=['old_str'])
test_int = Integer('int help', 9)
test_false_toggle = Toggle('toggle help', False)
test_true_toggle = Toggle('toggle help', True)
2019-01-21 21:55:50 +01:00
servers = Servers('servers help', [('localhost', 80)])
strings = Strings('cheese', ['string'])
string_choice = StringChoice("one of string", ["a", "b", "c"], "a")
2019-01-20 10:06:55 +01:00
class ConfigurationTests(unittest.TestCase):
2021-07-30 16:21:52 +02:00
@unittest.skipIf('darwin' not in sys.platform, 'skipping mac only test')
def test_mac_defaults(self):
c = Config()
self.assertEqual(c.data_dir, os.path.expanduser("~/Library/Application Support/LBRY"))
self.assertEqual(c.wallet_dir, os.path.expanduser('~/.lbryum'))
self.assertEqual(c.download_dir, os.path.expanduser('~/Downloads'))
self.assertEqual(c.config, os.path.join(c.data_dir, 'daemon_settings.yml'))
self.assertEqual(c.api_connection_url, 'http://localhost:5279/lbryapi')
self.assertEqual(c.log_file_path, os.path.join(c.data_dir, 'lbrynet.log'))
@unittest.skipIf('win32' not in sys.platform, 'skipping windows only test')
def test_windows_defaults(self):
c = Config()
prefix = os.path.join(r"C:\Users", os.getlogin(), r"AppData\Local\lbry")
self.assertEqual(c.data_dir, os.path.join(prefix, 'lbrynet'))
self.assertEqual(c.wallet_dir, os.path.join(prefix, 'lbryum'))
self.assertEqual(c.download_dir, os.path.join(r"C:\Users", os.getlogin(), "Downloads"))
self.assertEqual(c.config, os.path.join(c.data_dir, 'daemon_settings.yml'))
self.assertEqual(c.api_connection_url, 'http://localhost:5279/lbryapi')
self.assertEqual(c.log_file_path, os.path.join(c.data_dir, 'lbrynet.log'))
2019-01-20 10:06:55 +01:00
@unittest.skipIf('linux' not in sys.platform, 'skipping linux only test')
def test_linux_defaults(self):
2019-01-21 21:55:50 +01:00
c = Config()
2019-01-20 10:06:55 +01:00
self.assertEqual(c.data_dir, os.path.expanduser('~/.local/share/lbry/lbrynet'))
self.assertEqual(c.wallet_dir, os.path.expanduser('~/.local/share/lbry/lbryum'))
self.assertEqual(c.download_dir, os.path.expanduser('~/Downloads'))
self.assertEqual(c.config, os.path.expanduser('~/.local/share/lbry/lbrynet/daemon_settings.yml'))
2019-01-21 21:55:50 +01:00
self.assertEqual(c.api_connection_url, 'http://localhost:5279/lbryapi')
self.assertEqual(c.log_file_path, os.path.expanduser('~/.local/share/lbry/lbrynet/lbrynet.log'))
2019-01-20 10:06:55 +01:00
def test_search_order(self):
c = TestConfig()
2019-01-21 21:55:50 +01:00
c.runtime = {'test_str': 'runtime'}
c.arguments = {'test_str': 'arguments'}
c.environment = {'test_str': 'environment'}
c.persisted = {'test_str': 'persisted'}
self.assertEqual(c.test_str, 'runtime')
2019-01-20 10:06:55 +01:00
c.runtime = {}
2019-01-21 21:55:50 +01:00
self.assertEqual(c.test_str, 'arguments')
2019-01-20 10:06:55 +01:00
c.arguments = {}
2019-01-21 21:55:50 +01:00
self.assertEqual(c.test_str, 'environment')
2019-01-20 10:06:55 +01:00
c.environment = {}
2019-01-21 21:55:50 +01:00
self.assertEqual(c.test_str, 'persisted')
2019-01-20 10:06:55 +01:00
c.persisted = {}
2019-01-21 21:55:50 +01:00
self.assertEqual(c.test_str, 'the default')
2019-01-20 10:06:55 +01:00
def test_is_set(self):
c = TestConfig()
self.assertEqual(c.test_str, 'the default')
self.assertFalse(TestConfig.test_str.is_set(c))
c.test_str = 'new value'
self.assertEqual(c.test_str, 'new value')
self.assertTrue(TestConfig.test_str.is_set(c))
def test_is_set_to_default(self):
c = TestConfig()
self.assertEqual(TestConfig.test_str.default, 'the default')
self.assertFalse(TestConfig.test_str.is_set(c))
self.assertFalse(TestConfig.test_str.is_set_to_default(c))
c.test_str = 'new value'
self.assertTrue(TestConfig.test_str.is_set(c))
self.assertFalse(TestConfig.test_str.is_set_to_default(c))
c.test_str = 'the default'
self.assertTrue(TestConfig.test_str.is_set(c))
self.assertTrue(TestConfig.test_str.is_set_to_default(c))
2019-01-20 10:06:55 +01:00
def test_arguments(self):
parser = argparse.ArgumentParser()
TestConfig.contribute_to_argparse(parser)
args = parser.parse_args([])
c = TestConfig.create_from_arguments(args)
self.assertEqual(c.test_str, 'the default')
self.assertTrue(c.test_true_toggle)
self.assertFalse(c.test_false_toggle)
self.assertEqual(c.servers, [('localhost', 80)])
self.assertEqual(c.strings, ['string'])
2019-01-21 21:55:50 +01:00
args = parser.parse_args(['--test-str', 'blah'])
2019-01-20 10:06:55 +01:00
c = TestConfig.create_from_arguments(args)
2019-01-21 21:55:50 +01:00
self.assertEqual(c.test_str, 'blah')
self.assertTrue(c.test_true_toggle)
self.assertFalse(c.test_false_toggle)
args = parser.parse_args(['--test-true-toggle'])
c = TestConfig.create_from_arguments(args)
self.assertTrue(c.test_true_toggle)
self.assertFalse(c.test_false_toggle)
args = parser.parse_args(['--test-false-toggle'])
c = TestConfig.create_from_arguments(args)
self.assertTrue(c.test_true_toggle)
self.assertTrue(c.test_false_toggle)
args = parser.parse_args(['--no-test-true-toggle'])
c = TestConfig.create_from_arguments(args)
self.assertFalse(c.test_true_toggle)
self.assertFalse(c.test_false_toggle)
args = parser.parse_args(['--servers=localhost:1', '--servers=192.168.0.1:2'])
c = TestConfig.create_from_arguments(args)
self.assertEqual(c.servers, [('localhost', 1), ('192.168.0.1', 2)])
2019-01-20 10:06:55 +01:00
args = parser.parse_args(['--strings=cheddar', '--strings=mozzarella'])
c = TestConfig.create_from_arguments(args)
self.assertEqual(c.strings, ['cheddar', 'mozzarella'])
2019-01-20 10:06:55 +01:00
def test_environment(self):
c = TestConfig()
2020-05-18 14:51:06 +02:00
2019-01-21 21:55:50 +01:00
self.assertEqual(c.test_str, 'the default')
c.set_environment({'LBRY_TEST_STR': 'from environ'})
self.assertEqual(c.test_str, 'from environ')
2020-05-18 14:51:06 +02:00
self.assertEqual(c.test_int, 9)
c.set_environment({'LBRY_TEST_INT': '1'})
self.assertEqual(c.test_int, 1)
2019-01-20 10:06:55 +01:00
def test_persisted(self):
with tempfile.TemporaryDirectory() as temp_dir:
c = TestConfig.create_from_arguments(
types.SimpleNamespace(config=os.path.join(temp_dir, 'settings.yml'))
)
# settings.yml doesn't exist on file system
self.assertFalse(c.persisted.exists)
2019-01-21 21:55:50 +01:00
self.assertEqual(c.test_str, 'the default')
2019-01-20 10:06:55 +01:00
self.assertEqual(c.modify_order, [c.runtime])
with c.update_config():
self.assertEqual(c.modify_order, [c.runtime, c.persisted])
2019-01-21 21:55:50 +01:00
c.test_str = 'original'
2019-01-20 10:06:55 +01:00
self.assertEqual(c.modify_order, [c.runtime])
# share_usage_data has been saved to settings file
self.assertTrue(c.persisted.exists)
with open(c.config, 'r') as fd:
2019-01-21 21:55:50 +01:00
self.assertEqual(fd.read(), 'test_str: original\n')
2019-01-20 10:06:55 +01:00
# load the settings file and check share_usage_data is false
c = TestConfig.create_from_arguments(
types.SimpleNamespace(config=os.path.join(temp_dir, 'settings.yml'))
)
self.assertTrue(c.persisted.exists)
2019-01-21 21:55:50 +01:00
self.assertEqual(c.test_str, 'original')
2019-01-20 10:06:55 +01:00
# setting in runtime overrides config
2019-01-21 21:55:50 +01:00
self.assertNotIn('test_str', c.runtime)
c.test_str = 'from runtime'
self.assertIn('test_str', c.runtime)
self.assertEqual(c.test_str, 'from runtime')
# without context manager NOT_SET only clears it in runtime location
c.test_str = NOT_SET
self.assertNotIn('test_str', c.runtime)
self.assertEqual(c.test_str, 'original')
# clear it in persisted as well by using context manager
self.assertIn('test_str', c.persisted)
2019-01-20 10:06:55 +01:00
with c.update_config():
2019-01-21 21:55:50 +01:00
c.test_str = NOT_SET
self.assertNotIn('test_str', c.persisted)
self.assertEqual(c.test_str, 'the default')
2019-01-20 10:06:55 +01:00
with open(c.config, 'r') as fd:
self.assertEqual(fd.read(), '{}\n')
2019-01-21 21:55:50 +01:00
def test_persisted_upgrade(self):
with tempfile.TemporaryDirectory() as temp_dir:
config = os.path.join(temp_dir, 'settings.yml')
with open(config, 'w') as fd:
fd.write('old_str: old stuff\n')
c = TestConfig.create_from_arguments(
types.SimpleNamespace(config=config)
)
self.assertEqual(c.test_str, 'old stuff')
self.assertNotIn('old_str', c.persisted)
with open(config, 'w') as fd:
fd.write('test_str: old stuff\n')
2019-01-20 10:06:55 +01:00
def test_validation(self):
c = TestConfig()
with self.assertRaisesRegex(AssertionError, 'must be a string'):
2019-01-21 21:55:50 +01:00
c.test_str = 9
2019-01-20 10:06:55 +01:00
with self.assertRaisesRegex(AssertionError, 'must be an integer'):
c.test_int = 'hi'
with self.assertRaisesRegex(AssertionError, 'must be a true/false'):
c.test_true_toggle = 'hi'
c.test_false_toggle = 'hi'
2019-01-20 10:06:55 +01:00
def test_file_extension_validation(self):
with self.assertRaisesRegex(AssertionError, "'.json' is not supported"):
TestConfig.create_from_arguments(
types.SimpleNamespace(config=os.path.join('settings.json'))
)
def test_serialize_deserialize(self):
with tempfile.TemporaryDirectory() as temp_dir:
c = TestConfig.create_from_arguments(
types.SimpleNamespace(config=os.path.join(temp_dir, 'settings.yml'))
)
self.assertEqual(c.servers, [('localhost', 80)])
with c.update_config():
c.servers = [('localhost', 8080)]
with open(c.config, 'r+') as fd:
self.assertEqual(fd.read(), 'servers:\n- localhost:8080\n')
fd.write('servers:\n - localhost:5566\n')
c = TestConfig.create_from_arguments(
types.SimpleNamespace(config=os.path.join(temp_dir, 'settings.yml'))
)
self.assertEqual(c.servers, [('localhost', 5566)])
def test_max_key_fee_from_yaml(self):
2019-01-20 10:06:55 +01:00
with tempfile.TemporaryDirectory() as temp_dir:
config = os.path.join(temp_dir, 'settings.yml')
with open(config, 'w') as fd:
2019-01-25 00:45:52 +01:00
fd.write('max_key_fee: {currency: USD, amount: 1}\n')
2019-01-21 21:55:50 +01:00
c = Config.create_from_arguments(
2019-01-20 10:06:55 +01:00
types.SimpleNamespace(config=config)
)
self.assertEqual(c.max_key_fee['currency'], 'USD')
self.assertEqual(c.max_key_fee['amount'], 1)
with self.assertRaises(InvalidCurrencyError):
c.max_key_fee = {'currency': 'BCH', 'amount': 1}
with c.update_config():
c.max_key_fee = {'currency': 'BTC', 'amount': 1}
with open(config, 'r') as fd:
2019-01-25 00:45:52 +01:00
self.assertEqual(fd.read(), 'max_key_fee:\n amount: 1\n currency: BTC\n')
2019-01-26 04:27:10 +01:00
with c.update_config():
c.max_key_fee = None
with open(config, 'r') as fd:
self.assertEqual(fd.read(), 'max_key_fee: null\n')
def test_max_key_fee_from_args(self):
parser = argparse.ArgumentParser()
Config.contribute_to_argparse(parser)
# default
args = parser.parse_args([])
c = Config.create_from_arguments(args)
self.assertEqual(c.max_key_fee, {'amount': 50.0, 'currency': 'USD'})
# disabled
args = parser.parse_args(['--no-max-key-fee'])
c = Config.create_from_arguments(args)
2019-10-02 18:58:51 +02:00
self.assertIsNone(c.max_key_fee)
args = parser.parse_args(['--max-key-fee', 'null'])
c = Config.create_from_arguments(args)
2019-10-02 18:58:51 +02:00
self.assertIsNone(c.max_key_fee)
# set
args = parser.parse_args(['--max-key-fee', '1.0', 'BTC'])
c = Config.create_from_arguments(args)
self.assertEqual(c.max_key_fee, {'amount': 1.0, 'currency': 'BTC'})
2019-06-19 17:36:46 +02:00
def test_string_choice(self):
with self.assertRaisesRegex(ValueError, "No valid values provided"):
StringChoice("no valid values", [], "")
with self.assertRaisesRegex(ValueError, "Default value must be one of"):
StringChoice("invalid default", ["a"], "b")
2019-06-19 17:36:46 +02:00
c = TestConfig()
self.assertEqual("a", c.string_choice) # default
c.string_choice = "b"
self.assertEqual("b", c.string_choice)
with self.assertRaisesRegex(ValueError, "Setting 'string_choice' value must be one of"):
c.string_choice = "d"
2019-06-19 17:36:46 +02:00
parser = argparse.ArgumentParser()
TestConfig.contribute_to_argparse(parser)
args = parser.parse_args(['--string-choice', 'c'])
2019-06-19 17:36:46 +02:00
c = TestConfig.create_from_arguments(args)
self.assertEqual("c", c.string_choice)
def test_known_hubs_list(self):
with tempfile.TemporaryDirectory() as temp_dir:
hubs = Config(config=os.path.join(temp_dir, 'settings.yml'), wallet_dir=temp_dir).known_hubs
self.assertEqual(hubs.serialized, {})
self.assertEqual(list(hubs), [])
self.assertFalse(hubs)
hubs.set('new.hub.io:99', {'jurisdiction': 'us'})
self.assertTrue(hubs)
self.assertFalse(hubs.exists)
hubs.save()
self.assertTrue(hubs.exists)
hubs = Config(config=os.path.join(temp_dir, 'settings.yml'), wallet_dir=temp_dir).known_hubs
self.assertEqual(list(hubs), [('new.hub.io', 99)])
self.assertEqual(hubs.serialized, {'new.hub.io:99': {'jurisdiction': 'us'}})
hubs.set('any.hub.io:99', {})
hubs.set('oth.hub.io:99', {'jurisdiction': 'other'})
self.assertEqual(list(hubs), [('new.hub.io', 99), ('any.hub.io', 99), ('oth.hub.io', 99)])
self.assertEqual(hubs.filter(), {
('new.hub.io', 99): {'jurisdiction': 'us'},
('oth.hub.io', 99): {'jurisdiction': 'other'},
('any.hub.io', 99): {}
})
self.assertEqual(hubs.filter(foo="bar"), {})
self.assertEqual(hubs.filter(jurisdiction="us"), {
('new.hub.io', 99): {'jurisdiction': 'us'}
})
self.assertEqual(hubs.filter(jurisdiction="us", match_none=True), {
('new.hub.io', 99): {'jurisdiction': 'us'},
('any.hub.io', 99): {}
})