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