More property tests

Also put proper comparison methods on `DerivedPath` and
`NixStringContextElem`, which is needed for the tests but good in
general.
This commit is contained in:
John Ericson 2023-01-29 13:52:38 -05:00
parent ec0c0efec6
commit ecd3e4ebd7
15 changed files with 279 additions and 24 deletions

View file

@ -14,6 +14,6 @@ libexpr-tests_SOURCES := \
libexpr-tests_CXXFLAGS += -I src/libexpr -I src/libutil -I src/libstore -I src/libexpr/tests
libexpr-tests_LIBS = libstore-tests libexpr libutil libstore libfetchers
libexpr-tests_LIBS = libstore-tests libutils-tests libexpr libutil libstore libfetchers
libexpr-tests_LDFLAGS := $(GTEST_LIBS) -lgmock

View file

@ -1,6 +1,10 @@
#include "value/context.hh"
#include <nlohmann/json.hpp>
#include <gtest/gtest.h>
#include <rapidcheck/gtest.h>
#include "tests/path.hh"
#include "tests/libexpr.hh"
#include "tests/value/context.hh"
namespace nix {
@ -70,3 +74,39 @@ TEST_F(NixStringContextElemTest, built) {
}
}
namespace rc {
using namespace nix;
Gen<NixStringContextElem> Arbitrary<NixStringContextElem>::arbitrary()
{
switch (*gen::inRange<uint8_t>(0, 2)) {
case 0:
return gen::just((NixStringContextElem) NixStringContextElem::Opaque {
.path = *gen::arbitrary<StorePath>(),
});
case 1:
return gen::just((NixStringContextElem) NixStringContextElem::DrvDeep {
.drvPath = *gen::arbitrary<StorePath>(),
});
default:
return gen::just((NixStringContextElem) NixStringContextElem::Built {
.drvPath = *gen::arbitrary<StorePath>(),
.output = (*gen::arbitrary<StorePathName>()).name,
});
}
}
}
namespace nix {
RC_GTEST_FIXTURE_PROP(
NixStringContextElemTest,
prop_round_rip,
(const NixStringContextElem & o))
{
RC_ASSERT(o == NixStringContextElem::parse(store(), o.to_string(store())));
}
}

View file

@ -0,0 +1,15 @@
#pragma once
#include <rapidcheck/gen/Arbitrary.h>
#include <value/context.hh>
namespace rc {
using namespace nix;
template<>
struct Arbitrary<NixStringContextElem> {
static Gen<NixStringContextElem> arbitrary();
};
}

View file

@ -1,9 +1,10 @@
#pragma once
#include "util.hh"
#include "comparator.hh"
#include "path.hh"
#include <optional>
#include <variant>
#include <nlohmann/json_fwd.hpp>
@ -31,7 +32,9 @@ class Store;
Encoded as just the path: <path>.
*/
struct NixStringContextElem_Opaque {
StorePath path;
StorePath path;
GENERATE_CMP(NixStringContextElem_Opaque, me->path);
};
/* Path to a derivation and its entire build closure.
@ -43,7 +46,9 @@ struct NixStringContextElem_Opaque {
Encoded in the form =<drvPath>.
*/
struct NixStringContextElem_DrvDeep {
StorePath drvPath;
StorePath drvPath;
GENERATE_CMP(NixStringContextElem_DrvDeep, me->drvPath);
};
/* Derivation output.
@ -51,8 +56,10 @@ struct NixStringContextElem_DrvDeep {
Encoded in the form !<output>!<drvPath>.
*/
struct NixStringContextElem_Built {
StorePath drvPath;
std::string output;
StorePath drvPath;
std::string output;
GENERATE_CMP(NixStringContextElem_Built, me->drvPath, me->output);
};
using _NixStringContextElem_Raw = std::variant<

View file

@ -4,8 +4,9 @@
#include "path.hh"
#include "realisation.hh"
#include "outputs-spec.hh"
#include "comparator.hh"
#include <optional>
#include <variant>
#include <nlohmann/json_fwd.hpp>
@ -27,8 +28,7 @@ struct DerivedPathOpaque {
std::string to_string(const Store & store) const;
static DerivedPathOpaque parse(const Store & store, std::string_view);
bool operator < (const DerivedPathOpaque & b) const
{ return path < b.path; }
GENERATE_CMP(DerivedPathOpaque, me->path);
};
/**
@ -51,8 +51,7 @@ struct DerivedPathBuilt {
static DerivedPathBuilt parse(const Store & store, std::string_view, std::string_view);
nlohmann::json toJSON(ref<Store> store) const;
bool operator < (const DerivedPathBuilt & b) const
{ return std::make_pair(drvPath, outputs) < std::make_pair(b.drvPath, b.outputs); }
GENERATE_CMP(DerivedPathBuilt, me->drvPath, me->outputs);
};
using _DerivedPathRaw = std::variant<
@ -96,6 +95,8 @@ struct BuiltPathBuilt {
nlohmann::json toJSON(ref<Store> store) const;
static BuiltPathBuilt parse(const Store & store, std::string_view);
GENERATE_CMP(BuiltPathBuilt, me->drvPath, me->outputs);
};
using _BuiltPathRaw = std::variant<

View file

@ -0,0 +1,52 @@
#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> Arbitrary<DerivedPath>::arbitrary()
{
switch (*gen::inRange<uint8_t>(0, 1)) {
case 0:
return gen::just((DerivedPath) DerivedPath::Opaque {
.path = *gen::arbitrary<StorePath>(),
});
default:
return gen::just((DerivedPath) DerivedPath::Built {
.drvPath = *gen::arbitrary<StorePath>(),
.outputs = *gen::arbitrary<OutputsSpec>(),
});
}
}
}
namespace nix {
class DerivedPathTest : public LibStoreTest
{
};
// FIXME: `RC_GTEST_FIXTURE_PROP` isn't calling `SetUpTestSuite` because it is
// no a real fixture.
//
// See https://github.com/emil-e/rapidcheck/blob/master/doc/gtest.md#rc_gtest_fixture_propfixture-name-args
TEST_F(DerivedPathTest, force_init)
{
}
RC_GTEST_FIXTURE_PROP(
DerivedPathTest,
prop_round_rip,
(const DerivedPath & o))
{
RC_ASSERT(o == DerivedPath::parse(*store, o.to_string(*store)));
}
}

View file

@ -0,0 +1,18 @@
#pragma once
#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<DerivedPath> {
static Gen<DerivedPath> arbitrary();
};
}

View file

@ -24,6 +24,6 @@ libstore-tests_SOURCES := $(wildcard $(d)/*.cc)
libstore-tests_CXXFLAGS += -I src/libstore -I src/libutil
libstore-tests_LIBS = libstore libutil
libstore-tests_LIBS = libutil-tests libstore libutil
libstore-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS)

View file

@ -2,6 +2,7 @@
#include <nlohmann/json.hpp>
#include <gtest/gtest.h>
#include <rapidcheck/gtest.h>
namespace nix {
@ -199,3 +200,34 @@ TEST_JSON(ExtendedOutputsSpec, names, R"(["a","b"])", (ExtendedOutputsSpec::Expl
#undef TEST_JSON
}
namespace rc {
using namespace nix;
Gen<OutputsSpec> Arbitrary<OutputsSpec>::arbitrary()
{
switch (*gen::inRange<uint8_t>(0, 1)) {
case 0:
return gen::just((OutputsSpec) OutputsSpec::All { });
default:
return gen::just((OutputsSpec) OutputsSpec::Names {
*gen::nonEmpty(gen::container<StringSet>(gen::map(
gen::arbitrary<StorePathName>(),
[](StorePathName n) { return n.name; }))),
});
}
}
}
namespace nix {
RC_GTEST_PROP(
OutputsSpec,
prop_round_rip,
(const OutputsSpec & o))
{
RC_ASSERT(o == OutputsSpec::parse(o.to_string()));
}
}

View file

@ -0,0 +1,17 @@
#pragma once
#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();
};
}

View file

@ -7,6 +7,7 @@
#include "path-regex.hh"
#include "store-api.hh"
#include "tests/hash.hh"
#include "tests/libstore.hh"
#include "tests/path.hh"
@ -74,12 +75,14 @@ void showValue(const StorePath & p, std::ostream & os) {
namespace rc {
using namespace nix;
Gen<StorePath> Arbitrary<StorePath>::arbitrary()
Gen<StorePathName> Arbitrary<StorePathName>::arbitrary()
{
auto len = *gen::inRange<size_t>(1, StorePath::MaxPathLen);
auto len = *gen::inRange<size_t>(
1,
StorePath::MaxPathLen - std::string_view { HASH_PART }.size());
std::string pre { HASH_PART "-" };
pre.reserve(pre.size() + len);
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)) {
@ -114,7 +117,17 @@ Gen<StorePath> Arbitrary<StorePath>::arbitrary()
}
}
return gen::just(StorePath { pre });
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

View file

@ -1,12 +1,25 @@
#pragma once
#include <rapidcheck.h>
#include <rapidcheck/gen/Arbitrary.h>
#include "path.hh"
#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();

View file

@ -1,5 +1,12 @@
#include "hash.hh"
#include <regex>
#include <nlohmann/json.hpp>
#include <gtest/gtest.h>
#include <rapidcheck/gtest.h>
#include <hash.hh>
#include "tests/hash.hh"
namespace nix {
@ -73,3 +80,16 @@ namespace nix {
"c7d329eeb6dd26545e96e55b874be909");
}
}
namespace rc {
using namespace nix;
Gen<Hash> Arbitrary<Hash>::arbitrary()
{
Hash hash(htSHA1);
for (size_t i = 0; i < hash.hashSize; ++i)
hash.hash[i] = *gen::arbitrary<uint8_t>();
return gen::just(hash);
}
}

15
src/libutil/tests/hash.hh Normal file
View file

@ -0,0 +1,15 @@
#pragma once
#include <rapidcheck/gen/Arbitrary.h>
#include <hash.hh>
namespace rc {
using namespace nix;
template<>
struct Arbitrary<Hash> {
static Gen<Hash> arbitrary();
};
}

View file

@ -2,7 +2,19 @@ check: libutil-tests_RUN
programs += libutil-tests
libutil-tests_NAME := libnixutil-tests
libutil-tests-exe_NAME = libnixutil-tests
libutil-tests-exe_DIR := $(d)
libutil-tests-exe_INSTALL_DIR :=
libutil-tests-exe_LIBS = libutil-tests
libutil-tests-exe_LDFLAGS := $(GTEST_LIBS)
libraries += libutil-tests
libutil-tests_NAME = libnixutil-tests
libutil-tests_DIR := $(d)
@ -10,8 +22,8 @@ libutil-tests_INSTALL_DIR :=
libutil-tests_SOURCES := $(wildcard $(d)/*.cc)
libutil-tests_CXXFLAGS += -I src/libutil -I src/libexpr
libutil-tests_CXXFLAGS += -I src/libutil
libutil-tests_LIBS = libutil
libutil-tests_LDFLAGS := $(GTEST_LIBS)
libutil-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS)