create tests for config
This commit is contained in:
parent
687afe32ef
commit
bc3f6ac452
6 changed files with 471 additions and 96 deletions
|
@ -7,7 +7,11 @@ from typing import Any, List, Optional
|
||||||
import pytimeparse
|
import pytimeparse
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
from matrix_alertbot.errors import ConfigError
|
from matrix_alertbot.errors import (
|
||||||
|
InvalidConfigError,
|
||||||
|
ParseConfigError,
|
||||||
|
RequiredConfigKeyError,
|
||||||
|
)
|
||||||
|
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
logging.getLogger("peewee").setLevel(
|
logging.getLogger("peewee").setLevel(
|
||||||
|
@ -21,7 +25,7 @@ class Config:
|
||||||
def __init__(self, filepath: str):
|
def __init__(self, filepath: str):
|
||||||
self.filepath = filepath
|
self.filepath = filepath
|
||||||
if not os.path.isfile(filepath):
|
if not os.path.isfile(filepath):
|
||||||
raise ConfigError(f"Config file '{filepath}' does not exist")
|
raise ParseConfigError(f"Config file '{filepath}' does not exist")
|
||||||
|
|
||||||
# Load in the config file at the given filepath
|
# Load in the config file at the given filepath
|
||||||
with open(filepath) as file_stream:
|
with open(filepath) as file_stream:
|
||||||
|
@ -44,7 +48,7 @@ class Config:
|
||||||
["logging", "file_logging", "enabled"], default=False
|
["logging", "file_logging", "enabled"], default=False
|
||||||
)
|
)
|
||||||
file_logging_filepath = self._get_cfg(
|
file_logging_filepath = self._get_cfg(
|
||||||
["logging", "file_logging", "filepath"], default="bot.log"
|
["logging", "file_logging", "filepath"], default="matrix-alertbot.log"
|
||||||
)
|
)
|
||||||
if file_logging_enabled:
|
if file_logging_enabled:
|
||||||
file_handler = logging.FileHandler(file_logging_filepath)
|
file_handler = logging.FileHandler(file_logging_filepath)
|
||||||
|
@ -60,67 +64,77 @@ class Config:
|
||||||
logger.addHandler(console_handler)
|
logger.addHandler(console_handler)
|
||||||
|
|
||||||
# Storage setup
|
# Storage setup
|
||||||
self.store_path = self._get_cfg(["storage", "store_path"], required=True)
|
self.store_dir: str = self._get_cfg(["storage", "path"], required=True)
|
||||||
|
|
||||||
# Create the store folder if it doesn't exist
|
# Create the store folder if it doesn't exist
|
||||||
if not os.path.isdir(self.store_path):
|
if not os.path.isdir(self.store_dir):
|
||||||
if not os.path.exists(self.store_path):
|
if not os.path.exists(self.store_dir):
|
||||||
os.mkdir(self.store_path)
|
os.mkdir(self.store_dir)
|
||||||
else:
|
else:
|
||||||
raise ConfigError(
|
raise InvalidConfigError(
|
||||||
f"storage.store_path '{self.store_path}' is not a directory"
|
f"storage.path '{self.store_dir}' is not a directory"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Cache setup
|
# Cache setup
|
||||||
self.cache_dir = self._get_cfg(["cache", "directory"], required=True)
|
self.cache_dir: str = self._get_cfg(["cache", "path"], required=True)
|
||||||
expire_time = self._get_cfg(["cache", "expire_time"], default="1w")
|
expire_time: str = self._get_cfg(["cache", "expire_time"], default="1w")
|
||||||
self.cache_expire_time = pytimeparse.parse(expire_time)
|
self.cache_expire_time = pytimeparse.parse(expire_time)
|
||||||
|
|
||||||
# Alertmanager client setup
|
# Alertmanager client setup
|
||||||
self.alertmanager_url = self._get_cfg(["alertmanager", "url"], required=True)
|
self.alertmanager_url: str = self._get_cfg(
|
||||||
|
["alertmanager", "url"], required=True
|
||||||
|
)
|
||||||
|
|
||||||
# Matrix bot account setup
|
# Matrix bot account setup
|
||||||
self.user_id = self._get_cfg(["matrix", "user_id"], required=True)
|
self.user_id: str = self._get_cfg(["matrix", "user_id"], required=True)
|
||||||
if not re.match("@.*:.*", self.user_id):
|
if not re.match("@.+:.+", self.user_id):
|
||||||
raise ConfigError("matrix.user_id must be in the form @name:domain")
|
raise InvalidConfigError("matrix.user_id must be in the form @name:domain")
|
||||||
|
|
||||||
self.user_password = self._get_cfg(["matrix", "user_password"], required=False)
|
self.user_password: str = self._get_cfg(
|
||||||
self.user_token = self._get_cfg(["matrix", "user_token"], required=False)
|
["matrix", "user_password"], required=False
|
||||||
if not self.user_token and not self.user_password:
|
|
||||||
raise ConfigError("Must supply either user token or password")
|
|
||||||
|
|
||||||
self.device_id = self._get_cfg(["matrix", "device_id"], required=True)
|
|
||||||
self.device_name = self._get_cfg(
|
|
||||||
["matrix", "device_name"], default="nio-template"
|
|
||||||
)
|
)
|
||||||
self.homeserver_url = self._get_cfg(["matrix", "url"], required=True)
|
self.user_token: str = self._get_cfg(["matrix", "user_token"], required=False)
|
||||||
self.room_id = self._get_cfg(["matrix", "room"], required=True)
|
if not self.user_token and not self.user_password:
|
||||||
|
raise RequiredConfigKeyError("Must supply either user token or password")
|
||||||
|
|
||||||
self.address = self._get_cfg(["webhook", "address"], required=False)
|
self.device_id: str = self._get_cfg(["matrix", "device_id"], required=True)
|
||||||
self.port = self._get_cfg(["webhook", "port"], required=False)
|
self.device_name: str = self._get_cfg(
|
||||||
self.socket = self._get_cfg(["webhook", "socket"], required=False)
|
["matrix", "device_name"], default="matrix-alertbot"
|
||||||
|
)
|
||||||
|
self.homeserver_url: str = self._get_cfg(["matrix", "url"], required=True)
|
||||||
|
self.room_id: str = self._get_cfg(["matrix", "room"], required=True)
|
||||||
|
|
||||||
|
self.address: str = self._get_cfg(["webhook", "address"], required=False)
|
||||||
|
self.port: int = self._get_cfg(["webhook", "port"], required=False)
|
||||||
|
self.socket: str = self._get_cfg(["webhook", "socket"], required=False)
|
||||||
if (
|
if (
|
||||||
not (self.address or self.port or self.socket)
|
not (self.address or self.port or self.socket)
|
||||||
or (self.socket and self.address and self.port)
|
|
||||||
or (self.address and not self.port)
|
or (self.address and not self.port)
|
||||||
or (not self.address and self.port)
|
or (not self.address and self.port)
|
||||||
):
|
):
|
||||||
raise ConfigError(
|
raise RequiredConfigKeyError(
|
||||||
"Must supply either webhook.socket or both webhook.address and webhook.port"
|
"Must supply either webhook.socket or both webhook.address and webhook.port"
|
||||||
)
|
)
|
||||||
self.command_prefix = self._get_cfg(["command_prefix"], default="!c") + " "
|
elif self.socket and self.address and self.port:
|
||||||
|
raise InvalidConfigError(
|
||||||
|
"Supplied both webhook.socket and both webhook.address"
|
||||||
|
)
|
||||||
|
|
||||||
|
self.command_prefix: str = (
|
||||||
|
self._get_cfg(["command_prefix"], default="!alert") + " "
|
||||||
|
)
|
||||||
|
|
||||||
def _get_cfg(
|
def _get_cfg(
|
||||||
self,
|
self,
|
||||||
path: List[str],
|
path: List[str],
|
||||||
default: Optional[Any] = None,
|
default: Optional[Any] = None,
|
||||||
required: Optional[bool] = True,
|
required: bool = True,
|
||||||
) -> Any:
|
) -> Any:
|
||||||
"""Get a config option from a path and option name, specifying whether it is
|
"""Get a config option from a path and option name, specifying whether it is
|
||||||
required.
|
required.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
ConfigError: If required is True and the object is not found (and there is
|
RequiredConfigKeyError: If required is True and the object is not found (and there is
|
||||||
no default value provided), a ConfigError will be raised.
|
no default value provided), a ConfigError will be raised.
|
||||||
"""
|
"""
|
||||||
# Sift through the the config until we reach our option
|
# Sift through the the config until we reach our option
|
||||||
|
@ -131,8 +145,10 @@ class Config:
|
||||||
# If at any point we don't get our expected option...
|
# If at any point we don't get our expected option...
|
||||||
if config is None:
|
if config is None:
|
||||||
# Raise an error if it was required
|
# Raise an error if it was required
|
||||||
if required and not default:
|
if required and default is None:
|
||||||
raise ConfigError(f"Config option {'.'.join(path)} is required")
|
raise RequiredConfigKeyError(
|
||||||
|
f"Config option {'.'.join(path)} is required"
|
||||||
|
)
|
||||||
|
|
||||||
# or return the default value
|
# or return the default value
|
||||||
return default
|
return default
|
||||||
|
|
|
@ -7,6 +7,24 @@ class ConfigError(Exception):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ParseConfigError(ConfigError):
|
||||||
|
"""An error encountered when config file cannot be parsed."""
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class InvalidConfigError(ParseConfigError):
|
||||||
|
"""An error encountered when a config key is not valid."""
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class RequiredConfigKeyError(ConfigError):
|
||||||
|
"""An error encountered when a required config key is missing."""
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class AlertmanagerError(Exception):
|
class AlertmanagerError(Exception):
|
||||||
"""An error encountered with Alertmanager."""
|
"""An error encountered with Alertmanager."""
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ def create_matrix_client(config: Config) -> AsyncClient:
|
||||||
config.homeserver_url,
|
config.homeserver_url,
|
||||||
config.user_id,
|
config.user_id,
|
||||||
device_id=config.device_id,
|
device_id=config.device_id,
|
||||||
store_path=config.store_path,
|
store_path=config.store_dir,
|
||||||
config=client_config,
|
config=client_config,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
54
tests/resources/config/config.full.yml
Normal file
54
tests/resources/config/config.full.yml
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
# Welcome to the sample config file
|
||||||
|
# Below you will find various config sections and options
|
||||||
|
# Default values are shown
|
||||||
|
|
||||||
|
# The string to prefix messages with to talk to the bot in group chats
|
||||||
|
command_prefix: "!alert"
|
||||||
|
|
||||||
|
# Options for connecting to the bot's Matrix account
|
||||||
|
matrix:
|
||||||
|
# The Matrix User ID of the bot account
|
||||||
|
user_id: "@fakes_user:matrix.example.com"
|
||||||
|
# Matrix account password (optional if access token used)
|
||||||
|
user_password: "password"
|
||||||
|
# Matrix account access token (optional if password used)
|
||||||
|
#user_token: ""
|
||||||
|
# The URL of the homeserver to connect to
|
||||||
|
url: https://matrix.example.com
|
||||||
|
# The device ID that is **non pre-existing** device
|
||||||
|
# If this device ID already exists, messages will be dropped silently in encrypted rooms
|
||||||
|
device_id: ABCDEFGHIJ
|
||||||
|
# What to name the logged in device
|
||||||
|
device_name: fake_device_name
|
||||||
|
room: "!abcdefgh:matrix.example.com"
|
||||||
|
|
||||||
|
webhook:
|
||||||
|
socket: matrix-alertbot.socket
|
||||||
|
|
||||||
|
alertmanager:
|
||||||
|
url: http://localhost:9093
|
||||||
|
|
||||||
|
cache:
|
||||||
|
# The path to a directory for caching alerts and silences
|
||||||
|
path: "data/cache"
|
||||||
|
|
||||||
|
storage:
|
||||||
|
# The path to a directory for internal bot storage
|
||||||
|
# containing encryption keys, sync tokens, etc.
|
||||||
|
path: "data/store"
|
||||||
|
|
||||||
|
# Logging setup
|
||||||
|
logging:
|
||||||
|
# Logging level
|
||||||
|
# Allowed levels are 'INFO', 'WARNING', 'ERROR', 'DEBUG' where DEBUG is most verbose
|
||||||
|
level: DEBUG
|
||||||
|
# Configure logging to a file
|
||||||
|
file_logging:
|
||||||
|
# Whether logging to a file is enabled
|
||||||
|
enabled: true
|
||||||
|
# The path to the file to log to. May be relative or absolute
|
||||||
|
filepath: fake.log
|
||||||
|
# Configure logging to the console output
|
||||||
|
console_logging:
|
||||||
|
# Whether logging to the console is enabled
|
||||||
|
enabled: false
|
34
tests/resources/config/config.minimal.yml
Normal file
34
tests/resources/config/config.minimal.yml
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
# Welcome to the sample config file
|
||||||
|
# Below you will find various config sections and options
|
||||||
|
# Default values are shown
|
||||||
|
|
||||||
|
# Options for connecting to the bot's Matrix account
|
||||||
|
matrix:
|
||||||
|
# The Matrix User ID of the bot account
|
||||||
|
user_id: "@fakes_user:matrix.example.com"
|
||||||
|
# Matrix account password (optional if access token used)
|
||||||
|
user_password: "password"
|
||||||
|
# Matrix account access token (optional if password used)
|
||||||
|
#user_token: ""
|
||||||
|
# The URL of the homeserver to connect to
|
||||||
|
url: https://matrix.example.com
|
||||||
|
# The device ID that is **non pre-existing** device
|
||||||
|
# If this device ID already exists, messages will be dropped silently in encrypted rooms
|
||||||
|
device_id: ABCDEFGHIJ
|
||||||
|
room: "!abcdefgh:matrix.example.com"
|
||||||
|
|
||||||
|
webhook:
|
||||||
|
address: 0.0.0.0
|
||||||
|
port: 8080
|
||||||
|
|
||||||
|
alertmanager:
|
||||||
|
url: http://localhost:9093
|
||||||
|
|
||||||
|
cache:
|
||||||
|
# The path to a directory for caching alerts and silences
|
||||||
|
path: "data/cache"
|
||||||
|
|
||||||
|
storage:
|
||||||
|
# The path to a directory for internal bot storage
|
||||||
|
# containing encryption keys, sync tokens, etc.
|
||||||
|
path: "data/store"
|
|
@ -1,80 +1,333 @@
|
||||||
|
import os
|
||||||
import unittest
|
import unittest
|
||||||
from unittest.mock import Mock
|
from datetime import timedelta
|
||||||
|
from unittest.mock import Mock, patch
|
||||||
|
|
||||||
|
import yaml
|
||||||
|
|
||||||
from matrix_alertbot.config import Config
|
from matrix_alertbot.config import Config
|
||||||
from matrix_alertbot.errors import ConfigError
|
from matrix_alertbot.errors import (
|
||||||
|
ConfigError,
|
||||||
|
InvalidConfigError,
|
||||||
|
ParseConfigError,
|
||||||
|
RequiredConfigKeyError,
|
||||||
|
)
|
||||||
|
|
||||||
|
WORKING_DIR = os.path.dirname(__file__)
|
||||||
|
CONFIG_RESOURCES_DIR = os.path.join(WORKING_DIR, "resources", "config")
|
||||||
|
|
||||||
|
|
||||||
|
class DummyConfig(Config):
|
||||||
|
def __init__(self, filepath: str):
|
||||||
|
with open(filepath) as file_stream:
|
||||||
|
self.config_dict = yaml.safe_load(file_stream.read())
|
||||||
|
|
||||||
|
|
||||||
|
def mock_path_isdir(path: str) -> bool:
|
||||||
|
if path == "data/store":
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def mock_path_exists(path: str) -> bool:
|
||||||
|
if path == "data/store":
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
class ConfigTestCase(unittest.TestCase):
|
class ConfigTestCase(unittest.TestCase):
|
||||||
def test_get_cfg(self) -> None:
|
@patch("os.path.isdir")
|
||||||
"""Test that Config._get_cfg works correctly"""
|
@patch("os.path.exists")
|
||||||
|
@patch("os.mkdir")
|
||||||
|
def test_read_minimal_config(
|
||||||
|
self, fake_mkdir: Mock, fake_path_exists: Mock, fake_path_isdir: Mock
|
||||||
|
) -> None:
|
||||||
|
fake_path_isdir.return_value = False
|
||||||
|
fake_path_exists.return_value = False
|
||||||
|
|
||||||
# Here's our test dictionary. Pretend that this was parsed from a YAML config file.
|
config_path = os.path.join(CONFIG_RESOURCES_DIR, "config.minimal.yml")
|
||||||
test_config_dict = {"a_key": 5, "some_key": {"some_other_key": "some_value"}}
|
config = Config(config_path)
|
||||||
|
|
||||||
# We create a fake config using Mock. _get_cfg will attempt to pull from self.config_dict,
|
fake_path_isdir.assert_called_once_with("data/store")
|
||||||
# so we use a Mock to quickly create a dummy class, and set the 'config_dict' attribute to
|
fake_path_exists.assert_called_once_with("data/store")
|
||||||
# our test dictionary.
|
fake_mkdir.assert_called_once_with("data/store")
|
||||||
fake_config = Mock()
|
|
||||||
fake_config.config_dict = test_config_dict
|
|
||||||
|
|
||||||
# Now let's make some calls to Config._get_cfg. We provide 'fake_cfg' as the first argument
|
self.assertEqual("@fakes_user:matrix.example.com", config.user_id)
|
||||||
# as a substitute for 'self'. _get_cfg will then be pulling values from fake_cfg.config_dict.
|
self.assertEqual("password", config.user_password)
|
||||||
|
self.assertIsNone(config.user_token)
|
||||||
|
self.assertEqual("ABCDEFGHIJ", config.device_id)
|
||||||
|
self.assertEqual("matrix-alertbot", config.device_name)
|
||||||
|
self.assertEqual("https://matrix.example.com", config.homeserver_url)
|
||||||
|
self.assertEqual("!abcdefgh:matrix.example.com", config.room_id)
|
||||||
|
|
||||||
# Test that we can get the value of a top-level key
|
self.assertEqual("0.0.0.0", config.address)
|
||||||
self.assertEqual(
|
self.assertEqual(8080, config.port)
|
||||||
Config._get_cfg(fake_config, ["a_key"]),
|
self.assertIsNone(config.socket)
|
||||||
5,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Test that we can get the value of a nested key
|
self.assertEqual("http://localhost:9093", config.alertmanager_url)
|
||||||
self.assertEqual(
|
|
||||||
Config._get_cfg(fake_config, ["some_key", "some_other_key"]),
|
|
||||||
"some_value",
|
|
||||||
)
|
|
||||||
|
|
||||||
# Test that the value provided by the default option is used when a key does not exist
|
expected_expire_time = timedelta(days=7).total_seconds()
|
||||||
self.assertEqual(
|
self.assertEqual(expected_expire_time, config.cache_expire_time)
|
||||||
Config._get_cfg(
|
self.assertEqual("data/cache", config.cache_dir)
|
||||||
fake_config,
|
|
||||||
["a_made_up_key", "this_does_not_exist"],
|
|
||||||
default="The default",
|
|
||||||
),
|
|
||||||
"The default",
|
|
||||||
)
|
|
||||||
|
|
||||||
# Test that the value provided by the default option is *not* used when a key *does* exist
|
self.assertEqual("data/store", config.store_dir)
|
||||||
self.assertEqual(
|
|
||||||
Config._get_cfg(fake_config, ["a_key"], default="The default"),
|
|
||||||
5,
|
|
||||||
)
|
|
||||||
|
|
||||||
# Test that keys that do not exist raise a ConfigError when the required argument is True
|
self.assertEqual("!alert ", config.command_prefix)
|
||||||
with self.assertRaises(ConfigError):
|
|
||||||
Config._get_cfg(
|
|
||||||
fake_config, ["a_made_up_key", "this_does_not_exist"], required=True
|
|
||||||
)
|
|
||||||
|
|
||||||
# Test that a ConfigError is not returned when a non-existent key is provided and required is False
|
@patch("os.path.isdir")
|
||||||
self.assertIsNone(
|
@patch("os.path.exists")
|
||||||
Config._get_cfg(
|
@patch("os.mkdir")
|
||||||
fake_config, ["a_made_up_key", "this_does_not_exist"], required=False
|
def test_read_full_config(
|
||||||
)
|
self, fake_mkdir: Mock, fake_path_exists: Mock, fake_path_isdir: Mock
|
||||||
)
|
) -> None:
|
||||||
|
fake_path_isdir.return_value = False
|
||||||
|
fake_path_exists.return_value = False
|
||||||
|
|
||||||
# Test that default is used for non-existent keys, even if required is True
|
config_path = os.path.join(CONFIG_RESOURCES_DIR, "config.full.yml")
|
||||||
# (Typically one shouldn't use a default with required=True anyways...)
|
config = Config(config_path)
|
||||||
self.assertEqual(
|
|
||||||
Config._get_cfg(
|
|
||||||
fake_config,
|
|
||||||
["a_made_up_key", "this_does_not_exist"],
|
|
||||||
default="something",
|
|
||||||
required=True,
|
|
||||||
),
|
|
||||||
"something",
|
|
||||||
)
|
|
||||||
|
|
||||||
# TODO: Test creating a test yaml file, passing the path to Config and _parse_config_values is called correctly
|
fake_path_isdir.assert_called_once_with("data/store")
|
||||||
|
fake_path_exists.assert_called_once_with("data/store")
|
||||||
|
fake_mkdir.assert_called_once_with("data/store")
|
||||||
|
|
||||||
|
self.assertEqual("@fakes_user:matrix.example.com", config.user_id)
|
||||||
|
self.assertEqual("password", config.user_password)
|
||||||
|
self.assertIsNone(config.user_token)
|
||||||
|
self.assertEqual("ABCDEFGHIJ", config.device_id)
|
||||||
|
self.assertEqual("fake_device_name", config.device_name)
|
||||||
|
self.assertEqual("https://matrix.example.com", config.homeserver_url)
|
||||||
|
self.assertEqual("!abcdefgh:matrix.example.com", config.room_id)
|
||||||
|
|
||||||
|
self.assertIsNone(config.address)
|
||||||
|
self.assertIsNone(config.port)
|
||||||
|
self.assertEqual("matrix-alertbot.socket", config.socket)
|
||||||
|
|
||||||
|
self.assertEqual("http://localhost:9093", config.alertmanager_url)
|
||||||
|
|
||||||
|
expected_expire_time = timedelta(days=7).total_seconds()
|
||||||
|
self.assertEqual(expected_expire_time, config.cache_expire_time)
|
||||||
|
self.assertEqual("data/cache", config.cache_dir)
|
||||||
|
|
||||||
|
self.assertEqual("data/store", config.store_dir)
|
||||||
|
|
||||||
|
self.assertEqual("!alert ", config.command_prefix)
|
||||||
|
|
||||||
|
def test_read_config_raise_config_error(self) -> None:
|
||||||
|
with self.assertRaises(ParseConfigError):
|
||||||
|
Config("")
|
||||||
|
|
||||||
|
@patch("os.path.isdir")
|
||||||
|
@patch("os.path.exists")
|
||||||
|
@patch("os.mkdir")
|
||||||
|
def test_parse_config_with_storage_path_error(
|
||||||
|
self, fake_mkdir: Mock, fake_path_exists: Mock, fake_path_isdir: Mock
|
||||||
|
) -> None:
|
||||||
|
fake_path_isdir.return_value = False
|
||||||
|
fake_path_exists.return_value = True
|
||||||
|
|
||||||
|
config_path = os.path.join(CONFIG_RESOURCES_DIR, "config.minimal.yml")
|
||||||
|
with self.assertRaises(ParseConfigError):
|
||||||
|
Config(config_path)
|
||||||
|
|
||||||
|
fake_path_isdir.assert_called_once_with("data/store")
|
||||||
|
fake_path_exists.assert_called_once_with("data/store")
|
||||||
|
fake_mkdir.assert_not_called()
|
||||||
|
|
||||||
|
@patch("os.path.isdir")
|
||||||
|
@patch("os.path.exists")
|
||||||
|
@patch("os.mkdir")
|
||||||
|
def test_parse_config_with_missing_matrix_user_id(
|
||||||
|
self, fake_mkdir: Mock, fake_path_exists: Mock, fake_path_isdir: Mock
|
||||||
|
) -> None:
|
||||||
|
fake_path_isdir.return_value = False
|
||||||
|
fake_path_exists.return_value = False
|
||||||
|
|
||||||
|
config_path = os.path.join(CONFIG_RESOURCES_DIR, "config.minimal.yml")
|
||||||
|
config = DummyConfig(config_path)
|
||||||
|
del config.config_dict["matrix"]["user_id"]
|
||||||
|
|
||||||
|
with self.assertRaises(RequiredConfigKeyError):
|
||||||
|
config._parse_config_values()
|
||||||
|
|
||||||
|
@patch("os.path.isdir")
|
||||||
|
@patch("os.path.exists")
|
||||||
|
@patch("os.mkdir")
|
||||||
|
def test_parse_config_with_missing_matrix_user_password(
|
||||||
|
self, fake_mkdir: Mock, fake_path_exists: Mock, fake_path_isdir: Mock
|
||||||
|
) -> None:
|
||||||
|
fake_path_isdir.return_value = False
|
||||||
|
fake_path_exists.return_value = False
|
||||||
|
|
||||||
|
config_path = os.path.join(CONFIG_RESOURCES_DIR, "config.minimal.yml")
|
||||||
|
config = DummyConfig(config_path)
|
||||||
|
del config.config_dict["matrix"]["user_password"]
|
||||||
|
|
||||||
|
with self.assertRaises(RequiredConfigKeyError):
|
||||||
|
config._parse_config_values()
|
||||||
|
|
||||||
|
@patch("os.path.isdir")
|
||||||
|
@patch("os.path.exists")
|
||||||
|
@patch("os.mkdir")
|
||||||
|
def test_parse_config_with_missing_matrix_device_id(
|
||||||
|
self, fake_mkdir: Mock, fake_path_exists: Mock, fake_path_isdir: Mock
|
||||||
|
) -> None:
|
||||||
|
fake_path_isdir.return_value = False
|
||||||
|
fake_path_exists.return_value = False
|
||||||
|
|
||||||
|
config_path = os.path.join(CONFIG_RESOURCES_DIR, "config.minimal.yml")
|
||||||
|
config = DummyConfig(config_path)
|
||||||
|
del config.config_dict["matrix"]["device_id"]
|
||||||
|
|
||||||
|
with self.assertRaises(RequiredConfigKeyError):
|
||||||
|
config._parse_config_values()
|
||||||
|
|
||||||
|
@patch("os.path.isdir")
|
||||||
|
@patch("os.path.exists")
|
||||||
|
@patch("os.mkdir")
|
||||||
|
def test_parse_config_with_missing_matrix_url(
|
||||||
|
self, fake_mkdir: Mock, fake_path_exists: Mock, fake_path_isdir: Mock
|
||||||
|
) -> None:
|
||||||
|
fake_path_isdir.return_value = False
|
||||||
|
fake_path_exists.return_value = False
|
||||||
|
|
||||||
|
config_path = os.path.join(CONFIG_RESOURCES_DIR, "config.minimal.yml")
|
||||||
|
config = DummyConfig(config_path)
|
||||||
|
del config.config_dict["matrix"]["url"]
|
||||||
|
|
||||||
|
with self.assertRaises(RequiredConfigKeyError):
|
||||||
|
config._parse_config_values()
|
||||||
|
|
||||||
|
@patch("os.path.isdir")
|
||||||
|
@patch("os.path.exists")
|
||||||
|
@patch("os.mkdir")
|
||||||
|
def test_parse_config_with_missing_matrix_room(
|
||||||
|
self, fake_mkdir: Mock, fake_path_exists: Mock, fake_path_isdir: Mock
|
||||||
|
) -> None:
|
||||||
|
fake_path_isdir.return_value = False
|
||||||
|
fake_path_exists.return_value = False
|
||||||
|
|
||||||
|
config_path = os.path.join(CONFIG_RESOURCES_DIR, "config.minimal.yml")
|
||||||
|
config = DummyConfig(config_path)
|
||||||
|
del config.config_dict["matrix"]["room"]
|
||||||
|
|
||||||
|
with self.assertRaises(RequiredConfigKeyError):
|
||||||
|
config._parse_config_values()
|
||||||
|
|
||||||
|
@patch("os.path.isdir")
|
||||||
|
@patch("os.path.exists")
|
||||||
|
@patch("os.mkdir")
|
||||||
|
def test_parse_config_with_missing_webhook_address(
|
||||||
|
self, fake_mkdir: Mock, fake_path_exists: Mock, fake_path_isdir: Mock
|
||||||
|
) -> None:
|
||||||
|
fake_path_isdir.return_value = False
|
||||||
|
fake_path_exists.return_value = False
|
||||||
|
|
||||||
|
config_path = os.path.join(CONFIG_RESOURCES_DIR, "config.minimal.yml")
|
||||||
|
config = DummyConfig(config_path)
|
||||||
|
del config.config_dict["webhook"]["address"]
|
||||||
|
|
||||||
|
with self.assertRaises(RequiredConfigKeyError):
|
||||||
|
config._parse_config_values()
|
||||||
|
|
||||||
|
@patch("os.path.isdir")
|
||||||
|
@patch("os.path.exists")
|
||||||
|
@patch("os.mkdir")
|
||||||
|
def test_parse_config_with_missing_alertmanager_url(
|
||||||
|
self, fake_mkdir: Mock, fake_path_exists: Mock, fake_path_isdir: Mock
|
||||||
|
) -> None:
|
||||||
|
fake_path_isdir.return_value = False
|
||||||
|
fake_path_exists.return_value = False
|
||||||
|
|
||||||
|
config_path = os.path.join(CONFIG_RESOURCES_DIR, "config.minimal.yml")
|
||||||
|
config = DummyConfig(config_path)
|
||||||
|
del config.config_dict["alertmanager"]["url"]
|
||||||
|
|
||||||
|
with self.assertRaises(RequiredConfigKeyError):
|
||||||
|
config._parse_config_values()
|
||||||
|
|
||||||
|
@patch("os.path.isdir")
|
||||||
|
@patch("os.path.exists")
|
||||||
|
@patch("os.mkdir")
|
||||||
|
def test_parse_config_with_missing_cache_path(
|
||||||
|
self, fake_mkdir: Mock, fake_path_exists: Mock, fake_path_isdir: Mock
|
||||||
|
) -> None:
|
||||||
|
fake_path_isdir.return_value = False
|
||||||
|
fake_path_exists.return_value = False
|
||||||
|
|
||||||
|
config_path = os.path.join(CONFIG_RESOURCES_DIR, "config.minimal.yml")
|
||||||
|
config = DummyConfig(config_path)
|
||||||
|
del config.config_dict["cache"]["path"]
|
||||||
|
|
||||||
|
with self.assertRaises(RequiredConfigKeyError):
|
||||||
|
config._parse_config_values()
|
||||||
|
|
||||||
|
@patch("os.path.isdir")
|
||||||
|
@patch("os.path.exists")
|
||||||
|
@patch("os.mkdir")
|
||||||
|
def test_parse_config_with_missing_storage_path(
|
||||||
|
self, fake_mkdir: Mock, fake_path_exists: Mock, fake_path_isdir: Mock
|
||||||
|
) -> None:
|
||||||
|
fake_path_isdir.return_value = False
|
||||||
|
fake_path_exists.return_value = False
|
||||||
|
|
||||||
|
config_path = os.path.join(CONFIG_RESOURCES_DIR, "config.minimal.yml")
|
||||||
|
config = DummyConfig(config_path)
|
||||||
|
del config.config_dict["storage"]["path"]
|
||||||
|
|
||||||
|
with self.assertRaises(RequiredConfigKeyError):
|
||||||
|
config._parse_config_values()
|
||||||
|
|
||||||
|
@patch("os.path.isdir")
|
||||||
|
@patch("os.path.exists")
|
||||||
|
@patch("os.mkdir")
|
||||||
|
def test_parse_config_with_invalid_matrix_user_id(
|
||||||
|
self, fake_mkdir: Mock, fake_path_exists: Mock, fake_path_isdir: Mock
|
||||||
|
) -> None:
|
||||||
|
fake_path_isdir.return_value = False
|
||||||
|
fake_path_exists.return_value = False
|
||||||
|
|
||||||
|
config_path = os.path.join(CONFIG_RESOURCES_DIR, "config.minimal.yml")
|
||||||
|
config = DummyConfig(config_path)
|
||||||
|
|
||||||
|
config.config_dict["matrix"]["user_id"] = ""
|
||||||
|
with self.assertRaises(InvalidConfigError):
|
||||||
|
config._parse_config_values()
|
||||||
|
|
||||||
|
config.config_dict["matrix"]["user_id"] = "@fake_user"
|
||||||
|
with self.assertRaises(InvalidConfigError):
|
||||||
|
config._parse_config_values()
|
||||||
|
|
||||||
|
config.config_dict["matrix"]["user_id"] = "@fake_user:"
|
||||||
|
with self.assertRaises(InvalidConfigError):
|
||||||
|
config._parse_config_values()
|
||||||
|
|
||||||
|
config.config_dict["matrix"]["user_id"] = ":matrix.example.com"
|
||||||
|
with self.assertRaises(InvalidConfigError):
|
||||||
|
config._parse_config_values()
|
||||||
|
|
||||||
|
config.config_dict["matrix"]["user_id"] = "@:matrix.example.com"
|
||||||
|
with self.assertRaises(InvalidConfigError):
|
||||||
|
config._parse_config_values()
|
||||||
|
|
||||||
|
config.config_dict["matrix"]["user_id"] = "@:"
|
||||||
|
with self.assertRaises(InvalidConfigError):
|
||||||
|
config._parse_config_values()
|
||||||
|
|
||||||
|
@patch("os.path.isdir")
|
||||||
|
@patch("os.path.exists")
|
||||||
|
@patch("os.mkdir")
|
||||||
|
def test_parse_config_with_both_webhook_socket_and_address(
|
||||||
|
self, fake_mkdir: Mock, fake_path_exists: Mock, fake_path_isdir: Mock
|
||||||
|
) -> None:
|
||||||
|
fake_path_isdir.return_value = False
|
||||||
|
fake_path_exists.return_value = False
|
||||||
|
|
||||||
|
config_path = os.path.join(CONFIG_RESOURCES_DIR, "config.minimal.yml")
|
||||||
|
config = DummyConfig(config_path)
|
||||||
|
config.config_dict["webhook"]["socket"] = "matrix-alertbot.socket"
|
||||||
|
|
||||||
|
with self.assertRaises(InvalidConfigError):
|
||||||
|
config._parse_config_values()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
Loading…
Reference in a new issue