delorean_lang 0.0.33

Sign up to get free protection for your applications and to get access to all the features.
data/spec/func_spec.rb ADDED
@@ -0,0 +1,192 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "Delorean" do
4
+
5
+ let(:engine) {
6
+ Delorean::Engine.new("ZZZ")
7
+ }
8
+
9
+ it "should handle MAX as a node name" do
10
+ engine.parse defn("MAX:",
11
+ " a = MAX(1, 2, 3, 0, -10)",
12
+ )
13
+
14
+ r = engine.evaluate("MAX", "a")
15
+ r.should == 3
16
+ end
17
+
18
+ it "should handle MAX" do
19
+ engine.parse defn("A:",
20
+ " a = MAX(1, 2, 3)",
21
+ )
22
+
23
+ r = engine.evaluate("A", "a")
24
+ r.should == 3
25
+ end
26
+
27
+ it "should handle insufficient args" do
28
+ lambda {
29
+ engine.parse defn("A:",
30
+ " a = MAX(1)",
31
+ )
32
+ }.should raise_error(Delorean::BadCallError)
33
+ end
34
+
35
+ it "should handle MIN" do
36
+ engine.parse defn("A:",
37
+ " a = MIN(1, 2, -3, 4)",
38
+ )
39
+
40
+ r = engine.evaluate("A", "a")
41
+ r.should == -3
42
+ end
43
+
44
+ it "should handle MAXLIST" do
45
+ engine.parse defn("A:",
46
+ " a = MAXLIST([1, 2, 3])",
47
+ )
48
+
49
+ engine.evaluate("A", "a").should == 3
50
+ end
51
+
52
+ it "should handle MINLIST" do
53
+ engine.parse defn("A:",
54
+ " a = MINLIST([1, 10, -3])",
55
+ )
56
+
57
+ engine.evaluate("A", "a").should == -3
58
+ end
59
+
60
+ it "should handle ROUND" do
61
+ engine.parse defn("A:",
62
+ " a = ROUND(12.3456, 2)",
63
+ " b = ROUND(12.3456, 1)",
64
+ " c = ROUND(12.3456)",
65
+ )
66
+
67
+ r = engine.evaluate_attrs("A", ["a", "b", "c"])
68
+ r.should == [12.35, 12.3, 12]
69
+ end
70
+
71
+ it "should handle TIMEPART" do
72
+ engine.parse defn("A:",
73
+ " p =?",
74
+ " p2 =?",
75
+ " h = TIMEPART(p, 'h')",
76
+ " m = TIMEPART(p, 'm')",
77
+ " s = TIMEPART(p, 's')",
78
+ " d = TIMEPART(p, 'd')",
79
+ " d2 = TIMEPART(p2, 'd')",
80
+ " h2 = TIMEPART(p2, 'h')",
81
+ )
82
+
83
+ p = Time.now
84
+ params = {"p" => p, "p2" => Float::INFINITY}
85
+ r = engine.evaluate_attrs("A", %w{h m s d d2}, params)
86
+ r.should == [p.hour, p.min, p.sec, p.to_date, Float::INFINITY]
87
+
88
+ expect { engine.evaluate_attrs("A", ["h2"], params) }.to raise_error
89
+
90
+ # Non time argument should raise an error
91
+ expect { engine.evaluate_attrs("A", ["m"], {"p" => 123}) }.to raise_error
92
+
93
+ end
94
+
95
+ it "should handle DATEPART" do
96
+ engine.parse defn("A:",
97
+ " p =?",
98
+ " y = DATEPART(p, 'y')",
99
+ " d = DATEPART(p, 'd')",
100
+ " m = DATEPART(p, 'm')",
101
+ )
102
+
103
+ p = Date.today
104
+ r = engine.evaluate_attrs("A", ["y", "d", "m"], {"p" => p})
105
+ r.should == [p.year, p.day, p.month]
106
+
107
+ # Non date argument should raise an error
108
+ expect { engine.evaluate_attrs("A", ["y", "d", "m"], {"p" => 123}) }.to raise_error
109
+ # Invalid part argument should raise an error
110
+ engine.reset
111
+ engine.parse defn("A:",
112
+ " p =?",
113
+ " x = DATEPART(p, 'x')",
114
+ )
115
+ expect { engine.evaluate_attrs("A", ["x"], {"p" => p}) }.to raise_error
116
+ end
117
+
118
+ it "should handle DATEADD" do
119
+ engine.parse defn("A:",
120
+ " p =?",
121
+ " y = DATEADD(p, 1, 'y')",
122
+ " d = DATEADD(p, 30, 'd')",
123
+ " m = DATEADD(p, 2, 'm')",
124
+ )
125
+
126
+ p = Date.today
127
+ r = engine.evaluate_attrs("A", ["y", "d", "m"], {"p" => p})
128
+ r.should == [p + 1.years, p + 30.days, p + 2.months]
129
+
130
+ # Non date argument should raise an error
131
+ expect { engine.evaluate_attrs("A", ["y", "d", "m"], {"p" => 123}) }.to raise_error
132
+
133
+ # Invalid interval argument should raise an error
134
+ engine.reset
135
+ engine.parse defn("A:",
136
+ " p =?",
137
+ " m = DATEADD(p, 1.3, 'm')",
138
+ )
139
+ expect { engine.evaluate_attrs("A", ["m"], {"p" => p}) }.to raise_error
140
+
141
+ # Invalid part argument should raise an error
142
+ engine.reset
143
+ engine.parse defn("A:",
144
+ " p =?",
145
+ " x = DATEADD(p, 1, 'x')",
146
+ )
147
+ expect { engine.evaluate_attrs("A", ["x"], {"p" => p}) }.to raise_error
148
+ end
149
+
150
+ it "should handle INDEX" do
151
+ engine.parse defn("A:",
152
+ " a = [INDEX([0, 11, 22, 33], i) for i in [1,2]]",
153
+ )
154
+
155
+ engine.evaluate("A", "a").should == [11,22]
156
+ end
157
+
158
+ it "should handle FLATTEN" do
159
+ x = [[1,2,[3]], 4, 5, [6]]
160
+
161
+ engine.parse defn("A:",
162
+ " a = #{x}",
163
+ " b = FLATTEN(a) + FLATTEN(a, 1)"
164
+ )
165
+
166
+ engine.evaluate("A", "b").should == x.flatten + x.flatten(1)
167
+ end
168
+
169
+ it "should handle ERR" do
170
+ engine.parse defn("A:",
171
+ " a = ERR('hello')",
172
+ " b = ERR('xx', 1, 2, 3)",
173
+ )
174
+
175
+ expect { engine.evaluate("A", "a") }.to raise_error('hello')
176
+
177
+ lambda {
178
+ r = engine.evaluate("A", "b")
179
+ }.should raise_error("xx, 1, 2, 3")
180
+
181
+ end
182
+
183
+ it "should handle SYM" do
184
+ engine.parse defn("S:",
185
+ ' a = TOSYM("hello")',
186
+ )
187
+
188
+ r = engine.evaluate("S", "a")
189
+ r.should == :hello
190
+ end
191
+
192
+ end
@@ -0,0 +1,688 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "Delorean" do
4
+
5
+ let(:engine) {
6
+ Delorean::Engine.new "YYY"
7
+ }
8
+
9
+ let(:sset) {
10
+ TestContainer.new({
11
+ ["AAA", "0001"] =>
12
+ defn("X:",
13
+ " a = 123",
14
+ " b = a",
15
+ )
16
+ })
17
+ }
18
+
19
+ it "can parse very simple calls" do
20
+ engine.parse defn("X:",
21
+ " a = 123",
22
+ " b = a",
23
+ )
24
+ end
25
+
26
+ it "can parse simple expressions - 1" do
27
+ engine.parse defn("A:",
28
+ " a = 123",
29
+ " x = -(a*2)",
30
+ " b = -(a + 1)",
31
+ )
32
+ end
33
+
34
+ it "can parse simple expressions - 2" do
35
+ engine.parse defn("A:",
36
+ " a = 1 + 2 * -3 - -4",
37
+ )
38
+ end
39
+
40
+ it "can parse params" do
41
+ engine.parse defn("A:",
42
+ " a =?",
43
+ " b =? a*2",
44
+ )
45
+ end
46
+
47
+ it "should accept default param definitions" do
48
+ lambda {
49
+ engine.parse defn("A:",
50
+ " b =? 1",
51
+ " c =? -1.1",
52
+ " d = b + c",
53
+ )
54
+ }.should_not raise_error
55
+ end
56
+
57
+ it "gives errors with attrs not in node" do
58
+ lambda {
59
+ engine.parse defn("a = 123",
60
+ "b = a * 2",
61
+ )
62
+ }.should raise_error(Delorean::ParseError)
63
+ end
64
+
65
+ it "should disallow .<digits> literals" do
66
+ lambda {
67
+ engine.parse defn("A:",
68
+ " a = .123",
69
+ )
70
+ }.should raise_error(Delorean::ParseError)
71
+ end
72
+
73
+ it "should disallow bad attr names" do
74
+ lambda {
75
+ engine.parse defn("A:",
76
+ " B = 1",
77
+ )
78
+ }.should raise_error(Delorean::ParseError)
79
+
80
+ engine.reset
81
+
82
+ lambda {
83
+ engine.parse defn("A:",
84
+ " _b = 1",
85
+ )
86
+ }.should raise_error(Delorean::ParseError)
87
+ end
88
+
89
+ it "should disallow bad node names" do
90
+ lambda {
91
+ engine.parse defn("a:",
92
+ )
93
+ }.should raise_error(Delorean::ParseError)
94
+
95
+ engine.reset
96
+
97
+ lambda {
98
+ engine.parse defn("_A:",
99
+ )
100
+ }.should raise_error(Delorean::ParseError)
101
+ end
102
+
103
+ it "should disallow recursion" do
104
+ lambda {
105
+ engine.parse defn("A:",
106
+ " a = 1",
107
+ "B: A",
108
+ " a = a + 1",
109
+ )
110
+ }.should raise_error(Delorean::RecursionError)
111
+
112
+ engine.reset
113
+
114
+ lambda {
115
+ engine.parse defn("A:",
116
+ " a = 1",
117
+ "B: A",
118
+ " b = a",
119
+ " a = b",
120
+ )
121
+ }.should raise_error(Delorean::RecursionError)
122
+
123
+ end
124
+
125
+ it "should allow non-recursive code 1" do
126
+ # this is not a recursion error
127
+ engine.parse defn("A:",
128
+ " a = 1",
129
+ " b = 2",
130
+ "B: A",
131
+ " a = A.b",
132
+ " b = a",
133
+ )
134
+
135
+ end
136
+
137
+ it "should allow non-recursive code 2" do
138
+ engine.parse defn("A:",
139
+ " a = 1",
140
+ " b = 2",
141
+ "B: A",
142
+ " a = A.b",
143
+ " b = A.b + B.a",
144
+ )
145
+ end
146
+
147
+ it "should allow non-recursive code 3" do
148
+ engine.parse defn("A:",
149
+ " b = 2",
150
+ " a = A.b + A.b",
151
+ " c = a + b + a + b",
152
+ )
153
+ end
154
+
155
+ it "should check for recursion with default params 1" do
156
+ lambda {
157
+ engine.parse defn("A:",
158
+ " a =? a",
159
+ )
160
+ }.should raise_error(Delorean::UndefinedError)
161
+ end
162
+
163
+ it "should check for recursion with default params 2" do
164
+ lambda {
165
+ engine.parse defn("A:",
166
+ " a = 1",
167
+ "B: A",
168
+ " b =? a",
169
+ " a =? b",
170
+ )
171
+ }.should raise_error(Delorean::RecursionError)
172
+ end
173
+
174
+ it "gives errors for attrs defined more than once in a node" do
175
+ lambda {
176
+ engine.parse defn("B:",
177
+ " b = 1 + 1",
178
+ " b = 123",
179
+ )
180
+ }.should raise_error(Delorean::RedefinedError)
181
+
182
+ engine.reset
183
+
184
+ lambda {
185
+ engine.parse defn("B:",
186
+ " b =?",
187
+ " b = 123",
188
+ )
189
+ }.should raise_error(Delorean::RedefinedError)
190
+
191
+ engine.reset
192
+
193
+ lambda {
194
+ engine.parse defn("B:",
195
+ " b =? 22",
196
+ " b = 123",
197
+ )
198
+ }.should raise_error(Delorean::RedefinedError)
199
+ end
200
+
201
+ it "should raise error for nodes defined more than once" do
202
+ lambda {
203
+ engine.parse defn("B:",
204
+ " b =?",
205
+ "B:",
206
+ )
207
+ }.should raise_error(Delorean::RedefinedError)
208
+
209
+ engine.reset
210
+
211
+ lambda {
212
+ engine.parse defn("B:",
213
+ "A:",
214
+ "B:",
215
+ )
216
+ }.should raise_error(Delorean::RedefinedError)
217
+ end
218
+
219
+ it "should not be valid to derive from undefined nodes" do
220
+ lambda {
221
+ engine.parse defn("A: B",
222
+ " a = 456 * 123",
223
+ )
224
+ }.should raise_error(Delorean::UndefinedError)
225
+ end
226
+
227
+ it "should not be valid to use an undefined attr" do
228
+ lambda {
229
+ engine.parse defn("A:",
230
+ " a = 456 * 123",
231
+ "B: A",
232
+ " b = a",
233
+ " c = d",
234
+ )
235
+ }.should raise_error(Delorean::UndefinedError)
236
+ end
237
+
238
+ it "should be able to use ruby keywords as identifier" do
239
+ lambda {
240
+ engine.parse defn("A:",
241
+ " in = 123",
242
+ )
243
+ }.should_not raise_error
244
+
245
+ engine.reset
246
+
247
+ lambda {
248
+ engine.parse defn("B:",
249
+ " in1 = 123",
250
+ )
251
+ }.should_not raise_error
252
+
253
+ engine.reset
254
+
255
+ lambda {
256
+ engine.parse defn("C:",
257
+ " ifx = 123",
258
+ " elsey = ifx + 1",
259
+ )
260
+ }.should_not raise_error
261
+
262
+ engine.reset
263
+
264
+ lambda {
265
+ engine.parse defn("D:",
266
+ " true = false",
267
+ )
268
+ }.should_not raise_error
269
+
270
+ engine.reset
271
+
272
+ lambda {
273
+ engine.parse defn("E:",
274
+ " a = 1",
275
+ " return=a",
276
+ )
277
+ }.should_not raise_error
278
+ end
279
+
280
+ it "should be able to chain method calls on model functions" do
281
+ lambda {
282
+ engine.parse defn("A:",
283
+ " b = Dummy.i_just_met_you('CRJ', 123).name"
284
+ )
285
+ }.should_not raise_error
286
+ end
287
+
288
+ it "should be able to call class methods on ActiveRecord classes" do
289
+ engine.parse defn("A:",
290
+ " b = Dummy.call_me_maybe()",
291
+ )
292
+ end
293
+
294
+ it "shouldn't be able to call ActiveRecord methods without signature" do
295
+ lambda {
296
+ engine.parse defn("A:",
297
+ " b = Dummy.this_is_crazy()",
298
+ )
299
+ }.should raise_error(Delorean::UndefinedFunctionError)
300
+ end
301
+
302
+ it "should be able to call class methods on ActiveRecord classes in modules" do
303
+ engine.parse defn("A:",
304
+ " b = M::LittleDummy.heres_my_number(867, 5309)",
305
+ )
306
+ end
307
+
308
+ it "should be able to override parameters with attribute definitions" do
309
+ engine.parse defn("A:",
310
+ " b =? 22",
311
+ "B: A",
312
+ " b = 123",
313
+ "C: B",
314
+ " b =? 11",
315
+ )
316
+ end
317
+
318
+ it "should raise error on node attr access without all needed params" do
319
+ pending
320
+ end
321
+
322
+ it "should be able to access derived attrs" do
323
+ engine.parse defn("A:",
324
+ " b =? 22",
325
+ "B: A",
326
+ " c = b * 123",
327
+ "C: B",
328
+ " d =? c * b + 11",
329
+ )
330
+ end
331
+
332
+ it "should not be able to access attrs not defined in ancestors" do
333
+ lambda {
334
+ engine.parse defn("A:",
335
+ " b =? 22",
336
+ "B: A",
337
+ " c = b * 123",
338
+ "C: A",
339
+ " d =? c * b + 11",
340
+ )
341
+ }.should raise_error(Delorean::UndefinedError)
342
+ end
343
+
344
+ it "should be able to access specific node attrs " do
345
+ engine.parse defn("A:",
346
+ " b = 123",
347
+ " c = A.b",
348
+ )
349
+
350
+ engine.reset
351
+
352
+ engine.parse defn("A:",
353
+ " b = 123",
354
+ "B: A",
355
+ " b = 111",
356
+ " c = A.b * 123",
357
+ " d = B.b",
358
+ )
359
+ end
360
+
361
+ it "should be able to perform arbitrary getattr" do
362
+ engine.parse defn("A:",
363
+ " b = 22",
364
+ " c = b.x.y.z",
365
+ )
366
+
367
+ engine.reset
368
+
369
+ lambda {
370
+ engine.parse defn("B:",
371
+ " c = b.x.y.z",
372
+ )
373
+ }.should raise_error(Delorean::UndefinedError)
374
+
375
+ end
376
+
377
+ it "should handle lines with comments" do
378
+ engine.parse defn("A: # kaka",
379
+ " b = 22 # testing #",
380
+ " c = b",
381
+ )
382
+ end
383
+
384
+ it "should be able to report error line during parse" do
385
+ begin
386
+ engine.parse defn("A:",
387
+ " b = 123",
388
+ "B: .A",
389
+ )
390
+ rescue => exc
391
+ end
392
+
393
+ exc.module_name.should == "YYY"
394
+ exc.line.should == 3
395
+
396
+ engine.reset
397
+
398
+ begin
399
+ engine.parse defn("A:",
400
+ " b = 3 % b",
401
+ )
402
+ rescue => exc
403
+ end
404
+
405
+ exc.module_name.should == "YYY"
406
+ exc.line.should == 2
407
+ end
408
+
409
+ it "should raise error on malformed string" do
410
+ lambda {
411
+ engine.parse defn("A:",
412
+ ' d = "testing"" ',
413
+ )
414
+ }.should raise_error(Delorean::ParseError)
415
+ end
416
+
417
+ it "should not allow inherited ruby methods as attrs" do
418
+ lambda {
419
+ engine.parse defn("A:",
420
+ " a = name",
421
+ )
422
+ }.should raise_error(Delorean::UndefinedError)
423
+
424
+ engine.reset
425
+
426
+ lambda {
427
+ engine.parse defn("A:",
428
+ " a = new",
429
+ )
430
+ }.should raise_error(Delorean::UndefinedError)
431
+ end
432
+
433
+ it "should be able to parse lists" do
434
+ engine.parse defn("A:",
435
+ " b = []",
436
+ " c = [1,2,3]",
437
+ " d = [b, c, b, c, 1, 2, '123', 1.1]",
438
+ " e = [1, 1+1, 1+1+1]",
439
+ )
440
+
441
+ engine.reset
442
+
443
+ lambda {
444
+ engine.parse defn("A:",
445
+ " a = [",
446
+ )
447
+ }.should raise_error(Delorean::ParseError)
448
+
449
+ engine.reset
450
+
451
+ lambda {
452
+ engine.parse defn("A:",
453
+ " a = []-",
454
+ )
455
+ }.should raise_error(Delorean::ParseError)
456
+
457
+ end
458
+
459
+ it "should handle trailing ',' with lists" do
460
+ engine.parse defn("A:",
461
+ " b = [1,2,3,]",
462
+ )
463
+
464
+ engine.reset
465
+
466
+ lambda {
467
+ engine.parse defn("A:",
468
+ " a = [,]",
469
+ )
470
+ }.should raise_error(Delorean::ParseError)
471
+
472
+ engine.reset
473
+
474
+ lambda {
475
+ engine.parse defn("A:",
476
+ " a = [1,2,,]",
477
+ )
478
+ }.should raise_error(Delorean::ParseError)
479
+ end
480
+
481
+ it "should be able to parse hashes" do
482
+ engine.parse defn("A:",
483
+ " b = {}",
484
+ " c = {'a':1, 'b': 2, 'c':-3}",
485
+ " d = [{1:11}, {2: 22}]",
486
+ )
487
+
488
+ engine.reset
489
+
490
+ lambda {
491
+ engine.parse defn("A:",
492
+ " a = {",
493
+ )
494
+ }.should raise_error(Delorean::ParseError)
495
+
496
+ engine.reset
497
+
498
+ lambda {
499
+ engine.parse defn("A:",
500
+ " a = {}+",
501
+ )
502
+ }.should raise_error(Delorean::ParseError)
503
+ end
504
+
505
+ it "should handle trailing ',' with hashes" do
506
+ engine.parse defn("A:",
507
+ " b = {-1:1,}",
508
+ )
509
+
510
+ engine.reset
511
+
512
+ lambda {
513
+ engine.parse defn("A:",
514
+ " a = {,}",
515
+ )
516
+ }.should raise_error(Delorean::ParseError)
517
+
518
+ engine.reset
519
+
520
+ lambda {
521
+ engine.parse defn("A:",
522
+ " a = {-1:1,,}",
523
+ )
524
+ }.should raise_error(Delorean::ParseError)
525
+ end
526
+
527
+ it "should be able to parse list operations " do
528
+ engine.parse defn("A:",
529
+ " b = [] + []",
530
+ )
531
+ end
532
+
533
+ it "should parse list comprehension" do
534
+ engine.parse defn("A:",
535
+ " b = [123 for i in 123]",
536
+ )
537
+
538
+ end
539
+
540
+ it "should parse list comprehension (2)" do
541
+ engine.parse defn("A:",
542
+ " b = [i+1 for i in [1,2,3]]",
543
+ )
544
+
545
+ end
546
+
547
+ it "should parse nested list comprehension" do
548
+ engine.parse defn("A:",
549
+ " b = [[a+c for c in [4,5]] for a in [1,2,3]]",
550
+ )
551
+
552
+ end
553
+
554
+ it "should accept list comprehension variable override" do
555
+ engine.parse defn("A:",
556
+ " b = [b+1 for b in [1,2,3]]",
557
+ )
558
+ end
559
+
560
+ it "should accept list comprehension variable override (2)" do
561
+ engine.parse defn("A:",
562
+ " a = 1",
563
+ " b = [a+1 for a in [1,2,3]]",
564
+ )
565
+ end
566
+
567
+ it "errors out on bad list comprehension" do
568
+ lambda {
569
+ engine.parse defn("A:",
570
+ " b = [i+1 for x in [1,2,3]]",
571
+ )
572
+ }.should raise_error(Delorean::UndefinedError)
573
+ engine.reset
574
+
575
+ lambda {
576
+ engine.parse defn("A:",
577
+ " a = [123 for b in b]",
578
+ )
579
+ }.should raise_error(Delorean::UndefinedError)
580
+ engine.reset
581
+
582
+ # disallow nested comprehension var reuse
583
+ lambda {
584
+ engine.parse defn("A:",
585
+ " b = [[a+1 for a in [4,5]] for a in [1,2,3]]",
586
+ )
587
+ }.should raise_error(Delorean::RedefinedError)
588
+ engine.reset
589
+ end
590
+
591
+ it "should parse module calls" do
592
+ engine.parse defn("A:",
593
+ " a = 123",
594
+ " b = 456 + a",
595
+ " n = 'A'",
596
+ " c = @('a', 'b', x: 123, y: 456)",
597
+ " d = @n('a', 'b', x: 123, y: 456)",
598
+ )
599
+ end
600
+
601
+ it "should parse module calls by node name" do
602
+ engine.parse defn("A:",
603
+ " a = 123",
604
+ " d = @A('a')",
605
+ )
606
+ end
607
+
608
+ it "should parse multiline attr defs" do
609
+ engine.parse defn("A:",
610
+ " a = [1,",
611
+ " 2,",
612
+ " 3]",
613
+ " b = 456",
614
+ )
615
+ end
616
+
617
+ it "should give proper errors on parse multiline attr defs" do
618
+ begin
619
+ engine.parse defn("A:",
620
+ " a = [1,",
621
+ " 2,",
622
+ " 3];",
623
+ " b = 456",
624
+ )
625
+ raise "fail"
626
+ rescue Delorean::ParseError => exc
627
+ exc.line.should == 2
628
+ end
629
+ end
630
+
631
+ it "should give proper errors when multiline error falls off the end" do
632
+ begin
633
+ engine.parse defn("A:",
634
+ " x = 123",
635
+ " a = 1 +",
636
+ " 2 +",
637
+ )
638
+ raise "fail"
639
+ rescue Delorean::ParseError => exc
640
+ exc.line.should == 3
641
+ end
642
+ end
643
+
644
+ it "should parse imports" do
645
+ engine.parse defn("import AAA 0001",
646
+ "A:",
647
+ " b = 456",
648
+ "B: AAA::X",
649
+ ), sset
650
+
651
+ end
652
+
653
+ it "should disallow import loops" do
654
+ pending
655
+ sset.merge({
656
+ ["BBB", "0001"] =>
657
+ defn("import AAA 0001",
658
+ "import CCC 0001",
659
+ ),
660
+ ["CCC", "0001"] =>
661
+ defn("import BBB 0001",
662
+ ),
663
+ })
664
+ sset.get_engine("CCC", "0001")
665
+ end
666
+
667
+ it "should disallow multiple versions of same script" do
668
+ sset.merge({
669
+ ["AAA", "0002"] =>
670
+ defn("A:",
671
+ ),
672
+ ["BBB", "0001"] =>
673
+ defn("import AAA 0001",
674
+ ),
675
+ ["CCC", "0001"] =>
676
+ defn("import BBB 0001",
677
+ "import AAA 0002",
678
+ ),
679
+ })
680
+ begin
681
+ sset.get_engine("CCC", "0001")
682
+ rescue Delorean::ImportError => exc
683
+ exc.line.should == 2
684
+ end
685
+ end
686
+
687
+ end
688
+