github.com/kolbycrouch/elvish@v0.14.1-0.20210614162631-215b9ac1c423/pkg/eval/builtin_fn_misc_test.go (about) 1 package eval_test 2 3 import ( 4 "os" 5 "testing" 6 "time" 7 8 . "src.elv.sh/pkg/eval" 9 10 . "src.elv.sh/pkg/eval/evaltest" 11 "src.elv.sh/pkg/eval/vals" 12 "src.elv.sh/pkg/testutil" 13 ) 14 15 func TestConstantly(t *testing.T) { 16 Test(t, 17 That(`f = (constantly foo); $f; $f`).Puts("foo", "foo"), 18 ) 19 } 20 21 func TestEval(t *testing.T) { 22 Test(t, 23 That("eval 'put x'").Puts("x"), 24 // Using variable from the local scope. 25 That("x = foo; eval 'put $x'").Puts("foo"), 26 // Setting a variable in the local scope. 27 That("x = foo; eval 'x = bar'; put $x").Puts("bar"), 28 // Using variable from the upvalue scope. 29 That("x = foo; { nop $x; eval 'put $x' }").Puts("foo"), 30 // Specifying a namespace. 31 That("n = (ns [&x=foo]); eval 'put $x' &ns=$n").Puts("foo"), 32 // Altering variables in the specified namespace. 33 That("n = (ns [&x=foo]); eval 'x = bar' &ns=$n; put $n[x]").Puts("bar"), 34 // Newly created variables do not appear in the local namespace. 35 That("eval 'x = foo'; put $x").DoesNotCompile(), 36 // Newly created variables do not alter the specified namespace, either. 37 That("n = (ns [&]); eval &ns=$n 'x = foo'; put $n[x]"). 38 Throws(vals.NoSuchKey("x"), "$n[x]"), 39 // However, newly created variable can be accessed in the final 40 // namespace using &on-end. 41 That("eval &on-end=[n]{ put $n[x] } 'x = foo'").Puts("foo"), 42 // Parse error. 43 That("eval '['").Throws(AnyError), 44 // Compilation error. 45 That("eval 'put $x'").Throws(AnyError), 46 // Exception. 47 That("eval 'fail x'").Throws(FailError{"x"}), 48 ) 49 } 50 51 func TestDeprecate(t *testing.T) { 52 Test(t, 53 That("deprecate msg").PrintsStderrWith("msg"), 54 // Different call sites trigger multiple deprecation messages 55 That("fn f { deprecate msg }", "f 2>"+os.DevNull, "f"). 56 PrintsStderrWith("msg"), 57 // The same call site only triggers the message once 58 That("fn f { deprecate msg}", "fn g { f }", "g 2>"+os.DevNull, "g 2>&1"). 59 DoesNothing(), 60 ) 61 } 62 63 func TestTime(t *testing.T) { 64 Test(t, 65 // Since runtime duration is non-deterministic, we only have some sanity 66 // checks here. 67 That("time { echo foo } | a _ = (all)", "put $a").Puts("foo"), 68 That("duration = ''", 69 "time &on-end=[x]{ duration = $x } { echo foo } | out = (all)", 70 "put $out", "kind-of $duration").Puts("foo", "number"), 71 That("time { fail body } | nop (all)").Throws(FailError{"body"}), 72 That("time &on-end=[_]{ fail on-end } { }").Throws( 73 FailError{"on-end"}), 74 75 That("time &on-end=[_]{ fail on-end } { fail body }").Throws( 76 FailError{"body"}), 77 ) 78 } 79 80 func TestUseMod(t *testing.T) { 81 _, cleanup := testutil.InTestDir() 82 defer cleanup() 83 testutil.MustWriteFile("mod.elv", []byte("x = value"), 0600) 84 85 Test(t, 86 That("put (use-mod ./mod)[x]").Puts("value"), 87 ) 88 } 89 90 func timeAfterMock(fm *Frame, d time.Duration) <-chan time.Time { 91 fm.OutputChan() <- d // report to the test framework the duration we received 92 return time.After(0) 93 } 94 95 func TestSleep(t *testing.T) { 96 TimeAfter = timeAfterMock 97 Test(t, 98 That(`sleep 0`).Puts(0*time.Second), 99 That(`sleep 1`).Puts(1*time.Second), 100 That(`sleep 1.3s`).Puts(1300*time.Millisecond), 101 That(`sleep 0.1`).Puts(100*time.Millisecond), 102 That(`sleep 0.1ms`).Puts(100*time.Microsecond), 103 That(`sleep 3h5m7s`).Puts((3*3600+5*60+7)*time.Second), 104 105 That(`sleep 1x`).Throws(ErrInvalidSleepDuration, "sleep 1x"), 106 That(`sleep -7`).Throws(ErrNegativeSleepDuration, "sleep -7"), 107 That(`sleep -3h`).Throws(ErrNegativeSleepDuration, "sleep -3h"), 108 109 That(`sleep 1/2`).Puts(time.Second/2), // rational number string 110 111 // Verify the correct behavior if a numeric type, rather than a string, is passed to the 112 // command. 113 That(`sleep (num 42)`).Puts(42*time.Second), 114 That(`sleep (float64 0)`).Puts(0*time.Second), 115 That(`sleep (float64 1.7)`).Puts(1700*time.Millisecond), 116 That(`sleep (float64 -7)`).Throws(ErrNegativeSleepDuration, "sleep (float64 -7)"), 117 118 // An invalid argument type should raise an exception. 119 That(`sleep [1]`).Throws(ErrInvalidSleepDuration, "sleep [1]"), 120 ) 121 } 122 123 func TestResolve(t *testing.T) { 124 libdir, cleanup := testutil.InTestDir() 125 defer cleanup() 126 127 testutil.MustWriteFile("mod.elv", []byte("fn func { }"), 0600) 128 129 TestWithSetup(t, func(ev *Evaler) { ev.SetLibDir(libdir) }, 130 That("resolve for").Puts("special"), 131 That("resolve put").Puts("$put~"), 132 That("fn f { }; resolve f").Puts("$f~"), 133 That("use mod; resolve mod:func").Puts("$mod:func~"), 134 That("resolve cat").Puts("(external cat)"), 135 That(`resolve external`).Puts("$external~"), 136 ) 137 }