kwalify 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/kwalify/rule.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  ###
2
- ### $Rev: 22 $
3
- ### $Release: 0.3.0 $
2
+ ### $Rev: 35 $
3
+ ### $Release: 0.4.0 $
4
4
  ### copyright(c) 2005 kuwata-lab all rights reserved.
5
5
  ###
6
6
 
@@ -250,23 +250,29 @@ module Kwalify
250
250
  if val != nil && !val.is_a?(Hash)
251
251
  #* key=:mapping_notmap msg="not a mapping."
252
252
  raise schema_error(:mapping_notmap, rule, curr_path, val)
253
- elsif val == nil || val.empty?
253
+ elsif val == nil || (val.empty? && !val.default)
254
254
  #* key=:mapping_noelem msg="required at least one element."
255
255
  raise schema_error(:mapping_noelem, rule, curr_path, val)
256
256
  else
257
257
  @mapping = {}
258
+ if val.default
259
+ elem = val.default # hash
260
+ rule = rule_table[elem.__id__]
261
+ rule ||= Rule.new(nil, self).configure(elem, "#{curr_path}/=", rule_table)
262
+ @mapping.default = rule
263
+ end
258
264
  val.each do |key, elem|
259
265
  ##* key=:key_duplicate msg="key duplicated."
260
266
  #raise schema_error(:key_duplicate, rule, curr_path, key) if @mapping.key?(key)
261
267
  elem ||= {}
262
268
  rule = rule_table[elem.__id__]
263
269
  rule ||= Rule.new(nil, self).configure(elem, "#{curr_path}/#{key}", rule_table)
264
- if key == '*'
270
+ if key == '='
265
271
  @mapping.default = rule
266
272
  else
267
273
  @mapping[key] = rule
268
274
  end
269
- end
275
+ end if val
270
276
  end
271
277
 
272
278
  else
@@ -277,7 +283,7 @@ module Kwalify
277
283
 
278
284
  if @type == 'seq'
279
285
  #* key=:seq_nosequence msg="type 'seq' requires 'sequence:'."
280
- raise Kwalify.validate_error(:seq_nosequence, rule, path, nil) unless hash.key?('sequence')
286
+ raise schema_error(:seq_nosequence, rule, path, nil) unless hash.key?('sequence')
281
287
  #* key=:seq_conflict msg="not available with sequence."
282
288
  raise schema_error(:seq_conflict, rule, path, 'enum:') if @enum
283
289
  raise schema_error(:seq_conflict, rule, path, 'pattern:') if @pattern
@@ -286,7 +292,7 @@ module Kwalify
286
292
  raise schema_error(:seq_conflict, rule, path, 'length:') if @length
287
293
  elsif @type == 'map'
288
294
  #* key=:map_nomapping msg="type 'map' requires 'mapping:'."
289
- raise Kwalify.validate_error(:map_nomapping, rule, path, nil) unless hash.key?('mapping')
295
+ raise schema_error(:map_nomapping, rule, path, nil) unless hash.key?('mapping')
290
296
  #* key=:map_conflict msg="not available with mapping."
291
297
  raise schema_error(:map_conflict, rule, path, 'enum:') if @enum
292
298
  raise schema_error(:map_conflict, rule, path, 'pattern:') if @pattern
data/lib/kwalify/types.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  ###
2
- ### $Rev: 18 $
3
- ### $Release: 0.3.0 $
2
+ ### $Rev: 25 $
3
+ ### $Release: 0.4.0 $
4
4
  ### copyright(c) 2005 kuwata-lab all rights reserved.
5
5
  ###
6
6
 
@@ -114,20 +114,21 @@ module Kwalify
114
114
 
115
115
 
116
116
  module TypeHelper
117
- def collection_class?(klass)
118
- return klass == Array || klass == Hash
119
- end
120
-
121
- def scalar_class?(klass)
122
- return klass != Array && klass != Hash && klass != Object
123
- end
117
+ #--
118
+ #def collection_class?(klass)
119
+ # return klass.is_a?(Array) || klass.is_a?(Hash)
120
+ #end
121
+ #
122
+ #def scalar_class?(klass)
123
+ # return !klass.is_a?(Array) && !klass.is_a?(Hash) && klass != Object
124
+ #end
124
125
 
125
126
  def collection?(val)
126
- return collection_class?(val.class)
127
+ return val.is_a?(Array) || val.is_a?(Hash)
127
128
  end
128
129
 
129
130
  def scalar?(val)
130
- return scalar_class?(val.class)
131
+ return !val.is_a?(Array) && !val.is_a?(Hash) && val.class != Object
131
132
  end
132
133
  end
133
134
 
@@ -1,6 +1,6 @@
1
1
  ###
2
2
  ### $Rev: 5 $
3
- ### $Release: 0.3.0 $
3
+ ### $Release: 0.4.0 $
4
4
  ### copyright(c) 2005 kuwata-lab all rights reserved.
5
5
  ###
6
6
 
@@ -1,6 +1,6 @@
1
1
  ###
2
2
  ### $Rev: 6 $
3
- ### $Release: 0.3.0 $
3
+ ### $Release: 0.4.0 $
4
4
  ### copyright(c) 2005 kuwata-lab all rights reserved.
5
5
  ###
6
6
 
@@ -1,6 +1,6 @@
1
1
  ###
2
2
  ### $Rev: 10 $
3
- ### $Release: 0.3.0 $
3
+ ### $Release: 0.4.0 $
4
4
  ### copyright(c) 2005 kuwata-lab all rights reserved.
5
5
  ###
6
6
 
@@ -1,6 +1,6 @@
1
1
  ###
2
- ### $Rev: 21 $
3
- ### $Release: 0.3.0 $
2
+ ### $Rev: 32 $
3
+ ### $Release: 0.4.0 $
4
4
  ### copyright(c) 2005 kuwata-lab all rights reserved.
5
5
  ###
6
6
 
@@ -39,9 +39,9 @@ module Kwalify
39
39
  end
40
40
 
41
41
 
42
- def validate(val)
42
+ def validate(value)
43
43
  path = ""; errors = []; done = {}
44
- _validate(val, @rule, path, errors, done)
44
+ _validate(value, @rule, path, errors, done)
45
45
  return errors
46
46
  end
47
47
 
@@ -49,107 +49,107 @@ module Kwalify
49
49
  protected
50
50
 
51
51
 
52
- def validate_hook(val, rule, path, errors)
52
+ def validate_hook(value, rule, path, errors)
53
53
  end
54
54
 
55
55
 
56
- def _validate(val, rule, path, errors, done)
57
- if Kwalify.collection_class?(val.class)
58
- return true if done[val.__id__] # avoid infinite loop
59
- done[val.__id__] = true
56
+ def _validate(value, rule, path, errors, done)
57
+ if Kwalify.collection?(value)
58
+ return true if done[value.__id__] # avoid infinite loop
59
+ done[value.__id__] = true
60
60
  end
61
- if rule.required && val == nil
61
+ if rule.required && value == nil
62
62
  #* key=:required_novalue msg="value required but none."
63
- errors << validate_error(:required_novalue, rule, path, val)
63
+ errors << validate_error(:required_novalue, rule, path, value)
64
64
  return
65
65
  end
66
- if rule.klass && val != nil && !val.is_a?(rule.klass)
66
+ if rule.klass && value != nil && !value.is_a?(rule.klass)
67
67
  #* key=:type_unmatch msg="not a %s."
68
- errors << validate_error(:type_unmatch, rule, path, val, [Kwalify.word(rule.type)])
68
+ errors << validate_error(:type_unmatch, rule, path, value, [Kwalify.word(rule.type)])
69
69
  return
70
70
  end
71
71
  #
72
72
  n = errors.length
73
73
  if rule.sequence
74
- _validate_sequence(val, rule, path, errors, done)
74
+ _validate_sequence(value, rule, path, errors, done)
75
75
  elsif rule.mapping
76
- _validate_mapping(val, rule, path, errors, done)
76
+ _validate_mapping(value, rule, path, errors, done)
77
77
  else
78
- _validate_scalar(val, rule, path, errors, done)
78
+ _validate_scalar(value, rule, path, errors, done)
79
79
  end
80
80
  return unless errors.length == n
81
81
  #
82
- validate_hook(val, rule, path, errors)
83
- @block.call(val, rule, path, errors) if @block
82
+ validate_hook(value, rule, path, errors)
83
+ @block.call(value, rule, path, errors) if @block
84
84
  end
85
85
 
86
86
 
87
87
  private
88
88
 
89
89
 
90
- def _validate_scalar(val, rule, path, errors, done)
90
+ def _validate_scalar(value, rule, path, errors, done)
91
91
  assert_error("rule.sequence.class==#{rule.sequence.class.name} (expected NilClass)") if rule.sequence
92
92
  assert_error("rule.mapping.class==#{rule.mapping.class.name} (expected NilClass)") if rule.mapping
93
93
  if rule.assert_proc
94
- unless rule.assert_proc.call(val)
94
+ unless rule.assert_proc.call(value)
95
95
  #* key=:assert_failed msg="assertion expression failed (%s)."
96
- errors << validate_error(:assert_failed, rule, path, val, [rule.assert])
96
+ errors << validate_error(:assert_failed, rule, path, value, [rule.assert])
97
97
  end
98
98
  end
99
99
  if rule.enum
100
- unless rule.enum.include?(val)
100
+ unless rule.enum.include?(value)
101
101
  keyname = File.basename(path)
102
102
  keyname = 'enum' if keyname =~ /\A\d+\z/
103
103
  #* key=:enum_notexist msg="invalid %s value."
104
- errors << validate_error(:enum_notexist, rule, path, val, [keyname])
104
+ errors << validate_error(:enum_notexist, rule, path, value, [keyname])
105
105
  end
106
106
  end
107
107
  #
108
- return if val == nil
108
+ return if value == nil
109
109
  #
110
110
  if rule.pattern
111
- unless val.to_s =~ rule.pattern
111
+ unless value.to_s =~ rule.pattern
112
112
  #* key=:pattern_unmatch msg="not matched to pattern %s."
113
- errors << validate_error(:pattern_unmatch, rule, path, val, [rule.pattern.inspect])
113
+ errors << validate_error(:pattern_unmatch, rule, path, value, [rule.pattern.inspect])
114
114
  end
115
115
  end
116
116
  if rule.range
117
- assert_error("val.class=#{val.class.name}") unless Kwalify.scalar?(val)
118
- if rule.range['max'] && rule.range['max'] < val
117
+ assert_error("value.class=#{value.class.name}") unless Kwalify.scalar?(value)
118
+ if rule.range['max'] && rule.range['max'] < value
119
119
  #* key=:range_toolarge msg="too large (> max %s)."
120
- errors << validate_error(:range_toolarge, rule, path, val, [rule.range['max'].to_s])
120
+ errors << validate_error(:range_toolarge, rule, path, value, [rule.range['max'].to_s])
121
121
  end
122
- if rule.range['min'] && rule.range['min'] > val
122
+ if rule.range['min'] && rule.range['min'] > value
123
123
  #* key=:range_toosmall msg="too small (< min %s)."
124
- errors << validate_error(:range_toosmall, rule, path, val, [rule.range['min'].to_s])
124
+ errors << validate_error(:range_toosmall, rule, path, value, [rule.range['min'].to_s])
125
125
  end
126
- if rule.range['max-ex'] && rule.range['max-ex'] <= val
126
+ if rule.range['max-ex'] && rule.range['max-ex'] <= value
127
127
  #* key=:range_toolargeex msg="too large (>= max %s)."
128
- errors << validate_error(:range_toolargeex, rule, path, val, [rule.range['max-ex'].to_s])
128
+ errors << validate_error(:range_toolargeex, rule, path, value, [rule.range['max-ex'].to_s])
129
129
  end
130
- if rule.range['min-ex'] && rule.range['min-ex'] >= val
130
+ if rule.range['min-ex'] && rule.range['min-ex'] >= value
131
131
  #* key=:range_toosmallex msg="too small (<= min %s)."
132
- errors << validate_error(:range_toosmallex, rule, path, val, [rule.range['min-ex'].to_s])
132
+ errors << validate_error(:range_toosmallex, rule, path, value, [rule.range['min-ex'].to_s])
133
133
  end
134
134
  end
135
135
  if rule.length
136
- assert_error("val.class=#{val.class.name}") unless val.is_a?(String) || val.is_a?(Text)
137
- len = val.to_s.length
136
+ assert_error("value.class=#{value.class.name}") unless value.is_a?(String) || value.is_a?(Text)
137
+ len = value.to_s.length
138
138
  if rule.length['max'] && rule.length['max'] < len
139
139
  #* key=:length_toolong msg="too long (length %d > max %d)."
140
- errors << validate_error(:length_toolong, rule, path, val, [len, rule.length['max']])
140
+ errors << validate_error(:length_toolong, rule, path, value, [len, rule.length['max']])
141
141
  end
142
142
  if rule.length['min'] && rule.length['min'] > len
143
143
  #* key=:length_tooshort msg="too short (length %d < min %d)."
144
- errors << validate_error(:length_tooshort, rule, path, val, [len, rule.length['min']])
144
+ errors << validate_error(:length_tooshort, rule, path, value, [len, rule.length['min']])
145
145
  end
146
146
  if rule.length['max-ex'] && rule.length['max-ex'] <= len
147
147
  #* key=:length_toolongex msg="too long (length %d >= max %d)."
148
- errors << validate_error(:length_toolongex, rule, path, val, [len, rule.length['max-ex']])
148
+ errors << validate_error(:length_toolongex, rule, path, value, [len, rule.length['max-ex']])
149
149
  end
150
150
  if rule.length['min-ex'] && rule.length['min-ex'] >= len
151
151
  #* key=:length_tooshortex msg="too short (length %d <= min %d)."
152
- errors << validate_error(:length_tooshortex, rule, path, val, [len, rule.length['min-ex']])
152
+ errors << validate_error(:length_tooshortex, rule, path, value, [len, rule.length['min-ex']])
153
153
  end
154
154
  end
155
155
  end
@@ -191,7 +191,7 @@ module Kwalify
191
191
  # #* key=:value_notunique msg="is already used at '%s'."
192
192
  errors << validate_error(:value_notunique, rule, "#{path}/#{i}", val, "#{path}/#{table[val]}")
193
193
  else
194
- table[val] = i
194
+ table[val] = i
195
195
  end
196
196
  end
197
197
  end
@@ -207,15 +207,15 @@ module Kwalify
207
207
  errors << validate_error(:required_nokey, rule, path, hash, [key])
208
208
  end
209
209
  end
210
- hash.each do |key, value|
210
+ hash.each do |key, val|
211
211
  rule = map_rule.mapping[key]
212
- if rule
213
- _validate(value, rule, "#{path}/#{key}", errors, done) ## validate recursively
214
- else
212
+ unless rule
215
213
  #* key=:key_undefined msg="key '%s' is undefined."
216
- errors << validate_error(:key_undefined, rule, path, nil, ["#{key}:"])
214
+ errors << validate_error(:key_undefined, rule, path, hash, ["#{key}:"])
217
215
  ##* key=:key_undefined msg="undefined key."
218
216
  #errors << validate_error(:key_undefined, rule, path, "#{key}:")
217
+ else
218
+ _validate(val, rule, "#{path}/#{key}", errors, done) ## validate recursively
219
219
  end
220
220
  end
221
221
  end
@@ -223,3 +223,11 @@ module Kwalify
223
223
  end
224
224
 
225
225
  end
226
+
227
+ if __FILE__ == $0
228
+ require 'kwalify/parser'
229
+ parser = Kwalify::Parser.new(File.read(ARGV.shift))
230
+ schema = parser.parse()
231
+ validator = Kwalify::Validator.new(schema)
232
+ YARGF.read()
233
+ end
@@ -1,20 +1,21 @@
1
1
  ###
2
- ### $Rev: 21 $
3
- ### $Release: 0.3.0 $
2
+ ### $Rev: 31 $
3
+ ### $Release: 0.4.0 $
4
4
  ### copyright(c) 2005 kuwata-lab all rights reserved.
5
5
  ###
6
6
 
7
- if $0 == __FILE__
8
- testdir = File.dirname(__FILE__)
9
- libdir = File.dirname(testdir) + "/lib"
10
- $LOAD_PATH << libdir << testdir
11
- require 'test/unit'
12
- require 'test/unit/ui/console/testrunner'
13
- require 'kwalify'
14
- require 'kwalify/util/assert-diff'
15
- require 'yaml'
7
+ unless defined?(TESTDIR)
8
+ TESTDIR = File.dirname(__FILE__)
9
+ libdir = File.dirname(TESTDIR) + "/lib"
10
+ $LOAD_PATH << libdir << TESTDIR
16
11
  end
17
12
 
13
+ require 'test/unit'
14
+ require 'test/unit/ui/console/testrunner'
15
+ require 'kwalify'
16
+ require 'kwalify/util/assert-diff'
17
+ require 'yaml'
18
+
18
19
 
19
20
  class MetaValidatorTest < Test::Unit::TestCase
20
21
 
@@ -80,6 +81,10 @@ class MetaValidatorTest < Test::Unit::TestCase
80
81
 
81
82
  end
82
83
 
84
+ #if $0 == __FILE__
85
+ # Test::Unit::UI::Console::TestRunner.run(MetaValidatorTest)
86
+ #end
87
+
83
88
  __END__
84
89
  ---
85
90
  name: schema_notmap
@@ -0,0 +1,1276 @@
1
+ ###
2
+ ### $Rev: 35 $
3
+ ### $Release: 0.4.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 'yaml'
18
+ require 'pp'
19
+ require 'stringio'
20
+
21
+
22
+ class ParserTest < Test::Unit::TestCase
23
+ def _test()
24
+ parser = Kwalify::Parser.new(@input)
25
+ if @error_class
26
+ assert_raise(@error_class) do
27
+ doc = parser.parse()
28
+ end
29
+ else
30
+ doc = parser.parse()
31
+ sio = StringIO.new
32
+ PP.pp(doc, sio)
33
+ actual = sio.string
34
+ if $log
35
+ File.open("#{@name}.expected", 'w') { |f| f.write(@expected) }
36
+ File.open("#{@name}.actual", 'w') { |f| f.write(actual) }
37
+ end
38
+ if $print
39
+ print actual
40
+ else
41
+ assert_equal_with_diff(@expected, actual)
42
+ end
43
+ end
44
+ end
45
+
46
+ #str = DATA.read() # doesn't work when required by other script
47
+ str = File.read(__FILE__)
48
+ str.gsub!(/.*^__END__$/m, '')
49
+ doc_table = {}
50
+ YAML.load_documents(str) do |doc|
51
+ name = doc['name']
52
+ raise "name '#{name}' is duplicated." if doc_table[name]
53
+ doc_table[name] = doc
54
+ next if $target && $target != doc['name']
55
+ #if $target && $show
56
+ # puts doc.to_yaml
57
+ # exit
58
+ #end
59
+ s = <<-END
60
+ def test_#{name}
61
+ @name = #{doc['name'].dump}
62
+ @input = #{doc['input'].dump}
63
+ @expected = #{doc['expected'].dump}
64
+ @error_class = #{doc['error'] ? doc['error'] : 'nil'}
65
+ @option = #{doc['option'] ? doc['option'].dump : 'nil'}
66
+ _test()
67
+ end
68
+ END
69
+ if $target && $show
70
+ puts s
71
+ exit
72
+ end
73
+ eval s
74
+ end
75
+ end
76
+
77
+ #if $0 == __FILE__
78
+ # Test::Unit::UI::Console::TestRunner.run(ParserTest)
79
+ #end
80
+
81
+ __END__
82
+ ---
83
+ name: parse01
84
+ desc: basic
85
+ #flag: print
86
+ #
87
+ input: |
88
+ - AAA
89
+ - BBB
90
+ - CCC
91
+ #
92
+ expected: |
93
+ ["AAA", "BBB", "CCC"]
94
+ #
95
+ ---
96
+ name: parse02
97
+ desc: scalar
98
+ #
99
+ input: |
100
+ - abc
101
+ - 123
102
+ - 3.14
103
+ - true
104
+ - false
105
+ - yes
106
+ - no
107
+ - ~
108
+ - null
109
+ - "123"
110
+ - '456'
111
+ - 2005-01-01
112
+ - :sym
113
+ #
114
+ expected: |
115
+ ["abc",
116
+ 123,
117
+ 3.14,
118
+ true,
119
+ false,
120
+ true,
121
+ false,
122
+ nil,
123
+ nil,
124
+ "123",
125
+ "456",
126
+ #<Date: 4906743/2,0,2299161>,
127
+ :sym]
128
+ # ["abc", 123, true, false, true, false, nil, nil, "123", "456", #<Date: 4906743/2,0,2299161>, :sym]
129
+ #
130
+ ---
131
+ name: parse03
132
+ desc: nested sequence
133
+ #
134
+ input: |
135
+ - AAA
136
+ -
137
+ - BBB1
138
+ - BBB2
139
+ - CCC
140
+ #
141
+ expected: |
142
+ ["AAA", ["BBB1", "BBB2"], "CCC"]
143
+ #
144
+ ---
145
+ name: parse04
146
+ desc: nested sequence #2
147
+ #
148
+ input: |
149
+ - A
150
+ -
151
+ - B1
152
+ -
153
+ - B1-1
154
+ - B1-2
155
+ - C
156
+ #
157
+ expected: |
158
+ ["A", ["B1", ["B1-1", "B1-2"]], "C"]
159
+ #
160
+ ---
161
+ name: parse05
162
+ desc: null item of sequence
163
+ #
164
+ input: |
165
+ - A
166
+ -
167
+ - C
168
+ -
169
+ -
170
+ -
171
+ - G
172
+ #
173
+ expected: |
174
+ ["A", nil, "C", nil, nil, nil, "G"]
175
+ #
176
+ ---
177
+ name: parse06
178
+ desc: null item of nested sequence
179
+ #
180
+ input: |
181
+ -
182
+ -
183
+ -
184
+ -
185
+ -
186
+ -
187
+ #
188
+ expected: |
189
+ [[[nil, nil, nil]], nil]
190
+ #
191
+ ---
192
+ name: parse07
193
+ desc: sequence with empty lines
194
+ #
195
+ input: |
196
+
197
+ - A
198
+
199
+ -
200
+
201
+
202
+ - B
203
+
204
+
205
+ -
206
+ #
207
+ expected: |
208
+ ["A", ["B"], nil]
209
+ #
210
+ ---
211
+ name: parse08
212
+ desc: syntax error - invalid indent of sequence.
213
+ error: Kwalify::ParseError
214
+ #
215
+ input: |
216
+ - AAA
217
+ - BBB1
218
+ - BBB2
219
+ - CCC
220
+ #
221
+ expected: |
222
+ #
223
+ ---
224
+ name: parse09
225
+ desc: syntax error - sequence item is exepcted.
226
+ error: Kwalify::ParseError
227
+ #
228
+ input: |
229
+ -
230
+ - a1
231
+ - a2
232
+ a3
233
+ -
234
+ - b1
235
+ - b2
236
+ b3
237
+ #
238
+ expected: |
239
+ #
240
+ ---
241
+ name: parse11
242
+ desc: mapping
243
+ #
244
+ input: |
245
+ A: foo
246
+ B: bar
247
+ C : baz
248
+ #
249
+ expected: |
250
+ {"A"=>"foo", "B"=>"bar", "C"=>"baz"}
251
+ ---
252
+ name: parse12
253
+ desc: mapping of scalar
254
+ #
255
+ input: |
256
+ abc: ABC
257
+ 123: 1.23
258
+ 3.14: 314
259
+ #
260
+ expected: |
261
+ {"abc"=>"ABC", 3.14=>314, 123=>1.23}
262
+ ---
263
+ name: parse12b
264
+ desc: mapping of scalar
265
+ #
266
+ input: |
267
+ true: yes
268
+ false: no
269
+ #
270
+ expected: |
271
+ {false=>false, true=>true}
272
+ #
273
+ ---
274
+ name: parse12c
275
+ desc: mapping of scalar
276
+ #
277
+ input: |
278
+ :sym: :symbol
279
+ --: -10
280
+ #
281
+ expected: |
282
+ {"--"=>-10, :sym=>:symbol}
283
+ #
284
+ ---
285
+ name: parse13
286
+ desc: nested mapping
287
+ #
288
+ input: |
289
+ A: 10
290
+ B:
291
+ B1: 21
292
+ B2: 22
293
+ C: 30
294
+ #
295
+ expected: |
296
+ {"A"=>10, "B"=>{"B1"=>21, "B2"=>22}, "C"=>30}
297
+ #
298
+ ---
299
+ name: parse14
300
+ desc: nested mapping #2
301
+ #
302
+ input: |
303
+ A: 10
304
+ B:
305
+ B1:
306
+ B1-1: 21
307
+ B1-2: 22
308
+ B1-3: 23
309
+ C: 30
310
+ #
311
+ expected: |
312
+ {"A"=>10, "B"=>{"B1"=>{"B1-1"=>21, "B1-2"=>22, "B1-3"=>23}}, "C"=>30}
313
+ #
314
+ ---
315
+ name: parse15
316
+ desc: null item in mapping
317
+ #
318
+ input: |
319
+ A:
320
+ B:
321
+ C:
322
+ D:
323
+ #
324
+ expected: |
325
+ {"A"=>nil, "B"=>nil, "C"=>nil, "D"=>nil}
326
+ #
327
+ ---
328
+ name: parse16
329
+ desc: null mapping
330
+ #
331
+ input: |
332
+ A:
333
+ B:
334
+ B1:
335
+ B1-2:
336
+ C:
337
+ #
338
+ expected: |
339
+ {"A"=>nil, "B"=>{"B1"=>{"B1-2"=>nil}}, "C"=>nil}
340
+ #
341
+ ---
342
+ name: parse17
343
+ desc: mapping with empty lines
344
+ #
345
+ input: |
346
+
347
+ A: 1
348
+
349
+ B:
350
+
351
+
352
+ B1:
353
+
354
+
355
+
356
+ B1a: 2
357
+ C: 3
358
+
359
+ #
360
+ expected: |
361
+ {"A"=>1, "B"=>{"B1"=>{"B1a"=>2}}, "C"=>3}
362
+ #
363
+ ---
364
+ name: parse18
365
+ desc: parse error - invalid indent of mapping.
366
+ error: Kwalify::ParseError
367
+ #
368
+ input: |
369
+ A: 10
370
+ B: 20
371
+ B1: 21
372
+ B2: 22
373
+ C: 30
374
+ #
375
+ expected: |
376
+
377
+ #
378
+ ---
379
+ name: parse19
380
+ desc: parse error - mapping item is expected.
381
+ error: Kwalify::ParseError
382
+ #
383
+ input: |
384
+ A:
385
+ a1: 1
386
+ a2: 2
387
+ a3 3
388
+ B:
389
+ b1: 1
390
+ b2: 2
391
+ b3 3
392
+ expected: |
393
+ #
394
+ ---
395
+ name: parse21
396
+ desc: seq of mapping
397
+ #
398
+ input: |
399
+ -
400
+ x: 10
401
+ y: 20
402
+ -
403
+ x: 15
404
+ y: 25
405
+ #
406
+ expected: |
407
+ [{"x"=>10, "y"=>20}, {"x"=>15, "y"=>25}]
408
+ ---
409
+ name: parse22
410
+ desc: seq of mapping (inline)
411
+ #
412
+ input: |
413
+ - x: 10
414
+ y: 20
415
+ - x: 15
416
+ y: 25
417
+ #
418
+ expected: |
419
+ [{"x"=>10, "y"=>20}, {"x"=>15, "y"=>25}]
420
+ ---
421
+ name: parse23
422
+ desc: seq of seq of seq (inline)
423
+ #
424
+ input: |
425
+ - - - a
426
+ - b
427
+ - - - c
428
+ - d
429
+ #
430
+ expected: |
431
+ [[["a", "b"]], [["c", "d"]]]
432
+ ---
433
+ name: parse24
434
+ desc: map of sequence
435
+ #
436
+ input: |
437
+ foo:
438
+ - 1
439
+ - 2
440
+ - 3
441
+ bar:
442
+ - 4
443
+ - 5
444
+ - 6
445
+ #
446
+ expected: |
447
+ {"foo"=>[1, 2, 3], "bar"=>[4, 5, 6]}
448
+ ---
449
+ name: parse25
450
+ desc: map of sequence (inline)
451
+ #
452
+ input: |
453
+ foo: - 1
454
+ - 2
455
+ - 3
456
+ bar: - 4
457
+ - 5
458
+ - 6
459
+ #
460
+ expected: |
461
+ {"foo"=>[1, 2, 3], "bar"=>[4, 5, 6]}
462
+ ---
463
+ name: parse26
464
+ desc: map of map of map (inline)
465
+ #
466
+ input: |
467
+ A: a: 1: 100
468
+ 2: 200
469
+ B: b: 3: 300
470
+ 4: 400
471
+ #
472
+ expected: |
473
+ {"A"=>{"a"=>{1=>100, 2=>200}}, "B"=>{"b"=>{3=>300, 4=>400}}}
474
+ ---
475
+ name: comment1
476
+ desc: line comment
477
+ #
478
+ input: |
479
+ # comment
480
+ - A
481
+ - B
482
+ # comment
483
+ -
484
+ # comment
485
+ - C
486
+ #
487
+ expected: |
488
+ ["A", "B", ["C"]]
489
+ ---
490
+ name: comment2
491
+ desc: escape line comment
492
+ #
493
+ input: |
494
+ # comment
495
+ - A
496
+ - B:
497
+ "# comment"
498
+ -
499
+ '# comment'
500
+ #
501
+ expected: |
502
+ ["A", {"B"=>"# comment"}, "# comment"]
503
+ ---
504
+ name: comment3
505
+ desc: line comment with seq and map
506
+ #
507
+ input: |
508
+ - A # comment
509
+ - B: # comment
510
+ C: foo # comment
511
+ D: "bar#bar" #comment
512
+ #
513
+ expected: |
514
+ ["A", {"B"=>{"C"=>"foo", "D"=>"bar#bar"}}]
515
+ ---
516
+ name: comment4
517
+ desc: line comment with anchor and alias
518
+ #
519
+ input: |
520
+ - &a1 # comment
521
+ foo
522
+ - *a1 # comment
523
+ #
524
+ expected: |
525
+ ["foo", "foo"]
526
+ ---
527
+ name: flowseq1
528
+ desc: flow style seq
529
+ #
530
+ input: |
531
+ - [ 10, 20 ]
532
+ - [15,25,35]
533
+ #
534
+ expected: |
535
+ [[10, 20], [15, 25, 35]]
536
+ #
537
+ ---
538
+ name: flowseq2
539
+ desc: nested flow style seq
540
+ #
541
+ input: |
542
+ 1: [ A, [B1, B2]]
543
+ 2: [[[X]]]
544
+ 3: [[x1,y1],[x2,"y2"],['x3',y3]]
545
+ #
546
+ expected: |
547
+ {1=>["A", ["B1", "B2"]],
548
+ 2=>[[["X"]]],
549
+ 3=>[["x1", "y1"], ["x2", "y2"], ["x3", "y3"]]}
550
+ #
551
+ ---
552
+ name: flowseq3
553
+ desc: flow style seq with some lines
554
+ #
555
+ input: |
556
+ A: [ [10,20],
557
+ [11,21],
558
+ [12,22]]
559
+ B: [
560
+ [1.1,
561
+ 1.2,
562
+ 1.3
563
+ ]
564
+ ]
565
+ #
566
+ expected: |
567
+ {"A"=>[[10, 20], [11, 21], [12, 22]], "B"=>[[1.1, 1.2, 1.3]]}
568
+ #
569
+ ---
570
+ name: flowseq4
571
+ desc: invalid flow style seq (sequence item required (or last comma is extra).)
572
+ mesg: sequence item required (or last comma is extra).
573
+ error: Kwalify::ParseError
574
+ #
575
+ input: |
576
+ A: [ [10,20], ]
577
+ #
578
+ expected: |
579
+ #
580
+ ---
581
+ name: flowseq5
582
+ desc: invalid flow style seq (flow style sequence requires ']').
583
+ mesg: flow style sequence requires ']'
584
+ error: Kwalify::ParseError
585
+ #
586
+ input: |
587
+ A: [ [10,20]
588
+ B: [ [30, 40]]
589
+ #
590
+ expected: |
591
+ #
592
+ ---
593
+ name: flowseq6
594
+ desc: invalid flow style seq (flow style sequence requires ']').
595
+ mesg: flow style sequence is closed but got ']'.
596
+ error: Kwalify::ParseError
597
+ #
598
+ input: |
599
+ [ 10 ]]
600
+ #
601
+ expected: |
602
+ #
603
+ ---
604
+ name: flowmap1
605
+ desc: flow style map
606
+ #
607
+ input: |
608
+ - { A1: 10, A2: 20 }
609
+ - {B1: 15, 'B2': 25, "B3": 35}
610
+ #
611
+ expected: |
612
+ [{"A1"=>10, "A2"=>20}, {"B1"=>15, "B2"=>25, "B3"=>35}]
613
+ #
614
+ ---
615
+ name: flowmap2
616
+ desc: flow style map nested
617
+ #
618
+ input: |
619
+ A: { x: {y: {z: 10}}}
620
+ B: { a: 1, b:{c: 2, d: 3, e:{f: 4}}, g: 5}
621
+ #
622
+ expected: |
623
+ {"A"=>{"x"=>{"y"=>{"z"=>10}}},
624
+ "B"=>{"a"=>1, "b"=>{"c"=>2, "d"=>3, "e"=>{"f"=>4}}, "g"=>5}}
625
+ #
626
+ ---
627
+ name: flowmap3
628
+ desc: flow style map with some lines
629
+ #
630
+ input: |
631
+ A: { x:
632
+ {y:
633
+ {z: 10}
634
+ }
635
+ }
636
+ B: {
637
+ a: 1,
638
+ b: {
639
+ c: 2,
640
+ d: 3,
641
+ e: {
642
+ f: 4
643
+ }
644
+ },
645
+ g: 5
646
+ }
647
+ #
648
+ expected: |
649
+ {"A"=>{"x"=>{"y"=>{"z"=>10}}},
650
+ "B"=>{"a"=>1, "b"=>{"c"=>2, "d"=>3, "e"=>{"f"=>4}}, "g"=>5}}
651
+ #
652
+ ---
653
+ name: flowmap4
654
+ desc: invalid flow style map (mapping item required (or last comma is extra).)
655
+ mesg: mapping item required (or last comma is extra).
656
+ error: Kwalify::ParseError
657
+ #
658
+ input: |
659
+ - {A: 10, B: 20, }
660
+ #
661
+ expected: |
662
+ #
663
+ ---
664
+ name: flowmap5
665
+ desc: invalid flow style map (flow style mapping requires '}').
666
+ mesg: flow style mapping requires '}'
667
+ error: Kwalify::ParseError
668
+ #
669
+ input: |
670
+ - {A: { x: 10, y: 20 }
671
+ - {A: { x: 11, y: 21 }}
672
+ #
673
+ expected: |
674
+ #
675
+ ---
676
+ name: flowmap6
677
+ desc: invalid flow style map (flow style mapping requires ']').
678
+ mesg: flow style mapping is closed but got '}'.
679
+ error: Kwalify::ParseError
680
+ #
681
+ input: |
682
+ { x: 10 }}
683
+ #
684
+ expected: |
685
+ #
686
+ ---
687
+ name: parse61
688
+ desc: combination of flow style seq and map
689
+ #
690
+ input: |
691
+ [
692
+ {name: ' foo ',
693
+ e-mail: foo@mail.com},
694
+ {name: ba z,
695
+ e-mail: ba__z@mail.com }
696
+ ]
697
+ #
698
+ expected: |
699
+ [{"name"=>" foo ", "e-mail"=>"foo@mail.com"},
700
+ {"name"=>"ba z", "e-mail"=>"ba__z@mail.com"}]
701
+ #
702
+ ---
703
+ name: block_text1
704
+ desc: parse_block_text
705
+ #
706
+ input: |
707
+ - text1: |
708
+ foo
709
+ bar
710
+ baz
711
+ - text2: |
712
+ aaa
713
+ bbb
714
+ ccc
715
+ - |
716
+ foo
717
+ bar
718
+ baz
719
+ - |
720
+ aaa
721
+ bbb
722
+ ccc
723
+ #
724
+ expected: |
725
+ [{"text1"=>"foo\nbar\nbaz\n"},
726
+ {"text2"=>" aaa\nbbb\n ccc\n"},
727
+ "foo\nbar\nbaz\n",
728
+ " aaa\nbbb\n ccc\n"]
729
+ #
730
+ ---
731
+ name: block_text2
732
+ desc: block text with '|+' or '|-'
733
+ #
734
+ input: |
735
+ - text1: |
736
+ A
737
+
738
+ B
739
+ C
740
+
741
+
742
+ - text2: |+
743
+ A
744
+
745
+ B
746
+ C
747
+
748
+
749
+ - text3: |-
750
+ A
751
+
752
+ B
753
+ C
754
+
755
+
756
+ #
757
+ expected: |
758
+ [{"text1"=>"A\n\nB\nC\n"},
759
+ {"text2"=>"A\n\nB\nC\n\n\n"},
760
+ {"text3"=>"A\n\nB\nC"}]
761
+ #
762
+ ---
763
+ name: block_text3
764
+ desc: block text with '| foo'
765
+ #
766
+ input: |
767
+ - text1: | foo
768
+ A
769
+
770
+ B
771
+ C
772
+
773
+ - | foo
774
+ A
775
+ B
776
+ C
777
+ #
778
+ expected: |
779
+ [{"text1"=>"foo A\n\nB\nC\n"}, "fooA\n B\n C\n"]
780
+ #
781
+ ---
782
+ name: block_text4
783
+ desc: block text with '#' (comment)
784
+ #
785
+ input: |
786
+ #
787
+ - text1: |
788
+ A
789
+ #
790
+ B
791
+ #
792
+ text2: |
793
+ #
794
+ #
795
+ #
796
+ - |
797
+ A
798
+ #
799
+ B
800
+ #
801
+ - |
802
+ #
803
+ #
804
+ #
805
+ - x
806
+
807
+ #
808
+ expected: |
809
+ [{"text1"=>"A\n#\nB\n", "text2"=>"#\n#\n"}, "A\n#\nB\n", "#\n#\n", "x"]
810
+ #
811
+ ---
812
+ name: block_text6
813
+ desc: parse_block_text (>)
814
+ #
815
+ input: |
816
+ - text1: >
817
+ foo
818
+ bar
819
+ baz
820
+ - text2: >
821
+ aaa
822
+ bbb
823
+ ccc
824
+ - >
825
+ foo
826
+ bar
827
+ baz
828
+ - >
829
+ aaa
830
+ bbb
831
+ ccc
832
+ #
833
+ expected: |
834
+ [{"text1"=>"foo bar baz\n"},
835
+ {"text2"=>" aaa bbb ccc\n"},
836
+ "foo bar baz\n",
837
+ " aaa bbb ccc\n"]
838
+ #
839
+ ---
840
+ name: block_text7
841
+ desc: block text with '>+' or '>-'
842
+ #
843
+ input: |
844
+ - text1: >
845
+ A
846
+
847
+ B
848
+ C
849
+
850
+
851
+ - text2: >+
852
+ A
853
+
854
+ B
855
+ C
856
+
857
+
858
+ - text3: >-
859
+ A
860
+
861
+ B
862
+ C
863
+
864
+
865
+ #
866
+ expected: |
867
+ [{"text1"=>"A\nB C\n"}, {"text2"=>"A\nB C\n\n"}, {"text3"=>"A\nB C"}]
868
+ #
869
+ ---
870
+ name: block_text8
871
+ desc: block text with '> foo'
872
+ #
873
+ input: |
874
+ - text1: > foo
875
+ A
876
+
877
+ B
878
+ C
879
+
880
+ - > foo
881
+ A
882
+ B
883
+ C
884
+ #
885
+ expected: |
886
+ [{"text1"=>"foo A\nB C\n"}, "fooA B C\n"]
887
+ #
888
+ ---
889
+ name: block_text9
890
+ desc: block text with '#' (comment)
891
+ #
892
+ input: |
893
+ #
894
+ - text1: >
895
+ AA
896
+ ##
897
+ BB
898
+ #
899
+ text2: >
900
+ #
901
+ #
902
+ #
903
+ - >
904
+ AA
905
+ ##
906
+ BB
907
+ #
908
+ - >
909
+ #
910
+ #
911
+ #
912
+ - x
913
+
914
+ #
915
+ expected: |
916
+ [{"text1"=>"AA ## BB\n", "text2"=>"# #\n"}, "AA ## BB\n", "# #\n", "x"]
917
+ #
918
+ ---
919
+ name: anchor1
920
+ desc: parse_anchor, parse_alias
921
+ #
922
+ input: |
923
+ - &a1 foo
924
+ - &a2
925
+ bar
926
+ - *a1
927
+ - *a2
928
+ #
929
+ expected: |
930
+ ["foo", "bar", "foo", "bar"]
931
+ #
932
+ ---
933
+ name: anchor2
934
+ desc: parse_anchor, parse_alias
935
+ #
936
+ input: |
937
+ - A: &a1
938
+ x: 10
939
+ y: 20
940
+ - B: bar
941
+ - C: *a1
942
+ #
943
+ expected: |
944
+ [{"A"=>{"x"=>10, "y"=>20}}, {"B"=>"bar"}, {"C"=>{"x"=>10, "y"=>20}}]
945
+ #
946
+ ---
947
+ name: anchor3
948
+ desc: anchor on child node
949
+ #
950
+ input: |
951
+ - A: &a1
952
+ x: 10
953
+ y: 20
954
+ z: *a1
955
+ #
956
+ expected: |
957
+ [{"A"=>{"x"=>10, "y"=>20, "z"=>{...}}}]
958
+ #
959
+ ---
960
+ name: anchor4
961
+ desc: backward anchor
962
+ #
963
+ input: |
964
+ - *a1
965
+ - *a1
966
+ - foo
967
+ - &a1 bar
968
+ #
969
+ expected: |
970
+ ["bar", "bar", "foo", "bar"]
971
+ #
972
+ ---
973
+ name: anchor5
974
+ desc: anchor not found
975
+ error: Kwalify::ParseError
976
+ mesg: anchor 'a2' not found (Kwalify::ParseError)
977
+ #
978
+ input: |
979
+ - &a1 foo
980
+ - bar
981
+ - *a2
982
+ #
983
+ expected: |
984
+ #
985
+ ---
986
+ name: anchor6
987
+ desc: anchor on child node
988
+ #
989
+ input: |
990
+ type: seq
991
+ sequence:
992
+ - &employee
993
+ type: map
994
+ mapping:
995
+ name:
996
+ type: str
997
+ post:
998
+ type: str
999
+ enum:
1000
+ - exective
1001
+ - manager
1002
+ - clerk
1003
+ supervisor: *employee
1004
+ #
1005
+ expected: |
1006
+ {"sequence"=>
1007
+ [{"type"=>"map",
1008
+ "mapping"=>
1009
+ {"name"=>{"type"=>"str"},
1010
+ "post"=>{"type"=>"str", "enum"=>["exective", "manager", "clerk"]},
1011
+ "supervisor"=>{...}}}],
1012
+ "type"=>"seq"}
1013
+ #
1014
+ ---
1015
+ name: tag1
1016
+ desc: tag
1017
+ #
1018
+ input: |
1019
+ - !str 123
1020
+ - foo: !text 123
1021
+ #
1022
+ expected: |
1023
+ [123, {"foo"=>123}]
1024
+ #
1025
+ ---
1026
+ name: docend1
1027
+ desc: ... (document end)
1028
+ #
1029
+ input: |
1030
+ - aaa
1031
+ - bbb
1032
+ ...
1033
+ - ccc
1034
+ #
1035
+ expected: |
1036
+ ["aaa", "bbb"]
1037
+ #
1038
+ ---
1039
+ name: docend2
1040
+ desc: ... (document end) in block text
1041
+ #
1042
+ input: |
1043
+ - |
1044
+ foo
1045
+ ...
1046
+ bar
1047
+ #
1048
+ expected: |
1049
+ ["foo\n...\nbar\n"]
1050
+ #
1051
+ ---
1052
+ name: docstart1
1053
+ desc: --- (document start)
1054
+ #
1055
+ input: |
1056
+ # comment
1057
+ ---
1058
+ - foo
1059
+ - bar
1060
+ #
1061
+ expected: |
1062
+ ["foo", "bar"]
1063
+ #
1064
+ ---
1065
+ name: docstart2
1066
+ desc: --- (document start) with tag
1067
+ #
1068
+ input: |
1069
+ # comment
1070
+ --- %YAML !seq
1071
+ - foo
1072
+ - bar
1073
+ #
1074
+ expected: |
1075
+ ["foo", "bar"]
1076
+ #
1077
+ ---
1078
+ name: docstart3
1079
+ desc: --- (document start) with tag
1080
+ #
1081
+ input: |
1082
+ - |
1083
+ foo
1084
+ ---
1085
+ bar
1086
+ ---
1087
+ baz
1088
+ #
1089
+ expected: |
1090
+ ["foo\n---\nbar\n---\nbaz\n"]
1091
+ #
1092
+ ---
1093
+ name: default1
1094
+ desc: map default value
1095
+ #
1096
+ input: |
1097
+ A: 10
1098
+ B: 20
1099
+ =: 0
1100
+ #
1101
+ expected: |
1102
+ {"A"=>10, "B"=>20}
1103
+ #
1104
+ ---
1105
+ name: merge1
1106
+ desc: merge key '<<'
1107
+ #
1108
+ input: |
1109
+ - &a1
1110
+ A: 10
1111
+ B: 20
1112
+ - C: 30
1113
+ <<: *a1
1114
+ A: ~
1115
+ #
1116
+ expected: |
1117
+ [{"A"=>10, "B"=>20}, {"A"=>nil, "B"=>20, "C"=>30}]
1118
+ ---
1119
+ name: example1
1120
+ desc: complex combination of seq and map
1121
+ #
1122
+ input: |
1123
+ columns:
1124
+ - name: id
1125
+ type: integer
1126
+ primary-key: yes
1127
+ sequence: yes
1128
+
1129
+ - name: name
1130
+ type: string
1131
+ not-null: yes
1132
+ width: 63
1133
+
1134
+ - name: desc
1135
+ type: string
1136
+
1137
+ - name: email
1138
+ type: string
1139
+ width: 63
1140
+
1141
+ - name: birth
1142
+ type: date
1143
+
1144
+ - name: age
1145
+ type: integer
1146
+
1147
+ - name: last_update
1148
+ type: timestamp
1149
+
1150
+ - name: gender
1151
+ type: string
1152
+ values:
1153
+ - M
1154
+ - F
1155
+
1156
+ tables:
1157
+ - name: groups
1158
+ class: Group
1159
+ desc: Group master table
1160
+ columns:
1161
+ - name: id
1162
+ - name: name
1163
+ - name: desc
1164
+
1165
+ - name: users
1166
+ class: User
1167
+ desc: User master table
1168
+ columns:
1169
+ - name: id
1170
+ - name: name
1171
+ - name: desc
1172
+ - name: email
1173
+ - name: group_id
1174
+ type: ref
1175
+ ref: groups.id
1176
+ - name: account
1177
+ type: string
1178
+ maxlength: 31
1179
+ not-null: yes
1180
+ - name: password
1181
+ not-null: yes
1182
+ #
1183
+ expected: |
1184
+ {"columns"=>
1185
+ [{"name"=>"id", "sequence"=>true, "type"=>"integer", "primary-key"=>true},
1186
+ {"name"=>"name", "not-null"=>true, "type"=>"string", "width"=>63},
1187
+ {"name"=>"desc", "type"=>"string"},
1188
+ {"name"=>"email", "type"=>"string", "width"=>63},
1189
+ {"name"=>"birth", "type"=>"date"},
1190
+ {"name"=>"age", "type"=>"integer"},
1191
+ {"name"=>"last_update", "type"=>"timestamp"},
1192
+ {"name"=>"gender", "type"=>"string", "values"=>["M", "F"]}],
1193
+ "tables"=>
1194
+ [{"columns"=>[{"name"=>"id"}, {"name"=>"name"}, {"name"=>"desc"}],
1195
+ "name"=>"groups",
1196
+ "class"=>"Group",
1197
+ "desc"=>"Group master table"},
1198
+ {"columns"=>
1199
+ [{"name"=>"id"},
1200
+ {"name"=>"name"},
1201
+ {"name"=>"desc"},
1202
+ {"name"=>"email"},
1203
+ {"name"=>"group_id", "type"=>"ref", "ref"=>"groups.id"},
1204
+ {"name"=>"account", "not-null"=>true, "type"=>"string", "maxlength"=>31},
1205
+ {"name"=>"password", "not-null"=>true}],
1206
+ "name"=>"users",
1207
+ "class"=>"User",
1208
+ "desc"=>"User master table"}]}
1209
+ #
1210
+ ---
1211
+ name: example2
1212
+ desc: invoice
1213
+ #
1214
+ input: |
1215
+ invoice: 34843
1216
+ date : 2001-01-23
1217
+ bill-to: &id001
1218
+ given : Chris
1219
+ family : Dumars
1220
+ address:
1221
+ lines: |
1222
+ 458 Walkman Dr.
1223
+ Suite #292
1224
+ city : Royal Oak
1225
+ state : MI
1226
+ postal : 48046
1227
+ ship-to: *id001
1228
+ product:
1229
+ - sku : BL394D
1230
+ quantity : 4
1231
+ description : Basketball
1232
+ price : 450.00
1233
+ - sku : BL4438H
1234
+ quantity : 1
1235
+ description : Super Hoop
1236
+ price : 2392.00
1237
+ tax : 251.42
1238
+ total: 4443.52
1239
+ comments: >
1240
+ Late afternoon is best.
1241
+ Backup contact is Nancy
1242
+ Billsmer @ 338-4338.
1243
+ #
1244
+ expected: |
1245
+ {"tax"=>251.42,
1246
+ "bill-to"=>
1247
+ {"given"=>"Chris",
1248
+ "family"=>"Dumars",
1249
+ "address"=>
1250
+ {"postal"=>48046,
1251
+ "city"=>"Royal Oak",
1252
+ "lines"=>"458 Walkman Dr.\nSuite #292\n",
1253
+ "state"=>"MI"}},
1254
+ "comments"=>
1255
+ "Late afternoon is best. Backup contact is Nancy Billsmer @ 338-4338.\n",
1256
+ "invoice"=>34843,
1257
+ "date"=>#<Date: 4903865/2,0,2299161>,
1258
+ "total"=>4443.52,
1259
+ "product"=>
1260
+ [{"price"=>450.0,
1261
+ "quantity"=>4,
1262
+ "description"=>"Basketball",
1263
+ "sku"=>"BL394D"},
1264
+ {"price"=>2392.0,
1265
+ "quantity"=>1,
1266
+ "description"=>"Super Hoop",
1267
+ "sku"=>"BL4438H"}],
1268
+ "ship-to"=>
1269
+ {"given"=>"Chris",
1270
+ "family"=>"Dumars",
1271
+ "address"=>
1272
+ {"postal"=>48046,
1273
+ "city"=>"Royal Oak",
1274
+ "lines"=>"458 Walkman Dr.\nSuite #292\n",
1275
+ "state"=>"MI"}}}
1276
+ #