]>
Commit | Line | Data |
---|---|---|
85bc5755 WB |
1 | #!/usr/bin/perl |
2 | ||
3 | use lib '../src'; | |
4 | ||
5 | package Conf; | |
6 | use strict; | |
7 | use warnings; | |
8 | ||
9 | use Test::More; | |
10 | ||
11 | use base qw(PVE::SectionConfig); | |
12 | ||
13 | my $defaultData = { | |
14 | propertyList => { | |
15 | type => { description => "Section type." }, | |
16 | id => { | |
17 | description => "ID", | |
18 | type => 'string', | |
19 | format => 'pve-configid', | |
20 | maxLength => 64, | |
21 | }, | |
22 | common => { | |
23 | type => 'string', | |
24 | description => 'common value', | |
25 | maxLength => 512, | |
26 | }, | |
27 | }, | |
28 | }; | |
29 | ||
30 | sub private { | |
31 | return $defaultData; | |
32 | } | |
33 | ||
34 | sub expect_success { | |
35 | my ($class, $filename, $expected, $raw, $allow_unknown) = @_; | |
36 | ||
37 | my $res = $class->parse_config($filename, $raw, $allow_unknown); | |
38 | delete $res->{digest}; | |
39 | ||
40 | is_deeply($res, $expected, $filename); | |
41 | ||
42 | my $written = $class->write_config($filename, $res, $allow_unknown); | |
43 | my $res2 = $class->parse_config($filename, $written, $allow_unknown); | |
44 | delete $res2->{digest}; | |
45 | ||
46 | is_deeply($res, $res2, "$filename - verify rewritten data"); | |
47 | } | |
48 | ||
49 | sub expect_fail { | |
50 | my ($class, $filename, $expected, $raw) = @_; | |
51 | ||
52 | eval { $class->parse_config($filename, $raw) }; | |
53 | die "test '$filename' succeeded unexpectedly\n" if !$@; | |
54 | ok(1, "$filename should fail to parse"); | |
55 | } | |
56 | ||
57 | package Conf::One; | |
58 | use strict; | |
59 | use warnings; | |
60 | ||
61 | use base 'Conf'; | |
62 | ||
63 | sub type { | |
64 | return 'one'; | |
65 | } | |
66 | ||
67 | sub properties { | |
68 | return { | |
69 | field1 => { | |
70 | description => 'Field One', | |
71 | type => 'integer', | |
72 | minimum => 3, | |
73 | maximum => 9, | |
74 | }, | |
75 | another => { | |
76 | description => 'Another field', | |
77 | type => 'string', | |
78 | }, | |
79 | }; | |
80 | } | |
81 | ||
82 | sub options { | |
83 | return { | |
84 | common => { optional => 1 }, | |
85 | field1 => {}, | |
86 | another => { optional => 1 }, | |
87 | }; | |
88 | } | |
89 | ||
90 | package Conf::Two; | |
91 | use strict; | |
92 | use warnings; | |
93 | ||
94 | use base 'Conf'; | |
95 | ||
96 | sub type { | |
97 | return 'two'; | |
98 | } | |
99 | ||
100 | sub properties { | |
101 | return { | |
102 | field2 => { | |
103 | description => 'Field Two', | |
104 | type => 'integer', | |
105 | minimum => 3, | |
106 | maximum => 9, | |
107 | }, | |
69d9edcc DC |
108 | arrayfield => { |
109 | description => "Array Field with property string", | |
110 | type => 'array', | |
111 | items => { | |
112 | type => 'string', | |
113 | description => 'a property string', | |
114 | format => { | |
115 | subfield1 => { | |
116 | type => 'string', | |
117 | description => 'first subfield' | |
118 | }, | |
119 | subfield2 => { | |
120 | type => 'integer', | |
121 | minimum => 0, | |
122 | optional => 1, | |
123 | }, | |
124 | }, | |
125 | }, | |
126 | }, | |
85bc5755 WB |
127 | }; |
128 | } | |
129 | ||
130 | sub options { | |
131 | return { | |
132 | common => { optional => 1 }, | |
133 | field2 => {}, | |
134 | another => {}, | |
69d9edcc | 135 | arrayfield => { optional => 1 }, |
85bc5755 WB |
136 | }; |
137 | } | |
138 | ||
139 | package main; | |
140 | ||
141 | use strict; | |
142 | use warnings; | |
143 | ||
144 | use Test::More; | |
e42f1dd6 | 145 | use PVE::JSONSchema; |
85bc5755 WB |
146 | |
147 | Conf::One->register(); | |
148 | Conf::Two->register(); | |
149 | Conf->init(); | |
150 | ||
8b7b0cc5 | 151 | # FIXME: allow development debug warnings?! |
85bc5755 WB |
152 | local $SIG{__WARN__} = sub { die @_; }; |
153 | ||
154 | my sub enum { | |
155 | my $n = 1; | |
156 | return { map { $_ => $n++ } @_ }; | |
157 | } | |
158 | ||
159 | Conf->expect_success( | |
160 | 'test1', | |
161 | { | |
162 | ids => { | |
163 | t1 => { | |
164 | type => 'one', | |
165 | common => 'foo', | |
166 | field1 => 3, | |
167 | }, | |
168 | t2 => { | |
169 | type => 'one', | |
170 | common => 'foo2', | |
171 | field1 => 4, | |
172 | another => 'more-text', | |
173 | }, | |
174 | t3 => { | |
175 | type => 'two', | |
176 | field2 => 5, | |
177 | another => 'even more text', | |
178 | }, | |
179 | }, | |
180 | order => { t1 => 1, t2 => 2, t3 => 3 }, | |
181 | }, | |
182 | <<"EOF"); | |
183 | one: t1 | |
184 | common foo | |
185 | field1 3 | |
186 | ||
187 | one: t2 | |
188 | common foo2 | |
189 | field1 4 | |
190 | another more-text | |
191 | ||
192 | two: t3 | |
193 | field2 5 | |
194 | another even more text | |
195 | EOF | |
196 | ||
197 | my $with_unknown_data = { | |
198 | ids => { | |
199 | t1 => { | |
200 | type => 'one', | |
201 | common => 'foo', | |
202 | field1 => 3, | |
203 | }, | |
204 | t2 => { | |
205 | type => 'one', | |
206 | common => 'foo2', | |
207 | field1 => 4, | |
208 | another => 'more-text', | |
209 | }, | |
210 | t3 => { | |
211 | type => 'two', | |
212 | field2 => 5, | |
213 | another => 'even more text', | |
69d9edcc DC |
214 | arrayfield => [ |
215 | 'subfield1=test,subfield2=2', | |
216 | 'subfield1=test2', | |
217 | ], | |
85bc5755 WB |
218 | }, |
219 | invalid => { | |
220 | type => 'bad', | |
221 | common => 'omg', | |
d2a6411c | 222 | unknownfield => 'shouldnotbehere', |
9c357928 | 223 | unknownarray => ['entry1', 'entry2'], |
85bc5755 WB |
224 | }, |
225 | }, | |
226 | order => enum(qw(t1 t2 invalid t3)), | |
227 | }; | |
228 | my $with_unknown_text = <<"EOF"; | |
229 | one: t1 | |
230 | common foo | |
231 | field1 3 | |
232 | ||
233 | one: t2 | |
234 | common foo2 | |
235 | field1 4 | |
236 | another more-text | |
237 | ||
238 | bad: invalid | |
239 | common omg | |
d2a6411c | 240 | unknownfield shouldnotbehere |
9c357928 FE |
241 | unknownarray entry1 |
242 | unknownarray entry2 | |
85bc5755 WB |
243 | |
244 | two: t3 | |
245 | field2 5 | |
246 | another even more text | |
69d9edcc DC |
247 | arrayfield subfield1=test,subfield2=2 |
248 | arrayfield subfield1=test2 | |
85bc5755 WB |
249 | EOF |
250 | ||
251 | Conf->expect_fail('unknown-forbidden', $with_unknown_data, $with_unknown_text); | |
252 | Conf->expect_success('unknown-allowed', $with_unknown_data, $with_unknown_text, 1); | |
253 | ||
e42f1dd6 DC |
254 | # schema tests |
255 | my $create_schema = Conf->createSchema(); | |
256 | my $expected_create_schema = { | |
257 | additionalProperties => 0, | |
258 | type => 'object', | |
259 | properties => { | |
260 | id => { | |
261 | description => 'ID', | |
262 | format => 'pve-configid', | |
263 | maxLength => 64, | |
264 | type => 'string', | |
265 | }, | |
266 | type => { | |
267 | description => 'Section type.', | |
268 | enum => ['one', 'two'], | |
269 | type => 'string', | |
270 | }, | |
271 | common => { | |
272 | type => 'string', | |
273 | description => 'common value', | |
274 | maxLength => 512, | |
275 | }, | |
276 | field1 => { | |
277 | description => 'Field One', | |
278 | maximum => 9, | |
279 | minimum => 3, | |
280 | optional => 1, | |
281 | type => 'integer', | |
282 | ||
283 | }, | |
284 | 'field2'=> { | |
285 | 'description'=> 'Field Two', | |
286 | 'maximum'=> 9, | |
287 | 'minimum'=> 3, | |
288 | 'optional'=> 1, | |
289 | 'type'=> 'integer', | |
290 | }, | |
291 | 'arrayfield'=> { | |
292 | 'description'=> 'Array Field with property string', | |
293 | 'items'=> { | |
294 | 'description'=> 'a property string', | |
295 | 'format'=> { | |
296 | 'subfield2'=> { | |
297 | 'optional'=> 1, | |
298 | 'type'=> 'integer', | |
299 | 'minimum'=> 0 | |
300 | }, | |
301 | 'subfield1'=> { | |
302 | 'description'=> 'first subfield', | |
303 | 'type'=> 'string', | |
304 | }, | |
305 | }, | |
306 | 'type'=> 'string' | |
307 | }, | |
308 | 'optional'=> 1, | |
309 | 'type'=> 'array', | |
310 | }, | |
311 | 'another'=> { | |
312 | 'description'=> 'Another field', | |
313 | 'optional'=> 1, | |
314 | 'type'=> 'string', | |
315 | }, | |
316 | }, | |
317 | }; | |
318 | ||
319 | is_deeply($create_schema, $expected_create_schema, "create schema test"); | |
320 | ||
321 | my $update_schema = Conf->updateSchema(); | |
322 | my $expected_update_schema = { | |
323 | additionalProperties => 0, | |
324 | type => 'object', | |
325 | properties => { | |
326 | id => { | |
327 | description => 'ID', | |
328 | format => 'pve-configid', | |
329 | maxLength => 64, | |
330 | type => 'string', | |
331 | }, | |
332 | delete => { | |
333 | type => 'string', format => 'pve-configid-list', | |
334 | description => "A list of settings you want to delete.", | |
335 | maxLength => 4096, | |
336 | optional => 1, | |
337 | }, | |
338 | digest => PVE::JSONSchema::get_standard_option('pve-config-digest'), | |
339 | common => { | |
340 | description => 'common value', | |
341 | maxLength => 512, | |
342 | type => 'string', | |
343 | }, | |
344 | field1 => { | |
345 | description => 'Field One', | |
346 | maximum => 9, | |
347 | minimum => 3, | |
348 | optional => 1, | |
349 | type => 'integer' | |
350 | }, | |
351 | field2 => { | |
352 | description => 'Field Two', | |
353 | maximum => 9, | |
354 | minimum => 3, | |
355 | optional => 1, | |
356 | type => 'integer', | |
357 | }, | |
358 | arrayfield => { | |
359 | description => 'Array Field with property string', | |
360 | items => { | |
361 | type => 'string', | |
362 | description => 'a property string', | |
363 | format => { | |
364 | subfield2 => { | |
365 | type => 'integer', | |
366 | minimum => 0, | |
367 | optional => 1 | |
368 | }, | |
369 | subfield1 => { | |
370 | description => 'first subfield', | |
371 | type => 'string' | |
372 | } | |
373 | } | |
374 | }, | |
375 | optional => 1, | |
376 | type => 'array', | |
377 | }, | |
378 | another => { | |
379 | description => 'Another field', | |
380 | optional => 1, | |
381 | type => 'string', | |
382 | }, | |
383 | }, | |
384 | }; | |
385 | is_deeply($update_schema, $expected_update_schema, "update schema test"); | |
85bc5755 WB |
386 | |
387 | done_testing(); | |
388 | ||
389 | 1; |