2020-09-03 13:48:39 +08:00
|
|
|
package eval_test
|
2018-03-03 03:43:38 +08:00
|
|
|
|
2018-02-28 06:56:02 +08:00
|
|
|
import (
|
2021-01-24 23:32:24 +08:00
|
|
|
"os"
|
2018-02-28 06:56:02 +08:00
|
|
|
"testing"
|
2018-05-22 07:54:29 +08:00
|
|
|
|
2021-07-15 10:31:01 +08:00
|
|
|
"src.elv.sh/pkg/diag"
|
2021-01-27 09:28:38 +08:00
|
|
|
. "src.elv.sh/pkg/eval"
|
2022-06-21 03:29:14 +08:00
|
|
|
"src.elv.sh/pkg/must"
|
2020-09-03 13:48:39 +08:00
|
|
|
|
2021-12-29 09:16:44 +08:00
|
|
|
"src.elv.sh/pkg/eval/errs"
|
2021-01-27 09:28:38 +08:00
|
|
|
. "src.elv.sh/pkg/eval/evaltest"
|
|
|
|
"src.elv.sh/pkg/eval/vals"
|
|
|
|
"src.elv.sh/pkg/testutil"
|
2018-02-28 06:56:02 +08:00
|
|
|
)
|
2018-03-03 03:43:38 +08:00
|
|
|
|
2021-06-25 06:24:43 +08:00
|
|
|
func TestKindOf(t *testing.T) {
|
|
|
|
Test(t,
|
|
|
|
That("kind-of a []").Puts("string", "list"),
|
|
|
|
thatOutputErrorIsBubbled("kind-of a"),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2021-01-10 22:48:21 +08:00
|
|
|
func TestConstantly(t *testing.T) {
|
2018-05-22 08:08:11 +08:00
|
|
|
Test(t,
|
2022-01-03 08:10:40 +08:00
|
|
|
That(`var f = (constantly foo); $f; $f`).Puts("foo", "foo"),
|
2021-06-25 06:24:43 +08:00
|
|
|
thatOutputErrorIsBubbled("(constantly foo)"),
|
2021-01-10 22:48:21 +08:00
|
|
|
)
|
|
|
|
}
|
2019-10-21 19:42:18 +08:00
|
|
|
|
2021-12-29 09:16:44 +08:00
|
|
|
func TestCallCommand(t *testing.T) {
|
|
|
|
Test(t,
|
|
|
|
That(`call {|arg &opt=v| put $arg $opt } [foo] [&opt=bar]`).
|
|
|
|
Puts("foo", "bar"),
|
|
|
|
That(`call { } [foo] [&[]=bar]`).
|
|
|
|
Throws(errs.BadValue{What: "option key", Valid: "string", Actual: "list"}),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2021-01-10 22:48:21 +08:00
|
|
|
func TestEval(t *testing.T) {
|
|
|
|
Test(t,
|
2020-08-17 06:02:51 +08:00
|
|
|
That("eval 'put x'").Puts("x"),
|
2021-01-09 22:59:00 +08:00
|
|
|
// Using variable from the local scope.
|
2022-01-03 08:10:40 +08:00
|
|
|
That("var x = foo; eval 'put $x'").Puts("foo"),
|
2021-01-09 22:59:00 +08:00
|
|
|
// Setting a variable in the local scope.
|
2022-01-03 08:10:40 +08:00
|
|
|
That("var x = foo; eval 'set x = bar'; put $x").Puts("bar"),
|
2021-01-09 22:59:00 +08:00
|
|
|
// Using variable from the upvalue scope.
|
2022-01-03 08:10:40 +08:00
|
|
|
That("var x = foo; { nop $x; eval 'put $x' }").Puts("foo"),
|
2021-01-09 22:59:00 +08:00
|
|
|
// Specifying a namespace.
|
2022-01-03 08:10:40 +08:00
|
|
|
That("var n = (ns [&x=foo]); eval 'put $x' &ns=$n").Puts("foo"),
|
2021-01-09 22:59:00 +08:00
|
|
|
// Altering variables in the specified namespace.
|
2022-01-03 08:10:40 +08:00
|
|
|
That("var n = (ns [&x=foo]); eval 'set x = bar' &ns=$n; put $n[x]").Puts("bar"),
|
2021-01-09 22:59:00 +08:00
|
|
|
// Newly created variables do not appear in the local namespace.
|
2022-10-02 12:01:39 +08:00
|
|
|
That("eval 'x = foo'; put $x").DoesNotCompile("variable $x not found"),
|
2021-01-09 22:59:00 +08:00
|
|
|
// Newly created variables do not alter the specified namespace, either.
|
2022-01-03 08:10:40 +08:00
|
|
|
That("var n = (ns [&]); eval &ns=$n 'var x = foo'; put $n[x]").
|
2021-01-09 22:59:00 +08:00
|
|
|
Throws(vals.NoSuchKey("x"), "$n[x]"),
|
|
|
|
// However, newly created variable can be accessed in the final
|
|
|
|
// namespace using &on-end.
|
2022-01-03 08:10:40 +08:00
|
|
|
That("eval &on-end={|n| put $n[x] } 'var x = foo'").Puts("foo"),
|
2020-08-17 06:02:51 +08:00
|
|
|
// Parse error.
|
2022-11-30 09:05:16 +08:00
|
|
|
That("eval '['").Throws(AnyParseError),
|
2020-08-17 06:02:51 +08:00
|
|
|
// Compilation error.
|
2021-07-15 10:31:01 +08:00
|
|
|
That("eval 'put $x'").Throws(ErrorWithType(&diag.Error{})),
|
2020-08-17 06:02:51 +08:00
|
|
|
// Exception.
|
2020-09-05 03:31:47 +08:00
|
|
|
That("eval 'fail x'").Throws(FailError{"x"}),
|
2021-01-10 22:48:21 +08:00
|
|
|
)
|
|
|
|
}
|
2020-08-17 06:02:51 +08:00
|
|
|
|
2021-01-24 23:32:24 +08:00
|
|
|
func TestDeprecate(t *testing.T) {
|
|
|
|
Test(t,
|
|
|
|
That("deprecate msg").PrintsStderrWith("msg"),
|
|
|
|
// Different call sites trigger multiple deprecation messages
|
|
|
|
That("fn f { deprecate msg }", "f 2>"+os.DevNull, "f").
|
|
|
|
PrintsStderrWith("msg"),
|
|
|
|
// The same call site only triggers the message once
|
|
|
|
That("fn f { deprecate msg}", "fn g { f }", "g 2>"+os.DevNull, "g 2>&1").
|
|
|
|
DoesNothing(),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2020-08-17 07:11:25 +08:00
|
|
|
func TestUseMod(t *testing.T) {
|
2021-08-07 05:18:09 +08:00
|
|
|
testutil.InTempDir(t)
|
2022-06-21 03:29:14 +08:00
|
|
|
must.WriteFile("mod.elv", "var x = value")
|
2020-08-17 07:11:25 +08:00
|
|
|
|
|
|
|
Test(t,
|
|
|
|
That("put (use-mod ./mod)[x]").Puts("value"),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2018-05-22 07:54:29 +08:00
|
|
|
func TestResolve(t *testing.T) {
|
2021-08-07 05:18:09 +08:00
|
|
|
libdir := testutil.InTempDir(t)
|
2022-06-21 03:29:14 +08:00
|
|
|
must.WriteFile("mod.elv", "fn func { }")
|
2018-10-12 11:02:14 +08:00
|
|
|
|
2021-10-05 07:52:28 +08:00
|
|
|
TestWithSetup(t, func(ev *Evaler) { ev.LibDirs = []string{libdir} },
|
2018-10-12 11:02:14 +08:00
|
|
|
That("resolve for").Puts("special"),
|
|
|
|
That("resolve put").Puts("$put~"),
|
|
|
|
That("fn f { }; resolve f").Puts("$f~"),
|
|
|
|
That("use mod; resolve mod:func").Puts("$mod:func~"),
|
|
|
|
That("resolve cat").Puts("(external cat)"),
|
2020-08-13 12:09:38 +08:00
|
|
|
That(`resolve external`).Puts("$external~"),
|
2018-10-12 11:02:14 +08:00
|
|
|
)
|
2018-03-03 03:43:38 +08:00
|
|
|
}
|