Add helper functions to set up config file fixtures.
[dput.git] / test / test_configfile.py
blobd84fb5a5dbcd853d67bc52c3044830f7a9ef1fe7
1 # -*- coding: utf-8; -*-
3 # test/test_configfile.py
4 # Part of ‘dput’, a Debian package upload toolkit.
6 # Copyright © 2015 Ben Finney <ben+python@benfinney.id.au>
8 # This is free software: you may copy, modify, and/or distribute this work
9 # under the terms of the GNU General Public License as published by the
10 # Free Software Foundation; version 3 of that license or any later version.
12 """ Unit tests for config file behaviour. """
14 from __future__ import (absolute_import, unicode_literals)
16 import sys
17 import os
18 import os.path
19 import tempfile
20 import textwrap
22 __package__ = str("test")
23 __import__(__package__)
24 sys.path.insert(1, os.path.dirname(os.path.dirname(__file__)))
25 import dput.dput
27 from .helper import (
28 builtins,
29 StringIO,
30 configparser,
31 mock,
32 FileDouble,
33 setup_file_double_behaviour,
37 def make_config_from_stream(stream):
38 """ Make a ConfigParser parsed configuration from the stream content.
40 :param stream: Text stream content of a config file.
41 :return: The resulting config if the content parses correctly,
42 or ``None``.
44 """
45 config = configparser.ConfigParser(
46 defaults={
47 'allow_unsigned_uploads': "false",
51 config_file = StringIO(stream)
52 try:
53 config.readfp(config_file)
54 except configparser.ParsingError:
55 config = None
57 return config
60 def make_config_file_scenarios():
61 """ Make a collection of scenarios for testing with config files.
63 :return: A collection of scenarios for tests involving config files.
65 The collection is a mapping from scenario name to a dictionary of
66 scenario attributes.
68 """
70 runtime_config_file_path = tempfile.mktemp()
71 global_config_file_path = os.path.join(os.path.sep, "etc", "dput.cf")
72 user_config_file_path = os.path.join(os.path.expanduser("~"), ".dput.cf")
74 fake_file_empty = StringIO()
75 fake_file_bogus = StringIO("b0gUs")
76 fake_file_minimal = StringIO(textwrap.dedent("""\
77 [DEFAULT]
78 """))
79 fake_file_simple = StringIO(textwrap.dedent("""\
80 [DEFAULT]
81 hash = md5
82 [foo]
83 method = ftp
84 fqdn = quux.example.com
85 incoming = quux
86 check_version = false
87 allow_unsigned_uploads = false
88 allowed_distributions =
89 """))
90 fake_file_method_local = StringIO(textwrap.dedent("""\
91 [foo]
92 method = local
93 incoming = quux
94 """))
95 fake_file_missing_fqdn = StringIO(textwrap.dedent("""\
96 [foo]
97 method = ftp
98 incoming = quux
99 """))
100 fake_file_missing_incoming = StringIO(textwrap.dedent("""\
101 [foo]
102 method = ftp
103 fqdn = quux.example.com
104 """))
106 default_scenario_params = {
107 'runtime': {
108 'file_double_params': dict(
109 path=runtime_config_file_path,
110 fake_file=fake_file_minimal),
111 'open_scenario_name': 'okay',
113 'global': {
114 'file_double_params': dict(
115 path=global_config_file_path,
116 fake_file=fake_file_minimal),
117 'open_scenario_name': 'okay',
119 'user': {
120 'file_double_params': dict(
121 path=user_config_file_path,
122 fake_file=fake_file_minimal),
123 'open_scenario_name': 'okay',
127 scenarios = {
128 'default': {
129 'configs_by_name': {
130 'runtime': None,
133 'not-exist': {
134 'configs_by_name': {
135 'runtime': {
136 'open_scenario_name': 'nonexist',
140 'exist-read-denied': {
141 'configs_by_name': {
142 'runtime': {
143 'open_scenario_name': 'read_denied',
147 'exist-empty': {
148 'configs_by_name': {
149 'runtime': {
150 'file_double_params': dict(
151 path=runtime_config_file_path,
152 fake_file=fake_file_empty),
156 'exist-invalid': {
157 'configs_by_name': {
158 'runtime': {
159 'file_double_params': dict(
160 path=runtime_config_file_path,
161 fake_file=fake_file_bogus),
165 'exist-minimal': {},
166 'exist-simple': {
167 'configs_by_name': {
168 'runtime': {
169 'file_double_params': dict(
170 path=runtime_config_file_path,
171 fake_file=fake_file_simple),
172 'test_section': "foo",
176 'exist-method-local': {
177 'configs_by_name': {
178 'runtime': {
179 'file_double_params': dict(
180 path=runtime_config_file_path,
181 fake_file=fake_file_method_local),
182 'test_section': "foo",
186 'exist-missing-fqdn': {
187 'configs_by_name': {
188 'runtime': {
189 'file_double_params': dict(
190 path=runtime_config_file_path,
191 fake_file=fake_file_missing_fqdn),
195 'exist-missing-incoming': {
196 'configs_by_name': {
197 'runtime': {
198 'file_double_params': dict(
199 path=runtime_config_file_path,
200 fake_file=fake_file_missing_incoming),
204 'global-config-not-exist': {
205 'configs_by_name': {
206 'global': {
207 'open_scenario_name': 'nonexist',
209 'runtime': None,
212 'global-config-read-denied': {
213 'configs_by_name': {
214 'global': {
215 'open_scenario_name': 'read_denied',
217 'runtime': None,
220 'user-config-not-exist': {
221 'configs_by_name': {
222 'user': {
223 'open_scenario_name': 'nonexist',
225 'runtime': None,
228 'all-not-exist': {
229 'configs_by_name': {
230 'global': {
231 'open_scenario_name': 'nonexist',
233 'user': {
234 'open_scenario_name': 'nonexist',
236 'runtime': None,
241 for scenario in scenarios.values():
242 scenario['empty_file'] = fake_file_empty
243 if 'configs_by_name' not in scenario:
244 scenario['configs_by_name'] = {}
245 for (config_name, default_params) in default_scenario_params.items():
246 if config_name not in scenario['configs_by_name']:
247 params = default_params
248 elif scenario['configs_by_name'][config_name] is None:
249 continue
250 else:
251 params = default_params.copy()
252 params.update(scenario['configs_by_name'][config_name])
253 params['file_double'] = FileDouble(**params['file_double_params'])
254 params['file_double'].set_open_scenario(
255 params['open_scenario_name'])
256 params['config'] = make_config_from_stream(
257 params['file_double'].fake_file.getvalue())
258 scenario['configs_by_name'][config_name] = params
260 return scenarios
263 def get_file_doubles_from_config_file_scenarios(scenarios):
264 """ Get the `FileDouble` instances from config file scenarios.
266 :param scenarios: Collection of config file scenarios.
267 :return: Collection of `FileDouble` instances.
270 doubles = set()
271 for scenario in scenarios:
272 configs_by_name = scenario['configs_by_name']
273 doubles.update(
274 configs_by_name[config_name]['file_double']
275 for config_name in ['global', 'user', 'runtime']
276 if configs_by_name[config_name] is not None)
278 return doubles
281 def setup_config_file_fixtures(testcase):
282 """ Set up fixtures for config file doubles. """
284 scenarios = make_config_file_scenarios()
285 testcase.config_file_scenarios = scenarios
287 setup_file_double_behaviour(
288 testcase,
289 get_file_doubles_from_config_file_scenarios(scenarios.values()))
292 # Local variables:
293 # coding: utf-8
294 # mode: python
295 # End:
296 # vim: fileencoding=utf-8 filetype=python :