aboutsummaryrefslogtreecommitdiff
path: root/tests/unit/libstore/derivation.cc
diff options
context:
space:
mode:
authorJohn Ericson <John.Ericson@Obsidian.Systems>2023-08-25 10:20:28 -0400
committerJohn Ericson <John.Ericson@Obsidian.Systems>2023-12-01 13:05:03 -0500
commitf7f37035c81fa825a4dfc2df1ad2589013ac6380 (patch)
treebfcfef3efeb73cb0c3c6d812280191d03bda1233 /tests/unit/libstore/derivation.cc
parent30dcc19d1f30fc203be460134c4578509cce704f (diff)
Move tests to separate directories, and document
Today, with the tests inside a `tests` intermingled with the corresponding library's source code, we have a few problems: - We have to be careful that wildcards don't end up with tests being built as part of Nix proper, or test headers being installed as part of Nix proper. - Tests in libraries but not executables is not right: - It means each executable runs the previous unit tests again, because it needs the libraries. - It doesn't work right on Windows, which doesn't want you to load a DLL just for the side global variable . It could be made to work with the dlopen equivalent, but that's gross! This reorg solves these problems. There is a remaining problem which is that sibbling headers (like `hash.hh` the test header vs `hash.hh` the main `libnixutil` header) end up shadowing each other. This PR doesn't solve that. That is left as future work for a future PR. Co-authored-by: Valentin Gagarin <valentin.gagarin@tweag.io> (cherry picked from commit 91b6833686a6a6d9eac7f3f66393ec89ef1d3b57) (cherry picked from commit a61e42adb528b3d40ce43e07c79368d779a8b624)
Diffstat (limited to 'tests/unit/libstore/derivation.cc')
-rw-r--r--tests/unit/libstore/derivation.cc369
1 files changed, 369 insertions, 0 deletions
diff --git a/tests/unit/libstore/derivation.cc b/tests/unit/libstore/derivation.cc
new file mode 100644
index 000000000..c360c9707
--- /dev/null
+++ b/tests/unit/libstore/derivation.cc
@@ -0,0 +1,369 @@
+#include <nlohmann/json.hpp>
+#include <gtest/gtest.h>
+
+#include "experimental-features.hh"
+#include "derivations.hh"
+
+#include "tests/libstore.hh"
+
+namespace nix {
+
+class DerivationTest : public LibStoreTest
+{
+public:
+ /**
+ * We set these in tests rather than the regular globals so we don't have
+ * to worry about race conditions if the tests run concurrently.
+ */
+ ExperimentalFeatureSettings mockXpSettings;
+};
+
+class CaDerivationTest : public DerivationTest
+{
+ void SetUp() override
+ {
+ mockXpSettings.set("experimental-features", "ca-derivations");
+ }
+};
+
+class DynDerivationTest : public DerivationTest
+{
+ void SetUp() override
+ {
+ mockXpSettings.set("experimental-features", "dynamic-derivations ca-derivations");
+ }
+};
+
+class ImpureDerivationTest : public DerivationTest
+{
+ void SetUp() override
+ {
+ mockXpSettings.set("experimental-features", "impure-derivations");
+ }
+};
+
+TEST_F(DerivationTest, BadATerm_version) {
+ ASSERT_THROW(
+ parseDerivation(
+ *store,
+ R"(DrvWithVersion("invalid-version",[],[("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv",["cat","dog"])],["/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"],"wasm-sel4","foo",["bar","baz"],[("BIG_BAD","WOLF")]))",
+ "whatever",
+ mockXpSettings),
+ FormatError);
+}
+
+TEST_F(DynDerivationTest, BadATerm_oldVersionDynDeps) {
+ ASSERT_THROW(
+ parseDerivation(
+ *store,
+ R"(Derive([],[("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv",(["cat","dog"],[("cat",["kitten"]),("goose",["gosling"])]))],["/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"],"wasm-sel4","foo",["bar","baz"],[("BIG_BAD","WOLF")]))",
+ "dyn-dep-derivation",
+ mockXpSettings),
+ FormatError);
+}
+
+#define TEST_JSON(FIXTURE, NAME, STR, VAL, DRV_NAME, OUTPUT_NAME) \
+ TEST_F(FIXTURE, DerivationOutput_ ## NAME ## _to_json) { \
+ using nlohmann::literals::operator "" _json; \
+ ASSERT_EQ( \
+ STR ## _json, \
+ (DerivationOutput { VAL }).toJSON( \
+ *store, \
+ DRV_NAME, \
+ OUTPUT_NAME)); \
+ } \
+ \
+ TEST_F(FIXTURE, DerivationOutput_ ## NAME ## _from_json) { \
+ using nlohmann::literals::operator "" _json; \
+ ASSERT_EQ( \
+ DerivationOutput { VAL }, \
+ DerivationOutput::fromJSON( \
+ *store, \
+ DRV_NAME, \
+ OUTPUT_NAME, \
+ STR ## _json, \
+ mockXpSettings)); \
+ }
+
+TEST_JSON(DerivationTest, inputAddressed,
+ R"({
+ "path": "/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-drv-name-output-name"
+ })",
+ (DerivationOutput::InputAddressed {
+ .path = store->parseStorePath("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-drv-name-output-name"),
+ }),
+ "drv-name", "output-name")
+
+TEST_JSON(DerivationTest, caFixedFlat,
+ R"({
+ "hashAlgo": "sha256",
+ "hash": "894517c9163c896ec31a2adbd33c0681fd5f45b2c0ef08a64c92a03fb97f390f",
+ "path": "/nix/store/rhcg9h16sqvlbpsa6dqm57sbr2al6nzg-drv-name-output-name"
+ })",
+ (DerivationOutput::CAFixed {
+ .ca = {
+ .method = FileIngestionMethod::Flat,
+ .hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="),
+ },
+ }),
+ "drv-name", "output-name")
+
+TEST_JSON(DerivationTest, caFixedNAR,
+ R"({
+ "hashAlgo": "r:sha256",
+ "hash": "894517c9163c896ec31a2adbd33c0681fd5f45b2c0ef08a64c92a03fb97f390f",
+ "path": "/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-drv-name-output-name"
+ })",
+ (DerivationOutput::CAFixed {
+ .ca = {
+ .method = FileIngestionMethod::Recursive,
+ .hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="),
+ },
+ }),
+ "drv-name", "output-name")
+
+TEST_JSON(DynDerivationTest, caFixedText,
+ R"({
+ "hashAlgo": "text:sha256",
+ "hash": "894517c9163c896ec31a2adbd33c0681fd5f45b2c0ef08a64c92a03fb97f390f",
+ "path": "/nix/store/6s1zwabh956jvhv4w9xcdb5jiyanyxg1-drv-name-output-name"
+ })",
+ (DerivationOutput::CAFixed {
+ .ca = {
+ .hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="),
+ },
+ }),
+ "drv-name", "output-name")
+
+TEST_JSON(CaDerivationTest, caFloating,
+ R"({
+ "hashAlgo": "r:sha256"
+ })",
+ (DerivationOutput::CAFloating {
+ .method = FileIngestionMethod::Recursive,
+ .hashType = htSHA256,
+ }),
+ "drv-name", "output-name")
+
+TEST_JSON(DerivationTest, deferred,
+ R"({ })",
+ DerivationOutput::Deferred { },
+ "drv-name", "output-name")
+
+TEST_JSON(ImpureDerivationTest, impure,
+ R"({
+ "hashAlgo": "r:sha256",
+ "impure": true
+ })",
+ (DerivationOutput::Impure {
+ .method = FileIngestionMethod::Recursive,
+ .hashType = htSHA256,
+ }),
+ "drv-name", "output-name")
+
+#undef TEST_JSON
+
+#define TEST_JSON(FIXTURE, NAME, STR, VAL) \
+ TEST_F(FIXTURE, Derivation_ ## NAME ## _to_json) { \
+ using nlohmann::literals::operator "" _json; \
+ ASSERT_EQ( \
+ STR ## _json, \
+ (VAL).toJSON(*store)); \
+ } \
+ \
+ TEST_F(FIXTURE, Derivation_ ## NAME ## _from_json) { \
+ using nlohmann::literals::operator "" _json; \
+ ASSERT_EQ( \
+ (VAL), \
+ Derivation::fromJSON( \
+ *store, \
+ STR ## _json, \
+ mockXpSettings)); \
+ }
+
+#define TEST_ATERM(FIXTURE, NAME, STR, VAL, DRV_NAME) \
+ TEST_F(FIXTURE, Derivation_ ## NAME ## _to_aterm) { \
+ ASSERT_EQ( \
+ STR, \
+ (VAL).unparse(*store, false)); \
+ } \
+ \
+ TEST_F(FIXTURE, Derivation_ ## NAME ## _from_aterm) { \
+ auto parsed = parseDerivation( \
+ *store, \
+ STR, \
+ DRV_NAME, \
+ mockXpSettings); \
+ ASSERT_EQ( \
+ (VAL).toJSON(*store), \
+ parsed.toJSON(*store)); \
+ ASSERT_EQ( \
+ (VAL), \
+ parsed); \
+ }
+
+Derivation makeSimpleDrv(const Store & store) {
+ Derivation drv;
+ drv.name = "simple-derivation";
+ drv.inputSrcs = {
+ store.parseStorePath("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"),
+ };
+ drv.inputDrvs = {
+ .map = {
+ {
+ store.parseStorePath("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv"),
+ {
+ .value = {
+ "cat",
+ "dog",
+ },
+ },
+ },
+ },
+ };
+ drv.platform = "wasm-sel4";
+ drv.builder = "foo";
+ drv.args = {
+ "bar",
+ "baz",
+ };
+ drv.env = {
+ {
+ "BIG_BAD",
+ "WOLF",
+ },
+ };
+ return drv;
+}
+
+TEST_JSON(DerivationTest, simple,
+ R"({
+ "name": "simple-derivation",
+ "inputSrcs": [
+ "/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"
+ ],
+ "inputDrvs": {
+ "/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv": {
+ "dynamicOutputs": {},
+ "outputs": [
+ "cat",
+ "dog"
+ ]
+ }
+ },
+ "system": "wasm-sel4",
+ "builder": "foo",
+ "args": [
+ "bar",
+ "baz"
+ ],
+ "env": {
+ "BIG_BAD": "WOLF"
+ },
+ "outputs": {}
+ })",
+ makeSimpleDrv(*store))
+
+TEST_ATERM(DerivationTest, simple,
+ R"(Derive([],[("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv",["cat","dog"])],["/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"],"wasm-sel4","foo",["bar","baz"],[("BIG_BAD","WOLF")]))",
+ makeSimpleDrv(*store),
+ "simple-derivation")
+
+Derivation makeDynDepDerivation(const Store & store) {
+ Derivation drv;
+ drv.name = "dyn-dep-derivation";
+ drv.inputSrcs = {
+ store.parseStorePath("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"),
+ };
+ drv.inputDrvs = {
+ .map = {
+ {
+ store.parseStorePath("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv"),
+ DerivedPathMap<StringSet>::ChildNode {
+ .value = {
+ "cat",
+ "dog",
+ },
+ .childMap = {
+ {
+ "cat",
+ DerivedPathMap<StringSet>::ChildNode {
+ .value = {
+ "kitten",
+ },
+ },
+ },
+ {
+ "goose",
+ DerivedPathMap<StringSet>::ChildNode {
+ .value = {
+ "gosling",
+ },
+ },
+ },
+ },
+ },
+ },
+ },
+ };
+ drv.platform = "wasm-sel4";
+ drv.builder = "foo";
+ drv.args = {
+ "bar",
+ "baz",
+ };
+ drv.env = {
+ {
+ "BIG_BAD",
+ "WOLF",
+ },
+ };
+ return drv;
+}
+
+TEST_JSON(DynDerivationTest, dynDerivationDeps,
+ R"({
+ "name": "dyn-dep-derivation",
+ "inputSrcs": [
+ "/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"
+ ],
+ "inputDrvs": {
+ "/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv": {
+ "dynamicOutputs": {
+ "cat": {
+ "dynamicOutputs": {},
+ "outputs": ["kitten"]
+ },
+ "goose": {
+ "dynamicOutputs": {},
+ "outputs": ["gosling"]
+ }
+ },
+ "outputs": [
+ "cat",
+ "dog"
+ ]
+ }
+ },
+ "system": "wasm-sel4",
+ "builder": "foo",
+ "args": [
+ "bar",
+ "baz"
+ ],
+ "env": {
+ "BIG_BAD": "WOLF"
+ },
+ "outputs": {}
+ })",
+ makeDynDepDerivation(*store))
+
+TEST_ATERM(DynDerivationTest, dynDerivationDeps,
+ R"(DrvWithVersion("xp-dyn-drv",[],[("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv",(["cat","dog"],[("cat",["kitten"]),("goose",["gosling"])]))],["/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"],"wasm-sel4","foo",["bar","baz"],[("BIG_BAD","WOLF")]))",
+ makeDynDepDerivation(*store),
+ "dyn-dep-derivation")
+
+#undef TEST_JSON
+#undef TEST_ATERM
+
+}