rtext 0.8.0 → 0.9.1

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