test_config.py 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. # This file is part of Radicale Server - Calendar Server
  2. # Copyright © 2019 Unrud <unrud@outlook.com>
  3. #
  4. # This library is free software: you can redistribute it and/or modify
  5. # it under the terms of the GNU General Public License as published by
  6. # the Free Software Foundation, either version 3 of the License, or
  7. # (at your option) any later version.
  8. #
  9. # This library is distributed in the hope that it will be useful,
  10. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. # GNU General Public License for more details.
  13. #
  14. # You should have received a copy of the GNU General Public License
  15. # along with Radicale. If not, see <http://www.gnu.org/licenses/>.
  16. import os
  17. import shutil
  18. import tempfile
  19. from configparser import RawConfigParser
  20. import pytest
  21. from radicale import config
  22. from radicale.tests.helpers import configuration_to_dict
  23. class TestConfig:
  24. """Test the configuration."""
  25. def setup(self):
  26. self.colpath = tempfile.mkdtemp()
  27. def teardown(self):
  28. shutil.rmtree(self.colpath)
  29. def _write_config(self, config_dict, name):
  30. parser = RawConfigParser()
  31. parser.read_dict(config_dict)
  32. config_path = os.path.join(self.colpath, name)
  33. with open(config_path, "w") as f:
  34. parser.write(f)
  35. return config_path
  36. def test_parse_compound_paths(self):
  37. assert len(config.parse_compound_paths()) == 0
  38. assert len(config.parse_compound_paths("")) == 0
  39. assert len(config.parse_compound_paths(None, "")) == 0
  40. assert len(config.parse_compound_paths("config", "")) == 0
  41. assert len(config.parse_compound_paths("config", None)) == 1
  42. assert len(config.parse_compound_paths(os.pathsep.join(["", ""]))) == 0
  43. assert len(config.parse_compound_paths(os.pathsep.join([
  44. "", "config", ""]))) == 1
  45. paths = config.parse_compound_paths(os.pathsep.join([
  46. "config1", "?config2", "config3"]))
  47. assert len(paths) == 3
  48. for i, (name, ignore_if_missing) in enumerate([
  49. ("config1", False), ("config2", True), ("config3", False)]):
  50. assert os.path.isabs(paths[i][0])
  51. assert os.path.basename(paths[i][0]) == name
  52. assert paths[i][1] is ignore_if_missing
  53. def test_load_empty(self):
  54. config_path = self._write_config({}, "config")
  55. config.load([(config_path, False)])
  56. def test_load_full(self):
  57. config_path = self._write_config(
  58. configuration_to_dict(config.load()), "config")
  59. config.load([(config_path, False)])
  60. def test_load_missing(self):
  61. config_path = os.path.join(self.colpath, "does_not_exist")
  62. config.load([(config_path, True)])
  63. with pytest.raises(Exception) as exc_info:
  64. config.load([(config_path, False)])
  65. e = exc_info.value
  66. assert ("Failed to load config file %r" % config_path) in str(e)
  67. def test_load_multiple(self):
  68. config_path1 = self._write_config({
  69. "server": {"hosts": "192.0.2.1:1111"}}, "config1")
  70. config_path2 = self._write_config({
  71. "server": {"max_connections": 1111}}, "config2")
  72. configuration = config.load([(config_path1, False),
  73. (config_path2, False)])
  74. assert len(configuration.get("server", "hosts")) == 1
  75. assert configuration.get("server", "hosts")[0] == ("192.0.2.1", 1111)
  76. assert configuration.get("server", "max_connections") == 1111
  77. def test_copy(self):
  78. configuration1 = config.load()
  79. configuration1.update({"server": {"max_connections": "1111"}}, "test")
  80. configuration2 = configuration1.copy()
  81. configuration2.update({"server": {"max_connections": "1112"}}, "test")
  82. assert configuration1.get("server", "max_connections") == 1111
  83. assert configuration2.get("server", "max_connections") == 1112
  84. def test_invalid_section(self):
  85. configuration = config.load()
  86. with pytest.raises(Exception) as exc_info:
  87. configuration.update({"does_not_exist": {"x": "x"}}, "test")
  88. e = exc_info.value
  89. assert "Invalid section 'does_not_exist'" in str(e)
  90. def test_invalid_option(self):
  91. configuration = config.load()
  92. with pytest.raises(Exception) as exc_info:
  93. configuration.update({"server": {"x": "x"}}, "test")
  94. e = exc_info.value
  95. assert "Invalid option 'x'" in str(e)
  96. assert "section 'server'" in str(e)
  97. def test_invalid_option_plugin(self):
  98. configuration = config.load()
  99. with pytest.raises(Exception) as exc_info:
  100. configuration.update({"auth": {"x": "x"}}, "test")
  101. e = exc_info.value
  102. assert "Invalid option 'x'" in str(e)
  103. assert "section 'auth'" in str(e)
  104. def test_invalid_value(self):
  105. configuration = config.load()
  106. with pytest.raises(Exception) as exc_info:
  107. configuration.update({"server": {"max_connections": "x"}}, "test")
  108. e = exc_info.value
  109. assert "Invalid positive_int" in str(e)
  110. assert "option 'max_connections" in str(e)
  111. assert "section 'server" in str(e)
  112. assert "'x'" in str(e)
  113. def test_internal(self):
  114. configuration = config.load()
  115. configuration.update({"internal": {"internal_server": "True"}}, "test",
  116. internal=True)
  117. with pytest.raises(Exception) as exc_info:
  118. configuration.update(
  119. {"internal": {"internal_server": "True"}}, "test")
  120. e = exc_info.value
  121. assert "Invalid section 'internal'" in str(e)
  122. def test_plugin_schema(self):
  123. PLUGIN_SCHEMA = {"auth": {"new_option": {"value": "False",
  124. "type": bool}}}
  125. configuration = config.load()
  126. configuration.update({"auth": {"type": "new_plugin"}}, "test")
  127. plugin_configuration = configuration.copy(PLUGIN_SCHEMA)
  128. assert plugin_configuration.get("auth", "new_option") is False
  129. configuration.update({"auth": {"new_option": "True"}}, "test")
  130. plugin_configuration = configuration.copy(PLUGIN_SCHEMA)
  131. assert plugin_configuration.get("auth", "new_option") is True
  132. def test_plugin_schema_duplicate_option(self):
  133. PLUGIN_SCHEMA = {"auth": {"type": {"value": "False",
  134. "type": bool}}}
  135. configuration = config.load()
  136. with pytest.raises(Exception) as exc_info:
  137. configuration.copy(PLUGIN_SCHEMA)
  138. e = exc_info.value
  139. assert "option already exists in 'auth': 'type'" in str(e)
  140. def test_plugin_schema_invalid(self):
  141. PLUGIN_SCHEMA = {"server": {"new_option": {"value": "False",
  142. "type": bool}}}
  143. configuration = config.load()
  144. with pytest.raises(Exception) as exc_info:
  145. configuration.copy(PLUGIN_SCHEMA)
  146. e = exc_info.value
  147. assert "not a plugin section: 'server" in str(e)
  148. def test_plugin_schema_option_invalid(self):
  149. PLUGIN_SCHEMA = {"auth": {}}
  150. configuration = config.load()
  151. configuration.update({"auth": {"type": "new_plugin",
  152. "new_option": False}}, "test")
  153. with pytest.raises(Exception) as exc_info:
  154. configuration.copy(PLUGIN_SCHEMA)
  155. e = exc_info.value
  156. assert "Invalid option 'new_option'" in str(e)
  157. assert "section 'auth'" in str(e)