elvish/pkg/eval/compile_effect_unix_test.go
Kurtis Rader 358e52a7f5 Make testing compilation errors more deterministic
A year ago I submitted a change to replace AnyError with tests for specific
errors (see https://github.com/elves/elvish/commit/87656c99).  This does
something similar for DoesNotCompile. This ensures the test does what
is implied and makes correlating specific unit tests with compilation
errors easier.

This includes a couple of changes to compilation error messages to improve
readability (IMHO) but those are not the primary purpose of this change.

Related #1560
2022-11-20 16:33:29 +00:00

75 lines
2.4 KiB
Go

//go:build !windows && !plan9
package eval_test
import (
"os"
"strings"
"testing"
"src.elv.sh/pkg/eval/errs"
. "src.elv.sh/pkg/eval/evaltest"
"src.elv.sh/pkg/must"
"src.elv.sh/pkg/testutil"
)
func TestPipeline_ReaderGone_Unix(t *testing.T) {
Test(t,
// External commands terminated by SIGPIPE due to reader exiting early
// raise ReaderGone, which is then suppressed.
That("yes | true").DoesNothing(),
That(
"var reached = $false",
"{ yes; reached = $true } | true",
"put $reached",
).Puts(false),
)
}
func TestCommand_External(t *testing.T) {
d := testutil.InTempDir(t)
mustWriteScript("foo", "#!/bin/sh", "echo foo")
mustWriteScript("lorem/ipsum", "#!/bin/sh", "echo lorem ipsum")
testutil.Setenv(t, "PATH", d+"/bin")
mustWriteScript("bin/hello", "#!/bin/sh", "echo hello")
Test(t,
// External commands, searched and relative
That("hello").Prints("hello\n"),
That("./foo").Prints("foo\n"),
That("lorem/ipsum").Prints("lorem ipsum\n"),
// Using the explicit e: namespace.
That("e:hello").Prints("hello\n"),
That("e:./foo").Prints("foo\n"),
// Relative external commands may be a dynamic string.
That("var x = ipsum", "lorem/$x").Prints("lorem ipsum\n"),
// Searched external commands may not be a dynamic string.
That("var x = hello; $x").Throws(
errs.BadValue{What: "command",
Valid: "callable or string containing slash", Actual: "hello"},
"$x"),
// Using new FD as destination in external commands.
// Regression test against b.elv.sh/788.
That("./foo 5</dev/null").Prints("foo\n"),
// Using pragma to allow or disallow implicit searched commands
That("pragma unknown-command = disallow", "hello").DoesNotCompile("unknown command disallowed by current pragma"),
That("pragma unknown-command = external", "hello").Prints("hello\n"),
// Pragma applies to subscope
That("pragma unknown-command = disallow", "{ hello }").DoesNotCompile("unknown command disallowed by current pragma"),
// Explicit uses with e: is always allowed
That("pragma unknown-command = disallow", "e:hello").Prints("hello\n"),
// Relative external commands are always allowed
That("pragma unknown-command = disallow", "./foo").Prints("foo\n"),
That("pragma unknown-command = disallow", "var x = ./foo", "$x").Prints("foo\n"),
)
}
func mustWriteScript(name string, lines ...string) {
must.WriteFile(name, strings.Join(lines, "\n"))
must.OK(os.Chmod(name, 0700))
}