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", "--silent"] + 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=1, 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", "--silent"] + ([] 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
|
|
View Code Duplication |
|
|
|
|
|
57
|
|
|
def test_10_show_usage(self): |
58
|
|
|
self.run_and_check_exit_code(["--help"]) |
59
|
|
|
|
60
|
|
|
def test_20_wo_args(self): |
61
|
|
|
self.run_and_check_exit_code(_not=True) |
62
|
|
|
|
63
|
|
|
def test_30_wrong_option(self): |
64
|
|
|
self.run_and_check_exit_code(["--wrong-option-xyz"], _not=True) |
65
|
|
|
|
66
|
|
|
def test_40_list(self): |
67
|
|
|
self.run_and_check_exit_code(["--list"]) |
68
|
|
|
|
69
|
|
|
|
70
|
|
|
class Test_20_Base(RunTestBase): |
71
|
|
|
|
72
|
|
|
def setUp(self): |
73
|
|
|
self.workdir = tests.common.setup_workdir() |
74
|
|
|
self.script = os.path.join(tests.common.selfdir(), |
75
|
|
|
"..", "cli.py") |
76
|
|
|
|
77
|
|
|
def tearDown(self): |
78
|
|
|
tests.common.cleanup_workdir(self.workdir) |
79
|
|
|
|
80
|
|
|
def _assert_run_and_exit(self, *args): |
81
|
|
|
raised = False |
82
|
|
|
try: |
83
|
|
|
_run(*args) |
84
|
|
|
except SystemExit: |
85
|
|
|
raised = True |
86
|
|
|
|
87
|
|
|
self.assertTrue(raised) |
88
|
|
|
|
89
|
|
|
|
90
|
|
|
class Test_30_single_input(Test_20_Base): |
91
|
|
|
|
92
|
|
|
def test_10(self): |
93
|
|
View Code Duplication |
a = dict(name="a", a=1, b=dict(b=[1, 2], c="C")) |
|
|
|
|
94
|
|
|
|
95
|
|
|
infile = os.path.join(self.workdir, "a.json") |
96
|
|
|
output = os.path.join(self.workdir, "b.json") |
97
|
|
|
|
98
|
|
|
anyconfig.api.dump(a, infile) |
99
|
|
|
self.assertTrue(os.path.exists(infile)) |
100
|
|
|
|
101
|
|
|
TT.main(["dummy", "--silent", "-o", output, infile]) |
102
|
|
|
self.assertTrue(os.path.exists(output)) |
103
|
|
|
|
104
|
|
|
def test_20_wo_input_type(self): |
105
|
|
|
self._assert_run_and_exit("a.conf") |
106
|
|
|
|
107
|
|
|
def test_30_w_get_option(self): |
108
|
|
View Code Duplication |
d = dict(name="a", a=dict(b=dict(c=[1, 2], d="C"))) |
|
|
|
|
109
|
|
|
|
110
|
|
|
infile = os.path.join(self.workdir, "a.json") |
111
|
|
|
output = os.path.join(self.workdir, "b.json") |
112
|
|
|
|
113
|
|
|
anyconfig.api.dump(d, infile) |
114
|
|
|
self.assertTrue(os.path.exists(infile)) |
115
|
|
|
|
116
|
|
|
TT.main(["dummy", "--silent", "-o", output, "--get", "a.b", infile]) |
117
|
|
|
self.assertTrue(os.path.exists(output)) |
118
|
|
|
|
119
|
|
|
x = anyconfig.api.load(output) |
120
|
|
|
self.assertEqual(x, d['a']['b']) |
121
|
|
|
|
122
|
|
|
def test_32_w_set_option(self): |
123
|
|
|
d = dict(name="a", a=dict(b=dict(c=[1, 2], d="C"))) |
124
|
|
|
|
125
|
|
|
infile = os.path.join(self.workdir, "a.json") |
126
|
|
|
output = os.path.join(self.workdir, "b.json") |
127
|
|
|
|
128
|
|
|
anyconfig.api.dump(d, infile) |
129
|
|
|
self.assertTrue(os.path.exists(infile)) |
130
|
|
|
|
131
|
|
|
TT.main(["dummy", "-q", "-o", output, "--set", "a.b.d=E", infile]) |
132
|
|
|
self.assertTrue(os.path.exists(output)) |
133
|
|
|
|
134
|
|
|
ref = d.copy() |
135
|
|
|
ref['a']['b']['d'] = 'E' |
136
|
|
|
|
137
|
|
|
x = anyconfig.api.load(output) |
138
|
|
|
self.assertEqual(x, ref) |
139
|
|
|
|
140
|
|
|
def test_40_ignore_missing(self): |
141
|
|
|
infile = os.path.join(os.curdir, "conf_file_should_not_exist.json") |
142
|
|
|
assert not os.path.exists(infile) |
143
|
|
|
|
144
|
|
|
self.assertFalse(TT.main(["dummy", "--silent", "-O", "json", |
145
|
|
|
"--ignore-missing", infile])) |
146
|
|
|
|
147
|
|
|
def test_50_w_schema(self): |
148
|
|
|
(infile, scmfile) = (CNF_0_PATH, SCM_0_PATH) |
149
|
|
|
output = os.path.join(self.workdir, "output.json") |
150
|
|
|
self.run_and_check_exit_code(["--schema", scmfile, "--validate", |
151
|
|
View Code Duplication |
infile], 0) |
|
|
|
|
152
|
|
|
self.run_and_check_exit_code(["--schema", scmfile, "-o", output, |
153
|
|
|
infile], 0) |
154
|
|
|
|
155
|
|
|
infile2 = os.path.join(self.workdir, "input.yml") |
156
|
|
|
cnf = CNF_0.copy() |
157
|
|
|
cnf["a"] = "aaa" # Validation should fail. |
158
|
|
|
anyconfig.api.dump(cnf, infile2) |
159
|
|
|
self.run_and_check_exit_code(["--schema", scmfile, "--validate", |
160
|
|
|
infile2], 1) |
161
|
|
|
|
162
|
|
|
def test_52_wo_schema(self): |
163
|
|
|
self.run_and_check_exit_code(["--validate", CNF_0_PATH], 1) |
164
|
|
|
|
165
|
|
|
def test_54_gen_schema_and_validate_with_it(self): |
166
|
|
|
cnf = dict(name="a", a=1, b=dict(b=[1, 2], c="C")) |
167
|
|
|
infile = os.path.join(self.workdir, "cnf.json") |
168
|
|
|
output = os.path.join(self.workdir, "out.yaml") |
169
|
|
|
anyconfig.api.dump(cnf, infile) |
170
|
|
|
|
171
|
|
|
self.run_and_check_exit_code(["--gen-schema", "-o", output, infile], 0) |
172
|
|
|
self.assertTrue(os.path.exists(output)) |
173
|
|
|
self.run_and_check_exit_code(["--schema", output, "--validate", |
174
|
|
|
infile], 0) |
175
|
|
|
|
176
|
|
|
def test_60_w_arg_option(self): |
177
|
|
|
a = dict(name="a", a=1, b=dict(b=[1, 2], c="C"), d=[1, 2]) |
178
|
|
|
|
179
|
|
|
infile = os.path.join(self.workdir, "a.json") |
180
|
|
|
output = os.path.join(self.workdir, "b.json") |
181
|
|
|
|
182
|
|
|
anyconfig.api.dump(a, infile) |
183
|
|
|
self.assertTrue(os.path.exists(infile)) |
184
|
|
|
|
185
|
|
View Code Duplication |
TT.main(["dummy", "--silent", "-o", output, "-A", |
|
|
|
|
186
|
|
|
"a:10;name:x;d:3,4", infile]) |
187
|
|
|
self.assertTrue(os.path.exists(output)) |
188
|
|
|
|
189
|
|
|
x = anyconfig.api.load(output) |
190
|
|
|
|
191
|
|
|
self.assertNotEqual(a["name"], x["name"]) |
192
|
|
|
self.assertNotEqual(a["a"], x["a"]) |
193
|
|
|
self.assertNotEqual(a["d"], x["d"]) |
194
|
|
|
|
195
|
|
|
self.assertEqual(x["name"], 'x') |
196
|
|
|
self.assertEqual(x["a"], 10) |
197
|
|
|
self.assertEqual(x["d"], [3, 4]) |
198
|
|
|
|
199
|
|
|
def test_70_no_template(self): |
200
|
|
|
a = dict(name="a", a=1, b=dict(b=[1, 2], c="C")) |
201
|
|
|
|
202
|
|
|
infile = os.path.join(self.workdir, "a.json") |
203
|
|
|
output = os.path.join(self.workdir, "b.json") |
204
|
|
|
|
205
|
|
|
anyconfig.api.dump(a, infile) |
206
|
|
|
self.assertTrue(os.path.exists(infile)) |
207
|
|
|
|
208
|
|
|
TT.main(["dummy", "--silent", "-o", output, infile]) |
209
|
|
|
self.assertTrue(os.path.exists(output)) |
210
|
|
|
|
211
|
|
|
|
212
|
|
|
class Test_40_multi_inputs(Test_20_Base): |
213
|
|
|
|
214
|
|
|
def test_10(self): |
215
|
|
|
xs = [dict(a=1, ), |
216
|
|
|
dict(b=dict(b=[1, 2], c="C")), ] |
217
|
|
|
|
218
|
|
|
a = xs[0].copy() |
219
|
|
|
a.update(xs[1]) |
220
|
|
|
|
221
|
|
|
output = os.path.join(self.workdir, "b.json") |
222
|
|
|
|
223
|
|
|
inputs = [] |
224
|
|
|
for i in [0, 1]: |
225
|
|
|
infile = os.path.join(self.workdir, "a%d.json" % i) |
226
|
|
|
inputs.append(infile) |
227
|
|
|
|
228
|
|
|
anyconfig.api.dump(xs[i], infile) |
229
|
|
|
self.assertTrue(os.path.exists(infile)) |
230
|
|
|
|
231
|
|
|
TT.main(["dummy", "--silent", "-o", output] + inputs) |
232
|
|
|
self.assertTrue(os.path.exists(output)) |
233
|
|
|
|
234
|
|
|
def test_20_w_template(self): |
235
|
|
|
if not anyconfig.template.SUPPORTED: |
236
|
|
|
return |
237
|
|
|
|
238
|
|
|
a = dict(name="a", a=1, b=dict(b=[1, 2], c="C")) |
239
|
|
|
|
240
|
|
|
inputsdir = os.path.join(self.workdir, "in") |
241
|
|
|
os.makedirs(inputsdir) |
242
|
|
|
|
243
|
|
|
anyconfig.api.dump(a, os.path.join(inputsdir, "a0.yml")) |
244
|
|
|
open(os.path.join(inputsdir, "a1.yml"), 'w').write(CNF_TMPL_0) |
245
|
|
|
output = os.path.join(self.workdir, "b.json") |
246
|
|
|
|
247
|
|
|
TT.main(["dummy", "--silent", "--template", "-o", output, |
248
|
|
|
os.path.join(inputsdir, "*.yml")]) |
249
|
|
|
self.assertTrue(os.path.exists(output)) |
250
|
|
|
|
251
|
|
|
def test_30_w_template(self): |
252
|
|
|
if not anyconfig.template.SUPPORTED: |
253
|
|
|
return |
254
|
|
|
|
255
|
|
|
curdir = tests.common.selfdir() |
256
|
|
|
|
257
|
|
|
infile = os.path.join(curdir, "*template-c*.yml") |
258
|
|
|
output = os.path.join(self.workdir, "output.yml") |
259
|
|
|
|
260
|
|
|
TT.main(["dummy", "--silent", "--template", "-o", output, infile]) |
261
|
|
|
|
262
|
|
|
|
263
|
|
|
class Test_50_others_w_input(Test_20_Base): |
264
|
|
|
|
265
|
|
|
def setUp(self): |
266
|
|
|
super(Test_50_others_w_input, self).setUp() |
267
|
|
|
dic = dict(name="a", a=1, b=dict(b=[1, 2], c="C"), d=[1, 2]) |
268
|
|
|
self.infile = os.path.join(self.workdir, "a.json") |
269
|
|
|
anyconfig.api.dump(dic, self.infile) |
270
|
|
|
|
271
|
|
|
def test_10_output_wo_output_option_w_otype(self): |
272
|
|
|
self.run_and_check_exit_code(["--otype", "json", self.infile]) |
273
|
|
|
|
274
|
|
|
def test_12_output_wo_output_option_and_otype_w_itype(self): |
275
|
|
|
self.run_and_check_exit_code(["--itype", "json", self.infile]) |
276
|
|
|
|
277
|
|
|
def test_20_no_out_dumper(self): |
278
|
|
|
outfile = os.path.join(self.workdir, "out.conf") |
279
|
|
|
self.run_and_check_exit_code(["-o", outfile, self.infile], 1) |
280
|
|
|
|
281
|
|
|
def test_30_w_query_option(self): |
282
|
|
|
self.run_and_check_exit_code(["-Q", "b.b[::-1]", self.infile], 0) |
283
|
|
|
|
284
|
|
|
|
285
|
|
|
class Test_50_others_wo_input(Test_20_Base): |
286
|
|
|
|
287
|
|
|
def test_30_no_itype_and_otype(self): |
288
|
|
|
outfile = os.path.join(self.workdir, "out.conf") |
289
|
|
|
self.run_and_check_exit_code(["-o", outfile, "in.conf"], 1) |
290
|
|
|
|
291
|
|
|
def test_40_no_inputs__w_env_option(self): |
292
|
|
|
output = os.path.join(self.workdir, "out.json") |
293
|
|
|
self.run_and_check_exit_code(["--silent", "--env", "-o", output], 0) |
294
|
|
|
data = anyconfig.api.load(output) |
295
|
|
|
|
296
|
|
|
for env_var, env_val in os.environ.items(): |
297
|
|
|
self.assertTrue(env_var in data) |
298
|
|
|
self.assertEqual(env_val, os.environ[env_var]) |
299
|
|
|
|
300
|
|
|
# vim:sw=4:ts=4:et: |
301
|
|
|
|