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

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