(defnix spec-replaceStrings-simple
:source "builtins.replaceStrings [ \"a\" ] [ \"z\" ] \"banana\""
:expected-json "\"bznznz\""
:tags ("spec" "string" "verified")
:note
"CppNix semantics: each occurrence of from[i] in subject becomes
to[i]. Multiple froms matched left-to-right greedily.")
(defnix spec-replaceStrings-multi
:source "builtins.replaceStrings [ \"foo\" \"bar\" ] [ \"baz\" \"qux\" ] \"foo and bar\""
:expected-json "\"baz and qux\""
:tags ("spec" "string" "verified")
:note
"Length-2 from/to arrays. Each pair is an independent rewrite rule
applied in parallel (no from[i] result feeds into the next match).")
(defnix spec-catAttrs-basic
:source
"builtins.catAttrs \"x\" [ { x = 1; y = 10; } { x = 2; } { y = 20; } { x = 3; } ]"
:expected-json "[1,2,3]"
:tags ("spec" "attrs" "verified")
:note
"Spec: project name out of each list element, skipping elements
that don't have the attribute.")
(defnix spec-groupBy-parity
:source
"let parity = n: if (n / 2) * 2 == n then \"even\" else \"odd\";
in builtins.groupBy parity [ 1 2 3 4 5 ]"
:expected-json "{\"even\":[2,4],\"odd\":[1,3,5]}"
:tags ("spec" "list" "attrs" "verified")
:note
"Each elem goes into the bucket whose name is `f elem`. Bucket
order follows input order (stable). Attrset keys are lex-sorted
in to_json output.")
(defnix spec-unsafeDiscardOutputDependency-passthrough
:source "builtins.unsafeDiscardOutputDependency \"hello\""
:expected-json "\"hello\""
:tags ("spec" "string-context" "verified")
:note
"Context-free input round-trips verbatim. Full coverage needs a
derivation in the input to observe the actual context change —
deferred to the derivation-store integration corpus.")
(defnix spec-nixVersion-string
:source "builtins.nixVersion"
:expected-json "\"2.24.0\""
:tags ("spec" "meta" "verified" "version-dependent")
:skip #t
:note
"sui identifies as Nix 2.24.0 for compat. This test catches drift
on sui's side, but will diverge from the `oracle_corpus_matches_cppnix`
check whenever the host CppNix is a different version (e.g. 2.33 on
Determinate Nix 3.17). Skipped by default because it's the only
corpus entry that can't agree with arbitrary host nix — pick one
oracle or the other, not both. The author-curated value still
protects against sui-internal version drift when run standalone.")
(defnix spec-path-import-basic
:source "builtins.path { path = /tmp/nonexistent-oracle-path; name = \"x\"; }"
:expected-json "\"\""
:tags ("spec" "path" "needs-fixture")
:skip #t
:note
"sui's builtins.path requires a real path. Promote to a proper
test using tempfile fixtures so the store path is deterministic.
Needs a structural matcher for /nix/store/HASH-NAME format too.")
(defnix spec-fetchClosure-basic
:source
"builtins.fetchClosure {
fromStore = \"https://cache.nixos.org\";
fromPath = \"/nix/store/abc-hello\";
}"
:expected-json "\"/nix/store/abc-hello\""
:tags ("spec" "fetcher" "flake-blocker" "missing")
:skip #t
:note
"Not implemented. Fetcher-class builtin; requires substituter
client (Track C gap). Expected is a placeholder — when we
implement this, the result is the toPath (or fromPath when
content-preserving).")