cddl 0.4.2 → 0.5.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0f6311c506c4a4e5cbf7e7ae7311301a9d4b6c8d
4
- data.tar.gz: e6fdfe83c6aec225ce434ae492a709fd06d0c890
3
+ metadata.gz: 4b41bbfc4b845713489d878733a2c1e51277ce80
4
+ data.tar.gz: 00096ccc572f588b44cd35007ef8795453f57430
5
5
  SHA512:
6
- metadata.gz: c2926569f00e5e7e509b3e6d05271da2c0d79a79eb46e38e97701218fe339113d08a8057369ff3c4b5f02bdd3f5fbb80ebc34875c6767b619ea327f722bf7ce3
7
- data.tar.gz: 3df458899c4ed7890ef68a40b3c64484599b2805084eb9c8eee15789c94c269452c6352ce34d77dd078e612957c29ded13b650520c179dc6fe886f853e2a60e6
6
+ metadata.gz: 5481738cee35fb77e07500fe839b0f9a7c6473309938e098893f6af32cf3a00d5f720061e733211ac1df4f3dcd945cc0dbe3d855920a288e44cd432de01b723e
7
+ data.tar.gz: c3d84ab6506b6620996963e76040af1b097c4886b678317f70598a989fdd5d2a9e82d52119fb49e1e987e0abf9af7a2095addbafcf5592f9db287cd6f7dca3eb
@@ -1,6 +1,6 @@
1
1
  spec = Gem::Specification.new do |s|
2
2
  s.name = 'cddl'
3
- s.version = '0.4.2'
3
+ s.version = '0.5.0'
4
4
  s.summary = "CDDL generator and validator."
5
5
  s.description = %{A parser, generator, and validator for CDDL}
6
6
  s.add_dependency('cbor-diag')
@@ -1,6 +1,6 @@
1
1
  cddl = S 1*rule
2
2
  rule = typename [genericparm] S "=" S type S
3
- / groupname [genericparm] S "=" S group S
3
+ / groupname [genericparm] S "=" S grpent S
4
4
 
5
5
  typename = id
6
6
  groupname = id
@@ -27,11 +27,13 @@ rangeop = "..." / ".."
27
27
 
28
28
  annotator = "." id
29
29
 
30
- group = "(" S *grpent S ")"
31
- / *grpent
30
+ group = grpchoice S *("//" S grpchoice S)
31
+
32
+ grpchoice = *grpent
32
33
 
33
34
  grpent = [occur S] [memberkey S] type optcom
34
35
  / [occur S] groupname [genericarg] optcom ; always preempted by previous...
36
+ / [occur S] "(" S group S ")" optcom
35
37
 
36
38
  memberkey = type1 S "=>"
37
39
  / bareword S ":"
@@ -57,6 +57,10 @@ module CDDL
57
57
  @abnf.parse_results
58
58
  end
59
59
 
60
+ def ast_debug
61
+ ast.to_s[/.*comment/m] # stop at first comment -- prelude
62
+ end
63
+
60
64
  def strip_nodes(n)
61
65
  [n[0], *n[1..-1].map {|e|
62
66
  e._strip
@@ -70,7 +74,7 @@ module CDDL
70
74
  ast.each :rule do |rule|
71
75
  rule_ast =
72
76
  if rulename = rule.groupname
73
- [:grpent, *rule.group.children(:grpent)]
77
+ [:grpent, rule.grpent]
74
78
  elsif rulename = rule.typename
75
79
  [:type1, *rule.type.children(:type1)]
76
80
  else
@@ -117,10 +121,9 @@ module CDDL
117
121
 
118
122
  def lookup_recurse_grpent(name)
119
123
  rule = @stage1[name]
120
- [rule[0], *rule[1..-1].map {|x|
121
- fail rule.inspect if x.size != 1
122
- x[0]
123
- }]
124
+ # pp rule
125
+ fail unless rule.size == 2
126
+ [rule[0], *rule[1]]
124
127
  end
125
128
 
126
129
  # Memoize a bit here
@@ -138,10 +141,17 @@ module CDDL
138
141
  case where[0]
139
142
  when :type1
140
143
  generate1(where[rand(where.size-1)+1])
144
+ when :grpchoice
145
+ chosen = where[rand(where.size-1)+1]
146
+ # pp [:chosen, chosen]
147
+ r = chosen.flat_map {|m| generate1(m, inmap)}
148
+ # pp r
149
+ r
141
150
  when :map
142
151
  Hash[where[1..-1].flat_map {|m| generate1(m, true)}]
143
152
  when :recurse_grpent
144
- rule = lookup_recurse_grpent(where[1])
153
+ name = where[1]
154
+ rule = lookup_recurse_grpent(name)
145
155
  if @recursion < MAX_RECURSE
146
156
  @recursion += 1
147
157
  #p ["recurse_grpent", *rule]
@@ -315,6 +325,11 @@ module CDDL
315
325
  n = validate_linear(d, start+i, rule)
316
326
  return false unless n
317
327
  i += n
328
+ elsif t == :grpchoice
329
+ return false unless r[1..-1].any? {|cand|
330
+ if n = validate_forward(d, start+i, [:foo, *cand])
331
+ i += n
332
+ end}
318
333
  else
319
334
  fail r.inspect unless t == :member
320
335
  occ = 0
@@ -343,6 +358,49 @@ module CDDL
343
358
  end
344
359
  end
345
360
 
361
+ def map_check(d, d_check, members)
362
+ members.all? { |r|
363
+ # puts "SUBRULE: #{r.inspect}"
364
+ t, s, _e, k, v = r
365
+ case t
366
+ when :recurse_grpent
367
+ rule = lookup_recurse_grpent(s)
368
+ map_check(d, d_check, rule[1..-1])
369
+ when :grpchoice
370
+ r[1..-1].any? {|cand|
371
+ cand_d_check = d_check.dup
372
+ if map_check(d, cand_d_check, cand)
373
+ d_check.replace(cand_d_check)
374
+ end
375
+ }
376
+ when :member
377
+ # this is mostly quadratic; let's do the linear thing if possible
378
+ fail "member name not known for group entry #{r} in map" unless k
379
+ simple, simpleval = extract_value(k)
380
+ if simple
381
+ # puts "SIMPLE: #{d_check.inspect} #{simpleval}"
382
+ # add occurrence check; check that val is present in the first place
383
+ actual = d.fetch(simpleval, :not_found)
384
+ if actual == :not_found
385
+ s == 0 # minimum occurrence must be 0 then
386
+ else
387
+ validate1(actual, v) && d_check.delete(simpleval)
388
+ end
389
+ else
390
+ # puts "COMPLEX: #{k.inspect} #{simple.inspect} #{simpleval.inspect}"
391
+ keys = d_check.keys
392
+ ta, keys = keys.partition{ |key| validate1(key, k)}
393
+ # XXX check ta.size against s/e
394
+ ta.all? { |val|
395
+ validate1(d[val], v) && d_check.delete(val)
396
+ }
397
+ end
398
+ else
399
+ fail "Cannot validate #{t} in maps yet #{r}" # MMM
400
+ end
401
+ }
402
+ end
403
+
346
404
  def validate1(d, where=rules)
347
405
  # puts "DATA: #{d.inspect}"
348
406
  # puts "RULE: #{where.inspect}"
@@ -354,32 +412,7 @@ module CDDL
354
412
  when :map
355
413
  if Hash === d
356
414
  d_check = d.dup
357
- where[1..-1].all? { |r|
358
- # puts "SUBRULE: #{r.inspect}"
359
- t, s, _e, k, v = r
360
- fail unless t == :member
361
- # this is mostly quadratic; let's do the linear thing if possible
362
- fail "member name not known for group entry #{r} in map" unless k
363
- simple, simpleval = extract_value(k)
364
- if simple
365
- # puts "SIMPLE: #{d_check.inspect} #{simpleval}"
366
- # add occurrence check; check that val is present in the first place
367
- actual = d.fetch(simpleval, :not_found)
368
- if actual == :not_found
369
- s == 0 # minimum occurrence must be 0 then
370
- else
371
- validate1(actual, v) && d_check.delete(simpleval)
372
- end
373
- else
374
- # puts "COMPLEX: #{k.inspect} #{simple.inspect} #{simpleval.inspect}"
375
- keys = d_check.keys
376
- ta, keys = keys.partition{ |key| validate1(key, k)}
377
- # XXX check ta.size against s/e
378
- ta.all? { |val|
379
- validate1(d[val], v) && d_check.delete(val)
380
- }
381
- end
382
- } && d_check == {}
415
+ map_check(d, d_check, where[1..-1]) && d_check == {}
383
416
  end
384
417
  when :array
385
418
  if Array === d
@@ -511,7 +544,7 @@ module CDDL
511
544
  end
512
545
  end
513
546
 
514
- RECURSE_TYPE = {grpent: :recurse_grpent, type1: :recurse}
547
+ RECURSE_TYPE = {grpent: :recurse_grpent, type1: :recurse} # MMM
515
548
  RECURSE_TYPE.default_proc = proc do |a|
516
549
  fail a.inspect
517
550
  end
@@ -549,15 +582,33 @@ module CDDL
549
582
  end, val]
550
583
  end
551
584
 
585
+ def workaround1(n)
586
+ n.children.each do |ch|
587
+ if ch.to_s == ")"
588
+ # warn "W1 #{ch.inspect} -> #{ch.group.inspect}"
589
+ return ch.group
590
+ end
591
+ end
592
+ nil
593
+ end
594
+
552
595
  def grpent(n) # returns array of entries
553
- nt = n.type || n.bareword.s.type # check for grpchoice later
596
+ occ = occur(n.occur)
597
+ if g = n.group || workaround1(n)
598
+ gr = group(g)
599
+ if occ != [1, 1]
600
+ gr = [[:member, *occ, nil, [:grpent, *gr]]]
601
+ end
602
+ return gr
603
+ end
604
+ nt = n.type || (n.s && n.s.type) || (n.bareword && n.bareword.s.type) # workarounds
554
605
  unless nt
606
+ warn "NO NT"
555
607
  warn @abnf.ast?
556
608
  fail ["ntype", n, n.children].inspect
557
609
  end
558
- occ = occur(n.occur)
559
610
  if mk = n.memberkey # work around unclear bug in ast generation below
560
- if (t1 = mk.type1 || t1 = mk.value ||
611
+ if (t1 = mk.type1 || t1 = mk.value ||
561
612
  ((t1 = mk.s) && (t1 = t1.type) && (t1 = t1.type1))) # workaround
562
613
  [[:member, *occ, type1(t1), type(nt)]]
563
614
  else
@@ -582,6 +633,9 @@ module CDDL
582
633
  t1 = t[1..-1].flatten(1)
583
634
  if t1[0] == :recurse_grpent
584
635
  [t1]
636
+ elsif Array === t1[0] && t1[0][0] == :grpchoice
637
+ fail t1.inspect unless t1.size == 1
638
+ t1
585
639
  else
586
640
  t1.flat_map {|t2|
587
641
  if t2[0] == :member
@@ -667,6 +721,22 @@ module CDDL
667
721
  end
668
722
  end
669
723
 
724
+ def memberkey_check(s)
725
+ s.each do |member|
726
+ case member[0]
727
+ when :grpchoice
728
+ member[1..-1].each do |m|
729
+ memberkey_check(m)
730
+ end
731
+ when :recurse_grpent # XXX we don't have the entry yet
732
+ when :member
733
+ fail "map entry without member key given: #{member}" unless member[3]
734
+ else
735
+ fail ["type1 member", member].inspect unless member[0] == :member
736
+ end
737
+ end
738
+ end
739
+
670
740
  BRACE = {"{" => :map, "[" => :array}
671
741
  RANGE_EXCLUDE_END = {".." => false, "..." => true}
672
742
  SUPPORTED_ANNOTATIONS = [:bits, :size, :regexp]
@@ -711,10 +781,7 @@ module CDDL
711
781
  s = n.children(:group).flat_map {|ch| group(ch)}
712
782
  @insides.pop
713
783
  if type == :map
714
- s.each do |member|
715
- fail unless member[0] == :member
716
- fail "map entry without member key given: #{member}" unless member[3]
717
- end
784
+ memberkey_check(s)
718
785
  # XXX could do the occurrence multiplier here
719
786
  end
720
787
  # warn s.inspect
@@ -729,7 +796,7 @@ module CDDL
729
796
  end
730
797
  [:type1, *s.map {|mem|
731
798
  t, _s, _e, _k, v = mem
732
- fail unless t == :member
799
+ fail "enum #{t.inspect}" unless t == :member
733
800
  v
734
801
  }
735
802
  ]
@@ -750,7 +817,20 @@ module CDDL
750
817
  end
751
818
 
752
819
  def group(n) # returns array
753
- n.children(:grpent).flat_map {|ch| grpent(ch)}
820
+ choices = n.children(:grpchoice)
821
+ if choices == [] # "cannot happen", workaround
822
+ choices = n.s.children(:grpchoice)
823
+ # warn "W2: #{choices.inspect}"
824
+ end
825
+ choices = choices.map {|choice|
826
+ choice.children(:grpent).flat_map {|ch| grpent(ch)}
827
+ }
828
+ case choices.size
829
+ when 1
830
+ choices.first
831
+ else
832
+ [[:grpchoice, *choices]]
833
+ end
754
834
  end
755
835
 
756
836
  def occur(n)
@@ -0,0 +1,9 @@
1
+ col = {color}
2
+ color =
3
+ ( black: 0,
4
+ red: 1,
5
+ green: 2,)
6
+ //
7
+ ( foo: 4,
8
+ bar: 5,
9
+ baz: 6,)
@@ -0,0 +1,3 @@
1
+ x = (a, b)
2
+ a = ()
3
+ b = //
@@ -0,0 +1,392 @@
1
+ messages = request / response
2
+
3
+ request = new-session-request / end-session / renew-session / publish-request / search-request / subscribe-request / poll-request
4
+ / purge-publisher-request
5
+
6
+ ; response = subscribe-received / publish-received / purge-publisher-received / results
7
+
8
+ ;results = error-result / poll-result / search-result / new-session-result / end-session-result
9
+
10
+ message<namespace,name,attributes,content> = [
11
+ namespace: namespace,
12
+ name: name,
13
+ attributes: attributes,
14
+ content: content
15
+ ]
16
+
17
+ error-code = "AccessDenied" / "Failure" / "InvalidIdentifier" / "InvalidIdentifierType" /
18
+ "IdentifierTooLong" / "InvalidMetadata" / "InvalidSchemaVersion" / "InvalidSessionID" /
19
+ "MetadataTooLong" / "SearchResultsTooBig" / "PollResultsTooBig" / "SystemError"
20
+
21
+ error-result =
22
+ message<"ifmap", "error-result",
23
+ [ ],
24
+ [ ? "name", ? tstr,
25
+ "error-code", error-code,
26
+ "error-string", tstr
27
+ ]>
28
+
29
+ poll-result = ["", "poll-result", [], [ *(search-result / error-result)]]
30
+
31
+ response-choice = error-result / poll-result / search-result / subscribe-received /
32
+ publish-received / purge-publisher-received / new-session-result /
33
+ renew-session-result / end-session-result
34
+
35
+ response =
36
+ message<"ifmap", "response",
37
+ [ ? validation-attributes ],
38
+ [ response-choice ]>
39
+
40
+ purge-publisher-received =
41
+ ["", "purge-publisher-received", [], []]
42
+
43
+ purge-publisher-request =
44
+ message<"ifmap", "purge-publisher",
45
+ [ "ifmap-publisher-id", tstr,
46
+ session-attributes
47
+ ],
48
+ []>
49
+
50
+ ; needs to be constructed according to IF-MAP Filter syntax
51
+ filter-type = tstr
52
+
53
+ poll-request =
54
+ message<"ifmap", "poll",
55
+ [ session-attributes,
56
+ validation-attributes
57
+ ],
58
+ []>
59
+
60
+ subscribe-received =
61
+ ["", "subscribe-received", [], []]
62
+
63
+ subscribe-request =
64
+ message<"ifmap", "subscribe",
65
+ [ session-attributes,
66
+ validation-attributes
67
+ ],
68
+ [ 1*(subscribe-update / subscribe-delete)
69
+ ]>
70
+
71
+ subscribe-delete =
72
+ message<"", "delete",
73
+ [ "name", tstr,
74
+ ],
75
+ []>
76
+
77
+ subscribe-update =
78
+ message<"", "update",
79
+ [ "match-links", filter-type,
80
+ "max-depth", uint,
81
+ "terminal-identifier-type", tstr,
82
+ "max-size", uint,
83
+ "result-filter", filter-type,
84
+ "name", tstr,
85
+ ],
86
+ [ access-request / identity / ip-address / mac-address / device
87
+ ]>
88
+ search-request =
89
+ message<"ifmap", "search",
90
+ [ session-attributes,
91
+ validation-attributes,
92
+ "match-links", filter-type,
93
+ "max-depth", uint,
94
+ "terminal-identifier-type", tstr,
95
+ "max-size", uint,
96
+ "result-filter", filter-type
97
+ ],
98
+ [ access-request / identity / ip-address / mac-address / device
99
+ ]>
100
+
101
+ search-result =
102
+ ["", "search-result",
103
+ ["name", tstr],
104
+ [ *result-item]]
105
+
106
+ result-item =
107
+ message<"", "result-item",
108
+ [],
109
+ [ 1*2(access-request / identity / ip-address / mac-address / device),
110
+ "metadata", metadata-list-type
111
+ ]>
112
+
113
+ publish-request =
114
+ message<"ifmap", "publish",
115
+ [ session-attributes, validation-attributes ],
116
+ [+ (update-request / notify-request / delete-request) ]>
117
+
118
+ update-request = message<"", "update", [ ? lifetime-attributes], [ 1*2 identifier, metadata-list-type ]>
119
+ notify-request = message<"", "notify", [ ? lifetime-attributes], [ 1*2 identifier ]>
120
+ delete-request = message<"", "delete", [ "filter", tstr], []>
121
+
122
+ publish-received =
123
+ ["", "publish-received", [], []]
124
+
125
+ renew-session = message<"ifmap", "renew-session", [ ? session-attributes ], []>
126
+ renew-session-result = ["", "renew-session-result", [], []]
127
+
128
+ end-session = message<"ifmap", "end-session", [], []>
129
+ end-session-result =
130
+ ["", "end-session-result", [], []]
131
+
132
+ new-session-request =
133
+ message<"ifmap", "new-session",
134
+ [ "max-poll-result-size", uint],
135
+ []>
136
+
137
+ new-session-result =
138
+ ["", "new-session-result",
139
+ [ session-attributes,
140
+ "ifmap-publisher-id", tstr,
141
+ "max-poll-result-size", uint,
142
+ ],
143
+ []]
144
+
145
+ identifier = access-request / device / identity / ip-address / mac-address
146
+
147
+ session-attributes = (
148
+ "session-id", tstr
149
+ )
150
+
151
+ validation-attributes = (
152
+ "validation", ("None" / "BaseOnly" / "MetadataOnly" / "All")
153
+ )
154
+
155
+ adm-dom = (
156
+ "administrative-domain", tstr,
157
+ )
158
+
159
+ lifetime-attributes = (
160
+ "lifetime", ("session" / "forever")
161
+ )
162
+
163
+ access-request =
164
+ message<"ifmap", "access-request",
165
+ [ ? adm-dom,
166
+ "name", tstr
167
+ ],
168
+ []>
169
+
170
+ device = message<"ifmap", "device", [], [device-type]>
171
+ device-type =
172
+ message<"ifmap","aik-name", [], tstr> /
173
+ message<"ifmap","name", [], tstr>
174
+
175
+ identity = message<"ifmap", "identity",
176
+ [ ? adm-dom,
177
+ "name", tstr,
178
+ "type", ("aik-name" / "distinguished-name" / "dns-name" / "email-address" /
179
+ "hip-hit" / "kerberos-principal" / "trusted-platform-module" /
180
+ "username" / "other"),
181
+ "other-type-definition", tstr
182
+ ],
183
+ []>
184
+
185
+ ip-address = message<"ifmap", "ip-address",
186
+ [ ? adm-dom,
187
+ "value", tstr,
188
+ "type", ("IPv4" / "IPv6")
189
+ ],
190
+ []>
191
+
192
+ mac-address = message<"ifmap", "mac-address",
193
+ [ ? adm-dom,
194
+ "value", tstr,
195
+ ],
196
+ []>
197
+
198
+ metadata-attributes = (
199
+ "ifmap-publisher-id", tstr,
200
+ "ifmap-timestamp", tdate,
201
+ "ifmap-timestamp-fraction", tstr
202
+ )
203
+
204
+ ; optional metadata attributes? not yet possible
205
+ single-value-metadata-attributes = (
206
+ ? metadata-attributes,
207
+ "ifmap-cardinality", "singleValue"
208
+ )
209
+
210
+ multi-value-metadata-attributes = (
211
+ ? metadata-attributes,
212
+ "ifmap-cardinality", "multiValue"
213
+ )
214
+
215
+ access-request-device = message<"meta", "access-request-device",
216
+ [ single-value-metadata-attributes ], []>
217
+
218
+ access-request-ip = message<"meta", "access-request-ip",
219
+ [ single-value-metadata-attributes ], []>
220
+
221
+ access-request-mac = message<"meta", "access-request-mac",
222
+ [ single-value-metadata-attributes ], []>
223
+
224
+ authenticated-as = message<"meta", "authenticated-as",
225
+ [ single-value-metadata-attributes ], []>
226
+
227
+ authenticated-by = message<"meta", "authenticated-by",
228
+ [ single-value-metadata-attributes ], []>
229
+
230
+ capability = message<"meta", "capability",
231
+ [ multi-value-metadata-attributes ],
232
+ [ ? adm-dom,
233
+ "name", tstr
234
+ ]>
235
+
236
+ device-attribute = message<"meta", "device-attribute",
237
+ [ multi-value-metadata-attributes ],
238
+ [ "name", tstr
239
+ ]>
240
+
241
+ manufacturer = message<"", "manufacturer", [], tstr>
242
+ model = message<"", "model", [], tstr>
243
+ os = message<"", "os", [], tstr>
244
+ os-version = message<"", "os-version", [], tstr>
245
+ type = message<"", "type", [],
246
+ ("p2p" / "cve" / "botnet infection" / "worm infection" / "excessive flows" /
247
+ "behavioral change" / "policy violation" / "other")>
248
+ discovered-time = message<"", "discovered-time", [], tdate>
249
+ discoverer-id = message<"", "discoverer-id", [], tstr>
250
+ discovery-method = message<"", "discovery-method", [], tstr>
251
+ name = message<"", "name", [], tstr>
252
+ magnitude = message<"", "magnitude", [], 0..100>
253
+ confidence = message<"", "confidence", [], 0..100>
254
+ significance = message<"", "significance", [], ("critical" / "important" / "informational")>
255
+ information = message<"", "information", [], tstr>
256
+ vulnerability-uri = message<"", "vulnerability-uri", [], uri>
257
+ enforcement-action = message<"", "enforcement-action", [], tstr>
258
+ other-type-definition = message<"", "other-type-definition", [], tstr>
259
+ enforcement-reason = message<"", "enforcement-reason", [], tstr>
260
+ start-time = message<"", "start-time", [], tdate>
261
+ end-time = message<"", "end-time", [], tdate>
262
+ dhcp-server = message<"", "dhcp-server", [], tstr>
263
+ vlan = message<"", "vlan", [], uint>
264
+ vlan-name = message<"", "vlan-name", [], uint>
265
+ port = message<"", "port", [], uint>
266
+ location-information = message<"", "location-information",
267
+ [ "type", tstr,
268
+ "value", tstr], []>
269
+ qualifier = message<"", "qualifier", [], tstr>
270
+
271
+ device-characteristic = message<"meta", "device-characteristic",
272
+ [ multi-value-metadata-attributes ],
273
+ [ ? manufacturer,
274
+ ? model,
275
+ ? os,
276
+ ? os-version,
277
+ * type,
278
+ discovered-time,
279
+ discoverer-id,
280
+ + discovery-method
281
+ ]>
282
+
283
+ device-ip = message<"meta", "device-ip",
284
+ [ single-value-metadata-attributes ], [ device, ip-address]>
285
+
286
+ discovered-by = message<"meta", "discovered-by",
287
+ [ single-value-metadata-attributes ], []>
288
+
289
+ enforcement-report = message<"meta", "enforcement-report",
290
+ [ multi-value-metadata-attributes ],
291
+ [ enforcement-action,
292
+ other-type-definition,
293
+ enforcement-reason
294
+ ]>
295
+
296
+ event = message<"meta", "event",
297
+ [ multi-value-metadata-attributes ],
298
+ [ name,
299
+ discovered-time,
300
+ discoverer-id,
301
+ magnitude,
302
+ confidence,
303
+ significance,
304
+ ? type,
305
+ ? other-type-definition,
306
+ ? information,
307
+ ? vulnerability-uri
308
+ ]>
309
+
310
+ ip-mac = message<"meta", "ip-mac",
311
+ [ multi-value-metadata-attributes ],
312
+ [ ? start-time,
313
+ ? end-time,
314
+ ? dhcp-server
315
+ ]>
316
+
317
+ layer2-information = message<"meta", "layer2-information",
318
+ [ multi-value-metadata-attributes ],
319
+ [ ? vlan,
320
+ ? vlan-name,
321
+ ? port,
322
+ ? adm-dom
323
+ ]>
324
+
325
+ location = message<"meta", "location",
326
+ [ multi-value-metadata-attributes ],
327
+ [ discovered-time,
328
+ discoverer-id,
329
+ + location-information
330
+ ]>
331
+
332
+ request-for-investigation = message<"meta", "request-for-investigation",
333
+ [ multi-value-metadata-attributes ],
334
+ [ ? qualifier ]>
335
+
336
+ role = message<"meta", "role",
337
+ [ multi-value-metadata-attributes ],
338
+ [ ? adm-dom,
339
+ name
340
+ ]>
341
+
342
+ unexpected-behavior = message<"meta", "unexpected-behavior",
343
+ [ multi-value-metadata-attributes ],
344
+ [ discovered-time,
345
+ discoverer-id,
346
+ ? information,
347
+ magnitude,
348
+ ? confidence,
349
+ significance,
350
+ ? type
351
+ ]>
352
+
353
+ wlan-security-type = "open" / "wep" / "tkip" / "ccmp" / "bip" / "other"
354
+
355
+ ssid = message<"", "ssid", [], tstr>
356
+ ssid-unicast-security = message<"", "ssid-unicast-security",
357
+ [ ? other-type-definition ],
358
+ [ wlan-security-type ]>
359
+ ssid-group-security = message<"", "ssid-group-security",
360
+ [ ? other-type-definition ],
361
+ [ wlan-security-type ]>
362
+ ssid-management-security = message<"", "ssid-management-security",
363
+ [ ? other-type-definition ],
364
+ [ wlan-security-type ]>
365
+
366
+ wlan-information = message<"meta", "wlan-information",
367
+ [ single-value-metadata-attributes ],
368
+ [ ? ssid,
369
+ + ssid-unicast-security,
370
+ ssid-group-security,
371
+ + ssid-management-security
372
+ ]>
373
+
374
+ client-time = message<"opmeta", "client-time",
375
+ [ single-value-metadata-attributes,
376
+ "current-time", tdate
377
+ ], []>
378
+
379
+ ; list every capability explicitly?
380
+ server-capability = message<"opmeta", "server-capability",
381
+ [ single-value-metadata-attributes,
382
+ ],
383
+ [ message<"", "capability", [], tstr>,
384
+ ]>
385
+
386
+ metadata-list-type = [
387
+ *(access-request-device / access-request-ip / access-request-mac /
388
+ authenticated-as / authenticated-by / capability / device-attribute /
389
+ device-characteristic / device-ip / discovered-by / enforcement-report /
390
+ event / ip-mac / layer2-information / location / request-for-investigation /
391
+ role / unexpected-behavior / wlan-information
392
+ )]
@@ -410,6 +410,35 @@ HERE
410
410
  }
411
411
  end
412
412
 
413
+ def test_another_simple_alternative_group
414
+ parser = CDDL::Parser.new <<HERE
415
+ test = {
416
+ bar: int // bar: true
417
+ }
418
+ HERE
419
+ # pp parser.rules
420
+ 10.times {
421
+ g = parser.generate
422
+ # pp ["tasag", g]
423
+ bar = g['bar']
424
+ assert bar == true || Integer(bar)
425
+ assert parser.validate(g)
426
+ refute parser.validate(g.merge(foo: 3), false)
427
+ refute parser.validate(g.merge(bar: "baz"), false)
428
+ }
429
+ end
430
+
431
+
432
+ def test_bad_simple_alternative_group
433
+ parser = CDDL::Parser.new <<HERE
434
+ test = {
435
+ bar: int // true ; no member key in second choice
436
+ }
437
+ HERE
438
+ assert_raise { parser.rules }
439
+ end
440
+
441
+
413
442
  def test_simple_alternative_in_array
414
443
  parser = CDDL::Parser.new <<HERE
415
444
  test = [
@@ -450,6 +479,38 @@ HERE
450
479
  end
451
480
 
452
481
 
482
+ def test_group_choice_in_array2
483
+ parser = CDDL::Parser.new <<HERE
484
+ test = [
485
+ (1 // 2)
486
+ bar
487
+ (foob: 3 // boof: 4)
488
+ (bar // zab: 9, baz: 10)
489
+ ]
490
+ bar = (5 // 6)
491
+ HERE
492
+ # puts parser.ast_debug
493
+ pp parser.rules
494
+ 10.times {
495
+ g = parser.generate
496
+ pp ["gcia", g]
497
+ assert_equal g.size, (g[3] == 9 ? 5 : 4)
498
+ assert [1, 2].include? g[0]
499
+ assert [5, 6].include? g[1]
500
+ assert [3, 4].include? g[2]
501
+ assert [5, 6, 9].include? g[3]
502
+ assert_equal g[4], 10 if g[3] == 9
503
+ assert parser.validate(g)
504
+ }
505
+ refute parser.validate([1, 5, 8, 9], false)
506
+ refute parser.validate([1, 5, 3], false)
507
+ assert parser.validate([1, 5, 4, 5])
508
+ refute parser.validate([1, 5, 4, 9], false)
509
+ assert parser.validate([1, 5, 4, 9, 10])
510
+ refute parser.validate([1, 5, 4, 3], false)
511
+ refute parser.validate([1, 5, 4, 9, 10, 3], false)
512
+ end
513
+
453
514
  def test_validate_number_key
454
515
  parser = CDDL::Parser.new <<HERE
455
516
  test = [test1, test2, test3]
@@ -901,7 +962,7 @@ a = [a] / 1
901
962
  HERE
902
963
  10.times {
903
964
  g = parser.generate
904
- pp ["recurse-test1", g]
965
+ # pp ["recurse-test1", g]
905
966
  assert parser.validate(g)
906
967
  }
907
968
  end
@@ -943,11 +1004,31 @@ HERE
943
1004
  p parser.rules
944
1005
  10.times {
945
1006
  g = parser.generate
946
- # pp ["recurse-group-test", g]
1007
+ pp ["recurse-group-test", g]
947
1008
  assert parser.validate(g)
948
1009
  }
949
1010
  end
950
1011
 
1012
+
1013
+ def test_group_recursion2
1014
+ parser = CDDL::Parser.new <<HERE
1015
+ b = {1: 2, a}
1016
+ a = (
1017
+ foo: int
1018
+ bar: ([+aa] / 1 / 2)
1019
+ )
1020
+ aa = {a}
1021
+ HERE
1022
+ p parser.rules
1023
+ 10.times {
1024
+ g = parser.generate
1025
+ pp ["recurse-group-test2", g]
1026
+ assert parser.validate(g)
1027
+ refute parser.validate(g.merge(baz: 3), false)
1028
+ }
1029
+ end
1030
+
1031
+
951
1032
  def test_group_recursion_fail1
952
1033
  parser = CDDL::Parser.new <<HERE
953
1034
  b = {a}
@@ -964,6 +1045,25 @@ HERE
964
1045
  a = {b}
965
1046
  b = ()
966
1047
  HERE
1048
+ # puts "empty_group AST:"
1049
+ # puts parser.ast_debug
1050
+ # puts "empty_group RULES:"
1051
+ # pp parser.rules
1052
+ assert_equal({}, parser.generate)
1053
+ assert parser.validate({})
1054
+ end
1055
+
1056
+
1057
+ def test_empty_group_sp
1058
+ parser = CDDL::Parser.new <<HERE
1059
+ a = {b}
1060
+ b = (
1061
+ )
1062
+ HERE
1063
+ # puts "empty_group_sp AST:"
1064
+ # puts parser.ast_debug
1065
+ # puts "empty_group_sp RULES:"
1066
+ # pp parser.rules
967
1067
  assert_equal({}, parser.generate)
968
1068
  assert parser.validate({})
969
1069
  end
@@ -980,4 +1080,31 @@ HERE
980
1080
  # assert parser.validate({})
981
1081
  end
982
1082
 
1083
+ def test_group_occur
1084
+ parser = CDDL::Parser.new <<HERE
1085
+ a = [1*3 b]
1086
+ b = (
1087
+ 1, 2
1088
+ )
1089
+ HERE
1090
+ parser2 = CDDL::Parser.new <<HERE
1091
+ a = [1*3 (1, 2)]
1092
+ HERE
1093
+ # puts "empty_group_sp AST:"
1094
+ # puts parser.ast_debug
1095
+ # puts "empty_group_sp RULES:"
1096
+ pp parser.rules
1097
+ assert_equal parser.rules, parser2.rules
1098
+ # assert parser.validate({})
1099
+ 10.times {
1100
+ g = parser2.generate
1101
+ # pp ["group-occur", g]
1102
+ assert [2, 4, 6].include? g.size
1103
+ g.each_slice(2) do |sl|
1104
+ assert_equal sl, [1, 2]
1105
+ end
1106
+ assert parser2.validate(g)
1107
+ refute parser2.validate(g << 1, false)
1108
+ }
1109
+ end
983
1110
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cddl
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Carsten Bormann
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-04-17 00:00:00.000000000 Z
11
+ date: 2015-06-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cbor-diag
@@ -100,9 +100,12 @@ files:
100
100
  - lib/cddl.rb
101
101
  - test-data/7071-concise.cddl
102
102
  - test-data/7071-verbose.cddl
103
+ - test-data/a.cddl
104
+ - test-data/b.cddl
103
105
  - test-data/basic_syntax_example.cddl
104
106
  - test-data/cdni-ct.cddl
105
107
  - test-data/dcaf1.cddl
108
+ - test-data/ifmap-base-2.0v17.cddl
106
109
  - test-data/jcr-ex.cddl
107
110
  - test-data/minimal.cddl
108
111
  - test-data/reused_named_group.cddl