rtext 0.8.0 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,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