6a40c18c30237abb11bd2a9e1c4114120b7d2646
[utils.git] / src / budget_sync / test / test_config.py
1 import unittest
2 import io
3 from budget_sync.config import Config, ConfigParseError
4
5
6 class TestConfig(unittest.TestCase):
7 def test_config_parsing(self):
8 def check_error(text: str, expected_error_text: str):
9 with self.assertRaises(ConfigParseError) as e:
10 Config.from_str(text)
11 self.assertEqual(str(e.exception), expected_error_text)
12
13 def check(text: str, expected_repr_text: str):
14 self.assertEqual(repr(Config.from_str(text)), expected_repr_text)
15
16 check_error(
17 "bad-toml=",
18 "TOML parse error: Empty value is invalid "
19 "(line 1 column 1 char 0)")
20 check_error(
21 """
22 """,
23 "`bugzilla_url` field is missing")
24 check_error(
25 """
26 [bugzilla_url]
27 """,
28 "`bugzilla_url` must be a string")
29 check_error(
30 """
31 bugzilla_url = ""
32 """,
33 "`people` table is missing")
34 check_error(
35 """
36 blah = ""
37 """,
38 "unknown config entry: `blah`")
39 check_error(
40 """
41 bugzilla_url = ""
42 people = []
43 """,
44 "`people` field must be a table")
45 check_error(
46 """
47 bugzilla_url = ""
48 [people]
49 person1 = 1
50 """,
51 "person entry for 'person1' must be a table")
52 check_error(
53 """
54 bugzilla_url = ""
55 [people."person1"]
56 aliases = ""
57 """,
58 "`aliases` field in person entry for 'person1' must be a list "
59 "of strings")
60 check_error(
61 """
62 bugzilla_url = ""
63 [people."person1"]
64 aliases = [1]
65 """,
66 "`aliases` field in person entry for 'person1' must be a list "
67 "of strings")
68 check_error(
69 """
70 bugzilla_url = ""
71 [people."person1"]
72 aliases = ["a", "a"]
73 """,
74 "duplicate alias in person entry for 'person1': 'a'")
75 check_error(
76 """
77 bugzilla_url = ""
78 [people]
79 """,
80 "`milestones` table is missing")
81 check_error(
82 """
83 bugzilla_url = ""
84 [people."person1"]
85 """,
86 "`output_markdown_file` field is missing in person entry for "
87 "'person1'")
88 check_error(
89 """
90 bugzilla_url = ""
91 [people."person1"]
92 output_markdown_file = 1
93 """,
94 "`output_markdown_file` field in person entry for 'person1' must "
95 "be a string")
96 check(
97 """
98 bugzilla_url = ""
99 [milestones]
100 [people."person1"]
101 aliases = ["a"]
102 output_markdown_file = "person1.mdwn"
103 [people."person2"]
104 aliases = ["b"]
105 output_markdown_file = "person2.mdwn"
106 """,
107 "Config(bugzilla_url='', people={"
108 "'person1': Person(config=..., identifier='person1', "
109 "output_markdown_file='person1.mdwn', "
110 "aliases={'a'}, email=None), "
111 "'person2': Person(config=..., identifier='person2', "
112 "output_markdown_file='person2.mdwn', "
113 "aliases={'b'}, email=None)}, milestones={})")
114 check_error(
115 """
116 bugzilla_url = ""
117 [people."person1"]
118 email = 123
119 output_markdown_file = "person1.mdwn"
120 """,
121 "`email` field in person entry for 'person1' must be a string")
122 check(
123 """
124 bugzilla_url = ""
125 [people]
126 [milestones]
127 """,
128 "Config(bugzilla_url='', people={}, milestones={})")
129 check(
130 """
131 bugzilla_url = ""
132 [milestones]
133 [people."person1"]
134 email = "email@example.com"
135 output_markdown_file = "person1.mdwn"
136 """,
137 "Config(bugzilla_url='', people={"
138 "'person1': Person(config=..., identifier='person1', "
139 "output_markdown_file='person1.mdwn', "
140 "aliases=set(), email='email@example.com')}, milestones={})")
141 check_error(
142 """
143 bugzilla_url = ""
144 [people."person1"]
145 blah = 123
146 output_markdown_file = "person1.mdwn"
147 """,
148 "unknown field in person entry for 'person1': `blah`")
149 check_error(
150 """
151 bugzilla_url = ""
152 [milestones]
153 [people."person1"]
154 output_markdown_file = "person1.mdwn"
155 [people."person2"]
156 aliases = ["person1"]
157 output_markdown_file = "person2.mdwn"
158 """,
159 "alias is not allowed to be the same as any person's identifier: "
160 "in person entry for 'person2': 'person1' is also the identifier "
161 "for person 'person1'")
162 check_error(
163 """
164 bugzilla_url = ""
165 [milestones]
166 [people."person1"]
167 output_markdown_file = "person1.mdwn"
168 aliases = ["a"]
169 [people."person2"]
170 aliases = ["a"]
171 output_markdown_file = "person2.mdwn"
172 """,
173 "alias is not allowed to be the same as another person's alias: "
174 "in person entry for 'person2': 'a' is also an alias for person "
175 "'person1'")
176 check_error(
177 """
178 bugzilla_url = ""
179 [milestones]
180 "abc" = 1
181 [people]
182 """,
183 "milestones entry for 'abc' must be a table")
184 check_error(
185 """
186 bugzilla_url = ""
187 [milestones]
188 "abc" = { canonical_bug_id = "abc" }
189 [people]
190 """,
191 "`canonical_bug_id` field in milestones entry for 'abc' must "
192 "be an integer")
193 check_error(
194 """
195 bugzilla_url = ""
196 [milestones]
197 "abc" = { blah = "def" }
198 [people]
199 """,
200 "unknown field in milestones entry for 'abc': `blah`")
201 check_error(
202 """
203 bugzilla_url = ""
204 [milestones]
205 "abc" = {}
206 [people]
207 """,
208 "`canonical_bug_id` field is missing in milestones entry for 'abc'")
209 check_error(
210 """
211 bugzilla_url = ""
212 milestones = 1
213 [people]
214 """,
215 "`milestones` field must be a table")
216 check_error(
217 """
218 bugzilla_url = ""
219 [milestones]
220 "abc" = { canonical_bug_id = 1 }
221 "def" = { canonical_bug_id = 1 }
222 [people]
223 """,
224 "canonical_bug_id is not allowed to be the same as another "
225 "milestone's canonical_bug_id: in milestone entry for 'def': "
226 "1 is also the canonical_bug_id for milestone 'abc'")
227
228 def test_all_names(self):
229 config = Config.from_str(
230 """
231 bugzilla_url = ""
232 [milestones]
233 [people."person1"]
234 aliases = ["person1_alias1", "alias1"]
235 output_markdown_file = "person1.mdwn"
236 [people."person2"]
237 aliases = ["person2_alias2", "alias2"]
238 output_markdown_file = "person2.mdwn"
239 """)
240 person1 = config.people['person1']
241 person2 = config.people['person2']
242 self.assertEqual(config.all_names,
243 {
244 'person1': person1,
245 'person1_alias1': person1,
246 'alias1': person1,
247 'person2': person2,
248 'person2_alias2': person2,
249 'alias2': person2,
250 })
251
252 def test_canonical_bug_ids(self):
253 config = Config.from_str(
254 """
255 bugzilla_url = ""
256 [people]
257 [milestones]
258 "Milestone 1" = { canonical_bug_id = 1 }
259 "Milestone 2" = { canonical_bug_id = 2 }
260 """)
261 milestone1 = config.milestones['Milestone 1']
262 milestone2 = config.milestones['Milestone 2']
263 self.assertEqual(config.canonical_bug_ids,
264 {
265 1: milestone1,
266 2: milestone2,
267 })
268
269 def test_bugzilla_url_stripped(self):
270 c = Config.from_str(
271 """
272 bugzilla_url = "https://bugzilla.example.com/prefix"
273 [people]
274 [milestones]
275 """
276 )
277 self.assertEqual(c.bugzilla_url_stripped,
278 "https://bugzilla.example.com/prefix")
279 c = Config.from_str(
280 """
281 bugzilla_url = "https://bugzilla.example.com/prefix/"
282 [people]
283 [milestones]
284 """
285 )
286 self.assertEqual(c.bugzilla_url_stripped,
287 "https://bugzilla.example.com/prefix")
288 c = Config.from_str(
289 """
290 bugzilla_url = "https://bugzilla.example.com/"
291 [people]
292 [milestones]
293 """
294 )
295 self.assertEqual(c.bugzilla_url_stripped,
296 "https://bugzilla.example.com")
297
298 def test_from_file(self):
299 def load(text):
300 with io.StringIO(text) as file:
301 return Config.from_file(file)
302
303 with self.assertRaisesRegex(TypeError,
304 "^list is not a valid file or path$"):
305 Config.from_file([])
306
307 with self.assertRaisesRegex(
308 ConfigParseError,
309 "^TOML parse error: Empty value is invalid"):
310 load("""bad-toml=""")
311
312 self.assertEqual(str(load(
313 """
314 bugzilla_url = "https://bugzilla.example.com/"
315 [people."person1"]
316 email = "person1@example.com"
317 aliases = ["alias1"]
318 output_markdown_file = "person1.mdwn"
319 [milestones]
320 "Milestone 1" = { canonical_bug_id = 123 }
321 """)),
322 "Config(bugzilla_url='https://bugzilla.example.com/', "
323 "people={'person1': Person(config=..., identifier='person1', "
324 "output_markdown_file='person1.mdwn', "
325 "aliases={'alias1'}, email='person1@example.com')}, "
326 "milestones={'Milestone 1': Milestone(config=..., "
327 "identifier='Milestone 1', canonical_bug_id=123)})")
328
329
330 if __name__ == "__main__":
331 unittest.main()