mirror of
https://github.com/NixOS/nix.git
synced 2025-11-09 03:56:01 +01:00
Minimize the use of C Macros for characterization tests
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.
This commit is contained in:
parent
3bf1268ac6
commit
01b2037bc0
15 changed files with 364 additions and 252 deletions
|
|
@ -642,7 +642,7 @@ class ToStringPrimOpTest : public PrimOpTest,
|
||||||
|
|
||||||
TEST_P(ToStringPrimOpTest, toString)
|
TEST_P(ToStringPrimOpTest, toString)
|
||||||
{
|
{
|
||||||
const auto [input, output] = GetParam();
|
const auto & [input, output] = GetParam();
|
||||||
auto v = eval(input);
|
auto v = eval(input);
|
||||||
ASSERT_THAT(v, IsStringEq(output));
|
ASSERT_THAT(v, IsStringEq(output));
|
||||||
}
|
}
|
||||||
|
|
@ -798,7 +798,7 @@ class CompareVersionsPrimOpTest : public PrimOpTest,
|
||||||
|
|
||||||
TEST_P(CompareVersionsPrimOpTest, compareVersions)
|
TEST_P(CompareVersionsPrimOpTest, compareVersions)
|
||||||
{
|
{
|
||||||
auto [expression, expectation] = GetParam();
|
const auto & [expression, expectation] = GetParam();
|
||||||
auto v = eval(expression);
|
auto v = eval(expression);
|
||||||
ASSERT_THAT(v, IsIntEq(expectation));
|
ASSERT_THAT(v, IsIntEq(expectation));
|
||||||
}
|
}
|
||||||
|
|
@ -834,7 +834,7 @@ class ParseDrvNamePrimOpTest
|
||||||
|
|
||||||
TEST_P(ParseDrvNamePrimOpTest, parseDrvName)
|
TEST_P(ParseDrvNamePrimOpTest, parseDrvName)
|
||||||
{
|
{
|
||||||
auto [input, expectedName, expectedVersion] = GetParam();
|
const auto & [input, expectedName, expectedVersion] = GetParam();
|
||||||
const auto expr = fmt("builtins.parseDrvName \"%1%\"", input);
|
const auto expr = fmt("builtins.parseDrvName \"%1%\"", input);
|
||||||
auto v = eval(expr);
|
auto v = eval(expr);
|
||||||
ASSERT_THAT(v, IsAttrsOfSize(2));
|
ASSERT_THAT(v, IsAttrsOfSize(2));
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,14 @@
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
#include "nix/fetchers/fetchers.hh"
|
#include "nix/fetchers/fetchers.hh"
|
||||||
#include "nix/util/json-utils.hh"
|
#include "nix/util/json-utils.hh"
|
||||||
#include <nlohmann/json.hpp>
|
#include "nix/util/tests/json-characterization.hh"
|
||||||
#include "nix/util/tests/characterization.hh"
|
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
using nlohmann::json;
|
using nlohmann::json;
|
||||||
|
|
||||||
class PublicKeyTest : public CharacterizationTest
|
class PublicKeyTest : public JsonCharacterizationTest<fetchers::PublicKey>,
|
||||||
|
public ::testing::WithParamInterface<std::pair<std::string_view, fetchers::PublicKey>>
|
||||||
{
|
{
|
||||||
std::filesystem::path unitTestData = getUnitTestData() / "public-key";
|
std::filesystem::path unitTestData = getUnitTestData() / "public-key";
|
||||||
|
|
||||||
|
|
@ -19,30 +19,35 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TEST_JSON(FIXTURE, NAME, VAL) \
|
TEST_P(PublicKeyTest, from_json)
|
||||||
TEST_F(FIXTURE, PublicKey_##NAME##_from_json) \
|
{
|
||||||
{ \
|
const auto & [name, expected] = GetParam();
|
||||||
readTest(#NAME ".json", [&](const auto & encoded_) { \
|
readJsonTest(name, expected);
|
||||||
fetchers::PublicKey expected{VAL}; \
|
}
|
||||||
fetchers::PublicKey got = nlohmann::json::parse(encoded_); \
|
|
||||||
ASSERT_EQ(got, expected); \
|
|
||||||
}); \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
TEST_F(FIXTURE, PublicKey_##NAME##_to_json) \
|
|
||||||
{ \
|
|
||||||
writeTest( \
|
|
||||||
#NAME ".json", \
|
|
||||||
[&]() -> json { return nlohmann::json(fetchers::PublicKey{VAL}); }, \
|
|
||||||
[](const auto & file) { return json::parse(readFile(file)); }, \
|
|
||||||
[](const auto & file, const auto & got) { return writeFile(file, got.dump(2) + "\n"); }); \
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_JSON(PublicKeyTest, simple, (fetchers::PublicKey{.type = "ssh-rsa", .key = "ABCDE"}))
|
TEST_P(PublicKeyTest, to_json)
|
||||||
|
{
|
||||||
|
const auto & [name, value] = GetParam();
|
||||||
|
writeJsonTest(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
TEST_JSON(PublicKeyTest, defaultType, fetchers::PublicKey{.key = "ABCDE"})
|
INSTANTIATE_TEST_SUITE_P(
|
||||||
|
PublicKeyJSON,
|
||||||
#undef TEST_JSON
|
PublicKeyTest,
|
||||||
|
::testing::Values(
|
||||||
|
std::pair{
|
||||||
|
"simple",
|
||||||
|
fetchers::PublicKey{
|
||||||
|
.type = "ssh-rsa",
|
||||||
|
.key = "ABCDE",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
std::pair{
|
||||||
|
"defaultType",
|
||||||
|
fetchers::PublicKey{
|
||||||
|
.key = "ABCDE",
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
TEST_F(PublicKeyTest, PublicKey_noRoundTrip_from_json)
|
TEST_F(PublicKeyTest, PublicKey_noRoundTrip_from_json)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -5,13 +5,13 @@
|
||||||
#include "nix/store/derivations.hh"
|
#include "nix/store/derivations.hh"
|
||||||
|
|
||||||
#include "nix/store/tests/libstore.hh"
|
#include "nix/store/tests/libstore.hh"
|
||||||
#include "nix/util/tests/characterization.hh"
|
#include "nix/util/tests/json-characterization.hh"
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
using nlohmann::json;
|
using nlohmann::json;
|
||||||
|
|
||||||
class DerivationTest : public CharacterizationTest, public LibStoreTest
|
class DerivationTest : public virtual CharacterizationTest, public LibStoreTest
|
||||||
{
|
{
|
||||||
std::filesystem::path unitTestData = getUnitTestData() / "derivation";
|
std::filesystem::path unitTestData = getUnitTestData() / "derivation";
|
||||||
|
|
||||||
|
|
@ -66,146 +66,183 @@ TEST_F(DynDerivationTest, BadATerm_oldVersionDynDeps)
|
||||||
FormatError);
|
FormatError);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define TEST_JSON(FIXTURE, NAME, VAL, DRV_NAME, OUTPUT_NAME) \
|
#define MAKE_OUTPUT_JSON_TEST_P(FIXTURE) \
|
||||||
TEST_F(FIXTURE, DerivationOutput_##NAME##_from_json) \
|
TEST_P(FIXTURE, from_json) \
|
||||||
{ \
|
{ \
|
||||||
readTest("output-" #NAME ".json", [&](const auto & encoded_) { \
|
const auto & [name, expected] = GetParam(); \
|
||||||
auto encoded = json::parse(encoded_); \
|
/* Don't use readJsonTest because we want to check experimental \
|
||||||
DerivationOutput got = DerivationOutput::fromJSON(DRV_NAME, OUTPUT_NAME, encoded, mockXpSettings); \
|
features. */ \
|
||||||
DerivationOutput expected{VAL}; \
|
readTest(Path{"output-"} + name + ".json", [&](const auto & encoded_) { \
|
||||||
|
json j = json::parse(encoded_); \
|
||||||
|
DerivationOutput got = DerivationOutput::fromJSON(j, mockXpSettings); \
|
||||||
ASSERT_EQ(got, expected); \
|
ASSERT_EQ(got, expected); \
|
||||||
}); \
|
}); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
TEST_F(FIXTURE, DerivationOutput_##NAME##_to_json) \
|
TEST_P(FIXTURE, to_json) \
|
||||||
{ \
|
{ \
|
||||||
writeTest( \
|
const auto & [name, value] = GetParam(); \
|
||||||
"output-" #NAME ".json", \
|
writeJsonTest("output-" + name, value); \
|
||||||
[&]() -> json { return DerivationOutput{(VAL)}.toJSON((DRV_NAME), (OUTPUT_NAME)); }, \
|
|
||||||
[](const auto & file) { return json::parse(readFile(file)); }, \
|
|
||||||
[](const auto & file, const auto & got) { return writeFile(file, got.dump(2) + "\n"); }); \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_JSON(
|
struct DerivationOutputJsonTest : DerivationTest,
|
||||||
DerivationTest,
|
JsonCharacterizationTest<DerivationOutput>,
|
||||||
inputAddressed,
|
::testing::WithParamInterface<std::pair<std::string_view, DerivationOutput>>
|
||||||
(DerivationOutput::InputAddressed{
|
{};
|
||||||
.path = store->parseStorePath("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-drv-name-output-name"),
|
|
||||||
}),
|
|
||||||
"drv-name",
|
|
||||||
"output-name")
|
|
||||||
|
|
||||||
TEST_JSON(
|
MAKE_OUTPUT_JSON_TEST_P(DerivationOutputJsonTest)
|
||||||
DerivationTest,
|
|
||||||
caFixedFlat,
|
INSTANTIATE_TEST_SUITE_P(
|
||||||
(DerivationOutput::CAFixed{
|
DerivationOutputJSON,
|
||||||
|
DerivationOutputJsonTest,
|
||||||
|
::testing::Values(
|
||||||
|
std::pair{
|
||||||
|
"inputAddressed",
|
||||||
|
DerivationOutput{DerivationOutput::InputAddressed{
|
||||||
|
.path = StorePath{"c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-drv-name-output-name"},
|
||||||
|
}},
|
||||||
|
},
|
||||||
|
std::pair{
|
||||||
|
"caFixedFlat",
|
||||||
|
DerivationOutput{DerivationOutput::CAFixed{
|
||||||
.ca =
|
.ca =
|
||||||
{
|
{
|
||||||
.method = ContentAddressMethod::Raw::Flat,
|
.method = ContentAddressMethod::Raw::Flat,
|
||||||
.hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="),
|
.hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="),
|
||||||
},
|
},
|
||||||
}),
|
}},
|
||||||
"drv-name",
|
},
|
||||||
"output-name")
|
std::pair{
|
||||||
|
"caFixedNAR",
|
||||||
TEST_JSON(
|
DerivationOutput{DerivationOutput::CAFixed{
|
||||||
DerivationTest,
|
|
||||||
caFixedNAR,
|
|
||||||
(DerivationOutput::CAFixed{
|
|
||||||
.ca =
|
.ca =
|
||||||
{
|
{
|
||||||
.method = ContentAddressMethod::Raw::NixArchive,
|
.method = ContentAddressMethod::Raw::NixArchive,
|
||||||
.hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="),
|
.hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="),
|
||||||
},
|
},
|
||||||
}),
|
}},
|
||||||
"drv-name",
|
},
|
||||||
"output-name")
|
std::pair{
|
||||||
|
"deferred",
|
||||||
|
DerivationOutput{DerivationOutput::Deferred{}},
|
||||||
|
}));
|
||||||
|
|
||||||
TEST_JSON(
|
struct DynDerivationOutputJsonTest : DynDerivationTest,
|
||||||
DynDerivationTest,
|
JsonCharacterizationTest<DerivationOutput>,
|
||||||
caFixedText,
|
::testing::WithParamInterface<std::pair<std::string_view, DerivationOutput>>
|
||||||
(DerivationOutput::CAFixed{
|
{};
|
||||||
|
|
||||||
|
MAKE_OUTPUT_JSON_TEST_P(DynDerivationOutputJsonTest);
|
||||||
|
|
||||||
|
INSTANTIATE_TEST_SUITE_P(
|
||||||
|
DynDerivationOutputJSON,
|
||||||
|
DynDerivationOutputJsonTest,
|
||||||
|
::testing::Values(
|
||||||
|
std::pair{
|
||||||
|
"caFixedText",
|
||||||
|
DerivationOutput{DerivationOutput::CAFixed{
|
||||||
.ca =
|
.ca =
|
||||||
{
|
{
|
||||||
.method = ContentAddressMethod::Raw::Text,
|
.method = ContentAddressMethod::Raw::Text,
|
||||||
.hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="),
|
.hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="),
|
||||||
},
|
},
|
||||||
}),
|
}},
|
||||||
"drv-name",
|
}));
|
||||||
"output-name")
|
|
||||||
|
|
||||||
TEST_JSON(
|
struct CaDerivationOutputJsonTest : CaDerivationTest,
|
||||||
CaDerivationTest,
|
JsonCharacterizationTest<DerivationOutput>,
|
||||||
caFloating,
|
::testing::WithParamInterface<std::pair<std::string_view, DerivationOutput>>
|
||||||
(DerivationOutput::CAFloating{
|
{};
|
||||||
|
|
||||||
|
MAKE_OUTPUT_JSON_TEST_P(CaDerivationOutputJsonTest);
|
||||||
|
|
||||||
|
INSTANTIATE_TEST_SUITE_P(
|
||||||
|
CaDerivationOutputJSON,
|
||||||
|
CaDerivationOutputJsonTest,
|
||||||
|
::testing::Values(
|
||||||
|
std::pair{
|
||||||
|
"caFloating",
|
||||||
|
DerivationOutput{DerivationOutput::CAFloating{
|
||||||
.method = ContentAddressMethod::Raw::NixArchive,
|
.method = ContentAddressMethod::Raw::NixArchive,
|
||||||
.hashAlgo = HashAlgorithm::SHA256,
|
.hashAlgo = HashAlgorithm::SHA256,
|
||||||
}),
|
}},
|
||||||
"drv-name",
|
}));
|
||||||
"output-name")
|
|
||||||
|
|
||||||
TEST_JSON(DerivationTest, deferred, DerivationOutput::Deferred{}, "drv-name", "output-name")
|
struct ImpureDerivationOutputJsonTest : ImpureDerivationTest,
|
||||||
|
JsonCharacterizationTest<DerivationOutput>,
|
||||||
|
::testing::WithParamInterface<std::pair<std::string_view, DerivationOutput>>
|
||||||
|
{};
|
||||||
|
|
||||||
TEST_JSON(
|
MAKE_OUTPUT_JSON_TEST_P(ImpureDerivationOutputJsonTest);
|
||||||
ImpureDerivationTest,
|
|
||||||
impure,
|
INSTANTIATE_TEST_SUITE_P(
|
||||||
(DerivationOutput::Impure{
|
ImpureDerivationOutputJSON,
|
||||||
|
ImpureDerivationOutputJsonTest,
|
||||||
|
::testing::Values(
|
||||||
|
std::pair{
|
||||||
|
"impure",
|
||||||
|
DerivationOutput{DerivationOutput::Impure{
|
||||||
.method = ContentAddressMethod::Raw::NixArchive,
|
.method = ContentAddressMethod::Raw::NixArchive,
|
||||||
.hashAlgo = HashAlgorithm::SHA256,
|
.hashAlgo = HashAlgorithm::SHA256,
|
||||||
}),
|
}},
|
||||||
"drv-name",
|
}));
|
||||||
"output-name")
|
|
||||||
|
|
||||||
#undef TEST_JSON
|
#undef MAKE_OUTPUT_JSON_TEST_P
|
||||||
|
|
||||||
#define TEST_JSON(FIXTURE, NAME, VAL) \
|
#define MAKE_TEST_P(FIXTURE) \
|
||||||
TEST_F(FIXTURE, Derivation_##NAME##_from_json) \
|
TEST_P(FIXTURE, from_json) \
|
||||||
{ \
|
{ \
|
||||||
readTest(#NAME ".json", [&](const auto & encoded_) { \
|
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_); \
|
auto encoded = json::parse(encoded_); \
|
||||||
Derivation expected{VAL}; \
|
|
||||||
Derivation got = Derivation::fromJSON(encoded, mockXpSettings); \
|
Derivation got = Derivation::fromJSON(encoded, mockXpSettings); \
|
||||||
ASSERT_EQ(got, expected); \
|
ASSERT_EQ(got, drv); \
|
||||||
}); \
|
}); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
TEST_F(FIXTURE, Derivation_##NAME##_to_json) \
|
TEST_P(FIXTURE, to_json) \
|
||||||
{ \
|
{ \
|
||||||
writeTest( \
|
const auto & drv = GetParam(); \
|
||||||
#NAME ".json", \
|
writeJsonTest(drv.name, drv); \
|
||||||
[&]() -> json { return Derivation{VAL}.toJSON(); }, \
|
} \
|
||||||
[](const auto & file) { return json::parse(readFile(file)); }, \
|
\
|
||||||
[](const auto & file, const auto & got) { return writeFile(file, got.dump(2) + "\n"); }); \
|
TEST_P(FIXTURE, from_aterm) \
|
||||||
}
|
|
||||||
|
|
||||||
#define TEST_ATERM(FIXTURE, NAME, VAL, DRV_NAME) \
|
|
||||||
TEST_F(FIXTURE, Derivation_##NAME##_from_aterm) \
|
|
||||||
{ \
|
{ \
|
||||||
readTest(#NAME ".drv", [&](auto encoded) { \
|
const auto & drv = GetParam(); \
|
||||||
Derivation expected{VAL}; \
|
readTest(drv.name + ".drv", [&](auto encoded) { \
|
||||||
auto got = parseDerivation(*store, std::move(encoded), DRV_NAME, mockXpSettings); \
|
auto got = parseDerivation(*store, std::move(encoded), drv.name, mockXpSettings); \
|
||||||
ASSERT_EQ(got.toJSON(), expected.toJSON()); \
|
ASSERT_EQ(got.toJSON(), drv.toJSON()); \
|
||||||
ASSERT_EQ(got, expected); \
|
ASSERT_EQ(got, drv); \
|
||||||
}); \
|
}); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
TEST_F(FIXTURE, Derivation_##NAME##_to_aterm) \
|
TEST_P(FIXTURE, to_aterm) \
|
||||||
{ \
|
{ \
|
||||||
writeTest(#NAME ".drv", [&]() -> std::string { return (VAL).unparse(*store, false); }); \
|
const auto & drv = GetParam(); \
|
||||||
|
writeTest(drv.name + ".drv", [&]() -> std::string { return drv.unparse(*store, false); }); \
|
||||||
}
|
}
|
||||||
|
|
||||||
Derivation makeSimpleDrv(const Store & store)
|
struct DerivationJsonAtermTest : DerivationTest,
|
||||||
|
JsonCharacterizationTest<Derivation>,
|
||||||
|
::testing::WithParamInterface<Derivation>
|
||||||
|
{};
|
||||||
|
|
||||||
|
MAKE_TEST_P(DerivationJsonAtermTest);
|
||||||
|
|
||||||
|
Derivation makeSimpleDrv()
|
||||||
{
|
{
|
||||||
Derivation drv;
|
Derivation drv;
|
||||||
drv.name = "simple-derivation";
|
drv.name = "simple-derivation";
|
||||||
drv.inputSrcs = {
|
drv.inputSrcs = {
|
||||||
store.parseStorePath("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"),
|
StorePath("c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"),
|
||||||
};
|
};
|
||||||
drv.inputDrvs = {
|
drv.inputDrvs = {
|
||||||
.map =
|
.map =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
store.parseStorePath("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv"),
|
StorePath("c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv"),
|
||||||
{
|
{
|
||||||
.value =
|
.value =
|
||||||
{
|
{
|
||||||
|
|
@ -231,22 +268,27 @@ Derivation makeSimpleDrv(const Store & store)
|
||||||
return drv;
|
return drv;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_JSON(DerivationTest, simple, makeSimpleDrv(*store))
|
INSTANTIATE_TEST_SUITE_P(DerivationJSONATerm, DerivationJsonAtermTest, ::testing::Values(makeSimpleDrv()));
|
||||||
|
|
||||||
TEST_ATERM(DerivationTest, simple, makeSimpleDrv(*store), "simple-derivation")
|
struct DynDerivationJsonAtermTest : DynDerivationTest,
|
||||||
|
JsonCharacterizationTest<Derivation>,
|
||||||
|
::testing::WithParamInterface<Derivation>
|
||||||
|
{};
|
||||||
|
|
||||||
Derivation makeDynDepDerivation(const Store & store)
|
MAKE_TEST_P(DynDerivationJsonAtermTest);
|
||||||
|
|
||||||
|
Derivation makeDynDepDerivation()
|
||||||
{
|
{
|
||||||
Derivation drv;
|
Derivation drv;
|
||||||
drv.name = "dyn-dep-derivation";
|
drv.name = "dyn-dep-derivation";
|
||||||
drv.inputSrcs = {
|
drv.inputSrcs = {
|
||||||
store.parseStorePath("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"),
|
StorePath{"c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"},
|
||||||
};
|
};
|
||||||
drv.inputDrvs = {
|
drv.inputDrvs = {
|
||||||
.map =
|
.map =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
store.parseStorePath("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv"),
|
StorePath{"c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv"},
|
||||||
DerivedPathMap<StringSet>::ChildNode{
|
DerivedPathMap<StringSet>::ChildNode{
|
||||||
.value =
|
.value =
|
||||||
{
|
{
|
||||||
|
|
@ -293,11 +335,8 @@ Derivation makeDynDepDerivation(const Store & store)
|
||||||
return drv;
|
return drv;
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_JSON(DynDerivationTest, dynDerivationDeps, makeDynDepDerivation(*store))
|
INSTANTIATE_TEST_SUITE_P(DynDerivationJSONATerm, DynDerivationJsonAtermTest, ::testing::Values(makeDynDepDerivation()));
|
||||||
|
|
||||||
TEST_ATERM(DynDerivationTest, dynDerivationDeps, makeDynDepDerivation(*store), "dyn-dep-derivation")
|
#undef MAKE_TEST_P
|
||||||
|
|
||||||
#undef TEST_JSON
|
|
||||||
#undef TEST_ATERM
|
|
||||||
|
|
||||||
} // namespace nix
|
} // namespace nix
|
||||||
|
|
|
||||||
|
|
@ -3,12 +3,11 @@
|
||||||
#include <rapidcheck/gtest.h>
|
#include <rapidcheck/gtest.h>
|
||||||
|
|
||||||
#include "nix/store/tests/outputs-spec.hh"
|
#include "nix/store/tests/outputs-spec.hh"
|
||||||
|
#include "nix/util/tests/json-characterization.hh"
|
||||||
#include "nix/util/tests/characterization.hh"
|
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
class OutputsSpecTest : public CharacterizationTest
|
class OutputsSpecTest : public virtual CharacterizationTest
|
||||||
{
|
{
|
||||||
std::filesystem::path unitTestData = getUnitTestData() / "outputs-spec";
|
std::filesystem::path unitTestData = getUnitTestData() / "outputs-spec";
|
||||||
|
|
||||||
|
|
@ -20,7 +19,7 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ExtendedOutputsSpecTest : public CharacterizationTest
|
class ExtendedOutputsSpecTest : public virtual CharacterizationTest
|
||||||
{
|
{
|
||||||
std::filesystem::path unitTestData = getUnitTestData() / "outputs-spec" / "extended";
|
std::filesystem::path unitTestData = getUnitTestData() / "outputs-spec" / "extended";
|
||||||
|
|
||||||
|
|
@ -214,40 +213,49 @@ TEST_F(ExtendedOutputsSpecTest, many_carrot)
|
||||||
ASSERT_EQ(std::string{prefix} + expected.to_string(), "foo^bar^bin,out");
|
ASSERT_EQ(std::string{prefix} + expected.to_string(), "foo^bar^bin,out");
|
||||||
}
|
}
|
||||||
|
|
||||||
#define TEST_JSON(FIXTURE, TYPE, NAME, VAL) \
|
#define MAKE_TEST_P(FIXTURE, TYPE) \
|
||||||
static const TYPE FIXTURE##_##NAME = VAL; \
|
TEST_P(FIXTURE, from_json) \
|
||||||
\
|
|
||||||
TEST_F(FIXTURE, NAME##_from_json) \
|
|
||||||
{ \
|
{ \
|
||||||
using namespace nlohmann; \
|
const auto & [name, value] = GetParam(); \
|
||||||
\
|
readJsonTest(name, value); \
|
||||||
readTest(#NAME ".json", [&](const auto & encoded_) { \
|
|
||||||
auto encoded = json::parse(encoded_); \
|
|
||||||
TYPE got = adl_serializer<TYPE>::from_json(encoded); \
|
|
||||||
ASSERT_EQ(got, FIXTURE##_##NAME); \
|
|
||||||
}); \
|
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
TEST_F(FIXTURE, NAME##_to_json) \
|
TEST_P(FIXTURE, to_json) \
|
||||||
{ \
|
{ \
|
||||||
using namespace nlohmann; \
|
const auto & [name, value] = GetParam(); \
|
||||||
\
|
writeJsonTest(name, value); \
|
||||||
writeTest( \
|
|
||||||
#NAME ".json", \
|
|
||||||
[&]() -> json { return static_cast<json>(FIXTURE##_##NAME); }, \
|
|
||||||
[](const auto & file) { return json::parse(readFile(file)); }, \
|
|
||||||
[](const auto & file, const auto & got) { return writeFile(file, got.dump(2) + "\n"); }); \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_JSON(OutputsSpecTest, OutputsSpec, all, OutputsSpec::All{})
|
struct OutputsSpecJsonTest : OutputsSpecTest,
|
||||||
TEST_JSON(OutputsSpecTest, OutputsSpec, name, OutputsSpec::Names{"a"})
|
JsonCharacterizationTest<OutputsSpec>,
|
||||||
TEST_JSON(OutputsSpecTest, OutputsSpec, names, (OutputsSpec::Names{"a", "b"}))
|
::testing::WithParamInterface<std::pair<std::string_view, OutputsSpec>>
|
||||||
|
{};
|
||||||
|
|
||||||
TEST_JSON(ExtendedOutputsSpecTest, ExtendedOutputsSpec, def, ExtendedOutputsSpec::Default{})
|
MAKE_TEST_P(OutputsSpecJsonTest, OutputsSpec);
|
||||||
TEST_JSON(ExtendedOutputsSpecTest, ExtendedOutputsSpec, all, ExtendedOutputsSpec::Explicit{OutputsSpec::All{}})
|
|
||||||
TEST_JSON(ExtendedOutputsSpecTest, ExtendedOutputsSpec, name, ExtendedOutputsSpec::Explicit{OutputsSpec::Names{"a"}})
|
INSTANTIATE_TEST_SUITE_P(
|
||||||
TEST_JSON(
|
OutputsSpecJSON,
|
||||||
ExtendedOutputsSpecTest, ExtendedOutputsSpec, names, (ExtendedOutputsSpec::Explicit{OutputsSpec::Names{"a", "b"}}))
|
OutputsSpecJsonTest,
|
||||||
|
::testing::Values(
|
||||||
|
std::pair{"all", OutputsSpec{OutputsSpec::All{}}},
|
||||||
|
std::pair{"name", OutputsSpec{OutputsSpec::Names{"a"}}},
|
||||||
|
std::pair{"names", OutputsSpec{OutputsSpec::Names{"a", "b"}}}));
|
||||||
|
|
||||||
|
struct ExtendedOutputsSpecJsonTest : ExtendedOutputsSpecTest,
|
||||||
|
JsonCharacterizationTest<ExtendedOutputsSpec>,
|
||||||
|
::testing::WithParamInterface<std::pair<std::string_view, ExtendedOutputsSpec>>
|
||||||
|
{};
|
||||||
|
|
||||||
|
MAKE_TEST_P(ExtendedOutputsSpecJsonTest, ExtendedOutputsSpec);
|
||||||
|
|
||||||
|
INSTANTIATE_TEST_SUITE_P(
|
||||||
|
ExtendedOutputsSpecJSON,
|
||||||
|
ExtendedOutputsSpecJsonTest,
|
||||||
|
::testing::Values(
|
||||||
|
std::pair{"def", ExtendedOutputsSpec{ExtendedOutputsSpec::Default{}}},
|
||||||
|
std::pair{"all", ExtendedOutputsSpec{ExtendedOutputsSpec::Explicit{OutputsSpec::All{}}}},
|
||||||
|
std::pair{"name", ExtendedOutputsSpec{ExtendedOutputsSpec::Explicit{OutputsSpec::Names{"a"}}}},
|
||||||
|
std::pair{"names", ExtendedOutputsSpec{ExtendedOutputsSpec::Explicit{OutputsSpec::Names{"a", "b"}}}}));
|
||||||
|
|
||||||
#undef TEST_JSON
|
#undef TEST_JSON
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
#include "nix/store/path-regex.hh"
|
#include "nix/store/path-regex.hh"
|
||||||
#include "nix/store/store-api.hh"
|
#include "nix/store/store-api.hh"
|
||||||
|
|
||||||
#include "nix/util/tests/characterization.hh"
|
#include "nix/util/tests/json-characterization.hh"
|
||||||
#include "nix/store/tests/libstore.hh"
|
#include "nix/store/tests/libstore.hh"
|
||||||
#include "nix/store/tests/path.hh"
|
#include "nix/store/tests/path.hh"
|
||||||
|
|
||||||
|
|
@ -16,7 +16,7 @@ namespace nix {
|
||||||
#define STORE_DIR "/nix/store/"
|
#define STORE_DIR "/nix/store/"
|
||||||
#define HASH_PART "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q"
|
#define HASH_PART "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q"
|
||||||
|
|
||||||
class StorePathTest : public CharacterizationTest, public LibStoreTest
|
class StorePathTest : public virtual CharacterizationTest, public LibStoreTest
|
||||||
{
|
{
|
||||||
std::filesystem::path unitTestData = getUnitTestData() / "store-path";
|
std::filesystem::path unitTestData = getUnitTestData() / "store-path";
|
||||||
|
|
||||||
|
|
@ -149,27 +149,30 @@ RC_GTEST_FIXTURE_PROP(StorePathTest, prop_check_regex_eq_parse, ())
|
||||||
|
|
||||||
using nlohmann::json;
|
using nlohmann::json;
|
||||||
|
|
||||||
#define TEST_JSON(FIXTURE, NAME, VAL) \
|
struct StorePathJsonTest : StorePathTest,
|
||||||
static const StorePath NAME = VAL; \
|
JsonCharacterizationTest<StorePath>,
|
||||||
\
|
::testing::WithParamInterface<std::pair<std::string_view, StorePath>>
|
||||||
TEST_F(FIXTURE, NAME##_from_json) \
|
{};
|
||||||
{ \
|
|
||||||
readTest(#NAME ".json", [&](const auto & encoded_) { \
|
|
||||||
auto encoded = json::parse(encoded_); \
|
|
||||||
StorePath got = static_cast<StorePath>(encoded); \
|
|
||||||
ASSERT_EQ(got, NAME); \
|
|
||||||
}); \
|
|
||||||
} \
|
|
||||||
\
|
|
||||||
TEST_F(FIXTURE, NAME##_to_json) \
|
|
||||||
{ \
|
|
||||||
writeTest( \
|
|
||||||
#NAME ".json", \
|
|
||||||
[&]() -> json { return static_cast<json>(NAME); }, \
|
|
||||||
[](const auto & file) { return json::parse(readFile(file)); }, \
|
|
||||||
[](const auto & file, const auto & got) { return writeFile(file, got.dump(2) + "\n"); }); \
|
|
||||||
}
|
|
||||||
|
|
||||||
TEST_JSON(StorePathTest, simple, StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo.drv"});
|
TEST_P(StorePathJsonTest, from_json)
|
||||||
|
{
|
||||||
|
auto & [name, expected] = GetParam();
|
||||||
|
readJsonTest(name, expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_P(StorePathJsonTest, to_json)
|
||||||
|
{
|
||||||
|
auto & [name, value] = GetParam();
|
||||||
|
writeJsonTest(name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
INSTANTIATE_TEST_SUITE_P(
|
||||||
|
StorePathJSON,
|
||||||
|
StorePathJsonTest,
|
||||||
|
::testing::Values(
|
||||||
|
std::pair{
|
||||||
|
"simple",
|
||||||
|
StorePath{"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo.drv"},
|
||||||
|
}));
|
||||||
|
|
||||||
} // namespace nix
|
} // namespace nix
|
||||||
|
|
|
||||||
|
|
@ -6,12 +6,12 @@
|
||||||
|
|
||||||
#include "nix/store/store-api.hh"
|
#include "nix/store/store-api.hh"
|
||||||
|
|
||||||
#include "nix/util/tests/characterization.hh"
|
#include "nix/util/tests/json-characterization.hh"
|
||||||
#include "nix/store/tests/libstore.hh"
|
#include "nix/store/tests/libstore.hh"
|
||||||
|
|
||||||
namespace nix {
|
namespace nix {
|
||||||
|
|
||||||
class RealisationTest : public CharacterizationTest, public LibStoreTest
|
class RealisationTest : public JsonCharacterizationTest<Realisation>, public LibStoreTest
|
||||||
{
|
{
|
||||||
std::filesystem::path unitTestData = getUnitTestData() / "realisation";
|
std::filesystem::path unitTestData = getUnitTestData() / "realisation";
|
||||||
|
|
||||||
|
|
@ -34,22 +34,14 @@ struct RealisationJsonTest : RealisationTest, ::testing::WithParamInterface<std:
|
||||||
|
|
||||||
TEST_P(RealisationJsonTest, from_json)
|
TEST_P(RealisationJsonTest, from_json)
|
||||||
{
|
{
|
||||||
auto [name, expected] = GetParam();
|
const auto & [name, expected] = GetParam();
|
||||||
readTest(name + ".json", [&](const auto & encoded_) {
|
readJsonTest(name, expected);
|
||||||
auto encoded = json::parse(encoded_);
|
|
||||||
Realisation got = static_cast<Realisation>(encoded);
|
|
||||||
ASSERT_EQ(got, expected);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_P(RealisationJsonTest, to_json)
|
TEST_P(RealisationJsonTest, to_json)
|
||||||
{
|
{
|
||||||
auto [name, value] = GetParam();
|
const auto & [name, value] = GetParam();
|
||||||
writeTest(
|
writeJsonTest(name, value);
|
||||||
name + ".json",
|
|
||||||
[&]() -> json { return static_cast<json>(value); },
|
|
||||||
[](const auto & file) { return json::parse(readFile(file)); },
|
|
||||||
[](const auto & file, const auto & got) { return writeFile(file, got.dump(2) + "\n"); });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
INSTANTIATE_TEST_SUITE_P(
|
INSTANTIATE_TEST_SUITE_P(
|
||||||
|
|
|
||||||
|
|
@ -1257,14 +1257,18 @@ void Derivation::checkInvariants(Store & store, const StorePath & drvPath) const
|
||||||
|
|
||||||
const Hash impureOutputHash = hashString(HashAlgorithm::SHA256, "impure");
|
const Hash impureOutputHash = hashString(HashAlgorithm::SHA256, "impure");
|
||||||
|
|
||||||
nlohmann::json DerivationOutput::toJSON(std::string_view drvName, OutputNameView outputName) const
|
nlohmann::json DerivationOutput::toJSON() const
|
||||||
{
|
{
|
||||||
nlohmann::json res = nlohmann::json::object();
|
nlohmann::json res = nlohmann::json::object();
|
||||||
std::visit(
|
std::visit(
|
||||||
overloaded{
|
overloaded{
|
||||||
[&](const DerivationOutput::InputAddressed & doi) { res["path"] = doi.path; },
|
[&](const DerivationOutput::InputAddressed & doi) { res["path"] = doi.path; },
|
||||||
[&](const DerivationOutput::CAFixed & dof) {
|
[&](const DerivationOutput::CAFixed & dof) {
|
||||||
// res["path"] = dof.path(store, drvName, outputName);
|
/* it would be nice to output the path for user convenience, but
|
||||||
|
this would require us to know the store dir. */
|
||||||
|
#if 0
|
||||||
|
res["path"] = dof.path(store, drvName, outputName);
|
||||||
|
#endif
|
||||||
res["method"] = std::string{dof.ca.method.render()};
|
res["method"] = std::string{dof.ca.method.render()};
|
||||||
res["hashAlgo"] = printHashAlgo(dof.ca.hash.algo);
|
res["hashAlgo"] = printHashAlgo(dof.ca.hash.algo);
|
||||||
res["hash"] = dof.ca.hash.to_string(HashFormat::Base16, false);
|
res["hash"] = dof.ca.hash.to_string(HashFormat::Base16, false);
|
||||||
|
|
@ -1285,11 +1289,8 @@ nlohmann::json DerivationOutput::toJSON(std::string_view drvName, OutputNameView
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
DerivationOutput DerivationOutput::fromJSON(
|
DerivationOutput
|
||||||
std::string_view drvName,
|
DerivationOutput::fromJSON(const nlohmann::json & _json, const ExperimentalFeatureSettings & xpSettings)
|
||||||
OutputNameView outputName,
|
|
||||||
const nlohmann::json & _json,
|
|
||||||
const ExperimentalFeatureSettings & xpSettings)
|
|
||||||
{
|
{
|
||||||
std::set<std::string_view> keys;
|
std::set<std::string_view> keys;
|
||||||
auto & json = getObject(_json);
|
auto & json = getObject(_json);
|
||||||
|
|
@ -1321,6 +1322,8 @@ DerivationOutput DerivationOutput::fromJSON(
|
||||||
.hash = Hash::parseNonSRIUnprefixed(getString(valueAt(json, "hash")), hashAlgo),
|
.hash = Hash::parseNonSRIUnprefixed(getString(valueAt(json, "hash")), hashAlgo),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
/* We no longer produce this (denormalized) field (for the
|
||||||
|
reasons described above), so we don't need to check it. */
|
||||||
#if 0
|
#if 0
|
||||||
if (dof.path(store, drvName, outputName) != static_cast<StorePath>(valueAt(json, "path")))
|
if (dof.path(store, drvName, outputName) != static_cast<StorePath>(valueAt(json, "path")))
|
||||||
throw Error("Path doesn't match derivation output");
|
throw Error("Path doesn't match derivation output");
|
||||||
|
|
@ -1367,7 +1370,7 @@ nlohmann::json Derivation::toJSON() const
|
||||||
nlohmann::json & outputsObj = res["outputs"];
|
nlohmann::json & outputsObj = res["outputs"];
|
||||||
outputsObj = nlohmann::json::object();
|
outputsObj = nlohmann::json::object();
|
||||||
for (auto & [outputName, output] : outputs) {
|
for (auto & [outputName, output] : outputs) {
|
||||||
outputsObj[outputName] = output.toJSON(name, outputName);
|
outputsObj[outputName] = output;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1427,8 +1430,7 @@ Derivation Derivation::fromJSON(const nlohmann::json & _json, const Experimental
|
||||||
try {
|
try {
|
||||||
auto outputs = getObject(valueAt(json, "outputs"));
|
auto outputs = getObject(valueAt(json, "outputs"));
|
||||||
for (auto & [outputName, output] : outputs) {
|
for (auto & [outputName, output] : outputs) {
|
||||||
res.outputs.insert_or_assign(
|
res.outputs.insert_or_assign(outputName, DerivationOutput::fromJSON(output, xpSettings));
|
||||||
outputName, DerivationOutput::fromJSON(res.name, outputName, output, xpSettings));
|
|
||||||
}
|
}
|
||||||
} catch (Error & e) {
|
} catch (Error & e) {
|
||||||
e.addTrace({}, "while reading key 'outputs'");
|
e.addTrace({}, "while reading key 'outputs'");
|
||||||
|
|
@ -1489,6 +1491,16 @@ namespace nlohmann {
|
||||||
|
|
||||||
using namespace nix;
|
using namespace nix;
|
||||||
|
|
||||||
|
DerivationOutput adl_serializer<DerivationOutput>::from_json(const json & json)
|
||||||
|
{
|
||||||
|
return DerivationOutput::fromJSON(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
void adl_serializer<DerivationOutput>::to_json(json & json, const DerivationOutput & c)
|
||||||
|
{
|
||||||
|
json = c.toJSON();
|
||||||
|
}
|
||||||
|
|
||||||
Derivation adl_serializer<Derivation>::from_json(const json & json)
|
Derivation adl_serializer<Derivation>::from_json(const json & json)
|
||||||
{
|
{
|
||||||
return Derivation::fromJSON(json);
|
return Derivation::fromJSON(json);
|
||||||
|
|
|
||||||
|
|
@ -135,15 +135,12 @@ struct DerivationOutput
|
||||||
std::optional<StorePath>
|
std::optional<StorePath>
|
||||||
path(const StoreDirConfig & store, std::string_view drvName, OutputNameView outputName) const;
|
path(const StoreDirConfig & store, std::string_view drvName, OutputNameView outputName) const;
|
||||||
|
|
||||||
nlohmann::json toJSON(std::string_view drvName, OutputNameView outputName) const;
|
nlohmann::json toJSON() const;
|
||||||
/**
|
/**
|
||||||
* @param xpSettings Stop-gap to avoid globals during unit tests.
|
* @param xpSettings Stop-gap to avoid globals during unit tests.
|
||||||
*/
|
*/
|
||||||
static DerivationOutput fromJSON(
|
static DerivationOutput
|
||||||
std::string_view drvName,
|
fromJSON(const nlohmann::json & json, const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings);
|
||||||
OutputNameView outputName,
|
|
||||||
const nlohmann::json & json,
|
|
||||||
const ExperimentalFeatureSettings & xpSettings = experimentalFeatureSettings);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::map<std::string, DerivationOutput> DerivationOutputs;
|
typedef std::map<std::string, DerivationOutput> DerivationOutputs;
|
||||||
|
|
@ -540,4 +537,5 @@ std::string hashPlaceholder(const OutputNameView outputName);
|
||||||
|
|
||||||
} // namespace nix
|
} // namespace nix
|
||||||
|
|
||||||
|
JSON_IMPL(nix::DerivationOutput)
|
||||||
JSON_IMPL(nix::Derivation)
|
JSON_IMPL(nix::Derivation)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
#pragma once
|
||||||
|
///@file
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
#include "nix/util/types.hh"
|
||||||
|
#include "nix/util/file-system.hh"
|
||||||
|
|
||||||
|
#include "nix/util/tests/characterization.hh"
|
||||||
|
|
||||||
|
namespace nix {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mixin class for writing characterization tests for `nlohmann::json`
|
||||||
|
* conversions for a given type.
|
||||||
|
*/
|
||||||
|
template<typename T>
|
||||||
|
struct JsonCharacterizationTest : virtual CharacterizationTest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Golden test for reading
|
||||||
|
*
|
||||||
|
* @param test hook that takes the contents of the file and does the
|
||||||
|
* actual work
|
||||||
|
*/
|
||||||
|
void readJsonTest(PathView testStem, const T & expected)
|
||||||
|
{
|
||||||
|
using namespace nlohmann;
|
||||||
|
readTest(Path{testStem} + ".json", [&](const auto & encodedRaw) {
|
||||||
|
auto encoded = json::parse(encodedRaw);
|
||||||
|
T decoded = adl_serializer<T>::from_json(encoded);
|
||||||
|
ASSERT_EQ(decoded, expected);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Golden test for writing
|
||||||
|
*
|
||||||
|
* @param test hook that produces contents of the file and does the
|
||||||
|
* actual work
|
||||||
|
*/
|
||||||
|
void writeJsonTest(PathView testStem, const T & value)
|
||||||
|
{
|
||||||
|
using namespace nlohmann;
|
||||||
|
writeTest(
|
||||||
|
Path{testStem} + ".json",
|
||||||
|
[&]() -> json { return static_cast<json>(value); },
|
||||||
|
[](const auto & file) { return json::parse(readFile(file)); },
|
||||||
|
[](const auto & file, const auto & got) { return writeFile(file, got.dump(2) + "\n"); });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace nix
|
||||||
|
|
@ -7,6 +7,7 @@ headers = files(
|
||||||
'gmock-matchers.hh',
|
'gmock-matchers.hh',
|
||||||
'gtest-with-params.hh',
|
'gtest-with-params.hh',
|
||||||
'hash.hh',
|
'hash.hh',
|
||||||
|
'json-characterization.hh',
|
||||||
'nix_api_util.hh',
|
'nix_api_util.hh',
|
||||||
'string_callback.hh',
|
'string_callback.hh',
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -102,14 +102,14 @@ struct RandomPeekSort : public ::testing::TestWithParam<
|
||||||
|
|
||||||
void SetUp() override
|
void SetUp() override
|
||||||
{
|
{
|
||||||
auto [maxSize, min, max, iterations] = GetParam();
|
const auto & [maxSize, min, max, iterations] = GetParam();
|
||||||
urng_ = std::mt19937(GTEST_FLAG_GET(random_seed));
|
urng_ = std::mt19937(GTEST_FLAG_GET(random_seed));
|
||||||
distribution_ = std::uniform_int_distribution<int>(min, max);
|
distribution_ = std::uniform_int_distribution<int>(min, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto regenerate()
|
auto regenerate()
|
||||||
{
|
{
|
||||||
auto [maxSize, min, max, iterations] = GetParam();
|
const auto & [maxSize, min, max, iterations] = GetParam();
|
||||||
std::size_t dataSize = std::uniform_int_distribution<std::size_t>(0, maxSize)(urng_);
|
std::size_t dataSize = std::uniform_int_distribution<std::size_t>(0, maxSize)(urng_);
|
||||||
data_.resize(dataSize);
|
data_.resize(dataSize);
|
||||||
std::generate(data_.begin(), data_.end(), [&]() { return distribution_(urng_); });
|
std::generate(data_.begin(), data_.end(), [&]() { return distribution_(urng_); });
|
||||||
|
|
@ -118,7 +118,7 @@ struct RandomPeekSort : public ::testing::TestWithParam<
|
||||||
|
|
||||||
TEST_P(RandomPeekSort, defaultComparator)
|
TEST_P(RandomPeekSort, defaultComparator)
|
||||||
{
|
{
|
||||||
auto [maxSize, min, max, iterations] = GetParam();
|
const auto & [maxSize, min, max, iterations] = GetParam();
|
||||||
|
|
||||||
for (std::size_t i = 0; i < iterations; ++i) {
|
for (std::size_t i = 0; i < iterations; ++i) {
|
||||||
regenerate();
|
regenerate();
|
||||||
|
|
@ -132,7 +132,7 @@ TEST_P(RandomPeekSort, defaultComparator)
|
||||||
|
|
||||||
TEST_P(RandomPeekSort, greater)
|
TEST_P(RandomPeekSort, greater)
|
||||||
{
|
{
|
||||||
auto [maxSize, min, max, iterations] = GetParam();
|
const auto & [maxSize, min, max, iterations] = GetParam();
|
||||||
|
|
||||||
for (std::size_t i = 0; i < iterations; ++i) {
|
for (std::size_t i = 0; i < iterations; ++i) {
|
||||||
regenerate();
|
regenerate();
|
||||||
|
|
@ -146,7 +146,7 @@ TEST_P(RandomPeekSort, greater)
|
||||||
|
|
||||||
TEST_P(RandomPeekSort, brokenComparator)
|
TEST_P(RandomPeekSort, brokenComparator)
|
||||||
{
|
{
|
||||||
auto [maxSize, min, max, iterations] = GetParam();
|
const auto & [maxSize, min, max, iterations] = GetParam();
|
||||||
|
|
||||||
/* This is a pretty nice way of modeling a worst-case scenario for a broken comparator.
|
/* This is a pretty nice way of modeling a worst-case scenario for a broken comparator.
|
||||||
If the sorting algorithm doesn't break in such case, then surely all deterministic
|
If the sorting algorithm doesn't break in such case, then surely all deterministic
|
||||||
|
|
@ -170,7 +170,7 @@ TEST_P(RandomPeekSort, brokenComparator)
|
||||||
|
|
||||||
TEST_P(RandomPeekSort, stability)
|
TEST_P(RandomPeekSort, stability)
|
||||||
{
|
{
|
||||||
auto [maxSize, min, max, iterations] = GetParam();
|
const auto & [maxSize, min, max, iterations] = GetParam();
|
||||||
|
|
||||||
for (std::size_t i = 0; i < iterations; ++i) {
|
for (std::size_t i = 0; i < iterations; ++i) {
|
||||||
regenerate();
|
regenerate();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue