previously, `builtins.break` didn't force its argument, resulting in a value wrapped with `break` being opaque to most builtins if not also wrapped with `seq`. see [lix-project/lix#1165] for more details on what this can break. this tiny fix just adds a call to `forceValue` inside `prim_break`, but unfortunately this "breaks" a few existing tests because it changes the call stack; those tests' golden outputs have been adjusted without modifying their intended purpose. Fixes #1165 [lix-project/lix#1165]: https://git.lix.systems/lix-project/lix/issues/1165 Change-Id: I5fe4ee3ff28b38aaf924125b8978130812e58fef
86 lines
2.8 KiB
Python
86 lines
2.8 KiB
Python
import re
|
|
from textwrap import dedent
|
|
|
|
from testlib.fixtures.nix import Nix
|
|
|
|
|
|
def test_regression_9932(nix: Nix):
|
|
cmd = nix.nix(["eval", "--debugger", "--expr", '(_: throw "oh snap") 42'], flake=True)
|
|
cmd.with_stdin(b":env")
|
|
res = cmd.run().expect(1)
|
|
assert "error: oh snap" in res.stderr_plain
|
|
|
|
|
|
def test_debugger_output(nix: Nix):
|
|
expr = dedent("""
|
|
let x.a = 1; in
|
|
with x;
|
|
(_: builtins.seq x.a (throw "oh snap")) x.a
|
|
""")
|
|
|
|
res = (
|
|
nix.nix(["eval", "--debugger", "--expr", expr], flake=True)
|
|
.with_stdin(b":env\n")
|
|
.run()
|
|
.expect(1)
|
|
)
|
|
assert "error: oh snap" in res.stderr_plain
|
|
assert re.findall(r"with: .*a", res.stdout_plain)
|
|
assert re.findall(r"static: .*x", res.stdout_plain)
|
|
|
|
|
|
def test_transparent_break(nix: Nix):
|
|
"""
|
|
Make sure that adding a call to builtins.break doesn't
|
|
change the result of an expression
|
|
"""
|
|
|
|
expr = dedent("""
|
|
let
|
|
inherit (builtins)
|
|
attrNames
|
|
break
|
|
elem
|
|
functionArgs
|
|
head
|
|
isAttrs
|
|
isPath
|
|
isFunction
|
|
map
|
|
mapAttrs
|
|
removeAttrs
|
|
toJSON
|
|
typeOf;
|
|
in
|
|
builtins.all (b: b) [
|
|
((attrNames { a = 5; }) == (attrNames (break { a = 5; })))
|
|
((elem 5 [1 5]) == (elem 5 (break [1 5])))
|
|
((elem (2+3) [1 (2+3)]) == (elem (2+3) (break [1 (2+3)])))
|
|
((functionArgs ({ a }: 5)) == (functionArgs (break ({ a }: 5))))
|
|
((head [1 2]) == (head (break [1 2])))
|
|
((isAttrs { a = 5; }) == (isAttrs (break { a = 5; })))
|
|
((isPath ./.) == (isPath (break ./.)))
|
|
((isPath ./${".meow"}) == (isPath (break ./${".meow"})))
|
|
((isFunction (x: x)) == (isFunction (break (x: x))))
|
|
((map (x: x) [1 5]) == (map (x: x) (break [1 5])))
|
|
((mapAttrs (n: v: v) { a = 5; }) == (mapAttrs (n: v: v) (break { a = 5; })))
|
|
((removeAttrs { a = 5; b = 6; } ["a"]) == (removeAttrs (break { a = 5; b = 6; }) ["a"]))
|
|
((removeAttrs { ab = 5; } [("a"+"b")]) == (removeAttrs { ab = 5; } [(break ("a"+"b"))]))
|
|
((toJSON { a = 5; }) == (toJSON (break { a = 5; })))
|
|
((toJSON { a = [(1+2)]; }) == (toJSON { a = break [(1+2)]; }))
|
|
((typeOf { a = 5; }) == (typeOf (break { a = 5; })))
|
|
((typeOf (1+2)) == (typeOf (break (1+2))))
|
|
]
|
|
""")
|
|
|
|
res_no_dbg = nix.nix(["eval", "--expr", expr], flake=True).run().expect(0)
|
|
assert "true" in res_no_dbg.stdout_plain
|
|
|
|
res_with_dbg = (
|
|
nix.nix(["eval", "--debugger", "--expr", expr], flake=True)
|
|
.with_stdin(b":c\n" * 50)
|
|
.run()
|
|
.expect(0)
|
|
)
|
|
assert "true" in res_with_dbg.stdout_plain
|