1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-07-07 14:21:48 +02:00

Unit tests and external libraries

This commit is contained in:
John Ericson 2024-06-27 11:28:08 -04:00
parent 4fa8068b78
commit 17a8c2bfce
215 changed files with 873 additions and 461 deletions

View file

@ -1,21 +0,0 @@
libraries += libstore-test-support
libstore-test-support_NAME = libnixstore-test-support
libstore-test-support_DIR := $(d)
ifeq ($(INSTALL_UNIT_TESTS), yes)
libstore-test-support_INSTALL_DIR := $(checklibdir)
else
libstore-test-support_INSTALL_DIR :=
endif
libstore-test-support_SOURCES := $(wildcard $(d)/tests/*.cc)
libstore-test-support_CXXFLAGS += $(libstore-tests_EXTRA_INCLUDES)
libstore-test-support_LIBS = \
libutil-test-support \
libstore libutil
libstore-test-support_LDFLAGS := $(THREAD_LDFLAGS) -lrapidcheck

View file

@ -1,57 +0,0 @@
#include <regex>
#include <rapidcheck.h>
#include "tests/derived-path.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);
}
}
}

View file

@ -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();
};
}

View file

@ -1,34 +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(false);
}
protected:
LibStoreTest()
: store(openStore({
.variant =
StoreReference::Specified{
.scheme = "dummy",
},
.params = {},
}))
{
}
ref<Store> store;
};
} /* namespace nix */

View file

@ -1,66 +0,0 @@
#pragma once
///@file
#include "tests/nix_api_util.hh"
#include "file-system.hh"
#include "nix_api_store.h"
#include "nix_api_store_internal.h"
#include <filesystem>
#include <gtest/gtest.h>
namespace fs = std::filesystem;
namespace nixC {
class nix_api_store_test : public nix_api_util_context
{
public:
nix_api_store_test()
{
nix_libstore_init(ctx);
init_local_store();
};
~nix_api_store_test() override
{
nix_store_free(store);
for (auto & path : fs::recursive_directory_iterator(nixDir)) {
fs::permissions(path, fs::perms::owner_all);
}
fs::remove_all(nixDir);
}
Store * store;
std::string nixDir;
std::string nixStoreDir;
protected:
void init_local_store()
{
#ifdef _WIN32
// no `mkdtemp` with MinGW
auto tmpl = nix::defaultTempDir() + "/tests_nix-store.";
for (size_t i = 0; true; ++i) {
nixDir = tmpl + std::string { i };
if (fs::create_directory(nixDir)) break;
}
#else
auto tmpl = nix::defaultTempDir() + "/tests_nix-store.XXXXXX";
nixDir = mkdtemp((char *) tmpl.c_str());
#endif
nixStoreDir = nixDir + "/my_nix_store";
// Options documented in `nix help-stores`
const char * p1[] = {"store", nixStoreDir.c_str()};
const char * p2[] = {"state", (new std::string(nixDir + "/my_state"))->c_str()};
const char * p3[] = {"log", (new std::string(nixDir + "/my_log"))->c_str()};
const char ** params[] = {p1, p2, p3, nullptr};
store = nix_store_open(ctx, "local", params);
}
};
}

View file

@ -1,24 +0,0 @@
#include "tests/outputs-spec.hh"
#include <rapidcheck.h>
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);
}
}
}

View file

@ -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();
};
}

View file

@ -1,80 +0,0 @@
#include <rapidcheck/gen/Arbitrary.h>
#include <regex>
#include <rapidcheck.h>
#include "path-regex.hh"
#include "store-api.hh"
#include "tests/hash.hh"
#include "tests/path.hh"
namespace nix {
void showValue(const StorePath & p, std::ostream & os)
{
os << p.to_string();
}
}
namespace rc {
using namespace nix;
Gen<char> storePathChar()
{
return rc::gen::apply([](uint8_t i) -> char {
switch (i) {
case 0 ... 9:
return '0' + i;
case 10 ... 35:
return 'A' + (i - 10);
case 36 ... 61:
return 'a' + (i - 36);
case 62:
return '+';
case 63:
return '-';
case 64:
return '.';
case 65:
return '_';
case 66:
return '?';
case 67:
return '=';
default:
assert(false);
}
},
gen::inRange<uint8_t>(0, 10 + 2 * 26 + 6));
}
Gen<StorePathName> Arbitrary<StorePathName>::arbitrary()
{
return gen::construct<StorePathName>(
gen::suchThat(
gen::container<std::string>(storePathChar()),
[](const std::string & s) {
return
!( s == ""
|| s == "."
|| s == ".."
|| s.starts_with(".-")
|| s.starts_with("..-")
);
}
)
);
}
Gen<StorePath> Arbitrary<StorePath>::arbitrary()
{
return
gen::construct<StorePath>(
gen::arbitrary<Hash>(),
gen::apply([](StorePathName n){ return n.name; }, gen::arbitrary<StorePathName>())
);
}
} // namespace rc

View file

@ -1,32 +0,0 @@
#pragma once
///@file
#include <rapidcheck/gen/Arbitrary.h>
#include <path.hh>
namespace nix {
struct StorePathName {
std::string name;
};
// For rapidcheck
void showValue(const StorePath & p, std::ostream & os);
}
namespace rc {
using namespace nix;
template<>
struct Arbitrary<StorePathName> {
static Gen<StorePathName> arbitrary();
};
template<>
struct Arbitrary<StorePath> {
static Gen<StorePath> arbitrary();
};
}

View file

@ -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() + "/" + 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); \
}
}