mirror of
https://github.com/go-sylixos/elvish.git
synced 2024-12-15 03:37:52 +08:00
f49cf9f80e
Also fix a bug in handling redirections from invalid types. This addresses #944.
132 lines
4.4 KiB
Go
132 lines
4.4 KiB
Go
package eval
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/elves/elvish/pkg/util"
|
|
)
|
|
|
|
func TestCompileEffect(t *testing.T) {
|
|
_, cleanup := util.InTestDir()
|
|
defer cleanup()
|
|
|
|
Test(t,
|
|
// Chunks
|
|
// ------
|
|
|
|
// Empty chunk
|
|
That("").DoesNothing(),
|
|
// Outputs of pipelines in a chunk are concatenated
|
|
That("put x; put y; put z").Puts("x", "y", "z"),
|
|
// A failed pipeline cause the whole chunk to fail
|
|
That("put a; e:false; put b").Puts("a").ThrowsAny(),
|
|
|
|
// Pipelines
|
|
// ---------
|
|
|
|
// Pure byte pipeline
|
|
That(`echo "Albert\nAllan\nAlbraham\nBerlin" | sed s/l/1/g | grep e`).
|
|
Prints("A1bert\nBer1in\n"),
|
|
// Pure channel pipeline
|
|
That(`put 233 42 19 | each [x]{+ $x 10}`).Puts(243.0, 52.0, 29.0),
|
|
// Pipeline draining.
|
|
That(`range 100 | put x`).Puts("x"),
|
|
// Background pipeline.
|
|
That(
|
|
"notify-bg-job-success = $false",
|
|
"p = (pipe)",
|
|
"{ print foo > $p; pwclose $p }&",
|
|
"slurp < $p",
|
|
"prclose $p").Puts("foo"),
|
|
// TODO: Add a useful hybrid pipeline sample
|
|
|
|
// Commands
|
|
// --------
|
|
|
|
That("put foo").Puts("foo"),
|
|
// Command errors when the head is not a single value.
|
|
That("{put put} foo").ThrowsMessage("head of command must be a single value; got 2 values"),
|
|
// Command errors when when argument errors.
|
|
That("put [][1]").ThrowsMessage("index out of range"),
|
|
// Command errors when any optional evaluation errors.
|
|
That("put &x=[][1]").ThrowsMessage("index out of range"),
|
|
|
|
// Assignments
|
|
// -----------
|
|
|
|
// Spacey assignment.
|
|
That("a @b = 2 3 foo; put $a $b[1]").Puts("2", "foo"),
|
|
// List element assignment
|
|
That("li=[foo bar]; li[0]=233; put $@li").Puts("233", "bar"),
|
|
// Variable in list assignment must already be defined. Regression test
|
|
// for b.elv.sh/889.
|
|
That("foobarlorem[0] = a").DoesNotCompile(),
|
|
// Map element assignment
|
|
That("di=[&k=v]; di[k]=lorem; di[k2]=ipsum; put $di[k] $di[k2]").
|
|
Puts("lorem", "ipsum"),
|
|
That("d=[&a=[&b=v]]; put $d[a][b]; d[a][b]=u; put $d[a][b]").
|
|
Puts("v", "u"),
|
|
// Multi-assignments.
|
|
That("{a,b}=(put a b); put $a $b").Puts("a", "b"),
|
|
That("@a=(put a b); put $@a").Puts("a", "b"),
|
|
That("{a,@b}=(put a b c); put $@b").Puts("b", "c"),
|
|
//That("di=[&]; di[a b]=(put a b); put $di[a] $di[b]").Puts("a", "b"),
|
|
|
|
// Temporary assignment.
|
|
That("a=alice b=bob; {a,@b}=(put amy ben) put $a $@b; put $a $b").
|
|
Puts("amy", "ben", "alice", "bob"),
|
|
// Temporary assignment of list element.
|
|
That("l = [a]; l[0]=x put $l[0]; put $l[0]").Puts("x", "a"),
|
|
// Temporary assignment of map element.
|
|
That("m = [&k=v]; m[k]=v2 put $m[k]; put $m[k]").Puts("v2", "v"),
|
|
// Temporary assignment before special form.
|
|
That("li=[foo bar] for x $li { put $x }").Puts("foo", "bar"),
|
|
// Spacey assignment with temporary assignment
|
|
That("x = 1; x=2 y = (+ 1 $x); put $x $y").Puts("1", 3.0),
|
|
|
|
// Concurrently creating a new variable and accessing existing variable.
|
|
// Run with "go test -race".
|
|
That("x = 1", "put $x | y = (all)").DoesNothing(),
|
|
|
|
// Assignment errors when the RHS errors.
|
|
That("x = [][1]").ThrowsMessage("index out of range"),
|
|
// Arity mismatch.
|
|
That("x = 1 2").Throws(ErrArityMismatch),
|
|
That("x y = 1").Throws(ErrArityMismatch),
|
|
That("x y @z = 1").Throws(ErrArityMismatch),
|
|
|
|
// Redirections
|
|
// ------------
|
|
|
|
// Output and input redirection.
|
|
That("echo 233 > out1", " slurp < out1").Puts("233\n"),
|
|
// Append.
|
|
That("echo 1 > out; echo 2 >> out; slurp < out").Puts("1\n2\n"),
|
|
|
|
// Redirections from special form.
|
|
That(`for x [lorem ipsum] { echo $x } > out2`, `slurp < out2`).
|
|
Puts("lorem\nipsum\n"),
|
|
|
|
// Using numeric FDs as source and destination.
|
|
That(`{ echo foobar >&2 } 2> out3`, `slurp < out3`).
|
|
Puts("foobar\n"),
|
|
// Using named FDs as source and destination.
|
|
That(`{ echo foobar >&stderr } stderr> out4`, `slurp < out4`).
|
|
Puts("foobar\n"),
|
|
// Using a new FD as source throws an exception.
|
|
That(`echo foo >&4`).ThrowsAny(),
|
|
// Using a new FD as destination is OK, and makes it available.
|
|
That(`{ echo foo >&4 } 4>out5`, `slurp < out5`).Puts("foo\n"),
|
|
|
|
// Redirections from File object.
|
|
That(`echo haha > out3`, `f = (fopen out3)`, `slurp <$f`, ` fclose $f`).
|
|
Puts("haha\n"),
|
|
// Redirections from Pipe object.
|
|
That(`p = (pipe); echo haha > $p; pwclose $p; slurp < $p; prclose $p`).
|
|
Puts("haha\n"),
|
|
|
|
// Using anything else in redirection throws an exception.
|
|
That("echo > []").ThrowsMessage("redirection source must be string, file or pipe; got list"),
|
|
)
|
|
}
|