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