kwalify 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,179 @@
1
+ ###
2
+ ### $Rev: 42 $
3
+ ### $Release: 0.5.0 $
4
+ ### copyright(c) 2005 kuwata-lab all rights reserved.
5
+ ###
6
+
7
+ unless defined?(TESTDIR)
8
+ TESTDIR = File.dirname(__FILE__)
9
+ libdir = File.dirname(TESTDIR) + "/lib"
10
+ $LOAD_PATH << libdir << TESTDIR
11
+ end
12
+
13
+ require 'test/unit'
14
+ require 'test/unit/ui/console/testrunner'
15
+ require 'kwalify'
16
+ require 'kwalify/util/assert-diff'
17
+ require 'kwalify/main.rb'
18
+ require 'yaml'
19
+
20
+ module Kwalify
21
+ class Main
22
+ public :_parse_argv
23
+ end
24
+ end
25
+
26
+ class File
27
+ def self.move(filename, dirname)
28
+ File.rename(filename, "#{dirname}/filename")
29
+ end
30
+ end
31
+
32
+ class MainTest < Test::Unit::TestCase
33
+
34
+ ## define test methods
35
+ filename = __FILE__.sub(/\.rb$/, ".yaml")
36
+ str = File.read(filename)
37
+ @@docs = {}
38
+ YAML.load_documents(str) do |doc|
39
+ name = doc['name']
40
+ !@@docs.key?(name) or raise "*** test name '#{name}' is duplicated."
41
+ @@docs[name] = doc
42
+ doc.each do |key, val|
43
+ doc[$1] ||= val['ruby'] if key =~ /\A(.*)\*\z/
44
+ end
45
+ s = <<-END
46
+ def test_#{name}
47
+ doc = @@docs['#{name}']
48
+ @name = doc['name']
49
+ @desc = doc['desc']
50
+ @args = doc['args']
51
+ @inspect = doc['inspect']
52
+ @exception = #{doc['exception'] ? "Kwalify::" + doc['exception'] : 'nil'}
53
+ @error_symbol = doc['error_symbol']
54
+ @expected = doc['expected']
55
+ @schema = doc['schema']
56
+ @document = doc['document']
57
+ @valid = doc['valid']
58
+ @invalid = doc['invalid']
59
+ @valid_out = doc['valid-out']
60
+ @invalid_out = doc['invalid-out']
61
+ @method = doc['method']
62
+ # @options = doc['options']
63
+
64
+ case @method
65
+ when 'parseOptions'
66
+ _test_parse_options()
67
+ when 'execute'
68
+ raise "*** #{doc['name']}: args is not defined." unless doc['args']
69
+ raise "*** #{doc['name']}: expected is not defined." unless doc['expected']
70
+ _test_execute()
71
+ when 'validation'
72
+ _test_validation()
73
+ raise "*** #{doc['name']}: schema is not defined." unless doc['schema']
74
+ raise "*** #{doc['name']}: valid is not defined." unless doc['valid']
75
+ raise "*** #{doc['name']}: invalid is not defined." unless doc['invalid']
76
+
77
+ else
78
+ raise "*** #{@method}: invalid method name."
79
+ end
80
+ end
81
+ END
82
+ eval s
83
+ end
84
+
85
+
86
+ ## temporary directory
87
+ @@tmpdir = "tmp.dir"
88
+ Dir.mkdir(@@tmpdir) unless test(?d, @@tmpdir)
89
+
90
+
91
+ ## validation test
92
+ def _test_validation()
93
+ return if $target && $target != @name
94
+ raise "*** schema is not defined." unless @schema
95
+ raise "*** valid is not defined." unless @valid
96
+ raise "*** invalid is not defined." unless @invalid
97
+ #
98
+ schema_filename = @name + ".schema"
99
+ valid_filename = @name + ".valid"
100
+ invalid_filename = @name + ".invalid"
101
+ #
102
+ begin
103
+ #
104
+ File.open(schema_filename, 'w') { |f| f.write(@schema) }
105
+ File.open(valid_filename, 'w') { |f| f.write(@valid) }
106
+ File.open(invalid_filename, 'w') { |f| f.write(@invalid) }
107
+ #
108
+ main = Kwalify::Main.new('kwalify')
109
+ args = [ "-lf", schema_filename, valid_filename ]
110
+ output = main.execute(args)
111
+ assert_equal_with_diff(@valid_out, output)
112
+ #
113
+ main = Kwalify::Main.new('kwalify')
114
+ args = [ "-lf", schema_filename, invalid_filename ]
115
+ output = main.execute(args)
116
+ assert_equal_with_diff(@invalid_out, output)
117
+ #
118
+ ensure
119
+ File.move(schema_filename, @@tmpdir)
120
+ File.move(valid_filename, @@tmpdir)
121
+ File.move(invalid_filename, @@tmpdir)
122
+ end
123
+ end
124
+
125
+ ## execute test
126
+ def _test_execute()
127
+ return if $target && $target != @name
128
+ raise "*** args is required when method is 'execute'." unless @args
129
+ raise "*** expected is required when method is 'execute'." unless @expected
130
+ #
131
+ File.open("#{@name}.schema", 'w') { |f| f.write(@schema) } if @schema
132
+ File.open("#{@name}.document", 'w') { |f| f.write(@document) } if @document
133
+ #
134
+ begin
135
+ main = Kwalify::Main.new("kwalify")
136
+ if (! @exception)
137
+ actual = main.execute(@args)
138
+ assert_equal_with_diff(@expected, actual)
139
+ else
140
+ assert_raise(@exception) do
141
+ main.execute(@args)
142
+ end
143
+ end
144
+ ensure
145
+ File.move("#{@name}.schema", @@tmpdir) if @schema
146
+ File.move("#{@name}.document", @@tmpdir) if @document
147
+ end
148
+ end
149
+
150
+ ## command option test
151
+ def _test_parse_options()
152
+ return if $target && $target != @name
153
+ main = Kwalify::Main.new("kwalify")
154
+ begin
155
+ filenames = main._parse_argv(@args)
156
+ s = main._inspect()
157
+ s << "filenames:\n"
158
+ filenames.each do |filename|
159
+ s << " - #{filename}\n"
160
+ end
161
+ actual = s
162
+ assert_equal_with_diff(@inspect, actual)
163
+ rescue => ex
164
+ #klass = @exception
165
+ if @exception && ex.class == @exception
166
+ # OK
167
+ assert_equal(@error_symbol, ex.error_symbol) if ex.respond_to?(:error_symbol)
168
+ else
169
+ # NG
170
+ raise ex
171
+ end
172
+ end
173
+ end
174
+
175
+ end
176
+
177
+ #if $0 == __FILE__
178
+ # Test::Unit::UI::Console::TestRunner.run(ValidatorTest)
179
+ #end
@@ -0,0 +1,756 @@
1
+ ##
2
+ ## $Rev: 42 $
3
+ ## $Release: 0.5.0 $
4
+ ## copyright(c) 2005 kuwata-lab all rights reserved.
5
+ ##
6
+ ---
7
+ name: parseOptions1
8
+ desc: test Main#parseOptions()
9
+ method: parseOptions
10
+ args: [ -hvsmtlDf, schema.yaml, document.yaml, document2.yaml ]
11
+ inspect: |
12
+ command : kwalify
13
+ flag_help : true
14
+ flag_version : true
15
+ flag_silent : true
16
+ flag_meta : true
17
+ flag_untabify : true
18
+ flag_linenum : true
19
+ flag_debug : true
20
+ schema_filename : schema.yaml
21
+ properties:
22
+ filenames:
23
+ - document.yaml
24
+ - document2.yaml
25
+ #
26
+ ---
27
+ name: parseOptions2
28
+ desc: -ffilename
29
+ method: parseOptions
30
+ args: [ -lfschema.yaml]
31
+ inspect: |
32
+ command : kwalify
33
+ flag_help : false
34
+ flag_version : false
35
+ flag_silent : false
36
+ flag_meta : false
37
+ flag_untabify : false
38
+ flag_linenum : true
39
+ flag_debug : false
40
+ schema_filename : schema.yaml
41
+ properties:
42
+ filenames:
43
+ #
44
+ ---
45
+ name: parseOptions3
46
+ desc: "'--help' is equal to '-h'"
47
+ method: parseOptions
48
+ args: [ --help, document.yaml ]
49
+ inspect: |
50
+ command : kwalify
51
+ flag_help : true
52
+ flag_version : false
53
+ flag_silent : false
54
+ flag_meta : false
55
+ flag_untabify : false
56
+ flag_linenum : false
57
+ flag_debug : false
58
+ schema_filename : null
59
+ properties:
60
+ help: true
61
+ filenames:
62
+ - document.yaml
63
+ #
64
+ ---
65
+ name: optionError1
66
+ desc: invalid command-line option
67
+ method: parseOptions
68
+ args: [ -hvi ]
69
+ inspect: '*'
70
+ exception*:
71
+ ruby: CommandOptionError
72
+ java: CommandOptionException
73
+ message: "-i: invalid command option."
74
+ error_symbol*:
75
+ ruby: !ruby/sym :command_option_invalid
76
+ java: command.option.invalid
77
+ #
78
+ ---
79
+ name: optionError2
80
+ desc: no argument of '-f'
81
+ method: parseOptions
82
+ args: [ -f ]
83
+ inspect: '*'
84
+ exception*:
85
+ ruby: CommandOptionError
86
+ java: CommandOptionException
87
+ message: "-f: schema filename is required."
88
+ error_symbol*:
89
+ ruby: !ruby/sym :command_option_noschema
90
+ java: command.option.noschema
91
+ #
92
+ ##---
93
+ ##name: optionError3
94
+ ##desc: invalid property
95
+ ##method: parseOptions
96
+ ##args: [ --foo@var ]
97
+ ##inspect: '*'
98
+ ##exception*:
99
+ ## ruby: CommandOptionError
100
+ ## #java: CommandOptionException
101
+ ##message: "'--foo@var': invalid property."
102
+ ##error_symbol*:
103
+ ## ruby: !ruby/sym :command_property_invalid
104
+ ## #java: command.property.invalid
105
+ ---
106
+ name: optionError4
107
+ desc: action required
108
+ method: execute
109
+ args: [ document.yaml ]
110
+ inspect: '*'
111
+ expected: |
112
+ exception*:
113
+ ruby: CommandOptionError
114
+ java: CommandOptionException
115
+ message: "command-line option '-f' or '-m' required."
116
+ error_symbol*:
117
+ ruby: !ruby/sym :command_option_noschema
118
+ java: command.option.noaction
119
+
120
+ ---
121
+ name: version
122
+ desc: option '-v'
123
+ method: execute
124
+ args: [ -vt, document.yaml ]
125
+ expected: |
126
+ 0.0.0
127
+ #
128
+ ---
129
+ name: help
130
+ desc: option '-h'
131
+ method: execute
132
+ args: [ -hD, document.yaml ]
133
+ expected: |
134
+ Usage1: kwalify [-hvstl] -f schema.yaml document.yaml [document2.yaml ...]
135
+ Usage2: kwalify [-hvstl] -m schema.yaml [schema2.yaml ...]
136
+ -h, --help : help
137
+ -v : version
138
+ -s : silent
139
+ -f schema.yaml : schema definition file
140
+ -m : meta-validation mode
141
+ -t : expand tab character automatically
142
+ -l : show linenumber when errored (experimental)
143
+ #
144
+ ---
145
+ name: silent1
146
+ desc: option '-s' (valid)
147
+ method: execute
148
+ args: [ -sf, silent1.schema, silent1.document ]
149
+ expected: |
150
+ schema: |
151
+ type: seq
152
+ sequence:
153
+ - type: str
154
+ document: |
155
+ - foo
156
+ - bar
157
+ - baz
158
+ #
159
+ ---
160
+ name: silent2
161
+ desc: option '-s' (invalid)
162
+ method: execute
163
+ args: [ -sf, silent2.schema, silent2.document ]
164
+ expected: |
165
+ silent2.document#1: INVALID
166
+ - [/1] '123': not a string.
167
+ - [/2] 'true': not a string.
168
+ schema: |
169
+ type: seq
170
+ sequence:
171
+ - type: str
172
+ document: |
173
+ - foo
174
+ - bar
175
+ - baz
176
+ ---
177
+ - foo
178
+ - 123
179
+ - true
180
+ #
181
+ ---
182
+ name: untabify
183
+ desc: option '-t'
184
+ method: execute
185
+ args: [ -tf, untabify.schema, untabify.document ]
186
+ expected: |
187
+ untabify.document#0: valid.
188
+ schema: |
189
+ type: seq
190
+ sequence:
191
+ - type: map
192
+ mapping:
193
+ "key":
194
+ type: text
195
+ required: yes
196
+ "value":
197
+ type: any
198
+ required: yes
199
+ document: |
200
+ #
201
+ - key: foo
202
+ value: 123
203
+ - key: bar
204
+ value: [a, b, c]
205
+ #
206
+ ---
207
+ name: stream
208
+ desc: stream document
209
+ method: validation
210
+ schema: |
211
+ type: seq
212
+ sequence:
213
+ - type: str
214
+ valid: |
215
+ ---
216
+ - foo
217
+ - bar
218
+ - baz
219
+ ---
220
+ - aaa
221
+ - bbb
222
+ - ccc
223
+ valid-out: |
224
+ stream.valid#0: valid.
225
+ stream.valid#1: valid.
226
+ invalid: |
227
+ ---
228
+ - foo
229
+ - 123
230
+ - baz
231
+ ---
232
+ - aaa
233
+ - bbb
234
+ - true
235
+ invalid-out: |
236
+ stream.invalid#0: INVALID
237
+ - (line 3) [/1] '123': not a string.
238
+ stream.invalid#1: INVALID
239
+ - (line 8) [/2] 'true': not a string.
240
+ #
241
+ ---
242
+ name: meta1
243
+ desc: meta validation (valid)
244
+ method: execute
245
+ args: [ -m, meta1.schema ]
246
+ schema: |
247
+ type: seq
248
+ sequence:
249
+ - type: str
250
+ document: |
251
+ expected: |
252
+ meta1.schema: ok.
253
+ #
254
+ ---
255
+ name: meta2
256
+ desc: meta validation (invalid)
257
+ method: execute
258
+ args: [ -m, meta2.schema ]
259
+ schema: |
260
+ type: map
261
+ sequence:
262
+ - type: str
263
+ document: |
264
+ expected: |
265
+ meta2.schema: NG!
266
+ - [/] type 'map' requires 'mapping:'.
267
+ - [/] 'sequence:': not available with mapping.
268
+ #
269
+
270
+ ####
271
+ #### user's guide
272
+ ####
273
+ ---
274
+ name: validation01
275
+ desc: basic validation
276
+ method: validation
277
+ schema: |
278
+ type: seq
279
+ sequence:
280
+ - type: str
281
+ valid: |
282
+ - foo
283
+ - bar
284
+ - baz
285
+ valid-out: |
286
+ validation01.valid#0: valid.
287
+ invalid: |
288
+ - foo
289
+ - 123
290
+ - baz
291
+ invalid-out: |
292
+ validation01.invalid#0: INVALID
293
+ - (line 2) [/1] '123': not a string.
294
+ #
295
+ ---
296
+ name: validation02
297
+ desc: basic validation
298
+ method: validation
299
+ schema: |
300
+ type: map
301
+ mapping:
302
+ name:
303
+ type: str
304
+ required: yes
305
+ email:
306
+ type: str
307
+ pattern: /@/
308
+ age:
309
+ type: int
310
+ birth:
311
+ type: date
312
+ valid: |
313
+ name: foo
314
+ email: foo@mail.com
315
+ age: 20
316
+ birth: 1985-01-01
317
+ valid-out: |
318
+ validation02.valid#0: valid.
319
+ invalid: |
320
+ name: foo
321
+ email: foo(at)mail.com
322
+ age: twenty
323
+ birth: Jun 01, 1985
324
+ invalid-out: |
325
+ validation02.invalid#0: INVALID
326
+ - (line 2) [/email] 'foo(at)mail.com': not matched to pattern /@/.
327
+ - (line 3) [/age] 'twenty': not a integer.
328
+ - (line 4) [/birth] 'Jun 01, 1985': not a date.
329
+ #
330
+ ---
331
+ name: validation03
332
+ desc: sequence of mapping
333
+ method: validation
334
+ schema: |
335
+ type: seq
336
+ sequence:
337
+ - type: map
338
+ mapping:
339
+ name:
340
+ type: str
341
+ required: true
342
+ email:
343
+ type: str
344
+ valid: |
345
+ - name: foo
346
+ email: foo@mail.com
347
+ - name: bar
348
+ email: bar@mail.net
349
+ - name: baz
350
+ email: baz@mail.org
351
+ valid-out: |
352
+ validation03.valid#0: valid.
353
+ invalid: |
354
+ - name: foo
355
+ email: foo@mail.com
356
+ - naem: bar
357
+ email: bar@mail.net
358
+ - name: baz
359
+ mail: baz@mail.org
360
+ invalid-out: |
361
+ validation03.invalid#0: INVALID
362
+ - (line 3) [/1] key 'name:' is required.
363
+ - (line 3) [/1/naem] key 'naem:' is undefined.
364
+ - (line 6) [/2/mail] key 'mail:' is undefined.
365
+ #
366
+ ---
367
+ name: validation04
368
+ desc: mapping of sequence
369
+ method: validation
370
+ schema: |
371
+ type: map
372
+ mapping:
373
+ company:
374
+ type: str
375
+ required: yes
376
+ email:
377
+ type: str
378
+ employees:
379
+ type: seq
380
+ sequence:
381
+ - type: map
382
+ mapping:
383
+ code:
384
+ type: int
385
+ required: yes
386
+ name:
387
+ type: str
388
+ required: yes
389
+ email:
390
+ type: str
391
+ valid: |
392
+ company: Kuwata lab.
393
+ email: webmaster@kuwata-lab.com
394
+ employees:
395
+ - code: 101
396
+ name: foo
397
+ email: foo@kuwata-lab.com
398
+ - code: 102
399
+ name: bar
400
+ email: bar@kuwata-lab.com
401
+ valid-out: |
402
+ validation04.valid#0: valid.
403
+ invalid: |
404
+ company: Kuwata Lab.
405
+ email: webmaster@kuwata-lab.com
406
+ employees:
407
+ - code: A101
408
+ name: foo
409
+ email: foo@kuwata-lab.com
410
+ - code: 102
411
+ name: bar
412
+ mail: bar@kuwata-lab.com
413
+ invalid-out: |
414
+ validation04.invalid#0: INVALID
415
+ - (line 4) [/employees/0/code] 'A101': not a integer.
416
+ - (line 9) [/employees/1/mail] key 'mail:' is undefined.
417
+ #
418
+ ---
419
+ name: validation05
420
+ desc: rule and entry
421
+ method: validation
422
+ schema: |
423
+ type: seq # new rule
424
+ sequence:
425
+ -
426
+ type: map # new rule
427
+ mapping:
428
+ name:
429
+ type: str # new rule
430
+ required: yes
431
+ email:
432
+ type: str # new rule
433
+ required: yes
434
+ pattern: /@/
435
+ password:
436
+ type: str # new rule
437
+ length: { max: 16, min: 8 }
438
+ age:
439
+ type: int # new rule
440
+ range: { max: 30, min: 18 }
441
+ # or assert: 18 <= val && val <= 30
442
+ blood:
443
+ type: str # new rule
444
+ enum:
445
+ - A
446
+ - B
447
+ - O
448
+ - AB
449
+ birth:
450
+ type: date # new rule
451
+ memo:
452
+ type: any # new rule
453
+ valid: |
454
+ - name: foo
455
+ email: foo@mail.com
456
+ password: xxx123456
457
+ age: 20
458
+ blood: A
459
+ birth: 1985-01-01
460
+ - name: bar
461
+ email: bar@mail.net
462
+ age: 25
463
+ blood: AB
464
+ birth: 1980-01-01
465
+ valid-out: |
466
+ validation05.valid#0: valid.
467
+ invalid: |
468
+ - name: foo
469
+ email: foo(at)mail.com
470
+ password: xxx123
471
+ age: twenty
472
+ blood: a
473
+ birth: 1985-01-01
474
+ - given-name: bar
475
+ family-name: Bar
476
+ email: bar@mail.net
477
+ age: 15
478
+ blood: AB
479
+ birth: 1980/01/01
480
+ invalid-out*:
481
+ ruby: |
482
+ validation05.invalid#0: INVALID
483
+ - (line 2) [/0/email] 'foo(at)mail.com': not matched to pattern /@/.
484
+ - (line 3) [/0/password] 'xxx123': too short (length 6 < min 8).
485
+ - (line 4) [/0/age] 'twenty': not a integer.
486
+ - (line 5) [/0/blood] 'a': invalid blood value.
487
+ - (line 7) [/1/given-name] key 'given-name:' is undefined.
488
+ - (line 7) [/1] key 'name:' is required.
489
+ - (line 8) [/1/family-name] key 'family-name:' is undefined.
490
+ - (line 10) [/1/age] '15': too small (< min 18).
491
+ - (line 12) [/1/birth] '1980/01/01': not a date.
492
+ java: |
493
+ validation05.invalid#0: INVALID
494
+ - (line 2) [/0/email] 'foo(at)mail.com': not matched to pattern /@/.
495
+ - (line 3) [/0/password] 'xxx123': too short (length 6 < min 8).
496
+ - (line 4) [/0/age] 'twenty': not a integer.
497
+ - (line 5) [/0/blood] 'a': invalid blood value.
498
+ - (line 7) [/1] key 'name:' is required.
499
+ - (line 7) [/1/given-name] key 'given-name:' is undefined.
500
+ - (line 8) [/1/family-name] key 'family-name:' is undefined.
501
+ - (line 10) [/1/age] '15': too small (< min 18).
502
+ - (line 12) [/1/birth] '1980/01/01': not a date.
503
+ #
504
+ ---
505
+ name: validation06
506
+ desc: unique constraint
507
+ method: validation
508
+ schema: |
509
+ type: seq
510
+ sequence:
511
+ - type: map
512
+ required: yes
513
+ mapping:
514
+ name:
515
+ type: str
516
+ required: yes
517
+ unique: yes
518
+ email:
519
+ type: str
520
+ groups:
521
+ type: seq
522
+ sequence:
523
+ - type: str
524
+ unique: yes
525
+ valid: |
526
+ - name: foo
527
+ email: admin@mail.com
528
+ groups:
529
+ - users
530
+ - foo
531
+ - admin
532
+ - name: bar
533
+ email: admin@mail.com
534
+ groups:
535
+ - users
536
+ - admin
537
+ - name: baz
538
+ email: baz@mail.com
539
+ groups:
540
+ - users
541
+ valid-out: |
542
+ validation06.valid#0: valid.
543
+ invalid: |
544
+ - name: foo
545
+ email: admin@mail.com
546
+ groups:
547
+ - foo
548
+ - users
549
+ - admin
550
+ - foo
551
+ - name: bar
552
+ email: admin@mail.com
553
+ groups:
554
+ - admin
555
+ - users
556
+ - name: bar
557
+ email: baz@mail.com
558
+ groups:
559
+ - users
560
+ invalid-out: |
561
+ validation06.invalid#0: INVALID
562
+ - (line 7) [/0/groups/3] 'foo': is already used at '/0/groups/0'.
563
+ - (line 13) [/2/name] 'bar': is already used at '/1/name'.
564
+ #
565
+ ---
566
+ name: validation12
567
+ desc: json
568
+ method: validation
569
+ schema: |
570
+ { "type": "map",
571
+ "required": true,
572
+ "mapping": {
573
+ "name": {
574
+ "type": "str",
575
+ "required": true
576
+ },
577
+ "email": {
578
+ "type": "str"
579
+ },
580
+ "age": {
581
+ "type": "int"
582
+ },
583
+ "gender": {
584
+ "type": "str",
585
+ "enum": ["M", "F"]
586
+ },
587
+ "favorite": {
588
+ "type": "seq",
589
+ "sequence": [
590
+ { "type": "str" }
591
+ ]
592
+ }
593
+ }
594
+ }
595
+ valid: |
596
+ { "name": "Foo",
597
+ "email": "foo@mail.com",
598
+ "age": 20,
599
+ "gender": "F",
600
+ "favorite": [
601
+ "football",
602
+ "basketball",
603
+ "baseball"
604
+ ]
605
+ }
606
+ valid-out: |
607
+ validation12.valid#0: valid.
608
+ invalid: |
609
+ {
610
+ "mail": "foo@mail.com",
611
+ "age": twenty,
612
+ "gender": "X",
613
+ "favorite": [ 123, 456 ]
614
+ }
615
+ invalid-out: |
616
+ validation12.invalid#0: INVALID
617
+ - (line 1) [/] key 'name:' is required.
618
+ - (line 2) [/mail] key 'mail:' is undefined.
619
+ - (line 3) [/age] 'twenty': not a integer.
620
+ - (line 4) [/gender] 'X': invalid gender value.
621
+ - (line 5) [/favorite/0] '123': not a string.
622
+ - (line 5) [/favorite/1] '456': not a string.
623
+ #
624
+ ---
625
+ name: validation13
626
+ desc: anchor and alias
627
+ method: validation
628
+ schema: |
629
+ type: seq
630
+ sequence:
631
+ - &employee
632
+ type: map
633
+ mapping:
634
+ "given-name": &name
635
+ type: str
636
+ required: yes
637
+ "family-name": *name
638
+ "post":
639
+ enum:
640
+ - exective
641
+ - manager
642
+ - clerk
643
+ "supervisor": *employee
644
+ valid: |
645
+ - &foo
646
+ given-name: foo
647
+ family-name: Foo
648
+ post: exective
649
+ - &bar
650
+ given-name: bar
651
+ family-name: Bar
652
+ post: manager
653
+ supervisor: *foo
654
+ - given-name: baz
655
+ family-name: Baz
656
+ post: clerk
657
+ supervisor: *bar
658
+ - given-name: zak
659
+ family-name: Zak
660
+ post: clerk
661
+ supervisor: *bar
662
+ valid-out: |
663
+ validation13.valid#0: valid.
664
+ invalid: |
665
+ - &foo
666
+ #given-name: foo
667
+ family-name: Foo
668
+ post: exective
669
+ - &bar
670
+ given-name: bar
671
+ family-name: Bar
672
+ post: manager
673
+ supervisor: *foo
674
+ - given-name: baz
675
+ family-name: Baz
676
+ post: clerk
677
+ supervisor: *bar
678
+ - given-name: zak
679
+ family-name: Zak
680
+ post: clerk
681
+ supervisor: *bar
682
+ invalid-out: |
683
+ validation13.invalid#0: INVALID
684
+ - (line 1) [/0] key 'given-name:' is required.
685
+ #
686
+ ---
687
+ name: validation14
688
+ desc: anchor and alias
689
+ method: validation
690
+ schema: |
691
+ type: map
692
+ mapping:
693
+ =: # default rule
694
+ type: number
695
+ range: { max: 1, min: -1 }
696
+ valid: |
697
+ value1: 0
698
+ value2: 0.5
699
+ value3: -0.9
700
+ valid-out: |
701
+ validation14.valid#0: valid.
702
+ invalid: |
703
+ value1: 0
704
+ value2: 1.1
705
+ value3: -2.0
706
+ invalid-out: |
707
+ validation14.invalid#0: INVALID
708
+ - (line 2) [/value2] '1.1': too large (> max 1).
709
+ - (line 3) [/value3] '-2.0': too small (< min -1).
710
+ #
711
+ ---
712
+ name: validation15
713
+ desc: anchor and alias
714
+ method: validation
715
+ schema: |
716
+ type: map
717
+ mapping:
718
+ "group":
719
+ type: map
720
+ mapping:
721
+ "name": &name
722
+ type: str
723
+ required: yes
724
+ "email": &email
725
+ type: str
726
+ pattern: /@/
727
+ required: no
728
+ "user":
729
+ type: map
730
+ mapping:
731
+ "name":
732
+ <<: *name # merge
733
+ length: { max: 16 } # override
734
+ "email":
735
+ <<: *email # merge
736
+ required: yes # add
737
+ valid: |
738
+ group:
739
+ name: foo
740
+ email: foo@mail.com
741
+ user:
742
+ name: bar
743
+ email: bar@mail.com
744
+ valid-out: |
745
+ validation15.valid#0: valid.
746
+ invalid: |
747
+ group:
748
+ name: foo
749
+ email: foo@mail.com
750
+ user:
751
+ name: toooooo-looooong-name
752
+ invalid-out: |
753
+ validation15.invalid#0: INVALID
754
+ - (line 4) [/user] key 'email:' is required.
755
+ - (line 5) [/user/name] 'toooooo-looooong-name': too long (length 21 > max 16).
756
+ #