1
|
|
|
# |
2
|
|
|
# Copyright (C) 2013 Satoru SATOH <ssato @ redhat.com> |
3
|
|
|
# License: MIT |
4
|
|
|
# |
5
|
|
|
# pylint: disable=missing-docstring, invalid-name, too-many-public-methods |
6
|
|
|
from __future__ import absolute_import |
7
|
|
|
|
8
|
|
|
import os |
9
|
|
|
import os.path |
10
|
|
|
import unittest |
11
|
|
|
|
12
|
|
|
import anyconfig.cli as TT |
13
|
|
|
import anyconfig.api |
14
|
|
|
import anyconfig.template |
15
|
|
|
import tests.common |
16
|
|
|
import tests.api |
17
|
|
|
|
18
|
|
|
from tests.common import CNF_0 |
19
|
|
|
|
20
|
|
|
|
21
|
|
|
CNF_0_PATH = os.path.join(tests.common.selfdir(), "00-cnf.yml") |
22
|
|
|
SCM_0_PATH = os.path.join(tests.common.selfdir(), "00-scm.yml") |
23
|
|
|
CNF_TMPL_0 = tests.api.CNF_TMPL_1 |
24
|
|
|
|
25
|
|
|
|
26
|
|
|
def _run(*args): |
27
|
|
|
TT.main(["dummy"] + list(args)) |
28
|
|
|
|
29
|
|
|
|
30
|
|
|
class Test_00(unittest.TestCase): |
31
|
|
|
""" |
32
|
|
|
|
33
|
|
|
>>> psr = TT.make_parser() |
34
|
|
|
>>> assert isinstance(psr, TT.argparse.ArgumentParser) |
35
|
|
|
>>> psr.parse_args([]) # doctest: +NORMALIZE_WHITESPACE |
36
|
|
|
Namespace(args=None, atype=None, env=False, gen_schema=False, get=None, |
37
|
|
|
ignore_missing=False, inputs=[], itype=None, list=False, |
38
|
|
|
loglevel=0, merge='merge_dicts', otype=None, output=None, |
39
|
|
|
query=None, schema=None, set=None, template=False, |
40
|
|
|
validate=False) |
41
|
|
|
""" |
42
|
|
|
|
43
|
|
|
|
44
|
|
|
class RunTestBase(unittest.TestCase): |
45
|
|
|
|
46
|
|
|
def run_and_check_exit_code(self, args=None, code=0, _not=False, |
47
|
|
|
exc_cls=SystemExit): |
48
|
|
|
try: |
49
|
|
|
TT.main(["dummy"] + ([] if args is None else args)) |
50
|
|
|
except exc_cls as exc: |
51
|
|
|
ecode = getattr(exc, "code", 1) |
52
|
|
|
(self.assertNotEqual if _not else self.assertEqual)(ecode, code) |
53
|
|
|
|
54
|
|
|
|
55
|
|
|
class Test_10(RunTestBase): |
56
|
|
|
infile = os.path.join(tests.common.selfdir(), "00-cnf.json") |
57
|
|
|
|
58
|
|
|
def test_10_show_usage(self): |
59
|
|
|
self.run_and_check_exit_code(["--help"]) |
60
|
|
|
|
61
|
|
|
def test_20_wo_args(self): |
62
|
|
|
self.run_and_check_exit_code(_not=True) |
63
|
|
|
|
64
|
|
|
def test_30_wrong_option(self): |
65
|
|
|
self.run_and_check_exit_code(["--wrong-option-xyz"], _not=True) |
66
|
|
|
|
67
|
|
|
def test_40_list(self): |
68
|
|
|
self.run_and_check_exit_code(["--list"]) |
69
|
|
|
|
70
|
|
View Code Duplication |
def test_50_unknown_input_file_type(self): |
|
|
|
|
71
|
|
|
self.run_and_check_exit_code([__file__], _not=True) |
72
|
|
|
|
73
|
|
|
def test_52_unknown_input_parser_type(self): |
74
|
|
|
self.run_and_check_exit_code([__file__, "-I", "unknown_psr"], |
75
|
|
|
_not=True) |
76
|
|
|
|
77
|
|
|
def test_54_no_input_type_and_unknown_out_file_type(self): |
78
|
|
|
self.run_and_check_exit_code([__file__, __file__ + '.un_ext'], |
79
|
|
|
_not=True) |
80
|
|
|
|
81
|
|
|
def test_60_unknown_out_file_type(self): |
82
|
|
|
self.run_and_check_exit_code([self.infile, "-o", "t.unknown_ext"], |
83
|
|
|
_not=True) |
84
|
|
|
|
85
|
|
|
def test_62_unknown_out_parser_type(self): |
86
|
|
|
self.run_and_check_exit_code([self.infile, "-O", "unknown_psr"], |
87
|
|
|
_not=True) |
88
|
|
|
|
89
|
|
|
|
90
|
|
|
class Test_20_Base(RunTestBase): |
91
|
|
|
|
92
|
|
View Code Duplication |
def setUp(self): |
|
|
|
|
93
|
|
|
self.workdir = tests.common.setup_workdir() |
94
|
|
|
self.script = os.path.join(tests.common.selfdir(), |
95
|
|
|
"..", "cli.py") |
96
|
|
|
|
97
|
|
|
def tearDown(self): |
98
|
|
|
tests.common.cleanup_workdir(self.workdir) |
99
|
|
|
|
100
|
|
|
def _assert_run_and_exit(self, *args): |
101
|
|
|
raised = False |
102
|
|
|
try: |
103
|
|
|
_run(*args) |
104
|
|
|
except SystemExit: |
105
|
|
|
raised = True |
106
|
|
|
|
107
|
|
View Code Duplication |
self.assertTrue(raised) |
|
|
|
|
108
|
|
|
|
109
|
|
|
|
110
|
|
|
class Test_30_single_input(Test_20_Base): |
111
|
|
|
|
112
|
|
|
def test_10(self): |
113
|
|
|
a = dict(name="a", a=1, b=dict(b=[1, 2], c="C")) |
114
|
|
|
|
115
|
|
|
infile = os.path.join(self.workdir, "a.json") |
116
|
|
|
output = os.path.join(self.workdir, "b.json") |
117
|
|
|
|
118
|
|
|
anyconfig.api.dump(a, infile) |
119
|
|
|
self.assertTrue(os.path.exists(infile)) |
120
|
|
|
|
121
|
|
|
TT.main(["dummy", "-o", output, infile]) |
122
|
|
|
self.assertTrue(os.path.exists(output)) |
123
|
|
|
|
124
|
|
|
def test_20_wo_input_type(self): |
125
|
|
|
self._assert_run_and_exit("a.conf") |
126
|
|
|
|
127
|
|
|
def test_30_w_get_option(self): |
128
|
|
|
d = dict(name="a", a=dict(b=dict(c=[1, 2], d="C"))) |
129
|
|
|
|
130
|
|
View Code Duplication |
infile = os.path.join(self.workdir, "a.json") |
|
|
|
|
131
|
|
|
output = os.path.join(self.workdir, "b.json") |
132
|
|
|
|
133
|
|
|
anyconfig.api.dump(d, infile) |
134
|
|
|
self.assertTrue(os.path.exists(infile)) |
135
|
|
|
|
136
|
|
|
TT.main(["dummy", "-o", output, "--get", "a.b", infile]) |
137
|
|
|
self.assertTrue(os.path.exists(output)) |
138
|
|
|
|
139
|
|
|
x = anyconfig.api.load(output) |
140
|
|
|
self.assertEqual(x, d['a']['b']) |
141
|
|
|
|
142
|
|
|
def test_31_w_get_option_failure(self): |
143
|
|
|
(key, no_get_q) = ('a', "wrong_key_0.wrong_key_1") |
144
|
|
|
infile = os.path.join(self.workdir, "a.json") |
145
|
|
|
anyconfig.api.dump({key: "A"}, infile) |
146
|
|
|
self.assertTrue(os.path.exists(infile)) |
147
|
|
|
|
148
|
|
|
self.run_and_check_exit_code(["--get", no_get_q, infile], 1) |
149
|
|
|
|
150
|
|
|
def test_32_w_set_option(self): |
151
|
|
|
d = dict(name="a", a=dict(b=dict(c=[1, 2], d="C"))) |
152
|
|
|
|
153
|
|
|
infile = os.path.join(self.workdir, "a.json") |
154
|
|
|
output = os.path.join(self.workdir, "b.json") |
155
|
|
|
|
156
|
|
|
anyconfig.api.dump(d, infile) |
157
|
|
|
self.assertTrue(os.path.exists(infile)) |
158
|
|
|
|
159
|
|
|
TT.main(["dummy", "-o", output, "--set", "a.b.d=E", infile]) |
160
|
|
|
self.assertTrue(os.path.exists(output)) |
161
|
|
|
|
162
|
|
|
ref = d.copy() |
163
|
|
|
ref['a']['b']['d'] = 'E' |
164
|
|
|
|
165
|
|
|
x = anyconfig.api.load(output) |
166
|
|
|
self.assertEqual(x, ref) |
167
|
|
|
|
168
|
|
|
def test_40_ignore_missing(self): |
169
|
|
|
infile = os.path.join(os.curdir, "conf_file_should_not_exist.json") |
170
|
|
|
assert not os.path.exists(infile) |
171
|
|
|
|
172
|
|
|
self.assertFalse(TT.main(["dummy", "-O", "json", |
173
|
|
View Code Duplication |
"--ignore-missing", infile])) |
|
|
|
|
174
|
|
|
|
175
|
|
|
def test_50_w_schema(self): |
176
|
|
|
(infile, scmfile) = (CNF_0_PATH, SCM_0_PATH) |
177
|
|
|
output = os.path.join(self.workdir, "output.json") |
178
|
|
|
self.run_and_check_exit_code(["--schema", scmfile, "--validate", |
179
|
|
|
infile], 0) |
180
|
|
|
self.run_and_check_exit_code(["--schema", scmfile, "-o", output, |
181
|
|
|
infile], 0) |
182
|
|
|
|
183
|
|
|
infile2 = os.path.join(self.workdir, "input.yml") |
184
|
|
|
cnf = CNF_0.copy() |
185
|
|
|
cnf["a"] = "aaa" # Validation should fail. |
186
|
|
|
anyconfig.api.dump(cnf, infile2) |
187
|
|
|
self.run_and_check_exit_code(["--schema", scmfile, "--validate", |
188
|
|
|
infile2], 1) |
189
|
|
|
|
190
|
|
|
def test_52_wo_schema(self): |
191
|
|
|
self.run_and_check_exit_code(["--validate", CNF_0_PATH], 1) |
192
|
|
|
|
193
|
|
|
def test_54_gen_schema_and_validate_with_it(self): |
194
|
|
|
cnf = dict(name="a", a=1, b=dict(b=[1, 2], c="C")) |
195
|
|
|
infile = os.path.join(self.workdir, "cnf.json") |
196
|
|
|
output = os.path.join(self.workdir, "out.yml") |
197
|
|
|
anyconfig.api.dump(cnf, infile) |
198
|
|
|
|
199
|
|
|
self.run_and_check_exit_code(["--gen-schema", "-o", output, infile], 0) |
200
|
|
|
self.assertTrue(os.path.exists(output)) |
201
|
|
|
self.run_and_check_exit_code(["--schema", output, "--validate", |
202
|
|
|
infile], 0) |
203
|
|
|
|
204
|
|
|
def test_60_w_arg_option(self): |
205
|
|
|
a = dict(name="a", a=1, b=dict(b=[1, 2], c="C"), d=[1, 2]) |
206
|
|
|
|
207
|
|
|
infile = os.path.join(self.workdir, "a.json") |
208
|
|
|
output = os.path.join(self.workdir, "b.json") |
209
|
|
|
|
210
|
|
|
anyconfig.api.dump(a, infile) |
211
|
|
|
self.assertTrue(os.path.exists(infile)) |
212
|
|
|
|
213
|
|
|
TT.main(["dummy", "-o", output, "-A", |
214
|
|
|
"a:10;name:x;d:3,4", infile]) |
215
|
|
|
self.assertTrue(os.path.exists(output)) |
216
|
|
|
|
217
|
|
|
x = anyconfig.api.load(output) |
218
|
|
|
|
219
|
|
|
self.assertNotEqual(a["name"], x["name"]) |
220
|
|
|
self.assertNotEqual(a["a"], x["a"]) |
221
|
|
|
self.assertNotEqual(a["d"], x["d"]) |
222
|
|
|
|
223
|
|
|
self.assertEqual(x["name"], 'x') |
224
|
|
|
self.assertEqual(x["a"], 10) |
225
|
|
|
self.assertEqual(x["d"], [3, 4]) |
226
|
|
|
|
227
|
|
|
def test_70_no_template(self): |
228
|
|
|
a = dict(name="a", a=1, b=dict(b=[1, 2], c="C")) |
229
|
|
|
|
230
|
|
|
infile = os.path.join(self.workdir, "a.json") |
231
|
|
|
output = os.path.join(self.workdir, "b.json") |
232
|
|
|
|
233
|
|
|
anyconfig.api.dump(a, infile) |
234
|
|
|
self.assertTrue(os.path.exists(infile)) |
235
|
|
|
|
236
|
|
|
TT.main(["dummy", "-o", output, infile]) |
237
|
|
|
self.assertTrue(os.path.exists(output)) |
238
|
|
|
|
239
|
|
|
|
240
|
|
|
class Test_40_multi_inputs(Test_20_Base): |
241
|
|
|
|
242
|
|
|
def test_10(self): |
243
|
|
|
xs = [dict(a=1, ), |
244
|
|
|
dict(b=dict(b=[1, 2], c="C")), ] |
245
|
|
|
|
246
|
|
|
a = xs[0].copy() |
247
|
|
|
a.update(xs[1]) |
248
|
|
|
|
249
|
|
|
output = os.path.join(self.workdir, "b.json") |
250
|
|
|
|
251
|
|
|
inputs = [] |
252
|
|
|
for i in [0, 1]: |
253
|
|
|
infile = os.path.join(self.workdir, "a%d.json" % i) |
254
|
|
|
inputs.append(infile) |
255
|
|
|
|
256
|
|
|
anyconfig.api.dump(xs[i], infile) |
257
|
|
|
self.assertTrue(os.path.exists(infile)) |
258
|
|
|
|
259
|
|
|
TT.main(["dummy", "-o", output] + inputs) |
260
|
|
|
self.assertTrue(os.path.exists(output)) |
261
|
|
|
|
262
|
|
|
def test_20_w_template(self): |
263
|
|
|
if not anyconfig.template.SUPPORTED: |
264
|
|
|
return |
265
|
|
|
|
266
|
|
|
a = dict(name="a", a=1, b=dict(b=[1, 2], c="C")) |
267
|
|
|
|
268
|
|
|
inputsdir = os.path.join(self.workdir, "in") |
269
|
|
|
os.makedirs(inputsdir) |
270
|
|
|
|
271
|
|
|
anyconfig.api.dump(a, os.path.join(inputsdir, "a0.yml")) |
272
|
|
|
open(os.path.join(inputsdir, "a1.yml"), 'w').write(CNF_TMPL_0) |
273
|
|
|
output = os.path.join(self.workdir, "b.json") |
274
|
|
|
|
275
|
|
|
TT.main(["dummy", "--template", "-o", output, |
276
|
|
|
os.path.join(inputsdir, "*.yml")]) |
277
|
|
|
self.assertTrue(os.path.exists(output)) |
278
|
|
|
|
279
|
|
|
def test_30_w_template(self): |
280
|
|
|
if not anyconfig.template.SUPPORTED: |
281
|
|
|
return |
282
|
|
|
|
283
|
|
|
curdir = tests.common.selfdir() |
284
|
|
|
|
285
|
|
|
infile = os.path.join(curdir, "*template-c*.yml") |
286
|
|
|
output = os.path.join(self.workdir, "output.yml") |
287
|
|
|
|
288
|
|
|
TT.main(["dummy", "--template", "-o", output, infile]) |
289
|
|
|
|
290
|
|
|
|
291
|
|
|
class Test_50_others_w_input(Test_20_Base): |
292
|
|
|
|
293
|
|
|
def setUp(self): |
294
|
|
|
super(Test_50_others_w_input, self).setUp() |
295
|
|
|
dic = dict(name="a", a=1, b=dict(b=[1, 2], c="C"), d=[1, 2]) |
296
|
|
|
self.infile = os.path.join(self.workdir, "a.json") |
297
|
|
|
anyconfig.api.dump(dic, self.infile) |
298
|
|
|
|
299
|
|
|
def test_10_output_wo_output_option_w_otype(self): |
300
|
|
|
self.run_and_check_exit_code(["--otype", "json", self.infile]) |
301
|
|
|
|
302
|
|
|
def test_12_output_wo_output_option_and_otype_w_itype(self): |
303
|
|
|
self.run_and_check_exit_code(["--itype", "json", self.infile]) |
304
|
|
|
|
305
|
|
|
def test_20_no_out_dumper(self): |
306
|
|
|
outfile = os.path.join(self.workdir, "out.conf") |
307
|
|
|
self.run_and_check_exit_code(["-o", outfile, self.infile], 1) |
308
|
|
|
|
309
|
|
|
def test_22_no_out_dumper_nor_itype(self): |
310
|
|
|
infile = self.infile.replace(".json", ".conf") |
311
|
|
|
outfile = os.path.join(self.workdir, "out.conf") |
312
|
|
|
self.run_and_check_exit_code(["-o", outfile, infile], 1) |
313
|
|
|
|
314
|
|
|
def test_30_w_query_option(self): |
315
|
|
|
self.run_and_check_exit_code(["-Q", "b.b[::-1]", self.infile], 0) |
316
|
|
|
|
317
|
|
|
|
318
|
|
|
class Test_50_others_wo_input(Test_20_Base): |
319
|
|
|
|
320
|
|
|
def test_30_no_itype_and_otype(self): |
321
|
|
|
outfile = os.path.join(self.workdir, "out.conf") |
322
|
|
|
self.run_and_check_exit_code(["-o", outfile, "in.conf"], 1) |
323
|
|
|
|
324
|
|
|
def test_40_no_inputs__w_env_option(self): |
325
|
|
|
output = os.path.join(self.workdir, "out.json") |
326
|
|
|
self.run_and_check_exit_code(["--env", "-o", output], 0) |
327
|
|
|
data = anyconfig.api.load(output) |
328
|
|
|
|
329
|
|
|
for env_var, env_val in os.environ.items(): |
330
|
|
|
self.assertTrue(env_var in data) |
331
|
|
|
self.assertEqual(env_val, os.environ[env_var]) |
332
|
|
|
|
333
|
|
|
# vim:sw=4:ts=4:et: |
334
|
|
|
|