rtext 0.8.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,1691 +1,1732 @@
1
- # coding: binary
2
- $:.unshift File.join(File.dirname(__FILE__),"..","lib")
3
-
4
- require 'test/unit'
5
- require 'bigdecimal'
6
- require 'rgen/environment'
7
- require 'rgen/metamodel_builder'
8
- require 'rtext/instantiator'
9
- require 'rtext/language'
10
-
11
- class InstantiatorTest < Test::Unit::TestCase
12
-
13
- module TestMM
14
- extend RGen::MetamodelBuilder::ModuleExtension
15
- class TestNode < RGen::MetamodelBuilder::MMBase
16
- SomeEnum = RGen::MetamodelBuilder::DataTypes::Enum.new([:A, :B, :'non-word*chars', :'2you'])
17
- has_attr 'text', String
18
- has_attr 'integer', Integer
19
- has_attr 'boolean', Boolean
20
- has_attr 'enum', SomeEnum
21
- has_many_attr 'nums', Integer
22
- has_attr 'float', Float
23
- has_one 'related', TestNode
24
- has_many 'others', TestNode
25
- contains_many 'childs', TestNode, 'parent'
26
- end
27
- class SubNode < TestNode
28
- end
29
- end
30
-
31
- module TestMM2
32
- extend RGen::MetamodelBuilder::ModuleExtension
33
- class TestNode < RGen::MetamodelBuilder::MMBase
34
- contains_one 'singleChild', TestNode, 'parent'
35
- end
36
- class TestNode2 < RGen::MetamodelBuilder::MMBase
37
- end
38
- class TestNode3 < RGen::MetamodelBuilder::MMBase
39
- end
40
- class TestNode4 < TestNode
41
- end
42
- TestNode.contains_one 'singleChild2a', TestNode2, 'parentA'
43
- TestNode.contains_one 'singleChild2b', TestNode2, 'parentB'
44
- end
45
-
46
- module TestMMLinenoFilenameFragment
47
- extend RGen::MetamodelBuilder::ModuleExtension
48
- class TestNode < RGen::MetamodelBuilder::MMBase
49
- has_attr 'text', String
50
- has_attr 'lineno', Integer
51
- has_attr 'filename', String
52
- has_attr 'fragmentr', String
53
- contains_many 'childs', TestNode, 'parent'
54
- end
55
- end
56
-
57
- module TestMMAbstract
58
- extend RGen::MetamodelBuilder::ModuleExtension
59
- class TestNode < RGen::MetamodelBuilder::MMBase
60
- abstract
61
- end
62
- end
63
-
64
- module TestMMData
65
- extend RGen::MetamodelBuilder::ModuleExtension
66
- # class "Data" exists in the standard Ruby namespace
67
- class Data < RGen::MetamodelBuilder::MMBase
68
- has_attr 'notTheBuiltin', String
69
- end
70
- end
71
-
72
- module TestMMSubpackage
73
- extend RGen::MetamodelBuilder::ModuleExtension
74
- module SubPackage
75
- extend RGen::MetamodelBuilder::ModuleExtension
76
- class TestNodeSub < RGen::MetamodelBuilder::MMBase
77
- has_attr 'text', String
78
- end
79
- class Data < RGen::MetamodelBuilder::MMBase
80
- has_attr 'notTheBuiltin', String
81
- end
82
- end
83
- end
84
-
85
- module TestMMNonRootClass
86
- extend RGen::MetamodelBuilder::ModuleExtension
87
- class NonRootClass < RGen::MetamodelBuilder::MMBase
88
- end
89
- end
90
-
91
- module TestMMContextSensitiveCommands
92
- extend RGen::MetamodelBuilder::ModuleExtension
93
- module SubPackage2
94
- extend RGen::MetamodelBuilder::ModuleExtension
95
- class Command < RGen::MetamodelBuilder::MMBase
96
- end
97
- end
98
- module SubPackage1
99
- extend RGen::MetamodelBuilder::ModuleExtension
100
- class Command < RGen::MetamodelBuilder::MMBase
101
- contains_one 'command', SubPackage2::Command, 'super'
102
- end
103
- end
104
- class TestNode < RGen::MetamodelBuilder::MMBase
105
- contains_one 'command', SubPackage1::Command, 'testNode'
106
- end
107
- end
108
-
109
- def test_simple
110
- env, problems = instantiate(%Q(
111
- TestNode text: "some text", nums: [1,2] {
112
- TestNode text: "child"
113
- TestNode text: "child2"
114
- }
115
- ), TestMM)
116
- assert_no_problems(problems)
117
- assert_model_simple(env, :with_nums)
118
- end
119
-
120
- def test_multiple_roots
121
- env, problems = instantiate(%Q(
122
- TestNode
123
- TestNode
124
- ), TestMM)
125
- assert_no_problems(problems)
126
- assert_equal 2, env.elements.size
127
- end
128
-
129
- def test_comment
130
- env, problems = instantiate(%Q(
131
- # comment 1
132
- TestNode text: "some text" {# comment 1.1
133
- childs: [ # comment 1.2
134
- # comment 2
135
- TestNode text: "child" # comment 2.1
136
- # comment 3
137
- TestNode text: "child2" #comment 3.1
138
- # unassociated
139
- ] # comment 1.3
140
- # unassociated
141
- } # comment 1.4
142
- #comment 1
143
- TestNode { #comment 1.1
144
- childs: # comment 1.2
145
- TestNode text: "child" #comment2
146
- # unassociated
147
- }# comment 1.3
148
- # unassociated
149
- ), TestMM)
150
- assert_no_problems(problems)
151
- assert_model_simple(env)
152
- end
153
-
154
- def test_comment_only
155
- env, problems = instantiate(%Q(
156
- # comment 1
157
- ), TestMM)
158
- assert_no_problems(problems)
159
- end
160
-
161
- def test_empty
162
- env, problems = instantiate("", TestMM)
163
- assert_no_problems(problems)
164
- end
165
-
166
- #
167
- # options
168
- #
169
-
170
- def test_line_number_setter
171
- env, problems = instantiate(%q(
172
- TestNode text: "node1" {
173
- TestNode text: "node2"
174
-
175
- #some comment
176
- TestNode text: "node3"
177
- }
178
- TestNode text: "node4"
179
- ), TestMMLinenoFilenameFragment, :line_number_attribute => "lineno")
180
- assert_no_problems(problems)
181
- assert_equal 2, env.find(:text => "node1").first.lineno
182
- assert_equal 3, env.find(:text => "node2").first.lineno
183
- assert_equal 6, env.find(:text => "node3").first.lineno
184
- assert_equal 8, env.find(:text => "node4").first.lineno
185
- end
186
-
187
- def test_missing_line_number_setter
188
- env, problems = instantiate(%Q(
189
- TestNode text: A
190
- ), TestMMLinenoFilenameFragment, :line_number_attribute => "wrong_attribute_name")
191
- assert_no_problems(problems)
192
- assert_nil env.elements.first.lineno
193
- end
194
-
195
- def test_root_elements
196
- root_elements = []
197
- env, problems = instantiate(%Q(
198
- TestNode text: A
199
- TestNode text: B
200
- TestNode text: C
201
- ), TestMM, :root_elements => root_elements)
202
- assert_no_problems(problems)
203
- assert_equal ["A", "B", "C"], root_elements.text
204
- end
205
-
206
- def test_file_name_option
207
- env, problems = instantiate(%Q(
208
- TestNode text: A
209
- TestNode text: B
210
- TestNode a problem here
211
- ), TestMM, :file_name => "some_file")
212
- assert_equal "some_file", problems.first.file
213
- end
214
-
215
- def test_file_name_setter
216
- env, problems = instantiate(%Q(
217
- TestNode text: A
218
- ), TestMMLinenoFilenameFragment, :file_name => "some_file", :file_name_attribute => "filename")
219
- assert_equal "some_file", env.elements.first.filename
220
- end
221
-
222
- def test_missing_file_name_setter
223
- env, problems = instantiate(%Q(
224
- TestNode text: A
225
- ), TestMMLinenoFilenameFragment, :file_name => "some_file", :file_name_attribute => "wrong_attribute_name")
226
- assert_nil env.elements.first.filename
227
- end
228
-
229
- def test_fragment_ref_setter
230
- the_ref = "is a string here but would normally be an RGen fragment"
231
- env, problems = instantiate(%Q(
232
- TestNode text: A
233
- ), TestMMLinenoFilenameFragment, :fragment_ref => the_ref, :fragment_ref_attribute => "fragmentr")
234
- assert_equal the_ref.object_id, env.elements.first.fragmentr.object_id
235
- end
236
-
237
- def test_missing_fragment_ref_setter
238
- the_ref = "is a string here but would normally be an RGen fragment"
239
- env, problems = instantiate(%Q(
240
- TestNode text: A
241
- ), TestMMLinenoFilenameFragment, :fragment_ref => the_ref, :fragment_ref_attribute => "wrong_attribute_name")
242
- assert_nil env.elements.first.fragmentr
243
- end
244
-
245
- #
246
- # children with role
247
- #
248
-
249
- def test_child_role
250
- env, problems = instantiate(%Q(
251
- TestNode text: "some text" {
252
- TestNode text: "child"
253
- childs:
254
- TestNode text: "child2"
255
- }
256
- ), TestMM)
257
- assert_no_problems(problems)
258
- assert_model_simple(env)
259
- end
260
-
261
- def test_child_role2
262
- env, problems = instantiate(%Q(
263
- TestNode text: "some text" {
264
- childs: [
265
- TestNode text: "child"
266
- TestNode text: "child2"
267
- ]
268
- }
269
- ), TestMM)
270
- assert_no_problems(problems)
271
- assert_model_simple(env)
272
- end
273
-
274
- def test_child_role3
275
- env, problems = instantiate(%Q(
276
- TestNode text: "some text" {
277
- childs:
278
- TestNode text: "child"
279
- childs:
280
- TestNode text: "child2"
281
- }
282
- ), TestMM)
283
- assert_no_problems(problems)
284
- assert_model_simple(env)
285
- end
286
-
287
- def test_child_role4
288
- env, problems = instantiate(%Q(
289
- TestNode text: "some text" {
290
- childs: [
291
- TestNode text: "child"
292
- ]
293
- childs: [
294
- TestNode text: "child2"
295
- ]
296
- }
297
- ), TestMM)
298
- assert_no_problems(problems)
299
- assert_model_simple(env)
300
- end
301
-
302
- def test_child_role_empty
303
- env, problems = instantiate(%Q(
304
- TestNode {
305
- childs: [
306
- ]
307
- }
308
- ), TestMM)
309
- assert_no_problems(problems)
310
- end
311
-
312
-
313
- #
314
- # whitespace
315
- #
316
-
317
- def test_whitespace1
318
- env, problems = instantiate(%Q(
319
- TestNode text: "some text" , nums: [ 1 , 2 ] {
320
-
321
- # comment
322
-
323
- TestNode text: "child"
324
-
325
- TestNode text: "child2"
326
-
327
- }
328
- ), TestMM)
329
- assert_no_problems(problems)
330
- assert_model_simple(env, :with_nums)
331
- end
332
-
333
- def test_whitespace2
334
- env, problems = instantiate(%Q(
335
- # comment1
336
-
337
- # comment2
338
-
339
- TestNode text: "some text" {
340
-
341
- childs:
342
-
343
- # comment
344
-
345
- TestNode text: "child"
346
-
347
- childs: [
348
-
349
- TestNode text: "child2"
350
-
351
- ]
352
-
353
- }
354
- ), TestMM)
355
- assert_no_problems(problems)
356
- assert_model_simple(env)
357
- end
358
-
359
- def test_no_newline_at_eof
360
- env, problems = instantiate(%Q(
361
- TestNode), TestMM)
362
- assert_no_problems(problems)
363
- end
364
-
365
- def test_no_newline_at_eof2
366
- env, problems = instantiate(%Q(
367
- TestNode {
368
- }), TestMM)
369
- assert_no_problems(problems)
370
- end
371
-
372
- #
373
- # references
374
- #
375
-
376
- def test_references
377
- unresolved_refs = []
378
- env, problems = instantiate(%Q(
379
- TestNode text: "root" {
380
- TestNode related: /
381
- TestNode related: //
382
- TestNode related: /some
383
- TestNode related: //some
384
- TestNode related: /some/
385
- TestNode related: some/
386
- TestNode related: some//
387
- TestNode related: some
388
- TestNode related: /some/reference
389
- TestNode related: /some/reference/
390
- TestNode related: some/reference/
391
- TestNode related: some/reference
392
- }
393
- ), TestMM, :unresolved_refs => unresolved_refs)
394
- assert_no_problems(problems)
395
- ref_targets = [
396
- "/",
397
- "//",
398
- "/some",
399
- "//some",
400
- "/some/",
401
- "some/",
402
- "some//",
403
- "some",
404
- "/some/reference",
405
- "/some/reference/",
406
- "some/reference/",
407
- "some/reference"
408
- ]
409
- assert_equal ref_targets, env.find(:text => "root").first.childs.collect{|c| c.related.targetIdentifier}
410
- assert_equal ref_targets, unresolved_refs.collect{|ur| ur.proxy.targetIdentifier}
411
- assert unresolved_refs.all?{|ur| ur.feature_name == "related"}
412
- end
413
-
414
- def test_references_many
415
- env, problems = instantiate(%Q(
416
- TestNode text: "root" {
417
- TestNode others: /other
418
- TestNode others: [ /other ]
419
- TestNode others: [ /other1, /other2 ]
420
- }
421
- ), TestMM)
422
- assert_no_problems(problems)
423
- assert_equal [
424
- [ "/other" ],
425
- [ "/other" ],
426
- [ "/other1", "/other2" ],
427
- ], env.find(:text => "root").first.childs.collect{|c| c.others.collect{|p| p.targetIdentifier}}
428
- end
429
-
430
- def test_reference_regexp
431
- env, problems = instantiate(%Q(
432
- TestNode text: "root" {
433
- TestNode related: some
434
- TestNode related: ::some
435
- TestNode related: some::reference
436
- TestNode related: ::some::reference
437
- }
438
- ), TestMM, :reference_regexp => /\A\w*(::\w*)+/)
439
- assert_no_problems(problems)
440
- assert_equal [
441
- "some",
442
- "::some",
443
- "some::reference",
444
- "::some::reference"
445
- ], env.find(:text => "root").first.childs.collect{|c| c.related.targetIdentifier}
446
- end
447
-
448
- #
449
- # unlabled arguments
450
- #
451
-
452
- def test_unlabled_arguments
453
- env, problems = instantiate(%Q(
454
- TestNode "some text", [1,2] {
455
- TestNode "child"
456
- TestNode "child2"
457
- }
458
- ), TestMM, :unlabled_arguments => proc {|clazz| ["text", "nums"]})
459
- assert_no_problems(problems)
460
- assert_model_simple(env, :with_nums)
461
- end
462
-
463
- def test_unlabled_arguments_not_in_front
464
- env, problems = instantiate(%Q(
465
- TestNode nums: [1,2], "some text" {
466
- TestNode "child"
467
- TestNode "child2"
468
- }
469
- ), TestMM, :unlabled_arguments => proc {|clazz| ["text", "nums"]})
470
- assert_no_problems(problems)
471
- assert_model_simple(env, :with_nums)
472
- end
473
-
474
- def test_unlabled_arguments_using_labled
475
- env, problems = instantiate(%Q(
476
- TestNode text: "some text", nums: [1,2] {
477
- TestNode text: "child"
478
- TestNode text: "child2"
479
- }
480
- ), TestMM, :unlabled_arguments => proc {|clazz| ["text", "nums"]})
481
- assert_no_problems(problems)
482
- assert_model_simple(env, :with_nums)
483
- end
484
-
485
- def test_unlabled_arguments_subclass
486
- env, problems = instantiate(%Q(
487
- SubNode "some text", [1, 2] {
488
- TestNode text: "child"
489
- TestNode text: "child2"
490
- }
491
- ), TestMM, :unlabled_arguments => proc {|clazz| ["text", "nums"]})
492
- assert_no_problems(problems)
493
- assert_model_simple(env, :with_nums)
494
- end
495
-
496
- #
497
- # context sensitive commands
498
- #
499
-
500
- def test_context_sensitive
501
- env, problems = instantiate(%Q(
502
- TestNode {
503
- Command {
504
- Command
505
- }
506
- }
507
- ), TestMMContextSensitiveCommands)
508
- assert_no_problems(problems)
509
- root = env.find(:class => TestMMContextSensitiveCommands::TestNode).first
510
- assert_not_nil(root)
511
- assert(root.command.is_a?(TestMMContextSensitiveCommands::SubPackage1::Command))
512
- assert(root.command.command.is_a?(TestMMContextSensitiveCommands::SubPackage2::Command))
513
- end
514
-
515
- def test_context_sensitive_command_name_mapping
516
- env, problems = instantiate(%Q(
517
- Command {
518
- Command {
519
- Command
520
- }
521
- }
522
- ), TestMMContextSensitiveCommands, :command_name_provider => lambda do |c|
523
- "Command" end)
524
- assert_no_problems(problems)
525
- root = env.find(:class => TestMMContextSensitiveCommands::TestNode).first
526
- assert_not_nil(root)
527
- assert(root.command.is_a?(TestMMContextSensitiveCommands::SubPackage1::Command))
528
- assert(root.command.command.is_a?(TestMMContextSensitiveCommands::SubPackage2::Command))
529
- end
530
-
531
- #
532
- # problems
533
- #
534
-
535
- def test_unexpected_end_of_file
536
- env, problems = instantiate(%Q(
537
- TestNode text: "some text" {
538
- ), TestMM)
539
- assert_problems([[/unexpected end of file, expected \}/i, 2]], problems)
540
- end
541
-
542
- def test_unknown_command
543
- env, problems = instantiate(%Q(
544
- NotDefined
545
- ), TestMM)
546
- assert_problems([[/unknown command 'NotDefined'/i, 2]], problems)
547
- end
548
-
549
- def test_unknown_command_abstract
550
- env, problems = instantiate(%Q(
551
- TestNode
552
- ), TestMMAbstract)
553
- assert_problems([[/unknown command 'TestNode'/i, 2]], problems)
554
- end
555
-
556
- def test_unexpected_unlabled_argument
557
- env, problems = instantiate(%Q(
558
- TestNode "more text"
559
- ), TestMM)
560
- assert_problems([[/unexpected unlabled argument, 0 unlabled arguments expected/i, 2]], problems)
561
- end
562
-
563
- def test_unknown_child_role
564
- env, problems = instantiate(%Q(
565
- TestNode {
566
- notdefined:
567
- TestNode
568
- }
569
- ), TestMM)
570
- assert_problems([[/unknown child role 'notdefined'/i, 3]], problems)
571
- end
572
-
573
- def test_not_a_child_role
574
- env, problems = instantiate(%Q(
575
- TestNode {
576
- text:
577
- TestNode
578
- others:
579
- TestNode
580
- }
581
- ), TestMM)
582
- assert_problems([
583
- [/role 'text' can not take child elements/i, 3],
584
- [/role 'others' can not take child elements/i, 5]
585
- ], problems)
586
- end
587
-
588
- def test_not_a_single_child
589
- env, problems = instantiate(%Q(
590
- TestNode {
591
- singleChild: [
592
- TestNode
593
- TestNode
594
- ]
595
- }
596
- ), TestMM2)
597
- assert_problems([
598
- [/only one child allowed in role 'singleChild'/i, 5]
599
- ], problems)
600
- end
601
-
602
- def test_not_a_single_child2
603
- env, problems = instantiate(%Q(
604
- TestNode {
605
- singleChild:
606
- TestNode
607
- singleChild: [
608
- ]
609
- singleChild:
610
- TestNode
611
- }
612
- ), TestMM2)
613
- assert_problems([
614
- [/only one child allowed in role 'singleChild'/i, 8]
615
- ], problems)
616
- end
617
-
618
- def test_wrong_child_role
619
- env, problems = instantiate(%Q(
620
- TestNode {
621
- singleChild:
622
- TestNode2
623
- }
624
- ), TestMM2)
625
- assert_problems([
626
- [/role 'singleChild' can not take a TestNode2, expected TestNode/i, 4]
627
- ], problems)
628
- end
629
-
630
- def test_child_role_without_child
631
- env, problems = instantiate(%Q(
632
- TestNode {
633
- singleChild:
634
- }
635
- ), TestMM2)
636
- assert_problems([
637
- [/unexpected \}, expected identifier/i, 4]
638
- ], problems)
639
- end
640
-
641
- def test_wrong_child
642
- env, problems = instantiate(%Q(
643
- TestNode {
644
- TestNode3
645
- }
646
- ), TestMM2)
647
- assert_problems([
648
- [/command 'TestNode3' can not be used in this context/i, 3]
649
- ], problems)
650
- end
651
-
652
- def test_ambiguous_child_role
653
- env, problems = instantiate(%Q(
654
- TestNode {
655
- TestNode2
656
- }
657
- ), TestMM2)
658
- assert_problems([
659
- [/role of element is ambiguous, use a role label/i, 3]
660
- ], problems)
661
- end
662
-
663
- def test_non_ambiguous_child_role_subclass
664
- env, problems = instantiate(%Q(
665
- TestNode {
666
- TestNode4
667
- }
668
- ), TestMM2)
669
- assert_no_problems(problems)
670
- end
671
-
672
- def test_not_a_single_child3
673
- env, problems = instantiate(%Q(
674
- TestNode {
675
- TestNode
676
- TestNode
677
- }
678
- ), TestMM2)
679
- assert_problems([
680
- [/only one child allowed in role 'singleChild'/i, 4]
681
- ], problems)
682
- end
683
-
684
- def test_unknown_argument
685
- env, problems = instantiate(%Q(
686
- TestNode unknown: "some text"
687
- ), TestMM)
688
- assert_problems([[/unknown argument 'unknown'/i, 2]], problems)
689
- end
690
-
691
- def test_attribute_in_child_reference
692
- env, problems = instantiate(%Q(
693
- TestNode singleChild: "some text"
694
- ), TestMM2)
695
- assert_problems([[/argument 'singleChild' can only take child elements/i, 2]], problems)
696
- end
697
-
698
- def test_arguments_duplicate
699
- env, problems = instantiate(%Q(
700
- TestNode text: "some text", text: "more text"
701
- ), TestMM)
702
- assert_problems([[/argument 'text' already defined/i, 2]], problems)
703
- end
704
-
705
- def test_unlabled_arguments_duplicate
706
- env, problems = instantiate(%Q(
707
- TestNode text: "some text", "more text"
708
- ), TestMM, :unlabled_arguments => proc {|c| ["text"]})
709
- assert_problems([[/argument 'text' already defined/i, 2]], problems)
710
- end
711
-
712
- def test_multiple_arguments_in_non_many_attribute
713
- env, problems = instantiate(%Q(
714
- TestNode text: ["text1", "text2"]
715
- ), TestMM)
716
- assert_problems([[/argument 'text' can take only one value/i, 2]], problems)
717
- end
718
-
719
- def test_wrong_argument_type
720
- env, problems = instantiate(%Q(
721
- TestNode text: 1
722
- TestNode integer: "text"
723
- TestNode integer: true
724
- TestNode integer: 1.2
725
- TestNode integer: a
726
- TestNode integer: /a
727
- TestNode enum: 1
728
- TestNode enum: x
729
- TestNode related: 1
730
- ), TestMM)
731
- assert_problems([
732
- [/argument 'text' can not take a integer, expected string/i, 2],
733
- [/argument 'integer' can not take a string, expected integer/i, 3],
734
- [/argument 'integer' can not take a boolean, expected integer/i, 4],
735
- [/argument 'integer' can not take a float, expected integer/i, 5],
736
- [/argument 'integer' can not take a identifier, expected integer/i, 6],
737
- [/argument 'integer' can not take a reference, expected integer/i, 7],
738
- [/argument 'enum' can not take a integer, expected identifier/i, 8],
739
- [/argument 'enum' can not take value x, expected A, B/i, 9],
740
- [/argument 'related' can not take a integer, expected reference, identifier/i, 10]
741
- ], problems)
742
- end
743
-
744
- def test_missing_opening_brace
745
- env, problems = instantiate(%Q(
746
- TestNode
747
- }
748
- ), TestMM)
749
- assert_problems([[/unexpected \}, expected identifier/i, 3]], problems)
750
- end
751
-
752
- def test_invalid_root
753
- env, problems = instantiate(%Q(
754
- NonRootClass
755
- ), TestMMNonRootClass)
756
- assert_problems([[/command 'NonRootClass' can not be used on root level/i, 2]], problems)
757
- end
758
-
759
- #
760
- # problem recovery
761
- #
762
-
763
- def test_missing_value
764
- root_elements = []
765
- env, problems = instantiate(%Q(
766
- TestNode nums: 1, text:
767
- TestNode nums: 2, text: {
768
- SubNode
769
- }
770
- TestNode text: ,nums: 3 {
771
- SubNode
772
- }
773
- TestNode nums: , text: , bla:
774
- ), TestMM, :root_elements => root_elements)
775
- assert_equal 4, root_elements.size
776
- assert_equal [1], root_elements[0].nums
777
- assert_nil root_elements[0].text
778
- assert_equal [2], root_elements[1].nums
779
- assert_equal 1, root_elements[1].childs.size
780
- assert_equal [3], root_elements[2].nums
781
- assert_equal 1, root_elements[2].childs.size
782
- assert_problems([
783
- [/unexpected newline, expected.*integer/i, 2],
784
- [/unexpected \{, expected.*integer/i, 3],
785
- [/unexpected ,, expected.*integer/i, 6],
786
- [/unexpected ,, expected.*integer/i, 9],
787
- [/unexpected ,, expected.*integer/i, 9],
788
- [/unexpected newline, expected.*integer/i, 9],
789
- [/unknown argument 'bla'/i, 9],
790
- ], problems)
791
- end
792
-
793
- def test_missing_comma
794
- root_elements = []
795
- env, problems = instantiate(%Q(
796
- TestNode nums: 1 text: "bla"
797
- ), TestMM, :root_elements => root_elements)
798
- assert_equal 1, root_elements.size
799
- assert_equal [1], root_elements[0].nums
800
- assert_equal "bla", root_elements[0].text
801
- assert_problems([
802
- [/unexpected label .*, expected ,/i, 2],
803
- ], problems)
804
- end
805
-
806
- def test_missing_label
807
- root_elements = []
808
- env, problems = instantiate(%Q(
809
- TestNode nums: 1 "bla"
810
- ), TestMM, :root_elements => root_elements)
811
- assert_equal 1, root_elements.size
812
- assert_equal [1], root_elements[0].nums
813
- assert_problems([
814
- [/unexpected string 'bla', expected ,/i, 2],
815
- [/unexpected unlabled argument/i, 2]
816
- ], problems)
817
- end
818
-
819
- def test_unclosed_bracket1
820
- root_elements = []
821
- env, problems = instantiate(%Q(
822
- TestNode nums: [1, "bla"
823
- ), TestMM, :root_elements => root_elements)
824
- assert_equal 1, root_elements.size
825
- assert_equal [1], root_elements[0].nums
826
- assert_nil root_elements[0].text
827
- assert_problems([
828
- [/unexpected newline, expected \]/i, 2],
829
- [/argument 'nums' can not take a string, expected integer/i, 2],
830
- ], problems)
831
- end
832
-
833
- def test_unclosed_bracket2
834
- root_elements = []
835
- env, problems = instantiate(%Q(
836
- TestNode nums: [1, text: "bla"
837
- ), TestMM, :root_elements => root_elements)
838
- assert_equal 1, root_elements.size
839
- assert_equal [1], root_elements[0].nums
840
- assert_equal "bla", root_elements[0].text
841
- assert_problems([
842
- [/unexpected label 'text', expected identifier/i, 2],
843
- ], problems)
844
- end
845
-
846
- def test_unclosed_bracket3
847
- root_elements = []
848
- env, problems = instantiate(%Q(
849
- TestNode nums: [1 text: "bla"
850
- ), TestMM, :root_elements => root_elements)
851
- assert_equal 1, root_elements.size
852
- assert_equal [1], root_elements[0].nums
853
- assert_equal "bla", root_elements[0].text
854
- assert_problems([
855
- [/unexpected label 'text', expected \]/i, 2],
856
- ], problems)
857
- end
858
-
859
- def test_unclosed_bracket4
860
- root_elements = []
861
- env, problems = instantiate(%Q(
862
- TestNode nums: [1 "bla"
863
- ), TestMM, :root_elements => root_elements)
864
- assert_equal 1, root_elements.size
865
- assert_equal [1], root_elements[0].nums
866
- assert_nil root_elements[0].text
867
- assert_problems([
868
- [/unexpected string 'bla', expected ,/i, 2],
869
- [/argument 'nums' can not take a string, expected integer/i, 2],
870
- [/unexpected newline, expected \]/i, 2],
871
- ], problems)
872
- end
873
-
874
- def test_unclosed_bracket5
875
- root_elements = []
876
- env, problems = instantiate(%Q(
877
- TestNode [1, "bla"
878
- ), TestMM, :root_elements => root_elements)
879
- assert_equal 1, root_elements.size
880
- assert_equal [], root_elements[0].nums
881
- assert_nil root_elements[0].text
882
- assert_problems([
883
- [/unexpected newline, expected \]/i, 2],
884
- [/unexpected unlabled argument/i, 2],
885
- ], problems)
886
- end
887
-
888
- def test_unclosed_bracket6
889
- root_elements = []
890
- env, problems = instantiate(%Q(
891
- TestNode [1, "bla" [
892
- ), TestMM, :root_elements => root_elements)
893
- assert_equal 1, root_elements.size
894
- assert_problems([
895
- [/unexpected \[, expected \]/i, 2],
896
- [/unexpected end of file, expected \]/i, 2],
897
- [/unexpected unlabled argument/i, 2],
898
- [/unexpected unlabled argument/i, 2],
899
- ], problems)
900
- end
901
-
902
- def test_unclosed_bracket7
903
- root_elements = []
904
- env, problems = instantiate(%Q(
905
- TestNode [1, "bla", [
906
- ), TestMM, :root_elements => root_elements)
907
- assert_equal 1, root_elements.size
908
- assert_problems([
909
- [/unexpected \[, expected identifier/i, 2],
910
- [/unexpected unlabled argument/i, 2],
911
- [/unexpected unlabled argument/i, 2],
912
- [/unexpected end of file, expected \]/i, 2],
913
- ], problems)
914
- end
915
-
916
- def test_closing_bracket
917
- root_elements = []
918
- env, problems = instantiate(%Q(
919
- TestNode ]
920
- TestNode 1 ]
921
- TestNode 1, ]
922
- TestNode nums: ]1, "bla"
923
- TestNode text: "bla" ]
924
- ), TestMM, :root_elements => root_elements)
925
- assert_equal 5, root_elements.size
926
- assert_equal [], root_elements[3].nums
927
- assert_equal "bla", root_elements[4].text
928
- assert_problems([
929
- [/unexpected \], expected newline/i, 2],
930
- [/unexpected \], expected newline/i, 3],
931
- [/unexpected unlabled argument/i, 3],
932
- [/unexpected \], expected identifier/i, 4],
933
- [/unexpected unlabled argument/i, 4],
934
- [/unexpected \], expected identifier/i, 5],
935
- [/unexpected \], expected newline/i, 6],
936
- ], problems)
937
- end
938
-
939
- def test_closing_brace
940
- root_elements = []
941
- env, problems = instantiate(%Q(
942
- TestNode }
943
- TestNode 1 }
944
- TestNode 1, }
945
- TestNode nums: }1, "bla"
946
- TestNode text: "bla" }
947
- ), TestMM, :root_elements => root_elements)
948
- assert_equal 5, root_elements.size
949
- assert_equal [], root_elements[3].nums
950
- assert_equal "bla", root_elements[4].text
951
- assert_problems([
952
- [/unexpected \}, expected newline/i, 2],
953
- [/unexpected \}, expected newline/i, 3],
954
- [/unexpected unlabled argument/i, 3],
955
- [/unexpected \}, expected identifier/i, 4],
956
- [/unexpected unlabled argument/i, 4],
957
- [/unexpected \}, expected identifier/i, 5],
958
- [/unexpected \}, expected newline/i, 6],
959
- ], problems)
960
- end
961
-
962
- def test_starting_non_command
963
- root_elements = []
964
- env, problems = instantiate(%Q(
965
- \)
966
- TestNode
967
- *
968
- TestNode
969
- $
970
- TestNode
971
- ,
972
- TestNode
973
- [
974
- TestNode
975
- {
976
- TestNode
977
- ]
978
- TestNode
979
- }
980
- TestNode
981
- }}
982
- ), TestMM, :root_elements => root_elements)
983
- assert_equal 8, root_elements.size
984
- assert_problems([
985
- [/parse error on token '\)'/i, 2],
986
- [/parse error on token '\*'/i, 4],
987
- [/parse error on token '\$'/i, 6],
988
- [/unexpected ,, expected identifier/i, 8],
989
- [/unexpected \[, expected identifier/i, 10],
990
- [/unexpected \{, expected identifier/i, 12],
991
- [/unexpected \], expected identifier/i, 14],
992
- [/unexpected \}, expected identifier/i, 16],
993
- [/unexpected \}, expected identifier/i, 18],
994
- ], problems)
995
- end
996
-
997
- def test_parse_error_in_argument_list
998
- root_elements = []
999
- env, problems = instantiate(%Q(
1000
- TestNode text: "bla", * nums: 1
1001
- TestNode text: "bla" * , nums: 1
1002
- TestNode ?text: "bla"
1003
- TestNode nums: [1, * 3]
1004
- ), TestMM, :root_elements => root_elements)
1005
- assert_equal 4, root_elements.size
1006
- assert_equal "bla", root_elements[0].text
1007
- assert_equal [1], root_elements[0].nums
1008
- assert_equal "bla", root_elements[1].text
1009
- assert_equal [1], root_elements[1].nums
1010
- assert_equal "bla", root_elements[2].text
1011
- assert_equal [1, 3], root_elements[3].nums
1012
- assert_problems([
1013
- [/parse error on token '\*'/i, 2],
1014
- [/parse error on token '\*'/i, 3],
1015
- [/parse error on token '\?'/i, 4],
1016
- [/parse error on token '\*'/i, 5],
1017
- ], problems)
1018
- end
1019
-
1020
- def test_unclosed_brace
1021
- root_elements = []
1022
- env, problems = instantiate(%Q(
1023
- TestNode {
1024
- ), TestMM, :root_elements => root_elements)
1025
- assert_equal 1, root_elements.size
1026
- assert_problems([
1027
- [/unexpected end of file, expected \}/i, 2]
1028
- ], problems)
1029
- end
1030
-
1031
- def test_unclosed_brace2
1032
- root_elements = []
1033
- env, problems = instantiate(%Q(
1034
- TestNode {
1035
- *
1036
- ), TestMM, :root_elements => root_elements)
1037
- assert_equal 1, root_elements.size
1038
- assert_problems([
1039
- [/parse error on token '\*'/i, 3]
1040
- ], problems)
1041
- end
1042
-
1043
- def test_unclosed_brace3
1044
- root_elements = []
1045
- env, problems = instantiate(%Q(
1046
- TestNode {
1047
- childs:
1048
- ), TestMM, :root_elements => root_elements)
1049
- assert_equal 1, root_elements.size
1050
- assert_problems([
1051
- [/unexpected end of file, expected identifier/i, 3]
1052
- ], problems)
1053
- end
1054
-
1055
- def test_label_without_child
1056
- root_elements = []
1057
- env, problems = instantiate(%Q(
1058
- TestNode {
1059
- childs:
1060
- }
1061
- ), TestMM, :root_elements => root_elements)
1062
- assert_equal 1, root_elements.size
1063
- assert_problems([
1064
- [/unexpected \}, expected identifier/i, 4]
1065
- ], problems)
1066
- end
1067
-
1068
- def test_unclosed_child_bracket
1069
- root_elements = []
1070
- env, problems = instantiate(%Q(
1071
- TestNode {
1072
- childs: [
1073
- ), TestMM, :root_elements => root_elements)
1074
- assert_equal 1, root_elements.size
1075
- assert_problems([
1076
- [/unexpected end of file, expected \]/i, 3]
1077
- ], problems)
1078
- end
1079
-
1080
- def test_child_label_problems
1081
- root_elements = []
1082
- env, problems = instantiate(%Q(
1083
- TestNode {
1084
- childs: x
1085
- SubNode
1086
- childs: *
1087
- SubNode
1088
- childs: &
1089
- }
1090
- ), TestMM, :root_elements => root_elements)
1091
- assert_equal 1, root_elements.size
1092
- assert_equal 2, root_elements[0].childs.size
1093
- assert_problems([
1094
- [/unexpected identifier 'x', expected newline/i, 3],
1095
- [/parse error on token '\*'/i, 5],
1096
- [/parse error on token '&'/i, 7]
1097
- ], problems)
1098
- end
1099
-
1100
- def test_child_label_problems_with_bracket
1101
- root_elements = []
1102
- env, problems = instantiate(%Q(
1103
- TestNode {
1104
- childs: [ x
1105
- SubNode
1106
- ]
1107
- childs: [ *
1108
- SubNode
1109
- ]
1110
- childs: [&
1111
- ]
1112
- }
1113
- ), TestMM, :root_elements => root_elements)
1114
- assert_equal 1, root_elements.size
1115
- assert_equal 2, root_elements[0].childs.size
1116
- assert_problems([
1117
- [/unexpected identifier 'x', expected newline/i, 3],
1118
- [/parse error on token '\*'/i, 6],
1119
- [/parse error on token '&'/i, 9]
1120
- ], problems)
1121
- end
1122
-
1123
- def test_missing_closing_bracket
1124
- root_elements = []
1125
- env, problems = instantiate(%Q(
1126
- TestNode {
1127
- childs: [
1128
- SubNode
1129
- childs: [
1130
- SubNode
1131
- SubNode
1132
- }
1133
- ), TestMM, :root_elements => root_elements)
1134
- assert_equal 1, root_elements.size
1135
- assert_equal 3, root_elements[0].childs.size
1136
- assert_problems([
1137
- [/unexpected label 'childs', expected identifier/i, 5],
1138
- [/unexpected \}, expected identifier/i, 8],
1139
- ], problems)
1140
- end
1141
-
1142
- def test_missing_closing_brace
1143
- root_elements = []
1144
- env, problems = instantiate(%Q(
1145
- TestNode {
1146
- TestNode {
1147
- TestNode
1148
- }
1149
- ), TestMM, :root_elements => root_elements)
1150
- assert_equal 1, root_elements.size
1151
- assert_equal 1, root_elements[0].childs.size
1152
- assert_equal 1, root_elements[0].childs[0].childs.size
1153
- assert_problems([
1154
- [/unexpected end of file, expected \}/i, 5],
1155
- ], problems)
1156
- end
1157
-
1158
- #
1159
- # command name provider
1160
- #
1161
-
1162
- def test_command_name_provider
1163
- env, problems = instantiate(%Q(
1164
- TestNodeX text: "some text", nums: [1,2] {
1165
- TestNodeX text: "child"
1166
- TestNodeX text: "child2"
1167
- }
1168
- ), TestMM, :command_name_provider => proc do |c|
1169
- c.name + "X"
1170
- end)
1171
- assert_no_problems(problems)
1172
- assert_model_simple(env, :with_nums)
1173
- end
1174
-
1175
- def test_command_name_provider_ambiguous
1176
- begin
1177
- env, problems = instantiate(%Q(
1178
- TestNode
1179
- ), TestMM, :command_name_provider => proc do |c|
1180
- "Fixed"
1181
- end)
1182
- assert false
1183
- rescue RuntimeError => e
1184
- assert e.message =~ /ambiguous command name/
1185
- end
1186
- end
1187
-
1188
- #
1189
- # comment handler
1190
- #
1191
-
1192
- def test_comment_handler
1193
- proc_calls = 0
1194
- env, problems = instantiate(%Q(
1195
- #comment
1196
- TestNode text: "node1"
1197
- #comment
1198
- # multiline
1199
- TestNode text: "node2"
1200
- TestNode text: "node3" #comment
1201
- #above
1202
- TestNode text: "node4" {#right1
1203
- childs: [ #right2
1204
- #unassociated1
1205
- ] #right3
1206
- #unassociated2
1207
- } #below
1208
- #above1
1209
- #above2
1210
- TestNode text: "node5" { #right1
1211
- childs: #right2
1212
- TestNode
1213
- }#below
1214
- #comment without
1215
- #an element following
1216
- ), TestMM, :comment_handler => proc {|c,k,e,env|
1217
- proc_calls += 1
1218
- if e.nil?
1219
- case proc_calls
1220
- when 4
1221
- assert_equal "unassociated1", c
1222
- assert_equal :unassociated, k
1223
- when 5
1224
- assert_equal "unassociated2", c
1225
- assert_equal :unassociated, k
1226
- when 15
1227
- assert_equal "comment without\nan element following", c
1228
- assert_equal :unassociated, k
1229
- end
1230
- elsif e.text == "node1"
1231
- assert_equal "comment", c
1232
- assert_equal :above, k
1233
- elsif e.text == "node2"
1234
- assert_equal "comment\n multiline", c
1235
- assert_equal :above, k
1236
- elsif e.text == "node3"
1237
- assert_equal "comment", c
1238
- assert_equal :eol, k
1239
- elsif e.text == "node4"
1240
- case proc_calls
1241
- when 6
1242
- assert_equal "above", c
1243
- assert_equal :above, k
1244
- when 7
1245
- assert_equal "right1", c
1246
- assert_equal :eol, k
1247
- when 8
1248
- assert_equal "right2", c
1249
- assert_equal :eol, k
1250
- when 9
1251
- assert_equal "right3", c
1252
- assert_equal :eol, k
1253
- when 10
1254
- assert_equal "below", c
1255
- assert_equal :eol, k
1256
- end
1257
- elsif e.text == "node5"
1258
- case proc_calls
1259
- when 11
1260
- assert_equal "above1\nabove2", c
1261
- assert_equal :above, k
1262
- when 12
1263
- assert_equal "right1", c
1264
- assert_equal :eol, k
1265
- when 13
1266
- assert_equal "right2", c
1267
- assert_equal :eol, k
1268
- when 14
1269
- assert_equal "below", c
1270
- assert_equal :eol, k
1271
- end
1272
- else
1273
- assert false, "unexpected element in comment handler"
1274
- end
1275
- true
1276
- })
1277
- assert_no_problems(problems)
1278
- assert_equal 15, proc_calls
1279
- end
1280
-
1281
- def test_comment_handler_comment_not_allowed
1282
- env, problems = instantiate(%Q(
1283
- #comment
1284
- TestNode
1285
- ), TestMM, :comment_handler => proc {|c,k,e,env|
1286
- false
1287
- })
1288
- assert_problems([[/element can not take this comment/, 3]], problems)
1289
- end
1290
-
1291
- def test_comment_handler_comment_not_allowed_unassociated
1292
- env, problems = instantiate(%Q(
1293
- #comment
1294
- ), TestMM, :comment_handler => proc {|c,k,e,env|
1295
- false
1296
- })
1297
- assert_problems([[/Unassociated comment not allowed/, 2]], problems)
1298
- end
1299
-
1300
- #
1301
- # annotations
1302
- #
1303
-
1304
- def test_annotation_not_supported
1305
- env, problems = instantiate(%Q(
1306
- @annotation
1307
- TestNode
1308
- ), TestMM)
1309
- assert_problems([[/annotation not allowed/i, 3]], problems)
1310
- end
1311
-
1312
- def test_annotation_not_allowed
1313
- env, problems = instantiate(%Q(
1314
- @annotation
1315
- TestNode
1316
- ), TestMM, :annotation_handler => proc {|a,e,env|
1317
- false
1318
- })
1319
- assert_problems([[/annotation not allowed/i, 3]], problems)
1320
- end
1321
-
1322
- def test_annotation_in_wrong_places
1323
- env, problems = instantiate(%Q(
1324
- @annotation
1325
- #comment
1326
- TestNode {
1327
- @annotation
1328
- childs:
1329
- TestNode
1330
- @annotation
1331
- }
1332
- @annotation
1333
- ), TestMM)
1334
- assert_problems([
1335
- [/unexpected comment 'comment', expected identifier/i, 3],
1336
- [/unexpected label 'childs', expected identifier/i, 6],
1337
- [/unexpected \}, expected identifier/i, 9],
1338
- [/unexpected end of file, expected identifier/i, 10]
1339
- ], problems)
1340
- end
1341
-
1342
- def test_annotation_handler
1343
- annotations = []
1344
- elements = []
1345
- env, problems = instantiate(%Q(
1346
- @annotation
1347
- TestNode text: "aa"
1348
- @annotation
1349
- @ in a new line
1350
-
1351
- @ even with space in between
1352
-
1353
- TestNode text: "bb" {
1354
- @at child
1355
- TestNode text: "cc"
1356
- childs:
1357
- @after label
1358
- TestNode text: "dd"
1359
- @another child
1360
- TestNode text: "ee"
1361
- childs: [
1362
- @in brackets
1363
- TestNode text: "ff"
1364
- ]
1365
- }
1366
- ), TestMM, :annotation_handler => proc {|a,e,env|
1367
- annotations << a
1368
- elements << e
1369
- true
1370
- })
1371
- assert_equal "aa", elements[0].text
1372
- assert_equal "annotation", annotations[0]
1373
- assert_equal "cc", elements[1].text
1374
- assert_equal "at child", annotations[1]
1375
- assert_equal "dd", elements[2].text
1376
- assert_equal "after label", annotations[2]
1377
- assert_equal "ee", elements[3].text
1378
- assert_equal "another child", annotations[3]
1379
- assert_equal "ff", elements[4].text
1380
- assert_equal "in brackets", annotations[4]
1381
- assert_equal "bb", elements[5].text
1382
- assert_equal "annotation\n in a new line\n even with space in between", annotations[5]
1383
- assert_no_problems(problems)
1384
- end
1385
-
1386
- #
1387
- # generics
1388
- #
1389
-
1390
- def test_generics_parse_error
1391
- env, problems = instantiate(%Q(
1392
- TestNode text: <bla
1393
- TestNode text: bla>
1394
- TestNode text: <a<b>
1395
- TestNode text: <a>b>
1396
- TestNode text: <%a
1397
- TestNode text: <%a%
1398
- TestNode text: <%a%>b%>
1399
- ), TestMM, :enable_generics => true)
1400
- assert_problems([
1401
- [/parse error on token '<'/i, 2],
1402
- [/unexpected unlabled argument/i, 2],
1403
- [/parse error on token '>'/i, 3],
1404
- [/unexpected identifier 'b'/i, 5],
1405
- [/parse error on token '>'/i, 5],
1406
- [/unexpected unlabled argument/i, 5],
1407
- [/parse error on token '<'/i, 6],
1408
- [/unexpected unlabled argument/i, 6],
1409
- [/parse error on token '<'/i, 7],
1410
- [/unexpected unlabled argument/i, 7],
1411
- [/parse error on token '%'/i, 7],
1412
- [/unexpected identifier 'b'/i, 8],
1413
- [/unexpected unlabled argument/i, 8],
1414
- [/parse error on token '%'/i, 8],
1415
- ], problems)
1416
- end
1417
-
1418
- def test_generics
1419
- root_elements = []
1420
- env, problems = instantiate(%q(
1421
- TestNode text: <bla>, nums: [<1>, <%2%>], boolean: <truthy>, enum: <%option%>, float: <precise>, related: <%noderef%>, others: [<other1>, <%other2%>]
1422
- ), TestMM, :root_elements => root_elements, :enable_generics => true)
1423
- assert_no_problems(problems)
1424
- assert root_elements[0].text.is_a?(RText::Generic)
1425
- assert_equal "bla", root_elements[0].text.string
1426
- assert_equal ["1", "2"], root_elements[0].nums.collect{|n| n.string}
1427
- assert_equal "truthy", root_elements[0].boolean.string
1428
- assert_equal "option", root_elements[0].enum.string
1429
- assert_equal "precise", root_elements[0].float.string
1430
- assert_equal "noderef", root_elements[0].related.string
1431
- assert_equal ["other1", "other2"], root_elements[0].others.collect{|n| n.string}
1432
- end
1433
-
1434
- def test_generics_forbidden
1435
- env, problems = instantiate(%Q(\
1436
- TestNode text: <bla>
1437
- ), TestMM)
1438
- assert_problems([
1439
- [/generic value not allowed/i, 1],
1440
- ], problems)
1441
- end
1442
-
1443
- #
1444
- # subpackages
1445
- #
1446
-
1447
- def test_subpackage
1448
- env, problems = instantiate(%q(
1449
- TestNodeSub text: "something"
1450
- ), TestMMSubpackage)
1451
- assert_no_problems(problems)
1452
- assert_equal "something", env.elements.first.text
1453
- end
1454
-
1455
- #
1456
- # values
1457
- #
1458
-
1459
- def test_escapes
1460
- env, problems = instantiate(%q(
1461
- TestNode text: "some \" \\\\ \\\\\" text \r xx \n xx \r\n xx \t xx \b xx \f"
1462
- ), TestMM)
1463
- assert_no_problems(problems)
1464
- assert_equal %Q(some " \\ \\" text \r xx \n xx \r\n xx \t xx \b xx \f), env.elements.first.text
1465
- end
1466
-
1467
- def test_escape_single_backslash
1468
- env, problems = instantiate(%q(
1469
- TestNode text: "a single \\ will be just itself"
1470
- ), TestMM)
1471
- assert_no_problems(problems)
1472
- assert_equal %q(a single \\ will be just itself), env.elements.first.text
1473
- end
1474
-
1475
- def test_string_umlauts
1476
- env, problems = instantiate(%q(
1477
- TestNode text: "ä, ö, ü"
1478
- ), TestMM)
1479
- assert_no_problems(problems)
1480
- assert_equal %q(ä, ö, ü), env.elements.first.text
1481
- end
1482
-
1483
- def test_integer
1484
- env, problems = instantiate(%q(
1485
- TestNode integer: 7
1486
- TestNode integer: 4294967296
1487
- TestNode integer: 12345678901234567890
1488
- ), TestMM)
1489
- assert_no_problems(problems)
1490
- assert_equal 7, env.elements[0].integer
1491
- assert_equal 4294967296, env.elements[1].integer
1492
- assert_equal 12345678901234567890, env.elements[2].integer
1493
- end
1494
-
1495
- def test_integer_hex
1496
- env, problems = instantiate(%q(
1497
- TestNode text: root {
1498
- TestNode integer: 0x7
1499
- TestNode integer: 0X7
1500
- TestNode integer: 0x007
1501
- TestNode integer: 0x77
1502
- TestNode integer: 0xabCDEF
1503
- TestNode integer: 0xabcdefabcdefabcdef
1504
- }
1505
- ), TestMM)
1506
- assert_no_problems(problems)
1507
- assert_equal [7, 7, 7, 0x77, 0xABCDEF, 0xabcdefabcdefabcdef], env.find(:text => "root").first.childs.collect{|c| c.integer}
1508
- end
1509
-
1510
- def test_float
1511
- env, problems = instantiate(%q(
1512
- TestNode float: 1.23
1513
- TestNode float: 1.23e-08
1514
- TestNode float: 1.23e+10
1515
- TestNode float: 1234567890.123456789
1516
- ), TestMM)
1517
- assert_no_problems(problems)
1518
- assert_equal 1.23, env.elements[0].float
1519
- assert_equal 1.23e-08, env.elements[1].float
1520
- assert_equal 1.23e+10, env.elements[2].float
1521
- if rgen_with_bigdecimal?
1522
- assert env.elements[3].float.is_a?(BigDecimal)
1523
- assert_equal "1234567890.123456789", env.elements[3].float.to_s("F")
1524
- else
1525
- assert env.elements[3].float.is_a?(Float)
1526
- assert_equal "1234567890.1234567", env.elements[3].float.to_s
1527
- end
1528
- end
1529
-
1530
- def test_boolean
1531
- env, problems = instantiate(%q(
1532
- TestNode text: root {
1533
- TestNode boolean: true
1534
- TestNode boolean: false
1535
- }
1536
- ), TestMM)
1537
- assert_no_problems(problems)
1538
- assert_equal [true, false], env.find(:text => "root").first.childs.collect{|c| c.boolean}
1539
- end
1540
-
1541
- def test_enum
1542
- env, problems = instantiate(%q(
1543
- TestNode text: root {
1544
- TestNode enum: A
1545
- TestNode enum: B
1546
- TestNode enum: "non-word*chars"
1547
- TestNode enum: "2you"
1548
- }
1549
- ), TestMM)
1550
- assert_no_problems(problems)
1551
- assert_equal [:A, :B, :'non-word*chars', :'2you'], env.find(:text => "root").first.childs.collect{|c| c.enum}
1552
- end
1553
-
1554
- def test_with_bom
1555
- env, problems = instantiate(%Q(\xEF\xBB\xBF
1556
- TestNode text: "some text", nums: [1,2] {
1557
- TestNode text: "child"
1558
- TestNode text: "child2"
1559
- }
1560
- ), TestMM)
1561
- assert_no_problems(problems)
1562
- assert_model_simple(env, :with_nums)
1563
- end
1564
-
1565
- #
1566
- # conflicts with builtins
1567
- #
1568
-
1569
- def test_conflict_builtin
1570
- env, problems = instantiate(%q(
1571
- Data notTheBuiltin: "for sure"
1572
- ), TestMMData)
1573
- assert_no_problems(problems)
1574
- assert_equal "for sure", env.elements.first.notTheBuiltin
1575
- end
1576
-
1577
- def test_builtin_in_subpackage
1578
- env, problems = instantiate(%q(
1579
- Data notTheBuiltin: "for sure"
1580
- ), TestMMSubpackage)
1581
- assert_no_problems(problems)
1582
- assert_equal "for sure", env.elements.first.notTheBuiltin
1583
- end
1584
-
1585
- #
1586
- # encoding
1587
- #
1588
-
1589
- def test_encodings
1590
- input = %Q(TestNode text: "iso-8859-1 AE Umlaut: \xc4")
1591
- # force encoding to binary in order to prevent exceptions on invalid byte sequences
1592
- # if the encoding would be utf-8, there would be an exception with the string above
1593
- input.force_encoding("binary")
1594
- env, problems = instantiate(input, TestMM)
1595
- assert_no_problems(problems)
1596
- assert_match /AE Umlaut: /, env.elements.first.text
1597
- end
1598
-
1599
- #
1600
- # line breaks
1601
- #
1602
-
1603
- def test_linebreak
1604
- roots = []
1605
- env, problems = instantiate(%Q(
1606
- TestNode sometext,
1607
- integer: 1,
1608
- nums: [
1609
- 1,
1610
- 2
1611
- ]
1612
- ), TestMM, :root_elements => roots, :unlabled_arguments => proc {|clazz| ["text"]})
1613
- assert_no_problems(problems)
1614
- node = roots.first
1615
- assert_equal "sometext", node.text
1616
- assert_equal 1, node.integer
1617
- assert_equal [1,2], node.nums
1618
- end
1619
-
1620
- def test_linebreak_backslash
1621
- roots = []
1622
- env, problems = instantiate(%Q(
1623
- TestNode \\
1624
- sometext
1625
- ), TestMM, :root_elements => roots, :unlabled_arguments => proc {|clazz| ["text"]})
1626
- assert_no_problems(problems)
1627
- node = roots.first
1628
- assert_equal "sometext", node.text
1629
- end
1630
-
1631
- private
1632
-
1633
- def instantiate(text, mm, options={})
1634
- env = RGen::Environment.new
1635
- lang = RText::Language.new(mm.ecore, options.merge(
1636
- :root_classes => mm.ecore.eAllClasses.select{|c|
1637
- c.name == "TestNode" || c.name == "Data" || c.name == "TestNodeSub" || c.name == "SubNode"}))
1638
- inst = RText::Instantiator.new(lang)
1639
- problems = []
1640
- inst.instantiate(text, options.merge({:env => env, :problems => problems, :root_elements => options[:root_elements]}))
1641
- return env, problems
1642
- end
1643
-
1644
- def assert_no_problems(problems)
1645
- assert problems.empty?, problems.collect{|p| "#{p.message}, line: #{p.line}"}.join("\n")
1646
- end
1647
-
1648
- def assert_problems(expected, problems)
1649
- remaining = problems.dup
1650
- probs = []
1651
- expected.each do |e|
1652
- if e.is_a?(Array)
1653
- p = remaining.find{|p| p.message =~ e[0] && p.line == e[1]}
1654
- else
1655
- p = remaining.find{|p| p.message =~ e}
1656
- end
1657
- probs << "expected problem not present: #{e}" if !p
1658
- # make sure to not delete duplicate problems at once
1659
- idx = remaining.index(p)
1660
- remaining.delete_at(idx) if idx
1661
- end
1662
- remaining.each do |p|
1663
- probs << "unexpected problem: #{p.message}, line: #{p.line}"
1664
- end
1665
- assert probs.empty?, probs.join("\n")
1666
- end
1667
-
1668
- def assert_model_simple(env, *opts)
1669
- raise "unknown options" unless (opts - [:with_nums]).empty?
1670
- root = env.find(:class => TestMM::TestNode, :text => "some text").first
1671
- assert_not_nil root
1672
- assert_equal 2, root.childs.size
1673
- assert_equal [TestMM::TestNode, TestMM::TestNode], root.childs.collect{|c| c.class}
1674
- assert_equal ["child", "child2"], root.childs.text
1675
- if opts.include?(:with_nums)
1676
- assert_equal [1, 2], root.nums
1677
- end
1678
- end
1679
-
1680
- def rgen_with_bigdecimal?
1681
- begin
1682
- TestMM::TestNode.new.float = BigDecimal.new("0.0")
1683
- rescue StandardError
1684
- return false
1685
- end
1686
- true
1687
- end
1688
-
1689
- end
1690
-
1691
-
1
+ # coding: binary
2
+ $:.unshift File.join(File.dirname(__FILE__),"..","lib")
3
+
4
+ require 'minitest/autorun'
5
+ require 'bigdecimal'
6
+ require 'rgen/environment'
7
+ require 'rgen/metamodel_builder'
8
+ require 'rtext/instantiator'
9
+ require 'rtext/language'
10
+
11
+ class InstantiatorTest < MiniTest::Test
12
+
13
+ module TestMM
14
+ extend RGen::MetamodelBuilder::ModuleExtension
15
+ class TestNode < RGen::MetamodelBuilder::MMBase
16
+ SomeEnum = RGen::MetamodelBuilder::DataTypes::Enum.new([:A, :B, :'non-word*chars', :'2you'])
17
+ has_attr 'text', String
18
+ has_attr 'integer', Integer
19
+ has_attr 'boolean', Boolean
20
+ has_attr 'enum', SomeEnum
21
+ has_many_attr 'nums', Integer
22
+ has_attr 'float', Float
23
+ has_one 'related', TestNode
24
+ has_many 'others', TestNode
25
+ contains_many 'childs', TestNode, 'parent'
26
+ end
27
+ class SubNode < TestNode
28
+ end
29
+ end
30
+
31
+ module TestMM2
32
+ extend RGen::MetamodelBuilder::ModuleExtension
33
+ class TestNode < RGen::MetamodelBuilder::MMBase
34
+ contains_one 'singleChild', TestNode, 'parent'
35
+ end
36
+ class TestNode2 < RGen::MetamodelBuilder::MMBase
37
+ end
38
+ class TestNode3 < RGen::MetamodelBuilder::MMBase
39
+ end
40
+ class TestNode4 < TestNode
41
+ end
42
+ TestNode.contains_one 'singleChild2a', TestNode2, 'parentA'
43
+ TestNode.contains_one 'singleChild2b', TestNode2, 'parentB'
44
+ end
45
+
46
+ module TestMMLinenoFilenameFragment
47
+ extend RGen::MetamodelBuilder::ModuleExtension
48
+ class TestNode < RGen::MetamodelBuilder::MMBase
49
+ has_attr 'text', String
50
+ has_attr 'lineno', Integer
51
+ has_attr 'filename', String
52
+ has_attr 'fragmentr', String
53
+ contains_many 'childs', TestNode, 'parent'
54
+ end
55
+ end
56
+
57
+ module TestMMAbstract
58
+ extend RGen::MetamodelBuilder::ModuleExtension
59
+ class TestNode < RGen::MetamodelBuilder::MMBase
60
+ abstract
61
+ end
62
+ end
63
+
64
+ module TestMMData
65
+ extend RGen::MetamodelBuilder::ModuleExtension
66
+ # class "Data" exists in the standard Ruby namespace
67
+ class Data < RGen::MetamodelBuilder::MMBase
68
+ has_attr 'notTheBuiltin', String
69
+ end
70
+ end
71
+
72
+ module TestMMSubpackage
73
+ extend RGen::MetamodelBuilder::ModuleExtension
74
+ module SubPackage
75
+ extend RGen::MetamodelBuilder::ModuleExtension
76
+ class TestNodeSub < RGen::MetamodelBuilder::MMBase
77
+ has_attr 'text', String
78
+ end
79
+ class Data < RGen::MetamodelBuilder::MMBase
80
+ has_attr 'notTheBuiltin', String
81
+ end
82
+ end
83
+ end
84
+
85
+ module TestMMNonRootClass
86
+ extend RGen::MetamodelBuilder::ModuleExtension
87
+ class NonRootClass < RGen::MetamodelBuilder::MMBase
88
+ end
89
+ end
90
+
91
+ module TestMMContextSensitiveCommands
92
+ extend RGen::MetamodelBuilder::ModuleExtension
93
+ module SubPackage2
94
+ extend RGen::MetamodelBuilder::ModuleExtension
95
+ class Command < RGen::MetamodelBuilder::MMBase
96
+ end
97
+ end
98
+ module SubPackage1
99
+ extend RGen::MetamodelBuilder::ModuleExtension
100
+ class Command < RGen::MetamodelBuilder::MMBase
101
+ contains_one 'command', SubPackage2::Command, 'super'
102
+ end
103
+ end
104
+ class TestNode < RGen::MetamodelBuilder::MMBase
105
+ contains_one 'command', SubPackage1::Command, 'testNode'
106
+ end
107
+ end
108
+
109
+ def test_simple
110
+ env, problems = instantiate(%Q(
111
+ TestNode text: "some text", nums: [1,2] {
112
+ TestNode text: "child"
113
+ TestNode text: "child2"
114
+ }
115
+ ), TestMM)
116
+ assert_no_problems(problems)
117
+ assert_model_simple(env, :with_nums)
118
+ end
119
+
120
+ def test_multiple_roots
121
+ env, problems = instantiate(%Q(
122
+ TestNode
123
+ TestNode
124
+ ), TestMM)
125
+ assert_no_problems(problems)
126
+ assert_equal 2, env.elements.size
127
+ end
128
+
129
+ def test_comment
130
+ env, problems = instantiate(%Q(
131
+ # comment 1
132
+ TestNode text: "some text" {# comment 1.1
133
+ childs: [ # comment 1.2
134
+ # comment 2
135
+ TestNode text: "child" # comment 2.1
136
+ # comment 3
137
+ TestNode text: "child2" #comment 3.1
138
+ # unassociated
139
+ ] # comment 1.3
140
+ # unassociated
141
+ } # comment 1.4
142
+ #comment 1
143
+ TestNode { #comment 1.1
144
+ childs: # comment 1.2
145
+ TestNode text: "child" #comment2
146
+ # unassociated
147
+ }# comment 1.3
148
+ # unassociated
149
+ ), TestMM)
150
+ assert_no_problems(problems)
151
+ assert_model_simple(env)
152
+ end
153
+
154
+ def test_comment_only
155
+ env, problems = instantiate(%Q(
156
+ # comment 1
157
+ ), TestMM)
158
+ assert_no_problems(problems)
159
+ end
160
+
161
+ def test_empty
162
+ env, problems = instantiate("", TestMM)
163
+ assert_no_problems(problems)
164
+ end
165
+
166
+ #
167
+ # options
168
+ #
169
+
170
+ def test_line_number_setter
171
+ env, problems = instantiate(%q(
172
+ TestNode text: "node1" {
173
+ TestNode text: "node2"
174
+
175
+ #some comment
176
+ TestNode text: "node3"
177
+ }
178
+ TestNode text: "node4"
179
+ ), TestMMLinenoFilenameFragment, :line_number_attribute => "lineno")
180
+ assert_no_problems(problems)
181
+ assert_equal 2, env.find(:text => "node1").first.lineno
182
+ assert_equal 3, env.find(:text => "node2").first.lineno
183
+ assert_equal 6, env.find(:text => "node3").first.lineno
184
+ assert_equal 8, env.find(:text => "node4").first.lineno
185
+ end
186
+
187
+ def test_missing_line_number_setter
188
+ env, problems = instantiate(%Q(
189
+ TestNode text: A
190
+ ), TestMMLinenoFilenameFragment, :line_number_attribute => "wrong_attribute_name")
191
+ assert_no_problems(problems)
192
+ assert_nil env.elements.first.lineno
193
+ end
194
+
195
+ def test_root_elements
196
+ root_elements = []
197
+ env, problems = instantiate(%Q(
198
+ TestNode text: A
199
+ TestNode text: B
200
+ TestNode text: C
201
+ ), TestMM, :root_elements => root_elements)
202
+ assert_no_problems(problems)
203
+ assert_equal ["A", "B", "C"], root_elements.text
204
+ end
205
+
206
+ def test_file_name_option
207
+ env, problems = instantiate(%Q(
208
+ TestNode text: A
209
+ TestNode text: B
210
+ TestNode a problem here
211
+ ), TestMM, :file_name => "some_file")
212
+ assert_equal "some_file", problems.first.file
213
+ end
214
+
215
+ def test_file_name_setter
216
+ env, problems = instantiate(%Q(
217
+ TestNode text: A
218
+ ), TestMMLinenoFilenameFragment, :file_name => "some_file", :file_name_attribute => "filename")
219
+ assert_equal "some_file", env.elements.first.filename
220
+ end
221
+
222
+ def test_missing_file_name_setter
223
+ env, problems = instantiate(%Q(
224
+ TestNode text: A
225
+ ), TestMMLinenoFilenameFragment, :file_name => "some_file", :file_name_attribute => "wrong_attribute_name")
226
+ assert_nil env.elements.first.filename
227
+ end
228
+
229
+ def test_fragment_ref_setter
230
+ the_ref = "is a string here but would normally be an RGen fragment"
231
+ env, problems = instantiate(%Q(
232
+ TestNode text: A
233
+ ), TestMMLinenoFilenameFragment, :fragment_ref => the_ref, :fragment_ref_attribute => "fragmentr")
234
+ assert_equal the_ref.object_id, env.elements.first.fragmentr.object_id
235
+ end
236
+
237
+ def test_missing_fragment_ref_setter
238
+ the_ref = "is a string here but would normally be an RGen fragment"
239
+ env, problems = instantiate(%Q(
240
+ TestNode text: A
241
+ ), TestMMLinenoFilenameFragment, :fragment_ref => the_ref, :fragment_ref_attribute => "wrong_attribute_name")
242
+ assert_nil env.elements.first.fragmentr
243
+ end
244
+
245
+ #
246
+ # children with role
247
+ #
248
+
249
+ def test_child_role
250
+ env, problems = instantiate(%Q(
251
+ TestNode text: "some text" {
252
+ TestNode text: "child"
253
+ childs:
254
+ TestNode text: "child2"
255
+ }
256
+ ), TestMM)
257
+ assert_no_problems(problems)
258
+ assert_model_simple(env)
259
+ end
260
+
261
+ def test_child_role2
262
+ env, problems = instantiate(%Q(
263
+ TestNode text: "some text" {
264
+ childs: [
265
+ TestNode text: "child"
266
+ TestNode text: "child2"
267
+ ]
268
+ }
269
+ ), TestMM)
270
+ assert_no_problems(problems)
271
+ assert_model_simple(env)
272
+ end
273
+
274
+ def test_child_role3
275
+ env, problems = instantiate(%Q(
276
+ TestNode text: "some text" {
277
+ childs:
278
+ TestNode text: "child"
279
+ childs:
280
+ TestNode text: "child2"
281
+ }
282
+ ), TestMM)
283
+ assert_no_problems(problems)
284
+ assert_model_simple(env)
285
+ end
286
+
287
+ def test_child_role4
288
+ env, problems = instantiate(%Q(
289
+ TestNode text: "some text" {
290
+ childs: [
291
+ TestNode text: "child"
292
+ ]
293
+ childs: [
294
+ TestNode text: "child2"
295
+ ]
296
+ }
297
+ ), TestMM)
298
+ assert_no_problems(problems)
299
+ assert_model_simple(env)
300
+ end
301
+
302
+ def test_child_role_empty
303
+ env, problems = instantiate(%Q(
304
+ TestNode {
305
+ childs: [
306
+ ]
307
+ }
308
+ ), TestMM)
309
+ assert_no_problems(problems)
310
+ end
311
+
312
+
313
+ #
314
+ # whitespace
315
+ #
316
+
317
+ def test_whitespace1
318
+ env, problems = instantiate(%Q(
319
+ TestNode text: "some text" , nums: [ 1 , 2 ] {
320
+
321
+ # comment
322
+
323
+ TestNode text: "child"
324
+
325
+ TestNode text: "child2"
326
+
327
+ }
328
+ ), TestMM)
329
+ assert_no_problems(problems)
330
+ assert_model_simple(env, :with_nums)
331
+ end
332
+
333
+ def test_whitespace2
334
+ env, problems = instantiate(%Q(
335
+ # comment1
336
+
337
+ # comment2
338
+
339
+ TestNode text: "some text" {
340
+
341
+ childs:
342
+
343
+ # comment
344
+
345
+ TestNode text: "child"
346
+
347
+ childs: [
348
+
349
+ TestNode text: "child2"
350
+
351
+ ]
352
+
353
+ }
354
+ ), TestMM)
355
+ assert_no_problems(problems)
356
+ assert_model_simple(env)
357
+ end
358
+
359
+ def test_no_newline_at_eof
360
+ env, problems = instantiate(%Q(
361
+ TestNode), TestMM)
362
+ assert_no_problems(problems)
363
+ end
364
+
365
+ def test_no_newline_at_eof2
366
+ env, problems = instantiate(%Q(
367
+ TestNode {
368
+ }), TestMM)
369
+ assert_no_problems(problems)
370
+ end
371
+
372
+ #
373
+ # references
374
+ #
375
+
376
+ def test_references
377
+ unresolved_refs = []
378
+ env, problems = instantiate(%Q(
379
+ TestNode text: "root" {
380
+ TestNode related: /
381
+ TestNode related: //
382
+ TestNode related: /some
383
+ TestNode related: //some
384
+ TestNode related: /some/
385
+ TestNode related: some/
386
+ TestNode related: some//
387
+ TestNode related: some
388
+ TestNode related: /some/reference
389
+ TestNode related: /some/reference/
390
+ TestNode related: some/reference/
391
+ TestNode related: some/reference
392
+ }
393
+ ), TestMM, :unresolved_refs => unresolved_refs)
394
+ assert_no_problems(problems)
395
+ ref_targets = [
396
+ "/",
397
+ "//",
398
+ "/some",
399
+ "//some",
400
+ "/some/",
401
+ "some/",
402
+ "some//",
403
+ "some",
404
+ "/some/reference",
405
+ "/some/reference/",
406
+ "some/reference/",
407
+ "some/reference"
408
+ ]
409
+ assert_equal ref_targets, env.find(:text => "root").first.childs.collect{|c| c.related.targetIdentifier}
410
+ assert_equal ref_targets, unresolved_refs.collect{|ur| ur.proxy.targetIdentifier}
411
+ assert unresolved_refs.all?{|ur| ur.feature_name == "related"}
412
+ end
413
+
414
+ def test_references_many
415
+ env, problems = instantiate(%Q(
416
+ TestNode text: "root" {
417
+ TestNode others: /other
418
+ TestNode others: [ /other ]
419
+ TestNode others: [ /other1, /other2 ]
420
+ }
421
+ ), TestMM)
422
+ assert_no_problems(problems)
423
+ assert_equal [
424
+ [ "/other" ],
425
+ [ "/other" ],
426
+ [ "/other1", "/other2" ],
427
+ ], env.find(:text => "root").first.childs.collect{|c| c.others.collect{|p| p.targetIdentifier}}
428
+ end
429
+
430
+ def test_reference_regexp
431
+ env, problems = instantiate(%Q(
432
+ TestNode text: "root" {
433
+ TestNode related: some
434
+ TestNode related: ::some
435
+ TestNode related: some::reference
436
+ TestNode related: ::some::reference
437
+ }
438
+ ), TestMM, :reference_regexp => /\A\w*(::\w*)+/)
439
+ assert_no_problems(problems)
440
+ assert_equal [
441
+ "some",
442
+ "::some",
443
+ "some::reference",
444
+ "::some::reference"
445
+ ], env.find(:text => "root").first.childs.collect{|c| c.related.targetIdentifier}
446
+ end
447
+
448
+ #
449
+ # unlabled arguments
450
+ #
451
+
452
+ def test_unlabled_arguments
453
+ env, problems = instantiate(%Q(
454
+ TestNode "some text", [1,2] {
455
+ TestNode "child"
456
+ TestNode "child2"
457
+ }
458
+ ), TestMM, :unlabled_arguments => proc {|clazz| ["text", "nums"]})
459
+ assert_no_problems(problems)
460
+ assert_model_simple(env, :with_nums)
461
+ end
462
+
463
+ def test_unlabled_arguments_not_in_front
464
+ env, problems = instantiate(%Q(
465
+ TestNode nums: [1,2], "some text" {
466
+ TestNode "child"
467
+ TestNode "child2"
468
+ }
469
+ ), TestMM, :unlabled_arguments => proc {|clazz| ["text", "nums"]})
470
+ assert_no_problems(problems)
471
+ assert_model_simple(env, :with_nums)
472
+ end
473
+
474
+ def test_unlabled_arguments_using_labled
475
+ env, problems = instantiate(%Q(
476
+ TestNode text: "some text", nums: [1,2] {
477
+ TestNode text: "child"
478
+ TestNode text: "child2"
479
+ }
480
+ ), TestMM, :unlabled_arguments => proc {|clazz| ["text", "nums"]})
481
+ assert_no_problems(problems)
482
+ assert_model_simple(env, :with_nums)
483
+ end
484
+
485
+ def test_unlabled_arguments_subclass
486
+ env, problems = instantiate(%Q(
487
+ SubNode "some text", [1, 2] {
488
+ TestNode text: "child"
489
+ TestNode text: "child2"
490
+ }
491
+ ), TestMM, :unlabled_arguments => proc {|clazz| ["text", "nums"]})
492
+ assert_no_problems(problems)
493
+ assert_model_simple(env, :with_nums)
494
+ end
495
+
496
+ #
497
+ # context sensitive commands
498
+ #
499
+
500
+ def test_context_sensitive
501
+ env, problems = instantiate(%Q(
502
+ TestNode {
503
+ Command {
504
+ Command
505
+ }
506
+ }
507
+ ), TestMMContextSensitiveCommands)
508
+ assert_no_problems(problems)
509
+ root = env.find(:class => TestMMContextSensitiveCommands::TestNode).first
510
+ assert root != nil
511
+ assert(root.command.is_a?(TestMMContextSensitiveCommands::SubPackage1::Command))
512
+ assert(root.command.command.is_a?(TestMMContextSensitiveCommands::SubPackage2::Command))
513
+ end
514
+
515
+ def test_context_sensitive_command_name_mapping
516
+ env, problems = instantiate(%Q(
517
+ Command {
518
+ Command {
519
+ Command
520
+ }
521
+ }
522
+ ), TestMMContextSensitiveCommands, :command_name_provider => lambda do |c|
523
+ "Command" end)
524
+ assert_no_problems(problems)
525
+ root = env.find(:class => TestMMContextSensitiveCommands::TestNode).first
526
+ assert root != nil
527
+ assert(root.command.is_a?(TestMMContextSensitiveCommands::SubPackage1::Command))
528
+ assert(root.command.command.is_a?(TestMMContextSensitiveCommands::SubPackage2::Command))
529
+ end
530
+
531
+ #
532
+ # problems
533
+ #
534
+
535
+ def test_unexpected_end_of_file
536
+ env, problems = instantiate(%Q(
537
+ TestNode text: "some text" {
538
+ ), TestMM)
539
+ assert_problems([[/unexpected end of file, expected \}/i, 2]], problems)
540
+ end
541
+
542
+ def test_unknown_command
543
+ env, problems = instantiate(%Q(
544
+ NotDefined
545
+ ), TestMM)
546
+ assert_problems([[/unknown command 'NotDefined'/i, 2]], problems)
547
+ end
548
+
549
+ def test_unknown_command_abstract
550
+ env, problems = instantiate(%Q(
551
+ TestNode
552
+ ), TestMMAbstract)
553
+ assert_problems([[/unknown command 'TestNode'/i, 2]], problems)
554
+ end
555
+
556
+ def test_unexpected_unlabled_argument
557
+ env, problems = instantiate(%Q(
558
+ TestNode "more text"
559
+ ), TestMM)
560
+ assert_problems([[/unexpected unlabled argument, 0 unlabled arguments expected/i, 2]], problems)
561
+ end
562
+
563
+ def test_unknown_child_role
564
+ env, problems = instantiate(%Q(
565
+ TestNode {
566
+ notdefined:
567
+ TestNode
568
+ }
569
+ ), TestMM)
570
+ assert_problems([[/unknown child role 'notdefined'/i, 3]], problems)
571
+ end
572
+
573
+ def test_not_a_child_role
574
+ env, problems = instantiate(%Q(
575
+ TestNode {
576
+ text:
577
+ TestNode
578
+ others:
579
+ TestNode
580
+ }
581
+ ), TestMM)
582
+ assert_problems([
583
+ [/role 'text' can not take child elements/i, 3],
584
+ [/role 'others' can not take child elements/i, 5]
585
+ ], problems)
586
+ end
587
+
588
+ def test_not_a_single_child
589
+ env, problems = instantiate(%Q(
590
+ TestNode {
591
+ singleChild: [
592
+ TestNode
593
+ TestNode
594
+ ]
595
+ }
596
+ ), TestMM2)
597
+ assert_problems([
598
+ [/only one child allowed in role 'singleChild'/i, 5]
599
+ ], problems)
600
+ end
601
+
602
+ def test_not_a_single_child2
603
+ env, problems = instantiate(%Q(
604
+ TestNode {
605
+ singleChild:
606
+ TestNode
607
+ singleChild: [
608
+ ]
609
+ singleChild:
610
+ TestNode
611
+ }
612
+ ), TestMM2)
613
+ assert_problems([
614
+ [/only one child allowed in role 'singleChild'/i, 8]
615
+ ], problems)
616
+ end
617
+
618
+ def test_wrong_child_role
619
+ env, problems = instantiate(%Q(
620
+ TestNode {
621
+ singleChild:
622
+ TestNode2
623
+ }
624
+ ), TestMM2)
625
+ assert_problems([
626
+ [/role 'singleChild' can not take a TestNode2, expected TestNode/i, 4]
627
+ ], problems)
628
+ end
629
+
630
+ def test_child_role_without_child
631
+ env, problems = instantiate(%Q(
632
+ TestNode {
633
+ singleChild:
634
+ }
635
+ ), TestMM2)
636
+ assert_problems([
637
+ [/unexpected \}, expected identifier/i, 4]
638
+ ], problems)
639
+ end
640
+
641
+ def test_wrong_child
642
+ env, problems = instantiate(%Q(
643
+ TestNode {
644
+ TestNode3
645
+ }
646
+ ), TestMM2)
647
+ assert_problems([
648
+ [/command 'TestNode3' can not be used in this context/i, 3]
649
+ ], problems)
650
+ end
651
+
652
+ def test_ambiguous_child_role
653
+ env, problems = instantiate(%Q(
654
+ TestNode {
655
+ TestNode2
656
+ }
657
+ ), TestMM2)
658
+ assert_problems([
659
+ [/role of element is ambiguous, use a role label/i, 3]
660
+ ], problems)
661
+ end
662
+
663
+ def test_non_ambiguous_child_role_subclass
664
+ env, problems = instantiate(%Q(
665
+ TestNode {
666
+ TestNode4
667
+ }
668
+ ), TestMM2)
669
+ assert_no_problems(problems)
670
+ end
671
+
672
+ def test_not_a_single_child3
673
+ env, problems = instantiate(%Q(
674
+ TestNode {
675
+ TestNode
676
+ TestNode
677
+ }
678
+ ), TestMM2)
679
+ assert_problems([
680
+ [/only one child allowed in role 'singleChild'/i, 4]
681
+ ], problems)
682
+ end
683
+
684
+ def test_unknown_argument
685
+ env, problems = instantiate(%Q(
686
+ TestNode unknown: "some text"
687
+ ), TestMM)
688
+ assert_problems([[/unknown argument 'unknown'/i, 2]], problems)
689
+ end
690
+
691
+ def test_attribute_in_child_reference
692
+ env, problems = instantiate(%Q(
693
+ TestNode singleChild: "some text"
694
+ ), TestMM2)
695
+ assert_problems([[/argument 'singleChild' can only take child elements/i, 2]], problems)
696
+ end
697
+
698
+ def test_arguments_duplicate
699
+ env, problems = instantiate(%Q(
700
+ TestNode text: "some text", text: "more text"
701
+ ), TestMM)
702
+ assert_problems([[/argument 'text' already defined/i, 2]], problems)
703
+ end
704
+
705
+ def test_unlabled_arguments_duplicate
706
+ env, problems = instantiate(%Q(
707
+ TestNode text: "some text", "more text"
708
+ ), TestMM, :unlabled_arguments => proc {|c| ["text"]})
709
+ assert_problems([[/argument 'text' already defined/i, 2]], problems)
710
+ end
711
+
712
+ def test_multiple_arguments_in_non_many_attribute
713
+ env, problems = instantiate(%Q(
714
+ TestNode text: ["text1", "text2"]
715
+ ), TestMM)
716
+ assert_problems([[/argument 'text' can take only one value/i, 2]], problems)
717
+ end
718
+
719
+ def test_wrong_argument_type
720
+ env, problems = instantiate(%Q(
721
+ TestNode text: 1
722
+ TestNode integer: "text"
723
+ TestNode integer: true
724
+ TestNode integer: 1.2
725
+ TestNode integer: a
726
+ TestNode integer: /a
727
+ TestNode enum: 1
728
+ TestNode enum: x
729
+ TestNode related: 1
730
+ ), TestMM)
731
+ assert_problems([
732
+ [/argument 'text' can not take a integer, expected string/i, 2],
733
+ [/argument 'integer' can not take a string, expected integer/i, 3],
734
+ [/argument 'integer' can not take a boolean, expected integer/i, 4],
735
+ [/argument 'integer' can not take a float, expected integer/i, 5],
736
+ [/argument 'integer' can not take a identifier, expected integer/i, 6],
737
+ [/argument 'integer' can not take a reference, expected integer/i, 7],
738
+ [/argument 'enum' can not take a integer, expected identifier/i, 8],
739
+ [/argument 'enum' can not take value x, expected A, B/i, 9],
740
+ [/argument 'related' can not take a integer, expected reference, identifier/i, 10]
741
+ ], problems)
742
+ end
743
+
744
+ def test_missing_opening_brace
745
+ env, problems = instantiate(%Q(
746
+ TestNode
747
+ }
748
+ ), TestMM)
749
+ assert_problems([[/unexpected \}, expected identifier/i, 3]], problems)
750
+ end
751
+
752
+ def test_invalid_root
753
+ env, problems = instantiate(%Q(
754
+ NonRootClass
755
+ ), TestMMNonRootClass)
756
+ assert_problems([[/command 'NonRootClass' can not be used on root level/i, 2]], problems)
757
+ end
758
+
759
+ def test_invalid_root_label
760
+ root_elements = []
761
+ env, problems = instantiate(%Q(
762
+ TestNode text : A
763
+ ), TestMM, :root_elements => root_elements)
764
+ assert_problems([
765
+ [/Unexpected unlabled argument, 0 unlabled arguments expected/i, 2],
766
+ [/Unexpected :, expected newline/i, 2]
767
+ ], problems)
768
+ end
769
+
770
+ #
771
+ # problem recovery
772
+ #
773
+
774
+ def test_missing_value
775
+ root_elements = []
776
+ env, problems = instantiate(%Q(
777
+ TestNode nums: 1, text:
778
+ TestNode nums: 2, text: {
779
+ SubNode
780
+ }
781
+ TestNode text: ,nums: 3 {
782
+ SubNode
783
+ }
784
+ TestNode nums: , text: , bla:
785
+ ), TestMM, :root_elements => root_elements)
786
+ assert_equal 4, root_elements.size
787
+ assert_equal [1], root_elements[0].nums
788
+ assert_nil root_elements[0].text
789
+ assert_equal [2], root_elements[1].nums
790
+ assert_equal 1, root_elements[1].childs.size
791
+ assert_equal [3], root_elements[2].nums
792
+ assert_equal 1, root_elements[2].childs.size
793
+ assert_problems([
794
+ [/unexpected newline, expected.*integer/i, 2],
795
+ [/unexpected \{, expected.*integer/i, 3],
796
+ [/unexpected ,, expected.*integer/i, 6],
797
+ [/unexpected ,, expected.*integer/i, 9],
798
+ [/unexpected ,, expected.*integer/i, 9],
799
+ [/unexpected newline, expected.*integer/i, 9],
800
+ [/unknown argument 'bla'/i, 9],
801
+ ], problems)
802
+ end
803
+
804
+ def test_missing_comma
805
+ root_elements = []
806
+ env, problems = instantiate(%Q(
807
+ TestNode nums: 1 text: "bla"
808
+ ), TestMM, :root_elements => root_elements)
809
+ assert_equal 1, root_elements.size
810
+ assert_equal [1], root_elements[0].nums
811
+ assert_equal "bla", root_elements[0].text
812
+ assert_problems([
813
+ [/unexpected label .*, expected ,/i, 2],
814
+ ], problems)
815
+ end
816
+
817
+ def test_missing_label
818
+ root_elements = []
819
+ env, problems = instantiate(%Q(
820
+ TestNode nums: 1 "bla"
821
+ ), TestMM, :root_elements => root_elements)
822
+ assert_equal 1, root_elements.size
823
+ assert_equal [1], root_elements[0].nums
824
+ assert_problems([
825
+ [/unexpected string 'bla', expected ,/i, 2],
826
+ [/unexpected unlabled argument/i, 2]
827
+ ], problems)
828
+ end
829
+
830
+ def test_unclosed_bracket1
831
+ root_elements = []
832
+ env, problems = instantiate(%Q(
833
+ TestNode nums: [1, "bla"
834
+ ), TestMM, :root_elements => root_elements)
835
+ assert_equal 1, root_elements.size
836
+ assert_equal [1], root_elements[0].nums
837
+ assert_nil root_elements[0].text
838
+ assert_problems([
839
+ [/unexpected newline, expected \]/i, 2],
840
+ [/argument 'nums' can not take a string, expected integer/i, 2],
841
+ ], problems)
842
+ end
843
+
844
+ def test_unclosed_bracket2
845
+ root_elements = []
846
+ env, problems = instantiate(%Q(
847
+ TestNode nums: [1, text: "bla"
848
+ ), TestMM, :root_elements => root_elements)
849
+ assert_equal 1, root_elements.size
850
+ assert_equal [1], root_elements[0].nums
851
+ assert_equal "bla", root_elements[0].text
852
+ assert_problems([
853
+ [/unexpected label 'text', expected identifier/i, 2],
854
+ ], problems)
855
+ end
856
+
857
+ def test_unclosed_bracket3
858
+ root_elements = []
859
+ env, problems = instantiate(%Q(
860
+ TestNode nums: [1 text: "bla"
861
+ ), TestMM, :root_elements => root_elements)
862
+ assert_equal 1, root_elements.size
863
+ assert_equal [1], root_elements[0].nums
864
+ assert_equal "bla", root_elements[0].text
865
+ assert_problems([
866
+ [/unexpected label 'text', expected \]/i, 2],
867
+ ], problems)
868
+ end
869
+
870
+ def test_unclosed_bracket4
871
+ root_elements = []
872
+ env, problems = instantiate(%Q(
873
+ TestNode nums: [1 "bla"
874
+ ), TestMM, :root_elements => root_elements)
875
+ assert_equal 1, root_elements.size
876
+ assert_equal [1], root_elements[0].nums
877
+ assert_nil root_elements[0].text
878
+ assert_problems([
879
+ [/unexpected string 'bla', expected ,/i, 2],
880
+ [/argument 'nums' can not take a string, expected integer/i, 2],
881
+ [/unexpected newline, expected \]/i, 2],
882
+ ], problems)
883
+ end
884
+
885
+ def test_unclosed_bracket5
886
+ root_elements = []
887
+ env, problems = instantiate(%Q(
888
+ TestNode [1, "bla"
889
+ ), TestMM, :root_elements => root_elements)
890
+ assert_equal 1, root_elements.size
891
+ assert_equal [], root_elements[0].nums
892
+ assert_nil root_elements[0].text
893
+ assert_problems([
894
+ [/unexpected newline, expected \]/i, 2],
895
+ [/unexpected unlabled argument/i, 2],
896
+ ], problems)
897
+ end
898
+
899
+ def test_unclosed_bracket6
900
+ root_elements = []
901
+ env, problems = instantiate(%Q(
902
+ TestNode [1, "bla" [
903
+ ), TestMM, :root_elements => root_elements)
904
+ assert_equal 1, root_elements.size
905
+ assert_problems([
906
+ [/unexpected \[, expected \]/i, 2],
907
+ [/unexpected end of file, expected \]/i, 2],
908
+ [/unexpected unlabled argument/i, 2],
909
+ [/unexpected unlabled argument/i, 2],
910
+ ], problems)
911
+ end
912
+
913
+ def test_unclosed_bracket7
914
+ root_elements = []
915
+ env, problems = instantiate(%Q(
916
+ TestNode [1, "bla", [
917
+ ), TestMM, :root_elements => root_elements)
918
+ assert_equal 1, root_elements.size
919
+ assert_problems([
920
+ [/unexpected \[, expected identifier/i, 2],
921
+ [/unexpected unlabled argument/i, 2],
922
+ [/unexpected unlabled argument/i, 2],
923
+ [/unexpected end of file, expected \]/i, 2],
924
+ ], problems)
925
+ end
926
+
927
+ def test_closing_bracket
928
+ root_elements = []
929
+ env, problems = instantiate(%Q(
930
+ TestNode ]
931
+ TestNode 1 ]
932
+ TestNode 1, ]
933
+ TestNode nums: ]1, "bla"
934
+ TestNode text: "bla" ]
935
+ ), TestMM, :root_elements => root_elements)
936
+ assert_equal 5, root_elements.size
937
+ assert_equal [], root_elements[3].nums
938
+ assert_equal "bla", root_elements[4].text
939
+ assert_problems([
940
+ [/unexpected \], expected newline/i, 2],
941
+ [/unexpected \], expected newline/i, 3],
942
+ [/unexpected unlabled argument/i, 3],
943
+ [/unexpected \], expected identifier/i, 4],
944
+ [/unexpected unlabled argument/i, 4],
945
+ [/unexpected \], expected identifier/i, 5],
946
+ [/unexpected \], expected newline/i, 6],
947
+ ], problems)
948
+ end
949
+
950
+ def test_closing_brace
951
+ root_elements = []
952
+ env, problems = instantiate(%Q(
953
+ TestNode }
954
+ TestNode 1 }
955
+ TestNode 1, }
956
+ TestNode nums: }1, "bla"
957
+ TestNode text: "bla" }
958
+ ), TestMM, :root_elements => root_elements)
959
+ assert_equal 5, root_elements.size
960
+ assert_equal [], root_elements[3].nums
961
+ assert_equal "bla", root_elements[4].text
962
+ assert_problems([
963
+ [/unexpected \}, expected newline/i, 2],
964
+ [/unexpected \}, expected newline/i, 3],
965
+ [/unexpected unlabled argument/i, 3],
966
+ [/unexpected \}, expected identifier/i, 4],
967
+ [/unexpected unlabled argument/i, 4],
968
+ [/unexpected \}, expected identifier/i, 5],
969
+ [/unexpected \}, expected newline/i, 6],
970
+ ], problems)
971
+ end
972
+
973
+ def test_starting_non_command
974
+ root_elements = []
975
+ env, problems = instantiate(%Q(
976
+ \)
977
+ TestNode
978
+ *
979
+ TestNode
980
+ $
981
+ TestNode
982
+ ,
983
+ TestNode
984
+ [
985
+ TestNode
986
+ {
987
+ TestNode
988
+ ]
989
+ TestNode
990
+ }
991
+ TestNode
992
+ }}
993
+ ), TestMM, :root_elements => root_elements)
994
+ assert_equal 8, root_elements.size
995
+ assert_problems([
996
+ [/parse error on token '\)'/i, 2],
997
+ [/parse error on token '\*'/i, 4],
998
+ [/parse error on token '\$'/i, 6],
999
+ [/unexpected ,, expected identifier/i, 8],
1000
+ [/unexpected \[, expected identifier/i, 10],
1001
+ [/unexpected \{, expected identifier/i, 12],
1002
+ [/unexpected \], expected identifier/i, 14],
1003
+ [/unexpected \}, expected identifier/i, 16],
1004
+ [/unexpected \}, expected identifier/i, 18],
1005
+ ], problems)
1006
+ end
1007
+
1008
+ def test_parse_error_in_argument_list
1009
+ root_elements = []
1010
+ env, problems = instantiate(%Q(
1011
+ TestNode text: "bla", * nums: 1
1012
+ TestNode text: "bla" * , nums: 1
1013
+ TestNode ?text: "bla"
1014
+ TestNode nums: [1, * 3]
1015
+ ), TestMM, :root_elements => root_elements)
1016
+ assert_equal 4, root_elements.size
1017
+ assert_equal "bla", root_elements[0].text
1018
+ assert_equal [1], root_elements[0].nums
1019
+ assert_equal "bla", root_elements[1].text
1020
+ assert_equal [1], root_elements[1].nums
1021
+ assert_equal "bla", root_elements[2].text
1022
+ assert_equal [1, 3], root_elements[3].nums
1023
+ assert_problems([
1024
+ [/parse error on token '\*'/i, 2],
1025
+ [/parse error on token '\*'/i, 3],
1026
+ [/parse error on token '\?'/i, 4],
1027
+ [/parse error on token '\*'/i, 5],
1028
+ ], problems)
1029
+ end
1030
+
1031
+ def test_unclosed_brace
1032
+ root_elements = []
1033
+ env, problems = instantiate(%Q(
1034
+ TestNode {
1035
+ ), TestMM, :root_elements => root_elements)
1036
+ assert_equal 1, root_elements.size
1037
+ assert_problems([
1038
+ [/unexpected end of file, expected \}/i, 2]
1039
+ ], problems)
1040
+ end
1041
+
1042
+ def test_unclosed_brace2
1043
+ root_elements = []
1044
+ env, problems = instantiate(%Q(
1045
+ TestNode {
1046
+ *
1047
+ ), TestMM, :root_elements => root_elements)
1048
+ assert_equal 1, root_elements.size
1049
+ assert_problems([
1050
+ [/parse error on token '\*'/i, 3]
1051
+ ], problems)
1052
+ end
1053
+
1054
+ def test_unclosed_brace3
1055
+ root_elements = []
1056
+ env, problems = instantiate(%Q(
1057
+ TestNode {
1058
+ childs:
1059
+ ), TestMM, :root_elements => root_elements)
1060
+ assert_equal 1, root_elements.size
1061
+ assert_problems([
1062
+ [/unexpected end of file, expected identifier/i, 3]
1063
+ ], problems)
1064
+ end
1065
+
1066
+ def test_label_without_child
1067
+ root_elements = []
1068
+ env, problems = instantiate(%Q(
1069
+ TestNode {
1070
+ childs:
1071
+ }
1072
+ ), TestMM, :root_elements => root_elements)
1073
+ assert_equal 1, root_elements.size
1074
+ assert_problems([
1075
+ [/unexpected \}, expected identifier/i, 4]
1076
+ ], problems)
1077
+ end
1078
+
1079
+ def test_unclosed_child_bracket
1080
+ root_elements = []
1081
+ env, problems = instantiate(%Q(
1082
+ TestNode {
1083
+ childs: [
1084
+ ), TestMM, :root_elements => root_elements)
1085
+ assert_equal 1, root_elements.size
1086
+ assert_problems([
1087
+ [/unexpected end of file, expected \]/i, 3]
1088
+ ], problems)
1089
+ end
1090
+
1091
+ def test_child_label_problems
1092
+ root_elements = []
1093
+ env, problems = instantiate(%Q(
1094
+ TestNode {
1095
+ childs: x
1096
+ SubNode
1097
+ childs: *
1098
+ SubNode
1099
+ childs: &
1100
+ }
1101
+ ), TestMM, :root_elements => root_elements)
1102
+ assert_equal 1, root_elements.size
1103
+ assert_equal 2, root_elements[0].childs.size
1104
+ assert_problems([
1105
+ [/unexpected identifier 'x', expected newline/i, 3],
1106
+ [/parse error on token '\*'/i, 5],
1107
+ [/parse error on token '&'/i, 7]
1108
+ ], problems)
1109
+ end
1110
+
1111
+ def test_child_label_problems_with_bracket
1112
+ root_elements = []
1113
+ env, problems = instantiate(%Q(
1114
+ TestNode {
1115
+ childs: [ x
1116
+ SubNode
1117
+ ]
1118
+ childs: [ *
1119
+ SubNode
1120
+ ]
1121
+ childs: [&
1122
+ ]
1123
+ }
1124
+ ), TestMM, :root_elements => root_elements)
1125
+ assert_equal 1, root_elements.size
1126
+ assert_equal 2, root_elements[0].childs.size
1127
+ assert_problems([
1128
+ [/unexpected identifier 'x', expected newline/i, 3],
1129
+ [/parse error on token '\*'/i, 6],
1130
+ [/parse error on token '&'/i, 9]
1131
+ ], problems)
1132
+ end
1133
+
1134
+ def test_missing_closing_bracket
1135
+ root_elements = []
1136
+ env, problems = instantiate(%Q(
1137
+ TestNode {
1138
+ childs: [
1139
+ SubNode
1140
+ childs: [
1141
+ SubNode
1142
+ SubNode
1143
+ }
1144
+ ), TestMM, :root_elements => root_elements)
1145
+ assert_equal 1, root_elements.size
1146
+ assert_equal 3, root_elements[0].childs.size
1147
+ assert_problems([
1148
+ [/unexpected label 'childs', expected identifier/i, 5],
1149
+ [/unexpected \}, expected identifier/i, 8],
1150
+ ], problems)
1151
+ end
1152
+
1153
+ def test_missing_closing_brace
1154
+ root_elements = []
1155
+ env, problems = instantiate(%Q(
1156
+ TestNode {
1157
+ TestNode {
1158
+ TestNode
1159
+ }
1160
+ ), TestMM, :root_elements => root_elements)
1161
+ assert_equal 1, root_elements.size
1162
+ assert_equal 1, root_elements[0].childs.size
1163
+ assert_equal 1, root_elements[0].childs[0].childs.size
1164
+ assert_problems([
1165
+ [/unexpected end of file, expected \}/i, 5],
1166
+ ], problems)
1167
+ end
1168
+
1169
+ #
1170
+ # command name provider
1171
+ #
1172
+
1173
+ def test_command_name_provider
1174
+ env, problems = instantiate(%Q(
1175
+ TestNodeX text: "some text", nums: [1,2] {
1176
+ TestNodeX text: "child"
1177
+ TestNodeX text: "child2"
1178
+ }
1179
+ ), TestMM, :command_name_provider => proc do |c|
1180
+ c.name + "X"
1181
+ end)
1182
+ assert_no_problems(problems)
1183
+ assert_model_simple(env, :with_nums)
1184
+ end
1185
+
1186
+ def test_command_name_provider_ambiguous
1187
+ begin
1188
+ env, problems = instantiate(%Q(
1189
+ TestNode
1190
+ ), TestMM, :command_name_provider => proc do |c|
1191
+ "Fixed"
1192
+ end)
1193
+ assert false
1194
+ rescue RuntimeError => e
1195
+ assert e.message =~ /ambiguous command name/
1196
+ end
1197
+ end
1198
+
1199
+ #
1200
+ # comment handler
1201
+ #
1202
+
1203
+ def test_comment_handler
1204
+ proc_calls = 0
1205
+ env, problems = instantiate(%Q(
1206
+ #comment
1207
+ TestNode text: "node1"
1208
+ #comment
1209
+ # multiline
1210
+ TestNode text: "node2"
1211
+ TestNode text: "node3" #comment
1212
+ #above
1213
+ TestNode text: "node4" {#right1
1214
+ childs: [ #right2
1215
+ #unassociated1
1216
+ ] #right3
1217
+ #unassociated2
1218
+ } #below
1219
+ #above1
1220
+ #above2
1221
+ TestNode text: "node5" { #right1
1222
+ childs: #right2
1223
+ TestNode
1224
+ }#below
1225
+ #comment without
1226
+ #an element following
1227
+ ), TestMM, :comment_handler => proc {|c,k,e,env|
1228
+ proc_calls += 1
1229
+ if e.nil?
1230
+ case proc_calls
1231
+ when 4
1232
+ assert_equal "unassociated1", c
1233
+ assert_equal :unassociated, k
1234
+ when 5
1235
+ assert_equal "unassociated2", c
1236
+ assert_equal :unassociated, k
1237
+ when 15
1238
+ assert_equal "comment without\nan element following", c
1239
+ assert_equal :unassociated, k
1240
+ end
1241
+ elsif e.text == "node1"
1242
+ assert_equal "comment", c
1243
+ assert_equal :above, k
1244
+ elsif e.text == "node2"
1245
+ assert_equal "comment\n multiline", c
1246
+ assert_equal :above, k
1247
+ elsif e.text == "node3"
1248
+ assert_equal "comment", c
1249
+ assert_equal :eol, k
1250
+ elsif e.text == "node4"
1251
+ case proc_calls
1252
+ when 6
1253
+ assert_equal "above", c
1254
+ assert_equal :above, k
1255
+ when 7
1256
+ assert_equal "right1", c
1257
+ assert_equal :eol, k
1258
+ when 8
1259
+ assert_equal "right2", c
1260
+ assert_equal :eol, k
1261
+ when 9
1262
+ assert_equal "right3", c
1263
+ assert_equal :eol, k
1264
+ when 10
1265
+ assert_equal "below", c
1266
+ assert_equal :eol, k
1267
+ end
1268
+ elsif e.text == "node5"
1269
+ case proc_calls
1270
+ when 11
1271
+ assert_equal "above1\nabove2", c
1272
+ assert_equal :above, k
1273
+ when 12
1274
+ assert_equal "right1", c
1275
+ assert_equal :eol, k
1276
+ when 13
1277
+ assert_equal "right2", c
1278
+ assert_equal :eol, k
1279
+ when 14
1280
+ assert_equal "below", c
1281
+ assert_equal :eol, k
1282
+ end
1283
+ else
1284
+ assert false, "unexpected element in comment handler"
1285
+ end
1286
+ true
1287
+ })
1288
+ assert_no_problems(problems)
1289
+ assert_equal 15, proc_calls
1290
+ end
1291
+
1292
+ def test_comment_handler_comment_not_allowed
1293
+ env, problems = instantiate(%Q(
1294
+ #comment
1295
+ TestNode
1296
+ ), TestMM, :comment_handler => proc {|c,k,e,env|
1297
+ false
1298
+ })
1299
+ assert_problems([[/element can not take this comment/, 3]], problems)
1300
+ end
1301
+
1302
+ def test_comment_handler_comment_not_allowed_unassociated
1303
+ env, problems = instantiate(%Q(
1304
+ #comment
1305
+ ), TestMM, :comment_handler => proc {|c,k,e,env|
1306
+ false
1307
+ })
1308
+ assert_problems([[/Unassociated comment not allowed/, 2]], problems)
1309
+ end
1310
+
1311
+ #
1312
+ # annotations
1313
+ #
1314
+
1315
+ def test_annotation_not_supported
1316
+ env, problems = instantiate(%Q(
1317
+ @annotation
1318
+ TestNode
1319
+ ), TestMM)
1320
+ assert_problems([[/annotation not allowed/i, 3]], problems)
1321
+ end
1322
+
1323
+ def test_annotation_not_allowed
1324
+ env, problems = instantiate(%Q(
1325
+ @annotation
1326
+ TestNode
1327
+ ), TestMM, :annotation_handler => proc {|a,e,env|
1328
+ false
1329
+ })
1330
+ assert_problems([[/annotation not allowed/i, 3]], problems)
1331
+ end
1332
+
1333
+ def test_annotation_in_wrong_places
1334
+ env, problems = instantiate(%Q(
1335
+ @annotation
1336
+ #comment
1337
+ TestNode {
1338
+ @annotation
1339
+ childs:
1340
+ TestNode
1341
+ @annotation
1342
+ }
1343
+ @annotation
1344
+ ), TestMM)
1345
+ assert_problems([
1346
+ [/unexpected comment 'comment', expected identifier/i, 3],
1347
+ [/unexpected label 'childs', expected identifier/i, 6],
1348
+ [/unexpected \}, expected identifier/i, 9],
1349
+ [/unexpected end of file, expected identifier/i, 10]
1350
+ ], problems)
1351
+ end
1352
+
1353
+ def test_annotation_handler
1354
+ annotations = []
1355
+ elements = []
1356
+ env, problems = instantiate(%Q(
1357
+ @annotation
1358
+ TestNode text: "aa"
1359
+ @annotation
1360
+ @ in a new line
1361
+
1362
+ @ even with space in between
1363
+
1364
+ TestNode text: "bb" {
1365
+ @at child
1366
+ TestNode text: "cc"
1367
+ childs:
1368
+ @after label
1369
+ TestNode text: "dd"
1370
+ @another child
1371
+ TestNode text: "ee"
1372
+ childs: [
1373
+ @in brackets
1374
+ TestNode text: "ff"
1375
+ ]
1376
+ }
1377
+ ), TestMM, :annotation_handler => proc {|a,e,env|
1378
+ annotations << a
1379
+ elements << e
1380
+ true
1381
+ })
1382
+ assert_equal "aa", elements[0].text
1383
+ assert_equal "annotation", annotations[0]
1384
+ assert_equal "cc", elements[1].text
1385
+ assert_equal "at child", annotations[1]
1386
+ assert_equal "dd", elements[2].text
1387
+ assert_equal "after label", annotations[2]
1388
+ assert_equal "ee", elements[3].text
1389
+ assert_equal "another child", annotations[3]
1390
+ assert_equal "ff", elements[4].text
1391
+ assert_equal "in brackets", annotations[4]
1392
+ assert_equal "bb", elements[5].text
1393
+ assert_equal "annotation\n in a new line\n even with space in between", annotations[5]
1394
+ assert_no_problems(problems)
1395
+ end
1396
+
1397
+ #
1398
+ # generics
1399
+ #
1400
+
1401
+ def test_generics_parse_error
1402
+ env, problems = instantiate(%Q(
1403
+ TestNode text: <bla
1404
+ TestNode text: bla>
1405
+ TestNode text: <a<b>
1406
+ TestNode text: <a>b>
1407
+ TestNode text: <%a
1408
+ TestNode text: <%a%
1409
+ TestNode text: <%a%>b%>
1410
+ ), TestMM, :enable_generics => true)
1411
+ assert_problems([
1412
+ [/parse error on token '<'/i, 2],
1413
+ [/unexpected unlabled argument/i, 2],
1414
+ [/parse error on token '>'/i, 3],
1415
+ [/unexpected identifier 'b'/i, 5],
1416
+ [/parse error on token '>'/i, 5],
1417
+ [/unexpected unlabled argument/i, 5],
1418
+ [/parse error on token '<'/i, 6],
1419
+ [/unexpected unlabled argument/i, 6],
1420
+ [/parse error on token '<'/i, 7],
1421
+ [/unexpected unlabled argument/i, 7],
1422
+ [/parse error on token '%'/i, 7],
1423
+ [/unexpected identifier 'b'/i, 8],
1424
+ [/unexpected unlabled argument/i, 8],
1425
+ [/parse error on token '%'/i, 8],
1426
+ ], problems)
1427
+ end
1428
+
1429
+ def test_generics
1430
+ root_elements = []
1431
+ env, problems = instantiate(%q(
1432
+ TestNode text: <bla>, nums: [<1>, <%2%>], boolean: <truthy>, enum: <%option%>, float: <precise>, related: <%noderef%>, others: [<other1>, <%other2%>]
1433
+ ), TestMM, :root_elements => root_elements, :enable_generics => true)
1434
+ assert_no_problems(problems)
1435
+ assert root_elements[0].text.is_a?(RText::Generic)
1436
+ assert_equal "bla", root_elements[0].text.string
1437
+ assert_equal ["1", "2"], root_elements[0].nums.collect{|n| n.string}
1438
+ assert_equal "truthy", root_elements[0].boolean.string
1439
+ assert_equal "option", root_elements[0].enum.string
1440
+ assert_equal "precise", root_elements[0].float.string
1441
+ assert_equal "noderef", root_elements[0].related.string
1442
+ assert_equal ["other1", "other2"], root_elements[0].others.collect{|n| n.string}
1443
+ end
1444
+
1445
+ def test_generics_forbidden
1446
+ env, problems = instantiate(%Q(\
1447
+ TestNode text: <bla>
1448
+ ), TestMM)
1449
+ assert_problems([
1450
+ [/generic value not allowed/i, 1],
1451
+ ], problems)
1452
+ end
1453
+
1454
+ #
1455
+ # subpackages
1456
+ #
1457
+
1458
+ def test_subpackage
1459
+ env, problems = instantiate(%q(
1460
+ TestNodeSub text: "something"
1461
+ ), TestMMSubpackage)
1462
+ assert_no_problems(problems)
1463
+ assert_equal "something", env.elements.first.text
1464
+ end
1465
+
1466
+ #
1467
+ # values
1468
+ #
1469
+
1470
+ def test_escapes
1471
+ env, problems = instantiate(%q(
1472
+ TestNode text: "some \" \\\\ \\\\\" text \r xx \n xx \r\n xx \t xx \b xx \f"
1473
+ ), TestMM)
1474
+ assert_no_problems(problems)
1475
+ assert_equal %Q(some " \\ \\" text \r xx \n xx \r\n xx \t xx \b xx \f), env.elements.first.text
1476
+ end
1477
+
1478
+ def test_escape_single_backslash
1479
+ env, problems = instantiate(%q(
1480
+ TestNode text: "a single \\ will be just itself"
1481
+ ), TestMM)
1482
+ assert_no_problems(problems)
1483
+ assert_equal %q(a single \\ will be just itself), env.elements.first.text
1484
+ end
1485
+
1486
+ def test_string_umlauts
1487
+ env, problems = instantiate(%q(
1488
+ TestNode text: "ä, ö, ü"
1489
+ ), TestMM)
1490
+ assert_no_problems(problems)
1491
+ assert_equal %q(ä, ö, ü), env.elements.first.text
1492
+ end
1493
+
1494
+ def test_integer
1495
+ env, problems = instantiate(%q(
1496
+ TestNode integer: 7
1497
+ TestNode integer: 4294967296
1498
+ TestNode integer: 12345678901234567890
1499
+ ), TestMM)
1500
+ assert_no_problems(problems)
1501
+ assert_equal 7, env.elements[0].integer
1502
+ assert_equal 4294967296, env.elements[1].integer
1503
+ assert_equal 12345678901234567890, env.elements[2].integer
1504
+ end
1505
+
1506
+ def test_integer_hex
1507
+ env, problems = instantiate(%q(
1508
+ TestNode text: root {
1509
+ TestNode integer: 0x7
1510
+ TestNode integer: 0X7
1511
+ TestNode integer: 0x007
1512
+ TestNode integer: 0x77
1513
+ TestNode integer: 0xabCDEF
1514
+ TestNode integer: 0xabcdefabcdefabcdef
1515
+ }
1516
+ ), TestMM)
1517
+ assert_no_problems(problems)
1518
+ assert_equal [7, 7, 7, 0x77, 0xABCDEF, 0xabcdefabcdefabcdef], env.find(:text => "root").first.childs.collect{|c| c.integer}
1519
+ end
1520
+
1521
+ def test_float
1522
+ env, problems = instantiate(%q(
1523
+ TestNode float: 1.23
1524
+ TestNode float: 1.23e-08
1525
+ TestNode float: 1.23e+10
1526
+ TestNode float: 1234567890.123456789
1527
+ ), TestMM)
1528
+ assert_no_problems(problems)
1529
+ assert_equal 1.23, env.elements[0].float
1530
+ assert_equal 1.23e-08, env.elements[1].float
1531
+ assert_equal 1.23e+10, env.elements[2].float
1532
+ if rgen_with_bigdecimal?
1533
+ assert env.elements[3].float.is_a?(BigDecimal)
1534
+ assert_equal "1234567890.123456789", env.elements[3].float.to_s("F")
1535
+ else
1536
+ assert env.elements[3].float.is_a?(Float)
1537
+ assert_equal "1234567890.1234567", env.elements[3].float.to_s
1538
+ end
1539
+ end
1540
+
1541
+ def test_boolean
1542
+ env, problems = instantiate(%q(
1543
+ TestNode text: root {
1544
+ TestNode boolean: true
1545
+ TestNode boolean: false
1546
+ }
1547
+ ), TestMM)
1548
+ assert_no_problems(problems)
1549
+ assert_equal [true, false], env.find(:text => "root").first.childs.collect{|c| c.boolean}
1550
+ end
1551
+
1552
+ def test_enum
1553
+ env, problems = instantiate(%q(
1554
+ TestNode text: root {
1555
+ TestNode enum: A
1556
+ TestNode enum: B
1557
+ TestNode enum: "non-word*chars"
1558
+ TestNode enum: "2you"
1559
+ }
1560
+ ), TestMM)
1561
+ assert_no_problems(problems)
1562
+ assert_equal [:A, :B, :'non-word*chars', :'2you'], env.find(:text => "root").first.childs.collect{|c| c.enum}
1563
+ end
1564
+
1565
+ def test_with_bom
1566
+ env, problems = instantiate(%Q(\xEF\xBB\xBF
1567
+ TestNode text: "some text", nums: [1,2] {
1568
+ TestNode text: "child"
1569
+ TestNode text: "child2"
1570
+ }
1571
+ ), TestMM)
1572
+ assert_no_problems(problems)
1573
+ assert_model_simple(env, :with_nums)
1574
+ end
1575
+
1576
+ #
1577
+ # conflicts with builtins
1578
+ #
1579
+
1580
+ def test_conflict_builtin
1581
+ env, problems = instantiate(%q(
1582
+ Data notTheBuiltin: "for sure"
1583
+ ), TestMMData)
1584
+ assert_no_problems(problems)
1585
+ assert_equal "for sure", env.elements.first.notTheBuiltin
1586
+ end
1587
+
1588
+ def test_builtin_in_subpackage
1589
+ env, problems = instantiate(%q(
1590
+ Data notTheBuiltin: "for sure"
1591
+ ), TestMMSubpackage)
1592
+ assert_no_problems(problems)
1593
+ assert_equal "for sure", env.elements.first.notTheBuiltin
1594
+ end
1595
+
1596
+ #
1597
+ # encoding
1598
+ #
1599
+
1600
+ def test_encodings
1601
+ input = %Q(TestNode text: "iso-8859-1 AE Umlaut: \xc4")
1602
+ # force encoding to binary in order to prevent exceptions on invalid byte sequences
1603
+ # if the encoding would be utf-8, there would be an exception with the string above
1604
+ input.force_encoding("binary")
1605
+ env, problems = instantiate(input, TestMM)
1606
+ assert_no_problems(problems)
1607
+ assert_match /AE Umlaut: /, env.elements.first.text
1608
+ end
1609
+
1610
+ #
1611
+ # line breaks
1612
+ #
1613
+
1614
+ def test_linebreak
1615
+ roots = []
1616
+ env, problems = instantiate(%Q(
1617
+ TestNode sometext,
1618
+ integer: 1,
1619
+ nums: [
1620
+ 1,
1621
+ 2
1622
+ ]
1623
+ ), TestMM, :root_elements => roots, :unlabled_arguments => proc {|clazz| ["text"]})
1624
+ assert_no_problems(problems)
1625
+ node = roots.first
1626
+ assert_equal "sometext", node.text
1627
+ assert_equal 1, node.integer
1628
+ assert_equal [1,2], node.nums
1629
+ end
1630
+
1631
+ def test_linebreak_backslash
1632
+ roots = []
1633
+ env, problems = instantiate(%Q(
1634
+ TestNode \\
1635
+ sometext
1636
+ ), TestMM, :root_elements => roots, :unlabled_arguments => proc {|clazz| ["text"]})
1637
+ assert_no_problems(problems)
1638
+ node = roots.first
1639
+ assert_equal "sometext", node.text
1640
+ end
1641
+
1642
+ def test_linebreak_backslash_problems
1643
+ roots = []
1644
+ env, problems = instantiate(%Q(
1645
+ TostNode \\
1646
+ sometext
1647
+ TostNode
1648
+ ), TestMM, :root_elements => roots, :unlabled_arguments => proc {|clazz| ["text"]})
1649
+ assert_problems([
1650
+ [/unknown command/i, 2],
1651
+ [/unknown command/i, 4],
1652
+ ], problems)
1653
+ end
1654
+
1655
+ module TestMMObjectAttribute
1656
+ extend RGen::MetamodelBuilder::ModuleExtension
1657
+ class TestNode < RGen::MetamodelBuilder::MMBase
1658
+ has_many_attr 'objs', Object
1659
+ end
1660
+ end
1661
+
1662
+ def test_object_attribute
1663
+ roots = []
1664
+ env, problems = instantiate(%Q(
1665
+ TestNode objs: ["some text", -123, someSymbol, true, false, -0.097]
1666
+ ), TestMMObjectAttribute, :root_elements => roots)
1667
+ assert_no_problems(problems)
1668
+ node = roots.first
1669
+ assert_equal ['some text', -123, 'someSymbol', true, false, -0.097], node.objs
1670
+ end
1671
+
1672
+ private
1673
+
1674
+ def instantiate(text, mm, options={})
1675
+ env = RGen::Environment.new
1676
+ lang = RText::Language.new(mm.ecore, options.merge(
1677
+ :root_classes => mm.ecore.eAllClasses.select{|c|
1678
+ c.name == "TestNode" || c.name == "Data" || c.name == "TestNodeSub" || c.name == "SubNode"}))
1679
+ inst = RText::Instantiator.new(lang)
1680
+ problems = []
1681
+ inst.instantiate(text, options.merge({:env => env, :problems => problems, :root_elements => options[:root_elements]}))
1682
+ return env, problems
1683
+ end
1684
+
1685
+ def assert_no_problems(problems)
1686
+ assert problems.empty?, problems.collect{|p| "#{p.message}, line: #{p.line}"}.join("\n")
1687
+ end
1688
+
1689
+ def assert_problems(expected, problems)
1690
+ remaining = problems.dup
1691
+ probs = []
1692
+ expected.each do |e|
1693
+ if e.is_a?(Array)
1694
+ p = remaining.find{|p| p.message =~ e[0] && p.line == e[1]}
1695
+ else
1696
+ p = remaining.find{|p| p.message =~ e}
1697
+ end
1698
+ probs << "expected problem not present: #{e}" if !p
1699
+ # make sure to not delete duplicate problems at once
1700
+ idx = remaining.index(p)
1701
+ remaining.delete_at(idx) if idx
1702
+ end
1703
+ remaining.each do |p|
1704
+ probs << "unexpected problem: #{p.message}, line: #{p.line}"
1705
+ end
1706
+ assert probs.empty?, probs.join("\n")
1707
+ end
1708
+
1709
+ def assert_model_simple(env, *opts)
1710
+ raise "unknown options" unless (opts - [:with_nums]).empty?
1711
+ root = env.find(:class => TestMM::TestNode, :text => "some text").first
1712
+ assert root != nil
1713
+ assert_equal 2, root.childs.size
1714
+ assert_equal [TestMM::TestNode, TestMM::TestNode], root.childs.collect{|c| c.class}
1715
+ assert_equal ["child", "child2"], root.childs.text
1716
+ if opts.include?(:with_nums)
1717
+ assert_equal [1, 2], root.nums
1718
+ end
1719
+ end
1720
+
1721
+ def rgen_with_bigdecimal?
1722
+ begin
1723
+ TestMM::TestNode.new.float = BigDecimal.new("0.0")
1724
+ rescue StandardError
1725
+ return false
1726
+ end
1727
+ true
1728
+ end
1729
+
1730
+ end
1731
+
1732
+