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 anyconfig.tests.common |
16
|
|
|
import anyconfig.tests.api |
17
|
|
|
|
18
|
|
|
from anyconfig.tests.common import CNF_0 |
19
|
|
|
|
20
|
|
|
|
21
|
|
|
CNF_0_PATH = os.path.join(anyconfig.tests.common.selfdir(), "00-cnf.yml") |
22
|
|
|
SCM_0_PATH = os.path.join(anyconfig.tests.common.selfdir(), "00-scm.yml") |
23
|
|
|
CNF_TMPL_0 = anyconfig.tests.api.CNF_TMPL_1 |
24
|
|
|
|
25
|
|
|
|
26
|
|
|
def _run(*args): |
27
|
|
|
TT.main(["dummy", "--silent"] + list(args)) |
28
|
|
|
|
29
|
|
|
|
30
|
|
|
class Test_00_Base(unittest.TestCase): |
31
|
|
|
|
32
|
|
|
def run_and_check_exit_code(self, args=None, code=0, _not=False, |
33
|
|
|
exc_cls=SystemExit): |
34
|
|
|
try: |
35
|
|
|
TT.main(["dummy", "--silent"] + ([] if args is None else args)) |
36
|
|
|
except exc_cls as exc: |
37
|
|
|
ecode = getattr(exc, "code", 1) |
38
|
|
|
(self.assertNotEqual if _not else self.assertEqual)(ecode, code) |
39
|
|
|
|
40
|
|
|
|
41
|
|
|
class Test_10(Test_00_Base): |
42
|
|
|
|
43
|
|
|
def test_10_show_usage(self): |
44
|
|
|
self.run_and_check_exit_code(["--help"]) |
45
|
|
|
|
46
|
|
|
def test_20_wo_args(self): |
47
|
|
|
self.run_and_check_exit_code(_not=True) |
48
|
|
|
|
49
|
|
|
def test_30_wrong_option(self): |
50
|
|
|
self.run_and_check_exit_code(["--wrong-option-xyz"], _not=True) |
51
|
|
|
|
52
|
|
|
def test_40_list(self): |
53
|
|
|
self.run_and_check_exit_code(["--list"]) |
54
|
|
|
|
55
|
|
|
|
56
|
|
|
class Test_20_Base(Test_00_Base): |
57
|
|
|
|
58
|
|
|
def setUp(self): |
59
|
|
|
self.workdir = anyconfig.tests.common.setup_workdir() |
60
|
|
|
self.script = os.path.join(anyconfig.tests.common.selfdir(), |
61
|
|
|
"..", "cli.py") |
62
|
|
|
|
63
|
|
|
def tearDown(self): |
64
|
|
|
anyconfig.tests.common.cleanup_workdir(self.workdir) |
65
|
|
|
|
66
|
|
|
def _assert_run_and_exit(self, *args): |
67
|
|
|
raised = False |
68
|
|
|
try: |
69
|
|
|
_run(*args) |
70
|
|
|
except SystemExit: |
71
|
|
|
raised = True |
72
|
|
|
|
73
|
|
|
self.assertTrue(raised) |
74
|
|
|
|
75
|
|
|
|
76
|
|
|
class Test_30_single_input(Test_20_Base): |
77
|
|
|
|
78
|
|
|
def test_10(self): |
|
|
|
|
79
|
|
|
a = dict(name="a", a=1, b=dict(b=[1, 2], c="C")) |
80
|
|
|
|
81
|
|
|
infile = os.path.join(self.workdir, "a.json") |
82
|
|
|
output = os.path.join(self.workdir, "b.json") |
83
|
|
|
|
84
|
|
|
anyconfig.api.dump(a, infile) |
85
|
|
|
self.assertTrue(os.path.exists(infile)) |
86
|
|
|
|
87
|
|
|
TT.main(["dummy", "--silent", "-o", output, infile]) |
88
|
|
|
self.assertTrue(os.path.exists(output)) |
89
|
|
|
|
90
|
|
|
def test_20_wo_input_type(self): |
91
|
|
|
self._assert_run_and_exit("a.conf") |
92
|
|
|
|
93
|
|
|
def test_30_w_get_option(self): |
94
|
|
|
d = dict(name="a", a=dict(b=dict(c=[1, 2], d="C"))) |
95
|
|
|
|
96
|
|
|
infile = os.path.join(self.workdir, "a.json") |
97
|
|
|
output = os.path.join(self.workdir, "b.json") |
98
|
|
|
|
99
|
|
|
anyconfig.api.dump(d, infile) |
100
|
|
|
self.assertTrue(os.path.exists(infile)) |
101
|
|
|
|
102
|
|
|
TT.main(["dummy", "--silent", "-o", output, "--get", "a.b", infile]) |
103
|
|
|
self.assertTrue(os.path.exists(output)) |
104
|
|
|
|
105
|
|
|
x = anyconfig.api.load(output) |
106
|
|
|
self.assertEqual(x, d['a']['b']) |
107
|
|
|
|
108
|
|
|
def test_32_w_set_option(self): |
109
|
|
|
d = dict(name="a", a=dict(b=dict(c=[1, 2], d="C"))) |
110
|
|
|
|
111
|
|
|
infile = os.path.join(self.workdir, "a.json") |
112
|
|
|
output = os.path.join(self.workdir, "b.json") |
113
|
|
|
|
114
|
|
|
anyconfig.api.dump(d, infile) |
115
|
|
|
self.assertTrue(os.path.exists(infile)) |
116
|
|
|
|
117
|
|
|
TT.main(["dummy", "-q", "-o", output, "--set", "a.b.d=E", infile]) |
118
|
|
|
self.assertTrue(os.path.exists(output)) |
119
|
|
|
|
120
|
|
|
ref = d.copy() |
121
|
|
|
ref['a']['b']['d'] = 'E' |
122
|
|
|
|
123
|
|
|
x = anyconfig.api.load(output) |
124
|
|
|
self.assertEqual(x, ref) |
125
|
|
|
|
126
|
|
|
def test_40_ignore_missing(self): |
127
|
|
|
infile = os.path.join(os.curdir, "conf_file_should_not_exist.json") |
128
|
|
|
assert not os.path.exists(infile) |
129
|
|
|
|
130
|
|
|
self.assertFalse(TT.main(["dummy", "--silent", "-O", "json", |
131
|
|
|
"--ignore-missing", infile])) |
132
|
|
|
|
133
|
|
|
def test_50_w_schema(self): |
134
|
|
|
(infile, scmfile) = (CNF_0_PATH, SCM_0_PATH) |
135
|
|
|
output = os.path.join(self.workdir, "output.json") |
136
|
|
|
self.run_and_check_exit_code(["--schema", scmfile, "--validate", |
137
|
|
|
infile], 0) |
138
|
|
|
self.run_and_check_exit_code(["--schema", scmfile, "-o", output, |
139
|
|
|
infile], 0) |
140
|
|
|
|
141
|
|
|
infile2 = os.path.join(self.workdir, "input.yml") |
142
|
|
|
cnf = CNF_0.copy() |
143
|
|
|
cnf["a"] = "aaa" # Validation should fail. |
144
|
|
|
anyconfig.api.dump(cnf, infile2) |
145
|
|
|
self.run_and_check_exit_code(["--schema", scmfile, "--validate", |
146
|
|
|
infile2], 1) |
147
|
|
|
|
148
|
|
|
def test_52_wo_schema(self): |
149
|
|
|
self.run_and_check_exit_code(["--validate", CNF_0_PATH], 1) |
150
|
|
|
|
151
|
|
|
def test_54_gen_schema_and_validate_with_it(self): |
152
|
|
|
cnf = dict(name="a", a=1, b=dict(b=[1, 2], c="C")) |
153
|
|
|
infile = os.path.join(self.workdir, "cnf.json") |
154
|
|
|
output = os.path.join(self.workdir, "out.yaml") |
155
|
|
|
anyconfig.api.dump(cnf, infile) |
156
|
|
|
|
157
|
|
|
self.run_and_check_exit_code(["--gen-schema", "-o", output, infile], 0) |
158
|
|
|
self.assertTrue(os.path.exists(output)) |
159
|
|
|
self.run_and_check_exit_code(["--schema", output, "--validate", |
160
|
|
|
infile], 0) |
161
|
|
|
|
162
|
|
|
def test_60_w_arg_option(self): |
163
|
|
|
a = dict(name="a", a=1, b=dict(b=[1, 2], c="C"), d=[1, 2]) |
164
|
|
|
|
165
|
|
|
infile = os.path.join(self.workdir, "a.json") |
166
|
|
|
output = os.path.join(self.workdir, "b.json") |
167
|
|
|
|
168
|
|
|
anyconfig.api.dump(a, infile) |
169
|
|
|
self.assertTrue(os.path.exists(infile)) |
170
|
|
|
|
171
|
|
|
TT.main(["dummy", "--silent", "-o", output, "-A", |
172
|
|
|
"a:10;name:x;d:3,4", infile]) |
173
|
|
|
self.assertTrue(os.path.exists(output)) |
174
|
|
|
|
175
|
|
|
x = anyconfig.api.load(output) |
176
|
|
|
|
177
|
|
|
self.assertNotEqual(a["name"], x["name"]) |
178
|
|
|
self.assertNotEqual(a["a"], x["a"]) |
179
|
|
|
self.assertNotEqual(a["d"], x["d"]) |
180
|
|
|
|
181
|
|
|
self.assertEqual(x["name"], 'x') |
182
|
|
|
self.assertEqual(x["a"], 10) |
183
|
|
|
self.assertEqual(x["d"], [3, 4]) |
184
|
|
|
|
185
|
|
|
def test_70_no_template(self): |
|
|
|
|
186
|
|
|
a = dict(name="a", a=1, b=dict(b=[1, 2], c="C")) |
187
|
|
|
|
188
|
|
|
infile = os.path.join(self.workdir, "a.json") |
189
|
|
|
output = os.path.join(self.workdir, "b.json") |
190
|
|
|
|
191
|
|
|
anyconfig.api.dump(a, infile) |
192
|
|
|
self.assertTrue(os.path.exists(infile)) |
193
|
|
|
|
194
|
|
|
TT.main(["dummy", "--silent", "-o", output, infile]) |
195
|
|
|
self.assertTrue(os.path.exists(output)) |
196
|
|
|
|
197
|
|
|
|
198
|
|
|
class Test_40_multi_inputs(Test_20_Base): |
199
|
|
|
|
200
|
|
|
def test_10(self): |
201
|
|
|
xs = [dict(a=1, ), |
202
|
|
|
dict(b=dict(b=[1, 2], c="C")), ] |
203
|
|
|
|
204
|
|
|
a = xs[0].copy() |
205
|
|
|
a.update(xs[1]) |
206
|
|
|
|
207
|
|
|
output = os.path.join(self.workdir, "b.json") |
208
|
|
|
|
209
|
|
|
inputs = [] |
210
|
|
|
for i in [0, 1]: |
211
|
|
|
infile = os.path.join(self.workdir, "a%d.json" % i) |
212
|
|
|
inputs.append(infile) |
213
|
|
|
|
214
|
|
|
anyconfig.api.dump(xs[i], infile) |
215
|
|
|
self.assertTrue(os.path.exists(infile)) |
216
|
|
|
|
217
|
|
|
TT.main(["dummy", "--silent", "-o", output] + inputs) |
218
|
|
|
self.assertTrue(os.path.exists(output)) |
219
|
|
|
|
220
|
|
|
def test_20_w_template(self): |
221
|
|
|
if not anyconfig.template.SUPPORTED: |
222
|
|
|
return |
223
|
|
|
|
224
|
|
|
a = dict(name="a", a=1, b=dict(b=[1, 2], c="C")) |
225
|
|
|
|
226
|
|
|
inputsdir = os.path.join(self.workdir, "in") |
227
|
|
|
os.makedirs(inputsdir) |
228
|
|
|
|
229
|
|
|
anyconfig.api.dump(a, os.path.join(inputsdir, "a0.yml")) |
230
|
|
|
open(os.path.join(inputsdir, "a1.yml"), 'w').write(CNF_TMPL_0) |
231
|
|
|
output = os.path.join(self.workdir, "b.json") |
232
|
|
|
|
233
|
|
|
TT.main(["dummy", "--silent", "--template", "-o", output, |
234
|
|
|
os.path.join(inputsdir, "*.yml")]) |
235
|
|
|
self.assertTrue(os.path.exists(output)) |
236
|
|
|
|
237
|
|
|
def test_30_w_template(self): |
238
|
|
|
if not anyconfig.template.SUPPORTED: |
239
|
|
|
return |
240
|
|
|
|
241
|
|
|
curdir = anyconfig.tests.common.selfdir() |
242
|
|
|
|
243
|
|
|
infile = os.path.join(curdir, "*template-c*.yml") |
244
|
|
|
output = os.path.join(self.workdir, "output.yml") |
245
|
|
|
|
246
|
|
|
TT.main(["dummy", "--silent", "--template", "-o", output, infile]) |
247
|
|
|
|
248
|
|
|
|
249
|
|
|
class Test_50_others(Test_20_Base): |
250
|
|
|
|
251
|
|
|
def test_10_output_wo_output_option_w_otype(self): |
252
|
|
|
a = dict(name="a", a=1, b=dict(b=[1, 2], c="C")) |
253
|
|
|
infile = os.path.join(self.workdir, "a.json") |
254
|
|
|
anyconfig.api.dump(a, infile) |
255
|
|
|
|
256
|
|
|
self.run_and_check_exit_code(["--otype", "json", infile]) |
257
|
|
|
|
258
|
|
|
def test_12_output_wo_output_option_and_otype_w_itype(self): |
259
|
|
|
a = dict(name="a", a=1, b=dict(b=[1, 2], c="C")) |
260
|
|
|
infile = os.path.join(self.workdir, "a.json") |
261
|
|
|
anyconfig.api.dump(a, infile) |
262
|
|
|
|
263
|
|
|
self.run_and_check_exit_code(["--itype", "json", infile]) |
264
|
|
|
|
265
|
|
|
def test_20_no_out_dumper(self): |
266
|
|
|
a = dict(name="a", a=1, b=dict(b=[1, 2], c="C"), d=[1, 2]) |
267
|
|
|
infile = os.path.join(self.workdir, "a.json") |
268
|
|
|
anyconfig.api.dump(a, infile) |
269
|
|
|
|
270
|
|
|
exited = False |
271
|
|
|
outfile = os.path.join(self.workdir, "out.conf") |
272
|
|
|
_run("-o", outfile, infile) |
273
|
|
|
self.assertFalse(exited) |
274
|
|
|
|
275
|
|
|
def test_30_no_itype_and_otype(self): |
276
|
|
|
exited = False |
277
|
|
|
outfile = os.path.join(self.workdir, "out.conf") |
278
|
|
|
_run("-o", outfile, "in.conf") |
279
|
|
|
self.assertFalse(exited) |
280
|
|
|
|
281
|
|
|
def test_40_no_inputs__w_env_option(self): |
282
|
|
|
infile = "/dev/null" |
283
|
|
|
output = os.path.join(self.workdir, "out.yml") |
284
|
|
|
|
285
|
|
|
if anyconfig.api.find_loader(infile, "yaml") is None: |
286
|
|
|
return |
287
|
|
|
|
288
|
|
|
TT.main(["dummy", "--silent", "--env", "-o", output, infile]) |
289
|
|
|
data = anyconfig.api.load(output) |
290
|
|
|
|
291
|
|
|
for env_var, env_val in os.environ.items(): |
292
|
|
|
self.assertTrue(env_var in data) |
293
|
|
|
self.assertEqual(env_val, os.environ[env_var]) |
294
|
|
|
|
295
|
|
|
# vim:sw=4:ts=4:et: |
296
|
|
|
|
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.