mirror of
https://github.com/go-sylixos/elvish.git
synced 2024-12-05 03:17:50 +08:00
pkg/eval: Split test functions.
This commit is contained in:
parent
c67677fd8f
commit
50c971e5dd
|
@ -11,14 +11,18 @@ import (
|
|||
"github.com/elves/elvish/pkg/eval/vals"
|
||||
)
|
||||
|
||||
func TestBuiltinFnContainer(t *testing.T) {
|
||||
func TestNsCmd(t *testing.T) {
|
||||
Test(t,
|
||||
That("put (ns [&name=value])[name]").Puts("value"),
|
||||
That("n: = (ns [&name=value]); put $n:name").Puts("value"),
|
||||
That("ns [&[]=[]]").Throws(errs.BadValue{
|
||||
What: `key of argument of "ns"`,
|
||||
Valid: "string", Actual: "list"}),
|
||||
)
|
||||
}
|
||||
|
||||
func TestMakeMap(t *testing.T) {
|
||||
Test(t,
|
||||
That("make-map []").Puts(vals.EmptyMap),
|
||||
That("make-map [[k v]]").Puts(vals.MakeMap("k", "v")),
|
||||
That("make-map [[k v] [k v2]]").Puts(vals.MakeMap("k", "v2")),
|
||||
|
@ -36,43 +40,91 @@ func TestBuiltinFnContainer(t *testing.T) {
|
|||
What: "input to make-map", Valid: "iterable with 2 elements",
|
||||
Actual: "list with 1 elements"},
|
||||
"make-map [[k]]"),
|
||||
)
|
||||
}
|
||||
|
||||
func TestRange(t *testing.T) {
|
||||
Test(t,
|
||||
That(`range 3`).Puts(0.0, 1.0, 2.0),
|
||||
That(`range 1 3`).Puts(1.0, 2.0),
|
||||
That(`range 0 10 &step=3`).Puts(0.0, 3.0, 6.0, 9.0),
|
||||
)
|
||||
}
|
||||
|
||||
func TestRepeat(t *testing.T) {
|
||||
Test(t,
|
||||
That(`repeat 4 foo`).Puts("foo", "foo", "foo", "foo"),
|
||||
)
|
||||
}
|
||||
|
||||
func TestAssoc(t *testing.T) {
|
||||
Test(t,
|
||||
That(`put (assoc [0] 0 zero)[0]`).Puts("zero"),
|
||||
That(`put (assoc [&] k v)[k]`).Puts("v"),
|
||||
That(`put (assoc [&k=v] k v2)[k]`).Puts("v2"),
|
||||
That(`has-key (dissoc [&k=v] k) k`).Puts(false),
|
||||
)
|
||||
}
|
||||
|
||||
func TestDissoc(t *testing.T) {
|
||||
Test(t,
|
||||
That(`has-key (dissoc [&k=v] k) k`).Puts(false),
|
||||
)
|
||||
}
|
||||
|
||||
func TestAll(t *testing.T) {
|
||||
Test(t,
|
||||
That(`put foo bar | all`).Puts("foo", "bar"),
|
||||
That(`echo foobar | all`).Puts("foobar"),
|
||||
That(`all [foo bar]`).Puts("foo", "bar"),
|
||||
)
|
||||
}
|
||||
|
||||
func TestOne(t *testing.T) {
|
||||
Test(t,
|
||||
That(`put foo | one`).Puts("foo"),
|
||||
That(`put | one`).Throws(AnyError),
|
||||
That(`put foo bar | one`).Throws(AnyError),
|
||||
That(`one [foo]`).Puts("foo"),
|
||||
That(`one []`).Throws(AnyError),
|
||||
That(`one [foo bar]`).Throws(AnyError),
|
||||
)
|
||||
}
|
||||
|
||||
func TestTake(t *testing.T) {
|
||||
Test(t,
|
||||
That(`range 100 | take 2`).Puts(0.0, 1.0),
|
||||
That(`range 100 | drop 98`).Puts(98.0, 99.0),
|
||||
)
|
||||
}
|
||||
|
||||
func TestDrop(t *testing.T) {
|
||||
Test(t,
|
||||
That(`range 100 | drop 98`).Puts(98.0, 99.0),
|
||||
)
|
||||
}
|
||||
|
||||
func TestHasKey(t *testing.T) {
|
||||
Test(t,
|
||||
That(`has-key [foo bar] 0`).Puts(true),
|
||||
That(`has-key [foo bar] 0:1`).Puts(true),
|
||||
That(`has-key [foo bar] 0:20`).Puts(false),
|
||||
That(`has-key [&lorem=ipsum &foo=bar] lorem`).Puts(true),
|
||||
That(`has-key [&lorem=ipsum &foo=bar] loremwsq`).Puts(false),
|
||||
)
|
||||
}
|
||||
|
||||
func TestHasValue(t *testing.T) {
|
||||
Test(t,
|
||||
That(`has-value [&lorem=ipsum &foo=bar] lorem`).Puts(false),
|
||||
That(`has-value [&lorem=ipsum &foo=bar] bar`).Puts(true),
|
||||
That(`has-value [foo bar] bar`).Puts(true),
|
||||
That(`has-value [foo bar] badehose`).Puts(false),
|
||||
That(`has-value "foo" o`).Puts(true),
|
||||
That(`has-value "foo" d`).Puts(false),
|
||||
)
|
||||
}
|
||||
|
||||
func TestCount(t *testing.T) {
|
||||
Test(t,
|
||||
That(`range 100 | count`).Puts("100"),
|
||||
That(`count [(range 100)]`).Puts("100"),
|
||||
That(`count 123`).Puts("3"),
|
||||
|
@ -81,13 +133,21 @@ func TestBuiltinFnContainer(t *testing.T) {
|
|||
What: "arguments here", ValidLow: 0, ValidHigh: 1, Actual: 3},
|
||||
"count 1 2 3"),
|
||||
That(`count $true`).Throws(ErrorWithMessage("cannot get length of a bool")),
|
||||
)
|
||||
}
|
||||
|
||||
func TestKeys(t *testing.T) {
|
||||
Test(t,
|
||||
That(`keys [&]`).DoesNothing(),
|
||||
That(`keys [&a=foo]`).Puts("a"),
|
||||
// Windows does not have an external sort command. Disabled until we have a
|
||||
// builtin sort command.
|
||||
That(`keys [&a=foo &b=bar] | order`).Puts("a", "b"),
|
||||
)
|
||||
}
|
||||
|
||||
func TestOrder(t *testing.T) {
|
||||
Test(t,
|
||||
// Ordering strings
|
||||
That("put foo bar ipsum | order").Puts("bar", "foo", "ipsum"),
|
||||
That("put foo bar bar | order").Puts("bar", "bar", "foo"),
|
||||
|
@ -143,8 +203,8 @@ func TestBuiltinFnContainer(t *testing.T) {
|
|||
// &less-than and &reverse
|
||||
That("put 1 10 2 5 | order &reverse &less-than=[a b]{ < $a $b }").
|
||||
Puts("10", "5", "2", "1"),
|
||||
// Sort should be stable - test by pretending that all values but one d
|
||||
// are equal, an check that the order among them has not change d
|
||||
// Sort should be stable - test by pretending that all values but one
|
||||
// are equal, an check that the order among them has not changed.
|
||||
That("put l x o x r x e x m | order &less-than=[a b]{ eq $a x }").
|
||||
Puts("x", "x", "x", "x", "l", "o", "r", "e", "m"),
|
||||
)
|
||||
|
|
|
@ -4,34 +4,71 @@ import (
|
|||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/elves/elvish/pkg/env"
|
||||
"github.com/elves/elvish/pkg/eval"
|
||||
|
||||
. "github.com/elves/elvish/pkg/eval/evaltest"
|
||||
"github.com/elves/elvish/pkg/eval/vals"
|
||||
)
|
||||
|
||||
func TestBuiltinFnEnv(t *testing.T) {
|
||||
oldpath := os.Getenv(env.PATH)
|
||||
listSep := string(os.PathListSeparator)
|
||||
func TestGetEnv(t *testing.T) {
|
||||
restore := saveEnv("var")
|
||||
defer restore()
|
||||
|
||||
os.Unsetenv("var")
|
||||
Test(t, That(`get-env var`).Throws(eval.ErrNonExistentEnvVar))
|
||||
|
||||
os.Setenv("var", "test1")
|
||||
Test(t,
|
||||
That(`get-env var`).Throws(eval.ErrNonExistentEnvVar),
|
||||
That(`set-env var test1`),
|
||||
That(`get-env var`).Puts("test1"),
|
||||
That(`put $E:var`).Puts("test1"),
|
||||
)
|
||||
|
||||
That(`set-env var test2`),
|
||||
os.Setenv("var", "test2")
|
||||
Test(t,
|
||||
That(`get-env var`).Puts("test2"),
|
||||
That(`put $E:var`).Puts("test2"),
|
||||
)
|
||||
}
|
||||
|
||||
That(`has-env var`).Puts(true),
|
||||
That(`unset-env var`),
|
||||
That(`has-env var`).Puts(false),
|
||||
func TestHasEnv(t *testing.T) {
|
||||
restore := saveEnv("var")
|
||||
defer restore()
|
||||
|
||||
os.Setenv("var", "test1")
|
||||
Test(t, That(`has-env var`).Puts(true))
|
||||
|
||||
os.Unsetenv("var")
|
||||
Test(t, That(`has-env var`).Puts(false))
|
||||
}
|
||||
|
||||
func TestSetEnv(t *testing.T) {
|
||||
restore := saveEnv("var")
|
||||
defer restore()
|
||||
|
||||
Test(t, That("set-env var test1").DoesNothing())
|
||||
if envVal := os.Getenv("var"); envVal != "test1" {
|
||||
t.Errorf("got $E:var = %q, want 'test1'", envVal)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetEnv_PATH(t *testing.T) {
|
||||
restore := saveEnv("PATH")
|
||||
defer restore()
|
||||
|
||||
listSep := string(os.PathListSeparator)
|
||||
Test(t,
|
||||
That(`set-env PATH /test-path`),
|
||||
That(`put $paths`).Puts(vals.MakeList("/test-path")),
|
||||
That(`paths = [/test-path2 $@paths]`),
|
||||
That(`get-env PATH`).Puts("/test-path2"+listSep+"/test-path"),
|
||||
)
|
||||
os.Setenv(env.PATH, oldpath)
|
||||
}
|
||||
|
||||
func saveEnv(name string) func() {
|
||||
oldValue, ok := os.LookupEnv(name)
|
||||
return func() {
|
||||
if ok {
|
||||
os.Setenv(name, oldValue)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,11 +9,15 @@ import (
|
|||
"github.com/elves/elvish/pkg/eval/vals"
|
||||
)
|
||||
|
||||
func TestBuiltinFnFlow(t *testing.T) {
|
||||
func TestRunParallel(t *testing.T) {
|
||||
Test(t,
|
||||
That(`run-parallel { put lorem } { echo ipsum }`).
|
||||
Puts("lorem").Prints("ipsum\n"),
|
||||
)
|
||||
}
|
||||
|
||||
func TestEach(t *testing.T) {
|
||||
Test(t,
|
||||
That(`put 1 233 | each $put~`).Puts("1", "233"),
|
||||
That(`echo "1\n233" | each $put~`).Puts("1", "233"),
|
||||
That(`echo "1\r\n233" | each $put~`).Puts("1", "233"),
|
||||
|
@ -23,8 +27,13 @@ func TestBuiltinFnFlow(t *testing.T) {
|
|||
That(`range 10 | each [x]{ if (== $x 4) { fail haha }; put $x }`).
|
||||
Puts(0.0, 1.0, 2.0, 3.0).Throws(AnyError),
|
||||
// TODO(xiaq): Test that "each" does not close the stdin.
|
||||
// TODO: test peach
|
||||
)
|
||||
}
|
||||
|
||||
// TODO: test peach
|
||||
|
||||
func TestFail(t *testing.T) {
|
||||
Test(t,
|
||||
That("fail haha").Throws(FailError{"haha"}, "fail haha"),
|
||||
That("fn f { fail haha }", "fail ?(f)").Throws(
|
||||
FailError{"haha"}, "fail haha ", "f"),
|
||||
|
@ -32,7 +41,12 @@ func TestBuiltinFnFlow(t *testing.T) {
|
|||
FailError{vals.EmptyList}, "fail []"),
|
||||
That("put ?(fail 1)[reason][type]").Puts("fail"),
|
||||
That("put ?(fail 1)[reason][content]").Puts("1"),
|
||||
|
||||
That(`return`).Throws(Return),
|
||||
)
|
||||
}
|
||||
|
||||
func TestReturn(t *testing.T) {
|
||||
Test(t,
|
||||
That("return").Throws(Return),
|
||||
// Use of return inside fn is tested in TestFn
|
||||
)
|
||||
}
|
||||
|
|
|
@ -7,47 +7,105 @@ import (
|
|||
"github.com/elves/elvish/pkg/eval/vals"
|
||||
)
|
||||
|
||||
func TestBuiltinFnIO(t *testing.T) {
|
||||
func TestPut(t *testing.T) {
|
||||
Test(t,
|
||||
That(`put foo bar`).Puts("foo", "bar"),
|
||||
That(`put $nil`).Puts(nil),
|
||||
)
|
||||
}
|
||||
|
||||
func TestReadUpto(t *testing.T) {
|
||||
Test(t,
|
||||
That("print abcd | read-upto c").Puts("abc"),
|
||||
// read-upto does not consume more than needed
|
||||
That("print abcd | { read-upto c; slurp }").Puts("abc", "d"),
|
||||
// read-upto reads up to EOF
|
||||
That("print abcd | read-upto z").Puts("abcd"),
|
||||
)
|
||||
}
|
||||
|
||||
func TestReadLine(t *testing.T) {
|
||||
Test(t,
|
||||
That(`print eof-ending | read-line`).Puts("eof-ending"),
|
||||
That(`print "lf-ending\n" | read-line`).Puts("lf-ending"),
|
||||
That(`print "crlf-ending\r\n" | read-line`).Puts("crlf-ending"),
|
||||
That(`print "extra-cr\r\r\n" | read-line`).Puts("extra-cr\r"),
|
||||
)
|
||||
}
|
||||
|
||||
func TestPrint(t *testing.T) {
|
||||
Test(t,
|
||||
That(`print [foo bar]`).Prints("[foo bar]"),
|
||||
That(`print foo bar &sep=,`).Prints("foo,bar"),
|
||||
That(`echo [foo bar]`).Prints("[foo bar]\n"),
|
||||
That(`pprint [foo bar]`).Prints("[\n foo\n bar\n]\n"),
|
||||
That(`repr foo bar ['foo bar']`).Prints("foo bar ['foo bar']\n"),
|
||||
)
|
||||
}
|
||||
|
||||
func TestEcho(t *testing.T) {
|
||||
Test(t,
|
||||
That(`echo [foo bar]`).Prints("[foo bar]\n"),
|
||||
)
|
||||
}
|
||||
|
||||
func TestPprint(t *testing.T) {
|
||||
Test(t,
|
||||
That(`pprint [foo bar]`).Prints("[\n foo\n bar\n]\n"),
|
||||
)
|
||||
}
|
||||
|
||||
func TestReprCmd(t *testing.T) {
|
||||
Test(t,
|
||||
That(`repr foo bar ['foo bar']`).Prints("foo bar ['foo bar']\n"),
|
||||
)
|
||||
}
|
||||
|
||||
func TestShow(t *testing.T) {
|
||||
Test(t,
|
||||
// A sanity test that show writes something.
|
||||
That(`show ?(fail foo) | !=s (slurp) ''`).Puts(true),
|
||||
)
|
||||
}
|
||||
|
||||
func TestOnlyBytesAndOnlyValues(t *testing.T) {
|
||||
Test(t,
|
||||
// Baseline for only-{bytes,values}
|
||||
That(`{ print bytes; put values }`).Prints("bytes").Puts("values"),
|
||||
That(`{ print bytes; put values } | only-bytes`).Prints("bytes").Puts(),
|
||||
That(`{ print bytes; put values } | only-values`).Prints("").Puts("values"),
|
||||
)
|
||||
}
|
||||
|
||||
func TestSlurp(t *testing.T) {
|
||||
Test(t,
|
||||
That(`print "a\nb" | slurp`).Puts("a\nb"),
|
||||
)
|
||||
}
|
||||
|
||||
func TestFromLines(t *testing.T) {
|
||||
Test(t,
|
||||
That(`print "a\nb" | from-lines`).Puts("a", "b"),
|
||||
That(`print "a\nb\n" | from-lines`).Puts("a", "b"),
|
||||
)
|
||||
}
|
||||
|
||||
func TestFromJson(t *testing.T) {
|
||||
Test(t,
|
||||
That(`echo '{"k": "v", "a": [1, 2]}' '"foo"' | from-json`).
|
||||
Puts(vals.MakeMap("k", "v", "a", vals.MakeList(1.0, 2.0)),
|
||||
"foo"),
|
||||
That(`echo '[null, "foo"]' | from-json`).Puts(
|
||||
vals.MakeList(nil, "foo")),
|
||||
That(`echo 'invalid' | from-json`).Throws(AnyError),
|
||||
)
|
||||
}
|
||||
|
||||
func TestToLines(t *testing.T) {
|
||||
Test(t,
|
||||
That(`put "l\norem" ipsum | to-lines`).Prints("l\norem\nipsum\n"),
|
||||
)
|
||||
}
|
||||
|
||||
func TestToJson(t *testing.T) {
|
||||
Test(t,
|
||||
That(`put [&k=v &a=[1 2]] foo | to-json`).
|
||||
Prints(`{"a":["1","2"],"k":"v"}
|
||||
"foo"
|
||||
|
|
|
@ -12,12 +12,14 @@ import (
|
|||
"github.com/elves/elvish/pkg/testutil"
|
||||
)
|
||||
|
||||
func TestBuiltinFnMisc(t *testing.T) {
|
||||
func TestConstantly(t *testing.T) {
|
||||
Test(t,
|
||||
That(`f = (constantly foo); $f; $f`).Puts("foo", "foo"),
|
||||
)
|
||||
}
|
||||
|
||||
// eval
|
||||
// ====
|
||||
func TestEval(t *testing.T) {
|
||||
Test(t,
|
||||
That("eval 'put x'").Puts("x"),
|
||||
// Using variable from the local scope.
|
||||
That("x = foo; eval 'put $x'").Puts("foo"),
|
||||
|
@ -43,9 +45,11 @@ func TestBuiltinFnMisc(t *testing.T) {
|
|||
That("eval 'put $x'").Throws(AnyError),
|
||||
// Exception.
|
||||
That("eval 'fail x'").Throws(FailError{"x"}),
|
||||
)
|
||||
}
|
||||
|
||||
// Test the "time" builtin.
|
||||
//
|
||||
func TestTime(t *testing.T) {
|
||||
Test(t,
|
||||
// Since runtime duration is non-deterministic, we only have some sanity
|
||||
// checks here.
|
||||
That("time { echo foo } | a _ = (all)", "put $a").Puts("foo"),
|
||||
|
|
|
@ -10,11 +10,15 @@ import (
|
|||
. "github.com/elves/elvish/pkg/eval/evaltest"
|
||||
)
|
||||
|
||||
func TestBuiltinFnNum(t *testing.T) {
|
||||
func TestFloat64(t *testing.T) {
|
||||
Test(t,
|
||||
That("float64 1").Puts(1.0),
|
||||
That("float64 (float64 1)").Puts(1.0),
|
||||
)
|
||||
}
|
||||
|
||||
func TestNumberComparisonCommands(t *testing.T) {
|
||||
Test(t,
|
||||
That("< 1 2 3").Puts(true),
|
||||
That("< 1 3 2").Puts(false),
|
||||
That("<= 1 1 2").Puts(true),
|
||||
|
@ -27,7 +31,11 @@ func TestBuiltinFnNum(t *testing.T) {
|
|||
That("> 3 1 2").Puts(false),
|
||||
That(">= 3 3 2").Puts(true),
|
||||
That(">= 3 2 3").Puts(false),
|
||||
)
|
||||
}
|
||||
|
||||
func TestArithmeticCommands(t *testing.T) {
|
||||
Test(t,
|
||||
// TODO test more edge cases
|
||||
That("+ 233100 233").Puts(233333.0),
|
||||
That("- 233333 233100").Puts(233.0),
|
||||
|
@ -37,7 +45,11 @@ func TestBuiltinFnNum(t *testing.T) {
|
|||
That("/ 1 0").Puts(math.Inf(1)),
|
||||
That("% 23 7").Puts("2"),
|
||||
That("% 1 0").Throws(AnyError),
|
||||
)
|
||||
}
|
||||
|
||||
func TestRandint(t *testing.T) {
|
||||
Test(t,
|
||||
That("randint 1 2").Puts("1"),
|
||||
That("i = (randint 10 100); >= $i 10; < $i 100").Puts(true, true),
|
||||
That("randint 2 1").Throws(ErrArgs, "randint 2 1"),
|
||||
|
|
|
@ -19,23 +19,39 @@ func TestBool(t *testing.T) {
|
|||
// Only errors and $false are false
|
||||
That(`bool ?(fail x)`).Puts(false),
|
||||
That(`bool $false`).Puts(false),
|
||||
)
|
||||
}
|
||||
|
||||
func TestNot(t *testing.T) {
|
||||
Test(t,
|
||||
That(`not $false`).Puts(true),
|
||||
That(`not ?(fail x)`).Puts(true),
|
||||
That(`not $true`).Puts(false),
|
||||
That(`not 0`).Puts(false),
|
||||
)
|
||||
}
|
||||
|
||||
func TestIs(t *testing.T) {
|
||||
Test(t,
|
||||
That(`is 1 1`).Puts(true),
|
||||
That(`is a b`).Puts(false),
|
||||
That(`is [] []`).Puts(true),
|
||||
That(`is [1] [1]`).Puts(false),
|
||||
)
|
||||
}
|
||||
|
||||
func TestEq(t *testing.T) {
|
||||
Test(t,
|
||||
That(`eq 1 1`).Puts(true),
|
||||
That(`eq a b`).Puts(false),
|
||||
That(`eq [] []`).Puts(true),
|
||||
That(`eq [1] [1]`).Puts(true),
|
||||
That(`eq 1 1 2`).Puts(false),
|
||||
)
|
||||
}
|
||||
|
||||
func TestNotEq(t *testing.T) {
|
||||
Test(t,
|
||||
That(`not-eq a b`).Puts(true),
|
||||
That(`not-eq a a`).Puts(false),
|
||||
// not-eq is true as long as each adjacent pair is not equal.
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
. "github.com/elves/elvish/pkg/eval/evaltest"
|
||||
)
|
||||
|
||||
func TestBuiltinFnStr(t *testing.T) {
|
||||
func TestStringComparisonCommands(t *testing.T) {
|
||||
Test(t,
|
||||
That(`<s a b`).Puts(true),
|
||||
That(`<s 2 10`).Puts(false),
|
||||
|
@ -22,28 +22,62 @@ func TestBuiltinFnStr(t *testing.T) {
|
|||
That(`>=s a a`).Puts(true),
|
||||
That(`>=s a b`).Puts(false),
|
||||
That(`>=s b a`).Puts(true),
|
||||
)
|
||||
}
|
||||
|
||||
func TestToString(t *testing.T) {
|
||||
Test(t,
|
||||
That(`to-string str (float64 1) $true`).Puts("str", "1", "$true"),
|
||||
)
|
||||
}
|
||||
|
||||
func TestOrd(t *testing.T) {
|
||||
Test(t,
|
||||
That(`ord a`).Puts("0x61"),
|
||||
That(`ord 你好`).Puts("0x4f60", "0x597d"),
|
||||
)
|
||||
}
|
||||
|
||||
func TestChr(t *testing.T) {
|
||||
Test(t,
|
||||
That(`chr 0x61`).Puts("a"),
|
||||
That(`chr 0x4f60 0x597d`).Puts("你好"),
|
||||
That(`chr -1`).Throws(AnyError),
|
||||
)
|
||||
}
|
||||
|
||||
func TestBase(t *testing.T) {
|
||||
Test(t,
|
||||
That(`base 2 1 3 4 16 255`).Puts("1", "11", "100", "10000", "11111111"),
|
||||
That(`base 16 42 233`).Puts("2a", "e9"),
|
||||
That(`base 1 1`).Throws(AnyError), // no base-1
|
||||
That(`base 37 10`).Throws(AnyError), // no letter for base-37
|
||||
)
|
||||
}
|
||||
|
||||
func TestWcswidth(t *testing.T) {
|
||||
Test(t,
|
||||
That(`wcswidth 你好`).Puts("4"),
|
||||
That(`-override-wcwidth x 10; wcswidth 1x2x; -override-wcwidth x 1`).
|
||||
Puts("22"),
|
||||
)
|
||||
}
|
||||
|
||||
func TestHasPrefix(t *testing.T) {
|
||||
Test(t,
|
||||
That(`has-prefix golang go`).Puts(true),
|
||||
That(`has-prefix golang x`).Puts(false),
|
||||
That(`has-suffix golang x`).Puts(false),
|
||||
)
|
||||
}
|
||||
|
||||
func TestHasSuffix(t *testing.T) {
|
||||
Test(t,
|
||||
That(`has-suffix golang x`).Puts(false),
|
||||
)
|
||||
}
|
||||
|
||||
func TestEawk(t *testing.T) {
|
||||
Test(t,
|
||||
That(`echo " ax by cz \n11\t22 33" | eawk [@a]{ put $a[-1] }`).
|
||||
Puts("cz", "33"),
|
||||
)
|
||||
|
|
|
@ -13,7 +13,7 @@ import (
|
|||
"github.com/elves/elvish/pkg/testutil"
|
||||
)
|
||||
|
||||
func TestBuiltinSpecial(t *testing.T) {
|
||||
func TestDel(t *testing.T) {
|
||||
Test(t,
|
||||
// del - deleting variable
|
||||
That("x = 1; del x").DoesNothing(),
|
||||
|
@ -31,48 +31,69 @@ func TestBuiltinSpecial(t *testing.T) {
|
|||
That("x = 1; del $x").DoesNotCompile(),
|
||||
That("del [a]").DoesNotCompile(),
|
||||
That("x = []; del @x").DoesNotCompile(),
|
||||
)
|
||||
}
|
||||
|
||||
// and
|
||||
func TestAnd(t *testing.T) {
|
||||
Test(t,
|
||||
That("and $true $false").Puts(false),
|
||||
// and - short circuit
|
||||
That("and a b").Puts("b"),
|
||||
That("and $false b").Puts(false),
|
||||
That("and $true b").Puts("b"),
|
||||
// short circuit
|
||||
That("x = a; and $false (x = b); put $x").Puts(false, "a"),
|
||||
)
|
||||
}
|
||||
|
||||
// or
|
||||
func TestOr(t *testing.T) {
|
||||
Test(t,
|
||||
That("or $true $false").Puts(true),
|
||||
That("or a b").Puts("a"),
|
||||
// or - short circuit
|
||||
That("or $false b").Puts("b"),
|
||||
That("or $true b").Puts(true),
|
||||
// short circuit
|
||||
That("x = a; or $true (x = b); put $x").Puts(true, "a"),
|
||||
)
|
||||
}
|
||||
|
||||
// if
|
||||
func TestIf(t *testing.T) {
|
||||
Test(t,
|
||||
That("if true { put then }").Puts("then"),
|
||||
That("if $false { put then } else { put else }").Puts("else"),
|
||||
That("if $false { put 1 } elif $false { put 2 } else { put 3 }").
|
||||
Puts("3"),
|
||||
That("if $false { put 2 } elif true { put 2 } else { put 3 }").Puts("2"),
|
||||
)
|
||||
}
|
||||
|
||||
// try
|
||||
func TestTry(t *testing.T) {
|
||||
Test(t,
|
||||
That("try { nop } except { put bad } else { put good }").Puts("good"),
|
||||
That("try { e:false } except - { put bad } else { put good }").
|
||||
Puts("bad"),
|
||||
That("try { fail tr }").Throws(ErrorWithMessage("tr")),
|
||||
That("try { fail tr } finally { put final }").
|
||||
Puts("final").Throws(ErrorWithMessage(
|
||||
"tr")),
|
||||
Puts("final").
|
||||
Throws(ErrorWithMessage("tr")),
|
||||
|
||||
That("try { fail tr } except { fail ex } finally { put final }").
|
||||
Puts("final").Throws(ErrorWithMessage(
|
||||
"ex")),
|
||||
Puts("final").
|
||||
Throws(ErrorWithMessage("ex")),
|
||||
|
||||
That("try { fail tr } except { put ex } finally { fail final }").
|
||||
Puts("ex").Throws(ErrorWithMessage(
|
||||
"final")),
|
||||
Puts("ex").
|
||||
Throws(ErrorWithMessage("final")),
|
||||
|
||||
That("try { fail tr } except { fail ex } finally { fail final }").Throws(ErrorWithMessage(
|
||||
"final")),
|
||||
That("try { fail tr } except { fail ex } finally { fail final }").
|
||||
Throws(ErrorWithMessage("final")),
|
||||
|
||||
// try - wrong use
|
||||
// wrong syntax
|
||||
That("try { nop } except @a { }").DoesNotCompile(),
|
||||
)
|
||||
}
|
||||
|
||||
func TestWhile(t *testing.T) {
|
||||
Test(t,
|
||||
// while
|
||||
That("x=0; while (< $x 4) { put $x; x=(+ $x 1) }").
|
||||
Puts("0", 1.0, 2.0, 3.0),
|
||||
|
@ -81,7 +102,11 @@ func TestBuiltinSpecial(t *testing.T) {
|
|||
That("x = 0; while (< $x 4) { put $x; x=(+ $x 1) } else { put bad }").
|
||||
Puts("0", 1.0, 2.0, 3.0),
|
||||
That("while $false { put bad } else { put good }").Puts("good"),
|
||||
)
|
||||
}
|
||||
|
||||
func TestFor(t *testing.T) {
|
||||
Test(t,
|
||||
// for
|
||||
That("for x [tempora mores] { put 'O '$x }").
|
||||
Puts("O tempora", "O mores"),
|
||||
|
@ -104,15 +129,17 @@ func TestBuiltinSpecial(t *testing.T) {
|
|||
What: "value being iterated",
|
||||
ValidLow: 1, ValidHigh: 1, Actual: 2},
|
||||
"(put a b)"),
|
||||
)
|
||||
}
|
||||
|
||||
// fn.
|
||||
func TestFn(t *testing.T) {
|
||||
Test(t,
|
||||
That("fn f [x]{ put x=$x'.' }; f lorem; f ipsum").
|
||||
Puts("x=lorem.", "x=ipsum."),
|
||||
// Recursive functions with fn. Regression test for #1206.
|
||||
That("fn f [n]{ if (== $n 0) { put 1 } else { * $n (f (- $n 1)) } }; f 3").
|
||||
Puts(6.0),
|
||||
|
||||
// return.
|
||||
// Exception thrown by return is swallowed by a fn-defined function.
|
||||
That("fn f []{ put a; return; put b }; f").Puts("a"),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
. "github.com/elves/elvish/pkg/eval/evaltest"
|
||||
)
|
||||
|
||||
func TestClosure(t *testing.T) {
|
||||
func TestClosureAsValue(t *testing.T) {
|
||||
Test(t,
|
||||
// Basic operations as a value.
|
||||
That("kind-of { }").Puts("fn"),
|
||||
|
|
|
@ -5,34 +5,30 @@ import (
|
|||
|
||||
"github.com/elves/elvish/pkg/eval/errs"
|
||||
|
||||
. "github.com/elves/elvish/pkg/eval"
|
||||
. "github.com/elves/elvish/pkg/eval/evaltest"
|
||||
"github.com/elves/elvish/pkg/eval/vals"
|
||||
"github.com/elves/elvish/pkg/eval/vars"
|
||||
"github.com/elves/elvish/pkg/testutil"
|
||||
)
|
||||
|
||||
func TestCompileEffect(t *testing.T) {
|
||||
_, cleanup := testutil.InTestDir()
|
||||
defer cleanup()
|
||||
|
||||
func TestChunk(t *testing.T) {
|
||||
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").Throws(AnyError),
|
||||
)
|
||||
}
|
||||
|
||||
// Pipelines
|
||||
// ---------
|
||||
|
||||
func TestPipeline(t *testing.T) {
|
||||
Test(t,
|
||||
// Pure byte pipeline
|
||||
That(`echo "Albert\nAllan\nAlbraham\nBerlin" | sed s/l/1/g | grep e`).
|
||||
Prints("A1bert\nBer1in\n"),
|
||||
// Pure channel pipeline
|
||||
// Pure value 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"),
|
||||
|
@ -44,10 +40,11 @@ func TestCompileEffect(t *testing.T) {
|
|||
"slurp < $p",
|
||||
"prclose $p").Puts("foo"),
|
||||
// TODO: Add a useful hybrid pipeline sample
|
||||
)
|
||||
}
|
||||
|
||||
// Commands
|
||||
// --------
|
||||
|
||||
func TestCommand(t *testing.T) {
|
||||
Test(t,
|
||||
That("put foo").Puts("foo"),
|
||||
// Command errors when the head is not a single value.
|
||||
That("{put put} foo").Throws(
|
||||
|
@ -69,14 +66,25 @@ func TestCompileEffect(t *testing.T) {
|
|||
"put &[]=[]"),
|
||||
// Command errors when any optional evaluation errors.
|
||||
That("put &x=[][1]").Throws(ErrorWithType(errs.OutOfRange{}), "[][1]"),
|
||||
)
|
||||
}
|
||||
|
||||
func TestCommand_Special(t *testing.T) {
|
||||
Test(t,
|
||||
// Regression test for #1204; ensures that the arguments of special
|
||||
// forms are not accidentally compiled twice.
|
||||
That("nop (and (use builtin)); nop $builtin:echo~").DoesNothing(),
|
||||
|
||||
// Assignments
|
||||
// -----------
|
||||
// Behavior of individual special commands are tested in
|
||||
// builtin_special_test.go.
|
||||
)
|
||||
}
|
||||
|
||||
func TestCommand_Assignment(t *testing.T) {
|
||||
// NOTE: TestClosure has more tests for the interaction between assignment
|
||||
// and variable scoping.
|
||||
|
||||
Test(t,
|
||||
// Spacey assignment.
|
||||
That("a = foo; put $a").Puts("foo"),
|
||||
That("a b = foo bar; put $a $b").Puts("foo", "bar"),
|
||||
|
@ -141,9 +149,17 @@ func TestCompileEffect(t *testing.T) {
|
|||
ValidLow: 2, ValidHigh: -1, Actual: 1},
|
||||
"x y @z = 1"),
|
||||
|
||||
// Redirections
|
||||
// ------------
|
||||
// Trying to add a new name in a namespace throws an exception.
|
||||
// Regression test for #1214.
|
||||
That("ns: = (ns [&]); ns:a = b").Throws(NoSuchVariable("ns:a"), "ns:a = b"),
|
||||
)
|
||||
}
|
||||
|
||||
func TestCommand_Redir(t *testing.T) {
|
||||
_, cleanup := testutil.InTestDir()
|
||||
defer cleanup()
|
||||
|
||||
Test(t,
|
||||
// Output and input redirection.
|
||||
That("echo 233 > out1", " slurp < out1").Puts("233\n"),
|
||||
// Append.
|
||||
|
@ -198,7 +214,7 @@ func TestCompileEffect(t *testing.T) {
|
|||
)
|
||||
}
|
||||
|
||||
func TestStacktrace(t *testing.T) {
|
||||
func TestCommand_Stacktrace(t *testing.T) {
|
||||
oops := ErrorWithMessage("oops")
|
||||
Test(t,
|
||||
// Stack traces.
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
package eval_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/elves/elvish/pkg/eval"
|
||||
. "github.com/elves/elvish/pkg/eval/evaltest"
|
||||
)
|
||||
|
||||
func TestAssignment(t *testing.T) {
|
||||
Test(t,
|
||||
That("x = a; put $x").Puts("a"),
|
||||
That("x = [a]; x[0] = b; put $x[0]").Puts("b"),
|
||||
That("x = a; { x = b }; put $x").Puts("b"),
|
||||
That("x = [a]; { x[0] = b }; put $x[0]").Puts("b"),
|
||||
|
||||
// Trying to add a new name in a namespace throws an exception.
|
||||
// Regression test for #1214.
|
||||
That("ns: = (ns [&]); ns:a = b").Throws(NoSuchVariable("ns:a"), "ns:a = b"),
|
||||
)
|
||||
}
|
|
@ -11,15 +11,8 @@ import (
|
|||
"github.com/elves/elvish/pkg/eval/vals"
|
||||
)
|
||||
|
||||
func TestCompileValue(t *testing.T) {
|
||||
home, cleanup := testutil.InTempHome()
|
||||
testutil.MustCreateEmpty("file1")
|
||||
testutil.MustCreateEmpty("file2")
|
||||
defer cleanup()
|
||||
|
||||
func TestCompound(t *testing.T) {
|
||||
Test(t,
|
||||
// Compounding
|
||||
// -----------
|
||||
That("put {fi,elvi}sh{1.0,1.1}").Puts(
|
||||
"fish1.0", "fish1.1", "elvish1.0", "elvish1.1"),
|
||||
|
||||
|
@ -36,52 +29,90 @@ func TestCompileValue(t *testing.T) {
|
|||
That("put []a").Throws(ErrorWithMessage("cannot concatenate list and string")),
|
||||
// Error when applying tilde throws an exception.
|
||||
That("put ~[]").Throws(ErrorWithMessage("tilde doesn't work on value of type list")),
|
||||
)
|
||||
}
|
||||
|
||||
// List, Map and Indexing
|
||||
// ----------------------
|
||||
|
||||
That("echo [a b c] [&key=value] | each $put~").
|
||||
Puts("[a b c] [&key=value]"),
|
||||
func TestIndexing(t *testing.T) {
|
||||
Test(t,
|
||||
That("put [a b c][2]").Puts("c"),
|
||||
That("put [][0]").Throws(ErrorWithType(errs.OutOfRange{}), "[][0]"),
|
||||
That("put [&key=value][key]").Puts("value"),
|
||||
That("put [&key=value][bad]").Throws(
|
||||
vals.NoSuchKey("bad"), "[&key=value][bad]"),
|
||||
)
|
||||
}
|
||||
|
||||
func TestListLiteral(t *testing.T) {
|
||||
Test(t,
|
||||
That("put [a b c]").Puts(vals.MakeList("a", "b", "c")),
|
||||
That("put []").Puts(vals.EmptyList),
|
||||
// List expression errors if an element expression errors.
|
||||
That("put [ [][0] ]").Throws(ErrorWithType(errs.OutOfRange{}), "[][0]"),
|
||||
)
|
||||
}
|
||||
|
||||
func TestMapLiteral(t *testing.T) {
|
||||
Test(t,
|
||||
That("put [&key=value]").Puts(vals.MakeMap("key", "value")),
|
||||
That("put [&]").Puts(vals.EmptyMap),
|
||||
// Map keys and values may evaluate to multiple values as long as their
|
||||
// numbers match.
|
||||
That("put [&{a b}={foo bar}]").Puts(vals.MakeMap("a", "foo", "b", "bar")),
|
||||
|
||||
// List expression errors if an element expression errors.
|
||||
That("put [ [][0] ]").Throws(ErrorWithType(errs.OutOfRange{}), "[][0]"),
|
||||
// Map expression errors if a key or value expression errors.
|
||||
That("put [ &[][0]=a ]").Throws(ErrorWithType(errs.OutOfRange{}), "[][0]"),
|
||||
That("put [ &a=[][0] ]").Throws(ErrorWithType(errs.OutOfRange{}), "[][0]"),
|
||||
// Map expression errors if number of keys and values in a single pair
|
||||
// does not match.
|
||||
That("put [&{a b}={foo bar lorem}]").Throws(ErrorWithMessage("2 keys but 3 values")),
|
||||
)
|
||||
}
|
||||
|
||||
// String Literals
|
||||
// ---------------
|
||||
func TestStringLiteral(t *testing.T) {
|
||||
Test(t,
|
||||
That(`put 'such \"''literal'`).Puts(`such \"'literal`),
|
||||
That(`put "much \n\033[31;1m$cool\033[m"`).
|
||||
Puts("much \n\033[31;1m$cool\033[m"),
|
||||
)
|
||||
}
|
||||
|
||||
// Captures
|
||||
// ---------
|
||||
func TestTilde(t *testing.T) {
|
||||
home, cleanup := testutil.InTempHome()
|
||||
testutil.MustCreateEmpty("file1")
|
||||
testutil.MustCreateEmpty("file2")
|
||||
defer cleanup()
|
||||
|
||||
Test(t,
|
||||
// Tilde
|
||||
// -----
|
||||
That("put ~").Puts(home),
|
||||
That("put ~/src").Puts(home+"/src"),
|
||||
// Make sure that tilde processing retains trailing slashes.
|
||||
That("put ~/src/").Puts(home+"/src/"),
|
||||
// Tilde and wildcard.
|
||||
That("put ~/*").Puts(home+"/file1", home+"/file2"),
|
||||
// TODO(xiaq): Add regression test for #793.
|
||||
)
|
||||
}
|
||||
|
||||
func TestOutputCapture(t *testing.T) {
|
||||
Test(t,
|
||||
// Output capture
|
||||
That("put (put lorem ipsum)").Puts("lorem", "ipsum"),
|
||||
That("put (print \"lorem\nipsum\")").Puts("lorem", "ipsum"),
|
||||
// \r\n is also supported as a line separator
|
||||
That(`print "lorem\r\nipsum\r\n" | all`).Puts("lorem", "ipsum"),
|
||||
)
|
||||
}
|
||||
|
||||
func TestExceptionCapture(t *testing.T) {
|
||||
Test(t,
|
||||
// Exception capture
|
||||
That("bool ?(nop); bool ?(e:false)").Puts(true, false),
|
||||
)
|
||||
}
|
||||
|
||||
// Variable Use
|
||||
// ------------
|
||||
|
||||
func TestVariableUse(t *testing.T) {
|
||||
Test(t,
|
||||
That("x = foo", "put $x").Puts("foo"),
|
||||
// Must exist before use
|
||||
That("put $x").DoesNotCompile(),
|
||||
|
@ -136,27 +167,22 @@ func TestCompileValue(t *testing.T) {
|
|||
// Multi-level namespace access can be combined with the up:
|
||||
// pseudo-namespaces.
|
||||
That("ns: = (ns [&a:= (ns [&b= val])]); { put $up:ns:a:b }").Puts("val"),
|
||||
)
|
||||
}
|
||||
|
||||
// Tilde
|
||||
// -----
|
||||
That("put ~").Puts(home),
|
||||
That("put ~/src").Puts(home+"/src"),
|
||||
// Make sure that tilde processing retains trailing slashes.
|
||||
That("put ~/src/").Puts(home+"/src/"),
|
||||
// Tilde and wildcard.
|
||||
That("put ~/*").Puts(home+"/file1", home+"/file2"),
|
||||
// TODO(xiaq): Add regression test for #793.
|
||||
|
||||
// Closure
|
||||
// -------
|
||||
|
||||
func TestClosure(t *testing.T) {
|
||||
Test(t,
|
||||
That("[]{ }").DoesNothing(),
|
||||
That("[x]{put $x} foo").Puts("foo"),
|
||||
|
||||
// Variable capture
|
||||
// Assigning to captured variable
|
||||
That("x=lorem; []{x=ipsum}; put $x").Puts("ipsum"),
|
||||
That("x=lorem; []{ put $x; x=ipsum }; put $x").Puts("lorem", "ipsum"),
|
||||
|
||||
// Assigning to element of captured variable
|
||||
That("x = a; { x = b }; put $x").Puts("b"),
|
||||
That("x = [a]; { x[0] = b }; put $x[0]").Puts("b"),
|
||||
|
||||
// Shadowing
|
||||
That("x=ipsum; []{ local:x=lorem; put $x }; put $x").Puts("lorem", "ipsum"),
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user