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

955 lines, 643 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-io() {
188 run-file builtin-io "$@"
189}
190
191nul-bytes() {
192 run-file nul-bytes "$@"
193}
194
195# Special bash printf things like -v and %q. Portable stuff goes in builtin-io.
196builtin-printf() {
197 run-file builtin-printf "$@"
198}
199
200builtins2() {
201 run-file builtins2 "$@"
202}
203
204builtin-history() {
205 run-file builtin-history "$@"
206}
207
208# dash and mksh don't implement 'dirs'
209builtin-dirs() {
210 sh-spec spec/builtin-dirs.test.sh \
211 $BASH $ZSH $OSH_LIST "$@"
212}
213
214builtin-vars() {
215 run-file builtin-vars "$@"
216}
217
218builtin-getopts() {
219 run-file builtin-getopts "$@"
220}
221
222builtin-bracket() {
223 run-file builtin-bracket "$@"
224}
225
226builtin-trap() {
227 sh-spec spec/builtin-trap.test.sh \
228 ${REF_SHELLS[@]} $OSH_LIST "$@"
229}
230
231builtin-trap-bash() {
232 run-file builtin-trap-bash "$@"
233}
234
235# Bash implements type -t, but no other shell does. For Nix.
236# zsh/mksh/dash don't have the 'help' builtin.
237builtin-bash() {
238 run-file builtin-bash "$@"
239}
240
241builtin-type() {
242 run-file builtin-type "$@"
243}
244
245builtin-type-bash() {
246 run-file builtin-type-bash "$@"
247}
248
249vars-bash() {
250 run-file vars-bash "$@"
251}
252
253vars-special() {
254 run-file vars-special "$@"
255}
256
257builtin-completion() {
258 run-file builtin-completion "$@"
259}
260
261builtin-special() {
262 sh-spec spec/builtin-special.test.sh --oils-failures-allowed 4 \
263 ${REF_SHELLS[@]} $ZSH $OSH_LIST "$@"
264}
265
266builtin-times() {
267 sh-spec spec/builtin-times.test.sh $BASH $ZSH $OSH_LIST "$@"
268}
269
270command-parsing() {
271 sh-spec spec/command-parsing.test.sh ${REF_SHELLS[@]} $OSH_LIST "$@"
272}
273
274func-parsing() {
275 sh-spec spec/func-parsing.test.sh ${REF_SHELLS[@]} $OSH_LIST "$@"
276}
277
278sh-func() {
279 sh-spec spec/sh-func.test.sh --oils-failures-allowed 1 \
280 ${REF_SHELLS[@]} $OSH_LIST "$@"
281}
282
283glob() {
284 # Note: can't pass because it assumes 'bin' exists, etc.
285 sh-spec spec/glob.test.sh --oils-failures-allowed 3 \
286 ${REF_SHELLS[@]} $BUSYBOX_ASH $OSH_LIST "$@"
287}
288
289globignore() {
290 run-file globignore "$@"
291}
292
293arith() {
294 run-file arith "$@"
295}
296
297command-sub() {
298 sh-spec spec/command-sub.test.sh \
299 ${REF_SHELLS[@]} $OSH_LIST "$@"
300}
301
302command_() {
303 sh-spec spec/command_.test.sh \
304 ${REF_SHELLS[@]} $ZSH $OSH_LIST "$@"
305}
306
307pipeline() {
308 sh-spec spec/pipeline.test.sh \
309 ${REF_SHELLS[@]} $ZSH $OSH_LIST "$@"
310}
311
312explore-parsing() {
313 sh-spec spec/explore-parsing.test.sh \
314 ${REF_SHELLS[@]} $OSH_LIST "$@"
315}
316
317parse-errors() {
318 sh-spec spec/parse-errors.test.sh --oils-failures-allowed 3 \
319 ${REF_SHELLS[@]} $OSH_LIST "$@"
320}
321
322here-doc() {
323 # NOTE: The last two tests, 31 and 32, have different behavior on my Ubuntu
324 # and Debian machines.
325 # - On Ubuntu, read_from_fd.py fails with Errno 9 -- bad file descriptor.
326 # - On Debian, the whole process hangs.
327 # Is this due to Python 3.2 vs 3.4? Either way osh doesn't implement the
328 # functionality, so it's probably best to just implement it.
329 sh-spec spec/here-doc.test.sh --range 0-31 \
330 ${REF_SHELLS[@]} $OSH_LIST "$@"
331}
332
333redirect() {
334 sh-spec spec/redirect.test.sh --oils-failures-allowed 2 \
335 ${REF_SHELLS[@]} $OSH_LIST "$@"
336}
337
338redirect-multi() {
339 run-file redirect-multi "$@"
340}
341
342posix() {
343 sh-spec spec/posix.test.sh \
344 ${REF_SHELLS[@]} $OSH_LIST "$@"
345}
346
347introspect() {
348 run-file introspect "$@"
349}
350
351tilde() {
352 run-file tilde "$@"
353}
354
355var-op-test() {
356 sh-spec spec/var-op-test.test.sh \
357 ${REF_SHELLS[@]} $OSH_LIST "$@"
358}
359
360var-op-len() {
361 sh-spec spec/var-op-len.test.sh \
362 ${REF_SHELLS[@]} $ZSH $OSH_LIST "$@"
363}
364
365var-op-patsub() {
366 # 1 unicode failure, and [^]] which is a parsing divergence
367 sh-spec spec/var-op-patsub.test.sh --oils-failures-allowed 2 \
368 $BASH $MKSH $ZSH $OSH_LIST "$@"
369 # TODO: can add $BUSYBOX_ASH
370}
371
372var-op-slice() {
373 # dash doesn't support any of these operations
374 sh-spec spec/var-op-slice.test.sh --oils-failures-allowed 1 \
375 $BASH $MKSH $ZSH $OSH_LIST "$@"
376}
377
378var-op-bash() {
379 run-file var-op-bash "$@"
380}
381
382var-op-strip() {
383 sh-spec spec/var-op-strip.test.sh \
384 ${REF_SHELLS[@]} $ZSH $BUSYBOX_ASH $OSH_LIST "$@"
385}
386
387var-sub() {
388 # NOTE: ZSH has interesting behavior, like echo hi > "$@" can write to TWO
389 # FILES! But ultimately we don't really care, so I disabled it.
390 sh-spec spec/var-sub.test.sh \
391 ${REF_SHELLS[@]} $OSH_LIST "$@"
392}
393
394var-num() {
395 run-file var-num "$@"
396}
397
398var-sub-quote() {
399 sh-spec spec/var-sub-quote.test.sh \
400 ${REF_SHELLS[@]} $OSH_LIST "$@"
401}
402
403sh-usage() {
404 run-file sh-usage "$@"
405}
406
407sh-options() {
408 run-file sh-options "$@"
409}
410
411xtrace() {
412 sh-spec spec/xtrace.test.sh --oils-failures-allowed 1 \
413 ${REF_SHELLS[@]} $OSH_LIST "$@"
414}
415
416strict-options() {
417 sh-spec spec/strict-options.test.sh \
418 ${REF_SHELLS[@]} $OSH_LIST "$@"
419}
420
421exit-status() {
422 run-file exit-status "$@"
423}
424
425errexit() {
426 sh-spec spec/errexit.test.sh \
427 ${REF_SHELLS[@]} $BUSYBOX_ASH $OSH_LIST "$@"
428}
429
430errexit-osh() {
431 run-file errexit-osh "$@"
432}
433
434fatal-errors() {
435 sh-spec spec/fatal-errors.test.sh \
436 ${REF_SHELLS[@]} $ZSH $OSH_LIST "$@"
437}
438
439#
440# Non-POSIX extensions: arrays, brace expansion, [[, ((, etc.
441#
442
443# There as many non-POSIX arithmetic contexts.
444arith-context() {
445 sh-spec spec/arith-context.test.sh \
446 $BASH $MKSH $ZSH $OSH_LIST "$@"
447}
448
449array() {
450 sh-spec spec/array.test.sh \
451 $BASH $MKSH $OSH_LIST "$@"
452}
453
454array-compat() {
455 run-file array-compat "$@"
456}
457
458type-compat() {
459 run-file type-compat "$@"
460}
461
462# += is not POSIX and not in dash.
463append() {
464 run-file append "$@"
465}
466
467# associative array -- mksh and zsh implement different associative arrays.
468assoc() {
469 run-file assoc "$@"
470}
471
472# ZSH also has associative arrays
473assoc-zsh() {
474 sh-spec spec/assoc-zsh.test.sh $ZSH "$@"
475}
476
477dbracket() {
478 run-file dbracket "$@"
479}
480
481dparen() {
482 sh-spec spec/dparen.test.sh --oils-failures-allowed 1 \
483 $BASH $MKSH $ZSH $OSH_LIST "$@"
484}
485
486brace-expansion() {
487 run-file brace-expansion "$@"
488}
489
490regex() {
491 sh-spec spec/regex.test.sh --oils-failures-allowed 2 \
492 $BASH $ZSH $OSH_LIST "$@"
493}
494
495process-sub() {
496 # mksh and dash don't support it
497 sh-spec spec/process-sub.test.sh \
498 $BASH $ZSH $OSH_LIST "$@"
499}
500
501# This does file system globbing
502extglob-files() {
503 sh-spec spec/extglob-files.test.sh --oils-failures-allowed 1 \
504 $BASH $MKSH $OSH_LIST "$@"
505}
506
507# This does string matching.
508extglob-match() {
509 sh-spec spec/extglob-match.test.sh \
510 $BASH $MKSH $OSH_LIST "$@"
511}
512
513nocasematch-match() {
514 run-file nocasematch-match "$@"
515}
516
517# ${!var} syntax -- oil should replace this with associative arrays.
518# mksh has completely different behavior for this syntax. Not worth testing.
519var-ref() {
520 run-file var-ref "$@"
521}
522
523# declare / local -n
524# there is one divergence when combining -n and ${!ref}
525nameref() {
526 sh-spec spec/nameref.test.sh --oils-failures-allowed 7 \
527 $BASH $MKSH $OSH_LIST "$@"
528}
529
530let() {
531 sh-spec spec/let.test.sh $BASH $MKSH $ZSH "$@"
532}
533
534for-expr() {
535 sh-spec spec/for-expr.test.sh \
536 $BASH $ZSH $OSH_LIST "$@"
537}
538
539empty-bodies() {
540 sh-spec spec/empty-bodies.test.sh "${REF_SHELLS[@]}" $ZSH $OSH_LIST "$@"
541}
542
543# TODO: This is for the ANTLR grammars, in the oil-sketch repo.
544# osh has infinite loop?
545shell-grammar() {
546 sh-spec spec/shell-grammar.test.sh $BASH $MKSH $ZSH "$@"
547}
548
549serialize() {
550 run-file serialize "$@"
551}
552
553#
554# Smoosh
555#
556
557readonly SMOOSH_REPO=~/git/languages/smoosh
558
559sh-spec-smoosh-env() {
560 local test_file=$1
561 shift
562
563 # - smoosh tests use $TEST_SHELL instead of $SH
564 # - cd $TMP to avoid littering repo
565 # - pass -o posix
566 # - timeout of 1 second
567 # - Some tests in smoosh use $HOME and $LOGNAME
568
569 sh-spec $test_file \
570 --sh-env-var-name TEST_SHELL \
571 --posix \
572 --env-pair "TEST_UTIL=$SMOOSH_REPO/tests/util" \
573 --env-pair "LOGNAME=$LOGNAME" \
574 --env-pair "HOME=$HOME" \
575 --timeout 1 \
576 --oils-bin-dir $REPO_ROOT/bin \
577 --compare-shells \
578 "$@"
579}
580
581# For speed, only run with one copy of OSH.
582readonly smoosh_osh_list=$OSH_CPYTHON
583
584smoosh() {
585 ### Run case smoosh from the console
586
587 # TODO: Use --oils-bin-dir
588 # our_shells, etc.
589
590 sh-spec-smoosh-env _tmp/smoosh.test.sh \
591 ${REF_SHELLS[@]} $smoosh_osh_list \
592 "$@"
593}
594
595smoosh-hang() {
596 ### Run case smoosh-hang from the console
597
598 # Need the smoosh timeout tool to run correctly.
599 sh-spec-smoosh-env _tmp/smoosh-hang.test.sh \
600 --timeout-bin "$SMOOSH_REPO/tests/util/timeout" \
601 --timeout 1 \
602 "$@"
603}
604
605_one-html() {
606 local spec_name=$1
607 shift
608
609 local out_dir=_tmp/spec/smoosh
610 local tmp_dir=_tmp/src-smoosh
611 mkdir -p $out_dir $out_dir
612
613 doctools/src_tree.py smoosh-file \
614 _tmp/$spec_name.test.sh \
615 $out_dir/$spec_name.test.html
616
617 local out=$out_dir/${spec_name}.html
618 set +o errexit
619 # Shell function is smoosh or smoosh-hang
620 time $spec_name --format html "$@" > $out
621 set -o errexit
622
623 echo
624 echo "Wrote $out"
625
626 # NOTE: This IGNORES the exit status.
627}
628
629# TODO:
630# - Put these tests in the CI
631# - Import smoosh spec tests into the repo, with 'test/smoosh.sh'
632
633smoosh-html() {
634 ### Run by devtools/release.sh
635 _one-html smoosh "$@"
636}
637
638smoosh-hang-html() {
639 ### Run by devtools/release.sh
640 _one-html smoosh-hang "$@"
641}
642
643html-demo() {
644 ### Test for --format html
645
646 local out=_tmp/spec/demo.html
647 builtin-special --format html "$@" > $out
648
649 echo
650 echo "Wrote $out"
651}
652
653#
654# Hay is part of the YSH suite
655#
656
657hay() {
658 run-file hay "$@"
659}
660
661hay-isolation() {
662 run-file hay-isolation "$@"
663}
664
665hay-meta() {
666 run-file hay-meta "$@"
667}
668
669#
670# YSH
671#
672
673ysh-convert() {
674 run-file ysh-convert "$@"
675}
676
677ysh-completion() {
678 run-file ysh-completion "$@"
679}
680
681ysh-stdlib() {
682 run-file ysh-stdlib "$@"
683}
684
685ysh-stdlib-2() {
686 run-file ysh-stdlib-2 "$@"
687}
688
689ysh-stdlib-args() {
690 run-file ysh-stdlib-args "$@"
691}
692
693ysh-stdlib-testing() {
694 run-file ysh-stdlib-testing "$@"
695}
696
697ysh-source() {
698 run-file ysh-source "$@"
699}
700
701ysh-usage() {
702 run-file ysh-usage "$@"
703}
704
705ysh-unicode() {
706 run-file ysh-unicode "$@"
707}
708
709ysh-bin() {
710 run-file ysh-bin "$@"
711}
712
713ysh-dict() {
714 run-file ysh-dict "$@"
715}
716
717ysh-list() {
718 run-file ysh-list "$@"
719}
720
721ysh-place() {
722 run-file ysh-place "$@"
723}
724
725ysh-prompt() {
726 run-file ysh-prompt "$@"
727}
728
729ysh-assign() {
730 run-file ysh-assign "$@"
731}
732
733ysh-augmented() {
734 run-file ysh-augmented "$@"
735}
736
737ysh-blocks() {
738 run-file ysh-blocks "$@"
739}
740
741ysh-bugs() {
742 run-file ysh-bugs "$@"
743}
744
745ysh-builtins() {
746 run-file ysh-builtins "$@"
747}
748
749ysh-builtin-module() {
750 run-file ysh-builtin-module "$@"
751}
752
753ysh-builtin-eval() {
754 run-file ysh-builtin-eval "$@"
755}
756
757# Related to errexit-oil
758ysh-builtin-error() {
759 run-file ysh-builtin-error "$@"
760}
761
762ysh-builtin-meta() {
763 run-file ysh-builtin-meta "$@"
764}
765
766ysh-builtin-process() {
767 run-file ysh-builtin-process "$@"
768}
769
770ysh-builtin-shopt() {
771 run-file ysh-builtin-shopt "$@"
772}
773
774ysh-case() {
775 run-file ysh-case "$@"
776}
777
778ysh-command-sub() {
779 run-file ysh-command-sub "$@"
780}
781
782ysh-demo() {
783 run-file ysh-demo "$@"
784}
785
786ysh-expr() {
787 run-file ysh-expr "$@"
788}
789
790ysh-int-float() {
791 run-file ysh-int-float "$@"
792}
793
794ysh-expr-bool() {
795 run-file ysh-expr-bool "$@"
796}
797
798ysh-expr-arith() {
799 run-file ysh-expr-arith "$@"
800}
801
802ysh-expr-compare() {
803 run-file ysh-expr-compare "$@"
804}
805
806ysh-expr-sub() {
807 run-file ysh-expr-sub "$@"
808}
809
810ysh-for() {
811 run-file ysh-for "$@"
812}
813
814ysh-methods() {
815 run-file ysh-methods "$@"
816}
817
818ysh-func() {
819 run-file ysh-func "$@"
820}
821
822ysh-func-builtin() {
823 run-file ysh-func-builtin "$@"
824}
825
826ysh-funcs-external() {
827 run-file ysh-funcs-external "$@"
828}
829
830ysh-interactive() {
831 run-file ysh-interactive "$@"
832}
833
834ysh-json() {
835 run-file ysh-json "$@"
836}
837
838ysh-keywords() {
839 run-file ysh-keywords "$@"
840}
841
842ysh-multiline() {
843 run-file ysh-multiline "$@"
844}
845
846ysh-options() {
847 run-file ysh-options "$@"
848}
849
850ysh-options-assign() {
851 run-file ysh-options-assign "$@"
852}
853
854ysh-proc() {
855 run-file ysh-proc "$@"
856}
857
858ysh-regex() {
859 run-file ysh-regex "$@"
860}
861
862ysh-regex-api() {
863 run-file ysh-regex-api "$@"
864}
865
866ysh-reserved() {
867 run-file ysh-reserved "$@"
868}
869
870ysh-scope() {
871 run-file ysh-scope "$@"
872}
873
874ysh-slice-range() {
875 run-file ysh-slice-range "$@"
876}
877
878ysh-string() {
879 run-file ysh-string "$@"
880}
881
882ysh-special-vars() {
883 run-file ysh-special-vars "$@"
884}
885
886ysh-tuple() {
887 run-file ysh-tuple "$@"
888}
889
890ysh-var-sub() {
891 run-file ysh-var-sub "$@"
892}
893
894ysh-with-sh() {
895 run-file ysh-with-sh "$@"
896}
897
898ysh-word-eval() {
899 run-file ysh-word-eval "$@"
900}
901
902ysh-xtrace() {
903 run-file ysh-xtrace "$@"
904}
905
906ysh-user-feedback() {
907 run-file ysh-user-feedback "$@"
908}
909
910ysh-builtin-ctx() {
911 run-file ysh-builtin-ctx "$@"
912}
913
914ysh-builtin-error() {
915 run-file ysh-builtin-error "$@"
916}
917
918ysh-builtin-help() {
919 run-file ysh-builtin-help "$@"
920}
921
922ysh-dev() {
923 run-file ysh-dev "$@"
924}
925
926
927#
928# More OSH
929#
930
931nix-idioms() {
932 run-file nix-idioms "$@"
933}
934
935ble-idioms() {
936 sh-spec spec/ble-idioms.test.sh \
937 $BASH $ZSH $MKSH $BUSYBOX_ASH $OSH_LIST "$@"
938}
939
940ble-features() {
941 sh-spec spec/ble-features.test.sh \
942 $BASH $ZSH $MKSH $BUSYBOX_ASH $DASH yash $OSH_LIST "$@"
943}
944
945toysh() {
946 sh-spec spec/toysh.test.sh --oils-failures-allowed 3 \
947 $BASH $MKSH $OSH_LIST "$@"
948}
949
950toysh-posix() {
951 sh-spec spec/toysh-posix.test.sh --oils-failures-allowed 3 \
952 ${REF_SHELLS[@]} $ZSH yash $OSH_LIST "$@"
953}
954
955run-task "$@"