OILS / spec / ysh-builtin-module.test.sh View on Github | oilshell.org

500 lines, 217 significant
1## oils_failures_allowed: 3
2
3#### source-guard is an old way of preventing redefinition - could remove it
4shopt --set ysh:upgrade
5
6source-guard 'main' || return 0
7source $REPO_ROOT/spec/testdata/module/common.ysh
8source $REPO_ROOT/spec/testdata/module/module1.ysh
9## STDOUT:
10common
11module1
12## END
13
14#### is-main
15
16# This sources lib.ysh
17$SH $REPO_ROOT/spec/testdata/module/main.ysh
18
19# Run it directly
20$SH $REPO_ROOT/spec/testdata/module/lib.ysh
21
22## STDOUT:
23lib.ysh is not the main module
24hi from main.ysh
25hi from lib.ysh
26## END
27
28#### is-main with -c and stdin
29
30$SH -c 'echo -c; is-main; echo status=$?'
31
32echo 'echo stdin; is-main; echo status=$?' | $SH
33
34## STDOUT:
35-c
36status=0
37stdin
38status=0
39## END
40
41#### is-main with use/modules
42shopt --set ysh:upgrade
43
44use $REPO_ROOT/spec/testdata/module2/main.ysh
45$SH $REPO_ROOT/spec/testdata/module2/main.ysh
46
47## STDOUT:
48main.ysh is not the main module
49hi from main.ysh
50## END
51
52#### use builtin usage
53
54use
55echo no-arg=$?
56
57use foo
58echo one-arg=$?
59
60use --extern foo
61echo extern=$?
62
63use --bad-flag
64echo bad-flag=$?
65
66use too many
67echo too-many=$?
68
69use ///no-builtin
70echo no-builtin=$?
71
72## STDOUT:
73no-arg=2
74one-arg=1
75extern=0
76bad-flag=2
77too-many=2
78no-builtin=1
79## END
80
81#### use usage with --pick etc.
82#shopt --set ysh:upgrade
83
84use foo --bad-flag
85echo bad-flag=$?
86
87use foo --all-provided zz
88echo all-provided=$?
89
90use foo --all-for-testing zz
91echo all-for-testing=$?
92
93echo
94
95use $REPO_ROOT/spec/testdata/module2/cycle1.ysh --pick
96echo no-picked=$?
97
98use $REPO_ROOT/spec/testdata/module2/cycle1.ysh --pick c1 c1
99echo picked=$?
100
101
102## STDOUT:
103bad-flag=2
104all-provided=2
105all-for-testing=2
106
107no-picked=2
108picked=0
109## END
110
111#### use --extern is a no-op, for static analysis
112
113use --extern grep sed awk
114echo status=$?
115
116use --extern zzz
117echo status=$?
118
119## STDOUT:
120status=0
121status=0
122## END
123
124#### use foo.ysh creates a value.Obj, and it's cached on later invocations
125
126shopt --set ysh:upgrade
127
128var caller_no_leak = 42
129
130use $REPO_ROOT/spec/testdata/module2/util.ysh
131
132# This is a value.Obj
133pp test_ (['util', util])
134var id1 = vm.id(util)
135
136var saved_util = util
137
138use $REPO_ROOT/spec/testdata/module2/util.ysh
139pp test_ (['repeated', util])
140var id2 = vm.id(util)
141
142# Create a symlink to test normalization
143
144ln -s $REPO_ROOT/spec/testdata/module2/util.ysh symlink.ysh
145
146use symlink.ysh
147pp test_ (['symlink', symlink])
148var id3 = vm.id(symlink)
149
150#pp test_ ([id1, id2, id3])
151
152# Make sure they are all the same object
153assert [id1 === id2]
154assert [id2 === id3]
155
156# Doesn't leak from util.ysh
157echo "setvar_noleak $[getVar('setvar_noleak')]"
158echo "setglobal_noleak $[getVar('setglobal_noleak')]"
159
160## STDOUT:
161caller_no_leak = null
162(List) ["util",("MY_INTEGER":42,"log":<Proc>,"die":<Proc>,"setvar_noleak":"util.ysh","setglobal_noleak":"util.ysh","invokableObj":("x":3,"y":4) --> ("__invoke__":<Proc>)) --> ("__invoke__":<BuiltinProc>)]
163(List) ["repeated",("MY_INTEGER":42,"log":<Proc>,"die":<Proc>,"setvar_noleak":"util.ysh","setglobal_noleak":"util.ysh","invokableObj":("x":3,"y":4) --> ("__invoke__":<Proc>)) --> ("__invoke__":<BuiltinProc>)]
164(List) ["symlink",("MY_INTEGER":42,"log":<Proc>,"die":<Proc>,"setvar_noleak":"util.ysh","setglobal_noleak":"util.ysh","invokableObj":("x":3,"y":4) --> ("__invoke__":<Proc>)) --> ("__invoke__":<BuiltinProc>)]
165setvar_noleak null
166setglobal_noleak null
167## END
168
169#### procs in a module can call setglobal on globals in that module
170shopt --set ysh:upgrade
171
172use $REPO_ROOT/spec/testdata/module2/globals.ysh
173
174# get() should work on Obj too. Possibly we should get rid of the default
175var myproc = get(propView(globals), 'mutate-g1', null)
176call setVar('mutate-g1', myproc)
177
178# you can mutate it internally, but the mutation isn't VISIBLE. GAH!
179# I wonder if you make Cell a value? or something
180mutate-g1
181echo
182
183# PROBLEM: This is a value.Obj COPY, not the fucking original!!!
184# immutable objects??
185
186#pp test_ ([vm.id(globals.d), globals.d])
187
188call globals.mutateG2()
189echo
190
191#= propView(globals)
192
193# these are not provided
194echo "globals.g1 = $[get(globals, 'g1', null)]"
195echo "globals.g2 = $[get(globals, 'g2', null)]"
196echo
197
198#pp frame_vars_
199# Shouldn't appear here
200echo "importer g1 = $[getVar('g1')]"
201echo "importer g2 = $[getVar('g2')]"
202
203## STDOUT:
204g1 = g1
205g1 = proc mutated
206
207g2 = g2
208g2 = func mutated
209
210globals.g1 = null
211globals.g2 = null
212
213importer g1 = null
214importer g2 = null
215## END
216
217#### no provided names
218shopt --set ysh:upgrade
219
220use $REPO_ROOT/spec/testdata/module2/no-provide.ysh
221
222## status: 1
223## STDOUT:
224## END
225
226#### bad provide type
227shopt --set ysh:upgrade
228
229use $REPO_ROOT/spec/testdata/module2/bad-provide-type.ysh
230
231echo 'should not get here'
232
233## status: 1
234## STDOUT:
235## END
236
237#### invalid provide entries
238shopt --set ysh:upgrade
239
240use $REPO_ROOT/spec/testdata/module2/bad-provide.ysh
241
242echo 'should not get here'
243
244## status: 1
245## STDOUT:
246## END
247
248#### use foo.ysh creates a value.Obj with __invoke__
249shopt --set ysh:upgrade
250
251use $REPO_ROOT/spec/testdata/module2/util.ysh
252
253# This is a value.Obj
254#pp test_ (util)
255
256util log 'hello'
257util die 'hello there'
258
259## STDOUT:
260caller_no_leak = null
261log hello
262die hello there
263## END
264
265#### module itself is invokable Obj, which can contain invokable obj!
266shopt --set ysh:upgrade
267
268use $REPO_ROOT/spec/testdata/module2/util.ysh
269
270util invokableObj (1)
271
272# Usage error
273#util invokableObj
274
275## STDOUT:
276caller_no_leak = null
277sum = 8
278## END
279
280#### argument binding test
281shopt --set ysh:upgrade
282
283use $REPO_ROOT/spec/testdata/module2/util2.ysh
284
285util2 echo-args w1 w2 w3 w4 (3, 4, 5, 6, n1=7, n2=8, n3=9) {
286 echo hi
287}
288
289echo ---
290
291util2 echo-args w1 w2 (3, 4, n3=9) {
292 echo hi
293}
294
295## STDOUT:
296(List) ["w1","w2"]
297(List) ["w3","w4"]
298
299(List) [3,4]
300(List) [5,6]
301
302(List) [7,8]
303(Dict) {"n3":9}
304
305<Command>
306---
307(List) ["w1","w2"]
308(List) []
309
310(List) [3,4]
311(List) []
312
313(List) [42,43]
314(Dict) {"n3":9}
315
316<Command>
317## END
318
319#### module-with-hyphens
320shopt --set ysh:upgrade
321
322use $REPO_ROOT/spec/testdata/module2/for-xtrace.ysh
323
324for-xtrace increment
325
326var mod = getVar('for-xtrace')
327pp test_ (mod.counter)
328
329## STDOUT:
330[for-xtrace]
331counter = 5
332counter = 6
333(Int) 6
334## END
335
336
337#### modules can access __builtins__ directly
338shopt --set ysh:upgrade
339
340use $REPO_ROOT/spec/testdata/module2/builtins.ysh
341
342var mylen = builtins.mylen
343
344pp test_ (mylen([3,4,5]))
345
346## STDOUT:
347(Int) 3
348## END
349
350#### use may only be used a TOP level, not within proc
351shopt --set ysh:upgrade
352
353proc use-it {
354 use $REPO_ROOT/spec/testdata/module2/builtins.ysh
355}
356
357use-it
358
359## status: 2
360## STDOUT:
361## END
362
363#### Mutable variables are frozen - beware!
364
365shopt --set ysh:upgrade
366
367use $REPO_ROOT/spec/testdata/module2/for-xtrace.ysh
368
369for-xtrace increment
370
371var mod = getVar('for-xtrace')
372pp test_ (mod.counter)
373
374for-xtrace increment
375
376pp test_ (mod.counter)
377
378for-xtrace increment
379
380## STDOUT:
381[for-xtrace]
382counter = 5
383counter = 6
384(Int) 6
385counter = 7
386(Int) 6
387counter = 8
388## END
389
390#### module invoked without any arguments is an error
391shopt --set ysh:upgrade
392
393use $REPO_ROOT/spec/testdata/module2/util.ysh
394
395util
396
397## status: 2
398## STDOUT:
399caller_no_leak = null
400## END
401
402#### module invoked with nonexistent name is error
403shopt --set ysh:upgrade
404
405use $REPO_ROOT/spec/testdata/module2/util.ysh
406
407util zzz
408
409## status: 2
410## STDOUT:
411caller_no_leak = null
412## END
413
414#### circular import doesn't result in infinite loop, or crash
415
416use $REPO_ROOT/spec/testdata/module2/cycle1.ysh
417
418# These use each other
419use $REPO_ROOT/spec/testdata/module2/cycle2.ysh
420
421pp test_ (cycle1)
422pp test_ (cycle2)
423
424echo hi
425
426## STDOUT:
427(Obj) ("c1":"c1") --> ("__invoke__":<BuiltinProc>)
428(Obj) ("c2":"c2") --> ("__invoke__":<BuiltinProc>)
429hi
430## END
431
432#### Module with parse error
433
434shopt --set ysh:upgrade
435
436use $REPO_ROOT/spec/testdata/module2/parse-error.ysh
437
438echo 'should not get here'
439
440## status: 2
441## STDOUT:
442## END
443
444#### Module with runtime error
445
446shopt --set ysh:upgrade
447
448use $REPO_ROOT/spec/testdata/module2/runtime-error.ysh
449
450echo 'should not get here'
451
452## status: 1
453## STDOUT:
454runtime-error before
455## END
456
457#### user can inspect __modules__ cache
458
459echo 'TODO: Dict view of realpath() string -> Obj instance'
460
461## STDOUT:
462## END
463
464#### use foo.ysh --pick a b
465
466use $REPO_ROOT/spec/testdata/module2/builtins.ysh --pick mylen mylen2
467
468pp test_ (mylen([3,4,5]))
469
470pp test_ (mylen2([4,5]))
471
472## STDOUT:
473(Int) 3
474(Int) 2
475## END
476
477#### use foo.ysh --pick nonexistent
478shopt --set ysh:upgrade
479
480use $REPO_ROOT/spec/testdata/module2/builtins.ysh --pick mylen nonexistent
481
482## status: 1
483## STDOUT:
484## END
485
486
487#### use foo.ysh --all-provided
488
489echo TODO
490
491## STDOUT:
492## END
493
494
495#### use foo.ysh --all-for-testing
496
497echo TODO
498
499## STDOUT:
500## END