rtext 0.9.0 → 0.9.1

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