rtext 0.9.0 → 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,968 +1,974 @@
1
- # encoding: binary
2
- $:.unshift(File.dirname(__FILE__)+"/../../lib")
3
-
4
- gem 'minitest'
5
- require 'minitest/autorun'
6
- require 'rtext/frontend/connector_manager'
7
- require 'rtext/frontend/context'
8
- require 'logger'
9
-
10
- class IntegrationTest < MiniTest::Test
11
-
12
- ModelFile = File.dirname(__FILE__)+"/model/test_metamodel.ect"
13
- ModelFile2 = File.dirname(__FILE__)+"/model/test_metamodel2.ect"
14
- ModelFile3 = File.dirname(__FILE__)+"/model/test_metamodel3.ect4"
15
- LargeWithErrorsFile = File.dirname(__FILE__)+"/model/test_large_with_errors.ect3"
16
- InvalidEncodingFile = File.dirname(__FILE__)+"/model/invalid_encoding.invenc"
17
- NotInRTextFile = File.dirname(__FILE__)+"/model/test.not_in_rtext"
18
- InvalidCmdLineFile = File.dirname(__FILE__)+"/model/test.invalid_cmd_line"
19
- CrashingBackendFile = File.dirname(__FILE__)+"/model/test.crashing_backend"
20
- DontOpenSocketFile = File.dirname(__FILE__)+"/model/test.dont_open_socket"
21
- CrashOnRequestFile = File.dirname(__FILE__)+"/model/test.crash_on_request"
22
-
23
- def setup_connector(file)
24
- @infile = file
25
- outfile = File.dirname(__FILE__)+"/backend.out"
26
- logfile = File.dirname(__FILE__)+"/frontend.log"
27
- logger = Logger.new(logfile)
28
- File.unlink(outfile) if File.exist?(outfile)
29
- @connection_timeout = false
30
- man = RText::Frontend::ConnectorManager.new(
31
- :logger => logger,
32
- :keep_outfile => true,
33
- :connection_timeout => 2,
34
- :outfile_provider => lambda { File.expand_path(outfile) },
35
- :connect_callback => lambda do |connector, state|
36
- @connection_timeout = true if state == :timeout
37
- end)
38
- @con = man.connector_for_file(@infile)
39
- end
40
-
41
- def teardown
42
- @con.stop if @con
43
- end
44
-
45
- def test_non_existing_file
46
- setup_connector("this is not a file")
47
- assert_nil @con
48
- end
49
-
50
- def test_not_in_rtext_file
51
- setup_connector(NotInRTextFile)
52
- assert_nil @con
53
- end
54
-
55
- def test_invalid_command_line
56
- setup_connector(InvalidCmdLineFile)
57
- assert @con
58
- response = load_model
59
- assert @connection_timeout
60
- end
61
-
62
- def test_crashing_backend
63
- setup_connector(CrashingBackendFile)
64
- assert @con
65
- response = load_model
66
- assert @connection_timeout
67
- end
68
-
69
- def test_backend_doesnt_open_socket
70
- setup_connector(DontOpenSocketFile)
71
- assert @con
72
- response = load_model
73
- assert @connection_timeout
74
- end
75
-
76
- def test_backend_crash_on_request
77
- setup_connector(CrashOnRequestFile)
78
- assert @con
79
- response = load_model
80
- assert_equal [], response["problems"]
81
- response = @con.execute_command({"command" => "link_targets", "context" => [], "column" => 1})
82
- assert_equal :timeout, response
83
- end
84
-
85
- # simulate external encoding utf-8 (-E in .rext) containing a iso-8859-1 character
86
- def test_invalid_encoding
87
- setup_connector(InvalidEncodingFile)
88
- response = load_model
89
- assert_equal "response", response["type"]
90
- assert_equal [], response["problems"]
91
- text = %Q(EPackage "iso-8859-1 umlaut: \xe4",| nsPrefix: "")
92
- context = build_context(text)
93
- assert_completions context, [
94
- "nsPrefix:",
95
- "nsURI:"
96
- ]
97
- end
98
-
99
- def test_loadmodel
100
- setup_connector(ModelFile)
101
- response = load_model
102
- assert_equal "response", response["type"]
103
- assert_equal [], response["problems"]
104
- end
105
-
106
- def test_loadmodel_large_with_errors
107
- setup_connector(LargeWithErrorsFile)
108
- response = load_model
109
- assert_equal "response", response["type"]
110
- assert_equal 43523, response["problems"].first["problems"].size
111
- end
112
-
113
- def test_unknown_command
114
- setup_connector(ModelFile)
115
- response = load_model
116
- response = @con.execute_command({"command" => "unknown"})
117
- assert_equal "unknown_command_error", response["type"]
118
- end
119
-
120
- #TODO: connector restart when .rtext file changes
121
-
122
- def test_complete_first_line
123
- setup_connector(ModelFile)
124
- load_model
125
- context = build_context <<-END
126
- |EPackage StatemachineMM {
127
- END
128
- assert_completions context, [
129
- "EPackage"
130
- ]
131
- context = build_context <<-END
132
- EPackage| StatemachineMM {
133
- END
134
- assert_completions context, [
135
- "EPackage"
136
- ]
137
- context = build_context <<-END
138
- EPackage |StatemachineMM {
139
- END
140
- assert_completions context, [
141
- "name",
142
- "nsPrefix:",
143
- "nsURI:"
144
- ]
145
- context = build_context <<-END
146
- EPackage S|tatemachineMM {
147
- END
148
- assert_completions context, [
149
- "name",
150
- "nsPrefix:",
151
- "nsURI:"
152
- ]
153
- context = build_context <<-END
154
- EPackage StatemachineMM| {
155
- END
156
- assert_completions context, [
157
- "name",
158
- "nsPrefix:",
159
- "nsURI:"
160
- ]
161
- context = build_context <<-END
162
- EPackage StatemachineMM |{
163
- END
164
- assert_completions context, [
165
- ]
166
- context = build_context <<-END
167
- EPackage StatemachineMM {|
168
- END
169
- # these columns don't exist
170
- assert_completions context, []
171
- context = build_context({:col => 27}, "EPackage StatemachineMM {")
172
- assert_completions context, []
173
- context = build_context({:col => 28}, "EPackage StatemachineMM {")
174
- assert_completions context, []
175
- context = build_context({:col => 100}, "EPackage StatemachineMM {")
176
- assert_completions context, []
177
- # before first column is like first column
178
- context = build_context({:col => 0}, "EPackage StatemachineMM {")
179
- assert_completions context, [
180
- "EPackage"
181
- ]
182
- context = build_context({:col => -1}, "EPackage StatemachineMM {")
183
- assert_completions context, [
184
- "EPackage"
185
- ]
186
- context = build_context({:col => -100}, "EPackage StatemachineMM {")
187
- assert_completions context, [
188
- "EPackage"
189
- ]
190
- end
191
-
192
- def test_nested_command
193
- setup_connector(ModelFile)
194
- load_model
195
- context = build_context <<-END
196
- EPackage StatemachineMM {
197
- | EClass State, abstract: true {
198
- END
199
- assert_completions context, [
200
- "EAnnotation",
201
- "EClass",
202
- "EClassifier",
203
- "EDataType",
204
- "EEnum",
205
- "EGenericType",
206
- "EPackage"
207
- ]
208
- context = build_context <<-END
209
- EPackage StatemachineMM {
210
- |EClass State, abstract: true {
211
- END
212
- assert_completions context, [
213
- "EAnnotation",
214
- "EClass",
215
- "EClassifier",
216
- "EDataType",
217
- "EEnum",
218
- "EGenericType",
219
- "EPackage"
220
- ]
221
- context = build_context <<-END
222
- EPackage StatemachineMM {
223
- EC|lass State, abstract: true {
224
- END
225
- assert_completions context, [
226
- "EAnnotation",
227
- "EClass",
228
- "EClassifier",
229
- "EDataType",
230
- "EEnum",
231
- "EGenericType",
232
- "EPackage"
233
- ]
234
- context = build_context <<-END
235
- EPackage StatemachineMM {
236
- EClass| State, abstract: true {
237
- END
238
- assert_completions context, [
239
- "EAnnotation",
240
- "EClass",
241
- "EClassifier",
242
- "EDataType",
243
- "EEnum",
244
- "EGenericType",
245
- "EPackage"
246
- ]
247
- context = build_context <<-END
248
- EPackage StatemachineMM {
249
- EClass |State, abstract: true {
250
- END
251
- assert_completions context, [
252
- "name",
253
- "abstract:",
254
- "interface:",
255
- "eSuperTypes:",
256
- "instanceClassName:"
257
- ]
258
- context = build_context <<-END
259
- EPackage StatemachineMM {
260
- EClass S|tate, abstract: true {
261
- END
262
- assert_completions context, [
263
- "name",
264
- "abstract:",
265
- "interface:",
266
- "eSuperTypes:",
267
- "instanceClassName:"
268
- ]
269
- context = build_context <<-END
270
- EPackage StatemachineMM {
271
- EClass State|, abstract: true {
272
- END
273
- assert_completions context, [
274
- "name",
275
- "abstract:",
276
- "interface:",
277
- "eSuperTypes:",
278
- "instanceClassName:"
279
- ]
280
- context = build_context <<-END
281
- EPackage StatemachineMM {
282
- EClass State,| abstract: true {
283
- END
284
- assert_completions context, [
285
- "abstract:",
286
- "interface:",
287
- "eSuperTypes:",
288
- "instanceClassName:"
289
- ]
290
- context = build_context <<-END
291
- EPackage StatemachineMM {
292
- EClass State, |abstract: true {
293
- END
294
- assert_completions context, [
295
- "abstract:",
296
- "interface:",
297
- "eSuperTypes:",
298
- "instanceClassName:"
299
- ]
300
- context = build_context <<-END
301
- EPackage StatemachineMM {
302
- EClass State, a|bstract: true {
303
- END
304
- assert_completions context, [
305
- "abstract:",
306
- "interface:",
307
- "eSuperTypes:",
308
- "instanceClassName:"
309
- ]
310
- context = build_context <<-END
311
- EPackage StatemachineMM {
312
- EClass State, abstract:| true {
313
- END
314
- assert_completions context, [
315
- "true",
316
- "false"
317
- ]
318
- context = build_context <<-END
319
- EPackage StatemachineMM {
320
- EClass State, abstract: |true {
321
- END
322
- assert_completions context, [
323
- "true",
324
- "false"
325
- ]
326
- context = build_context <<-END
327
- EPackage StatemachineMM {
328
- EClass State, abstract: t|rue {
329
- END
330
- assert_completions context, [
331
- "true",
332
- "false"
333
- ]
334
- context = build_context <<-END
335
- EPackage StatemachineMM {
336
- EClass State, abstract: true| {
337
- END
338
- assert_completions context, [
339
- "true",
340
- "false"
341
- ]
342
- context = build_context <<-END
343
- EPackage StatemachineMM {
344
- EClass State, abstract: true |{
345
- END
346
- assert_completions context, [
347
- ]
348
- context = build_context <<-END
349
- EPackage StatemachineMM {
350
- EClass State, abstract: true {|
351
- END
352
- assert_completions context, [
353
- ]
354
- end
355
-
356
- def test_complete_feature_after_linebreak
357
- setup_connector(ModelFile)
358
- load_model
359
- context = build_context <<-END
360
- EPackage StatemachineMM {
361
- EClass State, abstract: true {
362
- EAttribute name, eType: /StatemachineMM/StringType
363
- EReference parent,
364
- |eType: /StatemachineMM/CompositeState,
365
- END
366
- assert_completions context, [
367
- "containment:",
368
- "resolveProxies:",
369
- "eOpposite:",
370
- "changeable:",
371
- "defaultValueLiteral:",
372
- "derived:",
373
- "transient:",
374
- "unsettable:",
375
- "volatile:",
376
- "lowerBound:",
377
- "ordered:",
378
- "unique:",
379
- "upperBound:",
380
- "eType:"
381
- ]
382
- end
383
-
384
- def test_complete_reference_after_linebreak
385
- setup_connector(ModelFile)
386
- load_model
387
- context = build_context <<-END
388
- EPackage StatemachineMM {
389
- EClass State, abstract: true {
390
- EAttribute name, eType: /StatemachineMM/StringType
391
- EReference parent,
392
- eType: |/StatemachineMM/CompositeState,
393
- END
394
- assert_completions context, [
395
- "/StatemachineMM/CompositeState",
396
- "/StatemachineMM/SimpleState",
397
- "/StatemachineMM/State",
398
- "/StatemachineMM/StringType",
399
- "/StatemachineMM/Transition",
400
- "/StatemachineMM2/SimpleState",
401
- "/StatemachineMM2/State"
402
- ]
403
- end
404
-
405
- def test_complete_command_after_linebreak
406
- setup_connector(ModelFile)
407
- load_model
408
- context = build_context <<-END
409
- EPackage StatemachineMM {
410
- EClass State, abstract: true {
411
- EAttribute name, eType: /StatemachineMM/StringType
412
- EReference parent,
413
- eType: /StatemachineMM/CompositeState,
414
- eOpposite: /StatemachineMM/CompositeState/substates
415
- }
416
- EClass SimpleState, eSuperTypes: [/StatemachineMM/State]
417
- EClass CompositeState,
418
- eSuperTypes: [
419
- /StatemachineMM/State
420
- ],
421
- abstract: false {
422
- |EReference substates, upperBound: -1, containment: true, eType: /StatemachineMM/State, eOpposite: /StatemachineMM/State/parent
423
- END
424
- assert_completions context, [
425
- "EAnnotation",
426
- "EAttribute",
427
- "EOperation",
428
- "EReference",
429
- "EStructuralFeature"
430
- ]
431
- end
432
-
433
- def test_complete_value_after_linebreak
434
- setup_connector(ModelFile)
435
- load_model
436
- context = build_context <<-END
437
- EPackage StatemachineMM {
438
- EClass State, abstract: true {
439
- EAttribute name, eType: /StatemachineMM/StringType
440
- EReference parent,
441
- eType: /StatemachineMM/CompositeState,
442
- eOpposite: /StatemachineMM/CompositeState/substates
443
- }
444
- EClass SimpleState, eSuperTypes: [/StatemachineMM/State]
445
- EClass CompositeState,
446
- eSuperTypes: [
447
- /StatemachineMM/State
448
- ],
449
- abstract: |false {
450
- END
451
- assert_completions context, [
452
- "true",
453
- "false"
454
- ]
455
- end
456
-
457
- def test_complete_in_array_after_linebreak
458
- setup_connector(ModelFile)
459
- load_model
460
- context = build_context <<-END
461
- EPackage StatemachineMM {
462
- EClass State, abstract: true {
463
- EAttribute name, eType: /StatemachineMM/StringType
464
- EReference parent,
465
- eType: /StatemachineMM/CompositeState,
466
- eOpposite: /StatemachineMM/CompositeState/substates
467
- }
468
- EClass SimpleState, eSuperTypes: [/StatemachineMM/State]
469
- EClass CompositeState,
470
- eSuperTypes: [
471
- |/StatemachineMM/State
472
- END
473
- assert_completions context, [
474
- "/StatemachineMM/CompositeState",
475
- "/StatemachineMM/SimpleState",
476
- "/StatemachineMM/State",
477
- "/StatemachineMM/Transition",
478
- "/StatemachineMM2/SimpleState",
479
- "/StatemachineMM2/State"
480
- ]
481
- end
482
-
483
- def test_complete_in_array_after_linebreak2
484
- setup_connector(ModelFile)
485
- load_model
486
- context = build_context <<-END
487
- EPackage StatemachineMM {
488
- EClass State, abstract: true {
489
- EAttribute name, eType: /StatemachineMM/StringType
490
- EReference parent,
491
- eType: /StatemachineMM/CompositeState,
492
- eOpposite: /StatemachineMM/CompositeState/substates
493
- }
494
- EClass SimpleState, eSuperTypes: [/StatemachineMM/State]
495
- EClass CompositeState,
496
- eSuperTypes: [
497
- /StatemachineMM/State
498
- |],
499
- END
500
- assert_completions context, [
501
- ]
502
- end
503
-
504
- def test_complete_after_backslash
505
- setup_connector(ModelFile3)
506
- load_model
507
- context = build_context <<-END
508
- EPackage StatemachineMM3 {
509
- EClass State
510
- EClass \\
511
- |SimpleState,
512
- END
513
- assert_completions context, [
514
- "name",
515
- "abstract:",
516
- "interface:",
517
- "eSuperTypes:",
518
- "instanceClassName:"
519
- ]
520
- end
521
-
522
- def test_complete_after_backslash2
523
- setup_connector(ModelFile3)
524
- load_model
525
- context = build_context <<-END
526
- EPackage StatemachineMM3 {
527
- EClass State
528
- EClass \\
529
- SimpleState,
530
- |eSuperTypes: [/StatemachineMM3/State]
531
- END
532
- assert_completions context, [
533
- "abstract:",
534
- "interface:",
535
- "eSuperTypes:",
536
- "instanceClassName:"
537
- ]
538
- end
539
-
540
- def test_link_target_after_backslash
541
- setup_connector(ModelFile3)
542
- load_model
543
- context = build_context <<-END
544
- EPackage StatemachineMM3 {
545
- EClass State
546
- EClass \\
547
- SimpleState,
548
- eSuperTypes: [/S|tatemachineMM3/State]
549
- END
550
- assert_link_targets context, :file => ModelFile3, :begin => 45, :end => 66, :targets => [
551
- {"file"=> File.expand_path(ModelFile3),
552
- "line"=>2,
553
- "display"=>"/StatemachineMM3/State [EClass]"}
554
- ]
555
- end
556
-
557
- def test_reference_completion
558
- setup_connector(ModelFile)
559
- load_model
560
- context = build_context <<-END
561
- EPackage StatemachineMM {
562
- EClass State, abstract: true {
563
- EAttribute name, eType: |/StatemachineMM/StringType
564
- END
565
- assert_completions context, [
566
- "/StatemachineMM/CompositeState",
567
- "/StatemachineMM/SimpleState",
568
- "/StatemachineMM/State",
569
- "/StatemachineMM/StringType",
570
- "/StatemachineMM/Transition",
571
- "/StatemachineMM2/SimpleState",
572
- "/StatemachineMM2/State",
573
- ]
574
- context = build_context <<-END
575
- EPackage StatemachineMM {
576
- EClass State, abstract: true {
577
- EAttribute name, eType: /StatemachineMM/|StringType
578
- END
579
- assert_completions context, [
580
- "/StatemachineMM/CompositeState",
581
- "/StatemachineMM/SimpleState",
582
- "/StatemachineMM/State",
583
- "/StatemachineMM/StringType",
584
- "/StatemachineMM/Transition",
585
- "/StatemachineMM2/SimpleState",
586
- "/StatemachineMM2/State",
587
- ]
588
- context = build_context <<-END
589
- EPackage StatemachineMM {
590
- EClass State, abstract: true {
591
- EAttribute name, eType: /StatemachineMM/St|ringType
592
- END
593
- assert_completions context, [
594
- "/StatemachineMM/CompositeState",
595
- "/StatemachineMM/SimpleState",
596
- "/StatemachineMM/State",
597
- "/StatemachineMM/StringType",
598
- "/StatemachineMM/Transition",
599
- "/StatemachineMM2/SimpleState",
600
- "/StatemachineMM2/State",
601
- ]
602
- context = build_context <<-END
603
- EPackage StatemachineMM {
604
- EClass State, abstract: true {
605
- EAttribute name, eType: /StatemachineMM/StringType|
606
- END
607
- assert_completions context, [
608
- "/StatemachineMM/CompositeState",
609
- "/StatemachineMM/SimpleState",
610
- "/StatemachineMM/State",
611
- "/StatemachineMM/StringType",
612
- "/StatemachineMM/Transition",
613
- "/StatemachineMM2/SimpleState",
614
- "/StatemachineMM2/State",
615
- ]
616
- end
617
-
618
- def test_reference_completion_in_array
619
- setup_connector(ModelFile)
620
- load_model
621
- context = build_context <<-END
622
- EPackage StatemachineMM {
623
- EClass State, abstract: true {
624
- EAttribute name, eType: /StatemachineMM/StringType
625
- EReference parent,
626
- eType: /StatemachineMM/CompositeState,
627
- eOpposite: /StatemachineMM/CompositeState/substates
628
- }
629
- EClass SimpleState, eSuperTypes: [|/StatemachineMM/State]
630
- END
631
- assert_completions context, [
632
- "/StatemachineMM/CompositeState",
633
- "/StatemachineMM/SimpleState",
634
- "/StatemachineMM/State",
635
- "/StatemachineMM/Transition",
636
- "/StatemachineMM2/SimpleState",
637
- "/StatemachineMM2/State",
638
- ]
639
- context = build_context <<-END
640
- EPackage StatemachineMM {
641
- EClass State, abstract: true {
642
- EAttribute name, eType: /StatemachineMM/StringType
643
- EReference parent,
644
- eType: /StatemachineMM/CompositeState,
645
- eOpposite: /StatemachineMM/CompositeState/substates
646
- }
647
- EClass SimpleState, eSuperTypes: [/StatemachineMM/S|tate]
648
- END
649
- assert_completions context, [
650
- "/StatemachineMM/CompositeState",
651
- "/StatemachineMM/SimpleState",
652
- "/StatemachineMM/State",
653
- "/StatemachineMM/Transition",
654
- "/StatemachineMM2/SimpleState",
655
- "/StatemachineMM2/State",
656
- ]
657
- context = build_context <<-END
658
- EPackage StatemachineMM {
659
- EClass State, abstract: true {
660
- EAttribute name, eType: /StatemachineMM/StringType
661
- EReference parent,
662
- eType: /StatemachineMM/CompositeState,
663
- eOpposite: /StatemachineMM/CompositeState/substates
664
- }
665
- EClass SimpleState, eSuperTypes: [/StatemachineMM/State|]
666
- END
667
- assert_completions context, [
668
- "/StatemachineMM/CompositeState",
669
- "/StatemachineMM/SimpleState",
670
- "/StatemachineMM/State",
671
- "/StatemachineMM/Transition",
672
- "/StatemachineMM2/SimpleState",
673
- "/StatemachineMM2/State",
674
- ]
675
- context = build_context <<-END
676
- EPackage StatemachineMM {
677
- EClass State, abstract: true {
678
- EAttribute name, eType: /StatemachineMM/StringType
679
- EReference parent,
680
- eType: /StatemachineMM/CompositeState,
681
- eOpposite: /StatemachineMM/CompositeState/substates
682
- }
683
- EClass SimpleState, eSuperTypes: [/StatemachineMM/State]|
684
- END
685
- assert_completions context, [
686
- ]
687
- end
688
-
689
- def test_integer_completion
690
- setup_connector(ModelFile)
691
- load_model
692
- context = build_context <<-END
693
- EPackage StatemachineMM {
694
- EClass State, abstract: true {
695
- EAttribute name, eType: /StatemachineMM/StringType
696
- EReference parent,
697
- eType: /StatemachineMM/CompositeState,
698
- eOpposite: /StatemachineMM/CompositeState/substates
699
- }
700
- EClass SimpleState, eSuperTypes: [/StatemachineMM/State]
701
- EClass CompositeState,
702
- eSuperTypes: [
703
- /StatemachineMM/State
704
- ],
705
- abstract: false {
706
- EReference substates, upperBound: |-1, containment: true, eType: /StatemachineMM/State, eOpposite: /StatemachineMM/State/parent
707
- END
708
- assert_completions context, [
709
- "1",
710
- ]
711
- context = build_context <<-END
712
- EPackage StatemachineMM {
713
- EClass State, abstract: true {
714
- EAttribute name, eType: /StatemachineMM/StringType
715
- EReference parent,
716
- eType: /StatemachineMM/CompositeState,
717
- eOpposite: /StatemachineMM/CompositeState/substates
718
- }
719
- EClass SimpleState, eSuperTypes: [/StatemachineMM/State]
720
- EClass CompositeState,
721
- eSuperTypes: [
722
- /StatemachineMM/State
723
- ],
724
- abstract: false {
725
- EReference substates, upperBound: -1|, containment: true, eType: /StatemachineMM/State, eOpposite: /StatemachineMM/State/parent
726
- END
727
- assert_completions context, [
728
- "1",
729
- ]
730
- end
731
-
732
- def test_link_targets
733
- setup_connector(ModelFile)
734
- load_model
735
- context = build_context <<-END
736
- EPackage StatemachineMM {
737
- EClass State, abstract: true {
738
- EAttribute name, eType: /St|atemachineMM/StringType
739
- END
740
- assert_link_targets context, :begin => 29, :end => 54, :targets => [
741
- {"file"=> File.expand_path(@infile),
742
- "line"=>20,
743
- "display"=>"/StatemachineMM/StringType [EDataType]"}
744
- ]
745
- context = build_context <<-END
746
- EPackage StatemachineMM {
747
- EClass State, abstract: true {
748
- EAttribute name, eType: |/StatemachineMM/StringType
749
- END
750
- assert_link_targets context, :begin => 29, :end => 54, :targets => [
751
- {"file"=> File.expand_path(@infile),
752
- "line"=>20,
753
- "display"=>"/StatemachineMM/StringType [EDataType]"}
754
- ]
755
- context = build_context <<-END
756
- EPackage StatemachineMM {
757
- EClass State, abstract: true {
758
- EAttribute name, eType: /StatemachineMM/StringTyp|e
759
- END
760
- assert_link_targets context, :begin => 29, :end => 54, :targets => [
761
- {"file"=> File.expand_path(@infile),
762
- "line"=>20,
763
- "display"=>"/StatemachineMM/StringType [EDataType]"}
764
- ]
765
- context = build_context <<-END
766
- EPackage StatemachineMM {
767
- EClass State, abstract: true {
768
- EAttribute name, eType: /StatemachineMM/StringType|
769
- END
770
- assert_link_targets context, :begin => nil, :end => nil, :targets => []
771
- context = build_context <<-END
772
- EPackage StatemachineMM {
773
- EClass State, abstract: true {
774
- EAttribute name, eType:| /StatemachineMM/StringType
775
- END
776
- assert_link_targets context, :begin => nil, :end => nil, :targets => []
777
- # backward ref
778
- context = build_context <<-END
779
- EPackage StatemachineMM {
780
- E|Class State, abstract: true {
781
- END
782
- assert_link_targets context, :begin => 3, :end => 8, :targets => [
783
- {"file"=> File.expand_path(@infile),
784
- "line"=>8,
785
- "display"=>"/StatemachineMM/SimpleState [EClass]"},
786
- {"file"=> File.expand_path(@infile),
787
- "line"=>9,
788
- "display"=>"/StatemachineMM/CompositeState [EClass]"}
789
- ]
790
- context = build_context <<-END
791
- EPackage StatemachineMM {
792
- EClass State, abstract: true {
793
- EAttribute name, eType: /StatemachineMM/StringType
794
- EReference parent,
795
- eType: /StatemachineMM/CompositeState,
796
- eOpposite: /StatemachineMM/CompositeState/substates
797
- }
798
- |EClass SimpleState, eSuperTypes: [/StatemachineMM/State]
799
- END
800
- assert_link_targets context, :begin => 3, :end => 8, :targets => []
801
- # bad location
802
- context = build_context <<-END
803
- EPackage S|tatemachineMM {
804
- END
805
- assert_link_targets context, :begin => 10, :end => 23, :targets => []
806
- end
807
-
808
- def test_link_targets_no_text_after_name
809
- setup_connector(ModelFile)
810
- load_model
811
- context = build_context({:infile => ModelFile2}, <<-END
812
- EPackage StatemachineMM2 {
813
- ECl|ass State
814
- END
815
- )
816
- assert_link_targets context, :file => ModelFile2, :begin => 3, :end => 8, :targets => [
817
- {"file"=> File.expand_path(ModelFile2),
818
- "line"=>3,
819
- "display"=>"/StatemachineMM2/SimpleState [EClass]"}
820
- ]
821
- end
822
-
823
- def test_link_targets_after_linebreak
824
- setup_connector(ModelFile)
825
- load_model
826
- context = build_context <<-END
827
- EPackage StatemachineMM {
828
- EClass State, abstract: true {
829
- EAttribute name, eType: /StatemachineMM/StringType
830
- EReference parent,
831
- eType: /St|atemachineMM/CompositeState,
832
- END
833
- # in case of linebreaks, the begin and end column refer to the string which
834
- # was passed to the backend as the context; in this case the context extractor
835
- # appends each broken line to the previous line with all the leading whitespace removed
836
- assert_link_targets context, :begin => 37, :end => 66, :targets => [
837
- {"file"=> File.expand_path(@infile),
838
- "line"=>9,
839
- "display"=>"/StatemachineMM/CompositeState [EClass]"}
840
- ]
841
- context = build_context <<-END
842
- EPackage StatemachineMM {
843
- EClass State, abstract: true {
844
- EAttribute name, eType: /StatemachineMM/StringType
845
- EReference parent,
846
- eType: |/StatemachineMM/CompositeState,
847
- END
848
- assert_link_targets context, :begin => 37, :end => 66, :targets => [
849
- {"file"=> File.expand_path(@infile),
850
- "line"=>9,
851
- "display"=>"/StatemachineMM/CompositeState [EClass]"}
852
- ]
853
- context = build_context <<-END
854
- EPackage StatemachineMM {
855
- EClass State, abstract: true {
856
- EAttribute name, eType: /StatemachineMM/StringType
857
- EReference parent,
858
- eType: /StatemachineMM/CompositeStat|e,
859
- END
860
- assert_link_targets context, :begin => 37, :end => 66, :targets => [
861
- {"file"=> File.expand_path(@infile),
862
- "line"=>9,
863
- "display"=>"/StatemachineMM/CompositeState [EClass]"}
864
- ]
865
- context = build_context <<-END
866
- EPackage StatemachineMM {
867
- EClass State, abstract: true {
868
- EAttribute name, eType: /StatemachineMM/StringType
869
- EReference parent,
870
- eType: /StatemachineMM/CompositeState|,
871
- END
872
- assert_link_targets context, :begin => nil, :end => nil, :targets => []
873
- end
874
-
875
- def test_find_elements
876
- setup_connector(ModelFile)
877
- load_model
878
- response = @con.execute_command(
879
- {"command" => "find_elements", "search_pattern" => "Sta"})
880
- assert_equal \
881
- [{"display"=>"State [EClass] - /StatemachineMM",
882
- "file"=> File.expand_path(@infile),
883
- "line"=>2},
884
- {"display"=>"State [EClass] - /StatemachineMM2",
885
- "file"=> File.expand_path(ModelFile2),
886
- "line"=>2},
887
- {"display"=>"StatemachineMM [EPackage] - /StatemachineMM",
888
- "file"=> File.expand_path(@infile),
889
- "line"=>1},
890
- {"display"=>"StatemachineMM2 [EPackage] - /StatemachineMM2",
891
- "file"=> File.expand_path(ModelFile2),
892
- "line"=>1}], response["elements"]
893
- response = @con.execute_command(
894
- {"command" => "find_elements", "search_pattern" => "target"})
895
- assert_equal \
896
- [{"display"=>"target [EReference] - /StatemachineMM/Transition",
897
- "file"=> File.expand_path(@infile),
898
- "line"=>17}], response["elements"]
899
- response = @con.execute_command(
900
- {"command" => "find_elements", "search_pattern" => ""})
901
- assert_equal [], response["elements"]
902
- response = @con.execute_command(
903
- {"command" => "find_elements", "search_pattern" => "xxx"})
904
- assert_equal [], response["elements"]
905
- end
906
-
907
- TestContext = Struct.new(:line, :col)
908
-
909
- def build_context(text, text2=nil)
910
- if text.is_a?(Hash)
911
- context_lines = text2.split("\n")
912
- pos_in_line = text[:col] || context_lines.last.index("|") + 1
913
- infile = text[:infile] || @infile
914
- else
915
- context_lines = text.split("\n")
916
- pos_in_line = context_lines.last.index("|") + 1
917
- infile = @infile
918
- end
919
- context_lines.last.sub!("|", "")
920
-
921
- # check that the context data actally matches the real file in the filesystem
922
- content = File.open(infile, "rb"){|f| f.read}
923
- ref_lines = content.split(/\r?\n/)[0..context_lines.size-1]
924
- raise "inconsistent test data, expected\n:#{ref_lines.join("\n")}\ngot:\n#{context_lines.join("\n")}\n" \
925
- unless ref_lines == context_lines
926
-
927
- # column numbers start at 1
928
- TestContext.new(context_lines.size, pos_in_line)
929
- end
930
-
931
- def assert_link_targets(context, options)
932
- infile = options[:file] || @infile
933
- content = File.open(infile, "rb") {|f| f.read}
934
- lines = content.split(/\r?\n/)[0..context.line-1]
935
- lines, col = RText::Frontend::Context.new.extract(lines, context.col)
936
- response = @con.execute_command(
937
- {"command" => "link_targets", "context" => lines, "column" => col})
938
- assert_equal "response", response["type"]
939
- assert_equal options[:targets], response["targets"]
940
- assert_equal options[:begin], response["begin_column"]
941
- assert_equal options[:end], response["end_column"]
942
- end
943
-
944
- def assert_completions(context, expected)
945
- content = File.open(@infile, "rb"){|f| f.read}
946
- lines = content.split(/\r?\n/)[0..context.line-1]
947
- lines, col = RText::Frontend::Context.new.extract(lines, context.col)
948
- response = @con.execute_command(
949
- {"command" => "content_complete", "context" => lines, "column" => col})
950
- assert_equal expected, response["options"].collect{|o| o["insert"]}
951
- end
952
-
953
- def load_model
954
- done = false
955
- response = nil
956
- while !done
957
- response = @con.execute_command({"command" => "load_model"})
958
- if response == :connecting && !@connection_timeout
959
- sleep(0.1)
960
- @con.resume
961
- else
962
- done = true
963
- end
964
- end
965
- response
966
- end
967
-
968
- end
1
+ # encoding: binary
2
+ $:.unshift(File.dirname(__FILE__)+"/../../lib")
3
+
4
+ require 'minitest/autorun'
5
+ require 'rtext/frontend/connector_manager'
6
+ require 'rtext/frontend/context'
7
+ require 'logger'
8
+
9
+ class IntegrationTest < MiniTest::Test
10
+
11
+ ModelFile = File.dirname(__FILE__)+"/model/test_metamodel.ect"
12
+ ModelFile2 = File.dirname(__FILE__)+"/model/test_metamodel2.ect"
13
+ ModelFile3 = File.dirname(__FILE__)+"/model/test_metamodel3.ect4"
14
+ LargeWithErrorsFile = File.dirname(__FILE__)+"/model/test_large_with_errors.ect3"
15
+ InvalidEncodingFile = File.dirname(__FILE__)+"/model/invalid_encoding.invenc"
16
+ NotInRTextFile = File.dirname(__FILE__)+"/model/test.not_in_rtext"
17
+ InvalidCmdLineFile = File.dirname(__FILE__)+"/model/test.invalid_cmd_line"
18
+ CrashingBackendFile = File.dirname(__FILE__)+"/model/test.crashing_backend"
19
+ DontOpenSocketFile = File.dirname(__FILE__)+"/model/test.dont_open_socket"
20
+ CrashOnRequestFile = File.dirname(__FILE__)+"/model/test.crash_on_request"
21
+
22
+ def setup_connector(file)
23
+ @infile = file
24
+ outfile = File.dirname(__FILE__)+"/backend.out" + Random.new.rand(100000000).to_s
25
+ logfile = File.dirname(__FILE__)+"/frontend.log"
26
+ logger = Logger.new(logfile)
27
+ File.unlink(outfile) if File.exist?(outfile)
28
+ @connection_timeout = false
29
+ man = RText::Frontend::ConnectorManager.new(
30
+ :logger => logger,
31
+ :keep_outfile => true,
32
+ :connection_timeout => 10,
33
+ :outfile_provider => lambda { File.expand_path(outfile) },
34
+ :connect_callback => lambda do |connector, state|
35
+ @connection_timeout = true if state == :timeout
36
+ end)
37
+ @con = man.connector_for_file(@infile)
38
+ end
39
+
40
+ def teardown
41
+ @con.stop if @con
42
+ end
43
+
44
+ def test_non_existing_file
45
+ setup_connector("this is not a file")
46
+ assert_nil @con
47
+ end
48
+
49
+ def test_not_in_rtext_file
50
+ setup_connector(NotInRTextFile)
51
+ assert_nil @con
52
+ end
53
+
54
+ def test_invalid_command_line
55
+ setup_connector(InvalidCmdLineFile)
56
+ assert @con
57
+ response = load_model
58
+ assert @connection_timeout
59
+ end
60
+
61
+ def test_crashing_backend
62
+ setup_connector(CrashingBackendFile)
63
+ assert @con
64
+ response = load_model
65
+ assert @connection_timeout
66
+ end
67
+
68
+ def test_backend_doesnt_open_socket
69
+ setup_connector(DontOpenSocketFile)
70
+ assert @con
71
+ response = load_model
72
+ assert @connection_timeout
73
+ end
74
+
75
+ def test_backend_crash_on_request
76
+ setup_connector(CrashOnRequestFile)
77
+ assert @con
78
+ response = load_model
79
+ assert_equal [], response["problems"]
80
+ response = @con.execute_command({"command" => "link_targets", "context" => [], "column" => 1})
81
+ assert_equal :timeout, response
82
+ end
83
+
84
+ # simulate external encoding utf-8 (-E in .rext) containing a iso-8859-1 character
85
+ def test_invalid_encoding
86
+ setup_connector(InvalidEncodingFile)
87
+ response = load_model
88
+ assert_equal "response", response["type"]
89
+ assert_equal [], response["problems"]
90
+ text = %Q(EPackage "iso-8859-1 umlaut: \xe4",| nsPrefix: "")
91
+ context = build_context(text)
92
+ assert_completions context, [
93
+ "nsPrefix:",
94
+ "nsURI:"
95
+ ]
96
+ end
97
+
98
+ def test_loadmodel
99
+ setup_connector(ModelFile)
100
+ response = load_model
101
+ assert_equal "response", response["type"]
102
+ assert_equal [], response["problems"]
103
+ end
104
+
105
+ def test_loadmodel_large_with_errors
106
+ setup_connector(LargeWithErrorsFile)
107
+ response = load_model
108
+ assert_equal "response", response["type"]
109
+ assert_equal 43523, response["problems"].first["problems"].size
110
+ end
111
+
112
+ def test_unknown_command
113
+ setup_connector(ModelFile)
114
+ response = load_model
115
+ response = @con.execute_command({"command" => "unknown"})
116
+ assert_equal "unknown_command_error", response["type"]
117
+ end
118
+
119
+ #TODO: connector restart when .rtext file changes
120
+
121
+ def test_complete_first_line
122
+ setup_connector(ModelFile)
123
+ load_model
124
+ context = build_context <<-END
125
+ |EPackage StatemachineMM {
126
+ END
127
+ assert_completions context, [
128
+ "EPackage"
129
+ ]
130
+ context = build_context <<-END
131
+ EPackage| StatemachineMM {
132
+ END
133
+ assert_completions context, [
134
+ "EPackage"
135
+ ]
136
+ context = build_context <<-END
137
+ EPackage |StatemachineMM {
138
+ END
139
+ assert_completions context, [
140
+ "name",
141
+ "nsPrefix:",
142
+ "nsURI:"
143
+ ]
144
+ context = build_context <<-END
145
+ EPackage S|tatemachineMM {
146
+ END
147
+ assert_completions context, [
148
+ "name",
149
+ "nsPrefix:",
150
+ "nsURI:"
151
+ ]
152
+ context = build_context <<-END
153
+ EPackage StatemachineMM| {
154
+ END
155
+ assert_completions context, [
156
+ "name",
157
+ "nsPrefix:",
158
+ "nsURI:"
159
+ ]
160
+ context = build_context <<-END
161
+ EPackage StatemachineMM |{
162
+ END
163
+ assert_completions context, [
164
+ ]
165
+ context = build_context <<-END
166
+ EPackage StatemachineMM {|
167
+ END
168
+ # these columns don't exist
169
+ assert_completions context, []
170
+ context = build_context({:col => 27}, "EPackage StatemachineMM {")
171
+ assert_completions context, []
172
+ context = build_context({:col => 28}, "EPackage StatemachineMM {")
173
+ assert_completions context, []
174
+ context = build_context({:col => 100}, "EPackage StatemachineMM {")
175
+ assert_completions context, []
176
+ # before first column is like first column
177
+ context = build_context({:col => 0}, "EPackage StatemachineMM {")
178
+ assert_completions context, [
179
+ "EPackage"
180
+ ]
181
+ context = build_context({:col => -1}, "EPackage StatemachineMM {")
182
+ assert_completions context, [
183
+ "EPackage"
184
+ ]
185
+ context = build_context({:col => -100}, "EPackage StatemachineMM {")
186
+ assert_completions context, [
187
+ "EPackage"
188
+ ]
189
+ end
190
+
191
+ def test_nested_command
192
+ setup_connector(ModelFile)
193
+ load_model
194
+ context = build_context <<-END
195
+ EPackage StatemachineMM {
196
+ | EClass State, abstract: true {
197
+ END
198
+ assert_completions context, [
199
+ "EAnnotation",
200
+ "EClass",
201
+ "EClassifier",
202
+ "EDataType",
203
+ "EEnum",
204
+ "EGenericType",
205
+ "EPackage"
206
+ ]
207
+ context = build_context <<-END
208
+ EPackage StatemachineMM {
209
+ |EClass State, abstract: true {
210
+ END
211
+ assert_completions context, [
212
+ "EAnnotation",
213
+ "EClass",
214
+ "EClassifier",
215
+ "EDataType",
216
+ "EEnum",
217
+ "EGenericType",
218
+ "EPackage"
219
+ ]
220
+ context = build_context <<-END
221
+ EPackage StatemachineMM {
222
+ EC|lass State, abstract: true {
223
+ END
224
+ assert_completions context, [
225
+ "EAnnotation",
226
+ "EClass",
227
+ "EClassifier",
228
+ "EDataType",
229
+ "EEnum",
230
+ "EGenericType",
231
+ "EPackage"
232
+ ]
233
+ context = build_context <<-END
234
+ EPackage StatemachineMM {
235
+ EClass| State, abstract: true {
236
+ END
237
+ assert_completions context, [
238
+ "EAnnotation",
239
+ "EClass",
240
+ "EClassifier",
241
+ "EDataType",
242
+ "EEnum",
243
+ "EGenericType",
244
+ "EPackage"
245
+ ]
246
+ context = build_context <<-END
247
+ EPackage StatemachineMM {
248
+ EClass |State, abstract: true {
249
+ END
250
+ assert_completions context, [
251
+ "name",
252
+ "abstract:",
253
+ "interface:",
254
+ "eSuperTypes:",
255
+ "instanceClassName:"
256
+ ]
257
+ context = build_context <<-END
258
+ EPackage StatemachineMM {
259
+ EClass S|tate, abstract: true {
260
+ END
261
+ assert_completions context, [
262
+ "name",
263
+ "abstract:",
264
+ "interface:",
265
+ "eSuperTypes:",
266
+ "instanceClassName:"
267
+ ]
268
+ context = build_context <<-END
269
+ EPackage StatemachineMM {
270
+ EClass State|, abstract: true {
271
+ END
272
+ assert_completions context, [
273
+ "name",
274
+ "abstract:",
275
+ "interface:",
276
+ "eSuperTypes:",
277
+ "instanceClassName:"
278
+ ]
279
+ context = build_context <<-END
280
+ EPackage StatemachineMM {
281
+ EClass State,| abstract: true {
282
+ END
283
+ assert_completions context, [
284
+ "abstract:",
285
+ "interface:",
286
+ "eSuperTypes:",
287
+ "instanceClassName:"
288
+ ]
289
+ context = build_context <<-END
290
+ EPackage StatemachineMM {
291
+ EClass State, |abstract: true {
292
+ END
293
+ assert_completions context, [
294
+ "abstract:",
295
+ "interface:",
296
+ "eSuperTypes:",
297
+ "instanceClassName:"
298
+ ]
299
+ context = build_context <<-END
300
+ EPackage StatemachineMM {
301
+ EClass State, a|bstract: true {
302
+ END
303
+ assert_completions context, [
304
+ "abstract:",
305
+ "interface:",
306
+ "eSuperTypes:",
307
+ "instanceClassName:"
308
+ ]
309
+ context = build_context <<-END
310
+ EPackage StatemachineMM {
311
+ EClass State, abstract:| true {
312
+ END
313
+ assert_completions context, [
314
+ "true",
315
+ "false"
316
+ ]
317
+ context = build_context <<-END
318
+ EPackage StatemachineMM {
319
+ EClass State, abstract: |true {
320
+ END
321
+ assert_completions context, [
322
+ "true",
323
+ "false"
324
+ ]
325
+ context = build_context <<-END
326
+ EPackage StatemachineMM {
327
+ EClass State, abstract: t|rue {
328
+ END
329
+ assert_completions context, [
330
+ "true",
331
+ "false"
332
+ ]
333
+ context = build_context <<-END
334
+ EPackage StatemachineMM {
335
+ EClass State, abstract: true| {
336
+ END
337
+ assert_completions context, [
338
+ "true",
339
+ "false"
340
+ ]
341
+ context = build_context <<-END
342
+ EPackage StatemachineMM {
343
+ EClass State, abstract: true |{
344
+ END
345
+ assert_completions context, [
346
+ ]
347
+ context = build_context <<-END
348
+ EPackage StatemachineMM {
349
+ EClass State, abstract: true {|
350
+ END
351
+ assert_completions context, [
352
+ ]
353
+ end
354
+
355
+ def test_complete_feature_after_linebreak
356
+ setup_connector(ModelFile)
357
+ load_model
358
+ context = build_context <<-END
359
+ EPackage StatemachineMM {
360
+ EClass State, abstract: true {
361
+ EAttribute name, eType: /StatemachineMM/StringType
362
+ EReference parent,
363
+ |eType: /StatemachineMM/CompositeState,
364
+ END
365
+ assert_completions context, [
366
+ "containment:",
367
+ "resolveProxies:",
368
+ "eOpposite:",
369
+ "changeable:",
370
+ "defaultValueLiteral:",
371
+ "derived:",
372
+ "transient:",
373
+ "unsettable:",
374
+ "volatile:",
375
+ "lowerBound:",
376
+ "ordered:",
377
+ "unique:",
378
+ "upperBound:",
379
+ "eType:"
380
+ ]
381
+ end
382
+
383
+ def test_complete_reference_after_linebreak
384
+ setup_connector(ModelFile)
385
+ load_model
386
+ context = build_context <<-END
387
+ EPackage StatemachineMM {
388
+ EClass State, abstract: true {
389
+ EAttribute name, eType: /StatemachineMM/StringType
390
+ EReference parent,
391
+ eType: |/StatemachineMM/CompositeState,
392
+ END
393
+ assert_completions context, [
394
+ "/StatemachineMM/CompositeState",
395
+ "/StatemachineMM/SimpleState",
396
+ "/StatemachineMM/State",
397
+ "/StatemachineMM/StringType",
398
+ "/StatemachineMM/Transition",
399
+ "/StatemachineMM2/SimpleState",
400
+ "/StatemachineMM2/State"
401
+ ]
402
+ end
403
+
404
+ def test_complete_command_after_linebreak
405
+ setup_connector(ModelFile)
406
+ load_model
407
+ context = build_context <<-END
408
+ EPackage StatemachineMM {
409
+ EClass State, abstract: true {
410
+ EAttribute name, eType: /StatemachineMM/StringType
411
+ EReference parent,
412
+ eType: /StatemachineMM/CompositeState,
413
+ eOpposite: /StatemachineMM/CompositeState/substates
414
+ }
415
+ EClass SimpleState, eSuperTypes: [/StatemachineMM/State]
416
+ EClass CompositeState,
417
+ eSuperTypes: [
418
+ /StatemachineMM/State
419
+ ],
420
+ abstract: false {
421
+ |EReference substates, upperBound: -1, containment: true, eType: /StatemachineMM/State, eOpposite: /StatemachineMM/State/parent
422
+ END
423
+ assert_completions context, [
424
+ "EAnnotation",
425
+ "EAttribute",
426
+ "EOperation",
427
+ "EReference",
428
+ "EStructuralFeature"
429
+ ]
430
+ end
431
+
432
+ def test_complete_value_after_linebreak
433
+ setup_connector(ModelFile)
434
+ load_model
435
+ context = build_context <<-END
436
+ EPackage StatemachineMM {
437
+ EClass State, abstract: true {
438
+ EAttribute name, eType: /StatemachineMM/StringType
439
+ EReference parent,
440
+ eType: /StatemachineMM/CompositeState,
441
+ eOpposite: /StatemachineMM/CompositeState/substates
442
+ }
443
+ EClass SimpleState, eSuperTypes: [/StatemachineMM/State]
444
+ EClass CompositeState,
445
+ eSuperTypes: [
446
+ /StatemachineMM/State
447
+ ],
448
+ abstract: |false {
449
+ END
450
+ assert_completions context, [
451
+ "true",
452
+ "false"
453
+ ]
454
+ end
455
+
456
+ def test_complete_in_array_after_linebreak
457
+ setup_connector(ModelFile)
458
+ load_model
459
+ context = build_context <<-END
460
+ EPackage StatemachineMM {
461
+ EClass State, abstract: true {
462
+ EAttribute name, eType: /StatemachineMM/StringType
463
+ EReference parent,
464
+ eType: /StatemachineMM/CompositeState,
465
+ eOpposite: /StatemachineMM/CompositeState/substates
466
+ }
467
+ EClass SimpleState, eSuperTypes: [/StatemachineMM/State]
468
+ EClass CompositeState,
469
+ eSuperTypes: [
470
+ |/StatemachineMM/State
471
+ END
472
+ assert_completions context, [
473
+ "/StatemachineMM/CompositeState",
474
+ "/StatemachineMM/SimpleState",
475
+ "/StatemachineMM/State",
476
+ "/StatemachineMM/Transition",
477
+ "/StatemachineMM2/SimpleState",
478
+ "/StatemachineMM2/State"
479
+ ]
480
+ end
481
+
482
+ def test_complete_in_array_after_linebreak2
483
+ setup_connector(ModelFile)
484
+ load_model
485
+ context = build_context <<-END
486
+ EPackage StatemachineMM {
487
+ EClass State, abstract: true {
488
+ EAttribute name, eType: /StatemachineMM/StringType
489
+ EReference parent,
490
+ eType: /StatemachineMM/CompositeState,
491
+ eOpposite: /StatemachineMM/CompositeState/substates
492
+ }
493
+ EClass SimpleState, eSuperTypes: [/StatemachineMM/State]
494
+ EClass CompositeState,
495
+ eSuperTypes: [
496
+ /StatemachineMM/State
497
+ |],
498
+ END
499
+ assert_completions context, [
500
+ ]
501
+ end
502
+
503
+ def test_complete_after_backslash
504
+ setup_connector(ModelFile3)
505
+ load_model
506
+ context = build_context <<-END
507
+ EPackage StatemachineMM3 {
508
+ EClass State
509
+ EClass \\
510
+ |SimpleState,
511
+ END
512
+ assert_completions context, [
513
+ "name",
514
+ "abstract:",
515
+ "interface:",
516
+ "eSuperTypes:",
517
+ "instanceClassName:"
518
+ ]
519
+ end
520
+
521
+ def test_complete_after_backslash2
522
+ setup_connector(ModelFile3)
523
+ load_model
524
+ context = build_context <<-END
525
+ EPackage StatemachineMM3 {
526
+ EClass State
527
+ EClass \\
528
+ SimpleState,
529
+ |eSuperTypes: [/StatemachineMM3/State]
530
+ END
531
+ assert_completions context, [
532
+ "abstract:",
533
+ "interface:",
534
+ "eSuperTypes:",
535
+ "instanceClassName:"
536
+ ]
537
+ end
538
+
539
+ def test_link_target_after_backslash
540
+ setup_connector(ModelFile3)
541
+ load_model
542
+ context = build_context <<-END
543
+ EPackage StatemachineMM3 {
544
+ EClass State
545
+ EClass \\
546
+ SimpleState,
547
+ eSuperTypes: [/S|tatemachineMM3/State]
548
+ END
549
+ assert_link_targets context, :file => ModelFile3, :begin => 45, :end => 66, :targets => [
550
+ {"file"=> File.expand_path(ModelFile3),
551
+ "line"=>2,
552
+ "display"=>"/StatemachineMM3/State [EClass]"}
553
+ ]
554
+ end
555
+
556
+ def test_reference_completion
557
+ setup_connector(ModelFile)
558
+ load_model
559
+ context = build_context <<-END
560
+ EPackage StatemachineMM {
561
+ EClass State, abstract: true {
562
+ EAttribute name, eType: |/StatemachineMM/StringType
563
+ END
564
+ assert_completions context, [
565
+ "/StatemachineMM/CompositeState",
566
+ "/StatemachineMM/SimpleState",
567
+ "/StatemachineMM/State",
568
+ "/StatemachineMM/StringType",
569
+ "/StatemachineMM/Transition",
570
+ "/StatemachineMM2/SimpleState",
571
+ "/StatemachineMM2/State",
572
+ ]
573
+ context = build_context <<-END
574
+ EPackage StatemachineMM {
575
+ EClass State, abstract: true {
576
+ EAttribute name, eType: /StatemachineMM/|StringType
577
+ END
578
+ assert_completions context, [
579
+ "/StatemachineMM/CompositeState",
580
+ "/StatemachineMM/SimpleState",
581
+ "/StatemachineMM/State",
582
+ "/StatemachineMM/StringType",
583
+ "/StatemachineMM/Transition",
584
+ "/StatemachineMM2/SimpleState",
585
+ "/StatemachineMM2/State",
586
+ ]
587
+ context = build_context <<-END
588
+ EPackage StatemachineMM {
589
+ EClass State, abstract: true {
590
+ EAttribute name, eType: /StatemachineMM/St|ringType
591
+ END
592
+ assert_completions context, [
593
+ "/StatemachineMM/CompositeState",
594
+ "/StatemachineMM/SimpleState",
595
+ "/StatemachineMM/State",
596
+ "/StatemachineMM/StringType",
597
+ "/StatemachineMM/Transition",
598
+ "/StatemachineMM2/SimpleState",
599
+ "/StatemachineMM2/State",
600
+ ]
601
+ context = build_context <<-END
602
+ EPackage StatemachineMM {
603
+ EClass State, abstract: true {
604
+ EAttribute name, eType: /StatemachineMM/StringType|
605
+ END
606
+ assert_completions context, [
607
+ "/StatemachineMM/CompositeState",
608
+ "/StatemachineMM/SimpleState",
609
+ "/StatemachineMM/State",
610
+ "/StatemachineMM/StringType",
611
+ "/StatemachineMM/Transition",
612
+ "/StatemachineMM2/SimpleState",
613
+ "/StatemachineMM2/State",
614
+ ]
615
+ end
616
+
617
+ def test_reference_completion_in_array
618
+ setup_connector(ModelFile)
619
+ load_model
620
+ context = build_context <<-END
621
+ EPackage StatemachineMM {
622
+ EClass State, abstract: true {
623
+ EAttribute name, eType: /StatemachineMM/StringType
624
+ EReference parent,
625
+ eType: /StatemachineMM/CompositeState,
626
+ eOpposite: /StatemachineMM/CompositeState/substates
627
+ }
628
+ EClass SimpleState, eSuperTypes: [|/StatemachineMM/State]
629
+ END
630
+ assert_completions context, [
631
+ "/StatemachineMM/CompositeState",
632
+ "/StatemachineMM/SimpleState",
633
+ "/StatemachineMM/State",
634
+ "/StatemachineMM/Transition",
635
+ "/StatemachineMM2/SimpleState",
636
+ "/StatemachineMM2/State",
637
+ ]
638
+ context = build_context <<-END
639
+ EPackage StatemachineMM {
640
+ EClass State, abstract: true {
641
+ EAttribute name, eType: /StatemachineMM/StringType
642
+ EReference parent,
643
+ eType: /StatemachineMM/CompositeState,
644
+ eOpposite: /StatemachineMM/CompositeState/substates
645
+ }
646
+ EClass SimpleState, eSuperTypes: [/StatemachineMM/S|tate]
647
+ END
648
+ assert_completions context, [
649
+ "/StatemachineMM/CompositeState",
650
+ "/StatemachineMM/SimpleState",
651
+ "/StatemachineMM/State",
652
+ "/StatemachineMM/Transition",
653
+ "/StatemachineMM2/SimpleState",
654
+ "/StatemachineMM2/State",
655
+ ]
656
+ context = build_context <<-END
657
+ EPackage StatemachineMM {
658
+ EClass State, abstract: true {
659
+ EAttribute name, eType: /StatemachineMM/StringType
660
+ EReference parent,
661
+ eType: /StatemachineMM/CompositeState,
662
+ eOpposite: /StatemachineMM/CompositeState/substates
663
+ }
664
+ EClass SimpleState, eSuperTypes: [/StatemachineMM/State|]
665
+ END
666
+ assert_completions context, [
667
+ "/StatemachineMM/CompositeState",
668
+ "/StatemachineMM/SimpleState",
669
+ "/StatemachineMM/State",
670
+ "/StatemachineMM/Transition",
671
+ "/StatemachineMM2/SimpleState",
672
+ "/StatemachineMM2/State",
673
+ ]
674
+ context = build_context <<-END
675
+ EPackage StatemachineMM {
676
+ EClass State, abstract: true {
677
+ EAttribute name, eType: /StatemachineMM/StringType
678
+ EReference parent,
679
+ eType: /StatemachineMM/CompositeState,
680
+ eOpposite: /StatemachineMM/CompositeState/substates
681
+ }
682
+ EClass SimpleState, eSuperTypes: [/StatemachineMM/State]|
683
+ END
684
+ assert_completions context, [
685
+ ]
686
+ end
687
+
688
+ def test_integer_completion
689
+ setup_connector(ModelFile)
690
+ load_model
691
+ context = build_context <<-END
692
+ EPackage StatemachineMM {
693
+ EClass State, abstract: true {
694
+ EAttribute name, eType: /StatemachineMM/StringType
695
+ EReference parent,
696
+ eType: /StatemachineMM/CompositeState,
697
+ eOpposite: /StatemachineMM/CompositeState/substates
698
+ }
699
+ EClass SimpleState, eSuperTypes: [/StatemachineMM/State]
700
+ EClass CompositeState,
701
+ eSuperTypes: [
702
+ /StatemachineMM/State
703
+ ],
704
+ abstract: false {
705
+ EReference substates, upperBound: |-1, containment: true, eType: /StatemachineMM/State, eOpposite: /StatemachineMM/State/parent
706
+ END
707
+ assert_completions context, [
708
+ "1",
709
+ ]
710
+ context = build_context <<-END
711
+ EPackage StatemachineMM {
712
+ EClass State, abstract: true {
713
+ EAttribute name, eType: /StatemachineMM/StringType
714
+ EReference parent,
715
+ eType: /StatemachineMM/CompositeState,
716
+ eOpposite: /StatemachineMM/CompositeState/substates
717
+ }
718
+ EClass SimpleState, eSuperTypes: [/StatemachineMM/State]
719
+ EClass CompositeState,
720
+ eSuperTypes: [
721
+ /StatemachineMM/State
722
+ ],
723
+ abstract: false {
724
+ EReference substates, upperBound: -1|, containment: true, eType: /StatemachineMM/State, eOpposite: /StatemachineMM/State/parent
725
+ END
726
+ assert_completions context, [
727
+ "1",
728
+ ]
729
+ end
730
+
731
+ def test_link_targets
732
+ setup_connector(ModelFile)
733
+ load_model
734
+ context = build_context <<-END
735
+ EPackage StatemachineMM {
736
+ EClass State, abstract: true {
737
+ EAttribute name, eType: /St|atemachineMM/StringType
738
+ END
739
+ assert_link_targets context, :begin => 29, :end => 54, :targets => [
740
+ {"file"=> File.expand_path(@infile),
741
+ "line"=>20,
742
+ "display"=>"/StatemachineMM/StringType [EDataType]"}
743
+ ]
744
+ context = build_context <<-END
745
+ EPackage StatemachineMM {
746
+ EClass State, abstract: true {
747
+ EAttribute name, eType: |/StatemachineMM/StringType
748
+ END
749
+ assert_link_targets context, :begin => 29, :end => 54, :targets => [
750
+ {"file"=> File.expand_path(@infile),
751
+ "line"=>20,
752
+ "display"=>"/StatemachineMM/StringType [EDataType]"}
753
+ ]
754
+ context = build_context <<-END
755
+ EPackage StatemachineMM {
756
+ EClass State, abstract: true {
757
+ EAttribute name, eType: /StatemachineMM/StringTyp|e
758
+ END
759
+ assert_link_targets context, :begin => 29, :end => 54, :targets => [
760
+ {"file"=> File.expand_path(@infile),
761
+ "line"=>20,
762
+ "display"=>"/StatemachineMM/StringType [EDataType]"}
763
+ ]
764
+ context = build_context <<-END
765
+ EPackage StatemachineMM {
766
+ EClass State, abstract: true {
767
+ EAttribute name, eType: /StatemachineMM/StringType|
768
+ END
769
+ assert_link_targets context, :begin => nil, :end => nil, :targets => []
770
+ context = build_context <<-END
771
+ EPackage StatemachineMM {
772
+ EClass State, abstract: true {
773
+ EAttribute name, eType:| /StatemachineMM/StringType
774
+ END
775
+ assert_link_targets context, :begin => nil, :end => nil, :targets => []
776
+ # backward ref
777
+ context = build_context <<-END
778
+ EPackage StatemachineMM {
779
+ E|Class State, abstract: true {
780
+ END
781
+ assert_link_targets context, :begin => 3, :end => 8, :targets => [
782
+ {"file"=> File.expand_path(@infile),
783
+ "line"=>8,
784
+ "display"=>"/StatemachineMM/SimpleState [EClass]"},
785
+ {"file"=> File.expand_path(@infile),
786
+ "line"=>9,
787
+ "display"=>"/StatemachineMM/CompositeState [EClass]"}
788
+ ]
789
+ context = build_context <<-END
790
+ EPackage StatemachineMM {
791
+ EClass State, abstract: true {
792
+ EAttribute name, eType: /StatemachineMM/StringType
793
+ EReference parent,
794
+ eType: /StatemachineMM/CompositeState,
795
+ eOpposite: /StatemachineMM/CompositeState/substates
796
+ }
797
+ |EClass SimpleState, eSuperTypes: [/StatemachineMM/State]
798
+ END
799
+ assert_link_targets context, :begin => 3, :end => 8, :targets => []
800
+ # bad location
801
+ context = build_context <<-END
802
+ EPackage S|tatemachineMM {
803
+ END
804
+ assert_link_targets context, :begin => 10, :end => 23, :targets => []
805
+ end
806
+
807
+ def test_link_targets_no_text_after_name
808
+ setup_connector(ModelFile)
809
+ load_model
810
+ context = build_context({:infile => ModelFile2}, <<-END
811
+ EPackage StatemachineMM2 {
812
+ ECl|ass State
813
+ END
814
+ )
815
+ assert_link_targets context, :file => ModelFile2, :begin => 3, :end => 8, :targets => [
816
+ {"file"=> File.expand_path(ModelFile2),
817
+ "line"=>3,
818
+ "display"=>"/StatemachineMM2/SimpleState [EClass]"}
819
+ ]
820
+ end
821
+
822
+ def test_link_targets_after_linebreak
823
+ setup_connector(ModelFile)
824
+ load_model
825
+ context = build_context <<-END
826
+ EPackage StatemachineMM {
827
+ EClass State, abstract: true {
828
+ EAttribute name, eType: /StatemachineMM/StringType
829
+ EReference parent,
830
+ eType: /St|atemachineMM/CompositeState,
831
+ END
832
+ # in case of linebreaks, the begin and end column refer to the string which
833
+ # was passed to the backend as the context; in this case the context extractor
834
+ # appends each broken line to the previous line with all the leading whitespace removed
835
+ assert_link_targets context, :begin => 37, :end => 66, :targets => [
836
+ {"file"=> File.expand_path(@infile),
837
+ "line"=>9,
838
+ "display"=>"/StatemachineMM/CompositeState [EClass]"}
839
+ ]
840
+ context = build_context <<-END
841
+ EPackage StatemachineMM {
842
+ EClass State, abstract: true {
843
+ EAttribute name, eType: /StatemachineMM/StringType
844
+ EReference parent,
845
+ eType: |/StatemachineMM/CompositeState,
846
+ END
847
+ assert_link_targets context, :begin => 37, :end => 66, :targets => [
848
+ {"file"=> File.expand_path(@infile),
849
+ "line"=>9,
850
+ "display"=>"/StatemachineMM/CompositeState [EClass]"}
851
+ ]
852
+ context = build_context <<-END
853
+ EPackage StatemachineMM {
854
+ EClass State, abstract: true {
855
+ EAttribute name, eType: /StatemachineMM/StringType
856
+ EReference parent,
857
+ eType: /StatemachineMM/CompositeStat|e,
858
+ END
859
+ assert_link_targets context, :begin => 37, :end => 66, :targets => [
860
+ {"file"=> File.expand_path(@infile),
861
+ "line"=>9,
862
+ "display"=>"/StatemachineMM/CompositeState [EClass]"}
863
+ ]
864
+ context = build_context <<-END
865
+ EPackage StatemachineMM {
866
+ EClass State, abstract: true {
867
+ EAttribute name, eType: /StatemachineMM/StringType
868
+ EReference parent,
869
+ eType: /StatemachineMM/CompositeState|,
870
+ END
871
+ assert_link_targets context, :begin => nil, :end => nil, :targets => []
872
+ end
873
+
874
+ def test_find_elements
875
+ setup_connector(ModelFile)
876
+ load_model
877
+ response = @con.execute_command(
878
+ {"command" => "find_elements", "search_pattern" => "Sta"})
879
+ assert_equal \
880
+ [{"display"=>"State [EClass] - /StatemachineMM",
881
+ "file"=> File.expand_path(@infile),
882
+ "line"=>2},
883
+ {"display"=>"State [EClass] - /StatemachineMM2",
884
+ "file"=> File.expand_path(ModelFile2),
885
+ "line"=>2},
886
+ {"display"=>"StatemachineMM [EPackage] - /StatemachineMM",
887
+ "file"=> File.expand_path(@infile),
888
+ "line"=>1},
889
+ {"display"=>"StatemachineMM2 [EPackage] - /StatemachineMM2",
890
+ "file"=> File.expand_path(ModelFile2),
891
+ "line"=>1}], response["elements"]
892
+ response = @con.execute_command(
893
+ {"command" => "find_elements", "search_pattern" => "target"})
894
+ assert_equal \
895
+ [{"display"=>"target [EReference] - /StatemachineMM/Transition",
896
+ "file"=> File.expand_path(@infile),
897
+ "line"=>17}], response["elements"]
898
+ response = @con.execute_command(
899
+ {"command" => "find_elements", "search_pattern" => ""})
900
+ assert_equal [], response["elements"]
901
+ response = @con.execute_command(
902
+ {"command" => "find_elements", "search_pattern" => "xxx"})
903
+ assert_equal [], response["elements"]
904
+ end
905
+
906
+ TestContext = Struct.new(:line, :col)
907
+
908
+ def build_context(text, text2=nil)
909
+ if text.is_a?(Hash)
910
+ context_lines = text2.split("\n")
911
+ pos_in_line = text[:col] || context_lines.last.index("|") + 1
912
+ infile = text[:infile] || @infile
913
+ else
914
+ context_lines = text.split("\n")
915
+ pos_in_line = context_lines.last.index("|") + 1
916
+ infile = @infile
917
+ end
918
+ context_lines.last.sub!("|", "")
919
+
920
+ # check that the context data actally matches the real file in the filesystem
921
+ content = File.open(infile, "rb"){|f| f.read}
922
+ ref_lines = content.split(/\r?\n/)[0..context_lines.size-1]
923
+ raise "inconsistent test data, expected\n:#{ref_lines.join("\n")}\ngot:\n#{context_lines.join("\n")}\n" \
924
+ unless ref_lines == context_lines
925
+
926
+ # column numbers start at 1
927
+ TestContext.new(context_lines.size, pos_in_line)
928
+ end
929
+
930
+ def assert_link_targets(context, options)
931
+ infile = options[:file] || @infile
932
+ content = File.open(infile, "rb") {|f| f.read}
933
+ lines = content.split(/\r?\n/)[0..context.line-1]
934
+ lines, col = RText::Frontend::Context.new.extract(lines, context.col)
935
+ response = @con.execute_command(
936
+ {"command" => "link_targets", "context" => lines, "column" => col})
937
+ assert_equal "response", response["type"]
938
+ assert_equal options[:targets], response["targets"]
939
+ if options[:begin]
940
+ assert_equal options[:begin], response["begin_column"]
941
+ else
942
+ assert_nil response["begin_column"]
943
+ end
944
+ if options[:end]
945
+ assert_equal options[:end], response["end_column"]
946
+ else
947
+ assert_nil response["end_column"]
948
+ end
949
+ end
950
+
951
+ def assert_completions(context, expected)
952
+ content = File.open(@infile, "rb"){|f| f.read}
953
+ lines = content.split(/\r?\n/)[0..context.line-1]
954
+ lines, col = RText::Frontend::Context.new.extract(lines, context.col)
955
+ response = @con.execute_command(
956
+ {"command" => "content_complete", "context" => lines, "column" => col})
957
+ assert_equal expected, response["options"].collect{|o| o["insert"]}
958
+ end
959
+
960
+ def load_model
961
+ done = false
962
+ response = nil
963
+ while !done
964
+ response = @con.execute_command({"command" => "load_model"})
965
+ if response == :connecting && !@connection_timeout
966
+ sleep(0.1)
967
+ else
968
+ done = true
969
+ end
970
+ end
971
+ response
972
+ end
973
+
974
+ end