diff options
author | Shea Levy <shea@shealevy.com> | 2024-01-11 07:21:16 -0500 |
---|---|---|
committer | Shea Levy <shea@shealevy.com> | 2024-01-11 07:21:16 -0500 |
commit | ba48ab4b954dd1c8af388d1c5a33bbd62373c6f5 (patch) | |
tree | f17f8492bed32f78c04d9d4e9ffd2b672af85943 /src/libstore | |
parent | e7c2b35827e9f4ddbec4248c5cf1ad793a2988ad (diff) | |
parent | 4dd5171652018e29bf9e496522df3be51d615a2c (diff) |
Merge branch '2.18-maintenance' into ifd-buildStore-2.18
Diffstat (limited to 'src/libstore')
30 files changed, 88 insertions, 1847 deletions
diff --git a/src/libstore/build/create-derivation-and-realise-goal.cc b/src/libstore/build/create-derivation-and-realise-goal.cc deleted file mode 100644 index 60f67956d..000000000 --- a/src/libstore/build/create-derivation-and-realise-goal.cc +++ /dev/null @@ -1,157 +0,0 @@ -#include "create-derivation-and-realise-goal.hh" -#include "worker.hh" - -namespace nix { - -CreateDerivationAndRealiseGoal::CreateDerivationAndRealiseGoal(ref<SingleDerivedPath> drvReq, - const OutputsSpec & wantedOutputs, Worker & worker, BuildMode buildMode) - : Goal(worker, DerivedPath::Built { .drvPath = drvReq, .outputs = wantedOutputs }) - , drvReq(drvReq) - , wantedOutputs(wantedOutputs) - , buildMode(buildMode) -{ - state = &CreateDerivationAndRealiseGoal::getDerivation; - name = fmt( - "outer obtaining drv from '%s' and then building outputs %s", - drvReq->to_string(worker.store), - std::visit(overloaded { - [&](const OutputsSpec::All) -> std::string { - return "* (all of them)"; - }, - [&](const OutputsSpec::Names os) { - return concatStringsSep(", ", quoteStrings(os)); - }, - }, wantedOutputs.raw)); - trace("created outer"); - - worker.updateProgress(); -} - - -CreateDerivationAndRealiseGoal::~CreateDerivationAndRealiseGoal() -{ -} - - -static StorePath pathPartOfReq(const SingleDerivedPath & req) -{ - return std::visit(overloaded { - [&](const SingleDerivedPath::Opaque & bo) { - return bo.path; - }, - [&](const SingleDerivedPath::Built & bfd) { - return pathPartOfReq(*bfd.drvPath); - }, - }, req.raw()); -} - - -std::string CreateDerivationAndRealiseGoal::key() -{ - /* Ensure that derivations get built in order of their name, - i.e. a derivation named "aardvark" always comes before "baboon". And - substitution goals and inner derivation goals always happen before - derivation goals (due to "b$"). */ - return "c$" + std::string(pathPartOfReq(*drvReq).name()) + "$" + drvReq->to_string(worker.store); -} - - -void CreateDerivationAndRealiseGoal::timedOut(Error && ex) -{ -} - - -void CreateDerivationAndRealiseGoal::work() -{ - (this->*state)(); -} - - -void CreateDerivationAndRealiseGoal::addWantedOutputs(const OutputsSpec & outputs) -{ - /* If we already want all outputs, there is nothing to do. */ - auto newWanted = wantedOutputs.union_(outputs); - bool needRestart = !newWanted.isSubsetOf(wantedOutputs); - wantedOutputs = newWanted; - - if (!needRestart) return; - - if (!optDrvPath) - // haven't started steps where the outputs matter yet - return; - worker.makeDerivationGoal(*optDrvPath, outputs, buildMode); -} - - -void CreateDerivationAndRealiseGoal::getDerivation() -{ - trace("outer init"); - - /* The first thing to do is to make sure that the derivation - exists. If it doesn't, it may be created through a - substitute. */ - if (auto optDrvPath = [this]() -> std::optional<StorePath> { - if (buildMode != bmNormal) return std::nullopt; - - auto drvPath = StorePath::dummy; - try { - drvPath = resolveDerivedPath(worker.store, *drvReq); - } catch (MissingRealisation &) { - return std::nullopt; - } - return worker.evalStore.isValidPath(drvPath) || worker.store.isValidPath(drvPath) - ? std::optional { drvPath } - : std::nullopt; - }()) { - trace(fmt("already have drv '%s' for '%s', can go straight to building", - worker.store.printStorePath(*optDrvPath), - drvReq->to_string(worker.store))); - - loadAndBuildDerivation(); - } else { - trace("need to obtain drv we want to build"); - - addWaitee(worker.makeGoal(DerivedPath::fromSingle(*drvReq))); - - state = &CreateDerivationAndRealiseGoal::loadAndBuildDerivation; - if (waitees.empty()) work(); - } -} - - -void CreateDerivationAndRealiseGoal::loadAndBuildDerivation() -{ - trace("outer load and build derivation"); - - if (nrFailed != 0) { - amDone(ecFailed, Error("cannot build missing derivation '%s'", drvReq->to_string(worker.store))); - return; - } - - StorePath drvPath = resolveDerivedPath(worker.store, *drvReq); - /* Build this step! */ - concreteDrvGoal = worker.makeDerivationGoal(drvPath, wantedOutputs, buildMode); - addWaitee(upcast_goal(concreteDrvGoal)); - state = &CreateDerivationAndRealiseGoal::buildDone; - optDrvPath = std::move(drvPath); - if (waitees.empty()) work(); -} - - -void CreateDerivationAndRealiseGoal::buildDone() -{ - trace("outer build done"); - - buildResult = upcast_goal(concreteDrvGoal)->getBuildResult(DerivedPath::Built { - .drvPath = drvReq, - .outputs = wantedOutputs, - }); - - if (buildResult.success()) - amDone(ecSuccess); - else - amDone(ecFailed, Error("building '%s' failed", drvReq->to_string(worker.store))); -} - - -} diff --git a/src/libstore/build/create-derivation-and-realise-goal.hh b/src/libstore/build/create-derivation-and-realise-goal.hh deleted file mode 100644 index ca936fc95..000000000 --- a/src/libstore/build/create-derivation-and-realise-goal.hh +++ /dev/null @@ -1,96 +0,0 @@ -#pragma once - -#include "parsed-derivations.hh" -#include "lock.hh" -#include "store-api.hh" -#include "pathlocks.hh" -#include "goal.hh" - -namespace nix { - -struct DerivationGoal; - -/** - * This goal type is essentially the serial composition (like function - * composition) of a goal for getting a derivation, and then a - * `DerivationGoal` using the newly-obtained derivation. - * - * In the (currently experimental) general inductive case of derivations - * that are themselves build outputs, that first goal will be *another* - * `CreateDerivationAndRealiseGoal`. In the (much more common) base-case - * where the derivation has no provence and is just referred to by - * (content-addressed) store path, that first goal is a - * `SubstitutionGoal`. - * - * If we already have the derivation (e.g. if the evalutator has created - * the derivation locally and then instructured the store to build it), - * we can skip the first goal entirely as a small optimization. - */ -struct CreateDerivationAndRealiseGoal : public Goal -{ - /** - * How to obtain a store path of the derivation to build. - */ - ref<SingleDerivedPath> drvReq; - - /** - * The path of the derivation, once obtained. - **/ - std::optional<StorePath> optDrvPath; - - /** - * The goal for the corresponding concrete derivation. - **/ - std::shared_ptr<DerivationGoal> concreteDrvGoal; - - /** - * The specific outputs that we need to build. - */ - OutputsSpec wantedOutputs; - - typedef void (CreateDerivationAndRealiseGoal::*GoalState)(); - GoalState state; - - /** - * The final output paths of the build. - * - * - For input-addressed derivations, always the precomputed paths - * - * - For content-addressed derivations, calcuated from whatever the - * hash ends up being. (Note that fixed outputs derivations that - * produce the "wrong" output still install that data under its - * true content-address.) - */ - OutputPathMap finalOutputs; - - BuildMode buildMode; - - CreateDerivationAndRealiseGoal(ref<SingleDerivedPath> drvReq, - const OutputsSpec & wantedOutputs, Worker & worker, - BuildMode buildMode = bmNormal); - virtual ~CreateDerivationAndRealiseGoal(); - - void timedOut(Error && ex) override; - - std::string key() override; - - void work() override; - - /** - * Add wanted outputs to an already existing derivation goal. - */ - void addWantedOutputs(const OutputsSpec & outputs); - - /** - * The states. - */ - void getDerivation(); - void loadAndBuildDerivation(); - void buildDone(); - - JobCategory jobCategory() const override { - return JobCategory::Administration; - }; -}; - -} diff --git a/src/libstore/build/derivation-goal.cc b/src/libstore/build/derivation-goal.cc index 6472ecd99..83c0a3135 100644 --- a/src/libstore/build/derivation-goal.cc +++ b/src/libstore/build/derivation-goal.cc @@ -71,7 +71,7 @@ DerivationGoal::DerivationGoal(const StorePath & drvPath, , wantedOutputs(wantedOutputs) , buildMode(buildMode) { - state = &DerivationGoal::loadDerivation; + state = &DerivationGoal::getDerivation; name = fmt( "building of '%s' from .drv file", DerivedPath::Built { makeConstantStorePathRef(drvPath), wantedOutputs }.to_string(worker.store)); @@ -164,6 +164,24 @@ void DerivationGoal::addWantedOutputs(const OutputsSpec & outputs) } +void DerivationGoal::getDerivation() +{ + trace("init"); + + /* The first thing to do is to make sure that the derivation + exists. If it doesn't, it may be created through a + substitute. */ + if (buildMode == bmNormal && worker.evalStore.isValidPath(drvPath)) { + loadDerivation(); + return; + } + + addWaitee(upcast_goal(worker.makePathSubstitutionGoal(drvPath))); + + state = &DerivationGoal::loadDerivation; +} + + void DerivationGoal::loadDerivation() { trace("loading derivation"); @@ -1498,24 +1516,23 @@ void DerivationGoal::waiteeDone(GoalPtr waitee, ExitCode result) if (!useDerivation) return; auto & fullDrv = *dynamic_cast<Derivation *>(drv.get()); - std::optional info = tryGetConcreteDrvGoal(waitee); - if (!info) return; - const auto & [dg, drvReq] = *info; + auto * dg = dynamic_cast<DerivationGoal *>(&*waitee); + if (!dg) return; - auto * nodeP = fullDrv.inputDrvs.findSlot(drvReq.get()); + auto * nodeP = fullDrv.inputDrvs.findSlot(DerivedPath::Opaque { .path = dg->drvPath }); if (!nodeP) return; auto & outputs = nodeP->value; for (auto & outputName : outputs) { - auto buildResult = dg.get().getBuildResult(DerivedPath::Built { - .drvPath = makeConstantStorePathRef(dg.get().drvPath), + auto buildResult = dg->getBuildResult(DerivedPath::Built { + .drvPath = makeConstantStorePathRef(dg->drvPath), .outputs = OutputsSpec::Names { outputName }, }); if (buildResult.success()) { auto i = buildResult.builtOutputs.find(outputName); if (i != buildResult.builtOutputs.end()) inputDrvOutputs.insert_or_assign( - { dg.get().drvPath, outputName }, + { dg->drvPath, outputName }, i->second.outPath); } } diff --git a/src/libstore/build/derivation-goal.hh b/src/libstore/build/derivation-goal.hh index 62b122c27..ddb5ee1e3 100644 --- a/src/libstore/build/derivation-goal.hh +++ b/src/libstore/build/derivation-goal.hh @@ -52,10 +52,6 @@ struct InitialOutput { /** * A goal for building some or all of the outputs of a derivation. - * - * The derivation must already be present, either in the store in a drv - * or in memory. If the derivation itself needs to be gotten first, a - * `CreateDerivationAndRealiseGoal` goal must be used instead. */ struct DerivationGoal : public Goal { @@ -235,6 +231,7 @@ struct DerivationGoal : public Goal /** * The states. */ + void getDerivation(); void loadDerivation(); void haveDerivation(); void outputsSubstitutionTried(); diff --git a/src/libstore/build/entry-points.cc b/src/libstore/build/entry-points.cc index f0f0e5519..13ff22f45 100644 --- a/src/libstore/build/entry-points.cc +++ b/src/libstore/build/entry-points.cc @@ -1,6 +1,5 @@ #include "worker.hh" #include "substitution-goal.hh" -#include "create-derivation-and-realise-goal.hh" #include "derivation-goal.hh" #include "local-store.hh" @@ -16,7 +15,7 @@ void Store::buildPaths(const std::vector<DerivedPath> & reqs, BuildMode buildMod worker.run(goals); - StringSet failed; + StorePathSet failed; std::optional<Error> ex; for (auto & i : goals) { if (i->ex) { @@ -26,10 +25,10 @@ void Store::buildPaths(const std::vector<DerivedPath> & reqs, BuildMode buildMod ex = std::move(i->ex); } if (i->exitCode != Goal::ecSuccess) { - if (auto i2 = dynamic_cast<CreateDerivationAndRealiseGoal *>(i.get())) - failed.insert(i2->drvReq->to_string(*this)); + if (auto i2 = dynamic_cast<DerivationGoal *>(i.get())) + failed.insert(i2->drvPath); else if (auto i2 = dynamic_cast<PathSubstitutionGoal *>(i.get())) - failed.insert(printStorePath(i2->storePath)); + failed.insert(i2->storePath); } } @@ -38,7 +37,7 @@ void Store::buildPaths(const std::vector<DerivedPath> & reqs, BuildMode buildMod throw std::move(*ex); } else if (!failed.empty()) { if (ex) logError(ex->info()); - throw Error(worker.failingExitStatus(), "build of %s failed", concatStringsSep(", ", quoteStrings(failed))); + throw Error(worker.failingExitStatus(), "build of %s failed", showPaths(failed)); } } diff --git a/src/libstore/build/goal.hh b/src/libstore/build/goal.hh index 01d3c3491..9af083230 100644 --- a/src/libstore/build/goal.hh +++ b/src/libstore/build/goal.hh @@ -49,16 +49,6 @@ enum struct JobCategory { * A substitution an arbitrary store object; it will use network resources. */ Substitution, - /** - * A goal that does no "real" work by itself, and just exists to depend on - * other goals which *do* do real work. These goals therefore are not - * limited. - * - * These goals cannot infinitely create themselves, so there is no risk of - * a "fork bomb" type situation (which would be a problem even though the - * goal do no real work) either. - */ - Administration, }; struct Goal : public std::enable_shared_from_this<Goal> diff --git a/src/libstore/build/worker.cc b/src/libstore/build/worker.cc index b4a634e7b..37cb86b91 100644 --- a/src/libstore/build/worker.cc +++ b/src/libstore/build/worker.cc @@ -2,7 +2,6 @@ #include "worker.hh" #include "substitution-goal.hh" #include "drv-output-substitution-goal.hh" -#include "create-derivation-and-realise-goal.hh" #include "local-derivation-goal.hh" #include "hook-instance.hh" @@ -42,24 +41,6 @@ Worker::~Worker() } -std::shared_ptr<CreateDerivationAndRealiseGoal> Worker::makeCreateDerivationAndRealiseGoal( - ref<SingleDerivedPath> drvReq, - const OutputsSpec & wantedOutputs, - BuildMode buildMode) -{ - std::weak_ptr<CreateDerivationAndRealiseGoal> & goal_weak = outerDerivationGoals.ensureSlot(*drvReq).value; - std::shared_ptr<CreateDerivationAndRealiseGoal> goal = goal_weak.lock(); - if (!goal) { - goal = std::make_shared<CreateDerivationAndRealiseGoal>(drvReq, wantedOutputs, *this, buildMode); - goal_weak = goal; - wakeUp(goal); - } else { - goal->addWantedOutputs(wantedOutputs); - } - return goal; -} - - std::shared_ptr<DerivationGoal> Worker::makeDerivationGoalCommon( const StorePath & drvPath, const OutputsSpec & wantedOutputs, @@ -130,7 +111,10 @@ GoalPtr Worker::makeGoal(const DerivedPath & req, BuildMode buildMode) { return std::visit(overloaded { [&](const DerivedPath::Built & bfd) -> GoalPtr { - return makeCreateDerivationAndRealiseGoal(bfd.drvPath, bfd.outputs, buildMode); + if (auto bop = std::get_if<DerivedPath::Opaque>(&*bfd.drvPath)) + return makeDerivationGoal(bop->path, bfd.outputs, buildMode); + else + throw UnimplementedError("Building dynamic derivations in one shot is not yet implemented."); }, [&](const DerivedPath::Opaque & bo) -> GoalPtr { return makePathSubstitutionGoal(bo.path, buildMode == bmRepair ? Repair : NoRepair); @@ -139,46 +123,24 @@ GoalPtr Worker::makeGoal(const DerivedPath & req, BuildMode buildMode) } -template<typename K, typename V, typename F> -static void cullMap(std::map<K, V> & goalMap, F f) -{ - for (auto i = goalMap.begin(); i != goalMap.end();) - if (!f(i->second)) - i = goalMap.erase(i); - else ++i; -} - - template<typename K, typename G> static void removeGoal(std::shared_ptr<G> goal, std::map<K, std::weak_ptr<G>> & goalMap) { /* !!! inefficient */ - cullMap(goalMap, [&](const std::weak_ptr<G> & gp) -> bool { - return gp.lock() != goal; - }); -} - -template<typename K> -static void removeGoal(std::shared_ptr<CreateDerivationAndRealiseGoal> goal, std::map<K, DerivedPathMap<std::weak_ptr<CreateDerivationAndRealiseGoal>>::ChildNode> & goalMap); - -template<typename K> -static void removeGoal(std::shared_ptr<CreateDerivationAndRealiseGoal> goal, std::map<K, DerivedPathMap<std::weak_ptr<CreateDerivationAndRealiseGoal>>::ChildNode> & goalMap) -{ - /* !!! inefficient */ - cullMap(goalMap, [&](DerivedPathMap<std::weak_ptr<CreateDerivationAndRealiseGoal>>::ChildNode & node) -> bool { - if (node.value.lock() == goal) - node.value.reset(); - removeGoal(goal, node.childMap); - return !node.value.expired() || !node.childMap.empty(); - }); + for (auto i = goalMap.begin(); + i != goalMap.end(); ) + if (i->second.lock() == goal) { + auto j = i; ++j; + goalMap.erase(i); + i = j; + } + else ++i; } void Worker::removeGoal(GoalPtr goal) { - if (auto drvGoal = std::dynamic_pointer_cast<CreateDerivationAndRealiseGoal>(goal)) - nix::removeGoal(drvGoal, outerDerivationGoals.map); - else if (auto drvGoal = std::dynamic_pointer_cast<DerivationGoal>(goal)) + if (auto drvGoal = std::dynamic_pointer_cast<DerivationGoal>(goal)) nix::removeGoal(drvGoal, derivationGoals); else if (auto subGoal = std::dynamic_pointer_cast<PathSubstitutionGoal>(goal)) nix::removeGoal(subGoal, substitutionGoals); @@ -236,19 +198,8 @@ void Worker::childStarted(GoalPtr goal, const std::set<int> & fds, child.respectTimeouts = respectTimeouts; children.emplace_back(child); if (inBuildSlot) { - switch (goal->jobCategory()) { - case JobCategory::Substitution: - nrSubstitutions++; - break; - case JobCategory::Build: - nrLocalBuilds++; - break; - case JobCategory::Administration: - /* Intentionally not limited, see docs */ - break; - default: - abort(); - } + if (goal->jobCategory() == JobCategory::Substitution) nrSubstitutions++; + else nrLocalBuilds++; } } @@ -260,20 +211,12 @@ void Worker::childTerminated(Goal * goal, bool wakeSleepers) if (i == children.end()) return; if (i->inBuildSlot) { - switch (goal->jobCategory()) { - case JobCategory::Substitution: + if (goal->jobCategory() == JobCategory::Substitution) { assert(nrSubstitutions > 0); nrSubstitutions--; - break; - case JobCategory::Build: + } else { assert(nrLocalBuilds > 0); nrLocalBuilds--; - break; - case JobCategory::Administration: - /* Intentionally not limited, see docs */ - break; - default: - abort(); } } @@ -324,9 +267,9 @@ void Worker::run(const Goals & _topGoals) for (auto & i : _topGoals) { topGoals.insert(i); - if (auto goal = dynamic_cast<CreateDerivationAndRealiseGoal *>(i.get())) { + if (auto goal = dynamic_cast<DerivationGoal *>(i.get())) { topPaths.push_back(DerivedPath::Built { - .drvPath = goal->drvReq, + .drvPath = makeConstantStorePathRef(goal->drvPath), .outputs = goal->wantedOutputs, }); } else if (auto goal = dynamic_cast<PathSubstitutionGoal *>(i.get())) { @@ -589,19 +532,4 @@ GoalPtr upcast_goal(std::shared_ptr<DrvOutputSubstitutionGoal> subGoal) return subGoal; } -GoalPtr upcast_goal(std::shared_ptr<DerivationGoal> subGoal) -{ - return subGoal; -} - -std::optional<std::pair<std::reference_wrapper<const DerivationGoal>, std::reference_wrapper<const SingleDerivedPath>>> tryGetConcreteDrvGoal(GoalPtr waitee) -{ - auto * odg = dynamic_cast<CreateDerivationAndRealiseGoal *>(&*waitee); - if (!odg) return std::nullopt; - return {{ - std::cref(*odg->concreteDrvGoal), - std::cref(*odg->drvReq), - }}; -} - } diff --git a/src/libstore/build/worker.hh b/src/libstore/build/worker.hh index 6f6d25d7d..23ad87914 100644 --- a/src/libstore/build/worker.hh +++ b/src/libstore/build/worker.hh @@ -4,7 +4,6 @@ #include "types.hh" #include "lock.hh" #include "store-api.hh" -#include "derived-path-map.hh" #include "goal.hh" #include "realisation.hh" @@ -14,7 +13,6 @@ namespace nix { /* Forward definition. */ -struct CreateDerivationAndRealiseGoal; struct DerivationGoal; struct PathSubstitutionGoal; class DrvOutputSubstitutionGoal; @@ -33,26 +31,10 @@ class DrvOutputSubstitutionGoal; */ GoalPtr upcast_goal(std::shared_ptr<PathSubstitutionGoal> subGoal); GoalPtr upcast_goal(std::shared_ptr<DrvOutputSubstitutionGoal> subGoal); -GoalPtr upcast_goal(std::shared_ptr<DerivationGoal> subGoal); typedef std::chrono::time_point<std::chrono::steady_clock> steady_time_point; /** - * The current implementation of impure derivations has - * `DerivationGoal`s accumulate realisations from their waitees. - * Unfortunately, `DerivationGoal`s don't directly depend on other - * goals, but instead depend on `CreateDerivationAndRealiseGoal`s. - * - * We try not to share any of the details of any goal type with any - * other, for sake of modularity and quicker rebuilds. This means we - * cannot "just" downcast and fish out the field. So as an escape hatch, - * we have made the function, written in `worker.cc` where all the goal - * types are visible, and use it instead. - */ - -std::optional<std::pair<std::reference_wrapper<const DerivationGoal>, std::reference_wrapper<const SingleDerivedPath>>> tryGetConcreteDrvGoal(GoalPtr waitee); - -/** * A mapping used to remember for each child process to what goal it * belongs, and file descriptors for receiving log data and output * path creation commands. @@ -119,9 +101,6 @@ private: * Maps used to prevent multiple instantiations of a goal for the * same derivation / path. */ - - DerivedPathMap<std::weak_ptr<CreateDerivationAndRealiseGoal>> outerDerivationGoals; - std::map<StorePath, std::weak_ptr<DerivationGoal>> derivationGoals; std::map<StorePath, std::weak_ptr<PathSubstitutionGoal>> substitutionGoals; std::map<DrvOutput, std::weak_ptr<DrvOutputSubstitutionGoal>> drvOutputSubstitutionGoals; @@ -209,9 +188,6 @@ public: * @ref DerivationGoal "derivation goal" */ private: - std::shared_ptr<CreateDerivationAndRealiseGoal> makeCreateDerivationAndRealiseGoal( - ref<SingleDerivedPath> drvPath, - const OutputsSpec & wantedOutputs, BuildMode buildMode = bmNormal); std::shared_ptr<DerivationGoal> makeDerivationGoalCommon( const StorePath & drvPath, const OutputsSpec & wantedOutputs, std::function<std::shared_ptr<DerivationGoal>()> mkDrvGoal); diff --git a/src/libstore/derived-path-map.cc b/src/libstore/derived-path-map.cc index 437b6a71a..5982c04b3 100644 --- a/src/libstore/derived-path-map.cc +++ b/src/libstore/derived-path-map.cc @@ -51,11 +51,8 @@ typename DerivedPathMap<V>::ChildNode * DerivedPathMap<V>::findSlot(const Single // instantiations -#include "create-derivation-and-realise-goal.hh" namespace nix { -template struct DerivedPathMap<std::weak_ptr<CreateDerivationAndRealiseGoal>>; - GENERATE_CMP_EXT( template<>, DerivedPathMap<std::set<std::string>>::ChildNode, diff --git a/src/libstore/derived-path-map.hh b/src/libstore/derived-path-map.hh index 4a2c90733..4d72b301e 100644 --- a/src/libstore/derived-path-map.hh +++ b/src/libstore/derived-path-map.hh @@ -20,11 +20,8 @@ namespace nix { * * @param V A type to instantiate for each output. It should probably * should be an "optional" type so not every interior node has to have a - * value. For example, the scheduler uses - * `DerivedPathMap<std::weak_ptr<CreateDerivationAndRealiseGoal>>` to - * remember which goals correspond to which outputs. `* const Something` - * or `std::optional<Something>` would also be good choices for - * "optional" types. + * value. `* const Something` or `std::optional<Something>` would be + * good choices for "optional" types. */ template<typename V> struct DerivedPathMap { diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index 26c87391c..516cbef83 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -776,7 +776,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results) } }; - /* Synchronisation point for testing, see tests/gc-concurrent.sh. */ + /* Synchronisation point for testing, see tests/functional/gc-concurrent.sh. */ if (auto p = getEnv("_NIX_TEST_GC_SYNC")) readFile(*p); diff --git a/src/libstore/globals.cc b/src/libstore/globals.cc index 5a4cb1824..9c25d9868 100644 --- a/src/libstore/globals.cc +++ b/src/libstore/globals.cc @@ -24,6 +24,9 @@ #include "config-impl.hh" +#ifdef __APPLE__ +#include <sys/sysctl.h> +#endif namespace nix { @@ -154,6 +157,29 @@ unsigned int Settings::getDefaultCores() return concurrency; } +#if __APPLE__ +static bool hasVirt() { + + int hasVMM; + int hvSupport; + size_t size; + + size = sizeof(hasVMM); + if (sysctlbyname("kern.hv_vmm_present", &hasVMM, &size, NULL, 0) == 0) { + if (hasVMM) + return false; + } + + // whether the kernel and hardware supports virt + size = sizeof(hvSupport); + if (sysctlbyname("kern.hv_support", &hvSupport, &size, NULL, 0) == 0) { + return hvSupport == 1; + } else { + return false; + } +} +#endif + StringSet Settings::getDefaultSystemFeatures() { /* For backwards compatibility, accept some "features" that are @@ -170,6 +196,11 @@ StringSet Settings::getDefaultSystemFeatures() features.insert("kvm"); #endif + #if __APPLE__ + if (hasVirt()) + features.insert("apple-virt"); + #endif + return features; } diff --git a/src/libstore/globals.hh b/src/libstore/globals.hh index cf10edebd..dba7d78ef 100644 --- a/src/libstore/globals.hh +++ b/src/libstore/globals.hh @@ -708,6 +708,7 @@ public: `kvm` feature. This setting by default includes `kvm` if `/dev/kvm` is accessible, + `apple-virt` if hardware virtualization is available on macOS, and the pseudo-features `nixos-test`, `benchmark` and `big-parallel` that are used in Nixpkgs to route builds to specific machines. )", {}, false}; diff --git a/src/libstore/path-regex.hh b/src/libstore/path-regex.hh index 4f8dc4c1f..a44e6a2eb 100644 --- a/src/libstore/path-regex.hh +++ b/src/libstore/path-regex.hh @@ -3,6 +3,6 @@ namespace nix { -static constexpr std::string_view nameRegexStr = R"([0-9a-zA-Z\+\-\._\?=]+)"; +static constexpr std::string_view nameRegexStr = R"([0-9a-zA-Z\+\-_\?=][0-9a-zA-Z\+\-\._\?=]*)"; } diff --git a/src/libstore/path.cc b/src/libstore/path.cc index 552e83114..3c6b9fc10 100644 --- a/src/libstore/path.cc +++ b/src/libstore/path.cc @@ -11,6 +11,8 @@ static void checkName(std::string_view path, std::string_view name) if (name.size() > StorePath::MaxPathLen) throw BadStorePath("store path '%s' has a name longer than %d characters", path, StorePath::MaxPathLen); + if (name[0] == '.') + throw BadStorePath("store path '%s' starts with illegal character '.'", path); // See nameRegexStr for the definition for (auto c : name) if (!((c >= '0' && c <= '9') diff --git a/src/libstore/tests/derivation.cc b/src/libstore/tests/derivation.cc deleted file mode 100644 index c360c9707..000000000 --- a/src/libstore/tests/derivation.cc +++ /dev/null @@ -1,369 +0,0 @@ -#include <nlohmann/json.hpp> -#include <gtest/gtest.h> - -#include "experimental-features.hh" -#include "derivations.hh" - -#include "tests/libstore.hh" - -namespace nix { - -class DerivationTest : public LibStoreTest -{ -public: - /** - * We set these in tests rather than the regular globals so we don't have - * to worry about race conditions if the tests run concurrently. - */ - ExperimentalFeatureSettings mockXpSettings; -}; - -class CaDerivationTest : public DerivationTest -{ - void SetUp() override - { - mockXpSettings.set("experimental-features", "ca-derivations"); - } -}; - -class DynDerivationTest : public DerivationTest -{ - void SetUp() override - { - mockXpSettings.set("experimental-features", "dynamic-derivations ca-derivations"); - } -}; - -class ImpureDerivationTest : public DerivationTest -{ - void SetUp() override - { - mockXpSettings.set("experimental-features", "impure-derivations"); - } -}; - -TEST_F(DerivationTest, BadATerm_version) { - ASSERT_THROW( - parseDerivation( - *store, - R"(DrvWithVersion("invalid-version",[],[("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv",["cat","dog"])],["/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"],"wasm-sel4","foo",["bar","baz"],[("BIG_BAD","WOLF")]))", - "whatever", - mockXpSettings), - FormatError); -} - -TEST_F(DynDerivationTest, BadATerm_oldVersionDynDeps) { - ASSERT_THROW( - parseDerivation( - *store, - R"(Derive([],[("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv",(["cat","dog"],[("cat",["kitten"]),("goose",["gosling"])]))],["/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"],"wasm-sel4","foo",["bar","baz"],[("BIG_BAD","WOLF")]))", - "dyn-dep-derivation", - mockXpSettings), - FormatError); -} - -#define TEST_JSON(FIXTURE, NAME, STR, VAL, DRV_NAME, OUTPUT_NAME) \ - TEST_F(FIXTURE, DerivationOutput_ ## NAME ## _to_json) { \ - using nlohmann::literals::operator "" _json; \ - ASSERT_EQ( \ - STR ## _json, \ - (DerivationOutput { VAL }).toJSON( \ - *store, \ - DRV_NAME, \ - OUTPUT_NAME)); \ - } \ - \ - TEST_F(FIXTURE, DerivationOutput_ ## NAME ## _from_json) { \ - using nlohmann::literals::operator "" _json; \ - ASSERT_EQ( \ - DerivationOutput { VAL }, \ - DerivationOutput::fromJSON( \ - *store, \ - DRV_NAME, \ - OUTPUT_NAME, \ - STR ## _json, \ - mockXpSettings)); \ - } - -TEST_JSON(DerivationTest, inputAddressed, - R"({ - "path": "/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-drv-name-output-name" - })", - (DerivationOutput::InputAddressed { - .path = store->parseStorePath("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-drv-name-output-name"), - }), - "drv-name", "output-name") - -TEST_JSON(DerivationTest, caFixedFlat, - R"({ - "hashAlgo": "sha256", - "hash": "894517c9163c896ec31a2adbd33c0681fd5f45b2c0ef08a64c92a03fb97f390f", - "path": "/nix/store/rhcg9h16sqvlbpsa6dqm57sbr2al6nzg-drv-name-output-name" - })", - (DerivationOutput::CAFixed { - .ca = { - .method = FileIngestionMethod::Flat, - .hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="), - }, - }), - "drv-name", "output-name") - -TEST_JSON(DerivationTest, caFixedNAR, - R"({ - "hashAlgo": "r:sha256", - "hash": "894517c9163c896ec31a2adbd33c0681fd5f45b2c0ef08a64c92a03fb97f390f", - "path": "/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-drv-name-output-name" - })", - (DerivationOutput::CAFixed { - .ca = { - .method = FileIngestionMethod::Recursive, - .hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="), - }, - }), - "drv-name", "output-name") - -TEST_JSON(DynDerivationTest, caFixedText, - R"({ - "hashAlgo": "text:sha256", - "hash": "894517c9163c896ec31a2adbd33c0681fd5f45b2c0ef08a64c92a03fb97f390f", - "path": "/nix/store/6s1zwabh956jvhv4w9xcdb5jiyanyxg1-drv-name-output-name" - })", - (DerivationOutput::CAFixed { - .ca = { - .hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="), - }, - }), - "drv-name", "output-name") - -TEST_JSON(CaDerivationTest, caFloating, - R"({ - "hashAlgo": "r:sha256" - })", - (DerivationOutput::CAFloating { - .method = FileIngestionMethod::Recursive, - .hashType = htSHA256, - }), - "drv-name", "output-name") - -TEST_JSON(DerivationTest, deferred, - R"({ })", - DerivationOutput::Deferred { }, - "drv-name", "output-name") - -TEST_JSON(ImpureDerivationTest, impure, - R"({ - "hashAlgo": "r:sha256", - "impure": true - })", - (DerivationOutput::Impure { - .method = FileIngestionMethod::Recursive, - .hashType = htSHA256, - }), - "drv-name", "output-name") - -#undef TEST_JSON - -#define TEST_JSON(FIXTURE, NAME, STR, VAL) \ - TEST_F(FIXTURE, Derivation_ ## NAME ## _to_json) { \ - using nlohmann::literals::operator "" _json; \ - ASSERT_EQ( \ - STR ## _json, \ - (VAL).toJSON(*store)); \ - } \ - \ - TEST_F(FIXTURE, Derivation_ ## NAME ## _from_json) { \ - using nlohmann::literals::operator "" _json; \ - ASSERT_EQ( \ - (VAL), \ - Derivation::fromJSON( \ - *store, \ - STR ## _json, \ - mockXpSettings)); \ - } - -#define TEST_ATERM(FIXTURE, NAME, STR, VAL, DRV_NAME) \ - TEST_F(FIXTURE, Derivation_ ## NAME ## _to_aterm) { \ - ASSERT_EQ( \ - STR, \ - (VAL).unparse(*store, false)); \ - } \ - \ - TEST_F(FIXTURE, Derivation_ ## NAME ## _from_aterm) { \ - auto parsed = parseDerivation( \ - *store, \ - STR, \ - DRV_NAME, \ - mockXpSettings); \ - ASSERT_EQ( \ - (VAL).toJSON(*store), \ - parsed.toJSON(*store)); \ - ASSERT_EQ( \ - (VAL), \ - parsed); \ - } - -Derivation makeSimpleDrv(const Store & store) { - Derivation drv; - drv.name = "simple-derivation"; - drv.inputSrcs = { - store.parseStorePath("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"), - }; - drv.inputDrvs = { - .map = { - { - store.parseStorePath("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv"), - { - .value = { - "cat", - "dog", - }, - }, - }, - }, - }; - drv.platform = "wasm-sel4"; - drv.builder = "foo"; - drv.args = { - "bar", - "baz", - }; - drv.env = { - { - "BIG_BAD", - "WOLF", - }, - }; - return drv; -} - -TEST_JSON(DerivationTest, simple, - R"({ - "name": "simple-derivation", - "inputSrcs": [ - "/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1" - ], - "inputDrvs": { - "/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv": { - "dynamicOutputs": {}, - "outputs": [ - "cat", - "dog" - ] - } - }, - "system": "wasm-sel4", - "builder": "foo", - "args": [ - "bar", - "baz" - ], - "env": { - "BIG_BAD": "WOLF" - }, - "outputs": {} - })", - makeSimpleDrv(*store)) - -TEST_ATERM(DerivationTest, simple, - R"(Derive([],[("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv",["cat","dog"])],["/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"],"wasm-sel4","foo",["bar","baz"],[("BIG_BAD","WOLF")]))", - makeSimpleDrv(*store), - "simple-derivation") - -Derivation makeDynDepDerivation(const Store & store) { - Derivation drv; - drv.name = "dyn-dep-derivation"; - drv.inputSrcs = { - store.parseStorePath("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"), - }; - drv.inputDrvs = { - .map = { - { - store.parseStorePath("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv"), - DerivedPathMap<StringSet>::ChildNode { - .value = { - "cat", - "dog", - }, - .childMap = { - { - "cat", - DerivedPathMap<StringSet>::ChildNode { - .value = { - "kitten", - }, - }, - }, - { - "goose", - DerivedPathMap<StringSet>::ChildNode { - .value = { - "gosling", - }, - }, - }, - }, - }, - }, - }, - }; - drv.platform = "wasm-sel4"; - drv.builder = "foo"; - drv.args = { - "bar", - "baz", - }; - drv.env = { - { - "BIG_BAD", - "WOLF", - }, - }; - return drv; -} - -TEST_JSON(DynDerivationTest, dynDerivationDeps, - R"({ - "name": "dyn-dep-derivation", - "inputSrcs": [ - "/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1" - ], - "inputDrvs": { - "/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv": { - "dynamicOutputs": { - "cat": { - "dynamicOutputs": {}, - "outputs": ["kitten"] - }, - "goose": { - "dynamicOutputs": {}, - "outputs": ["gosling"] - } - }, - "outputs": [ - "cat", - "dog" - ] - } - }, - "system": "wasm-sel4", - "builder": "foo", - "args": [ - "bar", - "baz" - ], - "env": { - "BIG_BAD": "WOLF" - }, - "outputs": {} - })", - makeDynDepDerivation(*store)) - -TEST_ATERM(DynDerivationTest, dynDerivationDeps, - R"(DrvWithVersion("xp-dyn-drv",[],[("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv",(["cat","dog"],[("cat",["kitten"]),("goose",["gosling"])]))],["/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"],"wasm-sel4","foo",["bar","baz"],[("BIG_BAD","WOLF")]))", - makeDynDepDerivation(*store), - "dyn-dep-derivation") - -#undef TEST_JSON -#undef TEST_ATERM - -} diff --git a/src/libstore/tests/derived-path.cc b/src/libstore/tests/derived-path.cc deleted file mode 100644 index 3fa3c0801..000000000 --- a/src/libstore/tests/derived-path.cc +++ /dev/null @@ -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 - -} diff --git a/src/libstore/tests/derived-path.hh b/src/libstore/tests/derived-path.hh deleted file mode 100644 index 98d61f228..000000000 --- a/src/libstore/tests/derived-path.hh +++ /dev/null @@ -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(); -}; - -} diff --git a/src/libstore/tests/downstream-placeholder.cc b/src/libstore/tests/downstream-placeholder.cc deleted file mode 100644 index fd29530ac..000000000 --- a/src/libstore/tests/downstream-placeholder.cc +++ /dev/null @@ -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"); -} - -} diff --git a/src/libstore/tests/libstore.hh b/src/libstore/tests/libstore.hh deleted file mode 100644 index ef93457b5..000000000 --- a/src/libstore/tests/libstore.hh +++ /dev/null @@ -1,26 +0,0 @@ -#pragma once -///@file - -#include <gtest/gtest.h> -#include <gmock/gmock.h> - -#include "store-api.hh" - -namespace nix { - -class LibStoreTest : public ::testing::Test { - public: - static void SetUpTestSuite() { - initLibStore(); - } - - protected: - LibStoreTest() - : store(openStore("dummy://")) - { } - - ref<Store> store; -}; - - -} /* namespace nix */ diff --git a/src/libstore/tests/local.mk b/src/libstore/tests/local.mk deleted file mode 100644 index 03becc7d1..000000000 --- a/src/libstore/tests/local.mk +++ /dev/null @@ -1,29 +0,0 @@ -check: libstore-tests-exe_RUN - -programs += libstore-tests-exe - -libstore-tests-exe_NAME = libnixstore-tests - -libstore-tests-exe_DIR := $(d) - -libstore-tests-exe_INSTALL_DIR := - -libstore-tests-exe_LIBS = libstore-tests - -libstore-tests-exe_LDFLAGS := $(GTEST_LIBS) - -libraries += libstore-tests - -libstore-tests_NAME = libnixstore-tests - -libstore-tests_DIR := $(d) - -libstore-tests_INSTALL_DIR := - -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) diff --git a/src/libstore/tests/machines.cc b/src/libstore/tests/machines.cc deleted file mode 100644 index f51052b14..000000000 --- a/src/libstore/tests/machines.cc +++ /dev/null @@ -1,169 +0,0 @@ -#include "machines.hh" -#include "globals.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); -} diff --git a/src/libstore/tests/nar-info-disk-cache.cc b/src/libstore/tests/nar-info-disk-cache.cc deleted file mode 100644 index b4bdb8329..000000000 --- a/src/libstore/tests/nar-info-disk-cache.cc +++ /dev/null @@ -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); - // } - } -} - -} diff --git a/src/libstore/tests/outputs-spec.cc b/src/libstore/tests/outputs-spec.cc deleted file mode 100644 index 952945185..000000000 --- a/src/libstore/tests/outputs-spec.cc +++ /dev/null @@ -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 - -} diff --git a/src/libstore/tests/outputs-spec.hh b/src/libstore/tests/outputs-spec.hh deleted file mode 100644 index ded331b33..000000000 --- a/src/libstore/tests/outputs-spec.hh +++ /dev/null @@ -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(); -}; - -} diff --git a/src/libstore/tests/path.cc b/src/libstore/tests/path.cc deleted file mode 100644 index efa35ef2b..000000000 --- a/src/libstore/tests/path.cc +++ /dev/null @@ -1,157 +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") - -#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: - 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 - -} diff --git a/src/libstore/tests/path.hh b/src/libstore/tests/path.hh deleted file mode 100644 index 21cb62310..000000000 --- a/src/libstore/tests/path.hh +++ /dev/null @@ -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(); -}; - -} diff --git a/src/libstore/tests/references.cc b/src/libstore/tests/references.cc deleted file mode 100644 index d91d1cedd..000000000 --- a/src/libstore/tests/references.cc +++ /dev/null @@ -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})); - } -} - -} diff --git a/src/libstore/tests/test-data/machines.bad_format b/src/libstore/tests/test-data/machines.bad_format deleted file mode 100644 index 7255a1216..000000000 --- a/src/libstore/tests/test-data/machines.bad_format +++ /dev/null @@ -1 +0,0 @@ -nix@scratchy.labs.cs.uu.nl - - eight diff --git a/src/libstore/tests/test-data/machines.valid b/src/libstore/tests/test-data/machines.valid deleted file mode 100644 index 1a6c8017c..000000000 --- a/src/libstore/tests/test-data/machines.valid +++ /dev/null @@ -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= |