OILS / test / spec.sh View on Github | oilshell.org

969 lines, 653 significant
1#!/usr/bin/env bash
2#
3# Usage:
4# test/spec.sh <function name>
5
6set -o nounset
7set -o pipefail
8set -o errexit
9shopt -s strict:all 2>/dev/null || true # dogfood for OSH
10
11REPO_ROOT=$(cd "$(dirname $0)/.."; pwd)
12
13source test/common.sh
14source test/spec-common.sh
15source devtools/run-task.sh
16
17if test -z "${IN_NIX_SHELL:-}"; then
18 source build/dev-shell.sh # to run 'dash', etc.
19fi
20
21# TODO: Just use 'dash bash' and $PATH
22readonly DASH=dash
23readonly BASH=bash
24readonly MKSH=mksh
25readonly ZSH=zsh
26readonly BUSYBOX_ASH=ash
27
28# ash and dash are similar, so not including ash by default. zsh is not quite
29# POSIX.
30readonly REF_SHELLS=($DASH $BASH $MKSH)
31
32check-survey-shells() {
33 ### Make sure bash, zsh, OSH, etc. exist
34
35 # Note: yash isn't here, but it is used in a couple tests
36
37 test/spec-runner.sh shell-sanity-check "${REF_SHELLS[@]}" $ZSH $BUSYBOX_ASH $OSH_LIST
38}
39
40# TODO: remove this stub after we hollow out this file
41
42run-file() { test/spec-py.sh run-file "$@"; }
43
44#
45# Misc
46#
47
48# Really what I want is enter(func) and exit(func), and filter by regex?
49trace-var-sub() {
50 local out=_tmp/coverage
51 mkdir -p $out
52
53 # This creates *.cover files, with line counts.
54 #python -m trace --count -C $out \
55
56 # This prints trace with line numbers to stdout.
57 #python -m trace --trace -C $out \
58 PYTHONPATH=. python -m trace --trackcalls -C $out \
59 test/sh_spec.py spec/var-sub.test.sh $DASH $BASH "$@"
60
61 ls -l $out
62 head $out/*.cover
63}
64
65#
66# Individual tests.
67#
68# We configure the shells they run on and the number of allowed failures (to
69# prevent regressions.)
70#
71
72interactive-parse() {
73 run-file interactive-parse "$@"
74}
75
76smoke() {
77 run-file smoke "$@"
78}
79
80interactive() {
81 run-file interactive "$@"
82}
83
84prompt() {
85 run-file prompt "$@"
86}
87
88bugs() {
89 run-file bugs "$@"
90}
91
92TODO-deprecate() {
93 run-file TODO-deprecate "$@"
94}
95
96blog1() {
97 sh-spec spec/blog1.test.sh \
98 ${REF_SHELLS[@]} $ZSH $OSH_LIST "$@"
99}
100
101blog2() {
102 sh-spec spec/blog2.test.sh \
103 ${REF_SHELLS[@]} $ZSH $OSH_LIST "$@"
104}
105
106blog-other1() {
107 sh-spec spec/blog-other1.test.sh \
108 ${REF_SHELLS[@]} $ZSH $OSH_LIST "$@"
109}
110
111alias() {
112 run-file alias "$@"
113}
114
115comments() {
116 sh-spec spec/comments.test.sh ${REF_SHELLS[@]} $OSH_LIST "$@"
117}
118
119word-split() {
120 run-file word-split "$@"
121}
122
123word-eval() {
124 sh-spec spec/word-eval.test.sh \
125 ${REF_SHELLS[@]} $OSH_LIST "$@"
126}
127
128# These cases apply to many shells.
129assign() {
130 run-file assign "$@"
131}
132
133# These cases apply to a few shells.
134assign-extended() {
135 sh-spec spec/assign-extended.test.sh \
136 $BASH $MKSH $OSH_LIST "$@"
137}
138
139# Corner cases that OSH doesn't handle
140assign-deferred() {
141 sh-spec spec/assign-deferred.test.sh \
142 $BASH $MKSH "$@"
143}
144
145# These test associative arrays
146assign-dialects() {
147 run-file assign-dialects "$@"
148}
149
150background() {
151 run-file background "$@"
152}
153
154subshell() {
155 sh-spec spec/subshell.test.sh \
156 ${REF_SHELLS[@]} $OSH_LIST "$@"
157}
158
159quote() {
160 sh-spec spec/quote.test.sh \
161 ${REF_SHELLS[@]} $BUSYBOX_ASH $OSH_LIST "$@"
162}
163
164loop() {
165 sh-spec spec/loop.test.sh \
166 ${REF_SHELLS[@]} $ZSH $OSH_LIST "$@"
167}
168
169case_() {
170 run-file case_ "$@"
171}
172
173if_() {
174 sh-spec spec/if_.test.sh \
175 ${REF_SHELLS[@]} $ZSH $OSH_LIST "$@"
176}
177
178builtins() {
179 run-file builtins "$@"
180}
181
182builtin-eval-source() {
183 sh-spec spec/builtin-eval-source.test.sh \
184 ${REF_SHELLS[@]} $ZSH $OSH_LIST "$@"
185}
186
187builtin-echo() {
188 run-file builtin-echo "$@"
189}
190
191builtin-read() {
192 run-file builtin-read "$@"
193}
194
195nul-bytes() {
196 run-file nul-bytes "$@"
197}
198
199whitespace() {
200 run-file whitespace "$@"
201}
202
203# Special bash printf things like -v and %q. Portable stuff goes in builtin-io.
204builtin-printf() {
205 run-file builtin-printf "$@"
206}
207
208builtins2() {
209 run-file builtins2 "$@"
210}
211
212builtin-history() {
213 run-file builtin-history "$@"
214}
215
216# dash and mksh don't implement 'dirs'
217builtin-dirs() {
218 sh-spec spec/builtin-dirs.test.sh \
219 $BASH $ZSH $OSH_LIST "$@"
220}
221
222builtin-vars() {
223 run-file builtin-vars "$@"
224}
225
226builtin-getopts() {
227 run-file builtin-getopts "$@"
228}
229
230builtin-bracket() {
231 run-file builtin-bracket "$@"
232}
233
234builtin-trap() {
235 sh-spec spec/builtin-trap.test.sh \
236 ${REF_SHELLS[@]} $OSH_LIST "$@"
237}
238
239builtin-trap-bash() {
240 run-file builtin-trap-bash "$@"
241}
242
243# Bash implements type -t, but no other shell does. For Nix.
244# zsh/mksh/dash don't have the 'help' builtin.
245builtin-bash() {
246 run-file builtin-bash "$@"
247}
248
249builtin-type() {
250 run-file builtin-type "$@"
251}
252
253builtin-type-bash() {
254 run-file builtin-type-bash "$@"
255}
256
257vars-bash() {
258 run-file vars-bash "$@"
259}
260
261vars-special() {
262 run-file vars-special "$@"
263}
264
265builtin-completion() {
266 run-file builtin-completion "$@"
267}
268
269builtin-special() {
270 sh-spec spec/builtin-special.test.sh --oils-failures-allowed 4 \
271 ${REF_SHELLS[@]} $ZSH $OSH_LIST "$@"
272}
273
274builtin-times() {
275 sh-spec spec/builtin-times.test.sh $BASH $ZSH $OSH_LIST "$@"
276}
277
278command-parsing() {
279 sh-spec spec/command-parsing.test.sh ${REF_SHELLS[@]} $OSH_LIST "$@"
280}
281
282func-parsing() {
283 sh-spec spec/func-parsing.test.sh ${REF_SHELLS[@]} $OSH_LIST "$@"
284}
285
286sh-func() {
287 sh-spec spec/sh-func.test.sh --oils-failures-allowed 1 \
288 ${REF_SHELLS[@]} $OSH_LIST "$@"
289}
290
291glob() {
292 # Note: can't pass because it assumes 'bin' exists, etc.
293 sh-spec spec/glob.test.sh --oils-failures-allowed 3 \
294 ${REF_SHELLS[@]} $BUSYBOX_ASH $OSH_LIST "$@"
295}
296
297globignore() {
298 run-file globignore "$@"
299}
300
301arith() {
302 run-file arith "$@"
303}
304
305command-sub() {
306 sh-spec spec/command-sub.test.sh \
307 ${REF_SHELLS[@]} $OSH_LIST "$@"
308}
309
310command_() {
311 sh-spec spec/command_.test.sh \
312 ${REF_SHELLS[@]} $ZSH $OSH_LIST "$@"
313}
314
315pipeline() {
316 sh-spec spec/pipeline.test.sh \
317 ${REF_SHELLS[@]} $ZSH $OSH_LIST "$@"
318}
319
320explore-parsing() {
321 sh-spec spec/explore-parsing.test.sh \
322 ${REF_SHELLS[@]} $OSH_LIST "$@"
323}
324
325parse-errors() {
326 sh-spec spec/parse-errors.test.sh --oils-failures-allowed 3 \
327 ${REF_SHELLS[@]} $OSH_LIST "$@"
328}
329
330here-doc() {
331 # NOTE: The last two tests, 31 and 32, have different behavior on my Ubuntu
332 # and Debian machines.
333 # - On Ubuntu, read_from_fd.py fails with Errno 9 -- bad file descriptor.
334 # - On Debian, the whole process hangs.
335 # Is this due to Python 3.2 vs 3.4? Either way osh doesn't implement the
336 # functionality, so it's probably best to just implement it.
337 sh-spec spec/here-doc.test.sh --range 0-31 \
338 ${REF_SHELLS[@]} $OSH_LIST "$@"
339}
340
341redirect() {
342 sh-spec spec/redirect.test.sh --oils-failures-allowed 2 \
343 ${REF_SHELLS[@]} $OSH_LIST "$@"
344}
345
346redirect-multi() {
347 run-file redirect-multi "$@"
348}
349
350posix() {
351 sh-spec spec/posix.test.sh \
352 ${REF_SHELLS[@]} $OSH_LIST "$@"
353}
354
355introspect() {
356 run-file introspect "$@"
357}
358
359tilde() {
360 run-file tilde "$@"
361}
362
363var-op-test() {
364 run-file var-op-test "$@"
365}
366
367var-op-len() {
368 sh-spec spec/var-op-len.test.sh \
369 ${REF_SHELLS[@]} $ZSH $OSH_LIST "$@"
370}
371
372var-op-patsub() {
373 # 1 unicode failure, and [^]] which is a parsing divergence
374 sh-spec spec/var-op-patsub.test.sh --oils-failures-allowed 2 \
375 $BASH $MKSH $ZSH $OSH_LIST "$@"
376 # TODO: can add $BUSYBOX_ASH
377}
378
379var-op-slice() {
380 # dash doesn't support any of these operations
381 sh-spec spec/var-op-slice.test.sh --oils-failures-allowed 1 \
382 $BASH $MKSH $ZSH $OSH_LIST "$@"
383}
384
385var-op-bash() {
386 run-file var-op-bash "$@"
387}
388
389var-op-strip() {
390 sh-spec spec/var-op-strip.test.sh \
391 ${REF_SHELLS[@]} $ZSH $BUSYBOX_ASH $OSH_LIST "$@"
392}
393
394var-sub() {
395 # NOTE: ZSH has interesting behavior, like echo hi > "$@" can write to TWO
396 # FILES! But ultimately we don't really care, so I disabled it.
397 sh-spec spec/var-sub.test.sh \
398 ${REF_SHELLS[@]} $OSH_LIST "$@"
399}
400
401var-num() {
402 run-file var-num "$@"
403}
404
405var-sub-quote() {
406 sh-spec spec/var-sub-quote.test.sh \
407 ${REF_SHELLS[@]} $OSH_LIST "$@"
408}
409
410sh-usage() {
411 run-file sh-usage "$@"
412}
413
414sh-options() {
415 run-file sh-options "$@"
416}
417
418xtrace() {
419 sh-spec spec/xtrace.test.sh --oils-failures-allowed 1 \
420 ${REF_SHELLS[@]} $OSH_LIST "$@"
421}
422
423strict-options() {
424 sh-spec spec/strict-options.test.sh \
425 ${REF_SHELLS[@]} $OSH_LIST "$@"
426}
427
428exit-status() {
429 run-file exit-status "$@"
430}
431
432errexit() {
433 sh-spec spec/errexit.test.sh \
434 ${REF_SHELLS[@]} $BUSYBOX_ASH $OSH_LIST "$@"
435}
436
437errexit-osh() {
438 run-file errexit-osh "$@"
439}
440
441fatal-errors() {
442 sh-spec spec/fatal-errors.test.sh \
443 ${REF_SHELLS[@]} $ZSH $OSH_LIST "$@"
444}
445
446#
447# Non-POSIX extensions: arrays, brace expansion, [[, ((, etc.
448#
449
450# There as many non-POSIX arithmetic contexts.
451arith-context() {
452 sh-spec spec/arith-context.test.sh \
453 $BASH $MKSH $ZSH $OSH_LIST "$@"
454}
455
456array() {
457 sh-spec spec/array.test.sh \
458 $BASH $MKSH $OSH_LIST "$@"
459}
460
461array-compat() {
462 run-file array-compat "$@"
463}
464
465type-compat() {
466 run-file type-compat "$@"
467}
468
469# += is not POSIX and not in dash.
470append() {
471 run-file append "$@"
472}
473
474# associative array -- mksh and zsh implement different associative arrays.
475assoc() {
476 run-file assoc "$@"
477}
478
479# ZSH also has associative arrays
480assoc-zsh() {
481 sh-spec spec/assoc-zsh.test.sh $ZSH "$@"
482}
483
484dbracket() {
485 run-file dbracket "$@"
486}
487
488dparen() {
489 sh-spec spec/dparen.test.sh --oils-failures-allowed 1 \
490 $BASH $MKSH $ZSH $OSH_LIST "$@"
491}
492
493brace-expansion() {
494 run-file brace-expansion "$@"
495}
496
497regex() {
498 run-file regex "$@"
499}
500
501process-sub() {
502 # mksh and dash don't support it
503 sh-spec spec/process-sub.test.sh \
504 $BASH $ZSH $OSH_LIST "$@"
505}
506
507# This does file system globbing
508extglob-files() {
509 sh-spec spec/extglob-files.test.sh --oils-failures-allowed 1 \
510 $BASH $MKSH $OSH_LIST "$@"
511}
512
513# This does string matching.
514extglob-match() {
515 sh-spec spec/extglob-match.test.sh \
516 $BASH $MKSH $OSH_LIST "$@"
517}
518
519nocasematch-match() {
520 run-file nocasematch-match "$@"
521}
522
523# ${!var} syntax -- oil should replace this with associative arrays.
524# mksh has completely different behavior for this syntax. Not worth testing.
525var-ref() {
526 run-file var-ref "$@"
527}
528
529# declare / local -n
530# there is one divergence when combining -n and ${!ref}
531nameref() {
532 sh-spec spec/nameref.test.sh --oils-failures-allowed 7 \
533 $BASH $MKSH $OSH_LIST "$@"
534}
535
536let() {
537 sh-spec spec/let.test.sh $BASH $MKSH $ZSH "$@"
538}
539
540for-expr() {
541 sh-spec spec/for-expr.test.sh \
542 $BASH $ZSH $OSH_LIST "$@"
543}
544
545empty-bodies() {
546 sh-spec spec/empty-bodies.test.sh "${REF_SHELLS[@]}" $ZSH $OSH_LIST "$@"
547}
548
549# TODO: This is for the ANTLR grammars, in the oil-sketch repo.
550# osh has infinite loop?
551shell-grammar() {
552 sh-spec spec/shell-grammar.test.sh $BASH $MKSH $ZSH "$@"
553}
554
555serialize() {
556 run-file serialize "$@"
557}
558
559#
560# Smoosh
561#
562
563readonly SMOOSH_REPO=~/git/languages/smoosh
564
565sh-spec-smoosh-env() {
566 local test_file=$1
567 shift
568
569 # - smoosh tests use $TEST_SHELL instead of $SH
570 # - cd $TMP to avoid littering repo
571 # - pass -o posix
572 # - timeout of 1 second
573 # - Some tests in smoosh use $HOME and $LOGNAME
574
575 sh-spec $test_file \
576 --sh-env-var-name TEST_SHELL \
577 --posix \
578 --env-pair "TEST_UTIL=$SMOOSH_REPO/tests/util" \
579 --env-pair "LOGNAME=$LOGNAME" \
580 --env-pair "HOME=$HOME" \
581 --timeout 1 \
582 --oils-bin-dir $REPO_ROOT/bin \
583 --compare-shells \
584 "$@"
585}
586
587# For speed, only run with one copy of OSH.
588readonly smoosh_osh_list=$OSH_CPYTHON
589
590smoosh() {
591 ### Run case smoosh from the console
592
593 # TODO: Use --oils-bin-dir
594 # our_shells, etc.
595
596 sh-spec-smoosh-env _tmp/smoosh.test.sh \
597 ${REF_SHELLS[@]} $smoosh_osh_list \
598 "$@"
599}
600
601smoosh-hang() {
602 ### Run case smoosh-hang from the console
603
604 # Need the smoosh timeout tool to run correctly.
605 sh-spec-smoosh-env _tmp/smoosh-hang.test.sh \
606 --timeout-bin "$SMOOSH_REPO/tests/util/timeout" \
607 --timeout 1 \
608 "$@"
609}
610
611_one-html() {
612 local spec_name=$1
613 shift
614
615 local out_dir=_tmp/spec/smoosh
616 local tmp_dir=_tmp/src-smoosh
617 mkdir -p $out_dir $out_dir
618
619 doctools/src_tree.py smoosh-file \
620 _tmp/$spec_name.test.sh \
621 $out_dir/$spec_name.test.html
622
623 local out=$out_dir/${spec_name}.html
624 set +o errexit
625 # Shell function is smoosh or smoosh-hang
626 time $spec_name --format html "$@" > $out
627 set -o errexit
628
629 echo
630 echo "Wrote $out"
631
632 # NOTE: This IGNORES the exit status.
633}
634
635# TODO:
636# - Put these tests in the CI
637# - Import smoosh spec tests into the repo, with 'test/smoosh.sh'
638
639smoosh-html() {
640 ### Run by devtools/release.sh
641 _one-html smoosh "$@"
642}
643
644smoosh-hang-html() {
645 ### Run by devtools/release.sh
646 _one-html smoosh-hang "$@"
647}
648
649html-demo() {
650 ### Test for --format html
651
652 local out=_tmp/spec/demo.html
653 builtin-special --format html "$@" > $out
654
655 echo
656 echo "Wrote $out"
657}
658
659#
660# Hay is part of the YSH suite
661#
662
663hay() {
664 run-file hay "$@"
665}
666
667hay-isolation() {
668 run-file hay-isolation "$@"
669}
670
671hay-meta() {
672 run-file hay-meta "$@"
673}
674
675#
676# YSH
677#
678
679ysh-convert() {
680 run-file ysh-convert "$@"
681}
682
683ysh-completion() {
684 run-file ysh-completion "$@"
685}
686
687ysh-stdlib() {
688 run-file ysh-stdlib "$@"
689}
690
691ysh-stdlib-2() {
692 run-file ysh-stdlib-2 "$@"
693}
694
695ysh-stdlib-args() {
696 run-file ysh-stdlib-args "$@"
697}
698
699ysh-stdlib-testing() {
700 run-file ysh-stdlib-testing "$@"
701}
702
703ysh-stdlib-synch() {
704 run-file ysh-stdlib-synch "$@"
705}
706
707ysh-source() {
708 run-file ysh-source "$@"
709}
710
711ysh-usage() {
712 run-file ysh-usage "$@"
713}
714
715ysh-unicode() {
716 run-file ysh-unicode "$@"
717}
718
719ysh-bin() {
720 run-file ysh-bin "$@"
721}
722
723ysh-dict() {
724 run-file ysh-dict "$@"
725}
726
727ysh-list() {
728 run-file ysh-list "$@"
729}
730
731ysh-place() {
732 run-file ysh-place "$@"
733}
734
735ysh-prompt() {
736 run-file ysh-prompt "$@"
737}
738
739ysh-assign() {
740 run-file ysh-assign "$@"
741}
742
743ysh-augmented() {
744 run-file ysh-augmented "$@"
745}
746
747ysh-blocks() {
748 run-file ysh-blocks "$@"
749}
750
751ysh-bugs() {
752 run-file ysh-bugs "$@"
753}
754
755ysh-builtins() {
756 run-file ysh-builtins "$@"
757}
758
759ysh-builtin-module() {
760 run-file ysh-builtin-module "$@"
761}
762
763ysh-builtin-eval() {
764 run-file ysh-builtin-eval "$@"
765}
766
767# Related to errexit-oil
768ysh-builtin-error() {
769 run-file ysh-builtin-error "$@"
770}
771
772ysh-builtin-meta() {
773 run-file ysh-builtin-meta "$@"
774}
775
776ysh-builtin-process() {
777 run-file ysh-builtin-process "$@"
778}
779
780ysh-builtin-shopt() {
781 run-file ysh-builtin-shopt "$@"
782}
783
784ysh-case() {
785 run-file ysh-case "$@"
786}
787
788ysh-command-sub() {
789 run-file ysh-command-sub "$@"
790}
791
792ysh-demo() {
793 run-file ysh-demo "$@"
794}
795
796ysh-expr() {
797 run-file ysh-expr "$@"
798}
799
800ysh-int-float() {
801 run-file ysh-int-float "$@"
802}
803
804ysh-expr-bool() {
805 run-file ysh-expr-bool "$@"
806}
807
808ysh-expr-arith() {
809 run-file ysh-expr-arith "$@"
810}
811
812ysh-expr-compare() {
813 run-file ysh-expr-compare "$@"
814}
815
816ysh-expr-sub() {
817 run-file ysh-expr-sub "$@"
818}
819
820ysh-for() {
821 run-file ysh-for "$@"
822}
823
824ysh-methods() {
825 run-file ysh-methods "$@"
826}
827
828ysh-func() {
829 run-file ysh-func "$@"
830}
831
832ysh-func-builtin() {
833 run-file ysh-func-builtin "$@"
834}
835
836ysh-funcs-external() {
837 run-file ysh-funcs-external "$@"
838}
839
840ysh-interactive() {
841 run-file ysh-interactive "$@"
842}
843
844ysh-json() {
845 run-file ysh-json "$@"
846}
847
848ysh-keywords() {
849 run-file ysh-keywords "$@"
850}
851
852ysh-multiline() {
853 run-file ysh-multiline "$@"
854}
855
856ysh-options() {
857 run-file ysh-options "$@"
858}
859
860ysh-options-assign() {
861 run-file ysh-options-assign "$@"
862}
863
864ysh-proc() {
865 run-file ysh-proc "$@"
866}
867
868ysh-regex() {
869 run-file ysh-regex "$@"
870}
871
872ysh-regex-api() {
873 run-file ysh-regex-api "$@"
874}
875
876ysh-reserved() {
877 run-file ysh-reserved "$@"
878}
879
880ysh-scope() {
881 run-file ysh-scope "$@"
882}
883
884ysh-slice-range() {
885 run-file ysh-slice-range "$@"
886}
887
888ysh-string() {
889 run-file ysh-string "$@"
890}
891
892ysh-special-vars() {
893 run-file ysh-special-vars "$@"
894}
895
896ysh-tuple() {
897 run-file ysh-tuple "$@"
898}
899
900ysh-var-sub() {
901 run-file ysh-var-sub "$@"
902}
903
904ysh-with-sh() {
905 run-file ysh-with-sh "$@"
906}
907
908ysh-word-eval() {
909 run-file ysh-word-eval "$@"
910}
911
912ysh-xtrace() {
913 run-file ysh-xtrace "$@"
914}
915
916ysh-user-feedback() {
917 run-file ysh-user-feedback "$@"
918}
919
920ysh-builtin-ctx() {
921 run-file ysh-builtin-ctx "$@"
922}
923
924ysh-builtin-error() {
925 run-file ysh-builtin-error "$@"
926}
927
928ysh-builtin-help() {
929 run-file ysh-builtin-help "$@"
930}
931
932ysh-dev() {
933 run-file ysh-dev "$@"
934}
935
936
937#
938# More OSH
939#
940
941nix-idioms() {
942 run-file nix-idioms "$@"
943}
944
945zsh-idioms() {
946 run-file zsh-idioms "$@"
947}
948
949ble-idioms() {
950 sh-spec spec/ble-idioms.test.sh \
951 $BASH $ZSH $MKSH $BUSYBOX_ASH $OSH_LIST "$@"
952}
953
954ble-features() {
955 sh-spec spec/ble-features.test.sh \
956 $BASH $ZSH $MKSH $BUSYBOX_ASH $DASH yash $OSH_LIST "$@"
957}
958
959toysh() {
960 sh-spec spec/toysh.test.sh --oils-failures-allowed 3 \
961 $BASH $MKSH $OSH_LIST "$@"
962}
963
964toysh-posix() {
965 sh-spec spec/toysh-posix.test.sh --oils-failures-allowed 3 \
966 ${REF_SHELLS[@]} $ZSH yash $OSH_LIST "$@"
967}
968
969run-task "$@"