planetmint/tests/test_config_utils.py
Jürgen Eckel 3afb2e6f3d
blackified with newest verion to satisfy CI
Signed-off-by: Jürgen Eckel <juergen@riddleandcode.com>
2023-02-14 22:43:33 +01:00

325 lines
11 KiB
Python

# Copyright © 2020 Interplanetary Database Association e.V.,
# Planetmint and IPDB software contributors.
# SPDX-License-Identifier: (Apache-2.0 AND CC-BY-4.0)
# Code is Apache-2.0 and docs are CC-BY-4.0
import pytest
import planetmint
from unittest.mock import mock_open, patch
from planetmint.config import Config
@pytest.fixture(scope="function", autouse=True)
def clean_config(monkeypatch, request):
original_config = Config().init_config("tarantool_db")
backend = request.config.getoption("--database-backend")
original_config["database"] = Config().get_db_map(backend)
monkeypatch.setattr("planetmint.config", original_config)
def test_bigchain_instance_is_initialized_when_conf_provided():
from planetmint import config_utils
assert "CONFIGURED" not in Config().get()
config_utils.set_config({"database": {"backend": "a"}})
assert Config().get()["CONFIGURED"] is True
def test_load_validation_plugin_loads_default_rules_without_name():
from planetmint import config_utils
from planetmint.validation import BaseValidationRules
assert config_utils.load_validation_plugin() == BaseValidationRules
def test_load_validation_plugin_raises_with_unknown_name():
from pkg_resources import ResolutionError
from planetmint import config_utils
with pytest.raises(ResolutionError):
config_utils.load_validation_plugin("bogus")
def test_load_validation_plugin_raises_with_invalid_subclass(monkeypatch):
# Monkeypatch entry_point.load to return something other than a
# ValidationRules instance
from planetmint import config_utils
import time
monkeypatch.setattr(
config_utils, "iter_entry_points", lambda *args: [type("entry_point", (object,), {"load": lambda: object})]
)
with pytest.raises(TypeError):
# Since the function is decorated with `lru_cache`, we need to
# "miss" the cache using a name that has not been used previously
config_utils.load_validation_plugin(str(time.time()))
def test_load_events_plugins(monkeypatch):
from planetmint import config_utils
monkeypatch.setattr(
config_utils, "iter_entry_points", lambda *args: [type("entry_point", (object,), {"load": lambda: object})]
)
plugins = config_utils.load_events_plugins(["one", "two"])
assert len(plugins) == 2
def test_map_leafs_iterator():
from planetmint import config_utils
mapping = {"a": {"b": {"c": 1}, "d": {"z": 44}}, "b": {"d": 2}, "c": 3}
result = config_utils.map_leafs(lambda x, path: x * 2, mapping)
assert result == {"a": {"b": {"c": 2}, "d": {"z": 88}}, "b": {"d": 4}, "c": 6}
result = config_utils.map_leafs(lambda x, path: path, mapping)
assert result == {
"a": {"b": {"c": ["a", "b", "c"]}, "d": {"z": ["a", "d", "z"]}},
"b": {"d": ["b", "d"]},
"c": ["c"],
}
def test_update_types():
from planetmint import config_utils
raw = {
"a_string": "test",
"an_int": "42",
"a_float": "3.14",
"a_list": "a:b:c",
}
reference = {
"a_string": "test",
"an_int": 42,
"a_float": 3.14,
"a_list": ["a", "b", "c"],
}
result = config_utils.update_types(raw, reference)
assert result == reference
def test_env_config(monkeypatch):
monkeypatch.setattr(
"os.environ", {"PLANETMINT_DATABASE_HOST": "test-host", "PLANETMINT_DATABASE_PORT": "test-port"}
)
from planetmint import config_utils
result = config_utils.env_config({"database": {"host": None, "port": None}})
expected = {"database": {"host": "test-host", "port": "test-port"}}
assert result == expected
@pytest.mark.skip
def test_autoconfigure_read_both_from_file_and_env(
monkeypatch, request
): # TODO Disabled until we create a better config format
return
# constants
DATABASE_HOST = "test-host"
DATABASE_NAME = "test-dbname"
DATABASE_PORT = 4242
DATABASE_BACKEND = request.config.getoption("--database-backend")
SERVER_BIND = "1.2.3.4:56"
WSSERVER_SCHEME = "ws"
WSSERVER_HOST = "1.2.3.4"
WSSERVER_PORT = 57
WSSERVER_ADVERTISED_SCHEME = "wss"
WSSERVER_ADVERTISED_HOST = "a.b.c.d"
WSSERVER_ADVERTISED_PORT = 89
LOG_FILE = "/somewhere/something.log"
file_config = {
"database": {"host": DATABASE_HOST},
"log": {
"level_console": "debug",
},
}
monkeypatch.setattr("planetmint.config_utils.file_config", lambda *args, **kwargs: file_config)
monkeypatch.setattr(
"os.environ",
{
"PLANETMINT_DATABASE_NAME": DATABASE_NAME,
"PLANETMINT_DATABASE_PORT": str(DATABASE_PORT),
"PLANETMINT_DATABASE_BACKEND": DATABASE_BACKEND,
"PLANETMINT_SERVER_BIND": SERVER_BIND,
"PLANETMINT_WSSERVER_SCHEME": WSSERVER_SCHEME,
"PLANETMINT_WSSERVER_HOST": WSSERVER_HOST,
"PLANETMINT_WSSERVER_PORT": WSSERVER_PORT,
"PLANETMINT_WSSERVER_ADVERTISED_SCHEME": WSSERVER_ADVERTISED_SCHEME,
"PLANETMINT_WSSERVER_ADVERTISED_HOST": WSSERVER_ADVERTISED_HOST,
"PLANETMINT_WSSERVER_ADVERTISED_PORT": WSSERVER_ADVERTISED_PORT,
"PLANETMINT_LOG_FILE": LOG_FILE,
"PLANETMINT_LOG_FILE": LOG_FILE,
"PLANETMINT_DATABASE_CA_CERT": "ca_cert",
"PLANETMINT_DATABASE_CRLFILE": "crlfile",
"PLANETMINT_DATABASE_CERTFILE": "certfile",
"PLANETMINT_DATABASE_KEYFILE": "keyfile",
"PLANETMINT_DATABASE_KEYFILE_PASSPHRASE": "passphrase",
},
)
from planetmint import config_utils
from planetmint.log import DEFAULT_LOGGING_CONFIG as log_config
config_utils.autoconfigure()
database_mongodb = {
"backend": "localmongodb",
"host": DATABASE_HOST,
"port": DATABASE_PORT,
"name": DATABASE_NAME,
"connection_timeout": 5000,
"max_tries": 3,
"replicaset": None,
"ssl": False,
"login": None,
"password": None,
"ca_cert": "ca_cert",
"certfile": "certfile",
"keyfile": "keyfile",
"keyfile_passphrase": "passphrase",
"crlfile": "crlfile",
}
assert planetmint.config == {
"CONFIGURED": True,
"server": {
"bind": SERVER_BIND,
"loglevel": "info",
"workers": None,
},
"wsserver": {
"scheme": WSSERVER_SCHEME,
"host": WSSERVER_HOST,
"port": WSSERVER_PORT,
"advertised_scheme": WSSERVER_ADVERTISED_SCHEME,
"advertised_host": WSSERVER_ADVERTISED_HOST,
"advertised_port": WSSERVER_ADVERTISED_PORT,
},
"database": database_mongodb,
"tendermint": {"host": "localhost", "port": 26657, "version": "v0.34.15"},
"log": {
"file": LOG_FILE,
"level_console": "debug",
"error_file": log_config["handlers"]["errors"]["filename"],
"level_console": "debug",
"level_logfile": "info",
"datefmt_console": log_config["formatters"]["console"]["datefmt"],
"datefmt_logfile": log_config["formatters"]["file"]["datefmt"],
"fmt_console": log_config["formatters"]["console"]["format"],
"fmt_logfile": log_config["formatters"]["file"]["format"],
"granular_levels": {},
},
}
def test_autoconfigure_env_precedence(monkeypatch):
file_config = {"database": {"host": "test-host", "name": "planetmint", "port": 28015}}
monkeypatch.setattr("planetmint.config_utils.file_config", lambda *args, **kwargs: file_config)
monkeypatch.setattr(
"os.environ",
{
"PLANETMINT_DATABASE_NAME": "test-dbname",
"PLANETMINT_DATABASE_PORT": 4242,
"PLANETMINT_SERVER_BIND": "localhost:9985",
},
)
from planetmint import config_utils
from planetmint.config import Config
config_utils.autoconfigure()
assert Config().get()["CONFIGURED"]
assert Config().get()["database"]["host"] == "test-host"
assert Config().get()["database"]["name"] == "test-dbname"
assert Config().get()["database"]["port"] == 4242
assert Config().get()["server"]["bind"] == "localhost:9985"
def test_autoconfigure_explicit_file(monkeypatch):
from planetmint import config_utils
def file_config(*args, **kwargs):
raise FileNotFoundError()
monkeypatch.setattr("planetmint.config_utils.file_config", file_config)
with pytest.raises(FileNotFoundError):
config_utils.autoconfigure(filename="autoexec.bat")
def test_update_config(monkeypatch):
from planetmint import config_utils
file_config = {"database": {"host": "test-host", "name": "planetmint", "port": 28015}}
monkeypatch.setattr("planetmint.config_utils.file_config", lambda *args, **kwargs: file_config)
config_utils.autoconfigure(config=file_config)
# update configuration, retaining previous changes
config_utils.update_config({"database": {"port": 28016, "name": "planetmint_other"}})
assert Config().get()["database"]["host"] == "test-host"
assert Config().get()["database"]["name"] == "planetmint_other"
assert Config().get()["database"]["port"] == 28016
def test_file_config():
from planetmint.config_utils import file_config, CONFIG_DEFAULT_PATH
with patch("builtins.open", mock_open(read_data="{}")) as m:
config = file_config()
m.assert_called_once_with(CONFIG_DEFAULT_PATH)
assert config == {}
def test_invalid_file_config():
from planetmint.config_utils import file_config
from transactions.common import exceptions
with patch("builtins.open", mock_open(read_data="{_INVALID_JSON_}")):
with pytest.raises(exceptions.ConfigurationError):
file_config()
def test_write_config():
from planetmint.config_utils import write_config, CONFIG_DEFAULT_PATH
m = mock_open()
with patch("builtins.open", m):
write_config({})
m.assert_called_once_with(CONFIG_DEFAULT_PATH, "w")
handle = m()
handle.write.assert_called_once_with("{}")
@pytest.mark.parametrize(
"env_name,env_value,config_key",
(
("PLANETMINT_DATABASE_BACKEND", "test-backend", "backend"),
("PLANETMINT_DATABASE_HOST", "test-host", "host"),
("PLANETMINT_DATABASE_PORT", 4242, "port"),
("PLANETMINT_DATABASE_NAME", "test-db", "name"),
),
)
def test_database_envs(env_name, env_value, config_key, monkeypatch):
monkeypatch.setattr("os.environ", {env_name: env_value})
planetmint.config_utils.autoconfigure()
expected_config = Config().get()
expected_config["database"][config_key] = env_value
assert planetmint.config == expected_config