feat: initial string context implementation
This commit is contained in:
290
nix-js/tests/string_context.rs
Normal file
290
nix-js/tests/string_context.rs
Normal file
@@ -0,0 +1,290 @@
|
||||
use nix_js::context::Context;
|
||||
use nix_js::value::Value;
|
||||
|
||||
fn eval(expr: &str) -> Value {
|
||||
let mut ctx = Context::new().unwrap();
|
||||
ctx.eval_code(expr).unwrap_or_else(|e| panic!("{}", e))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hascontext_plain_string() {
|
||||
let result = eval(r#"builtins.hasContext "hello""#);
|
||||
assert_eq!(result, Value::Bool(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hascontext_derivation_output() {
|
||||
let result = eval(
|
||||
r#"
|
||||
let
|
||||
drv = derivation { name = "test"; builder = "/bin/sh"; system = "x86_64-linux"; };
|
||||
in builtins.hasContext (builtins.toString drv)
|
||||
"#,
|
||||
);
|
||||
assert_eq!(result, Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn getcontext_plain_string() {
|
||||
let result = eval(r#"builtins.getContext "hello""#);
|
||||
match result {
|
||||
Value::AttrSet(attrs) => {
|
||||
assert!(attrs.is_empty(), "Plain string should have empty context");
|
||||
}
|
||||
_ => panic!("Expected AttrSet, got {:?}", result),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn getcontext_derivation_output() {
|
||||
let result = eval(
|
||||
r#"
|
||||
let
|
||||
drv = derivation { name = "test"; builder = "/bin/sh"; system = "x86_64-linux"; };
|
||||
str = builtins.toString drv;
|
||||
ctx = builtins.getContext str;
|
||||
in builtins.attrNames ctx
|
||||
"#,
|
||||
);
|
||||
match result {
|
||||
Value::List(list) => {
|
||||
assert_eq!(list.len(), 1, "Should have exactly one context entry");
|
||||
match list.first().unwrap() {
|
||||
Value::String(s) => {
|
||||
assert!(s.ends_with(".drv"), "Context key should be a .drv path");
|
||||
}
|
||||
other => panic!("Expected String, got {:?}", other),
|
||||
}
|
||||
}
|
||||
_ => panic!("Expected List, got {:?}", result),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unsafediscardstringcontext() {
|
||||
let result = eval(
|
||||
r#"
|
||||
let
|
||||
drv = derivation { name = "test"; builder = "/bin/sh"; system = "x86_64-linux"; };
|
||||
strWithContext = builtins.toString drv;
|
||||
strWithoutContext = builtins.unsafeDiscardStringContext strWithContext;
|
||||
in builtins.hasContext strWithoutContext
|
||||
"#,
|
||||
);
|
||||
assert_eq!(result, Value::Bool(false));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn unsafediscardstringcontext_preserves_value() {
|
||||
let result = eval(
|
||||
r#"
|
||||
let
|
||||
drv = derivation { name = "test"; builder = "/bin/sh"; system = "x86_64-linux"; };
|
||||
strWithContext = builtins.toString drv;
|
||||
strWithoutContext = builtins.unsafeDiscardStringContext strWithContext;
|
||||
in strWithContext == strWithoutContext
|
||||
"#,
|
||||
);
|
||||
assert_eq!(result, Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn appendcontext_basic() {
|
||||
let result = eval(
|
||||
r#"
|
||||
let
|
||||
str = builtins.appendContext "hello" {
|
||||
"/nix/store/0000000000000000000000000000000-test.drv" = { outputs = ["out"]; };
|
||||
};
|
||||
in builtins.hasContext str
|
||||
"#,
|
||||
);
|
||||
assert_eq!(result, Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn appendcontext_preserves_value() {
|
||||
let result = eval(
|
||||
r#"
|
||||
let
|
||||
str = builtins.appendContext "hello" {
|
||||
"/nix/store/0000000000000000000000000000000-test.drv" = { outputs = ["out"]; };
|
||||
};
|
||||
in str == "hello"
|
||||
"#,
|
||||
);
|
||||
assert_eq!(result, Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn string_concat_merges_context() {
|
||||
let result = eval(
|
||||
r#"
|
||||
let
|
||||
drv1 = derivation { name = "test1"; builder = "/bin/sh"; system = "x86_64-linux"; };
|
||||
drv2 = derivation { name = "test2"; builder = "/bin/sh"; system = "x86_64-linux"; };
|
||||
str1 = builtins.toString drv1;
|
||||
str2 = builtins.toString drv2;
|
||||
combined = str1 + " " + str2;
|
||||
ctx = builtins.getContext combined;
|
||||
in builtins.length (builtins.attrNames ctx)
|
||||
"#,
|
||||
);
|
||||
assert_eq!(result, Value::Int(2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn string_add_merges_context() {
|
||||
let result = eval(
|
||||
r#"
|
||||
let
|
||||
drv1 = derivation { name = "test1"; builder = "/bin/sh"; system = "x86_64-linux"; };
|
||||
drv2 = derivation { name = "test2"; builder = "/bin/sh"; system = "x86_64-linux"; };
|
||||
str1 = builtins.toString drv1;
|
||||
str2 = builtins.toString drv2;
|
||||
combined = str1 + " " + str2;
|
||||
ctx = builtins.getContext combined;
|
||||
in builtins.length (builtins.attrNames ctx)
|
||||
"#,
|
||||
);
|
||||
assert_eq!(result, Value::Int(2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn context_in_derivation_args() {
|
||||
let result = eval(
|
||||
r#"
|
||||
let
|
||||
dep = derivation { name = "dep"; builder = "/bin/sh"; system = "x86_64-linux"; };
|
||||
drv = derivation {
|
||||
name = "test";
|
||||
builder = "/bin/sh";
|
||||
system = "x86_64-linux";
|
||||
args = [ ((builtins.toString dep) + "/bin/run") ];
|
||||
};
|
||||
in drv.drvPath
|
||||
"#,
|
||||
);
|
||||
match result {
|
||||
Value::String(s) => {
|
||||
assert!(s.starts_with("/nix/store/"), "Should be a store path");
|
||||
assert!(s.ends_with(".drv"), "Should be a .drv file");
|
||||
}
|
||||
_ => panic!("Expected String, got {:?}", result),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn context_in_derivation_env() {
|
||||
let result = eval(
|
||||
r#"
|
||||
let
|
||||
dep = derivation { name = "dep"; builder = "/bin/sh"; system = "x86_64-linux"; };
|
||||
drv = derivation {
|
||||
name = "test";
|
||||
builder = "/bin/sh";
|
||||
system = "x86_64-linux";
|
||||
myDep = builtins.toString dep;
|
||||
};
|
||||
in drv.drvPath
|
||||
"#,
|
||||
);
|
||||
match result {
|
||||
Value::String(s) => {
|
||||
assert!(s.starts_with("/nix/store/"), "Should be a store path");
|
||||
assert!(s.ends_with(".drv"), "Should be a .drv file");
|
||||
}
|
||||
_ => panic!("Expected String, got {:?}", result),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn tostring_preserves_context() {
|
||||
let result = eval(
|
||||
r#"
|
||||
let
|
||||
drv = derivation { name = "test"; builder = "/bin/sh"; system = "x86_64-linux"; };
|
||||
str = builtins.toString drv;
|
||||
in builtins.hasContext str
|
||||
"#,
|
||||
);
|
||||
assert_eq!(result, Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn interpolation_derivation_returns_outpath() {
|
||||
let result = eval(
|
||||
r#"
|
||||
let
|
||||
drv = derivation { name = "test"; builder = "/bin/sh"; system = "x86_64-linux"; };
|
||||
in "${drv}"
|
||||
"#,
|
||||
);
|
||||
match result {
|
||||
Value::String(s) => {
|
||||
assert!(s.starts_with("/nix/store/"), "Should be a store path");
|
||||
assert!(s.ends_with("-test"), "Should end with derivation name");
|
||||
}
|
||||
_ => panic!("Expected String, got {:?}", result),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn interpolation_derivation_has_context() {
|
||||
let result = eval(
|
||||
r#"
|
||||
let
|
||||
drv = derivation { name = "test"; builder = "/bin/sh"; system = "x86_64-linux"; };
|
||||
in builtins.hasContext "${drv}"
|
||||
"#,
|
||||
);
|
||||
assert_eq!(result, Value::Bool(true));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn interpolation_derivation_context_correct() {
|
||||
let result = eval(
|
||||
r#"
|
||||
let
|
||||
drv = derivation { name = "test"; builder = "/bin/sh"; system = "x86_64-linux"; };
|
||||
ctx = builtins.getContext "${drv}";
|
||||
keys = builtins.attrNames ctx;
|
||||
drvPath = builtins.head keys;
|
||||
in ctx.${drvPath}.outputs
|
||||
"#,
|
||||
);
|
||||
match result {
|
||||
Value::List(list) => {
|
||||
assert_eq!(list.len(), 1);
|
||||
assert_eq!(list.first().unwrap(), &Value::String("out".to_string()));
|
||||
}
|
||||
_ => panic!("Expected List with ['out'], got {:?}", result),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn interpolation_multiple_derivations() {
|
||||
let result = eval(
|
||||
r#"
|
||||
let
|
||||
drv1 = derivation { name = "test1"; builder = "/bin/sh"; system = "x86_64-linux"; };
|
||||
drv2 = derivation { name = "test2"; builder = "/bin/sh"; system = "x86_64-linux"; };
|
||||
combined = "prefix-${drv1}-middle-${drv2}-suffix";
|
||||
ctx = builtins.getContext combined;
|
||||
in builtins.length (builtins.attrNames ctx)
|
||||
"#,
|
||||
);
|
||||
assert_eq!(result, Value::Int(2));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn interpolation_derivation_equals_tostring() {
|
||||
let result = eval(
|
||||
r#"
|
||||
let
|
||||
drv = derivation { name = "test"; builder = "/bin/sh"; system = "x86_64-linux"; };
|
||||
in "${drv}" == builtins.toString drv
|
||||
"#,
|
||||
);
|
||||
assert_eq!(result, Value::Bool(true));
|
||||
}
|
||||
@@ -225,8 +225,14 @@ fn function_to_string_fails() {
|
||||
|
||||
#[test]
|
||||
fn to_string_method_must_return_string() {
|
||||
let result = utils::eval_result(r#"toString { __toString = self: 42; }"#);
|
||||
assert!(result.is_err());
|
||||
assert_eq!(
|
||||
utils::eval(r#"toString { __toString = self: 42; }"#),
|
||||
Value::String("42".into())
|
||||
);
|
||||
assert_eq!(
|
||||
utils::eval(r#"toString { __toString = self: true; }"#),
|
||||
Value::String("1".into())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user