cisco_acl_intp 0.0.1

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.
Files changed (53) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +13 -0
  5. data/.travis.yml +3 -0
  6. data/.yardopts +4 -0
  7. data/Gemfile +19 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +132 -0
  10. data/Rakefile +78 -0
  11. data/acl_examples/err-acl.txt +49 -0
  12. data/acl_examples/named-ext-acl.txt +12 -0
  13. data/acl_examples/named-std-acl.txt +6 -0
  14. data/acl_examples/numd-acl.txt +21 -0
  15. data/cisco_acl_intp.gemspec +31 -0
  16. data/lib/cisco_acl_intp/ace.rb +432 -0
  17. data/lib/cisco_acl_intp/ace_ip.rb +136 -0
  18. data/lib/cisco_acl_intp/ace_other_qualifiers.rb +102 -0
  19. data/lib/cisco_acl_intp/ace_port.rb +146 -0
  20. data/lib/cisco_acl_intp/ace_proto.rb +319 -0
  21. data/lib/cisco_acl_intp/ace_srcdst.rb +114 -0
  22. data/lib/cisco_acl_intp/ace_tcp_flags.rb +65 -0
  23. data/lib/cisco_acl_intp/acl.rb +272 -0
  24. data/lib/cisco_acl_intp/acl_base.rb +111 -0
  25. data/lib/cisco_acl_intp/parser.rb +3509 -0
  26. data/lib/cisco_acl_intp/parser.ry +1397 -0
  27. data/lib/cisco_acl_intp/scanner.rb +176 -0
  28. data/lib/cisco_acl_intp/scanner_special_token_handler.rb +66 -0
  29. data/lib/cisco_acl_intp/version.rb +5 -0
  30. data/lib/cisco_acl_intp.rb +9 -0
  31. data/spec/cisco_acl_intp/ace_ip_spec.rb +111 -0
  32. data/spec/cisco_acl_intp/ace_other_qualifier_spec.rb +63 -0
  33. data/spec/cisco_acl_intp/ace_port_spec.rb +214 -0
  34. data/spec/cisco_acl_intp/ace_proto_spec.rb +200 -0
  35. data/spec/cisco_acl_intp/ace_spec.rb +605 -0
  36. data/spec/cisco_acl_intp/ace_srcdst_spec.rb +296 -0
  37. data/spec/cisco_acl_intp/ace_tcp_flags_spec.rb +38 -0
  38. data/spec/cisco_acl_intp/acl_spec.rb +523 -0
  39. data/spec/cisco_acl_intp/cisco_acl_intp_spec.rb +7 -0
  40. data/spec/cisco_acl_intp/parser_spec.rb +53 -0
  41. data/spec/cisco_acl_intp/scanner_spec.rb +122 -0
  42. data/spec/conf/extacl_objgrp_token_seq.yml +36 -0
  43. data/spec/conf/extacl_token_seq.yml +88 -0
  44. data/spec/conf/extended_acl.yml +226 -0
  45. data/spec/conf/scanner_spec_data.yml +120 -0
  46. data/spec/conf/single_tokens.yml +235 -0
  47. data/spec/conf/stdacl_token_seq.yml +8 -0
  48. data/spec/conf/tokens1.yml +158 -0
  49. data/spec/conf/tokens2.yml +206 -0
  50. data/spec/parser_fullfill_patterns.rb +145 -0
  51. data/spec/spec_helper.rb +54 -0
  52. data/tools/check_acl.rb +48 -0
  53. metadata +159 -0
@@ -0,0 +1,523 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'spec_helper'
3
+
4
+ describe NamedExtAcl do
5
+ describe '#add_entry' do
6
+ before do
7
+ @acl = NamedExtAcl.new 'test-ext-acl'
8
+ end
9
+
10
+ it 'should be zero when initialized' do
11
+ @acl.size.should be_zero
12
+ end
13
+
14
+ it 'should be size 1 and matches aclstr when added a acl entry' do
15
+ ea = ExtendedAce.new(
16
+ action: 'permit',
17
+ protocol: 'udp',
18
+ src: {
19
+ ipaddr: '192.168.3.3',
20
+ wildcard: '0.0.0.127'
21
+ },
22
+ dst: {
23
+ ipaddr: '192.168.4.4',
24
+ wildcard: '0.0.0.255'
25
+ }
26
+ )
27
+ @acl.add_entry ea
28
+ @acl.size.should eq 1
29
+ aclstr = <<'EOL'
30
+ ip access-list extended test-ext-acl
31
+ permit udp 192.168.3.0 0.0.0.127 192.168.4.0 0.0.0.255
32
+ EOL
33
+ @acl.to_s.should be_aclstr(aclstr)
34
+ end
35
+ end
36
+
37
+ describe '#add_entry_by_params' do
38
+ before do
39
+ @acl = NamedExtAcl.new 'test-ext-acl2'
40
+ @acl.add_entry_by_params(
41
+ action: 'permit',
42
+ protocol: 'udp',
43
+ src: {
44
+ ipaddr: '192.168.3.3',
45
+ wildcard: '0.0.0.127'
46
+ },
47
+ dst: {
48
+ ipaddr: '192.168.4.4',
49
+ wildcard: '0.0.0.255'
50
+ }
51
+ )
52
+ @acl.add_entry_by_params(
53
+ action: 'deny',
54
+ protocol: 'tcp',
55
+ src: {
56
+ ipaddr: '192.168.3.3',
57
+ wildcard: '0.0.0.0'
58
+ },
59
+ dst: {
60
+ ipaddr: '192.168.4.4',
61
+ wildcard: '0.0.0.255',
62
+ operator: 'gt',
63
+ port: AceUdpProtoSpec.new(
64
+ number: 32_768
65
+ )
66
+ }
67
+ )
68
+ end
69
+
70
+ it 'should be size 2' do
71
+ @acl.size.should eq 2
72
+ end
73
+
74
+ it 'mutches aclstr' do
75
+ aclstr = <<'EOL'
76
+ ip access-list extended test-ext-acl2
77
+ permit udp 192.168.3.0 0.0.0.127 192.168.4.0 0.0.0.255
78
+ deny tcp host 192.168.3.3 192.168.4.0 0.0.0.255 gt 32768
79
+ EOL
80
+ @acl.to_s.should be_aclstr(aclstr)
81
+ end
82
+
83
+ it 'mutches aclstr with remark' do
84
+ rmk = RemarkAce.new ' this is remark!!'
85
+ @acl.add_entry rmk
86
+ aclstr = <<'EOL'
87
+ ip access-list extended test-ext-acl2
88
+ permit udp 192.168.3.0 0.0.0.127 192.168.4.0 0.0.0.255
89
+ deny tcp host 192.168.3.3 192.168.4.0 0.0.0.255 gt 32768
90
+ remark this is remark!!
91
+ EOL
92
+ @acl.to_s.should be_aclstr(aclstr)
93
+ end
94
+
95
+ end
96
+
97
+ describe '#search_ace' do
98
+ # for extended ace, it is same as named/numbered ace.
99
+ # so that, tests only named-extended-ace
100
+ # and omit numbered-extended-acl
101
+ before do
102
+ @acl = NamedExtAcl.new 'test-ext-acl2'
103
+ @acl.add_entry_by_params(
104
+ action: 'permit',
105
+ protocol: 'udp',
106
+ src: {
107
+ ipaddr: '192.168.3.3',
108
+ wildcard: '0.0.0.127'
109
+ },
110
+ dst: {
111
+ ipaddr: '192.168.4.4',
112
+ wildcard: '0.0.0.255'
113
+ }
114
+ )
115
+ @acl.add_entry_by_params(
116
+ action: 'deny',
117
+ protocol: 'tcp',
118
+ src: {
119
+ ipaddr: '192.168.10.3',
120
+ wildcard: '0.0.0.0'
121
+ },
122
+ dst: {
123
+ ipaddr: '192.168.4.4',
124
+ wildcard: '0.0.0.255',
125
+ operator: 'gt',
126
+ port: AceUdpProtoSpec.new(
127
+ number: 32_768
128
+ )
129
+ }
130
+ )
131
+ @acl.add_entry_by_params(
132
+ action: 'deny',
133
+ protocol: 'ip',
134
+ src: {
135
+ ipaddr: '0.0.0.0',
136
+ wildcard: '255.255.255.255'
137
+ },
138
+ dst: {
139
+ ipaddr: '10.0.0.0',
140
+ wildcard: '0.0.0.255'
141
+ }
142
+ )
143
+ end
144
+
145
+ it 'should be match 2nd entry' do
146
+ ace = @acl.search_ace(
147
+ protocol: 'tcp',
148
+ src_ip: '192.168.10.3',
149
+ src_port: 64_332,
150
+ dst_ip: '192.168.4.5',
151
+ dst_port: 32_889
152
+ )
153
+ ace.to_s.should be_aclstr(
154
+ 'deny tcp host 192.168.10.3 192.168.4.0 0.0.0.255 gt 32768'
155
+ )
156
+ end
157
+
158
+ it 'should be last entry' do
159
+ ace = @acl.search_ace(
160
+ protocol: 'udp',
161
+ src_ip: '192.168.10.3',
162
+ src_port: 64_332,
163
+ dst_ip: '10.0.0.3',
164
+ dst_port: 33_890
165
+ )
166
+ ace.to_s.should be_aclstr('deny ip any 10.0.0.0 0.0.0.255')
167
+ end
168
+
169
+ it 'should be nil if not found match entry' do
170
+ @acl.search_ace(
171
+ protocol: 'udp',
172
+ src_ip: '192.168.10.3',
173
+ src_port: 62_223,
174
+ dst_ip: '11.0.0.3',
175
+ dst_port: 33_333
176
+ ).should be_nil
177
+ end
178
+ end
179
+ end
180
+
181
+ describe NumberedExtAcl do
182
+ describe '#add_entry' do
183
+ before do
184
+ @acl = NumberedExtAcl.new 102
185
+ end
186
+
187
+ it 'should be zero when initialized' do
188
+ @acl.size.should be_zero
189
+ end
190
+
191
+ it 'should be size 1 and matches aclstr when added a acl entry' do
192
+ ea = ExtendedAce.new(
193
+ action: 'permit',
194
+ protocol: 'udp',
195
+ src: {
196
+ ipaddr: '192.168.3.3',
197
+ wildcard: '0.0.0.127'
198
+ },
199
+ dst: {
200
+ ipaddr: '192.168.4.4',
201
+ wildcard: '0.0.0.255'
202
+ }
203
+ )
204
+ @acl.add_entry ea
205
+ @acl.size.should eq 1
206
+ aclstr = <<'EOL'
207
+ access-list 102 permit udp 192.168.3.0 0.0.0.127 192.168.4.0 0.0.0.255
208
+ EOL
209
+ @acl.to_s.should be_aclstr(aclstr)
210
+ end
211
+ end
212
+
213
+ describe '#add_entry_by_params' do
214
+ before do
215
+ @acl = NumberedExtAcl.new 104
216
+ @acl.add_entry_by_params(
217
+ action: 'permit',
218
+ protocol: 'udp',
219
+ src: {
220
+ ipaddr: '192.168.3.3',
221
+ wildcard: '0.0.0.127'
222
+ },
223
+ dst: {
224
+ ipaddr: '192.168.4.4',
225
+ wildcard: '0.0.0.255'
226
+ }
227
+ )
228
+ @acl.add_entry_by_params(
229
+ action: 'deny',
230
+ protocol: 'tcp',
231
+ src: {
232
+ ipaddr: '192.168.3.3',
233
+ wildcard: '0.0.0.0'
234
+ },
235
+ dst: {
236
+ ipaddr: '192.168.4.4',
237
+ wildcard: '0.0.0.255',
238
+ operator: 'gt',
239
+ port: AceUdpProtoSpec.new(
240
+ number: 32_768
241
+ )
242
+ }
243
+ )
244
+ end
245
+
246
+ it 'should be size 2' do
247
+ @acl.size.should eq 2
248
+ end
249
+
250
+ it 'mutches aclstr' do
251
+ aclstr = <<'EOL'
252
+ access-list 104 permit udp 192.168.3.0 0.0.0.127 192.168.4.0 0.0.0.255
253
+ access-list 104 deny tcp host 192.168.3.3 192.168.4.0 0.0.0.255 gt 32768
254
+ EOL
255
+ @acl.to_s.should be_aclstr(aclstr)
256
+ end
257
+
258
+ it 'mutches aclstr with remark' do
259
+ rmk = RemarkAce.new ' this is remark!!'
260
+ @acl.add_entry rmk
261
+ aclstr = <<'EOL'
262
+ access-list 104 permit udp 192.168.3.0 0.0.0.127 192.168.4.0 0.0.0.255
263
+ access-list 104 deny tcp host 192.168.3.3 192.168.4.0 0.0.0.255 gt 32768
264
+ access-list 104 remark this is remark!!
265
+ EOL
266
+ @acl.to_s.should be_aclstr(aclstr)
267
+ end
268
+ end
269
+ end
270
+
271
+ describe NamedStdAcl do
272
+ describe '#add_entry' do
273
+ before do
274
+ @acl = NamedStdAcl.new 'test-std-acl'
275
+ end
276
+
277
+ it 'should be zero when initialized' do
278
+ @acl.size.should be_zero
279
+ end
280
+
281
+ it 'should be size 1 and matches aclstr when added a acl entry' do
282
+ sa = StandardAce.new(
283
+ action: 'permit',
284
+ src: {
285
+ ipaddr: '192.168.3.3',
286
+ wildcard: '0.0.0.127'
287
+ }
288
+ )
289
+ @acl.add_entry sa
290
+ @acl.size.should eq 1
291
+ aclstr = <<'EOL'
292
+ ip access-list standard test-std-acl
293
+ permit 192.168.3.0 0.0.0.127
294
+ EOL
295
+ @acl.to_s.should be_aclstr(aclstr)
296
+ end
297
+ end
298
+
299
+ describe '#add_entry_by_params' do
300
+ before do
301
+ @acl = NamedStdAcl.new 'test-std-acl2'
302
+ @acl.add_entry_by_params(
303
+ action: 'permit',
304
+ src: {
305
+ ipaddr: '192.168.3.3',
306
+ wildcard: '0.0.0.127'
307
+ }
308
+ )
309
+ @acl.add_entry_by_params(
310
+ action: 'deny',
311
+ src: {
312
+ ipaddr: '192.168.4.4',
313
+ wildcard: '0.0.0.255'
314
+ }
315
+ )
316
+ end
317
+
318
+ it 'should be size 2' do
319
+ @acl.size.should eq 2
320
+ end
321
+
322
+ it 'mutches aclstr' do
323
+ aclstr = <<'EOL'
324
+ ip access-list standard test-std-acl2
325
+ permit 192.168.3.0 0.0.0.127
326
+ deny 192.168.4.0 0.0.0.255
327
+ EOL
328
+ @acl.to_s.should be_aclstr(aclstr)
329
+ end
330
+
331
+ it 'mutches aclstr with remark' do
332
+ rmk = RemarkAce.new ' this is remark!!'
333
+ @acl.add_entry rmk
334
+ aclstr = <<'EOL'
335
+ ip access-list standard test-std-acl2
336
+ permit 192.168.3.0 0.0.0.127
337
+ deny 192.168.4.0 0.0.0.255
338
+ remark this is remark!!
339
+ EOL
340
+ @acl.to_s.should be_aclstr(aclstr)
341
+ end
342
+ end
343
+
344
+ describe '#search_ace' do
345
+ # for standard ace, it is same as named/numbered ace.
346
+ # so that, tests only named-standard-ace
347
+ # and omit numbered-standard-acl
348
+ before do
349
+ @acl = NamedStdAcl.new 'test-stdacl3'
350
+ @acl.add_entry_by_params(
351
+ action: 'permit',
352
+ src: {
353
+ ipaddr: '192.168.3.3',
354
+ wildcard: '0.0.0.127'
355
+ }
356
+ )
357
+ @acl.add_entry_by_params(
358
+ action: 'deny',
359
+ src: {
360
+ ipaddr: '192.168.10.3',
361
+ wildcard: '0.0.0.0'
362
+ }
363
+ )
364
+ @acl.add_entry_by_params(
365
+ action: 'deny',
366
+ src: {
367
+ ipaddr: '10.0.0.0',
368
+ wildcard: '0.0.0.255'
369
+ }
370
+ )
371
+ end
372
+
373
+ it 'should be match 2nd entry' do
374
+ ace = @acl.search_ace(
375
+ src_ip: '192.168.10.3',
376
+ src_port: 64_332
377
+ )
378
+ ace.to_s.should be_aclstr('deny host 192.168.10.3')
379
+ end
380
+
381
+ it 'should be last entry' do
382
+ ace = @acl.search_ace(
383
+ src_ip: '10.0.0.3',
384
+ src_port: 33_890
385
+ )
386
+ ace.to_s.should be_aclstr('deny 10.0.0.0 0.0.0.255')
387
+ end
388
+
389
+ it 'should be nil if not found match entry' do
390
+ @acl.search_ace(
391
+ protocol: 'udp',
392
+ src_ip: '11.0.0.3',
393
+ src_port: 33_333
394
+ ).should be_nil
395
+ end
396
+
397
+ end
398
+
399
+ end
400
+
401
+ describe NumberedStdAcl do
402
+ describe '#add_entry' do
403
+ before do
404
+ @acl = NumberedStdAcl.new 10
405
+ end
406
+
407
+ it 'should be zero when initialized' do
408
+ @acl.size.should be_zero
409
+ end
410
+
411
+ it 'should be size 1 and matches aclstr when added a acl entry' do
412
+ sa = StandardAce.new(
413
+ action: 'permit',
414
+ src: {
415
+ ipaddr: '192.168.3.3',
416
+ wildcard: '0.0.0.127'
417
+ }
418
+ )
419
+ @acl.add_entry sa
420
+ @acl.size.should eq 1
421
+ aclstr = <<'EOL'
422
+ access-list 10 permit 192.168.3.0 0.0.0.127
423
+ EOL
424
+ @acl.to_s.should be_aclstr(aclstr)
425
+ end
426
+ end
427
+
428
+ describe '#add_entry_by_params' do
429
+ before do
430
+ @acl = NumberedStdAcl.new 14
431
+ @acl.add_entry_by_params(
432
+ action: 'permit',
433
+ src: {
434
+ ipaddr: '192.168.3.3',
435
+ wildcard: '0.0.0.127'
436
+ }
437
+ )
438
+ @acl.add_entry_by_params(
439
+ action: 'deny',
440
+ src: {
441
+ ipaddr: '192.168.4.4',
442
+ wildcard: '0.0.0.255'
443
+ }
444
+ )
445
+ end
446
+
447
+ it 'should be size 2' do
448
+ @acl.size.should eq 2
449
+ end
450
+
451
+ it 'mutches aclstr' do
452
+ aclstr = <<'EOL'
453
+ access-list 14 permit 192.168.3.0 0.0.0.127
454
+ access-list 14 deny 192.168.4.0 0.0.0.255
455
+ EOL
456
+ @acl.to_s.should be_aclstr(aclstr)
457
+ end
458
+
459
+ it 'mutches aclstr with remark' do
460
+ rmk = RemarkAce.new ' this is remark!!'
461
+ @acl.add_entry rmk
462
+ aclstr = <<'EOL'
463
+ access-list 14 permit 192.168.3.0 0.0.0.127
464
+ access-list 14 deny 192.168.4.0 0.0.0.255
465
+ access-list 14 remark this is remark!!
466
+ EOL
467
+ @acl.to_s.should be_aclstr(aclstr)
468
+ end
469
+ end
470
+
471
+ context 'list operations' do
472
+ before do
473
+ @acl = NumberedStdAcl.new 15
474
+ @acl.add_entry RemarkAce.new('entry 1')
475
+ @acl.add_entry RemarkAce.new('entry 2')
476
+ @acl.add_entry RemarkAce.new('entry 3')
477
+ @acl.add_entry RemarkAce.new('entry 4')
478
+ end
479
+
480
+ describe '#renumber' do
481
+ it 'should has seq number by add_entry' do
482
+ @acl.renumber
483
+ @acl.reduce(10) do |num, each|
484
+ each.seq_number.should eq num
485
+ num + 10
486
+ end
487
+ end
488
+ end
489
+
490
+ describe '#sort' do
491
+ it 'should be sorted by seq number' do
492
+ @acl.renumber # initialize seq number
493
+
494
+ last_ace = @acl.pop
495
+ last_ace.seq_number = 15
496
+ @acl.add_entry last_ace
497
+ acl_new = @acl.dup_with_list(@acl.sort)
498
+
499
+ aclstr = <<'EOL'
500
+ access-list 15 remark entry 1
501
+ access-list 15 remark entry 2
502
+ access-list 15 remark entry 3
503
+ access-list 15 remark entry 4
504
+ EOL
505
+ aclstr_new = <<'EOL'
506
+ access-list 15 remark entry 1
507
+ access-list 15 remark entry 4
508
+ access-list 15 remark entry 2
509
+ access-list 15 remark entry 3
510
+ EOL
511
+ @acl.name.should eq acl_new.name
512
+ @acl.acl_type.should eq acl_new.acl_type
513
+ @acl.to_s.should be_aclstr(aclstr)
514
+ acl_new.to_s.should be_aclstr(aclstr_new)
515
+ end
516
+ end
517
+ end
518
+ end
519
+ ### Local variables:
520
+ ### mode: Ruby
521
+ ### coding: utf-8-unix
522
+ ### indent-tabs-mode: nil
523
+ ### End:
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe CiscoAclIntp do
4
+ it 'should have a version number' do
5
+ CiscoAclIntp::VERSION.should_not be_nil
6
+ end
7
+ end
@@ -0,0 +1,53 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'spec_helper'
3
+ require 'yaml'
4
+
5
+ describe 'Parser' do
6
+ describe '#parse_file' do
7
+ before do
8
+ @parser = CiscoAclIntp::Parser.new(color: false)
9
+ end
10
+
11
+ # test data file
12
+ data_files = [
13
+ 'extended_acl.yml',
14
+ # 'object_group.yml'
15
+ ]
16
+
17
+ data_files.each do |each_file|
18
+ tests = YAML.load_file(_spec_conf_dir(each_file))
19
+ # puts YAML.dump data
20
+
21
+ tests.each do |each_test|
22
+ # filename
23
+ acl_file_base = [each_test[:symbol], '.acl.yml'].join
24
+ acl_file = _spec_data_dir(acl_file_base)
25
+
26
+ # write acl to file
27
+ File.open(acl_file, 'w') do |file|
28
+ file.puts each_test[:acl]
29
+ end
30
+
31
+ if each_test[:correct]
32
+ it "should be parsed #{acl_file} with no error" do
33
+ @parser.parse_file(acl_file)
34
+ @parser.contains_error?.should be_false
35
+ end
36
+ else
37
+ it "should be parsed #{acl_file} with error" do
38
+ @parser.parse_file(acl_file)
39
+ @parser.contains_error?.should be_true
40
+ end
41
+ end
42
+ end
43
+
44
+ end
45
+
46
+ end # parse_file
47
+ end # Parser
48
+
49
+ ### Local variables:
50
+ ### mode: Ruby
51
+ ### coding: utf-8-unix
52
+ ### indent-tabs-mode: nil
53
+ ### End:
@@ -0,0 +1,122 @@
1
+ # -*- coding: utf-8 -*-
2
+ require 'spec_helper'
3
+ require 'yaml'
4
+
5
+ describe 'Scanner' do
6
+ describe '#scan_line' do
7
+ before do
8
+ @s = Scanner.new
9
+ end
10
+
11
+ it 'should be parsed correct tokens as 1-line acl' do
12
+ acl = <<'EOL'
13
+ ip access-list extended FA8-OUT
14
+ deny udp any any eq bootpc
15
+ permit ip any any
16
+ EOL
17
+ @s.scan_line(acl).should == [
18
+ [:NAMED_ACL, 'ip access-list'],
19
+ %w[extended extended],
20
+ [:STRING, 'FA8-OUT'],
21
+ [:EOS, nil],
22
+ %w[deny deny],
23
+ %w[udp udp],
24
+ %w[any any],
25
+ %w[any any],
26
+ %w[eq eq],
27
+ %w[bootpc bootpc],
28
+ [:EOS, nil],
29
+ %w[permit permit],
30
+ %w[ip ip],
31
+ %w[any any],
32
+ %w[any any],
33
+ [:EOS, nil],
34
+ [:EOS, nil], # last, empty line
35
+ [false, 'EOF']
36
+ ]
37
+ end
38
+
39
+ tokens = YAML.load_file(_spec_conf_dir('single_tokens.yml'))
40
+ tokens.each do |each|
41
+ # run test
42
+ it "should be parsed single token: #{each}" do
43
+ @s.scan_line(each).should
44
+ eq [
45
+ [each, each],
46
+ [:EOS, nil],
47
+ [:EOS, nil],
48
+ [false, 'EOF']
49
+ ]
50
+ end
51
+ end
52
+ end # scan_line
53
+
54
+ describe '#scan_file' do
55
+ before do
56
+ @s = Scanner.new
57
+ end
58
+
59
+ tests = YAML.load_file(_spec_conf_dir('scanner_spec_data.yml'))
60
+
61
+ # generate test data (yaml file)
62
+ tests.each do |each_test|
63
+ tokens = []
64
+ lines = each_test[:test_data]
65
+
66
+ # filename
67
+ acl_file_base = [each_test[:test_symbol], '.acl.yml'].join
68
+ acl_file = _spec_data_dir(acl_file_base)
69
+
70
+ # generate access list string data file
71
+ # (input for scanner)
72
+ File.open(acl_file, 'w') do |file|
73
+ lines.each do |each_line|
74
+ file.puts each_line[:line]
75
+
76
+ # make tokens data
77
+ if each_line[:tokens]
78
+ each_line[:tokens].each do |each_token|
79
+ case each_token
80
+ when Array
81
+ (symbstr, val) = each_token
82
+ tokens.push [symbstr.intern, val] # symbolize
83
+ when String
84
+ tokens.push [each_token, each_token]
85
+ end
86
+ end
87
+ tokens.push [:EOS, nil] # End of String
88
+ end
89
+ end
90
+ tokens.push [false, 'EOF'] # last token (End of File)
91
+ end
92
+
93
+ # filename
94
+ token_file_base = [each_test[:test_symbol], '.token.yml'].join
95
+ token_file = _spec_data_dir(token_file_base)
96
+
97
+ # generate access list token data file
98
+ # (expected output of scanner)
99
+ File.open(token_file, 'w') do |file|
100
+ YAML.dump(tokens, file)
101
+ end
102
+
103
+ # run test
104
+ it "should be parsed #{File.basename(acl_file)} as \
105
+ #{File.basename(token_file)} in tests of \
106
+ #{each_test[:test_description]}" do
107
+ tokens = YAML.load_file(token_file)
108
+ File.open(acl_file) do |file|
109
+ @s.scan_file(file).should eq tokens
110
+ end
111
+ end
112
+ end # tests.each
113
+
114
+ end # scan_file
115
+
116
+ end # describe Scanner
117
+
118
+ ### Local variables:
119
+ ### mode: Ruby
120
+ ### coding: utf-8-unix
121
+ ### indent-tabs-mode: nil
122
+ ### End: