mirror of
https://github.com/NixOS/nix.git
synced 2025-12-16 22:11:05 +01:00
Fewer macros is better! Introduce a new `JsonChacterizationTest` mixin class to help with this. Also, avoid some needless copies with `GetParam`. Part of my effort shoring up the JSON formats with #13570.
342 lines
13 KiB
C++
342 lines
13 KiB
C++
#include <nlohmann/json.hpp>
|
|
#include <gtest/gtest.h>
|
|
|
|
#include "nix/util/experimental-features.hh"
|
|
#include "nix/store/derivations.hh"
|
|
|
|
#include "nix/store/tests/libstore.hh"
|
|
#include "nix/util/tests/json-characterization.hh"
|
|
|
|
namespace nix {
|
|
|
|
using nlohmann::json;
|
|
|
|
class DerivationTest : public virtual CharacterizationTest, public LibStoreTest
|
|
{
|
|
std::filesystem::path unitTestData = getUnitTestData() / "derivation";
|
|
|
|
public:
|
|
std::filesystem::path goldenMaster(std::string_view testStem) const override
|
|
{
|
|
return unitTestData / testStem;
|
|
}
|
|
|
|
/**
|
|
* 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, readFile(goldenMaster("bad-version.drv")), "whatever", mockXpSettings), FormatError);
|
|
}
|
|
|
|
TEST_F(DynDerivationTest, BadATerm_oldVersionDynDeps)
|
|
{
|
|
ASSERT_THROW(
|
|
parseDerivation(
|
|
*store, readFile(goldenMaster("bad-old-version-dyn-deps.drv")), "dyn-dep-derivation", mockXpSettings),
|
|
FormatError);
|
|
}
|
|
|
|
#define MAKE_OUTPUT_JSON_TEST_P(FIXTURE) \
|
|
TEST_P(FIXTURE, from_json) \
|
|
{ \
|
|
const auto & [name, expected] = GetParam(); \
|
|
/* Don't use readJsonTest because we want to check experimental \
|
|
features. */ \
|
|
readTest(Path{"output-"} + name + ".json", [&](const auto & encoded_) { \
|
|
json j = json::parse(encoded_); \
|
|
DerivationOutput got = DerivationOutput::fromJSON(j, mockXpSettings); \
|
|
ASSERT_EQ(got, expected); \
|
|
}); \
|
|
} \
|
|
\
|
|
TEST_P(FIXTURE, to_json) \
|
|
{ \
|
|
const auto & [name, value] = GetParam(); \
|
|
writeJsonTest("output-" + name, value); \
|
|
}
|
|
|
|
struct DerivationOutputJsonTest : DerivationTest,
|
|
JsonCharacterizationTest<DerivationOutput>,
|
|
::testing::WithParamInterface<std::pair<std::string_view, DerivationOutput>>
|
|
{};
|
|
|
|
MAKE_OUTPUT_JSON_TEST_P(DerivationOutputJsonTest)
|
|
|
|
INSTANTIATE_TEST_SUITE_P(
|
|
DerivationOutputJSON,
|
|
DerivationOutputJsonTest,
|
|
::testing::Values(
|
|
std::pair{
|
|
"inputAddressed",
|
|
DerivationOutput{DerivationOutput::InputAddressed{
|
|
.path = StorePath{"c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-drv-name-output-name"},
|
|
}},
|
|
},
|
|
std::pair{
|
|
"caFixedFlat",
|
|
DerivationOutput{DerivationOutput::CAFixed{
|
|
.ca =
|
|
{
|
|
.method = ContentAddressMethod::Raw::Flat,
|
|
.hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="),
|
|
},
|
|
}},
|
|
},
|
|
std::pair{
|
|
"caFixedNAR",
|
|
DerivationOutput{DerivationOutput::CAFixed{
|
|
.ca =
|
|
{
|
|
.method = ContentAddressMethod::Raw::NixArchive,
|
|
.hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="),
|
|
},
|
|
}},
|
|
},
|
|
std::pair{
|
|
"deferred",
|
|
DerivationOutput{DerivationOutput::Deferred{}},
|
|
}));
|
|
|
|
struct DynDerivationOutputJsonTest : DynDerivationTest,
|
|
JsonCharacterizationTest<DerivationOutput>,
|
|
::testing::WithParamInterface<std::pair<std::string_view, DerivationOutput>>
|
|
{};
|
|
|
|
MAKE_OUTPUT_JSON_TEST_P(DynDerivationOutputJsonTest);
|
|
|
|
INSTANTIATE_TEST_SUITE_P(
|
|
DynDerivationOutputJSON,
|
|
DynDerivationOutputJsonTest,
|
|
::testing::Values(
|
|
std::pair{
|
|
"caFixedText",
|
|
DerivationOutput{DerivationOutput::CAFixed{
|
|
.ca =
|
|
{
|
|
.method = ContentAddressMethod::Raw::Text,
|
|
.hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="),
|
|
},
|
|
}},
|
|
}));
|
|
|
|
struct CaDerivationOutputJsonTest : CaDerivationTest,
|
|
JsonCharacterizationTest<DerivationOutput>,
|
|
::testing::WithParamInterface<std::pair<std::string_view, DerivationOutput>>
|
|
{};
|
|
|
|
MAKE_OUTPUT_JSON_TEST_P(CaDerivationOutputJsonTest);
|
|
|
|
INSTANTIATE_TEST_SUITE_P(
|
|
CaDerivationOutputJSON,
|
|
CaDerivationOutputJsonTest,
|
|
::testing::Values(
|
|
std::pair{
|
|
"caFloating",
|
|
DerivationOutput{DerivationOutput::CAFloating{
|
|
.method = ContentAddressMethod::Raw::NixArchive,
|
|
.hashAlgo = HashAlgorithm::SHA256,
|
|
}},
|
|
}));
|
|
|
|
struct ImpureDerivationOutputJsonTest : ImpureDerivationTest,
|
|
JsonCharacterizationTest<DerivationOutput>,
|
|
::testing::WithParamInterface<std::pair<std::string_view, DerivationOutput>>
|
|
{};
|
|
|
|
MAKE_OUTPUT_JSON_TEST_P(ImpureDerivationOutputJsonTest);
|
|
|
|
INSTANTIATE_TEST_SUITE_P(
|
|
ImpureDerivationOutputJSON,
|
|
ImpureDerivationOutputJsonTest,
|
|
::testing::Values(
|
|
std::pair{
|
|
"impure",
|
|
DerivationOutput{DerivationOutput::Impure{
|
|
.method = ContentAddressMethod::Raw::NixArchive,
|
|
.hashAlgo = HashAlgorithm::SHA256,
|
|
}},
|
|
}));
|
|
|
|
#undef MAKE_OUTPUT_JSON_TEST_P
|
|
|
|
#define MAKE_TEST_P(FIXTURE) \
|
|
TEST_P(FIXTURE, from_json) \
|
|
{ \
|
|
const auto & drv = GetParam(); \
|
|
/* Don't use readJsonTest because we want to check experimental \
|
|
features. */ \
|
|
readTest(drv.name + ".json", [&](const auto & encoded_) { \
|
|
auto encoded = json::parse(encoded_); \
|
|
Derivation got = Derivation::fromJSON(encoded, mockXpSettings); \
|
|
ASSERT_EQ(got, drv); \
|
|
}); \
|
|
} \
|
|
\
|
|
TEST_P(FIXTURE, to_json) \
|
|
{ \
|
|
const auto & drv = GetParam(); \
|
|
writeJsonTest(drv.name, drv); \
|
|
} \
|
|
\
|
|
TEST_P(FIXTURE, from_aterm) \
|
|
{ \
|
|
const auto & drv = GetParam(); \
|
|
readTest(drv.name + ".drv", [&](auto encoded) { \
|
|
auto got = parseDerivation(*store, std::move(encoded), drv.name, mockXpSettings); \
|
|
ASSERT_EQ(got.toJSON(), drv.toJSON()); \
|
|
ASSERT_EQ(got, drv); \
|
|
}); \
|
|
} \
|
|
\
|
|
TEST_P(FIXTURE, to_aterm) \
|
|
{ \
|
|
const auto & drv = GetParam(); \
|
|
writeTest(drv.name + ".drv", [&]() -> std::string { return drv.unparse(*store, false); }); \
|
|
}
|
|
|
|
struct DerivationJsonAtermTest : DerivationTest,
|
|
JsonCharacterizationTest<Derivation>,
|
|
::testing::WithParamInterface<Derivation>
|
|
{};
|
|
|
|
MAKE_TEST_P(DerivationJsonAtermTest);
|
|
|
|
Derivation makeSimpleDrv()
|
|
{
|
|
Derivation drv;
|
|
drv.name = "simple-derivation";
|
|
drv.inputSrcs = {
|
|
StorePath("c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"),
|
|
};
|
|
drv.inputDrvs = {
|
|
.map =
|
|
{
|
|
{
|
|
StorePath("c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv"),
|
|
{
|
|
.value =
|
|
{
|
|
"cat",
|
|
"dog",
|
|
},
|
|
},
|
|
},
|
|
},
|
|
};
|
|
drv.platform = "wasm-sel4";
|
|
drv.builder = "foo";
|
|
drv.args = {
|
|
"bar",
|
|
"baz",
|
|
};
|
|
drv.env = StringPairs{
|
|
{
|
|
"BIG_BAD",
|
|
"WOLF",
|
|
},
|
|
};
|
|
return drv;
|
|
}
|
|
|
|
INSTANTIATE_TEST_SUITE_P(DerivationJSONATerm, DerivationJsonAtermTest, ::testing::Values(makeSimpleDrv()));
|
|
|
|
struct DynDerivationJsonAtermTest : DynDerivationTest,
|
|
JsonCharacterizationTest<Derivation>,
|
|
::testing::WithParamInterface<Derivation>
|
|
{};
|
|
|
|
MAKE_TEST_P(DynDerivationJsonAtermTest);
|
|
|
|
Derivation makeDynDepDerivation()
|
|
{
|
|
Derivation drv;
|
|
drv.name = "dyn-dep-derivation";
|
|
drv.inputSrcs = {
|
|
StorePath{"c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"},
|
|
};
|
|
drv.inputDrvs = {
|
|
.map =
|
|
{
|
|
{
|
|
StorePath{"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 = StringPairs{
|
|
{
|
|
"BIG_BAD",
|
|
"WOLF",
|
|
},
|
|
};
|
|
return drv;
|
|
}
|
|
|
|
INSTANTIATE_TEST_SUITE_P(DynDerivationJSONATerm, DynDerivationJsonAtermTest, ::testing::Values(makeDynDepDerivation()));
|
|
|
|
#undef MAKE_TEST_P
|
|
|
|
} // namespace nix
|