cddl 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: bc6439f876088c1d9355f78363bfa34eaa844613
4
+ data.tar.gz: eb88cc041f3a03ef495aeecf4b663af0a2384673
5
+ SHA512:
6
+ metadata.gz: 449e97a60fb3ee5584b582dc8da13d54de607f99ce02020a5565d7495142a8547965429b9d429582a2c898f8c6680a64d089339ff6c8fe4def07887da9ddd782
7
+ data.tar.gz: af6dd64fe9c1267fe4f86fbf4825e7da9faa4be03545991369b647c5766e5735fb1c760341bdf0afb7a4f07f3f7f06279bb1e900c459795eaf150c5c76cbb9a1
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+ require 'cddl'
4
+ require 'cbor-diagnostic'
5
+ require 'json'
6
+
7
+ Encoding.default_external = "UTF-8" # wake up, smell the coffee
8
+
9
+ def usage
10
+ warn "Usage:"
11
+ warn "#$0 spec.cddl generate [n]"
12
+ warn "#$0 spec.cddl json-generate [n]"
13
+ warn "#$0 spec.cddl validate instance.cbor"
14
+ warn "#$0 spec.cddl validate instance.json"
15
+ exit 1
16
+ end
17
+
18
+ case ARGV[1]
19
+ when /\Ag/
20
+ parser = CDDL::Parser.new(File.read(ARGV[0]))
21
+ n = 1
22
+ n = ARGV[2].to_i if ARGV[2]
23
+ n.times do
24
+ g = parser.generate
25
+ puts g.cbor_diagnostic
26
+ end
27
+ when /\Aj/
28
+ parser = CDDL::Parser.new(File.read(ARGV[0]))
29
+ n = 1
30
+ n = ARGV[2].to_i if ARGV[2]
31
+ n.times do
32
+ g = parser.generate
33
+ puts JSON.pretty_generate(g)
34
+ end
35
+ when /\Av/
36
+ parser = CDDL::Parser.new(File.read(ARGV[0]))
37
+ instance = File.read(ARGV[2])
38
+ instance = CBOR.decode(instance) rescue JSON.load(instance)
39
+ p parser.validate(instance)
40
+ else
41
+ usage
42
+ end
@@ -0,0 +1,19 @@
1
+ spec = Gem::Specification.new do |s|
2
+ s.name = 'cddl'
3
+ s.version = '0.1.0'
4
+ s.summary = "CDDL generator and validator."
5
+ s.description = %{A parser, generator, and validator for CDDL}
6
+ s.add_dependency('cbor-diag')
7
+ s.add_dependency('abnc')
8
+ s.add_dependency('json')
9
+ s.files = `git ls-files`.split("\n").grep(/^[a-z]/)
10
+ s.files = Dir['lib/**/*.rb'] + %w(cddl.gemspec) + Dir['data/**/*.abnf'] + Dir['data/**/*.cddl'] + Dir['test-data/**/*.cddl'] + Dir['test/**/*.rb']
11
+ s.require_path = 'lib'
12
+ s.executables = ['cddl']
13
+ s.default_executable = 'cddl'
14
+ s.required_ruby_version = '>= 1.9.2'
15
+ s.author = "Carsten Bormann"
16
+ s.email = "cabo@tzi.org"
17
+ s.homepage = "http://github.com/cabo/cddl"
18
+ s.license = 'MIT'
19
+ end
@@ -0,0 +1,62 @@
1
+ cddl = S 1*rule
2
+ rule = typename S "=" S type S
3
+ / groupname S "=" S group S
4
+
5
+ typename = id
6
+ groupname = id
7
+
8
+ type = type1 S *("/" S type1 S)
9
+
10
+ type1 = value
11
+ / "#" "6" ["." uint] "(" S type S ")" ; note no space!
12
+ / "#" DIGIT ["." uint] ; major/ai
13
+ / "#" ; any
14
+ / "{" S group S "}"
15
+ / "[" S group S "]"
16
+ / "(" type ")"
17
+ / typename
18
+
19
+ group = "(" S *grpent S ")"
20
+ / *grpent
21
+
22
+ grpent = [occur S] [memberkey S] type1 optcom
23
+ / [occur S] groupname optcom ; always preempted by previous...
24
+
25
+ memberkey = membername S ":"
26
+ membername = bareword ; note that this can be a typename
27
+ / type1 ; can be preempted by previous...
28
+
29
+ bareword = id
30
+
31
+ optcom = S ["," S]
32
+
33
+ occur = [uint] "*" [uint]
34
+ / "+"
35
+ / "?"
36
+
37
+ uint = "0"
38
+ / DIGIT1 *DIGIT
39
+
40
+ value = int
41
+ / float
42
+ / string
43
+
44
+ int = ["-"] uint
45
+
46
+ float = int ["." 1*DIGIT] ["e" int ]
47
+
48
+ string = %x22 *SCHAR %x22
49
+ SCHAR = %x20-21 / %x23-7E / SESC
50
+ SESC = "\" %x20-7E
51
+
52
+ id = ALPHA *(ALPHA / DIGIT / "_" / "-")
53
+ ALPHA = %x41-5A / %x61-7A
54
+ DIGIT = %x30-39
55
+ DIGIT1 = %x31-39
56
+ S = *WS
57
+ WS = SP / NL
58
+ SP = %x20
59
+ NL = COMMENT / CRLF
60
+ COMMENT = ";" *(SP / VCHAR) CRLF
61
+ VCHAR = %x21-7E
62
+ CRLF = %x0A / %x0D.0A
@@ -0,0 +1,43 @@
1
+ ; --- prelude ---
2
+
3
+ any = #
4
+
5
+ uint = #0
6
+ nint = #1
7
+ int = uint / nint
8
+
9
+ bstr = #2
10
+ tstr = #3
11
+
12
+ tdate = #6.0(tstr)
13
+ time = #6.1(number)
14
+ number = int / float
15
+ biguint = #6.2(bstr)
16
+ bignint = #6.3(bstr)
17
+ bigint = biguint / bignint
18
+ integer = int / bigint
19
+ decfrac = #6.4([e10: int, m: integer])
20
+ bigfloat = #6.5([e2: int, m: integer])
21
+ eb64url = #6.21(any)
22
+ eb64legacy = #6.21(any)
23
+ eb16 = #6.21(any)
24
+ encoded-cbor = #6.24(bstr)
25
+ uri = #6.32(tstr)
26
+ b64url = #6.33(tstr)
27
+ b64legacy = #6.34(tstr)
28
+ regexp = #6.35(tstr)
29
+ mime-message = #6.36(tstr)
30
+ cbor-any = #6.55799(any)
31
+
32
+ float16 = #7.25
33
+ float32 = #7.26
34
+ float64 = #7.27
35
+ float16-32 = float16 / float32
36
+ float32-64 = float32 / float64
37
+ float = float16-32 / float64
38
+
39
+ false = #7.20
40
+ true = #7.21
41
+ nil = #7.22
42
+ undefined = #7.23
43
+
@@ -0,0 +1,442 @@
1
+ require 'abnc'
2
+ require 'pp'
3
+ require 'pathname'
4
+
5
+ module CDDL
6
+
7
+ DATA_DIR = Pathname.new(__FILE__).split[0] + '../data'
8
+
9
+ PRELUDE = File.read("#{DATA_DIR}/prelude.cddl")
10
+ ABNF_SPEC = File.read("#{DATA_DIR}/cddl.abnf")
11
+
12
+ class Parser
13
+ def initialize(source_text)
14
+ @abnf = Peggy::ABNF.new
15
+ _cresult = @abnf.compile! ABNF_SPEC, ignore: :s
16
+ presult = @abnf.parse? :cddl, (source_text + PRELUDE)
17
+ expected_length = source_text.length + PRELUDE.length
18
+ if expected_length != presult
19
+ upto = @abnf.parse_results.keys.max
20
+ puts "UPTO: #{upto}"
21
+ pp @abnf.parse_results[upto]
22
+ pp @abnf.parse_results[presult]
23
+ p presult
24
+ puts @abnf.ast?
25
+ raise "parse error at #{presult} upto #{upto} of #{expected_length}"
26
+ end
27
+ puts @abnf.ast? if $debug_ast
28
+ @ast = @abnf.ast?
29
+ end
30
+
31
+ def apr # for debugging
32
+ @abnf.parse_results
33
+ end
34
+
35
+ def rules
36
+ @rules = {}
37
+ ast.each :rule do |rule|
38
+ # p rule
39
+ if rulename = rule.groupname
40
+ fail "Duplicate rule #{rulename.to_s}" if @rules[rulename.to_s]
41
+ @rules[rulename.to_s] = [:grpent, *rule.group.children(:grpent)]
42
+ elsif rulename = rule.typename
43
+ fail "Duplicate rule #{rulename.to_s}" if @rules[rulename.to_s]
44
+ @rules[rulename.to_s] = [:type1, *rule.type.children(:type1)]
45
+ else
46
+ fail "Huh?"
47
+ end
48
+ end
49
+ # pp @rules
50
+ @rootrule = @rules.keys.first
51
+ # now process the rules...
52
+ @stage1 = {}
53
+ r_process(@rootrule, @rules[@rootrule])
54
+ # @rules.each do |n, r| # debug only loop
55
+ # r_process(n, r)
56
+ # end
57
+ # @stage1
58
+ end
59
+
60
+ def generate(where=rules, inmap = false)
61
+ case where[0]
62
+ when :type1
63
+ generate(where[rand(where.size-1)+1])
64
+ when :map
65
+ Hash[where[1..-1].flat_map {|m| generate(m, true)}]
66
+ when :array
67
+ where[1..-1].flat_map {|m| generate(m).map{|e| e[1]}}
68
+ when :member
69
+ s = where[1]
70
+ e = where[2]
71
+ e = 4 if e == -1
72
+ s += rand(e + 1 - s) if e != s
73
+ kr = where[3]
74
+ vr = where[4]
75
+ fail "member key not given in map for #{where}" unless kr if inmap
76
+ Array.new(s) { [ (generate(kr) if kr), # XXX: need error in map context
77
+ generate(vr)
78
+ ]}
79
+ when :string, :int, :float
80
+ where[1]
81
+ when :prim
82
+ case where[1]
83
+ when nil
84
+ gen_word
85
+ when 0
86
+ rand(4711)
87
+ when 1
88
+ ~rand(815)
89
+ when 2
90
+ gen_word.force_encoding(Encoding::BINARY)
91
+ when 3
92
+ gen_word
93
+ when 7
94
+ case where[2]
95
+ when nil
96
+ Math::PI
97
+ when 20
98
+ false
99
+ when 21
100
+ true
101
+ when 22
102
+ nil
103
+ when 23
104
+ :undefined
105
+ when 25, 26, 27
106
+ rand()
107
+ end
108
+ else
109
+ fail "Can't generate prim #{where[1]}"
110
+ end
111
+ else
112
+ # fail where
113
+ end
114
+ end
115
+
116
+ VALUE_TYPE = {string: true, int: true, float: true}
117
+ SIMPLE_VALUE = {
118
+ [:prim, 7, 20] => [true, false],
119
+ [:prim, 7, 21] => [true, true],
120
+ [:prim, 7, 22] => [true, nil],
121
+ [:prim, 7, 23] => [true, :undefined],
122
+ }
123
+
124
+ def extract_value(t)
125
+ if VALUE_TYPE[t[0]]
126
+ [true, t[1]]
127
+ elsif v = SIMPLE_VALUE[t]
128
+ v
129
+ else
130
+ [false]
131
+ end
132
+ end
133
+
134
+ def validate_diag
135
+ [@last_data, @last_rule, @last_message]
136
+ end
137
+
138
+ def validate(d, warn=true)
139
+ result = validate1(d)
140
+ unless result
141
+ if warn
142
+ warn "CDDL validation failure:"
143
+ PP::pp(validate_diag, STDERR)
144
+ end
145
+ end
146
+ result
147
+ end
148
+
149
+ def validate_result(check)
150
+ check || (
151
+ @last_message = yield
152
+ false
153
+ )
154
+ end
155
+
156
+ def validate1(d, where=rules)
157
+ # puts "DATA: #{d.inspect}"
158
+ # puts "RULE: #{where.inspect}"
159
+ @last_data = d
160
+ @last_rule = where
161
+ case where[0]
162
+ when :type1
163
+ where[1..-1].any? {|r| validate1(d, r)}
164
+ when :map
165
+ if Hash === d
166
+ d_check = d.dup
167
+ where[1..-1].all? { |r|
168
+ # puts "SUBRULE: #{r.inspect}"
169
+ t, s, _e, k, v = r
170
+ fail unless t == :member
171
+ # this is mostly quadratic; let's do the linear thing if possible
172
+ fail "member name not known for group entry #{r} in map" unless k
173
+ simple, simpleval = extract_value(k)
174
+ if simple
175
+ # puts "SIMPLE: #{d_check.inspect} #{simpleval}"
176
+ # add occurrence check; check that val is present in the first place
177
+ actual = d.fetch(simpleval, :not_found)
178
+ if actual == :not_found
179
+ s == 0 # minimum occurrence must be 0 then
180
+ else
181
+ validate1(actual, v) && d_check.delete(simpleval)
182
+ end
183
+ else
184
+ # puts "COMPLEX: #{k.inspect} #{simple.inspect} #{simpleval.inspect}"
185
+ keys = d_check.keys
186
+ ta, keys = keys.partition{ |key| validate1(key, k)}
187
+ # XXX check ta.size against s/e
188
+ ta.all? { |val|
189
+ validate1(d[val], v) && d_check.delete(val)
190
+ }
191
+ end
192
+ } && d_check == {}
193
+ end
194
+ when :array
195
+ if Array === d
196
+ # validate1 against the record
197
+ i = 0
198
+ where[1..-1].each { |r|
199
+ t, s, e, _k, v = r # XXX
200
+ fail unless t == :member
201
+ occ = 0
202
+ while ((e == -1 || occ < e) && i != d.size && validate1(d[i], v))
203
+ i += 1
204
+ occ += 1
205
+ end
206
+ if occ < s
207
+ @last_message = "occur not reached in array #{d} for #{where}"
208
+ return false
209
+ end
210
+ }
211
+ validate_result(i == d.size) { "cannot complete array #{d} for #{where}" }
212
+ end
213
+ when :string, :int, :float
214
+ _, v = extract_value(where)
215
+ d == v
216
+ when :prim
217
+ case where[1]
218
+ when nil
219
+ true
220
+ when 0
221
+ Integer === d && d >= 0 && d <= 0xffffffffffffffff
222
+ when 1
223
+ Integer === d && d < 0 && d >= -0x10000000000000000
224
+ when 2
225
+ String === d && d.encoding == Encoding::BINARY
226
+ when 3
227
+ String === d && d.encoding != Encoding::BINARY # cheat
228
+ when 7
229
+ t, v = extract_value(where)
230
+ if t
231
+ v == d
232
+ else
233
+ case where[2]
234
+ when nil
235
+ # XXX
236
+ fail
237
+ when 25, 26, 27
238
+ Float === d
239
+ else
240
+ fail
241
+ end
242
+ end
243
+
244
+ else
245
+ fail "Can't generate prim #{where[1]}"
246
+ end
247
+ else
248
+ # fail where
249
+ end
250
+ end
251
+
252
+
253
+ attr_reader :ast
254
+
255
+ private
256
+
257
+ def gen_word
258
+ @words ||= File.read("/usr/share/dict/words").lines.shuffle
259
+ @wordptr ||= 0
260
+ @wordptr = 0 if @wordptr == @words.size
261
+ w = @words[@wordptr].chomp
262
+ @wordptr += 1
263
+ w
264
+ end
265
+
266
+ # XXX needs serious memoizing
267
+
268
+ def r_process(n, r)
269
+ t = r[0]
270
+ # puts "Processing rule #{n} = #{t}"
271
+ @stage1[n] ||= [t, *r[1..-1].map {|e| send(t, e)}]
272
+ end
273
+
274
+ def value(n)
275
+ # cheat:
276
+ val = eval(n.to_s)
277
+ [case val
278
+ when Integer; :int
279
+ when Numeric; :float
280
+ when String; :string
281
+ else fail "huh? value #{val.inspect}"
282
+ end, val]
283
+ end
284
+
285
+ def grpent(n) # returns array of entries
286
+ occ = occur(n.occur)
287
+ if mk = n.memberkey # work around unclear bug in ast generation
288
+ [[:member, *occ, label(mk.membername), type1(n.type1)]]
289
+ else
290
+ # fail n.inspect unless n.type1
291
+ t = if n.membername # work around unclear bug, part 2
292
+ type1(n.membername.type1, true)
293
+ else
294
+ type1(n.type1, true) # type1 can be a group here!
295
+ end
296
+ if t[0] == :grpent
297
+ # XXX go through the members here and multiply the occs
298
+ t1 = t[1..-1].flatten(1)
299
+ t1.flat_map {|t2|
300
+ if t2[0] == :member
301
+ [t2]
302
+ else
303
+ fail unless t2[0] == :grpent
304
+ t2[1..-1]
305
+ end
306
+ }.map {|mem|
307
+ # p mem
308
+ mem[1] *= occ[0]
309
+ mem[2] *= [occ[1], -1].max
310
+ # p mem
311
+ mem
312
+ }
313
+ else
314
+ [[:member, *occ, nil, t]]
315
+ end
316
+ end
317
+ end
318
+
319
+ def label(n)
320
+ # if this is not a rulename, it's a bareword
321
+ name = n.to_s
322
+ if r = @rules[name]
323
+ r_process(name, r)
324
+ else
325
+ [:string, name]
326
+ end
327
+ end
328
+
329
+ def type_recall(name, canbegroup)
330
+ if r = @rules[name]
331
+ t = r_process(name, r)
332
+ unless t[0] == :type1
333
+ fail "#{name} not a type" unless canbegroup && t[0] == :grpent
334
+ end
335
+ t
336
+ else
337
+ fail "Unknown type #{name}"
338
+ end
339
+ end
340
+
341
+ def group_recall(name)
342
+ if r = @rules[name]
343
+ g = r_process(name, r)
344
+ fail "#{name} not a group" unless g[0] == :grpent
345
+ g[1..-1]
346
+ else
347
+ fail "Unknown group #{name}"
348
+ end
349
+ end
350
+
351
+ BRACE = {"{" => :map, "[" => :array}
352
+
353
+ def type1(n, canbegroup = false)
354
+ # puts "NVALUE #{n.value.inspect}"
355
+ if v = n.value
356
+ value(n)
357
+ elsif v = n.typename
358
+ t = type_recall(v.to_s, canbegroup)
359
+ if t[0] == :type1
360
+ if t.size == 2
361
+ t = t[1]
362
+ else
363
+ t = [:type1, *t[1..-1].flat_map {|t1|
364
+ if t1[0] == :type1
365
+ t1[1..-1]
366
+ else
367
+ [t1]
368
+ end
369
+ }]
370
+
371
+ end
372
+ end # XXX should flatten the thing, too
373
+ t
374
+ else
375
+ case str = n.to_s
376
+ when "#"
377
+ [:prim]
378
+ when /\A#(\d+)/
379
+ maj = $1.to_i
380
+ s = [:prim, maj, *n.children(:uint).map(&:to_s).map(&:to_i)]
381
+ if tagged_type = n.type
382
+ s << type(tagged_type)
383
+ end
384
+ s
385
+ when /\A\(/
386
+ type(n.type)
387
+ when /\A[\[{]/
388
+ s = n.children(:group).flat_map {|ch| group(ch)}
389
+ type = BRACE[str[0]]
390
+ if type == :map
391
+ s.each do |member|
392
+ fail unless member[0] == :member
393
+ fail "map entry without member key given: #{member}" unless member[3]
394
+ end
395
+ end
396
+ [type, *s]
397
+ else
398
+ "unimplemented #{n}"
399
+ end
400
+ end
401
+ end
402
+
403
+ def type(n)
404
+ s = n.children(:type1).map {|ch| type1(ch)}
405
+ if s.size == 1
406
+ s.first
407
+ else
408
+ [:type1, *s]
409
+ end
410
+ end
411
+
412
+ def group(n) # returns array
413
+ n.children(:grpent).flat_map {|ch| grpent(ch)}
414
+ end
415
+
416
+ def occur(n)
417
+ case n.to_s
418
+ when ""
419
+ [1, 1]
420
+ when "+"
421
+ [1, -1]
422
+ when "?"
423
+ [0, 1]
424
+ when /\A(\d*)\*(\d*)\z/
425
+ if (s = $1) == ""
426
+ s = 0
427
+ else
428
+ s = s.to_i
429
+ end
430
+ if (e = $2) == ""
431
+ e = -1
432
+ else
433
+ e = e.to_i
434
+ end
435
+ [s, e]
436
+ else
437
+ fail "huh #{n.to_s}"
438
+ end
439
+ end
440
+
441
+ end
442
+ end
@@ -0,0 +1,17 @@
1
+ reputation-object = {
2
+ application: tstr
3
+ reputons: [* reputon]
4
+ }
5
+
6
+ reputon = {
7
+ rater: tstr
8
+ assertion: tstr
9
+ rated: tstr
10
+ rating: float16
11
+ ? confidence: float16
12
+ ? normal-rating: float16
13
+ ? sample-size: uint
14
+ ? generated: uint
15
+ ? expires: uint
16
+ * any: any
17
+ }
@@ -0,0 +1,42 @@
1
+
2
+
3
+ reputation-object = {
4
+ reputation-context,
5
+ reputon-list
6
+ }
7
+
8
+ reputation-context = (
9
+ application: tstr
10
+ )
11
+
12
+ reputon-list = (
13
+ reputons: reputon-array
14
+ )
15
+
16
+ reputon-array = [* reputon]
17
+
18
+ reputon = {
19
+ rater-value,
20
+ assertion-value,
21
+ rated-value,
22
+ rating-value,
23
+ ? conf-value,
24
+ ? normal-value,
25
+ ? sample-value,
26
+ ? gen-value,
27
+ ? expire-value,
28
+ * ext-value,
29
+ }
30
+
31
+ rater-value = ( rater: tstr )
32
+ assertion-value = ( assertion: tstr )
33
+ rated-value = ( rated: tstr )
34
+ rating-value = ( rating: float16 )
35
+ conf-value = ( confidence: float16 )
36
+ normal-value = ( normal-rating: float16 )
37
+ sample-value = ( sample-size: uint )
38
+ gen-value = ( generated: uint )
39
+ expire-value = ( expires: uint )
40
+ ext-value = ( any: any )
41
+
42
+
@@ -0,0 +1,292 @@
1
+ require 'test/unit'
2
+ require 'pathname'
3
+
4
+ require 'cbor-pretty.rb'
5
+ require 'cbor-diagnostic.rb'
6
+
7
+ require_relative '../lib/cddl'
8
+
9
+
10
+ class TestABNF < Test::Unit::TestCase
11
+
12
+ TEST_DATA_DIR = Pathname.new(__FILE__).split[0] + '../test-data'
13
+
14
+ EXPECTED_RULES = [:type1,
15
+ [:map,
16
+ [:member, 1, 1, [:string, "application"], [:prim, 3]],
17
+ [:member,
18
+ 1,
19
+ 1,
20
+ [:string, "reputons"],
21
+ [:array,
22
+ [:member,
23
+ 0,
24
+ -1,
25
+ nil,
26
+ [:map,
27
+ [:member, 1, 1, [:string, "rater"], [:prim, 3]],
28
+ [:member, 1, 1, [:string, "assertion"], [:prim, 3]],
29
+ [:member, 1, 1, [:string, "rated"], [:prim, 3]],
30
+ [:member, 1, 1, [:string, "rating"], [:prim, 7, 25]],
31
+ [:member, 0, 1, [:string, "confidence"], [:prim, 7, 25]],
32
+ [:member, 0, 1, [:string, "normal-rating"], [:prim, 7, 25]],
33
+ [:member, 0, 1, [:string, "sample-size"], [:prim, 0]],
34
+ [:member, 0, 1, [:string, "generated"], [:prim, 0]],
35
+ [:member, 0, 1, [:string, "expires"], [:prim, 0]],
36
+ [:member, 0, -1, [:type1, [:prim]], [:prim]]]]]]]]
37
+
38
+ def test_aa_rfc7071_concise
39
+ parser1 = CDDL::Parser.new(File.read("#{TEST_DATA_DIR}/7071-concise.cddl"))
40
+ assert_equal EXPECTED_RULES, parser1.rules
41
+ end
42
+
43
+ def test_aa_rfc7071_verbose
44
+ parser2 = CDDL::Parser.new(File.read("#{TEST_DATA_DIR}/7071-verbose.cddl"))
45
+ assert_equal EXPECTED_RULES, parser2.rules
46
+ 3.times do
47
+ # puts CBOR::pretty(CBOR::encode(parser2.generate(EXPECTED_RULES)))
48
+ puts parser2.generate.cbor_diagnostic
49
+ end
50
+ end
51
+
52
+ def test_validate
53
+ parser1 = CDDL::Parser.new(File.read("test-data/7071-concise.cddl"))
54
+ g = parser1.generate
55
+ pp g
56
+ assert parser1.validate(g)
57
+ old = g["application"]
58
+ g["application"] = 4711
59
+ refute parser1.validate(g, false)
60
+ g["application"] = old
61
+ g["reputons"] << 5712
62
+ refute parser1.validate(g, false)
63
+ end
64
+
65
+ def test_validate_1
66
+ parser = CDDL::Parser.new <<HERE
67
+ test = 1
68
+ HERE
69
+ assert parser.validate(1)
70
+ end
71
+
72
+ def test_validate_a
73
+ parser = CDDL::Parser.new <<HERE
74
+ test = [* one: 1]
75
+ HERE
76
+ assert parser.validate([])
77
+ assert parser.validate([1])
78
+ assert parser.validate([1, 1])
79
+ refute parser.validate([1, 2], false)
80
+ refute parser.validate([2, 1], false)
81
+ end
82
+
83
+ def test_validate_a_string
84
+ parser = CDDL::Parser.new <<HERE
85
+ test = [* one: "one"]
86
+ HERE
87
+ assert parser.validate([])
88
+ assert parser.validate(["one"])
89
+ assert parser.validate(["one", "one"])
90
+ refute parser.validate([1], false)
91
+ refute parser.validate(['two'], false)
92
+ refute parser.validate(["one", "two"], false)
93
+ end
94
+
95
+
96
+ def test_validate_a_string_string
97
+ parser = CDDL::Parser.new <<HERE
98
+ test = [* "two": "one"]
99
+ HERE
100
+ assert parser.validate([])
101
+ assert parser.validate(["one"])
102
+ assert parser.validate(["one", "one"])
103
+ refute parser.validate([1], false)
104
+ refute parser.validate(['two'], false)
105
+ refute parser.validate(["one", "two"], false)
106
+ end
107
+
108
+ def test_validate_a_once
109
+ # $debug_ast = true
110
+ parser = CDDL::Parser.new <<HERE
111
+ test = [1]
112
+ HERE
113
+ # puts "RULES:"
114
+ # pp parser.rules
115
+ # puts "APR:"
116
+ # pp parser.apr
117
+ refute parser.validate([], false)
118
+ assert parser.validate([1])
119
+ refute parser.validate([1, 1], false)
120
+ refute parser.validate([1, 2], false)
121
+ refute parser.validate([2, 1], false)
122
+ end
123
+
124
+ def test_validate_unknown_key
125
+ # $debug_ast = true
126
+ parser = CDDL::Parser.new <<HERE
127
+ test = { 1, 2 }
128
+ HERE
129
+ # puts "RULES:"
130
+ assert_raise { # TODO: This really should be checked at parse time
131
+ pp parser.rules
132
+ }
133
+ # puts "APR:"
134
+ # pp parser.apr
135
+ assert_raise { puts parser.generate() }
136
+ assert_raise { parser.validate({}) }
137
+ end
138
+
139
+ def test_validate_not_unknown_key
140
+ # $debug_ast = true
141
+ parser = CDDL::Parser.new <<HERE
142
+ test = [ 1, 2 ]
143
+ HERE
144
+ # puts "RULES:"
145
+ # pp parser.rules
146
+ # puts "APR:"
147
+ # pp parser.apr
148
+ assert_equal [1, 2], parser.generate()
149
+ refute parser.validate({}, false)
150
+ refute parser.validate([], false)
151
+ refute parser.validate([1], false)
152
+ assert parser.validate([1, 2])
153
+ end
154
+
155
+
156
+ def test_validate_not_unknown_key_paren
157
+ # $debug_ast = true
158
+ parser = CDDL::Parser.new <<HERE
159
+ test = [ (1, 2) ]
160
+ HERE
161
+ # puts "RULES:"
162
+ # pp parser.rules
163
+ # puts "APR:"
164
+ # pp parser.apr
165
+ assert_equal [1, 2], parser.generate()
166
+ refute parser.validate({}, false)
167
+ refute parser.validate([], false)
168
+ refute parser.validate([1], false)
169
+ assert parser.validate([1, 2])
170
+ end
171
+
172
+
173
+ def test_validate_alternate3 # XXX need indirection for now
174
+ # $debug_ast = true
175
+ parser = CDDL::Parser.new <<HERE
176
+ test = [* test1]
177
+ test1 = (one: 1, two: 2)
178
+ HERE
179
+ # puts "RULES:"
180
+ # pp parser.rules
181
+ # puts "APR:"
182
+ # pp parser.apr
183
+ assert parser.validate([])
184
+ assert parser.validate([1, 2])
185
+ assert parser.validate([1, 1, 2, 2]) # XXX: This is probably a BUG
186
+ refute parser.validate([1, 2, 1, 2], false) # XXX->assert: major surgery required
187
+ assert parser.validate([1]) # XXX -> refute (rules left)
188
+ refute parser.validate([1, 2, 1], false)
189
+ end
190
+
191
+ def test_validate_occur1 # XXX need indirection for now
192
+ # $debug_ast = true
193
+ parser = CDDL::Parser.new <<HERE
194
+ test = [test1]
195
+ test1 = (one: 1, two: 2)
196
+ HERE
197
+ # puts "RULES:"
198
+ # pp parser.rules
199
+ # puts "APR:"
200
+ # pp parser.apr
201
+ refute parser.validate([], false)
202
+ refute parser.validate([1], false)
203
+ assert parser.validate([1, 2])
204
+ refute parser.validate([2, 1], false)
205
+ refute parser.validate([1, 1, 2, 2], false)
206
+ refute parser.validate([1, 2, 1, 2], false)
207
+ refute parser.validate([1, 2, 1], false)
208
+ end
209
+
210
+ def test_validate_occur01 # XXX need indirection for now
211
+ # $debug_ast = true
212
+ parser = CDDL::Parser.new <<HERE
213
+ test = [? test1]
214
+ test1 = (one: 1, two: 2)
215
+ HERE
216
+ # puts "RULES:"
217
+ # pp parser.rules
218
+ # puts "APR:"
219
+ # pp parser.apr
220
+ assert parser.validate([])
221
+ assert parser.validate([1])
222
+ assert parser.validate([1, 2])
223
+ refute parser.validate([2, 1], false)
224
+ refute parser.validate([1, 1, 2, 2], false)
225
+ refute parser.validate([1, 2, 1, 2], false)
226
+ refute parser.validate([1, 2, 1], false)
227
+ end
228
+
229
+ def test_validate_occur1n # XXX need indirection for now
230
+ # $debug_ast = true
231
+ parser = CDDL::Parser.new <<HERE
232
+ test = [+ test1]
233
+ test1 = (one: 1, two: 2)
234
+ HERE
235
+ # puts "RULES:"
236
+ # pp parser.rules
237
+ # puts "APR:"
238
+ # pp parser.apr
239
+ refute parser.validate([], false)
240
+ refute parser.validate([1], false)
241
+ assert parser.validate([1, 2])
242
+ refute parser.validate([2, 1], false)
243
+ assert parser.validate([1, 1, 2, 2]) # XXX not sequence preserving
244
+ refute parser.validate([1, 2, 1, 2], false)
245
+ refute parser.validate([1, 2, 1], false)
246
+ end
247
+
248
+ def test_validate_occur0n # XXX need indirection for now
249
+ # $debug_ast = true
250
+ parser = CDDL::Parser.new <<HERE
251
+ test = [* test1]
252
+ test1 = (one: 1, two: 2)
253
+ HERE
254
+ # puts "RULES:"
255
+ # pp parser.rules
256
+ # puts "APR:"
257
+ # pp parser.apr
258
+ assert parser.validate([])
259
+ assert parser.validate([1])
260
+ assert parser.validate([1, 2])
261
+ refute parser.validate([2, 1], false)
262
+ assert parser.validate([1, 1, 2, 2]) # XXX not sequence preserving
263
+ refute parser.validate([1, 2, 1, 2], false)
264
+ refute parser.validate([1, 2, 1], false)
265
+ end
266
+
267
+
268
+ def test_validate_occur23 # XXX need indirection for now
269
+ # $debug_ast = true
270
+ parser = CDDL::Parser.new <<HERE
271
+ test = [2*3 test1]
272
+ test1 = (one: 1, two: 2)
273
+ HERE
274
+ # puts "RULES:"
275
+ # pp parser.rules
276
+ # puts "APR:"
277
+ # pp parser.apr
278
+ pp parser.generate
279
+ refute parser.validate([], false)
280
+ refute parser.validate([1], false)
281
+ refute parser.validate([1, 2], false)
282
+ refute parser.validate([2, 1], false)
283
+ assert parser.validate([1, 1, 2, 2]) # XXX not sequence preserving
284
+ assert parser.validate([1, 1, 1, 2, 2]) # XXX not sequence preserving
285
+ assert parser.validate([1, 1, 2, 2, 2]) # XXX not sequence preserving
286
+ assert parser.validate([1, 1, 1, 2, 2, 2]) # XXX not sequence preserving
287
+ refute parser.validate([1, 2, 1, 2], false)
288
+ refute parser.validate([1, 2, 1], false)
289
+ end
290
+
291
+
292
+ end
metadata ADDED
@@ -0,0 +1,95 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cddl
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Carsten Bormann
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-02-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: cbor-diag
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: abnc
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: json
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: A parser, generator, and validator for CDDL
56
+ email: cabo@tzi.org
57
+ executables:
58
+ - cddl
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - bin/cddl
63
+ - cddl.gemspec
64
+ - data/cddl.abnf
65
+ - data/prelude.cddl
66
+ - lib/cddl.rb
67
+ - test-data/7071-concise.cddl
68
+ - test-data/7071-verbose.cddl
69
+ - test/test-cddl.rb
70
+ homepage: http://github.com/cabo/cddl
71
+ licenses:
72
+ - MIT
73
+ metadata: {}
74
+ post_install_message:
75
+ rdoc_options: []
76
+ require_paths:
77
+ - lib
78
+ required_ruby_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: 1.9.2
83
+ required_rubygems_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ requirements: []
89
+ rubyforge_project:
90
+ rubygems_version: 2.4.5
91
+ signing_key:
92
+ specification_version: 4
93
+ summary: CDDL generator and validator.
94
+ test_files: []
95
+ has_rdoc: