github.com/markusbkk/elvish@v0.0.0-20231204143114-91dc52438621/pkg/eval/builtin_special_test.go (about)

     1  package eval_test
     2  
     3  import (
     4  	"errors"
     5  	"testing"
     6  
     7  	"github.com/markusbkk/elvish/pkg/diag"
     8  	. "github.com/markusbkk/elvish/pkg/eval"
     9  	"github.com/markusbkk/elvish/pkg/eval/errs"
    10  	"github.com/markusbkk/elvish/pkg/eval/vals"
    11  	"github.com/markusbkk/elvish/pkg/eval/vars"
    12  	"github.com/markusbkk/elvish/pkg/parse"
    13  	"github.com/markusbkk/elvish/pkg/prog/progtest"
    14  
    15  	. "github.com/markusbkk/elvish/pkg/eval/evaltest"
    16  	. "github.com/markusbkk/elvish/pkg/testutil"
    17  )
    18  
    19  func TestPragma(t *testing.T) {
    20  	Test(t,
    21  		That("pragma unknown-command").DoesNotCompile(),
    22  		That("pragma unknown-command =").DoesNotCompile(),
    23  		That("pragma unknown-command x").DoesNotCompile(),
    24  		That("pragma bad-name = some-value").DoesNotCompile(),
    25  		That("pragma unknown-command = bad").DoesNotCompile(),
    26  	)
    27  	// Actual effect of the unknown-command pragma is tested in TestCommand_External
    28  }
    29  
    30  func TestVar(t *testing.T) {
    31  	// NOTE: TestClosure has more tests for the interaction between assignment
    32  	// and variable scoping.
    33  
    34  	Test(t,
    35  		// Declaring one variable
    36  		That("var x", "put $x").Puts(nil),
    37  		// Declaring one variable whose name needs to be quoted
    38  		That("var 'a/b'", "put $'a/b'").Puts(nil),
    39  		// Declaring one variable whose name ends in ":".
    40  		That("var a:").DoesNothing(),
    41  		// Declaring a variable whose name ends in "~" initializes it to the
    42  		// builtin nop function.
    43  		That("var cmd~; cmd &ignored-opt ignored-arg").DoesNothing(),
    44  		// Declaring multiple variables
    45  		That("var x y", "put $x $y").Puts(nil, nil),
    46  		// Declaring one variable with initial value
    47  		That("var x = foo", "put $x").Puts("foo"),
    48  		// Declaring multiple variables with initial values
    49  		That("var x y = foo bar", "put $x $y").Puts("foo", "bar"),
    50  		// Declaring multiple variables with initial values, including a rest
    51  		// variable in the assignment LHS
    52  		That("var x @y z = a b c d", "put $x $y $z").
    53  			Puts("a", vals.MakeList("b", "c"), "d"),
    54  		// An empty RHS is technically legal although rarely useful.
    55  		That("var @x =", "put $x").Puts(vals.EmptyList),
    56  		// Shadowing.
    57  		That("var x = old; fn f { put $x }", "var x = new; put $x; f").
    58  			Puts("new", "old"),
    59  
    60  		// Concurrently creating a new variable and accessing existing variable.
    61  		// Run with "go test -race".
    62  		That("var x = 1", "put $x | var y = (all)").DoesNothing(),
    63  		That("nop (var x = 1) | nop").DoesNothing(),
    64  
    65  		// Assignment errors when the RHS errors.
    66  		That("var x = [][1]").Throws(ErrorWithType(errs.OutOfRange{}), "[][1]"),
    67  		// Arity mismatch.
    68  		That("var x = 1 2").Throws(
    69  			errs.ArityMismatch{What: "assignment right-hand-side",
    70  				ValidLow: 1, ValidHigh: 1, Actual: 2},
    71  			"var x = 1 2"),
    72  		That("var x y = 1").Throws(
    73  			errs.ArityMismatch{What: "assignment right-hand-side",
    74  				ValidLow: 2, ValidHigh: 2, Actual: 1},
    75  			"var x y = 1"),
    76  		That("var x y @z = 1").Throws(
    77  			errs.ArityMismatch{What: "assignment right-hand-side",
    78  				ValidLow: 2, ValidHigh: -1, Actual: 1},
    79  			"var x y @z = 1"),
    80  
    81  		// Variable name that must be quoted after $ must be quoted
    82  		That("var a/b").DoesNotCompile(),
    83  		// Multiple @ not allowed
    84  		That("var x @y @z = a b c d").DoesNotCompile(),
    85  		// Non-local not allowed
    86  		That("var ns:a").DoesNotCompile(),
    87  		// Index not allowed
    88  		That("var a[0]").DoesNotCompile(),
    89  		// Composite expression not allowed
    90  		That("var a'b'").DoesNotCompile(),
    91  	)
    92  }
    93  
    94  func TestSet(t *testing.T) {
    95  	Test(t,
    96  		// Setting one variable
    97  		That("var x; set x = foo", "put $x").Puts("foo"),
    98  		// An empty RHS is technically legal although rarely useful.
    99  		That("var x; set @x =", "put $x").Puts(vals.EmptyList),
   100  		// Variable must already exist
   101  		That("set x = foo").DoesNotCompile(),
   102  		// List element assignment
   103  		That("var li = [foo bar]; set li[0] = 233; put $@li").Puts("233", "bar"),
   104  		// Variable in list assignment must already be defined. Regression test
   105  		// for b.elv.sh/889.
   106  		That("set foobarlorem[0] = a").DoesNotCompile(),
   107  		// Map element assignment
   108  		That("var di = [&k=v]; set di[k] = lorem; set di[k2] = ipsum",
   109  			"put $di[k] $di[k2]").Puts("lorem", "ipsum"),
   110  		That("var d = [&a=[&b=v]]; put $d[a][b]; set d[a][b] = u; put $d[a][b]").
   111  			Puts("v", "u"),
   112  		That("var li = [foo]; set li[(fail foo)] = bar").Throws(FailError{"foo"}),
   113  		That("var li = [foo]; set li[0 1] = foo bar").
   114  			Throws(ErrorWithMessage("multi indexing not implemented")),
   115  		That("var li = [[]]; set li[1][2] = bar").
   116  			Throws(errs.OutOfRange{What: "index",
   117  				ValidLow: "0", ValidHigh: "0", Actual: "1"}, "li[1][2]"),
   118  
   119  		// Assignment to read-only var is a compile-time error.
   120  		That("set nil = 1").DoesNotCompile(),
   121  		That("var a b; set a true b = 1 2 3").DoesNotCompile(),
   122  		That("set @true = 1").DoesNotCompile(),
   123  		That("var r; set true @r = 1").DoesNotCompile(),
   124  		That("var r; set @r true = 1").DoesNotCompile(),
   125  
   126  		// Error conditions already covered by TestVar are not repeated.
   127  
   128  		// = is required.
   129  		That("var x; set x").DoesNotCompile(),
   130  	)
   131  }
   132  
   133  func TestSet_ErrorInSetMethod(t *testing.T) {
   134  	TestWithSetup(t, func(ev *Evaler) { addBadVar(ev, 0) },
   135  		That("set bad = foo").Throws(errBadVar, "bad"),
   136  		That("var a; set bad @a = foo").Throws(errBadVar, "bad"),
   137  		That("var a; set a @bad = foo").Throws(errBadVar, "@bad"),
   138  		That("var a; set @a bad = foo").Throws(errBadVar, "bad"),
   139  	)
   140  }
   141  
   142  func TestTmp(t *testing.T) {
   143  	Test(t,
   144  		That("var x = foo; put $x; { tmp x = bar; put $x }; put $x").
   145  			Puts("foo", "bar", "foo"),
   146  
   147  		That("var x; tmp x = y").DoesNotCompile(),
   148  		That("{ tmp x = y }").DoesNotCompile(),
   149  	)
   150  }
   151  
   152  func TestTmp_ErrorSetting(t *testing.T) {
   153  	TestWithSetup(t, func(ev *Evaler) { addBadVar(ev, 0) },
   154  		That("{ tmp bad = foo }").Throws(errBadVar, "bad", "{ tmp bad = foo }"),
   155  	)
   156  }
   157  
   158  func TestTmp_ErrorRestoring(t *testing.T) {
   159  	TestWithSetup(t, func(ev *Evaler) { addBadVar(ev, 1) },
   160  		That("{ tmp bad = foo; put after }").
   161  			Puts("after").
   162  			Throws(ErrorWithMessage("restore variable: bad var"),
   163  				"bad", "{ tmp bad = foo; put after }"),
   164  	)
   165  }
   166  
   167  func addBadVar(ev *Evaler, allowedSets int) {
   168  	ev.ExtendGlobal(BuildNs().AddVar("bad", &badVar{allowedSets}))
   169  }
   170  
   171  var errBadVar = errors.New("bad var")
   172  
   173  type badVar struct{ allowedSets int }
   174  
   175  func (v *badVar) Get() interface{} { return nil }
   176  
   177  func (v *badVar) Set(interface{}) error {
   178  	if v.allowedSets == 0 {
   179  		return errBadVar
   180  	}
   181  	v.allowedSets--
   182  	return nil
   183  }
   184  
   185  func TestDel(t *testing.T) {
   186  	Setenv(t, "TEST_ENV", "test value")
   187  
   188  	Test(t,
   189  		// Deleting variable
   190  		That("var x = 1; del x").DoesNothing(),
   191  		That("var x = 1; del x; echo $x").DoesNotCompile(),
   192  		// Deleting environment variable
   193  		That("has-env TEST_ENV", "del E:TEST_ENV", "has-env TEST_ENV").Puts(true, false),
   194  		// Deleting variable whose name contains special characters
   195  		That("var 'a/b' = foo; del 'a/b'").DoesNothing(),
   196  		// Deleting element
   197  		That("var x = [&k=v &k2=v2]; del x[k2]; keys $x").Puts("k"),
   198  		That("var x = [[&k=v &k2=v2]]; del x[0][k2]; keys $x[0]").Puts("k"),
   199  
   200  		// Error cases
   201  
   202  		// Deleting nonexistent variable
   203  		That("del x").DoesNotCompile(),
   204  		// Deleting element of nonexistent variable
   205  		That("del x[0]").DoesNotCompile(),
   206  		// Deleting variable in non-local namespace
   207  		That("var a: = (ns [&b=$nil])", "del a:b").DoesNotCompile(),
   208  		// Variable name given with $
   209  		That("var x = 1; del $x").DoesNotCompile(),
   210  		// Variable name not given as a single primary expression
   211  		That("var ab = 1; del a'b'").DoesNotCompile(),
   212  		// Variable name not a string
   213  		That("del [a]").DoesNotCompile(),
   214  		// Variable name has sigil
   215  		That("var x = []; del @x").DoesNotCompile(),
   216  		// Variable name not quoted when it should be
   217  		That("var 'a/b' = foo; del a/b").DoesNotCompile(),
   218  
   219  		// Index is multiple values
   220  		That("var x = [&k1=v1 &k2=v2]", "del x[k1 k2]").Throws(
   221  			ErrorWithMessage("index must evaluate to a single value in argument to del"),
   222  			"k1 k2"),
   223  		// Index expression throws exception
   224  		That("var x = [&k]", "del x[(fail x)]").Throws(FailError{"x"}, "fail x"),
   225  		// Value does not support element removal
   226  		That("var x = (num 1)", "del x[k]").Throws(
   227  			ErrorWithMessage("value does not support element removal"),
   228  			// TODO: Fix the stack trace so that it is "x[k]"
   229  			"x[k"),
   230  		// Intermediate element does not exist
   231  		That("var x = [&]", "del x[k][0]").Throws(
   232  			ErrorWithMessage("no such key: k"),
   233  			// TODO: Fix the stack trace so that it is "x[k]"
   234  			"x"),
   235  	)
   236  }
   237  
   238  func TestAnd(t *testing.T) {
   239  	Test(t,
   240  		That("and $true $false").Puts(false),
   241  		That("and a b").Puts("b"),
   242  		That("and $false b").Puts(false),
   243  		That("and $true b").Puts("b"),
   244  		// short circuit
   245  		That("var x = a; and $false (x = b); put $x").Puts(false, "a"),
   246  
   247  		// Exception
   248  		That("and a (fail x)").Throws(FailError{"x"}, "fail x"),
   249  		thatOutputErrorIsBubbled("and a"),
   250  	)
   251  }
   252  
   253  func TestOr(t *testing.T) {
   254  	Test(t,
   255  		That("or $true $false").Puts(true),
   256  		That("or a b").Puts("a"),
   257  		That("or $false b").Puts("b"),
   258  		That("or $true b").Puts(true),
   259  		// short circuit
   260  		That("var x = a; or $true (x = b); put $x").Puts(true, "a"),
   261  
   262  		// Exception
   263  		That("or $false (fail x)").Throws(FailError{"x"}, "fail x"),
   264  		thatOutputErrorIsBubbled("or a"),
   265  	)
   266  }
   267  
   268  func TestCoalesce(t *testing.T) {
   269  	Test(t,
   270  		That("coalesce a b").Puts("a"),
   271  		That("coalesce $nil b").Puts("b"),
   272  		That("coalesce $nil $nil").Puts(nil),
   273  		That("coalesce").Puts(nil),
   274  		// exception propagation
   275  		That("coalesce $nil (fail foo)").Throws(FailError{"foo"}),
   276  		// short circuit
   277  		That("coalesce a (fail foo)").Puts("a"),
   278  
   279  		thatOutputErrorIsBubbled("coalesce a"),
   280  	)
   281  }
   282  
   283  func TestSpecialFormThunks(t *testing.T) {
   284  	// Regression test for b.elv.sh/1456
   285  	Test(t,
   286  		That("for x [] {|arg| }").DoesNotCompile(),
   287  		That("for x [] {|&opt=val| }").DoesNotCompile(),
   288  		// The other special forms use the same utility under the hood and are
   289  		// not repeated
   290  	)
   291  }
   292  
   293  func TestIf(t *testing.T) {
   294  	Test(t,
   295  		That("if true { put then }").Puts("then"),
   296  		That("if $false { put then } else { put else }").Puts("else"),
   297  		That("if $false { put 1 } elif $false { put 2 } else { put 3 }").
   298  			Puts("3"),
   299  		That("if $false { put 2 } elif true { put 2 } else { put 3 }").Puts("2"),
   300  
   301  		// Exception in condition expression
   302  		That("if (fail x) { }").Throws(FailError{"x"}, "fail x"),
   303  	)
   304  }
   305  
   306  func TestTry(t *testing.T) {
   307  	Test(t,
   308  		That("try { nop } except { put bad } else { put good }").Puts("good"),
   309  		That("try { e:false } except - { put bad } else { put good }").
   310  			Puts("bad"),
   311  		That("try { fail tr }").Throws(ErrorWithMessage("tr")),
   312  		That("try { fail tr } finally { put final }").
   313  			Puts("final").
   314  			Throws(ErrorWithMessage("tr")),
   315  
   316  		That("try { fail tr } except { fail ex } finally { put final }").
   317  			Puts("final").
   318  			Throws(ErrorWithMessage("ex")),
   319  
   320  		That("try { fail tr } except { put ex } finally { fail final }").
   321  			Puts("ex").
   322  			Throws(ErrorWithMessage("final")),
   323  
   324  		That("try { fail tr } except { fail ex } finally { fail final }").
   325  			Throws(ErrorWithMessage("final")),
   326  
   327  		// wrong syntax
   328  		That("try { nop } except @a { }").DoesNotCompile(),
   329  
   330  		// A readonly var as a target for the "except" clause is a compile-time
   331  		// error.
   332  		That("try { fail reason } except nil { }").DoesNotCompile(),
   333  		That("try { fail reason } except x { }").DoesNothing(),
   334  
   335  		// A quoted var name, that would be invalid as a bareword, should be allowed as the referent
   336  		// in a `try...except...` block.
   337  		That("try { fail hard } except 'x=' { put 'x= ='(to-string $'x=') }").
   338  			Puts("x= =[&reason=[&content=hard &type=fail]]"),
   339  	)
   340  }
   341  
   342  func TestWhile(t *testing.T) {
   343  	Test(t,
   344  		That("var x = (num 0)", "while (< $x 4) { put $x; set x = (+ $x 1) }").
   345  			Puts(0, 1, 2, 3),
   346  		// break
   347  		That("var x = (num 0)", "while (< $x 4) { put $x; break }").Puts(0),
   348  		// continue
   349  		That("var x = (num 0)",
   350  			"while (< $x 4) { put $x; set x = (+ $x 1); continue; put bad }").
   351  			Puts(0, 1, 2, 3),
   352  		// Exception in body
   353  		That("var x = 0; while (< $x 4) { fail haha }").Throws(FailError{"haha"}),
   354  		// Exception in condition
   355  		That("while (fail x) { }").Throws(FailError{"x"}, "fail x"),
   356  
   357  		// else branch - not taken
   358  		That("var x = 0; while (< $x 4) { put $x; set x = (+ $x 1) } else { put bad }").
   359  			Puts("0", 1, 2, 3),
   360  		// else branch - taken
   361  		That("while $false { put bad } else { put good }").Puts("good"),
   362  	)
   363  }
   364  
   365  func TestFor(t *testing.T) {
   366  	Test(t,
   367  		// for
   368  		That("for x [tempora mores] { put 'O '$x }").
   369  			Puts("O tempora", "O mores"),
   370  		// break
   371  		That("for x [a] { break } else { put $x }").DoesNothing(),
   372  		// else
   373  		That("for x [a] { put $x } else { put $x }").Puts("a"),
   374  		// continue
   375  		That("for x [a b] { put $x; continue; put $x; }").Puts("a", "b"),
   376  		// else
   377  		That("for x [] { } else { put else }").Puts("else"),
   378  		That("for x [a] { } else { put else }").DoesNothing(),
   379  		// Propagating exception.
   380  		That("for x [a] { fail foo }").Throws(FailError{"foo"}),
   381  
   382  		// More than one iterator.
   383  		That("for {x,y} [] { }").DoesNotCompile(),
   384  		// Invalid for loop lvalue. You can't use a var in a namespace other
   385  		// than the local namespace as the lvalue in a for loop.
   386  		That("for no-such-namespace:x [a b] { }").DoesNotCompile(),
   387  		// Exception with the variable
   388  		That("var a: = (ns [&])", "for a:b [] { }").Throws(
   389  			ErrorWithMessage("no variable $a:b"),
   390  			"a:b"),
   391  		// Exception when evaluating iterable.
   392  		That("for x [][0] { }").Throws(ErrorWithType(errs.OutOfRange{}), "[][0]"),
   393  		// More than one iterable.
   394  		That("for x (put a b) { }").Throws(
   395  			errs.ArityMismatch{What: "value being iterated",
   396  				ValidLow: 1, ValidHigh: 1, Actual: 2},
   397  			"(put a b)"),
   398  		// Non-iterable value
   399  		That("for x (num 0) { }").Throws(ErrorWithMessage("cannot iterate number")),
   400  	)
   401  }
   402  
   403  func TestFn(t *testing.T) {
   404  	Test(t,
   405  		That("fn f {|x| put x=$x'.' }; f lorem; f ipsum").
   406  			Puts("x=lorem.", "x=ipsum."),
   407  		// Recursive functions with fn. Regression test for #1206.
   408  		That("fn f {|n| if (== $n 0) { num 1 } else { * $n (f (- $n 1)) } }; f 3").
   409  			Puts(6),
   410  		// Exception thrown by return is swallowed by a fn-defined function.
   411  		That("fn f { put a; return; put b }; f").Puts("a"),
   412  
   413  		// Error when evaluating the lambda
   414  		That("fn f {|&opt=(fail x)| }").Throws(FailError{"x"}, "fail x"),
   415  	)
   416  }
   417  
   418  // Regression test for #1225
   419  func TestUse_SetsVariableCorrectlyIfModuleCallsExtendGlobal(t *testing.T) {
   420  	libdir := InTempDir(t)
   421  
   422  	ApplyDir(Dir{"a.elv": "add-var"})
   423  	ev := NewEvaler()
   424  	ev.LibDirs = []string{libdir}
   425  	addVar := func() {
   426  		ev.ExtendGlobal(BuildNs().AddVar("b", vars.NewReadOnly("foo")))
   427  	}
   428  	ev.ExtendBuiltin(BuildNs().AddGoFn("add-var", addVar))
   429  
   430  	err := ev.Eval(parse.Source{Code: "use a"}, EvalCfg{})
   431  	if err != nil {
   432  		t.Fatal(err)
   433  	}
   434  
   435  	g := ev.Global()
   436  	if g.IndexString("a:").Get().(*Ns) == nil {
   437  		t.Errorf("$a: is nil")
   438  	}
   439  	if g.IndexString("b").Get().(string) != "foo" {
   440  		t.Errorf(`$b is not "foo"`)
   441  	}
   442  }
   443  
   444  func TestUse_SupportsCircularDependency(t *testing.T) {
   445  	libdir := InTempDir(t)
   446  	ApplyDir(Dir{
   447  		"a.elv": "var pre = apre; use b; put $b:pre $b:post; var post = apost",
   448  		"b.elv": "var pre = bpre; use a; put $a:pre $a:post; var post = bpost",
   449  	})
   450  
   451  	TestWithSetup(t, func(ev *Evaler) { ev.LibDirs = []string{libdir} },
   452  		That(`use a`).Puts(
   453  			// When b.elv is imported from a.elv, $a:pre is set but $a:post is
   454  			// not
   455  			"apre", nil,
   456  			// After a.elv imports b.elv, both $b:pre and $b:post are set
   457  			"bpre", "bpost"),
   458  	)
   459  }
   460  
   461  func TestUse(t *testing.T) {
   462  	libdir1 := InTempDir(t)
   463  	ApplyDir(Dir{
   464  		"shadow.elv": "put lib1",
   465  	})
   466  
   467  	libdir2 := InTempDir(t)
   468  	ApplyDir(Dir{
   469  		"has-init.elv": "put has-init",
   470  		"put-x.elv":    "put $x",
   471  		"lorem.elv":    "var name = lorem; fn put-name { put $name }",
   472  		"d.elv":        "var name = d",
   473  		"shadow.elv":   "put lib2",
   474  		"a": Dir{
   475  			"b": Dir{
   476  				"c": Dir{
   477  					"d.elv": "var name = a/b/c/d",
   478  					"x.elv": "use ./d; var d = $d:name; use ../../../lorem; var lorem = $lorem:name",
   479  				},
   480  			},
   481  		},
   482  	})
   483  
   484  	TestWithSetup(t, func(ev *Evaler) { ev.LibDirs = []string{libdir1, libdir2} },
   485  		That(`use lorem; put $lorem:name`).Puts("lorem"),
   486  		// imports are lexically scoped
   487  		// TODO: Support testing for compilation error
   488  		That(`{ use lorem }; put $lorem:name`).DoesNotCompile(),
   489  
   490  		// prefers lib dir that appear earlier
   491  		That("use shadow").Puts("lib1"),
   492  
   493  		// use of imported variable is captured in upvalue
   494  		That(`use lorem; { put $lorem:name }`).Puts("lorem"),
   495  		That(`{ use lorem; { put $lorem:name } }`).Puts("lorem"),
   496  		That(`({ use lorem; put { { put $lorem:name } } })`).Puts("lorem"),
   497  		// use of imported function is also captured in upvalue
   498  		That(`{ use lorem; { lorem:put-name } }`).Puts("lorem"),
   499  
   500  		// use of a nested module
   501  		That(`use a/b/c/d; put $d:name`).Puts("a/b/c/d"),
   502  		// module is cached after first use
   503  		That(`use has-init; use has-init`).Puts("has-init"),
   504  		// repeated uses result in the same namespace being imported
   505  		That("use lorem; use lorem lorem2; put $lorem:name $lorem2:name").
   506  			Puts("lorem", "lorem"),
   507  		// overriding module
   508  		That(`use d; put $d:name; use a/b/c/d; put $d:name`).
   509  			Puts("d", "a/b/c/d"),
   510  		// relative uses
   511  		That(`use a/b/c/x; put $x:d $x:lorem`).Puts("a/b/c/d", "lorem"),
   512  		// relative uses from top-level
   513  		That(`use ./d; put $d:name`).Puts("d"),
   514  
   515  		// Renaming module
   516  		That(`use a/b/c/d mod; put $mod:name`).Puts("a/b/c/d"),
   517  
   518  		// Variables defined in the default global scope is invisible from
   519  		// modules
   520  		That("var x = foo; use put-x").Throws(ErrorWithType(&diag.Error{})),
   521  
   522  		// Using an unknown module spec fails.
   523  		That("use unknown").Throws(ErrorWithType(NoSuchModule{})),
   524  		That("use ./unknown").Throws(ErrorWithType(NoSuchModule{})),
   525  		That("use ../unknown").Throws(ErrorWithType(NoSuchModule{})),
   526  
   527  		// Nonexistent module
   528  		That("use non-existent").Throws(ErrorWithMessage("no such module: non-existent")),
   529  
   530  		// Wrong uses of "use".
   531  		That("use").DoesNotCompile(),
   532  		That("use a b c").DoesNotCompile(),
   533  	)
   534  }
   535  
   536  // Regression test for #1072
   537  func TestUse_WarnsAboutDeprecatedFeatures(t *testing.T) {
   538  	progtest.SetDeprecationLevel(t, 18)
   539  	libdir := InTempDir(t)
   540  	MustWriteFile("dep.elv", "a=b nop $a")
   541  
   542  	TestWithSetup(t, func(ev *Evaler) { ev.LibDirs = []string{libdir} },
   543  		// Importing module triggers check for deprecated features
   544  		That("use dep").PrintsStderrWith("is deprecated"),
   545  	)
   546  }