feat(tvix/tests): check in Nix' language test suite

This adds scaffolding code for running the Nix language test suite.

The majority of eval-okay-* tests should eventually be runnable as-is
by Tvix, however the eval-fail-* tests might not as we intend to have
more useful error messages than upstream Nix.

Change-Id: I4f3227f0889c55e4274b804a3072850fb78dd1bd
Reviewed-on: https://cl.tvl.fyi/c/depot/+/6126
Tested-by: BuildkiteCI
Autosubmit: tazjin <tazjin@tvl.su>
Reviewed-by: grfn <grfn@gws.fyi>
This commit is contained in:
Vincent Ambo 2022-08-10 18:53:50 +03:00 committed by tazjin
parent b28da8ad56
commit 92c53fe982
248 changed files with 2217 additions and 9 deletions

View file

@ -23,8 +23,7 @@ let
command = "${pkgs.nixpkgs-fmt}/bin/nixpkgs-fmt" command = "${pkgs.nixpkgs-fmt}/bin/nixpkgs-fmt"
includes = [ "*.nix" ] includes = [ "*.nix" ]
excludes = [ excludes = [
"third_party/nix/tests/*", "tvix/eval/src/tests/*",
"third_party/nix/src/tests/*"
] ]
[formatter.rust] [formatter.rust]

2
tvix/eval/.skip-subtree Normal file
View file

@ -0,0 +1,2 @@
Do not traverse further, readTree will encounter Nix language tests
and such and fail.

View file

@ -1,9 +1,9 @@
use rnix::{self, types::TypedNode}; use rnix::{self, types::TypedNode};
use crate::errors::EvalResult; use crate::{errors::EvalResult, value::Value};
pub fn interpret(code: String) -> EvalResult<String> { pub fn interpret(code: &str) -> EvalResult<Value> {
let ast = rnix::parse(&code); let ast = rnix::parse(code);
let errors = ast.errors(); let errors = ast.errors();
if !errors.is_empty() { if !errors.is_empty() {
@ -15,6 +15,5 @@ pub fn interpret(code: String) -> EvalResult<String> {
let code = crate::compiler::compile(ast)?; let code = crate::compiler::compile(ast)?;
println!("code: {:?}", code); println!("code: {:?}", code);
let value = crate::vm::run_chunk(code)?; crate::vm::run_chunk(code)
Ok(format!("value: {} :: {}", value, value.type_of()))
} }

View file

@ -12,6 +12,9 @@ mod opcode;
mod value; mod value;
mod vm; mod vm;
#[cfg(test)]
mod tests;
fn main() { fn main() {
let mut args = env::args(); let mut args = env::args();
if args.len() > 2 { if args.len() > 2 {
@ -47,8 +50,8 @@ fn run_prompt() {
} }
fn run(code: String) { fn run(code: String) {
match eval::interpret(code) { match eval::interpret(&code) {
Ok(result) => println!("=> {}", result), Ok(result) => println!("=> {} :: {}", result, result.type_of()),
Err(err) => eprintln!("{}", err), Err(err) => eprintln!("{}", err),
} }
} }

View file

@ -0,0 +1,28 @@
use crate::eval::interpret;
use test_generator::test_resources;
// eval-okay-* tests contain a snippet of Nix code, and an expectation
// of the produced string output of the evaluator.
//
// These evaluations are always supposed to succeed, i.e. all snippets
// are guaranteed to be valid Nix code.
#[test_resources("src/tests/nix_tests/eval-okay-*.nix")]
fn eval_okay(code_path: &str) {
let base = code_path
.strip_suffix("nix")
.expect("test files always end in .nix");
let exp_path = format!("{}exp", base);
let code = std::fs::read_to_string(code_path).expect("should be able to read test code");
let exp = std::fs::read_to_string(exp_path).expect("should be able to read test expectation");
let result = interpret(&code).expect("evaluation of eval-okay test should succeed");
let result_str = format!("{}", result);
assert_eq!(
exp.trim(),
result_str,
"result value (and its representation) must match expectation"
);
}

View file

@ -0,0 +1,8 @@
These test definitions are taken from the Nix 2.3 code base, they can
be found upstream at:
https://github.com/NixOS/nix/tree/2.3.16/tests/lang
These tests follow the licensing directions of Nix 2.3 itself:
https://github.com/NixOS/nix/blob/2.3.16/COPYING

Binary file not shown.

View file

@ -0,0 +1 @@
foo

View file

@ -0,0 +1 @@
"a"

View file

@ -0,0 +1 @@
"X"

View file

@ -0,0 +1 @@
"b"

View file

@ -0,0 +1 @@
"X"

View file

@ -0,0 +1 @@
"X"

View file

@ -0,0 +1 @@
"c"

View file

@ -0,0 +1 @@
"X"

View file

@ -0,0 +1 @@
"X"

View file

@ -0,0 +1 @@
if true then abort "this should fail" else 1

View file

@ -0,0 +1,4 @@
# This must fail to evaluate, since ./fnord doesn't exist. If it did
# exist, it would produce "/nix/store/<hash>-fnord/xyzzy" (with an
# appropriate context).
"${./fnord}/xyzzy"

View file

@ -0,0 +1,5 @@
let {
x = arg: assert arg == "y"; 123;
body = x "x";
}

View file

@ -0,0 +1 @@
"${x: x}"

View file

@ -0,0 +1 @@
"${./fnord}"

View file

@ -0,0 +1 @@
''${x: x}''

View file

@ -0,0 +1,5 @@
let {
body = x;
x = y;
y = x;
}

View file

@ -0,0 +1 @@
builtins.deepSeq { x = abort "foo"; } 456

View file

@ -0,0 +1,5 @@
let
paths = [ ./this-file-is-definitely-not-there-7392097 "/and/neither/is/this/37293620" ];
in
toString (builtins.concatLists (map (hash: map (builtins.hashFile hash) paths) ["md5" "sha1" "sha256" "sha512"]))

View file

@ -0,0 +1 @@
({x, y, z}: x + y + z) {x = "foo"; z = "bar";}

View file

@ -0,0 +1,6 @@
# Trailing slashes in paths are not allowed.
# This restriction could be lifted sometime,
# for example if we make '/' a path concatenation operator.
# See https://github.com/NixOS/nix/issues/1138
# and https://nixos.org/nix-dev/2016-June/020829.html
/nix/store/

View file

@ -0,0 +1,5 @@
let {
attrs = {x = 123; y = 456;};
body = (removeAttrs attrs ["x"]).x;
}

View file

@ -0,0 +1,10 @@
let {
x = "a";
y = "b";
f = {x ? y, y ? x}: x + y;
body = f {};
}

View file

@ -0,0 +1 @@
builtins.seq (abort "foo") 2

View file

@ -0,0 +1 @@
builtins.substring (builtins.sub 0 1) 1 "x"

View file

@ -0,0 +1 @@
builtins.toPath "foo/bar"

View file

@ -0,0 +1 @@
({x, z}: x + z) {x = "foo"; y = "bla"; z = "bar";}

View file

@ -0,0 +1 @@
[ false false true true true true false true ]

View file

@ -0,0 +1,11 @@
with builtins;
[ (any (x: x == 1) [])
(any (x: x == 1) [2 3 4])
(any (x: x == 1) [1 2 3 4])
(any (x: x == 1) [4 3 2 1])
(all (x: x == 1) [])
(all (x: x == 1) [1])
(all (x: x == 1) [1 2 3])
(all (x: x == 1) [1 1 1])
]

View file

@ -0,0 +1 @@
2216

View file

@ -0,0 +1,59 @@
with import ./lib.nix;
let {
/* Supposedly tail recursive version:
range_ = accum: first: last:
if first == last then ([first] ++ accum)
else range_ ([first] ++ accum) (builtins.add first 1) last;
range = range_ [];
*/
x = 12;
err = abort "urgh";
body = sum
[ (sum (range 1 50))
(123 + 456)
(0 + -10 + -(-11) + -x)
(10 - 7 - -2)
(10 - (6 - -1))
(10 - 1 + 2)
(3 * 4 * 5)
(56088 / 123 / 2)
(3 + 4 * const 5 0 - 6 / id 2)
(builtins.bitAnd 12 10) # 0b1100 & 0b1010 = 8
(builtins.bitOr 12 10) # 0b1100 | 0b1010 = 14
(builtins.bitXor 12 10) # 0b1100 ^ 0b1010 = 6
(if 3 < 7 then 1 else err)
(if 7 < 3 then err else 1)
(if 3 < 3 then err else 1)
(if 3 <= 7 then 1 else err)
(if 7 <= 3 then err else 1)
(if 3 <= 3 then 1 else err)
(if 3 > 7 then err else 1)
(if 7 > 3 then 1 else err)
(if 3 > 3 then err else 1)
(if 3 >= 7 then err else 1)
(if 7 >= 3 then 1 else err)
(if 3 >= 3 then 1 else err)
(if 2 > 1 == 1 < 2 then 1 else err)
(if 1 + 2 * 3 >= 7 then 1 else err)
(if 1 + 2 * 3 < 7 then err else 1)
# Not integer, but so what.
(if "aa" < "ab" then 1 else err)
(if "aa" < "aa" then err else 1)
(if "foo" < "foobar" then 1 else err)
];
}

View file

@ -0,0 +1 @@
"newxfoonewxy"

View file

@ -0,0 +1,11 @@
with import ./lib.nix;
let
attrs = {y = "y"; x = "x"; foo = "foo";} // rec {x = "newx"; bar = x;};
names = builtins.attrNames attrs;
values = map (name: builtins.getAttr name attrs) names;
in assert values == builtins.attrValues attrs; concat values

View file

@ -0,0 +1 @@
987

View file

@ -0,0 +1,5 @@
let {
as = { x = 123; y = 456; } // { z = 789; } // { z = 987; };
body = if as ? a then as.a else assert as ? z; as.z;
}

View file

@ -0,0 +1 @@
987

View file

@ -0,0 +1,10 @@
let {
as = { x = 123; y = 456; } // { z = 789; } // { z = 987; };
A = "a";
Z = "z";
body = if builtins.hasAttr A as
then builtins.getAttr A as
else assert builtins.hasAttr Z as; builtins.getAttr Z as;
}

View file

@ -0,0 +1 @@
"foo 22 80 itchyxac"

View file

@ -0,0 +1,22 @@
let
config =
{
services.sshd.enable = true;
services.sshd.port = 22;
services.httpd.port = 80;
hostName = "itchy";
a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z = "x";
foo = {
a = "a";
b.c = "c";
};
};
in
if config.services.sshd.enable
then "foo ${toString config.services.sshd.port} ${toString config.services.httpd.port} ${config.hostName}"
+ "${config.a.b.c.d.e.f.g.h.i.j.k.l.m.n.o.p.q.r.s.t.u.v.w.x.y.z}"
+ "${config.foo.a}"
+ "${config.foo.b.c}"
else "bar"

View file

@ -0,0 +1 @@
[ true false true false false true false false ]

View file

@ -0,0 +1,7 @@
let
as = { x.y.z = 123; a.b.c = 456; };
bs = null;
in [ (as ? x) (as ? y) (as ? x.y.z) (as ? x.y.z.a) (as ? x.y.a) (as ? a.b.c) (bs ? x) (bs ? x.y.z) ]

View file

@ -0,0 +1 @@
[ 123 "foo" 456 456 "foo" "xyzzy" "xyzzy" true ]

View file

@ -0,0 +1,21 @@
with import ./lib.nix;
let
as = { x.y.z = 123; a.b.c = 456; };
bs = { f-o-o.bar = "foo"; };
or = x: y: x || y;
in
[ as.x.y.z
as.foo or "foo"
as.x.y.bla or as.a.b.c
as.a.b.c or as.x.y.z
as.x.y.bla or bs.f-o-o.bar or "xyzzy"
as.x.y.bla or bs.bar.foo or "xyzzy"
(123).bla or null.foo or "xyzzy"
# Backwards compatibility test.
(fold or [] [true false false])
]

View file

@ -0,0 +1 @@
{ __overrides = { bar = "qux"; }; bar = "qux"; foo = "bar"; }

View file

@ -0,0 +1,4 @@
rec {
"${"foo"}" = "bar";
__overrides = { bar = "qux"; };
}

View file

@ -0,0 +1 @@
"xyzzy!xyzzy!foobar"

View file

@ -0,0 +1 @@
--arg lib import(lang/lib.nix) --argstr xyzzy xyzzy! -A result

View file

@ -0,0 +1,15 @@
let
foobar = "foobar";
in
{ xyzzy2 ? xyzzy # mutually recursive args
, xyzzy ? "blaat" # will be overridden by --argstr
, fb ? foobar
, lib # will be set by --arg
}:
{
result = lib.concat [xyzzy xyzzy2 fb];
}

View file

@ -0,0 +1 @@
"a\nb"

View file

@ -0,0 +1,2 @@
"a\
b"

View file

@ -0,0 +1 @@
"a\nb"

View file

@ -0,0 +1,2 @@
''a''\
b''

View file

@ -0,0 +1 @@
[ 5 4 "int" "tt" "float" 4 ]

View file

@ -0,0 +1,8 @@
[
(builtins.add 2 3)
(builtins.add 2 2)
(builtins.typeOf (builtins.add 2 2))
("t" + "t")
(builtins.typeOf (builtins.add 2.0 2))
(builtins.add 2.0 2)
]

View file

@ -0,0 +1 @@
/foo

View file

@ -0,0 +1,12 @@
assert builtins ? currentSystem;
assert !builtins ? __currentSystem;
let {
x = if builtins ? dirOf then builtins.dirOf /foo/bar else "";
y = if builtins ? fnord then builtins.fnord "foo" else "";
body = x + y;
}

View file

@ -0,0 +1 @@
true

View file

@ -0,0 +1 @@
({ __functor = self: x: self.foo && x; foo = false; } // { foo = true; }) true

View file

@ -0,0 +1 @@
[ 1 2 ]

View file

@ -0,0 +1 @@
builtins.catAttrs "a" [ { a = 1; } { b = 0; } { a = 2; } ]

View file

@ -0,0 +1,343 @@
<?xml version='1.0' encoding='utf-8'?>
<expr>
<list>
<attrs>
<attr name="foo">
<bool value="true" />
</attr>
<attr name="key">
<int value="-13" />
</attr>
</attrs>
<attrs>
<attr name="foo">
<bool value="true" />
</attr>
<attr name="key">
<int value="-12" />
</attr>
</attrs>
<attrs>
<attr name="foo">
<bool value="true" />
</attr>
<attr name="key">
<int value="-11" />
</attr>
</attrs>
<attrs>
<attr name="foo">
<bool value="true" />
</attr>
<attr name="key">
<int value="-9" />
</attr>
</attrs>
<attrs>
<attr name="foo">
<bool value="true" />
</attr>
<attr name="key">
<int value="-8" />
</attr>
</attrs>
<attrs>
<attr name="foo">
<bool value="true" />
</attr>
<attr name="key">
<int value="-7" />
</attr>
</attrs>
<attrs>
<attr name="foo">
<bool value="true" />
</attr>
<attr name="key">
<int value="-5" />
</attr>
</attrs>
<attrs>
<attr name="foo">
<bool value="true" />
</attr>
<attr name="key">
<int value="-4" />
</attr>
</attrs>
<attrs>
<attr name="foo">
<bool value="true" />
</attr>
<attr name="key">
<int value="-3" />
</attr>
</attrs>
<attrs>
<attr name="key">
<int value="-1" />
</attr>
</attrs>
<attrs>
<attr name="foo">
<bool value="true" />
</attr>
<attr name="key">
<int value="0" />
</attr>
</attrs>
<attrs>
<attr name="foo">
<bool value="true" />
</attr>
<attr name="key">
<int value="1" />
</attr>
</attrs>
<attrs>
<attr name="foo">
<bool value="true" />
</attr>
<attr name="key">
<int value="2" />
</attr>
</attrs>
<attrs>
<attr name="foo">
<bool value="true" />
</attr>
<attr name="key">
<int value="4" />
</attr>
</attrs>
<attrs>
<attr name="foo">
<bool value="true" />
</attr>
<attr name="key">
<int value="5" />
</attr>
</attrs>
<attrs>
<attr name="foo">
<bool value="true" />
</attr>
<attr name="key">
<int value="6" />
</attr>
</attrs>
<attrs>
<attr name="key">
<int value="8" />
</attr>
</attrs>
<attrs>
<attr name="foo">
<bool value="true" />
</attr>
<attr name="key">
<int value="9" />
</attr>
</attrs>
<attrs>
<attr name="foo">
<bool value="true" />
</attr>
<attr name="key">
<int value="10" />
</attr>
</attrs>
<attrs>
<attr name="foo">
<bool value="true" />
</attr>
<attr name="key">
<int value="13" />
</attr>
</attrs>
<attrs>
<attr name="foo">
<bool value="true" />
</attr>
<attr name="key">
<int value="14" />
</attr>
</attrs>
<attrs>
<attr name="foo">
<bool value="true" />
</attr>
<attr name="key">
<int value="15" />
</attr>
</attrs>
<attrs>
<attr name="key">
<int value="17" />
</attr>
</attrs>
<attrs>
<attr name="foo">
<bool value="true" />
</attr>
<attr name="key">
<int value="18" />
</attr>
</attrs>
<attrs>
<attr name="foo">
<bool value="true" />
</attr>
<attr name="key">
<int value="19" />
</attr>
</attrs>
<attrs>
<attr name="foo">
<bool value="true" />
</attr>
<attr name="key">
<int value="22" />
</attr>
</attrs>
<attrs>
<attr name="foo">
<bool value="true" />
</attr>
<attr name="key">
<int value="23" />
</attr>
</attrs>
<attrs>
<attr name="key">
<int value="26" />
</attr>
</attrs>
<attrs>
<attr name="foo">
<bool value="true" />
</attr>
<attr name="key">
<int value="27" />
</attr>
</attrs>
<attrs>
<attr name="foo">
<bool value="true" />
</attr>
<attr name="key">
<int value="28" />
</attr>
</attrs>
<attrs>
<attr name="foo">
<bool value="true" />
</attr>
<attr name="key">
<int value="31" />
</attr>
</attrs>
<attrs>
<attr name="foo">
<bool value="true" />
</attr>
<attr name="key">
<int value="32" />
</attr>
</attrs>
<attrs>
<attr name="key">
<int value="35" />
</attr>
</attrs>
<attrs>
<attr name="foo">
<bool value="true" />
</attr>
<attr name="key">
<int value="36" />
</attr>
</attrs>
<attrs>
<attr name="foo">
<bool value="true" />
</attr>
<attr name="key">
<int value="40" />
</attr>
</attrs>
<attrs>
<attr name="foo">
<bool value="true" />
</attr>
<attr name="key">
<int value="41" />
</attr>
</attrs>
<attrs>
<attr name="key">
<int value="44" />
</attr>
</attrs>
<attrs>
<attr name="foo">
<bool value="true" />
</attr>
<attr name="key">
<int value="45" />
</attr>
</attrs>
<attrs>
<attr name="foo">
<bool value="true" />
</attr>
<attr name="key">
<int value="49" />
</attr>
</attrs>
<attrs>
<attr name="key">
<int value="53" />
</attr>
</attrs>
<attrs>
<attr name="foo">
<bool value="true" />
</attr>
<attr name="key">
<int value="54" />
</attr>
</attrs>
<attrs>
<attr name="foo">
<bool value="true" />
</attr>
<attr name="key">
<int value="58" />
</attr>
</attrs>
<attrs>
<attr name="key">
<int value="62" />
</attr>
</attrs>
<attrs>
<attr name="foo">
<bool value="true" />
</attr>
<attr name="key">
<int value="67" />
</attr>
</attrs>
<attrs>
<attr name="key">
<int value="71" />
</attr>
</attrs>
<attrs>
<attr name="key">
<int value="80" />
</attr>
</attrs>
</list>
</expr>

View file

@ -0,0 +1,13 @@
let
closure = builtins.genericClosure {
startSet = [{key = 80;}];
operator = {key, foo ? false}:
if builtins.lessThan key 0
then []
else [{key = builtins.sub key 9;} {key = builtins.sub key 13; foo = true;}];
};
sort = (import ./lib.nix).sortBy (a: b: builtins.lessThan a.key b.key);
in sort closure

View file

@ -0,0 +1 @@
"abcdefghijklmnopqrstuvwxyz"

View file

@ -0,0 +1,59 @@
# A simple comment
"a"+ # And another
## A double comment
"b"+ ## And another
# Nested # comments #
"c"+ # and # some # other #
# An empty line, following here:
"d"+ # and a comment not starting the line !
"e"+
/* multiline comments */
"f" +
/* multiline
comments,
on
multiple
lines
*/
"g" +
# Small, tricky comments
/**/ "h"+ /*/*/ "i"+ /***/ "j"+ /* /*/ "k"+ /*/* /*/ "l"+
# Comments with an even number of ending '*' used to fail:
"m"+
/* */ /* **/ /* ***/ /* ****/ "n"+
/* */ /** */ /*** */ /**** */ "o"+
/** **/ /*** ***/ /**** ****/ "p"+
/* * ** *** **** ***** */ "q"+
# Random comments
/* ***** ////// * / * / /* */ "r"+
# Mixed comments
/* # */
"s"+
# /* #
"t"+
# /* # */
"u"+
# /*********/
"v"+
## */*
"w"+
/*
* Multiline, decorated comments
* # This ain't a nest'd comm'nt
*/
"x"+
''${/** with **/"y"
# real
/* comments
inside ! # */
# (and empty lines)
}''+ /* And a multiline comment,
on the same line,
after some spaces
*/ # followed by a one-line comment
"z"
/* EOF */

View file

@ -0,0 +1 @@
[ 1 2 3 4 5 6 7 8 9 ]

View file

@ -0,0 +1 @@
[1 2 3] ++ [4 5 6] ++ [7 8 9]

View file

@ -0,0 +1 @@
[ [ 1 3 5 7 9 ] [ "a" "z" "b" "z" ] ]

View file

@ -0,0 +1,5 @@
with import ./lib.nix;
[ (builtins.concatMap (x: if x / 2 * 2 == x then [] else [ x ]) (range 0 10))
(builtins.concatMap (x: [x] ++ ["z"]) ["a" "b"])
]

View file

@ -0,0 +1 @@
[ "" "foobarxyzzy" "foo, bar, xyzzy" "foo" "" ]

View file

@ -0,0 +1,8 @@
with builtins;
[ (concatStringsSep "" [])
(concatStringsSep "" ["foo" "bar" "xyzzy"])
(concatStringsSep ", " ["foo" "bar" "xyzzy"])
(concatStringsSep ", " ["foo"])
(concatStringsSep ", " [])
]

View file

@ -0,0 +1 @@
true

View file

@ -0,0 +1,24 @@
let
drv = derivation {
name = "fail";
builder = "/bin/false";
system = "x86_64-linux";
outputs = [ "out" "foo" ];
};
path = "${./eval-okay-context-introspection.nix}";
desired-context = {
"${builtins.unsafeDiscardStringContext path}" = {
path = true;
};
"${builtins.unsafeDiscardStringContext drv.drvPath}" = {
outputs = [ "foo" "out" ];
allOutputs = true;
};
};
legit-context = builtins.getContext "${path}${drv.outPath}${drv.foo.outPath}${drv.drvPath}";
constructed-context = builtins.getContext (builtins.appendContext "" desired-context);
in legit-context == constructed-context

View file

@ -0,0 +1 @@
"foo eval-okay-context.nix bar"

View file

@ -0,0 +1,6 @@
let s = "foo ${builtins.substring 33 100 (baseNameOf "${./eval-okay-context.nix}")} bar";
in
if s != "foo eval-okay-context.nix bar"
then abort "context not discarded"
else builtins.unsafeDiscardStringContext s

View file

@ -0,0 +1 @@
[ 3 7 4 9 ]

View file

@ -0,0 +1,5 @@
# Bla
let
x = __curPos;
y = __curPos;
in [ x.line x.column y.line y.column ]

View file

@ -0,0 +1 @@
456

View file

@ -0,0 +1 @@
builtins.deepSeq (let as = { x = 123; y = as; }; in as) 456

View file

@ -0,0 +1 @@
"b-overridden"

View file

@ -0,0 +1,24 @@
let
pkgs_ = with pkgs; {
a = derivation {
name = "a";
system = builtins.currentSystem;
builder = "/bin/sh";
args = [ "-c" "touch $out" ];
inherit b;
};
inherit b;
};
packageOverrides = p: {
b = derivation {
name = "b-overridden";
system = builtins.currentSystem;
builder = "/bin/sh";
args = [ "-c" "touch $out" ];
};
};
pkgs = pkgs_ // (packageOverrides pkgs_);
in pkgs.a.b.name

View file

@ -0,0 +1 @@
"b-overridden b-overridden a"

View file

@ -0,0 +1,29 @@
let
pkgs_ = with pkgs; {
a = derivation {
name = "a";
system = builtins.currentSystem;
builder = "/bin/sh";
args = [ "-c" "touch $out" ];
inherit b;
};
b = derivation {
name = "b";
system = builtins.currentSystem;
builder = "/bin/sh";
args = [ "-c" "touch $out" ];
inherit a;
};
c = b;
};
packageOverrides = pkgs: with pkgs; {
b = derivation (b.drvAttrs // { name = "${b.name}-overridden"; });
};
pkgs = pkgs_ // (packageOverrides pkgs_);
in "${pkgs.a.b.name} ${pkgs.c.name} ${pkgs.b.a.name}"

View file

@ -0,0 +1 @@
true

View file

@ -0,0 +1 @@
{ a."${"b"}" = true; a."${"c"}" = false; }.a.b

View file

@ -0,0 +1 @@
{ binds = true; hasAttrs = true; multiAttrs = true; recBinds = true; selectAttrs = true; selectOrAttrs = true; }

View file

@ -0,0 +1,17 @@
let
aString = "a";
bString = "b";
in {
hasAttrs = { a.b = null; } ? ${aString}.b;
selectAttrs = { a.b = true; }.a.${bString};
selectOrAttrs = { }.${aString} or true;
binds = { ${aString}."${bString}c" = true; }.a.bc;
recBinds = rec { ${bString} = a; a = true; }.b;
multiAttrs = { ${aString} = true; ${bString} = false; }.a;
}

View file

@ -0,0 +1 @@
{ binds = true; hasAttrs = true; multiAttrs = true; recBinds = true; selectAttrs = true; selectOrAttrs = true; }

View file

@ -0,0 +1,17 @@
let
aString = "a";
bString = "b";
in {
hasAttrs = { a.b = null; } ? "${aString}".b;
selectAttrs = { a.b = true; }.a."${bString}";
selectOrAttrs = { }."${aString}" or true;
binds = { "${aString}"."${bString}c" = true; }.a.bc;
recBinds = rec { "${bString}" = a; a = true; }.b;
multiAttrs = { "${aString}" = true; "${bString}" = false; }.a;
}

View file

@ -0,0 +1 @@
[ true false 30 ]

View file

@ -0,0 +1,6 @@
with import ./lib.nix;
let xs = range 10 40; in
[ (builtins.elem 23 xs) (builtins.elem 42 xs) (builtins.elemAt xs 20) ]

View file

@ -0,0 +1 @@
"ab"

View file

@ -0,0 +1 @@
({}: {x,y,}: "${x}${y}") {} {x = "a"; y = "b";}

View file

@ -0,0 +1 @@
[ true true true false ]

View file

@ -0,0 +1,10 @@
let
drvA1 = derivation { name = "a"; builder = "/foo"; system = "i686-linux"; };
drvA2 = derivation { name = "a"; builder = "/foo"; system = "i686-linux"; };
drvA3 = derivation { name = "a"; builder = "/foo"; system = "i686-linux"; } // { dummy = 1; };
drvC1 = derivation { name = "c"; builder = "/foo"; system = "i686-linux"; };
drvC2 = derivation { name = "c"; builder = "/bar"; system = "i686-linux"; };
in [ (drvA1 == drvA1) (drvA1 == drvA2) (drvA1 == drvA3) (drvC1 == drvC2) ]

Some files were not shown because too many files have changed in this diff Show more