builtin_special_test.go 18 KB

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