mirror of
https://github.com/NixOS/nix.git
synced 2025-11-15 23:12:44 +01:00
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>
This commit is contained in:
parent
77adb55ae4
commit
91b6833686
134 changed files with 464 additions and 352 deletions
|
|
@ -1,187 +0,0 @@
|
|||
#include <regex>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "common-protocol.hh"
|
||||
#include "common-protocol-impl.hh"
|
||||
#include "build-result.hh"
|
||||
#include "tests/protocol.hh"
|
||||
#include "tests/characterization.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
const char commonProtoDir[] = "common-protocol";
|
||||
|
||||
class CommonProtoTest : public ProtoTest<CommonProto, commonProtoDir>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Golden test for `T` reading
|
||||
*/
|
||||
template<typename T>
|
||||
void readProtoTest(PathView testStem, const T & expected)
|
||||
{
|
||||
CharacterizationTest::readTest(testStem, [&](const auto & encoded) {
|
||||
T got = ({
|
||||
StringSource from { encoded };
|
||||
CommonProto::Serialise<T>::read(
|
||||
*store,
|
||||
CommonProto::ReadConn { .from = from });
|
||||
});
|
||||
|
||||
ASSERT_EQ(got, expected);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Golden test for `T` write
|
||||
*/
|
||||
template<typename T>
|
||||
void writeProtoTest(PathView testStem, const T & decoded)
|
||||
{
|
||||
CharacterizationTest::writeTest(testStem, [&]() -> std::string {
|
||||
StringSink to;
|
||||
CommonProto::Serialise<T>::write(
|
||||
*store,
|
||||
CommonProto::WriteConn { .to = to },
|
||||
decoded);
|
||||
return to.s;
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
#define CHARACTERIZATION_TEST(NAME, STEM, VALUE) \
|
||||
TEST_F(CommonProtoTest, NAME ## _read) { \
|
||||
readProtoTest(STEM, VALUE); \
|
||||
} \
|
||||
TEST_F(CommonProtoTest, NAME ## _write) { \
|
||||
writeProtoTest(STEM, VALUE); \
|
||||
}
|
||||
|
||||
CHARACTERIZATION_TEST(
|
||||
string,
|
||||
"string",
|
||||
(std::tuple<std::string, std::string, std::string, std::string, std::string> {
|
||||
"",
|
||||
"hi",
|
||||
"white rabbit",
|
||||
"大白兔",
|
||||
"oh no \0\0\0 what was that!",
|
||||
}))
|
||||
|
||||
CHARACTERIZATION_TEST(
|
||||
storePath,
|
||||
"store-path",
|
||||
(std::tuple<StorePath, StorePath> {
|
||||
StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo" },
|
||||
StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo-bar" },
|
||||
}))
|
||||
|
||||
CHARACTERIZATION_TEST(
|
||||
contentAddress,
|
||||
"content-address",
|
||||
(std::tuple<ContentAddress, ContentAddress, ContentAddress> {
|
||||
ContentAddress {
|
||||
.method = TextIngestionMethod {},
|
||||
.hash = hashString(HashType::htSHA256, "Derive(...)"),
|
||||
},
|
||||
ContentAddress {
|
||||
.method = FileIngestionMethod::Flat,
|
||||
.hash = hashString(HashType::htSHA1, "blob blob..."),
|
||||
},
|
||||
ContentAddress {
|
||||
.method = FileIngestionMethod::Recursive,
|
||||
.hash = hashString(HashType::htSHA256, "(...)"),
|
||||
},
|
||||
}))
|
||||
|
||||
CHARACTERIZATION_TEST(
|
||||
drvOutput,
|
||||
"drv-output",
|
||||
(std::tuple<DrvOutput, DrvOutput> {
|
||||
{
|
||||
.drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="),
|
||||
.outputName = "baz",
|
||||
},
|
||||
DrvOutput {
|
||||
.drvHash = Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="),
|
||||
.outputName = "quux",
|
||||
},
|
||||
}))
|
||||
|
||||
CHARACTERIZATION_TEST(
|
||||
realisation,
|
||||
"realisation",
|
||||
(std::tuple<Realisation, Realisation> {
|
||||
Realisation {
|
||||
.id = DrvOutput {
|
||||
.drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="),
|
||||
.outputName = "baz",
|
||||
},
|
||||
.outPath = StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo" },
|
||||
.signatures = { "asdf", "qwer" },
|
||||
},
|
||||
Realisation {
|
||||
.id = {
|
||||
.drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="),
|
||||
.outputName = "baz",
|
||||
},
|
||||
.outPath = StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo" },
|
||||
.signatures = { "asdf", "qwer" },
|
||||
.dependentRealisations = {
|
||||
{
|
||||
DrvOutput {
|
||||
.drvHash = Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="),
|
||||
.outputName = "quux",
|
||||
},
|
||||
StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo" },
|
||||
},
|
||||
},
|
||||
},
|
||||
}))
|
||||
|
||||
CHARACTERIZATION_TEST(
|
||||
vector,
|
||||
"vector",
|
||||
(std::tuple<std::vector<std::string>, std::vector<std::string>, std::vector<std::string>, std::vector<std::vector<std::string>>> {
|
||||
{ },
|
||||
{ "" },
|
||||
{ "", "foo", "bar" },
|
||||
{ {}, { "" }, { "", "1", "2" } },
|
||||
}))
|
||||
|
||||
CHARACTERIZATION_TEST(
|
||||
set,
|
||||
"set",
|
||||
(std::tuple<std::set<std::string>, std::set<std::string>, std::set<std::string>, std::set<std::set<std::string>>> {
|
||||
{ },
|
||||
{ "" },
|
||||
{ "", "foo", "bar" },
|
||||
{ {}, { "" }, { "", "1", "2" } },
|
||||
}))
|
||||
|
||||
CHARACTERIZATION_TEST(
|
||||
optionalStorePath,
|
||||
"optional-store-path",
|
||||
(std::tuple<std::optional<StorePath>, std::optional<StorePath>> {
|
||||
std::nullopt,
|
||||
std::optional {
|
||||
StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo-bar" },
|
||||
},
|
||||
}))
|
||||
|
||||
CHARACTERIZATION_TEST(
|
||||
optionalContentAddress,
|
||||
"optional-content-address",
|
||||
(std::tuple<std::optional<ContentAddress>, std::optional<ContentAddress>> {
|
||||
std::nullopt,
|
||||
std::optional {
|
||||
ContentAddress {
|
||||
.method = FileIngestionMethod::Flat,
|
||||
.hash = hashString(HashType::htSHA1, "blob blob..."),
|
||||
},
|
||||
},
|
||||
}))
|
||||
|
||||
}
|
||||
|
|
@ -1,298 +0,0 @@
|
|||
#include <nlohmann/json.hpp>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "experimental-features.hh"
|
||||
#include "derivations.hh"
|
||||
|
||||
#include "tests/libstore.hh"
|
||||
#include "tests/characterization.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
using nlohmann::json;
|
||||
|
||||
class DerivationTest : public CharacterizationTest, public LibStoreTest
|
||||
{
|
||||
Path unitTestData = getUnitTestData() + "/libstore/derivation";
|
||||
|
||||
public:
|
||||
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 TEST_JSON(FIXTURE, NAME, VAL, DRV_NAME, OUTPUT_NAME) \
|
||||
TEST_F(FIXTURE, DerivationOutput_ ## NAME ## _from_json) { \
|
||||
readTest("output-" #NAME ".json", [&](const auto & encoded_) { \
|
||||
auto encoded = json::parse(encoded_); \
|
||||
DerivationOutput got = DerivationOutput::fromJSON( \
|
||||
*store, \
|
||||
DRV_NAME, \
|
||||
OUTPUT_NAME, \
|
||||
encoded, \
|
||||
mockXpSettings); \
|
||||
DerivationOutput expected { VAL }; \
|
||||
ASSERT_EQ(got, expected); \
|
||||
}); \
|
||||
} \
|
||||
\
|
||||
TEST_F(FIXTURE, DerivationOutput_ ## NAME ## _to_json) { \
|
||||
writeTest("output-" #NAME ".json", [&]() -> json { \
|
||||
return DerivationOutput { (VAL) }.toJSON( \
|
||||
*store, \
|
||||
(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(DerivationTest, inputAddressed,
|
||||
(DerivationOutput::InputAddressed {
|
||||
.path = store->parseStorePath("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-drv-name-output-name"),
|
||||
}),
|
||||
"drv-name", "output-name")
|
||||
|
||||
TEST_JSON(DerivationTest, caFixedFlat,
|
||||
(DerivationOutput::CAFixed {
|
||||
.ca = {
|
||||
.method = FileIngestionMethod::Flat,
|
||||
.hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="),
|
||||
},
|
||||
}),
|
||||
"drv-name", "output-name")
|
||||
|
||||
TEST_JSON(DerivationTest, caFixedNAR,
|
||||
(DerivationOutput::CAFixed {
|
||||
.ca = {
|
||||
.method = FileIngestionMethod::Recursive,
|
||||
.hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="),
|
||||
},
|
||||
}),
|
||||
"drv-name", "output-name")
|
||||
|
||||
TEST_JSON(DynDerivationTest, caFixedText,
|
||||
(DerivationOutput::CAFixed {
|
||||
.ca = {
|
||||
.hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="),
|
||||
},
|
||||
}),
|
||||
"drv-name", "output-name")
|
||||
|
||||
TEST_JSON(CaDerivationTest, caFloating,
|
||||
(DerivationOutput::CAFloating {
|
||||
.method = FileIngestionMethod::Recursive,
|
||||
.hashType = htSHA256,
|
||||
}),
|
||||
"drv-name", "output-name")
|
||||
|
||||
TEST_JSON(DerivationTest, deferred,
|
||||
DerivationOutput::Deferred { },
|
||||
"drv-name", "output-name")
|
||||
|
||||
TEST_JSON(ImpureDerivationTest, impure,
|
||||
(DerivationOutput::Impure {
|
||||
.method = FileIngestionMethod::Recursive,
|
||||
.hashType = htSHA256,
|
||||
}),
|
||||
"drv-name", "output-name")
|
||||
|
||||
#undef TEST_JSON
|
||||
|
||||
#define TEST_JSON(FIXTURE, NAME, VAL) \
|
||||
TEST_F(FIXTURE, Derivation_ ## NAME ## _from_json) { \
|
||||
readTest(#NAME ".json", [&](const auto & encoded_) { \
|
||||
auto encoded = json::parse(encoded_); \
|
||||
Derivation expected { VAL }; \
|
||||
Derivation got = Derivation::fromJSON( \
|
||||
*store, \
|
||||
encoded, \
|
||||
mockXpSettings); \
|
||||
ASSERT_EQ(got, expected); \
|
||||
}); \
|
||||
} \
|
||||
\
|
||||
TEST_F(FIXTURE, Derivation_ ## NAME ## _to_json) { \
|
||||
writeTest(#NAME ".json", [&]() -> json { \
|
||||
return Derivation { VAL }.toJSON(*store); \
|
||||
}, [](const auto & file) { \
|
||||
return json::parse(readFile(file)); \
|
||||
}, [](const auto & file, const auto & got) { \
|
||||
return writeFile(file, got.dump(2) + "\n"); \
|
||||
}); \
|
||||
}
|
||||
|
||||
#define TEST_ATERM(FIXTURE, NAME, VAL, DRV_NAME) \
|
||||
TEST_F(FIXTURE, Derivation_ ## NAME ## _from_aterm) { \
|
||||
readTest(#NAME ".drv", [&](auto encoded) { \
|
||||
Derivation expected { VAL }; \
|
||||
auto got = parseDerivation( \
|
||||
*store, \
|
||||
std::move(encoded), \
|
||||
DRV_NAME, \
|
||||
mockXpSettings); \
|
||||
ASSERT_EQ(got.toJSON(*store), expected.toJSON(*store)) ; \
|
||||
ASSERT_EQ(got, expected); \
|
||||
}); \
|
||||
} \
|
||||
\
|
||||
TEST_F(FIXTURE, Derivation_ ## NAME ## _to_aterm) { \
|
||||
writeTest(#NAME ".drv", [&]() -> std::string { \
|
||||
return (VAL).unparse(*store, false); \
|
||||
}); \
|
||||
}
|
||||
|
||||
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, makeSimpleDrv(*store))
|
||||
|
||||
TEST_ATERM(DerivationTest, simple,
|
||||
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, makeDynDepDerivation(*store))
|
||||
|
||||
TEST_ATERM(DynDerivationTest, dynDerivationDeps,
|
||||
makeDynDepDerivation(*store),
|
||||
"dyn-dep-derivation")
|
||||
|
||||
#undef TEST_JSON
|
||||
#undef TEST_ATERM
|
||||
|
||||
}
|
||||
|
|
@ -1,153 +0,0 @@
|
|||
#include <regex>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <gtest/gtest.h>
|
||||
#include <rapidcheck/gtest.h>
|
||||
|
||||
#include "tests/derived-path.hh"
|
||||
#include "tests/libstore.hh"
|
||||
|
||||
namespace rc {
|
||||
using namespace nix;
|
||||
|
||||
Gen<DerivedPath::Opaque> Arbitrary<DerivedPath::Opaque>::arbitrary()
|
||||
{
|
||||
return gen::just(DerivedPath::Opaque {
|
||||
.path = *gen::arbitrary<StorePath>(),
|
||||
});
|
||||
}
|
||||
|
||||
Gen<SingleDerivedPath::Built> Arbitrary<SingleDerivedPath::Built>::arbitrary()
|
||||
{
|
||||
return gen::just(SingleDerivedPath::Built {
|
||||
.drvPath = make_ref<SingleDerivedPath>(*gen::arbitrary<SingleDerivedPath>()),
|
||||
.output = (*gen::arbitrary<StorePathName>()).name,
|
||||
});
|
||||
}
|
||||
|
||||
Gen<DerivedPath::Built> Arbitrary<DerivedPath::Built>::arbitrary()
|
||||
{
|
||||
return gen::just(DerivedPath::Built {
|
||||
.drvPath = make_ref<SingleDerivedPath>(*gen::arbitrary<SingleDerivedPath>()),
|
||||
.outputs = *gen::arbitrary<OutputsSpec>(),
|
||||
});
|
||||
}
|
||||
|
||||
Gen<SingleDerivedPath> Arbitrary<SingleDerivedPath>::arbitrary()
|
||||
{
|
||||
switch (*gen::inRange<uint8_t>(0, std::variant_size_v<SingleDerivedPath::Raw>)) {
|
||||
case 0:
|
||||
return gen::just<SingleDerivedPath>(*gen::arbitrary<SingleDerivedPath::Opaque>());
|
||||
case 1:
|
||||
return gen::just<SingleDerivedPath>(*gen::arbitrary<SingleDerivedPath::Built>());
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
Gen<DerivedPath> Arbitrary<DerivedPath>::arbitrary()
|
||||
{
|
||||
switch (*gen::inRange<uint8_t>(0, std::variant_size_v<DerivedPath::Raw>)) {
|
||||
case 0:
|
||||
return gen::just<DerivedPath>(*gen::arbitrary<DerivedPath::Opaque>());
|
||||
case 1:
|
||||
return gen::just<DerivedPath>(*gen::arbitrary<DerivedPath::Built>());
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace nix {
|
||||
|
||||
class DerivedPathTest : public LibStoreTest
|
||||
{
|
||||
};
|
||||
|
||||
/**
|
||||
* Round trip (string <-> data structure) test for
|
||||
* `DerivedPath::Opaque`.
|
||||
*/
|
||||
TEST_F(DerivedPathTest, opaque) {
|
||||
std::string_view opaque = "/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x";
|
||||
auto elem = DerivedPath::parse(*store, opaque);
|
||||
auto * p = std::get_if<DerivedPath::Opaque>(&elem);
|
||||
ASSERT_TRUE(p);
|
||||
ASSERT_EQ(p->path, store->parseStorePath(opaque));
|
||||
ASSERT_EQ(elem.to_string(*store), opaque);
|
||||
}
|
||||
|
||||
/**
|
||||
* Round trip (string <-> data structure) test for a simpler
|
||||
* `DerivedPath::Built`.
|
||||
*/
|
||||
TEST_F(DerivedPathTest, built_opaque) {
|
||||
std::string_view built = "/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x.drv^bar,foo";
|
||||
auto elem = DerivedPath::parse(*store, built);
|
||||
auto * p = std::get_if<DerivedPath::Built>(&elem);
|
||||
ASSERT_TRUE(p);
|
||||
ASSERT_EQ(p->outputs, ((OutputsSpec) OutputsSpec::Names { "foo", "bar" }));
|
||||
ASSERT_EQ(*p->drvPath, ((SingleDerivedPath) SingleDerivedPath::Opaque {
|
||||
.path = store->parseStorePath(built.substr(0, 49)),
|
||||
}));
|
||||
ASSERT_EQ(elem.to_string(*store), built);
|
||||
}
|
||||
|
||||
/**
|
||||
* Round trip (string <-> data structure) test for a more complex,
|
||||
* inductive `DerivedPath::Built`.
|
||||
*/
|
||||
TEST_F(DerivedPathTest, built_built) {
|
||||
/**
|
||||
* 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;
|
||||
mockXpSettings.set("experimental-features", "dynamic-derivations ca-derivations");
|
||||
|
||||
std::string_view built = "/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x.drv^foo^bar,baz";
|
||||
auto elem = DerivedPath::parse(*store, built, mockXpSettings);
|
||||
auto * p = std::get_if<DerivedPath::Built>(&elem);
|
||||
ASSERT_TRUE(p);
|
||||
ASSERT_EQ(p->outputs, ((OutputsSpec) OutputsSpec::Names { "bar", "baz" }));
|
||||
auto * drvPath = std::get_if<SingleDerivedPath::Built>(&*p->drvPath);
|
||||
ASSERT_TRUE(drvPath);
|
||||
ASSERT_EQ(drvPath->output, "foo");
|
||||
ASSERT_EQ(*drvPath->drvPath, ((SingleDerivedPath) SingleDerivedPath::Opaque {
|
||||
.path = store->parseStorePath(built.substr(0, 49)),
|
||||
}));
|
||||
ASSERT_EQ(elem.to_string(*store), built);
|
||||
}
|
||||
|
||||
/**
|
||||
* Without the right experimental features enabled, we cannot parse a
|
||||
* complex inductive derived path.
|
||||
*/
|
||||
TEST_F(DerivedPathTest, built_built_xp) {
|
||||
ASSERT_THROW(
|
||||
DerivedPath::parse(*store, "/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-x.drv^foo^bar,baz"),
|
||||
MissingExperimentalFeature);
|
||||
}
|
||||
|
||||
#ifndef COVERAGE
|
||||
|
||||
RC_GTEST_FIXTURE_PROP(
|
||||
DerivedPathTest,
|
||||
prop_legacy_round_rip,
|
||||
(const DerivedPath & o))
|
||||
{
|
||||
RC_ASSERT(o == DerivedPath::parseLegacy(*store, o.to_string_legacy(*store)));
|
||||
}
|
||||
|
||||
RC_GTEST_FIXTURE_PROP(
|
||||
DerivedPathTest,
|
||||
prop_round_rip,
|
||||
(const DerivedPath & o))
|
||||
{
|
||||
RC_ASSERT(o == DerivedPath::parse(*store, o.to_string(*store)));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
#pragma once
|
||||
///@file
|
||||
|
||||
#include <rapidcheck/gen/Arbitrary.h>
|
||||
|
||||
#include <derived-path.hh>
|
||||
|
||||
#include "tests/path.hh"
|
||||
#include "tests/outputs-spec.hh"
|
||||
|
||||
namespace rc {
|
||||
using namespace nix;
|
||||
|
||||
template<>
|
||||
struct Arbitrary<SingleDerivedPath::Opaque> {
|
||||
static Gen<SingleDerivedPath::Opaque> arbitrary();
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Arbitrary<SingleDerivedPath::Built> {
|
||||
static Gen<SingleDerivedPath::Built> arbitrary();
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Arbitrary<SingleDerivedPath> {
|
||||
static Gen<SingleDerivedPath> arbitrary();
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Arbitrary<DerivedPath::Built> {
|
||||
static Gen<DerivedPath::Built> arbitrary();
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Arbitrary<DerivedPath> {
|
||||
static Gen<DerivedPath> arbitrary();
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
#include <gtest/gtest.h>
|
||||
|
||||
#include "downstream-placeholder.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
TEST(DownstreamPlaceholder, unknownCaOutput) {
|
||||
/**
|
||||
* 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;
|
||||
mockXpSettings.set("experimental-features", "ca-derivations");
|
||||
|
||||
ASSERT_EQ(
|
||||
DownstreamPlaceholder::unknownCaOutput(
|
||||
StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo.drv" },
|
||||
"out",
|
||||
mockXpSettings).render(),
|
||||
"/0c6rn30q4frawknapgwq386zq358m8r6msvywcvc89n6m5p2dgbz");
|
||||
}
|
||||
|
||||
TEST(DownstreamPlaceholder, unknownDerivation) {
|
||||
/**
|
||||
* Same reason as above
|
||||
*/
|
||||
ExperimentalFeatureSettings mockXpSettings;
|
||||
mockXpSettings.set("experimental-features", "dynamic-derivations ca-derivations");
|
||||
|
||||
ASSERT_EQ(
|
||||
DownstreamPlaceholder::unknownDerivation(
|
||||
DownstreamPlaceholder::unknownCaOutput(
|
||||
StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo.drv.drv" },
|
||||
"out",
|
||||
mockXpSettings),
|
||||
"out",
|
||||
mockXpSettings).render(),
|
||||
"/0gn6agqxjyyalf0dpihgyf49xq5hqxgw100f0wydnj6yqrhqsb3w");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,26 +0,0 @@
|
|||
#pragma once
|
||||
///@file
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
#include "store-api.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
class LibStoreTest : public virtual ::testing::Test {
|
||||
public:
|
||||
static void SetUpTestSuite() {
|
||||
initLibStore();
|
||||
}
|
||||
|
||||
protected:
|
||||
LibStoreTest()
|
||||
: store(openStore("dummy://"))
|
||||
{ }
|
||||
|
||||
ref<Store> store;
|
||||
};
|
||||
|
||||
|
||||
} /* namespace nix */
|
||||
|
|
@ -1,37 +0,0 @@
|
|||
check: libstore-tests-exe_RUN
|
||||
|
||||
programs += libstore-tests-exe
|
||||
|
||||
libstore-tests-exe_NAME = libnixstore-tests
|
||||
|
||||
libstore-tests-exe_DIR := $(d)
|
||||
|
||||
ifeq ($(INSTALL_UNIT_TESTS), yes)
|
||||
libstore-tests-exe_INSTALL_DIR := $(checkbindir)
|
||||
else
|
||||
libstore-tests-exe_INSTALL_DIR :=
|
||||
endif
|
||||
|
||||
libstore-tests-exe_LIBS = libstore-tests
|
||||
|
||||
libstore-tests-exe_LDFLAGS := $(GTEST_LIBS)
|
||||
|
||||
libraries += libstore-tests
|
||||
|
||||
libstore-tests_NAME = libnixstore-tests
|
||||
|
||||
libstore-tests_DIR := $(d)
|
||||
|
||||
ifeq ($(INSTALL_UNIT_TESTS), yes)
|
||||
libstore-tests_INSTALL_DIR := $(checklibdir)
|
||||
else
|
||||
libstore-tests_INSTALL_DIR :=
|
||||
endif
|
||||
|
||||
libstore-tests_SOURCES := $(wildcard $(d)/*.cc)
|
||||
|
||||
libstore-tests_CXXFLAGS += -I src/libstore -I src/libutil
|
||||
|
||||
libstore-tests_LIBS = libutil-tests libstore libutil
|
||||
|
||||
libstore-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS)
|
||||
|
|
@ -1,171 +0,0 @@
|
|||
#include "machines.hh"
|
||||
#include "globals.hh"
|
||||
#include "file-system.hh"
|
||||
#include "util.hh"
|
||||
|
||||
#include <gmock/gmock-matchers.h>
|
||||
|
||||
using testing::Contains;
|
||||
using testing::ElementsAre;
|
||||
using testing::EndsWith;
|
||||
using testing::Eq;
|
||||
using testing::Field;
|
||||
using testing::SizeIs;
|
||||
|
||||
using nix::absPath;
|
||||
using nix::FormatError;
|
||||
using nix::getMachines;
|
||||
using nix::Machine;
|
||||
using nix::Machines;
|
||||
using nix::pathExists;
|
||||
using nix::Settings;
|
||||
using nix::settings;
|
||||
|
||||
class Environment : public ::testing::Environment {
|
||||
public:
|
||||
void SetUp() override { settings.thisSystem = "TEST_ARCH-TEST_OS"; }
|
||||
};
|
||||
|
||||
testing::Environment* const foo_env =
|
||||
testing::AddGlobalTestEnvironment(new Environment);
|
||||
|
||||
TEST(machines, getMachinesWithEmptyBuilders) {
|
||||
settings.builders = "";
|
||||
Machines actual = getMachines();
|
||||
ASSERT_THAT(actual, SizeIs(0));
|
||||
}
|
||||
|
||||
TEST(machines, getMachinesUriOnly) {
|
||||
settings.builders = "nix@scratchy.labs.cs.uu.nl";
|
||||
Machines actual = getMachines();
|
||||
ASSERT_THAT(actual, SizeIs(1));
|
||||
EXPECT_THAT(actual[0], Field(&Machine::storeUri, Eq("ssh://nix@scratchy.labs.cs.uu.nl")));
|
||||
EXPECT_THAT(actual[0], Field(&Machine::systemTypes, ElementsAre("TEST_ARCH-TEST_OS")));
|
||||
EXPECT_THAT(actual[0], Field(&Machine::sshKey, SizeIs(0)));
|
||||
EXPECT_THAT(actual[0], Field(&Machine::maxJobs, Eq(1)));
|
||||
EXPECT_THAT(actual[0], Field(&Machine::speedFactor, Eq(1)));
|
||||
EXPECT_THAT(actual[0], Field(&Machine::supportedFeatures, SizeIs(0)));
|
||||
EXPECT_THAT(actual[0], Field(&Machine::mandatoryFeatures, SizeIs(0)));
|
||||
EXPECT_THAT(actual[0], Field(&Machine::sshPublicHostKey, SizeIs(0)));
|
||||
}
|
||||
|
||||
TEST(machines, getMachinesDefaults) {
|
||||
settings.builders = "nix@scratchy.labs.cs.uu.nl - - - - - - -";
|
||||
Machines actual = getMachines();
|
||||
ASSERT_THAT(actual, SizeIs(1));
|
||||
EXPECT_THAT(actual[0], Field(&Machine::storeUri, Eq("ssh://nix@scratchy.labs.cs.uu.nl")));
|
||||
EXPECT_THAT(actual[0], Field(&Machine::systemTypes, ElementsAre("TEST_ARCH-TEST_OS")));
|
||||
EXPECT_THAT(actual[0], Field(&Machine::sshKey, SizeIs(0)));
|
||||
EXPECT_THAT(actual[0], Field(&Machine::maxJobs, Eq(1)));
|
||||
EXPECT_THAT(actual[0], Field(&Machine::speedFactor, Eq(1)));
|
||||
EXPECT_THAT(actual[0], Field(&Machine::supportedFeatures, SizeIs(0)));
|
||||
EXPECT_THAT(actual[0], Field(&Machine::mandatoryFeatures, SizeIs(0)));
|
||||
EXPECT_THAT(actual[0], Field(&Machine::sshPublicHostKey, SizeIs(0)));
|
||||
}
|
||||
|
||||
TEST(machines, getMachinesWithNewLineSeparator) {
|
||||
settings.builders = "nix@scratchy.labs.cs.uu.nl\nnix@itchy.labs.cs.uu.nl";
|
||||
Machines actual = getMachines();
|
||||
ASSERT_THAT(actual, SizeIs(2));
|
||||
EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, EndsWith("nix@scratchy.labs.cs.uu.nl"))));
|
||||
EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, EndsWith("nix@itchy.labs.cs.uu.nl"))));
|
||||
}
|
||||
|
||||
TEST(machines, getMachinesWithSemicolonSeparator) {
|
||||
settings.builders = "nix@scratchy.labs.cs.uu.nl ; nix@itchy.labs.cs.uu.nl";
|
||||
Machines actual = getMachines();
|
||||
EXPECT_THAT(actual, SizeIs(2));
|
||||
EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, EndsWith("nix@scratchy.labs.cs.uu.nl"))));
|
||||
EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, EndsWith("nix@itchy.labs.cs.uu.nl"))));
|
||||
}
|
||||
|
||||
TEST(machines, getMachinesWithCorrectCompleteSingleBuilder) {
|
||||
settings.builders = "nix@scratchy.labs.cs.uu.nl i686-linux "
|
||||
"/home/nix/.ssh/id_scratchy_auto 8 3 kvm "
|
||||
"benchmark SSH+HOST+PUBLIC+KEY+BASE64+ENCODED==";
|
||||
Machines actual = getMachines();
|
||||
ASSERT_THAT(actual, SizeIs(1));
|
||||
EXPECT_THAT(actual[0], Field(&Machine::storeUri, EndsWith("nix@scratchy.labs.cs.uu.nl")));
|
||||
EXPECT_THAT(actual[0], Field(&Machine::systemTypes, ElementsAre("i686-linux")));
|
||||
EXPECT_THAT(actual[0], Field(&Machine::sshKey, Eq("/home/nix/.ssh/id_scratchy_auto")));
|
||||
EXPECT_THAT(actual[0], Field(&Machine::maxJobs, Eq(8)));
|
||||
EXPECT_THAT(actual[0], Field(&Machine::speedFactor, Eq(3)));
|
||||
EXPECT_THAT(actual[0], Field(&Machine::supportedFeatures, ElementsAre("kvm")));
|
||||
EXPECT_THAT(actual[0], Field(&Machine::mandatoryFeatures, ElementsAre("benchmark")));
|
||||
EXPECT_THAT(actual[0], Field(&Machine::sshPublicHostKey, Eq("SSH+HOST+PUBLIC+KEY+BASE64+ENCODED==")));
|
||||
}
|
||||
|
||||
TEST(machines,
|
||||
getMachinesWithCorrectCompleteSingleBuilderWithTabColumnDelimiter) {
|
||||
settings.builders =
|
||||
"nix@scratchy.labs.cs.uu.nl\ti686-linux\t/home/nix/.ssh/"
|
||||
"id_scratchy_auto\t8\t3\tkvm\tbenchmark\tSSH+HOST+PUBLIC+"
|
||||
"KEY+BASE64+ENCODED==";
|
||||
Machines actual = getMachines();
|
||||
ASSERT_THAT(actual, SizeIs(1));
|
||||
EXPECT_THAT(actual[0], Field(&Machine::storeUri, EndsWith("nix@scratchy.labs.cs.uu.nl")));
|
||||
EXPECT_THAT(actual[0], Field(&Machine::systemTypes, ElementsAre("i686-linux")));
|
||||
EXPECT_THAT(actual[0], Field(&Machine::sshKey, Eq("/home/nix/.ssh/id_scratchy_auto")));
|
||||
EXPECT_THAT(actual[0], Field(&Machine::maxJobs, Eq(8)));
|
||||
EXPECT_THAT(actual[0], Field(&Machine::speedFactor, Eq(3)));
|
||||
EXPECT_THAT(actual[0], Field(&Machine::supportedFeatures, ElementsAre("kvm")));
|
||||
EXPECT_THAT(actual[0], Field(&Machine::mandatoryFeatures, ElementsAre("benchmark")));
|
||||
EXPECT_THAT(actual[0], Field(&Machine::sshPublicHostKey, Eq("SSH+HOST+PUBLIC+KEY+BASE64+ENCODED==")));
|
||||
}
|
||||
|
||||
TEST(machines, getMachinesWithMultiOptions) {
|
||||
settings.builders = "nix@scratchy.labs.cs.uu.nl Arch1,Arch2 - - - "
|
||||
"SupportedFeature1,SupportedFeature2 "
|
||||
"MandatoryFeature1,MandatoryFeature2";
|
||||
Machines actual = getMachines();
|
||||
ASSERT_THAT(actual, SizeIs(1));
|
||||
EXPECT_THAT(actual[0], Field(&Machine::storeUri, EndsWith("nix@scratchy.labs.cs.uu.nl")));
|
||||
EXPECT_THAT(actual[0], Field(&Machine::systemTypes, ElementsAre("Arch1", "Arch2")));
|
||||
EXPECT_THAT(actual[0], Field(&Machine::supportedFeatures, ElementsAre("SupportedFeature1", "SupportedFeature2")));
|
||||
EXPECT_THAT(actual[0], Field(&Machine::mandatoryFeatures, ElementsAre("MandatoryFeature1", "MandatoryFeature2")));
|
||||
}
|
||||
|
||||
TEST(machines, getMachinesWithIncorrectFormat) {
|
||||
settings.builders = "nix@scratchy.labs.cs.uu.nl - - eight";
|
||||
EXPECT_THROW(getMachines(), FormatError);
|
||||
settings.builders = "nix@scratchy.labs.cs.uu.nl - - -1";
|
||||
EXPECT_THROW(getMachines(), FormatError);
|
||||
settings.builders = "nix@scratchy.labs.cs.uu.nl - - 8 three";
|
||||
EXPECT_THROW(getMachines(), FormatError);
|
||||
settings.builders = "nix@scratchy.labs.cs.uu.nl - - 8 -3";
|
||||
EXPECT_THROW(getMachines(), FormatError);
|
||||
settings.builders = "nix@scratchy.labs.cs.uu.nl - - 8 3 - - BAD_BASE64";
|
||||
EXPECT_THROW(getMachines(), FormatError);
|
||||
}
|
||||
|
||||
TEST(machines, getMachinesWithCorrectFileReference) {
|
||||
auto path = absPath("src/libstore/tests/test-data/machines.valid");
|
||||
ASSERT_TRUE(pathExists(path));
|
||||
|
||||
settings.builders = std::string("@") + path;
|
||||
Machines actual = getMachines();
|
||||
ASSERT_THAT(actual, SizeIs(3));
|
||||
EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, EndsWith("nix@scratchy.labs.cs.uu.nl"))));
|
||||
EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, EndsWith("nix@itchy.labs.cs.uu.nl"))));
|
||||
EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, EndsWith("nix@poochie.labs.cs.uu.nl"))));
|
||||
}
|
||||
|
||||
TEST(machines, getMachinesWithCorrectFileReferenceToEmptyFile) {
|
||||
auto path = "/dev/null";
|
||||
ASSERT_TRUE(pathExists(path));
|
||||
|
||||
settings.builders = std::string("@") + path;
|
||||
Machines actual = getMachines();
|
||||
ASSERT_THAT(actual, SizeIs(0));
|
||||
}
|
||||
|
||||
TEST(machines, getMachinesWithIncorrectFileReference) {
|
||||
settings.builders = std::string("@") + absPath("/not/a/file");
|
||||
Machines actual = getMachines();
|
||||
ASSERT_THAT(actual, SizeIs(0));
|
||||
}
|
||||
|
||||
TEST(machines, getMachinesWithCorrectFileReferenceToIncorrectFile) {
|
||||
settings.builders = std::string("@") + absPath("src/libstore/tests/test-data/machines.bad_format");
|
||||
EXPECT_THROW(getMachines(), FormatError);
|
||||
}
|
||||
|
|
@ -1,123 +0,0 @@
|
|||
#include "nar-info-disk-cache.hh"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <rapidcheck/gtest.h>
|
||||
#include "sqlite.hh"
|
||||
#include <sqlite3.h>
|
||||
|
||||
|
||||
namespace nix {
|
||||
|
||||
TEST(NarInfoDiskCacheImpl, create_and_read) {
|
||||
// This is a large single test to avoid some setup overhead.
|
||||
|
||||
int prio = 12345;
|
||||
bool wantMassQuery = true;
|
||||
|
||||
Path tmpDir = createTempDir();
|
||||
AutoDelete delTmpDir(tmpDir);
|
||||
Path dbPath(tmpDir + "/test-narinfo-disk-cache.sqlite");
|
||||
|
||||
int savedId;
|
||||
int barId;
|
||||
SQLite db;
|
||||
SQLiteStmt getIds;
|
||||
|
||||
{
|
||||
auto cache = getTestNarInfoDiskCache(dbPath);
|
||||
|
||||
// Set up "background noise" and check that different caches receive different ids
|
||||
{
|
||||
auto bc1 = cache->createCache("https://bar", "/nix/storedir", wantMassQuery, prio);
|
||||
auto bc2 = cache->createCache("https://xyz", "/nix/storedir", false, 12);
|
||||
ASSERT_NE(bc1, bc2);
|
||||
barId = bc1;
|
||||
}
|
||||
|
||||
// Check that the fields are saved and returned correctly. This does not test
|
||||
// the select statement yet, because of in-memory caching.
|
||||
savedId = cache->createCache("http://foo", "/nix/storedir", wantMassQuery, prio);;
|
||||
{
|
||||
auto r = cache->upToDateCacheExists("http://foo");
|
||||
ASSERT_TRUE(r);
|
||||
ASSERT_EQ(r->priority, prio);
|
||||
ASSERT_EQ(r->wantMassQuery, wantMassQuery);
|
||||
ASSERT_EQ(savedId, r->id);
|
||||
}
|
||||
|
||||
// We're going to pay special attention to the id field because we had a bug
|
||||
// that changed it.
|
||||
db = SQLite(dbPath);
|
||||
getIds.create(db, "select id from BinaryCaches where url = 'http://foo'");
|
||||
|
||||
{
|
||||
auto q(getIds.use());
|
||||
ASSERT_TRUE(q.next());
|
||||
ASSERT_EQ(savedId, q.getInt(0));
|
||||
ASSERT_FALSE(q.next());
|
||||
}
|
||||
|
||||
// Pretend that the caches are older, but keep one up to date, as "background noise"
|
||||
db.exec("update BinaryCaches set timestamp = timestamp - 1 - 7 * 24 * 3600 where url <> 'https://xyz';");
|
||||
|
||||
// This shows that the in-memory cache works
|
||||
{
|
||||
auto r = cache->upToDateCacheExists("http://foo");
|
||||
ASSERT_TRUE(r);
|
||||
ASSERT_EQ(r->priority, prio);
|
||||
ASSERT_EQ(r->wantMassQuery, wantMassQuery);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
// We can't clear the in-memory cache, so we use a new cache object. This is
|
||||
// more realistic anyway.
|
||||
auto cache2 = getTestNarInfoDiskCache(dbPath);
|
||||
|
||||
{
|
||||
auto r = cache2->upToDateCacheExists("http://foo");
|
||||
ASSERT_FALSE(r);
|
||||
}
|
||||
|
||||
// "Update", same data, check that the id number is reused
|
||||
cache2->createCache("http://foo", "/nix/storedir", wantMassQuery, prio);
|
||||
|
||||
{
|
||||
auto r = cache2->upToDateCacheExists("http://foo");
|
||||
ASSERT_TRUE(r);
|
||||
ASSERT_EQ(r->priority, prio);
|
||||
ASSERT_EQ(r->wantMassQuery, wantMassQuery);
|
||||
ASSERT_EQ(r->id, savedId);
|
||||
}
|
||||
|
||||
{
|
||||
auto q(getIds.use());
|
||||
ASSERT_TRUE(q.next());
|
||||
auto currentId = q.getInt(0);
|
||||
ASSERT_FALSE(q.next());
|
||||
ASSERT_EQ(currentId, savedId);
|
||||
}
|
||||
|
||||
// Check that the fields can be modified, and the id remains the same
|
||||
{
|
||||
auto r0 = cache2->upToDateCacheExists("https://bar");
|
||||
ASSERT_FALSE(r0);
|
||||
|
||||
cache2->createCache("https://bar", "/nix/storedir", !wantMassQuery, prio + 10);
|
||||
auto r = cache2->upToDateCacheExists("https://bar");
|
||||
ASSERT_EQ(r->wantMassQuery, !wantMassQuery);
|
||||
ASSERT_EQ(r->priority, prio + 10);
|
||||
ASSERT_EQ(r->id, barId);
|
||||
}
|
||||
|
||||
// // Force update (no use case yet; we only retrieve cache metadata when stale based on timestamp)
|
||||
// {
|
||||
// cache2->createCache("https://bar", "/nix/storedir", wantMassQuery, prio + 20);
|
||||
// auto r = cache2->upToDateCacheExists("https://bar");
|
||||
// ASSERT_EQ(r->wantMassQuery, wantMassQuery);
|
||||
// ASSERT_EQ(r->priority, prio + 20);
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,86 +0,0 @@
|
|||
#include <nlohmann/json.hpp>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "path-info.hh"
|
||||
#include "nar-info.hh"
|
||||
|
||||
#include "tests/characterization.hh"
|
||||
#include "tests/libstore.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
using nlohmann::json;
|
||||
|
||||
class NarInfoTest : public CharacterizationTest, public LibStoreTest
|
||||
{
|
||||
Path unitTestData = getUnitTestData() + "/libstore/nar-info";
|
||||
|
||||
Path goldenMaster(PathView testStem) const override {
|
||||
return unitTestData + "/" + testStem + ".json";
|
||||
}
|
||||
};
|
||||
|
||||
static NarInfo makeNarInfo(const Store & store, bool includeImpureInfo) {
|
||||
NarInfo info = ValidPathInfo {
|
||||
store,
|
||||
"foo",
|
||||
FixedOutputInfo {
|
||||
.method = FileIngestionMethod::Recursive,
|
||||
.hash = hashString(HashType::htSHA256, "(...)"),
|
||||
|
||||
.references = {
|
||||
.others = {
|
||||
StorePath {
|
||||
"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar",
|
||||
},
|
||||
},
|
||||
.self = true,
|
||||
},
|
||||
},
|
||||
Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="),
|
||||
};
|
||||
info.narSize = 34878;
|
||||
if (includeImpureInfo) {
|
||||
info.deriver = StorePath {
|
||||
"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv",
|
||||
};
|
||||
info.registrationTime = 23423;
|
||||
info.ultimate = true;
|
||||
info.sigs = { "asdf", "qwer" };
|
||||
|
||||
info.url = "nar/1w1fff338fvdw53sqgamddn1b2xgds473pv6y13gizdbqjv4i5p3.nar.xz";
|
||||
info.compression = "xz";
|
||||
info.fileHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=");
|
||||
info.fileSize = 4029176;
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
#define JSON_TEST(STEM, PURE) \
|
||||
TEST_F(NarInfoTest, NarInfo_ ## STEM ## _from_json) { \
|
||||
readTest(#STEM, [&](const auto & encoded_) { \
|
||||
auto encoded = json::parse(encoded_); \
|
||||
auto expected = makeNarInfo(*store, PURE); \
|
||||
NarInfo got = NarInfo::fromJSON( \
|
||||
*store, \
|
||||
expected.path, \
|
||||
encoded); \
|
||||
ASSERT_EQ(got, expected); \
|
||||
}); \
|
||||
} \
|
||||
\
|
||||
TEST_F(NarInfoTest, NarInfo_ ## STEM ## _to_json) { \
|
||||
writeTest(#STEM, [&]() -> json { \
|
||||
return makeNarInfo(*store, PURE) \
|
||||
.toJSON(*store, PURE, HashFormat::SRI); \
|
||||
}, [](const auto & file) { \
|
||||
return json::parse(readFile(file)); \
|
||||
}, [](const auto & file, const auto & got) { \
|
||||
return writeFile(file, got.dump(2) + "\n"); \
|
||||
}); \
|
||||
}
|
||||
|
||||
JSON_TEST(pure, false)
|
||||
JSON_TEST(impure, true)
|
||||
|
||||
}
|
||||
|
|
@ -1,239 +0,0 @@
|
|||
#include "outputs-spec.hh"
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <gtest/gtest.h>
|
||||
#include <rapidcheck/gtest.h>
|
||||
|
||||
namespace nix {
|
||||
|
||||
#ifndef NDEBUG
|
||||
TEST(OutputsSpec, no_empty_names) {
|
||||
ASSERT_DEATH(OutputsSpec::Names { std::set<std::string> { } }, "");
|
||||
}
|
||||
#endif
|
||||
|
||||
#define TEST_DONT_PARSE(NAME, STR) \
|
||||
TEST(OutputsSpec, bad_ ## NAME) { \
|
||||
std::optional OutputsSpecOpt = \
|
||||
OutputsSpec::parseOpt(STR); \
|
||||
ASSERT_FALSE(OutputsSpecOpt); \
|
||||
}
|
||||
|
||||
TEST_DONT_PARSE(empty, "")
|
||||
TEST_DONT_PARSE(garbage, "&*()")
|
||||
TEST_DONT_PARSE(double_star, "**")
|
||||
TEST_DONT_PARSE(star_first, "*,foo")
|
||||
TEST_DONT_PARSE(star_second, "foo,*")
|
||||
|
||||
#undef TEST_DONT_PARSE
|
||||
|
||||
TEST(OutputsSpec, all) {
|
||||
std::string_view str = "*";
|
||||
OutputsSpec expected = OutputsSpec::All { };
|
||||
ASSERT_EQ(OutputsSpec::parse(str), expected);
|
||||
ASSERT_EQ(expected.to_string(), str);
|
||||
}
|
||||
|
||||
TEST(OutputsSpec, names_out) {
|
||||
std::string_view str = "out";
|
||||
OutputsSpec expected = OutputsSpec::Names { "out" };
|
||||
ASSERT_EQ(OutputsSpec::parse(str), expected);
|
||||
ASSERT_EQ(expected.to_string(), str);
|
||||
}
|
||||
|
||||
TEST(OutputsSpec, names_underscore) {
|
||||
std::string_view str = "a_b";
|
||||
OutputsSpec expected = OutputsSpec::Names { "a_b" };
|
||||
ASSERT_EQ(OutputsSpec::parse(str), expected);
|
||||
ASSERT_EQ(expected.to_string(), str);
|
||||
}
|
||||
|
||||
TEST(OutputsSpec, names_numberic) {
|
||||
std::string_view str = "01";
|
||||
OutputsSpec expected = OutputsSpec::Names { "01" };
|
||||
ASSERT_EQ(OutputsSpec::parse(str), expected);
|
||||
ASSERT_EQ(expected.to_string(), str);
|
||||
}
|
||||
|
||||
TEST(OutputsSpec, names_out_bin) {
|
||||
OutputsSpec expected = OutputsSpec::Names { "out", "bin" };
|
||||
ASSERT_EQ(OutputsSpec::parse("out,bin"), expected);
|
||||
// N.B. This normalization is OK.
|
||||
ASSERT_EQ(expected.to_string(), "bin,out");
|
||||
}
|
||||
|
||||
#define TEST_SUBSET(X, THIS, THAT) \
|
||||
X((OutputsSpec { THIS }).isSubsetOf(THAT));
|
||||
|
||||
TEST(OutputsSpec, subsets_all_all) {
|
||||
TEST_SUBSET(ASSERT_TRUE, OutputsSpec::All { }, OutputsSpec::All { });
|
||||
}
|
||||
|
||||
TEST(OutputsSpec, subsets_names_all) {
|
||||
TEST_SUBSET(ASSERT_TRUE, OutputsSpec::Names { "a" }, OutputsSpec::All { });
|
||||
}
|
||||
|
||||
TEST(OutputsSpec, subsets_names_names_eq) {
|
||||
TEST_SUBSET(ASSERT_TRUE, OutputsSpec::Names { "a" }, OutputsSpec::Names { "a" });
|
||||
}
|
||||
|
||||
TEST(OutputsSpec, subsets_names_names_noneq) {
|
||||
TEST_SUBSET(ASSERT_TRUE, OutputsSpec::Names { "a" }, (OutputsSpec::Names { "a", "b" }));
|
||||
}
|
||||
|
||||
TEST(OutputsSpec, not_subsets_all_names) {
|
||||
TEST_SUBSET(ASSERT_FALSE, OutputsSpec::All { }, OutputsSpec::Names { "a" });
|
||||
}
|
||||
|
||||
TEST(OutputsSpec, not_subsets_names_names) {
|
||||
TEST_SUBSET(ASSERT_FALSE, (OutputsSpec::Names { "a", "b" }), (OutputsSpec::Names { "a" }));
|
||||
}
|
||||
|
||||
#undef TEST_SUBSET
|
||||
|
||||
#define TEST_UNION(RES, THIS, THAT) \
|
||||
ASSERT_EQ(OutputsSpec { RES }, (OutputsSpec { THIS }).union_(THAT));
|
||||
|
||||
TEST(OutputsSpec, union_all_all) {
|
||||
TEST_UNION(OutputsSpec::All { }, OutputsSpec::All { }, OutputsSpec::All { });
|
||||
}
|
||||
|
||||
TEST(OutputsSpec, union_all_names) {
|
||||
TEST_UNION(OutputsSpec::All { }, OutputsSpec::All { }, OutputsSpec::Names { "a" });
|
||||
}
|
||||
|
||||
TEST(OutputsSpec, union_names_all) {
|
||||
TEST_UNION(OutputsSpec::All { }, OutputsSpec::Names { "a" }, OutputsSpec::All { });
|
||||
}
|
||||
|
||||
TEST(OutputsSpec, union_names_names) {
|
||||
TEST_UNION((OutputsSpec::Names { "a", "b" }), OutputsSpec::Names { "a" }, OutputsSpec::Names { "b" });
|
||||
}
|
||||
|
||||
#undef TEST_UNION
|
||||
|
||||
#define TEST_DONT_PARSE(NAME, STR) \
|
||||
TEST(ExtendedOutputsSpec, bad_ ## NAME) { \
|
||||
std::optional extendedOutputsSpecOpt = \
|
||||
ExtendedOutputsSpec::parseOpt(STR); \
|
||||
ASSERT_FALSE(extendedOutputsSpecOpt); \
|
||||
}
|
||||
|
||||
TEST_DONT_PARSE(carot_empty, "^")
|
||||
TEST_DONT_PARSE(prefix_carot_empty, "foo^")
|
||||
TEST_DONT_PARSE(garbage, "^&*()")
|
||||
TEST_DONT_PARSE(double_star, "^**")
|
||||
TEST_DONT_PARSE(star_first, "^*,foo")
|
||||
TEST_DONT_PARSE(star_second, "^foo,*")
|
||||
|
||||
#undef TEST_DONT_PARSE
|
||||
|
||||
TEST(ExtendedOutputsSpec, defeault) {
|
||||
std::string_view str = "foo";
|
||||
auto [prefix, extendedOutputsSpec] = ExtendedOutputsSpec::parse(str);
|
||||
ASSERT_EQ(prefix, "foo");
|
||||
ExtendedOutputsSpec expected = ExtendedOutputsSpec::Default { };
|
||||
ASSERT_EQ(extendedOutputsSpec, expected);
|
||||
ASSERT_EQ(std::string { prefix } + expected.to_string(), str);
|
||||
}
|
||||
|
||||
TEST(ExtendedOutputsSpec, all) {
|
||||
std::string_view str = "foo^*";
|
||||
auto [prefix, extendedOutputsSpec] = ExtendedOutputsSpec::parse(str);
|
||||
ASSERT_EQ(prefix, "foo");
|
||||
ExtendedOutputsSpec expected = OutputsSpec::All { };
|
||||
ASSERT_EQ(extendedOutputsSpec, expected);
|
||||
ASSERT_EQ(std::string { prefix } + expected.to_string(), str);
|
||||
}
|
||||
|
||||
TEST(ExtendedOutputsSpec, out) {
|
||||
std::string_view str = "foo^out";
|
||||
auto [prefix, extendedOutputsSpec] = ExtendedOutputsSpec::parse(str);
|
||||
ASSERT_EQ(prefix, "foo");
|
||||
ExtendedOutputsSpec expected = OutputsSpec::Names { "out" };
|
||||
ASSERT_EQ(extendedOutputsSpec, expected);
|
||||
ASSERT_EQ(std::string { prefix } + expected.to_string(), str);
|
||||
}
|
||||
|
||||
TEST(ExtendedOutputsSpec, out_bin) {
|
||||
auto [prefix, extendedOutputsSpec] = ExtendedOutputsSpec::parse("foo^out,bin");
|
||||
ASSERT_EQ(prefix, "foo");
|
||||
ExtendedOutputsSpec expected = OutputsSpec::Names { "out", "bin" };
|
||||
ASSERT_EQ(extendedOutputsSpec, expected);
|
||||
ASSERT_EQ(std::string { prefix } + expected.to_string(), "foo^bin,out");
|
||||
}
|
||||
|
||||
TEST(ExtendedOutputsSpec, many_carrot) {
|
||||
auto [prefix, extendedOutputsSpec] = ExtendedOutputsSpec::parse("foo^bar^out,bin");
|
||||
ASSERT_EQ(prefix, "foo^bar");
|
||||
ExtendedOutputsSpec expected = OutputsSpec::Names { "out", "bin" };
|
||||
ASSERT_EQ(extendedOutputsSpec, expected);
|
||||
ASSERT_EQ(std::string { prefix } + expected.to_string(), "foo^bar^bin,out");
|
||||
}
|
||||
|
||||
|
||||
#define TEST_JSON(TYPE, NAME, STR, VAL) \
|
||||
\
|
||||
TEST(TYPE, NAME ## _to_json) { \
|
||||
using nlohmann::literals::operator "" _json; \
|
||||
ASSERT_EQ( \
|
||||
STR ## _json, \
|
||||
((nlohmann::json) TYPE { VAL })); \
|
||||
} \
|
||||
\
|
||||
TEST(TYPE, NAME ## _from_json) { \
|
||||
using nlohmann::literals::operator "" _json; \
|
||||
ASSERT_EQ( \
|
||||
TYPE { VAL }, \
|
||||
(STR ## _json).get<TYPE>()); \
|
||||
}
|
||||
|
||||
TEST_JSON(OutputsSpec, all, R"(["*"])", OutputsSpec::All { })
|
||||
TEST_JSON(OutputsSpec, name, R"(["a"])", OutputsSpec::Names { "a" })
|
||||
TEST_JSON(OutputsSpec, names, R"(["a","b"])", (OutputsSpec::Names { "a", "b" }))
|
||||
|
||||
TEST_JSON(ExtendedOutputsSpec, def, R"(null)", ExtendedOutputsSpec::Default { })
|
||||
TEST_JSON(ExtendedOutputsSpec, all, R"(["*"])", ExtendedOutputsSpec::Explicit { OutputsSpec::All { } })
|
||||
TEST_JSON(ExtendedOutputsSpec, name, R"(["a"])", ExtendedOutputsSpec::Explicit { OutputsSpec::Names { "a" } })
|
||||
TEST_JSON(ExtendedOutputsSpec, names, R"(["a","b"])", (ExtendedOutputsSpec::Explicit { OutputsSpec::Names { "a", "b" } }))
|
||||
|
||||
#undef TEST_JSON
|
||||
|
||||
}
|
||||
|
||||
namespace rc {
|
||||
using namespace nix;
|
||||
|
||||
Gen<OutputsSpec> Arbitrary<OutputsSpec>::arbitrary()
|
||||
{
|
||||
switch (*gen::inRange<uint8_t>(0, std::variant_size_v<OutputsSpec::Raw>)) {
|
||||
case 0:
|
||||
return gen::just((OutputsSpec) OutputsSpec::All { });
|
||||
case 1:
|
||||
return gen::just((OutputsSpec) OutputsSpec::Names {
|
||||
*gen::nonEmpty(gen::container<StringSet>(gen::map(
|
||||
gen::arbitrary<StorePathName>(),
|
||||
[](StorePathName n) { return n.name; }))),
|
||||
});
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace nix {
|
||||
|
||||
#ifndef COVERAGE
|
||||
|
||||
RC_GTEST_PROP(
|
||||
OutputsSpec,
|
||||
prop_round_rip,
|
||||
(const OutputsSpec & o))
|
||||
{
|
||||
RC_ASSERT(o == OutputsSpec::parse(o.to_string()));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
#pragma once
|
||||
///@file
|
||||
|
||||
#include <rapidcheck/gen/Arbitrary.h>
|
||||
|
||||
#include <outputs-spec.hh>
|
||||
|
||||
#include <tests/path.hh>
|
||||
|
||||
namespace rc {
|
||||
using namespace nix;
|
||||
|
||||
template<>
|
||||
struct Arbitrary<OutputsSpec> {
|
||||
static Gen<OutputsSpec> arbitrary();
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -1,79 +0,0 @@
|
|||
#include <nlohmann/json.hpp>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "path-info.hh"
|
||||
|
||||
#include "tests/characterization.hh"
|
||||
#include "tests/libstore.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
using nlohmann::json;
|
||||
|
||||
class PathInfoTest : public CharacterizationTest, public LibStoreTest
|
||||
{
|
||||
Path unitTestData = getUnitTestData() + "/libstore/path-info";
|
||||
|
||||
Path goldenMaster(PathView testStem) const override {
|
||||
return unitTestData + "/" + testStem + ".json";
|
||||
}
|
||||
};
|
||||
|
||||
static UnkeyedValidPathInfo makePathInfo(const Store & store, bool includeImpureInfo) {
|
||||
UnkeyedValidPathInfo info = ValidPathInfo {
|
||||
store,
|
||||
"foo",
|
||||
FixedOutputInfo {
|
||||
.method = FileIngestionMethod::Recursive,
|
||||
.hash = hashString(HashType::htSHA256, "(...)"),
|
||||
|
||||
.references = {
|
||||
.others = {
|
||||
StorePath {
|
||||
"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar",
|
||||
},
|
||||
},
|
||||
.self = true,
|
||||
},
|
||||
},
|
||||
Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="),
|
||||
};
|
||||
info.narSize = 34878;
|
||||
if (includeImpureInfo) {
|
||||
info.deriver = StorePath {
|
||||
"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv",
|
||||
};
|
||||
info.registrationTime = 23423;
|
||||
info.ultimate = true;
|
||||
info.sigs = { "asdf", "qwer" };
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
#define JSON_TEST(STEM, PURE) \
|
||||
TEST_F(PathInfoTest, PathInfo_ ## STEM ## _from_json) { \
|
||||
readTest(#STEM, [&](const auto & encoded_) { \
|
||||
auto encoded = json::parse(encoded_); \
|
||||
UnkeyedValidPathInfo got = UnkeyedValidPathInfo::fromJSON( \
|
||||
*store, \
|
||||
encoded); \
|
||||
auto expected = makePathInfo(*store, PURE); \
|
||||
ASSERT_EQ(got, expected); \
|
||||
}); \
|
||||
} \
|
||||
\
|
||||
TEST_F(PathInfoTest, PathInfo_ ## STEM ## _to_json) { \
|
||||
writeTest(#STEM, [&]() -> json { \
|
||||
return makePathInfo(*store, PURE) \
|
||||
.toJSON(*store, PURE, HashFormat::SRI); \
|
||||
}, [](const auto & file) { \
|
||||
return json::parse(readFile(file)); \
|
||||
}, [](const auto & file, const auto & got) { \
|
||||
return writeFile(file, got.dump(2) + "\n"); \
|
||||
}); \
|
||||
}
|
||||
|
||||
JSON_TEST(pure, false)
|
||||
JSON_TEST(impure, true)
|
||||
|
||||
}
|
||||
|
|
@ -1,162 +0,0 @@
|
|||
#include <regex>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <gtest/gtest.h>
|
||||
#include <rapidcheck/gtest.h>
|
||||
|
||||
#include "path-regex.hh"
|
||||
#include "store-api.hh"
|
||||
|
||||
#include "tests/hash.hh"
|
||||
#include "tests/libstore.hh"
|
||||
#include "tests/path.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
#define STORE_DIR "/nix/store/"
|
||||
#define HASH_PART "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q"
|
||||
|
||||
class StorePathTest : public LibStoreTest
|
||||
{
|
||||
};
|
||||
|
||||
static std::regex nameRegex { std::string { nameRegexStr } };
|
||||
|
||||
#define TEST_DONT_PARSE(NAME, STR) \
|
||||
TEST_F(StorePathTest, bad_ ## NAME) { \
|
||||
std::string_view str = \
|
||||
STORE_DIR HASH_PART "-" STR; \
|
||||
ASSERT_THROW( \
|
||||
store->parseStorePath(str), \
|
||||
BadStorePath); \
|
||||
std::string name { STR }; \
|
||||
EXPECT_FALSE(std::regex_match(name, nameRegex)); \
|
||||
}
|
||||
|
||||
TEST_DONT_PARSE(empty, "")
|
||||
TEST_DONT_PARSE(garbage, "&*()")
|
||||
TEST_DONT_PARSE(double_star, "**")
|
||||
TEST_DONT_PARSE(star_first, "*,foo")
|
||||
TEST_DONT_PARSE(star_second, "foo,*")
|
||||
TEST_DONT_PARSE(bang, "foo!o")
|
||||
TEST_DONT_PARSE(dotfile, ".gitignore")
|
||||
|
||||
#undef TEST_DONT_PARSE
|
||||
|
||||
#define TEST_DO_PARSE(NAME, STR) \
|
||||
TEST_F(StorePathTest, good_ ## NAME) { \
|
||||
std::string_view str = \
|
||||
STORE_DIR HASH_PART "-" STR; \
|
||||
auto p = store->parseStorePath(str); \
|
||||
std::string name { p.name() }; \
|
||||
EXPECT_TRUE(std::regex_match(name, nameRegex)); \
|
||||
}
|
||||
|
||||
// 0-9 a-z A-Z + - . _ ? =
|
||||
|
||||
TEST_DO_PARSE(numbers, "02345")
|
||||
TEST_DO_PARSE(lower_case, "foo")
|
||||
TEST_DO_PARSE(upper_case, "FOO")
|
||||
TEST_DO_PARSE(plus, "foo+bar")
|
||||
TEST_DO_PARSE(dash, "foo-dev")
|
||||
TEST_DO_PARSE(underscore, "foo_bar")
|
||||
TEST_DO_PARSE(period, "foo.txt")
|
||||
TEST_DO_PARSE(question_mark, "foo?why")
|
||||
TEST_DO_PARSE(equals_sign, "foo=foo")
|
||||
|
||||
#undef TEST_DO_PARSE
|
||||
|
||||
// For rapidcheck
|
||||
void showValue(const StorePath & p, std::ostream & os) {
|
||||
os << p.to_string();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace rc {
|
||||
using namespace nix;
|
||||
|
||||
Gen<StorePathName> Arbitrary<StorePathName>::arbitrary()
|
||||
{
|
||||
auto len = *gen::inRange<size_t>(
|
||||
1,
|
||||
StorePath::MaxPathLen - std::string_view { HASH_PART }.size());
|
||||
|
||||
std::string pre;
|
||||
pre.reserve(len);
|
||||
|
||||
for (size_t c = 0; c < len; ++c) {
|
||||
switch (auto i = *gen::inRange<uint8_t>(0, 10 + 2 * 26 + 6)) {
|
||||
case 0 ... 9:
|
||||
pre += '0' + i;
|
||||
case 10 ... 35:
|
||||
pre += 'A' + (i - 10);
|
||||
break;
|
||||
case 36 ... 61:
|
||||
pre += 'a' + (i - 36);
|
||||
break;
|
||||
case 62:
|
||||
pre += '+';
|
||||
break;
|
||||
case 63:
|
||||
pre += '-';
|
||||
break;
|
||||
case 64:
|
||||
// names aren't permitted to start with a period,
|
||||
// so just fall through to the next case here
|
||||
if (c != 0) {
|
||||
pre += '.';
|
||||
break;
|
||||
}
|
||||
case 65:
|
||||
pre += '_';
|
||||
break;
|
||||
case 66:
|
||||
pre += '?';
|
||||
break;
|
||||
case 67:
|
||||
pre += '=';
|
||||
break;
|
||||
default:
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
|
||||
return gen::just(StorePathName {
|
||||
.name = std::move(pre),
|
||||
});
|
||||
}
|
||||
|
||||
Gen<StorePath> Arbitrary<StorePath>::arbitrary()
|
||||
{
|
||||
return gen::just(StorePath {
|
||||
*gen::arbitrary<Hash>(),
|
||||
(*gen::arbitrary<StorePathName>()).name,
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace rc
|
||||
|
||||
namespace nix {
|
||||
|
||||
#ifndef COVERAGE
|
||||
|
||||
RC_GTEST_FIXTURE_PROP(
|
||||
StorePathTest,
|
||||
prop_regex_accept,
|
||||
(const StorePath & p))
|
||||
{
|
||||
RC_ASSERT(std::regex_match(std::string { p.name() }, nameRegex));
|
||||
}
|
||||
|
||||
RC_GTEST_FIXTURE_PROP(
|
||||
StorePathTest,
|
||||
prop_round_rip,
|
||||
(const StorePath & p))
|
||||
{
|
||||
RC_ASSERT(p == store->parseStorePath(store->printStorePath(p)));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
#pragma once
|
||||
///@file
|
||||
|
||||
#include <rapidcheck/gen/Arbitrary.h>
|
||||
|
||||
#include <path.hh>
|
||||
|
||||
namespace nix {
|
||||
|
||||
struct StorePathName {
|
||||
std::string name;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace rc {
|
||||
using namespace nix;
|
||||
|
||||
template<>
|
||||
struct Arbitrary<StorePathName> {
|
||||
static Gen<StorePathName> arbitrary();
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Arbitrary<StorePath> {
|
||||
static Gen<StorePath> arbitrary();
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -1,75 +0,0 @@
|
|||
#pragma once
|
||||
///@file
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "tests/libstore.hh"
|
||||
#include "tests/characterization.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
template<class Proto, const char * protocolDir>
|
||||
class ProtoTest : public CharacterizationTest, public LibStoreTest
|
||||
{
|
||||
Path unitTestData = getUnitTestData() + "/libstore/" + protocolDir;
|
||||
|
||||
Path goldenMaster(std::string_view testStem) const override {
|
||||
return unitTestData + "/" + testStem + ".bin";
|
||||
}
|
||||
};
|
||||
|
||||
template<class Proto, const char * protocolDir>
|
||||
class VersionedProtoTest : public ProtoTest<Proto, protocolDir>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Golden test for `T` reading
|
||||
*/
|
||||
template<typename T>
|
||||
void readProtoTest(PathView testStem, typename Proto::Version version, T expected)
|
||||
{
|
||||
CharacterizationTest::readTest(testStem, [&](const auto & encoded) {
|
||||
T got = ({
|
||||
StringSource from { encoded };
|
||||
Proto::template Serialise<T>::read(
|
||||
*LibStoreTest::store,
|
||||
typename Proto::ReadConn {
|
||||
.from = from,
|
||||
.version = version,
|
||||
});
|
||||
});
|
||||
|
||||
ASSERT_EQ(got, expected);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Golden test for `T` write
|
||||
*/
|
||||
template<typename T>
|
||||
void writeProtoTest(PathView testStem, typename Proto::Version version, const T & decoded)
|
||||
{
|
||||
CharacterizationTest::writeTest(testStem, [&]() {
|
||||
StringSink to;
|
||||
Proto::template Serialise<T>::write(
|
||||
*LibStoreTest::store,
|
||||
typename Proto::WriteConn {
|
||||
.to = to,
|
||||
.version = version,
|
||||
},
|
||||
decoded);
|
||||
return std::move(to.s);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
#define VERSIONED_CHARACTERIZATION_TEST(FIXTURE, NAME, STEM, VERSION, VALUE) \
|
||||
TEST_F(FIXTURE, NAME ## _read) { \
|
||||
readProtoTest(STEM, VERSION, VALUE); \
|
||||
} \
|
||||
TEST_F(FIXTURE, NAME ## _write) { \
|
||||
writeProtoTest(STEM, VERSION, VALUE); \
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
#include "references.hh"
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
namespace nix {
|
||||
|
||||
TEST(references, scan)
|
||||
{
|
||||
std::string hash1 = "dc04vv14dak1c1r48qa0m23vr9jy8sm0";
|
||||
std::string hash2 = "zc842j0rz61mjsp3h3wp5ly71ak6qgdn";
|
||||
|
||||
{
|
||||
RefScanSink scanner(StringSet{hash1});
|
||||
auto s = "foobar";
|
||||
scanner(s);
|
||||
ASSERT_EQ(scanner.getResult(), StringSet{});
|
||||
}
|
||||
|
||||
{
|
||||
RefScanSink scanner(StringSet{hash1});
|
||||
auto s = "foobar" + hash1 + "xyzzy";
|
||||
scanner(s);
|
||||
ASSERT_EQ(scanner.getResult(), StringSet{hash1});
|
||||
}
|
||||
|
||||
{
|
||||
RefScanSink scanner(StringSet{hash1, hash2});
|
||||
auto s = "foobar" + hash1 + "xyzzy" + hash2;
|
||||
scanner(((std::string_view) s).substr(0, 10));
|
||||
scanner(((std::string_view) s).substr(10, 5));
|
||||
scanner(((std::string_view) s).substr(15, 5));
|
||||
scanner(((std::string_view) s).substr(20));
|
||||
ASSERT_EQ(scanner.getResult(), StringSet({hash1, hash2}));
|
||||
}
|
||||
|
||||
{
|
||||
RefScanSink scanner(StringSet{hash1, hash2});
|
||||
auto s = "foobar" + hash1 + "xyzzy" + hash2;
|
||||
for (auto & i : s)
|
||||
scanner(std::string(1, i));
|
||||
ASSERT_EQ(scanner.getResult(), StringSet({hash1, hash2}));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,279 +0,0 @@
|
|||
#include <regex>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "serve-protocol.hh"
|
||||
#include "serve-protocol-impl.hh"
|
||||
#include "build-result.hh"
|
||||
#include "tests/protocol.hh"
|
||||
#include "tests/characterization.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
const char serveProtoDir[] = "serve-protocol";
|
||||
|
||||
struct ServeProtoTest : VersionedProtoTest<ServeProto, serveProtoDir>
|
||||
{
|
||||
/**
|
||||
* For serializers that don't care about the minimum version, we
|
||||
* used the oldest one: 1.0.
|
||||
*/
|
||||
ServeProto::Version defaultVersion = 2 << 8 | 0;
|
||||
};
|
||||
|
||||
VERSIONED_CHARACTERIZATION_TEST(
|
||||
ServeProtoTest,
|
||||
string,
|
||||
"string",
|
||||
defaultVersion,
|
||||
(std::tuple<std::string, std::string, std::string, std::string, std::string> {
|
||||
"",
|
||||
"hi",
|
||||
"white rabbit",
|
||||
"大白兔",
|
||||
"oh no \0\0\0 what was that!",
|
||||
}))
|
||||
|
||||
VERSIONED_CHARACTERIZATION_TEST(
|
||||
ServeProtoTest,
|
||||
storePath,
|
||||
"store-path",
|
||||
defaultVersion,
|
||||
(std::tuple<StorePath, StorePath> {
|
||||
StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo" },
|
||||
StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo-bar" },
|
||||
}))
|
||||
|
||||
VERSIONED_CHARACTERIZATION_TEST(
|
||||
ServeProtoTest,
|
||||
contentAddress,
|
||||
"content-address",
|
||||
defaultVersion,
|
||||
(std::tuple<ContentAddress, ContentAddress, ContentAddress> {
|
||||
ContentAddress {
|
||||
.method = TextIngestionMethod {},
|
||||
.hash = hashString(HashType::htSHA256, "Derive(...)"),
|
||||
},
|
||||
ContentAddress {
|
||||
.method = FileIngestionMethod::Flat,
|
||||
.hash = hashString(HashType::htSHA1, "blob blob..."),
|
||||
},
|
||||
ContentAddress {
|
||||
.method = FileIngestionMethod::Recursive,
|
||||
.hash = hashString(HashType::htSHA256, "(...)"),
|
||||
},
|
||||
}))
|
||||
|
||||
VERSIONED_CHARACTERIZATION_TEST(
|
||||
ServeProtoTest,
|
||||
drvOutput,
|
||||
"drv-output",
|
||||
defaultVersion,
|
||||
(std::tuple<DrvOutput, DrvOutput> {
|
||||
{
|
||||
.drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="),
|
||||
.outputName = "baz",
|
||||
},
|
||||
DrvOutput {
|
||||
.drvHash = Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="),
|
||||
.outputName = "quux",
|
||||
},
|
||||
}))
|
||||
|
||||
VERSIONED_CHARACTERIZATION_TEST(
|
||||
ServeProtoTest,
|
||||
realisation,
|
||||
"realisation",
|
||||
defaultVersion,
|
||||
(std::tuple<Realisation, Realisation> {
|
||||
Realisation {
|
||||
.id = DrvOutput {
|
||||
.drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="),
|
||||
.outputName = "baz",
|
||||
},
|
||||
.outPath = StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo" },
|
||||
.signatures = { "asdf", "qwer" },
|
||||
},
|
||||
Realisation {
|
||||
.id = {
|
||||
.drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="),
|
||||
.outputName = "baz",
|
||||
},
|
||||
.outPath = StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo" },
|
||||
.signatures = { "asdf", "qwer" },
|
||||
.dependentRealisations = {
|
||||
{
|
||||
DrvOutput {
|
||||
.drvHash = Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="),
|
||||
.outputName = "quux",
|
||||
},
|
||||
StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo" },
|
||||
},
|
||||
},
|
||||
},
|
||||
}))
|
||||
|
||||
VERSIONED_CHARACTERIZATION_TEST(
|
||||
ServeProtoTest,
|
||||
buildResult_2_2,
|
||||
"build-result-2.2",
|
||||
2 << 8 | 2,
|
||||
({
|
||||
using namespace std::literals::chrono_literals;
|
||||
std::tuple<BuildResult, BuildResult, BuildResult> t {
|
||||
BuildResult {
|
||||
.status = BuildResult::OutputRejected,
|
||||
.errorMsg = "no idea why",
|
||||
},
|
||||
BuildResult {
|
||||
.status = BuildResult::NotDeterministic,
|
||||
.errorMsg = "no idea why",
|
||||
},
|
||||
BuildResult {
|
||||
.status = BuildResult::Built,
|
||||
},
|
||||
};
|
||||
t;
|
||||
}))
|
||||
|
||||
VERSIONED_CHARACTERIZATION_TEST(
|
||||
ServeProtoTest,
|
||||
buildResult_2_3,
|
||||
"build-result-2.3",
|
||||
2 << 8 | 3,
|
||||
({
|
||||
using namespace std::literals::chrono_literals;
|
||||
std::tuple<BuildResult, BuildResult, BuildResult> t {
|
||||
BuildResult {
|
||||
.status = BuildResult::OutputRejected,
|
||||
.errorMsg = "no idea why",
|
||||
},
|
||||
BuildResult {
|
||||
.status = BuildResult::NotDeterministic,
|
||||
.errorMsg = "no idea why",
|
||||
.timesBuilt = 3,
|
||||
.isNonDeterministic = true,
|
||||
.startTime = 30,
|
||||
.stopTime = 50,
|
||||
},
|
||||
BuildResult {
|
||||
.status = BuildResult::Built,
|
||||
.startTime = 30,
|
||||
.stopTime = 50,
|
||||
},
|
||||
};
|
||||
t;
|
||||
}))
|
||||
|
||||
VERSIONED_CHARACTERIZATION_TEST(
|
||||
ServeProtoTest,
|
||||
buildResult_2_6,
|
||||
"build-result-2.6",
|
||||
2 << 8 | 6,
|
||||
({
|
||||
using namespace std::literals::chrono_literals;
|
||||
std::tuple<BuildResult, BuildResult, BuildResult> t {
|
||||
BuildResult {
|
||||
.status = BuildResult::OutputRejected,
|
||||
.errorMsg = "no idea why",
|
||||
},
|
||||
BuildResult {
|
||||
.status = BuildResult::NotDeterministic,
|
||||
.errorMsg = "no idea why",
|
||||
.timesBuilt = 3,
|
||||
.isNonDeterministic = true,
|
||||
.startTime = 30,
|
||||
.stopTime = 50,
|
||||
},
|
||||
BuildResult {
|
||||
.status = BuildResult::Built,
|
||||
.timesBuilt = 1,
|
||||
.builtOutputs = {
|
||||
{
|
||||
"foo",
|
||||
{
|
||||
.id = DrvOutput {
|
||||
.drvHash = Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="),
|
||||
.outputName = "foo",
|
||||
},
|
||||
.outPath = StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo" },
|
||||
},
|
||||
},
|
||||
{
|
||||
"bar",
|
||||
{
|
||||
.id = DrvOutput {
|
||||
.drvHash = Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="),
|
||||
.outputName = "bar",
|
||||
},
|
||||
.outPath = StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar" },
|
||||
},
|
||||
},
|
||||
},
|
||||
.startTime = 30,
|
||||
.stopTime = 50,
|
||||
#if 0
|
||||
// These fields are not yet serialized.
|
||||
// FIXME Include in next version of protocol or document
|
||||
// why they are skipped.
|
||||
.cpuUser = std::chrono::milliseconds(500s),
|
||||
.cpuSystem = std::chrono::milliseconds(604s),
|
||||
#endif
|
||||
},
|
||||
};
|
||||
t;
|
||||
}))
|
||||
|
||||
VERSIONED_CHARACTERIZATION_TEST(
|
||||
ServeProtoTest,
|
||||
vector,
|
||||
"vector",
|
||||
defaultVersion,
|
||||
(std::tuple<std::vector<std::string>, std::vector<std::string>, std::vector<std::string>, std::vector<std::vector<std::string>>> {
|
||||
{ },
|
||||
{ "" },
|
||||
{ "", "foo", "bar" },
|
||||
{ {}, { "" }, { "", "1", "2" } },
|
||||
}))
|
||||
|
||||
VERSIONED_CHARACTERIZATION_TEST(
|
||||
ServeProtoTest,
|
||||
set,
|
||||
"set",
|
||||
defaultVersion,
|
||||
(std::tuple<std::set<std::string>, std::set<std::string>, std::set<std::string>, std::set<std::set<std::string>>> {
|
||||
{ },
|
||||
{ "" },
|
||||
{ "", "foo", "bar" },
|
||||
{ {}, { "" }, { "", "1", "2" } },
|
||||
}))
|
||||
|
||||
VERSIONED_CHARACTERIZATION_TEST(
|
||||
ServeProtoTest,
|
||||
optionalStorePath,
|
||||
"optional-store-path",
|
||||
defaultVersion,
|
||||
(std::tuple<std::optional<StorePath>, std::optional<StorePath>> {
|
||||
std::nullopt,
|
||||
std::optional {
|
||||
StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo-bar" },
|
||||
},
|
||||
}))
|
||||
|
||||
VERSIONED_CHARACTERIZATION_TEST(
|
||||
ServeProtoTest,
|
||||
optionalContentAddress,
|
||||
"optional-content-address",
|
||||
defaultVersion,
|
||||
(std::tuple<std::optional<ContentAddress>, std::optional<ContentAddress>> {
|
||||
std::nullopt,
|
||||
std::optional {
|
||||
ContentAddress {
|
||||
.method = FileIngestionMethod::Flat,
|
||||
.hash = hashString(HashType::htSHA1, "blob blob..."),
|
||||
},
|
||||
},
|
||||
}))
|
||||
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
nix@scratchy.labs.cs.uu.nl - - eight
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
nix@scratchy.labs.cs.uu.nl i686-linux /home/nix/.ssh/id_scratchy_auto 8 1 kvm
|
||||
nix@itchy.labs.cs.uu.nl i686-linux /home/nix/.ssh/id_scratchy_auto 8 2
|
||||
nix@poochie.labs.cs.uu.nl i686-linux /home/nix/.ssh/id_scratchy_auto 1 2 kvm benchmark c3NoLXJzYSBBQUFBQjNOemFDMXljMkVBQUFBREFRQUJBQUFDQVFDWWV5R1laNTNzd1VjMUZNSHBWL1BCcXlKaFR5S1JoRkpWWVRpRHlQN2h5c1JGa0w4VDlLOGdhL2Y2L3c3QjN2SjNHSFRIUFkybENiUEdZbGNLd2h6M2ZRbFNNOEViNi95b3ZLajdvM1FsMEx5Y0dzdGJvRmcwWkZKNldncUxsR0ltS0NobUlxOGZ3TW5ZTWUxbnRQeTBUZFZjSU1tOTV3YzF3SjBMd2c3cEVMRmtHazdkeTVvYnM4a3lGZ0pORDVRSmFwQWJjeWp4Z1QzdzdMcktNZ2xzeWhhd01JNVpkMGZsQTVudW5OZ3pid3plYVhLaUsyTW0vdGJXYTU1YTd4QmNYdHpIZGlPSWdSajJlRWxaMGh5bk10YjBmcklsdmxIcEtLaVFaZ3pQdCtIVXQ2bXpRMkRVME52MGYyYnNSU0krOGpJU2pQcmdlcVVHRldMUzVIUTg2N2xSMlpiaWtyclhZNTdqbVFEZk5DRHY1VFBHZU9UekFEd2pjMDc2aFZ3VFJCd3VTZFhtaWNxTS95b3lrWitkV1dnZ25MenE5QU1tdlNZcDhmZkZDcS9CSDBZNUFXWTFHay9vS3hMVTNaOWt3ZDd2UWNFQWFCQ2dxdnVZRGdTaHE1RlhndDM3OVZESWtEL05ZSTg2QXVvajVDRmVNTzlRM2pJSlRadlh6c1VldjVoSnA2djcxSVh5ODVtbTY5R20zcXdicVE1SjVQZDU1Um56SitpaW5BNjZxTEFSc0Y4amNsSnd5ekFXclBoYU9DRVY2bjVMeVhVazhzMW9EVVR4V1pWN25rVkFTbHJ0MllGcjN5dzdjRTRXQVhsemhHcDhocmdLMVVkMUlyeDVnZWRaSnBWcy9uNWVybmJFMUxmb2x5UHUvRUFIWlh6VGd4dHVDUFNobXc9PQo=
|
||||
|
|
@ -1,547 +0,0 @@
|
|||
#include <regex>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include "worker-protocol.hh"
|
||||
#include "worker-protocol-impl.hh"
|
||||
#include "derived-path.hh"
|
||||
#include "build-result.hh"
|
||||
#include "tests/protocol.hh"
|
||||
#include "tests/characterization.hh"
|
||||
|
||||
namespace nix {
|
||||
|
||||
const char workerProtoDir[] = "worker-protocol";
|
||||
|
||||
struct WorkerProtoTest : VersionedProtoTest<WorkerProto, workerProtoDir>
|
||||
{
|
||||
/**
|
||||
* For serializers that don't care about the minimum version, we
|
||||
* used the oldest one: 1.0.
|
||||
*/
|
||||
WorkerProto::Version defaultVersion = 1 << 8 | 0;
|
||||
};
|
||||
|
||||
|
||||
VERSIONED_CHARACTERIZATION_TEST(
|
||||
WorkerProtoTest,
|
||||
string,
|
||||
"string",
|
||||
defaultVersion,
|
||||
(std::tuple<std::string, std::string, std::string, std::string, std::string> {
|
||||
"",
|
||||
"hi",
|
||||
"white rabbit",
|
||||
"大白兔",
|
||||
"oh no \0\0\0 what was that!",
|
||||
}))
|
||||
|
||||
VERSIONED_CHARACTERIZATION_TEST(
|
||||
WorkerProtoTest,
|
||||
storePath,
|
||||
"store-path",
|
||||
defaultVersion,
|
||||
(std::tuple<StorePath, StorePath> {
|
||||
StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo" },
|
||||
StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo-bar" },
|
||||
}))
|
||||
|
||||
VERSIONED_CHARACTERIZATION_TEST(
|
||||
WorkerProtoTest,
|
||||
contentAddress,
|
||||
"content-address",
|
||||
defaultVersion,
|
||||
(std::tuple<ContentAddress, ContentAddress, ContentAddress> {
|
||||
ContentAddress {
|
||||
.method = TextIngestionMethod {},
|
||||
.hash = hashString(HashType::htSHA256, "Derive(...)"),
|
||||
},
|
||||
ContentAddress {
|
||||
.method = FileIngestionMethod::Flat,
|
||||
.hash = hashString(HashType::htSHA1, "blob blob..."),
|
||||
},
|
||||
ContentAddress {
|
||||
.method = FileIngestionMethod::Recursive,
|
||||
.hash = hashString(HashType::htSHA256, "(...)"),
|
||||
},
|
||||
}))
|
||||
|
||||
VERSIONED_CHARACTERIZATION_TEST(
|
||||
WorkerProtoTest,
|
||||
derivedPath_1_29,
|
||||
"derived-path-1.29",
|
||||
1 << 8 | 29,
|
||||
(std::tuple<DerivedPath, DerivedPath, DerivedPath> {
|
||||
DerivedPath::Opaque {
|
||||
.path = StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo" },
|
||||
},
|
||||
DerivedPath::Built {
|
||||
.drvPath = makeConstantStorePathRef(StorePath {
|
||||
"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv",
|
||||
}),
|
||||
.outputs = OutputsSpec::All { },
|
||||
},
|
||||
DerivedPath::Built {
|
||||
.drvPath = makeConstantStorePathRef(StorePath {
|
||||
"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv",
|
||||
}),
|
||||
.outputs = OutputsSpec::Names { "x", "y" },
|
||||
},
|
||||
}))
|
||||
|
||||
VERSIONED_CHARACTERIZATION_TEST(
|
||||
WorkerProtoTest,
|
||||
derivedPath_1_30,
|
||||
"derived-path-1.30",
|
||||
1 << 8 | 30,
|
||||
(std::tuple<DerivedPath, DerivedPath, DerivedPath, DerivedPath> {
|
||||
DerivedPath::Opaque {
|
||||
.path = StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo" },
|
||||
},
|
||||
DerivedPath::Opaque {
|
||||
.path = StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo.drv" },
|
||||
},
|
||||
DerivedPath::Built {
|
||||
.drvPath = makeConstantStorePathRef(StorePath {
|
||||
"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv",
|
||||
}),
|
||||
.outputs = OutputsSpec::All { },
|
||||
},
|
||||
DerivedPath::Built {
|
||||
.drvPath = makeConstantStorePathRef(StorePath {
|
||||
"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv",
|
||||
}),
|
||||
.outputs = OutputsSpec::Names { "x", "y" },
|
||||
},
|
||||
}))
|
||||
|
||||
VERSIONED_CHARACTERIZATION_TEST(
|
||||
WorkerProtoTest,
|
||||
drvOutput,
|
||||
"drv-output",
|
||||
defaultVersion,
|
||||
(std::tuple<DrvOutput, DrvOutput> {
|
||||
{
|
||||
.drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="),
|
||||
.outputName = "baz",
|
||||
},
|
||||
DrvOutput {
|
||||
.drvHash = Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="),
|
||||
.outputName = "quux",
|
||||
},
|
||||
}))
|
||||
|
||||
VERSIONED_CHARACTERIZATION_TEST(
|
||||
WorkerProtoTest,
|
||||
realisation,
|
||||
"realisation",
|
||||
defaultVersion,
|
||||
(std::tuple<Realisation, Realisation> {
|
||||
Realisation {
|
||||
.id = DrvOutput {
|
||||
.drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="),
|
||||
.outputName = "baz",
|
||||
},
|
||||
.outPath = StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo" },
|
||||
.signatures = { "asdf", "qwer" },
|
||||
},
|
||||
Realisation {
|
||||
.id = {
|
||||
.drvHash = Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="),
|
||||
.outputName = "baz",
|
||||
},
|
||||
.outPath = StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo" },
|
||||
.signatures = { "asdf", "qwer" },
|
||||
.dependentRealisations = {
|
||||
{
|
||||
DrvOutput {
|
||||
.drvHash = Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="),
|
||||
.outputName = "quux",
|
||||
},
|
||||
StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo" },
|
||||
},
|
||||
},
|
||||
},
|
||||
}))
|
||||
|
||||
VERSIONED_CHARACTERIZATION_TEST(
|
||||
WorkerProtoTest,
|
||||
buildResult_1_27,
|
||||
"build-result-1.27",
|
||||
1 << 8 | 27,
|
||||
({
|
||||
using namespace std::literals::chrono_literals;
|
||||
std::tuple<BuildResult, BuildResult, BuildResult> t {
|
||||
BuildResult {
|
||||
.status = BuildResult::OutputRejected,
|
||||
.errorMsg = "no idea why",
|
||||
},
|
||||
BuildResult {
|
||||
.status = BuildResult::NotDeterministic,
|
||||
.errorMsg = "no idea why",
|
||||
},
|
||||
BuildResult {
|
||||
.status = BuildResult::Built,
|
||||
},
|
||||
};
|
||||
t;
|
||||
}))
|
||||
|
||||
VERSIONED_CHARACTERIZATION_TEST(
|
||||
WorkerProtoTest,
|
||||
buildResult_1_28,
|
||||
"build-result-1.28",
|
||||
1 << 8 | 28,
|
||||
({
|
||||
using namespace std::literals::chrono_literals;
|
||||
std::tuple<BuildResult, BuildResult, BuildResult> t {
|
||||
BuildResult {
|
||||
.status = BuildResult::OutputRejected,
|
||||
.errorMsg = "no idea why",
|
||||
},
|
||||
BuildResult {
|
||||
.status = BuildResult::NotDeterministic,
|
||||
.errorMsg = "no idea why",
|
||||
},
|
||||
BuildResult {
|
||||
.status = BuildResult::Built,
|
||||
.builtOutputs = {
|
||||
{
|
||||
"foo",
|
||||
{
|
||||
.id = DrvOutput {
|
||||
.drvHash = Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="),
|
||||
.outputName = "foo",
|
||||
},
|
||||
.outPath = StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo" },
|
||||
},
|
||||
},
|
||||
{
|
||||
"bar",
|
||||
{
|
||||
.id = DrvOutput {
|
||||
.drvHash = Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="),
|
||||
.outputName = "bar",
|
||||
},
|
||||
.outPath = StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar" },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
t;
|
||||
}))
|
||||
|
||||
VERSIONED_CHARACTERIZATION_TEST(
|
||||
WorkerProtoTest,
|
||||
buildResult_1_29,
|
||||
"build-result-1.29",
|
||||
1 << 8 | 29,
|
||||
({
|
||||
using namespace std::literals::chrono_literals;
|
||||
std::tuple<BuildResult, BuildResult, BuildResult> t {
|
||||
BuildResult {
|
||||
.status = BuildResult::OutputRejected,
|
||||
.errorMsg = "no idea why",
|
||||
},
|
||||
BuildResult {
|
||||
.status = BuildResult::NotDeterministic,
|
||||
.errorMsg = "no idea why",
|
||||
.timesBuilt = 3,
|
||||
.isNonDeterministic = true,
|
||||
.startTime = 30,
|
||||
.stopTime = 50,
|
||||
},
|
||||
BuildResult {
|
||||
.status = BuildResult::Built,
|
||||
.timesBuilt = 1,
|
||||
.builtOutputs = {
|
||||
{
|
||||
"foo",
|
||||
{
|
||||
.id = DrvOutput {
|
||||
.drvHash = Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="),
|
||||
.outputName = "foo",
|
||||
},
|
||||
.outPath = StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo" },
|
||||
},
|
||||
},
|
||||
{
|
||||
"bar",
|
||||
{
|
||||
.id = DrvOutput {
|
||||
.drvHash = Hash::parseSRI("sha256-b4afnqKCO9oWXgYHb9DeQ2berSwOjS27rSd9TxXDc/U="),
|
||||
.outputName = "bar",
|
||||
},
|
||||
.outPath = StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar" },
|
||||
},
|
||||
},
|
||||
},
|
||||
.startTime = 30,
|
||||
.stopTime = 50,
|
||||
#if 0
|
||||
// These fields are not yet serialized.
|
||||
// FIXME Include in next version of protocol or document
|
||||
// why they are skipped.
|
||||
.cpuUser = std::chrono::milliseconds(500s),
|
||||
.cpuSystem = std::chrono::milliseconds(604s),
|
||||
#endif
|
||||
},
|
||||
};
|
||||
t;
|
||||
}))
|
||||
|
||||
VERSIONED_CHARACTERIZATION_TEST(
|
||||
WorkerProtoTest,
|
||||
keyedBuildResult_1_29,
|
||||
"keyed-build-result-1.29",
|
||||
1 << 8 | 29,
|
||||
({
|
||||
using namespace std::literals::chrono_literals;
|
||||
std::tuple<KeyedBuildResult, KeyedBuildResult/*, KeyedBuildResult*/> t {
|
||||
KeyedBuildResult {
|
||||
{
|
||||
.status = KeyedBuildResult::OutputRejected,
|
||||
.errorMsg = "no idea why",
|
||||
},
|
||||
/* .path = */ DerivedPath::Opaque {
|
||||
StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-xxx" },
|
||||
},
|
||||
},
|
||||
KeyedBuildResult {
|
||||
{
|
||||
.status = KeyedBuildResult::NotDeterministic,
|
||||
.errorMsg = "no idea why",
|
||||
.timesBuilt = 3,
|
||||
.isNonDeterministic = true,
|
||||
.startTime = 30,
|
||||
.stopTime = 50,
|
||||
},
|
||||
/* .path = */ DerivedPath::Built {
|
||||
.drvPath = makeConstantStorePathRef(StorePath {
|
||||
"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv",
|
||||
}),
|
||||
.outputs = OutputsSpec::Names { "out" },
|
||||
},
|
||||
},
|
||||
};
|
||||
t;
|
||||
}))
|
||||
|
||||
VERSIONED_CHARACTERIZATION_TEST(
|
||||
WorkerProtoTest,
|
||||
unkeyedValidPathInfo_1_15,
|
||||
"unkeyed-valid-path-info-1.15",
|
||||
1 << 8 | 15,
|
||||
(std::tuple<UnkeyedValidPathInfo, UnkeyedValidPathInfo> {
|
||||
({
|
||||
UnkeyedValidPathInfo info {
|
||||
Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="),
|
||||
};
|
||||
info.registrationTime = 23423;
|
||||
info.narSize = 34878;
|
||||
info;
|
||||
}),
|
||||
({
|
||||
UnkeyedValidPathInfo info {
|
||||
Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="),
|
||||
};
|
||||
info.deriver = StorePath {
|
||||
"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv",
|
||||
};
|
||||
info.references = {
|
||||
StorePath {
|
||||
"g1w7hyyyy1w7hy3qg1w7hy3qgqqqqy3q-foo.drv",
|
||||
},
|
||||
};
|
||||
info.registrationTime = 23423;
|
||||
info.narSize = 34878;
|
||||
info;
|
||||
}),
|
||||
}))
|
||||
|
||||
VERSIONED_CHARACTERIZATION_TEST(
|
||||
WorkerProtoTest,
|
||||
validPathInfo_1_15,
|
||||
"valid-path-info-1.15",
|
||||
1 << 8 | 15,
|
||||
(std::tuple<ValidPathInfo, ValidPathInfo> {
|
||||
({
|
||||
ValidPathInfo info {
|
||||
StorePath {
|
||||
"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar",
|
||||
},
|
||||
UnkeyedValidPathInfo {
|
||||
Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="),
|
||||
},
|
||||
};
|
||||
info.registrationTime = 23423;
|
||||
info.narSize = 34878;
|
||||
info;
|
||||
}),
|
||||
({
|
||||
ValidPathInfo info {
|
||||
StorePath {
|
||||
"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar",
|
||||
},
|
||||
UnkeyedValidPathInfo {
|
||||
Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="),
|
||||
},
|
||||
};
|
||||
info.deriver = StorePath {
|
||||
"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv",
|
||||
};
|
||||
info.references = {
|
||||
// other reference
|
||||
StorePath {
|
||||
"g1w7hyyyy1w7hy3qg1w7hy3qgqqqqy3q-foo",
|
||||
},
|
||||
// self reference
|
||||
StorePath {
|
||||
"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar",
|
||||
},
|
||||
};
|
||||
info.registrationTime = 23423;
|
||||
info.narSize = 34878;
|
||||
info;
|
||||
}),
|
||||
}))
|
||||
|
||||
VERSIONED_CHARACTERIZATION_TEST(
|
||||
WorkerProtoTest,
|
||||
validPathInfo_1_16,
|
||||
"valid-path-info-1.16",
|
||||
1 << 8 | 16,
|
||||
(std::tuple<ValidPathInfo, ValidPathInfo, ValidPathInfo> {
|
||||
({
|
||||
ValidPathInfo info {
|
||||
StorePath {
|
||||
"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar",
|
||||
},
|
||||
UnkeyedValidPathInfo {
|
||||
Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="),
|
||||
},
|
||||
};
|
||||
info.registrationTime = 23423;
|
||||
info.narSize = 34878;
|
||||
info.ultimate = true;
|
||||
info;
|
||||
}),
|
||||
({
|
||||
ValidPathInfo info {
|
||||
StorePath {
|
||||
"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar",
|
||||
},
|
||||
UnkeyedValidPathInfo {
|
||||
Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="),
|
||||
},
|
||||
};
|
||||
info.deriver = StorePath {
|
||||
"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv",
|
||||
};
|
||||
info.references = {
|
||||
// other reference
|
||||
StorePath {
|
||||
"g1w7hyyyy1w7hy3qg1w7hy3qgqqqqy3q-foo",
|
||||
},
|
||||
// self reference
|
||||
StorePath {
|
||||
"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar",
|
||||
},
|
||||
};
|
||||
info.registrationTime = 23423;
|
||||
info.narSize = 34878;
|
||||
info.sigs = {
|
||||
"fake-sig-1",
|
||||
"fake-sig-2",
|
||||
},
|
||||
info;
|
||||
}),
|
||||
({
|
||||
ValidPathInfo info {
|
||||
*LibStoreTest::store,
|
||||
"foo",
|
||||
FixedOutputInfo {
|
||||
.method = FileIngestionMethod::Recursive,
|
||||
.hash = hashString(HashType::htSHA256, "(...)"),
|
||||
.references = {
|
||||
.others = {
|
||||
StorePath {
|
||||
"g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar",
|
||||
},
|
||||
},
|
||||
.self = true,
|
||||
},
|
||||
},
|
||||
Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="),
|
||||
};
|
||||
info.registrationTime = 23423;
|
||||
info.narSize = 34878;
|
||||
info;
|
||||
}),
|
||||
}))
|
||||
|
||||
VERSIONED_CHARACTERIZATION_TEST(
|
||||
WorkerProtoTest,
|
||||
optionalTrustedFlag,
|
||||
"optional-trusted-flag",
|
||||
defaultVersion,
|
||||
(std::tuple<std::optional<TrustedFlag>, std::optional<TrustedFlag>, std::optional<TrustedFlag>> {
|
||||
std::nullopt,
|
||||
std::optional { Trusted },
|
||||
std::optional { NotTrusted },
|
||||
}))
|
||||
|
||||
VERSIONED_CHARACTERIZATION_TEST(
|
||||
WorkerProtoTest,
|
||||
vector,
|
||||
"vector",
|
||||
defaultVersion,
|
||||
(std::tuple<std::vector<std::string>, std::vector<std::string>, std::vector<std::string>, std::vector<std::vector<std::string>>> {
|
||||
{ },
|
||||
{ "" },
|
||||
{ "", "foo", "bar" },
|
||||
{ {}, { "" }, { "", "1", "2" } },
|
||||
}))
|
||||
|
||||
VERSIONED_CHARACTERIZATION_TEST(
|
||||
WorkerProtoTest,
|
||||
set,
|
||||
"set",
|
||||
defaultVersion,
|
||||
(std::tuple<std::set<std::string>, std::set<std::string>, std::set<std::string>, std::set<std::set<std::string>>> {
|
||||
{ },
|
||||
{ "" },
|
||||
{ "", "foo", "bar" },
|
||||
{ {}, { "" }, { "", "1", "2" } },
|
||||
}))
|
||||
|
||||
VERSIONED_CHARACTERIZATION_TEST(
|
||||
WorkerProtoTest,
|
||||
optionalStorePath,
|
||||
"optional-store-path",
|
||||
defaultVersion,
|
||||
(std::tuple<std::optional<StorePath>, std::optional<StorePath>> {
|
||||
std::nullopt,
|
||||
std::optional {
|
||||
StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo-bar" },
|
||||
},
|
||||
}))
|
||||
|
||||
VERSIONED_CHARACTERIZATION_TEST(
|
||||
WorkerProtoTest,
|
||||
optionalContentAddress,
|
||||
"optional-content-address",
|
||||
defaultVersion,
|
||||
(std::tuple<std::optional<ContentAddress>, std::optional<ContentAddress>> {
|
||||
std::nullopt,
|
||||
std::optional {
|
||||
ContentAddress {
|
||||
.method = FileIngestionMethod::Flat,
|
||||
.hash = hashString(HashType::htSHA1, "blob blob..."),
|
||||
},
|
||||
},
|
||||
}))
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue