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,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 = ContentAddressMethod::Raw::Text,
.hash = hashString(HashAlgorithm::SHA256, "Derive(...)"),
},
ContentAddress {
.method = ContentAddressMethod::Raw::Flat,
.hash = hashString(HashAlgorithm::SHA1, "blob blob..."),
},
ContentAddress {
.method = ContentAddressMethod::Raw::NixArchive,
.hash = hashString(HashAlgorithm::SHA256, "(...)"),
},
}))
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 = ContentAddressMethod::Raw::Flat,
.hash = hashString(HashAlgorithm::SHA1, "blob blob..."),
},
},
}))
}

View file

@ -1,37 +0,0 @@
#include <gtest/gtest.h>
#include "content-address.hh"
namespace nix {
/* ----------------------------------------------------------------------------
* ContentAddressMethod::parse, ContentAddressMethod::render
* --------------------------------------------------------------------------*/
TEST(ContentAddressMethod, testRoundTripPrintParse_1) {
for (ContentAddressMethod cam : {
ContentAddressMethod::Raw::Text,
ContentAddressMethod::Raw::Flat,
ContentAddressMethod::Raw::NixArchive,
ContentAddressMethod::Raw::Git,
}) {
EXPECT_EQ(ContentAddressMethod::parse(cam.render()), cam);
}
}
TEST(ContentAddressMethod, testRoundTripPrintParse_2) {
for (const std::string_view camS : {
"text",
"flat",
"nar",
"git",
}) {
EXPECT_EQ(ContentAddressMethod::parse(camS).render(), camS);
}
}
TEST(ContentAddressMethod, testParseContentAddressMethodOptException) {
EXPECT_THROW(ContentAddressMethod::parse("narwhal"), UsageError);
}
}

View file

@ -1 +0,0 @@
../../../../functional/derivation/advanced-attributes-defaults.drv

View file

@ -1,22 +0,0 @@
{
"args": [
"-c",
"echo hello > $out"
],
"builder": "/bin/bash",
"env": {
"builder": "/bin/bash",
"name": "advanced-attributes-defaults",
"out": "/nix/store/1qsc7svv43m4dw2prh6mvyf7cai5czji-advanced-attributes-defaults",
"system": "my-system"
},
"inputDrvs": {},
"inputSrcs": [],
"name": "advanced-attributes-defaults",
"outputs": {
"out": {
"path": "/nix/store/1qsc7svv43m4dw2prh6mvyf7cai5czji-advanced-attributes-defaults"
}
},
"system": "my-system"
}

View file

@ -1 +0,0 @@
../../../../functional/derivation/advanced-attributes-structured-attrs-defaults.drv

View file

@ -1,24 +0,0 @@
{
"args": [
"-c",
"echo hello > $out"
],
"builder": "/bin/bash",
"env": {
"__json": "{\"builder\":\"/bin/bash\",\"name\":\"advanced-attributes-structured-attrs-defaults\",\"outputs\":[\"out\",\"dev\"],\"system\":\"my-system\"}",
"dev": "/nix/store/8bazivnbipbyi569623skw5zm91z6kc2-advanced-attributes-structured-attrs-defaults-dev",
"out": "/nix/store/f8f8nvnx32bxvyxyx2ff7akbvwhwd9dw-advanced-attributes-structured-attrs-defaults"
},
"inputDrvs": {},
"inputSrcs": [],
"name": "advanced-attributes-structured-attrs-defaults",
"outputs": {
"dev": {
"path": "/nix/store/8bazivnbipbyi569623skw5zm91z6kc2-advanced-attributes-structured-attrs-defaults-dev"
},
"out": {
"path": "/nix/store/f8f8nvnx32bxvyxyx2ff7akbvwhwd9dw-advanced-attributes-structured-attrs-defaults"
}
},
"system": "my-system"
}

View file

@ -1 +0,0 @@
../../../../functional/derivation/advanced-attributes-structured-attrs.drv

View file

@ -1,41 +0,0 @@
{
"args": [
"-c",
"echo hello > $out"
],
"builder": "/bin/bash",
"env": {
"__json": "{\"__darwinAllowLocalNetworking\":true,\"__impureHostDeps\":[\"/usr/bin/ditto\"],\"__noChroot\":true,\"__sandboxProfile\":\"sandcastle\",\"allowSubstitutes\":false,\"builder\":\"/bin/bash\",\"impureEnvVars\":[\"UNICORN\"],\"name\":\"advanced-attributes-structured-attrs\",\"outputChecks\":{\"bin\":{\"disallowedReferences\":[\"/nix/store/7rhsm8i393hm1wcsmph782awg1hi2f7x-bar\"],\"disallowedRequisites\":[\"/nix/store/7rhsm8i393hm1wcsmph782awg1hi2f7x-bar\"]},\"dev\":{\"maxClosureSize\":5909,\"maxSize\":789},\"out\":{\"allowedReferences\":[\"/nix/store/3c08bzb71z4wiag719ipjxr277653ynp-foo\"],\"allowedRequisites\":[\"/nix/store/3c08bzb71z4wiag719ipjxr277653ynp-foo\"]}},\"outputs\":[\"out\",\"bin\",\"dev\"],\"preferLocalBuild\":true,\"requiredSystemFeatures\":[\"rainbow\",\"uid-range\"],\"system\":\"my-system\"}",
"bin": "/nix/store/pbzb48v0ycf80jgligcp4n8z0rblna4n-advanced-attributes-structured-attrs-bin",
"dev": "/nix/store/7xapi8jv7flcz1qq8jhw55ar8ag8hldh-advanced-attributes-structured-attrs-dev",
"out": "/nix/store/mpq3l1l1qc2yr50q520g08kprprwv79f-advanced-attributes-structured-attrs"
},
"inputDrvs": {
"/nix/store/4xm4wccqsvagz9gjksn24s7rip2fdy7v-foo.drv": {
"dynamicOutputs": {},
"outputs": [
"out"
]
},
"/nix/store/plsq5jbr5nhgqwcgb2qxw7jchc09dnl8-bar.drv": {
"dynamicOutputs": {},
"outputs": [
"out"
]
}
},
"inputSrcs": [],
"name": "advanced-attributes-structured-attrs",
"outputs": {
"bin": {
"path": "/nix/store/pbzb48v0ycf80jgligcp4n8z0rblna4n-advanced-attributes-structured-attrs-bin"
},
"dev": {
"path": "/nix/store/7xapi8jv7flcz1qq8jhw55ar8ag8hldh-advanced-attributes-structured-attrs-dev"
},
"out": {
"path": "/nix/store/mpq3l1l1qc2yr50q520g08kprprwv79f-advanced-attributes-structured-attrs"
}
},
"system": "my-system"
}

View file

@ -1 +0,0 @@
../../../../functional/derivation/advanced-attributes.drv

View file

@ -1 +0,0 @@
Derive([],[("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv",(["cat","dog"],[("cat",["kitten"]),("goose",["gosling"])]))],["/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"],"wasm-sel4","foo",["bar","baz"],[("BIG_BAD","WOLF")])

View file

@ -1 +0,0 @@
DrvWithVersion("invalid-version",[],[("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv",["cat","dog"])],["/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"],"wasm-sel4","foo",["bar","baz"],[("BIG_BAD","WOLF")])

View file

@ -1 +0,0 @@
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")])

View file

@ -1,38 +0,0 @@
{
"args": [
"bar",
"baz"
],
"builder": "foo",
"env": {
"BIG_BAD": "WOLF"
},
"inputDrvs": {
"/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv": {
"dynamicOutputs": {
"cat": {
"dynamicOutputs": {},
"outputs": [
"kitten"
]
},
"goose": {
"dynamicOutputs": {},
"outputs": [
"gosling"
]
}
},
"outputs": [
"cat",
"dog"
]
}
},
"inputSrcs": [
"/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"
],
"name": "dyn-dep-derivation",
"outputs": {},
"system": "wasm-sel4"
}

View file

@ -1,6 +0,0 @@
{
"hash": "894517c9163c896ec31a2adbd33c0681fd5f45b2c0ef08a64c92a03fb97f390f",
"hashAlgo": "sha256",
"method": "flat",
"path": "/nix/store/rhcg9h16sqvlbpsa6dqm57sbr2al6nzg-drv-name-output-name"
}

View file

@ -1,6 +0,0 @@
{
"hash": "894517c9163c896ec31a2adbd33c0681fd5f45b2c0ef08a64c92a03fb97f390f",
"hashAlgo": "sha256",
"method": "nar",
"path": "/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-drv-name-output-name"
}

View file

@ -1,6 +0,0 @@
{
"hash": "894517c9163c896ec31a2adbd33c0681fd5f45b2c0ef08a64c92a03fb97f390f",
"hashAlgo": "sha256",
"method": "text",
"path": "/nix/store/6s1zwabh956jvhv4w9xcdb5jiyanyxg1-drv-name-output-name"
}

View file

@ -1,4 +0,0 @@
{
"hashAlgo": "sha256",
"method": "nar"
}

View file

@ -1,5 +0,0 @@
{
"hashAlgo": "sha256",
"impure": true,
"method": "nar"
}

View file

@ -1,3 +0,0 @@
{
"path": "/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-drv-name-output-name"
}

View file

@ -1 +0,0 @@
Derive([],[("/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv",["cat","dog"])],["/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"],"wasm-sel4","foo",["bar","baz"],[("BIG_BAD","WOLF")])

View file

@ -1,25 +0,0 @@
{
"args": [
"bar",
"baz"
],
"builder": "foo",
"env": {
"BIG_BAD": "WOLF"
},
"inputDrvs": {
"/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep2.drv": {
"dynamicOutputs": {},
"outputs": [
"cat",
"dog"
]
}
},
"inputSrcs": [
"/nix/store/c015dhfh5l0lp6wxyvdn7bmwhbbr6hr9-dep1"
],
"name": "simple-derivation",
"outputs": {},
"system": "wasm-sel4"
}

View file

@ -1 +0,0 @@
nix@scratchy.labs.cs.uu.nl - - eight

View file

@ -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=

View file

@ -1,20 +0,0 @@
{
"ca": "fixed:r:sha256:1lr187v6dck1rjh2j6svpikcfz53wyl3qrlcbb405zlh13x0khhh",
"compression": "xz",
"deriver": "/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv",
"downloadHash": "sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=",
"downloadSize": 4029176,
"narHash": "sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=",
"narSize": 34878,
"references": [
"/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar",
"/nix/store/n5wkd9frr45pa74if5gpz9j7mifg27fh-foo"
],
"registrationTime": 23423,
"signatures": [
"asdf",
"qwer"
],
"ultimate": true,
"url": "nar/1w1fff338fvdw53sqgamddn1b2xgds473pv6y13gizdbqjv4i5p3.nar.xz"
}

View file

@ -1,9 +0,0 @@
{
"ca": "fixed:r:sha256:1lr187v6dck1rjh2j6svpikcfz53wyl3qrlcbb405zlh13x0khhh",
"narHash": "sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=",
"narSize": 34878,
"references": [
"/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar",
"/nix/store/n5wkd9frr45pa74if5gpz9j7mifg27fh-foo"
]
}

View file

@ -1,10 +0,0 @@
{
"ca": null,
"deriver": null,
"narHash": "sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=",
"narSize": 0,
"references": [],
"registrationTime": null,
"signatures": [],
"ultimate": false
}

View file

@ -1,6 +0,0 @@
{
"ca": null,
"narHash": "sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=",
"narSize": 0,
"references": []
}

View file

@ -1,16 +0,0 @@
{
"ca": "fixed:r:sha256:1lr187v6dck1rjh2j6svpikcfz53wyl3qrlcbb405zlh13x0khhh",
"deriver": "/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar.drv",
"narHash": "sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=",
"narSize": 34878,
"references": [
"/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar",
"/nix/store/n5wkd9frr45pa74if5gpz9j7mifg27fh-foo"
],
"registrationTime": 23423,
"signatures": [
"asdf",
"qwer"
],
"ultimate": true
}

View file

@ -1,9 +0,0 @@
{
"ca": "fixed:r:sha256:1lr187v6dck1rjh2j6svpikcfz53wyl3qrlcbb405zlh13x0khhh",
"narHash": "sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc=",
"narSize": 34878,
"references": [
"/nix/store/g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-bar",
"/nix/store/n5wkd9frr45pa74if5gpz9j7mifg27fh-foo"
]
}

View file

@ -1 +0,0 @@
auto

View file

@ -1 +0,0 @@
auto?root=/foo/bar/baz

View file

@ -1 +0,0 @@
local://?root=/foo/bar/baz

View file

@ -1 +0,0 @@
local:///foo/bar/baz?trusted=true

View file

@ -1 +0,0 @@
local?root=/foo/bar/baz

View file

@ -1 +0,0 @@
/foo/bar/baz?trusted=true

View file

@ -1 +0,0 @@
ssh://localhost

View file

@ -1 +0,0 @@
unix://?max-connections=7&trusted=true

View file

@ -1 +0,0 @@
daemon?max-connections=7&trusted=true

View file

@ -1,234 +0,0 @@
#include <nlohmann/json.hpp>
#include <gtest/gtest.h>
#include <optional>
#include "experimental-features.hh"
#include "derivations.hh"
#include "tests/libstore.hh"
#include "tests/characterization.hh"
#include "parsed-derivations.hh"
#include "types.hh"
namespace nix {
using nlohmann::json;
class DerivationAdvancedAttrsTest : public CharacterizationTest, public LibStoreTest
{
Path unitTestData = getUnitTestData() + "/derivation";
public:
Path goldenMaster(std::string_view testStem) const override
{
return unitTestData + "/" + testStem;
}
};
#define TEST_ATERM_JSON(STEM, NAME) \
TEST_F(DerivationAdvancedAttrsTest, Derivation_##STEM##_from_json) \
{ \
readTest(NAME ".json", [&](const auto & encoded_) { \
auto encoded = json::parse(encoded_); \
/* Use DRV file instead of C++ literal as source of truth. */ \
auto aterm = readFile(goldenMaster(NAME ".drv")); \
auto expected = parseDerivation(*store, std::move(aterm), NAME); \
Derivation got = Derivation::fromJSON(*store, encoded); \
EXPECT_EQ(got, expected); \
}); \
} \
\
TEST_F(DerivationAdvancedAttrsTest, Derivation_##STEM##_to_json) \
{ \
writeTest( \
NAME ".json", \
[&]() -> json { \
/* Use DRV file instead of C++ literal as source of truth. */ \
auto aterm = readFile(goldenMaster(NAME ".drv")); \
return parseDerivation(*store, std::move(aterm), NAME).toJSON(*store); \
}, \
[](const auto & file) { return json::parse(readFile(file)); }, \
[](const auto & file, const auto & got) { return writeFile(file, got.dump(2) + "\n"); }); \
} \
\
TEST_F(DerivationAdvancedAttrsTest, Derivation_##STEM##_from_aterm) \
{ \
readTest(NAME ".drv", [&](auto encoded) { \
/* Use JSON file instead of C++ literal as source of truth. */ \
auto json = json::parse(readFile(goldenMaster(NAME ".json"))); \
auto expected = Derivation::fromJSON(*store, json); \
auto got = parseDerivation(*store, std::move(encoded), NAME); \
EXPECT_EQ(got.toJSON(*store), expected.toJSON(*store)); \
EXPECT_EQ(got, expected); \
}); \
} \
\
/* No corresponding write test, because we need to read the drv to write the json file */
TEST_ATERM_JSON(advancedAttributes_defaults, "advanced-attributes-defaults");
TEST_ATERM_JSON(advancedAttributes, "advanced-attributes-defaults");
TEST_ATERM_JSON(advancedAttributes_structuredAttrs_defaults, "advanced-attributes-structured-attrs");
TEST_ATERM_JSON(advancedAttributes_structuredAttrs, "advanced-attributes-structured-attrs-defaults");
#undef TEST_ATERM_JSON
TEST_F(DerivationAdvancedAttrsTest, Derivation_advancedAttributes_defaults)
{
readTest("advanced-attributes-defaults.drv", [&](auto encoded) {
auto got = parseDerivation(*store, std::move(encoded), "foo");
auto drvPath = writeDerivation(*store, got, NoRepair, true);
ParsedDerivation parsedDrv(drvPath, got);
EXPECT_EQ(parsedDrv.getStringAttr("__sandboxProfile").value_or(""), "");
EXPECT_EQ(parsedDrv.getBoolAttr("__noChroot"), false);
EXPECT_EQ(parsedDrv.getStringsAttr("__impureHostDeps").value_or(Strings()), Strings());
EXPECT_EQ(parsedDrv.getStringsAttr("impureEnvVars").value_or(Strings()), Strings());
EXPECT_EQ(parsedDrv.getBoolAttr("__darwinAllowLocalNetworking"), false);
EXPECT_EQ(parsedDrv.getStringsAttr("allowedReferences"), std::nullopt);
EXPECT_EQ(parsedDrv.getStringsAttr("allowedRequisites"), std::nullopt);
EXPECT_EQ(parsedDrv.getStringsAttr("disallowedReferences"), std::nullopt);
EXPECT_EQ(parsedDrv.getStringsAttr("disallowedRequisites"), std::nullopt);
EXPECT_EQ(parsedDrv.getRequiredSystemFeatures(), StringSet());
EXPECT_EQ(parsedDrv.canBuildLocally(*store), false);
EXPECT_EQ(parsedDrv.willBuildLocally(*store), false);
EXPECT_EQ(parsedDrv.substitutesAllowed(), true);
EXPECT_EQ(parsedDrv.useUidRange(), false);
});
};
TEST_F(DerivationAdvancedAttrsTest, Derivation_advancedAttributes)
{
readTest("advanced-attributes.drv", [&](auto encoded) {
auto got = parseDerivation(*store, std::move(encoded), "foo");
auto drvPath = writeDerivation(*store, got, NoRepair, true);
ParsedDerivation parsedDrv(drvPath, got);
StringSet systemFeatures{"rainbow", "uid-range"};
EXPECT_EQ(parsedDrv.getStringAttr("__sandboxProfile").value_or(""), "sandcastle");
EXPECT_EQ(parsedDrv.getBoolAttr("__noChroot"), true);
EXPECT_EQ(parsedDrv.getStringsAttr("__impureHostDeps").value_or(Strings()), Strings{"/usr/bin/ditto"});
EXPECT_EQ(parsedDrv.getStringsAttr("impureEnvVars").value_or(Strings()), Strings{"UNICORN"});
EXPECT_EQ(parsedDrv.getBoolAttr("__darwinAllowLocalNetworking"), true);
EXPECT_EQ(
parsedDrv.getStringsAttr("allowedReferences"), Strings{"/nix/store/3c08bzb71z4wiag719ipjxr277653ynp-foo"});
EXPECT_EQ(
parsedDrv.getStringsAttr("allowedRequisites"), Strings{"/nix/store/3c08bzb71z4wiag719ipjxr277653ynp-foo"});
EXPECT_EQ(
parsedDrv.getStringsAttr("disallowedReferences"),
Strings{"/nix/store/7rhsm8i393hm1wcsmph782awg1hi2f7x-bar"});
EXPECT_EQ(
parsedDrv.getStringsAttr("disallowedRequisites"),
Strings{"/nix/store/7rhsm8i393hm1wcsmph782awg1hi2f7x-bar"});
EXPECT_EQ(parsedDrv.getRequiredSystemFeatures(), systemFeatures);
EXPECT_EQ(parsedDrv.canBuildLocally(*store), false);
EXPECT_EQ(parsedDrv.willBuildLocally(*store), false);
EXPECT_EQ(parsedDrv.substitutesAllowed(), false);
EXPECT_EQ(parsedDrv.useUidRange(), true);
});
};
TEST_F(DerivationAdvancedAttrsTest, Derivation_advancedAttributes_structuredAttrs_defaults)
{
readTest("advanced-attributes-structured-attrs-defaults.drv", [&](auto encoded) {
auto got = parseDerivation(*store, std::move(encoded), "foo");
auto drvPath = writeDerivation(*store, got, NoRepair, true);
ParsedDerivation parsedDrv(drvPath, got);
EXPECT_EQ(parsedDrv.getStringAttr("__sandboxProfile").value_or(""), "");
EXPECT_EQ(parsedDrv.getBoolAttr("__noChroot"), false);
EXPECT_EQ(parsedDrv.getStringsAttr("__impureHostDeps").value_or(Strings()), Strings());
EXPECT_EQ(parsedDrv.getStringsAttr("impureEnvVars").value_or(Strings()), Strings());
EXPECT_EQ(parsedDrv.getBoolAttr("__darwinAllowLocalNetworking"), false);
{
auto structuredAttrs_ = parsedDrv.getStructuredAttrs();
ASSERT_TRUE(structuredAttrs_);
auto & structuredAttrs = *structuredAttrs_;
auto outputChecks_ = get(structuredAttrs, "outputChecks");
ASSERT_FALSE(outputChecks_);
}
EXPECT_EQ(parsedDrv.getRequiredSystemFeatures(), StringSet());
EXPECT_EQ(parsedDrv.canBuildLocally(*store), false);
EXPECT_EQ(parsedDrv.willBuildLocally(*store), false);
EXPECT_EQ(parsedDrv.substitutesAllowed(), true);
EXPECT_EQ(parsedDrv.useUidRange(), false);
});
};
TEST_F(DerivationAdvancedAttrsTest, Derivation_advancedAttributes_structuredAttrs)
{
readTest("advanced-attributes-structured-attrs.drv", [&](auto encoded) {
auto got = parseDerivation(*store, std::move(encoded), "foo");
auto drvPath = writeDerivation(*store, got, NoRepair, true);
ParsedDerivation parsedDrv(drvPath, got);
StringSet systemFeatures{"rainbow", "uid-range"};
EXPECT_EQ(parsedDrv.getStringAttr("__sandboxProfile").value_or(""), "sandcastle");
EXPECT_EQ(parsedDrv.getBoolAttr("__noChroot"), true);
EXPECT_EQ(parsedDrv.getStringsAttr("__impureHostDeps").value_or(Strings()), Strings{"/usr/bin/ditto"});
EXPECT_EQ(parsedDrv.getStringsAttr("impureEnvVars").value_or(Strings()), Strings{"UNICORN"});
EXPECT_EQ(parsedDrv.getBoolAttr("__darwinAllowLocalNetworking"), true);
{
auto structuredAttrs_ = parsedDrv.getStructuredAttrs();
ASSERT_TRUE(structuredAttrs_);
auto & structuredAttrs = *structuredAttrs_;
auto outputChecks_ = get(structuredAttrs, "outputChecks");
ASSERT_TRUE(outputChecks_);
auto & outputChecks = *outputChecks_;
{
auto output_ = get(outputChecks, "out");
ASSERT_TRUE(output_);
auto & output = *output_;
EXPECT_EQ(
get(output, "allowedReferences")->get<Strings>(),
Strings{"/nix/store/3c08bzb71z4wiag719ipjxr277653ynp-foo"});
EXPECT_EQ(
get(output, "allowedRequisites")->get<Strings>(),
Strings{"/nix/store/3c08bzb71z4wiag719ipjxr277653ynp-foo"});
}
{
auto output_ = get(outputChecks, "bin");
ASSERT_TRUE(output_);
auto & output = *output_;
EXPECT_EQ(
get(output, "disallowedReferences")->get<Strings>(),
Strings{"/nix/store/7rhsm8i393hm1wcsmph782awg1hi2f7x-bar"});
EXPECT_EQ(
get(output, "disallowedRequisites")->get<Strings>(),
Strings{"/nix/store/7rhsm8i393hm1wcsmph782awg1hi2f7x-bar"});
}
{
auto output_ = get(outputChecks, "dev");
ASSERT_TRUE(output_);
auto & output = *output_;
EXPECT_EQ(get(output, "maxSize")->get<uint64_t>(), 789);
EXPECT_EQ(get(output, "maxClosureSize")->get<uint64_t>(), 5909);
}
}
EXPECT_EQ(parsedDrv.getRequiredSystemFeatures(), systemFeatures);
EXPECT_EQ(parsedDrv.canBuildLocally(*store), false);
EXPECT_EQ(parsedDrv.willBuildLocally(*store), false);
EXPECT_EQ(parsedDrv.substitutesAllowed(), false);
EXPECT_EQ(parsedDrv.useUidRange(), true);
});
};
}

View file

@ -1,299 +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() + "/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 = ContentAddressMethod::Raw::Flat,
.hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="),
},
}),
"drv-name", "output-name")
TEST_JSON(DerivationTest, caFixedNAR,
(DerivationOutput::CAFixed {
.ca = {
.method = ContentAddressMethod::Raw::NixArchive,
.hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="),
},
}),
"drv-name", "output-name")
TEST_JSON(DynDerivationTest, caFixedText,
(DerivationOutput::CAFixed {
.ca = {
.method = ContentAddressMethod::Raw::Text,
.hash = Hash::parseAnyPrefixed("sha256-iUUXyRY8iW7DGirb0zwGgf1fRbLA7wimTJKgP7l/OQ8="),
},
}),
"drv-name", "output-name")
TEST_JSON(CaDerivationTest, caFloating,
(DerivationOutput::CAFloating {
.method = ContentAddressMethod::Raw::NixArchive,
.hashAlgo = HashAlgorithm::SHA256,
}),
"drv-name", "output-name")
TEST_JSON(DerivationTest, deferred,
DerivationOutput::Deferred { },
"drv-name", "output-name")
TEST_JSON(ImpureDerivationTest, impure,
(DerivationOutput::Impure {
.method = ContentAddressMethod::Raw::NixArchive,
.hashAlgo = HashAlgorithm::SHA256,
}),
"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
}

View file

@ -1,100 +0,0 @@
#include <regex>
#include <gtest/gtest.h>
#include <rapidcheck/gtest.h>
#include "tests/derived-path.hh"
#include "tests/libstore.hh"
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
}

View file

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

View file

@ -1,38 +0,0 @@
check: libstore-tests_RUN
programs += libstore-tests
libstore-tests_NAME = libnixstore-tests
libstore-tests_ENV := _NIX_TEST_UNIT_DATA=$(d)/data GTEST_OUTPUT=xml:$$testresults/libstore-tests.xml
libstore-tests_DIR := $(d)
ifeq ($(INSTALL_UNIT_TESTS), yes)
libstore-tests_INSTALL_DIR := $(checkbindir)
else
libstore-tests_INSTALL_DIR :=
endif
libstore-tests_SOURCES := $(wildcard $(d)/*.cc)
libstore-tests_EXTRA_INCLUDES = \
-I tests/unit/libstore-support \
-I tests/unit/libutil-support \
$(INCLUDE_libstore) \
$(INCLUDE_libstorec) \
$(INCLUDE_libutil) \
$(INCLUDE_libutilc)
libstore-tests_CXXFLAGS += $(libstore-tests_EXTRA_INCLUDES)
libstore-tests_LIBS = \
libstore-test-support libutil-test-support \
libstore libstorec libutil libutilc
libstore-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS)
ifdef HOST_WINDOWS
# Increase the default reserved stack size to 65 MB so Nix doesn't run out of space
libstore-tests_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024)))
endif

View file

@ -1,165 +0,0 @@
#include "machines.hh"
#include "file-system.hh"
#include "util.hh"
#include "tests/characterization.hh"
#include <gtest/gtest.h>
#include <gmock/gmock-matchers.h>
using testing::Contains;
using testing::ElementsAre;
using testing::Eq;
using testing::Field;
using testing::SizeIs;
using namespace nix;
TEST(machines, getMachinesWithEmptyBuilders) {
auto actual = Machine::parseConfig({}, "");
ASSERT_THAT(actual, SizeIs(0));
}
TEST(machines, getMachinesUriOnly) {
auto actual = Machine::parseConfig({"TEST_ARCH-TEST_OS"}, "nix@scratchy.labs.cs.uu.nl");
ASSERT_THAT(actual, SizeIs(1));
EXPECT_THAT(actual[0], Field(&Machine::storeUri, Eq(StoreReference::parse("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) {
auto actual = Machine::parseConfig({"TEST_ARCH-TEST_OS"}, "nix@scratchy.labs.cs.uu.nl - - - - - - -");
ASSERT_THAT(actual, SizeIs(1));
EXPECT_THAT(actual[0], Field(&Machine::storeUri, Eq(StoreReference::parse("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)));
}
MATCHER_P(AuthorityMatches, authority, "") {
*result_listener
<< "where the authority of "
<< arg.render()
<< " is "
<< authority;
auto * generic = std::get_if<StoreReference::Specified>(&arg.variant);
if (!generic) return false;
return generic->authority == authority;
}
TEST(machines, getMachinesWithNewLineSeparator) {
auto actual = Machine::parseConfig({}, "nix@scratchy.labs.cs.uu.nl\nnix@itchy.labs.cs.uu.nl");
ASSERT_THAT(actual, SizeIs(2));
EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, AuthorityMatches("nix@scratchy.labs.cs.uu.nl"))));
EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, AuthorityMatches("nix@itchy.labs.cs.uu.nl"))));
}
TEST(machines, getMachinesWithSemicolonSeparator) {
auto actual = Machine::parseConfig({}, "nix@scratchy.labs.cs.uu.nl ; nix@itchy.labs.cs.uu.nl");
EXPECT_THAT(actual, SizeIs(2));
EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, AuthorityMatches("nix@scratchy.labs.cs.uu.nl"))));
EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, AuthorityMatches("nix@itchy.labs.cs.uu.nl"))));
}
TEST(machines, getMachinesWithCorrectCompleteSingleBuilder) {
auto actual = Machine::parseConfig({},
"nix@scratchy.labs.cs.uu.nl i686-linux "
"/home/nix/.ssh/id_scratchy_auto 8 3 kvm "
"benchmark SSH+HOST+PUBLIC+KEY+BASE64+ENCODED==");
ASSERT_THAT(actual, SizeIs(1));
EXPECT_THAT(actual[0], Field(&Machine::storeUri, AuthorityMatches("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) {
auto actual = Machine::parseConfig({},
"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==");
ASSERT_THAT(actual, SizeIs(1));
EXPECT_THAT(actual[0], Field(&Machine::storeUri, AuthorityMatches("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) {
auto actual = Machine::parseConfig({},
"nix@scratchy.labs.cs.uu.nl Arch1,Arch2 - - - "
"SupportedFeature1,SupportedFeature2 "
"MandatoryFeature1,MandatoryFeature2");
ASSERT_THAT(actual, SizeIs(1));
EXPECT_THAT(actual[0], Field(&Machine::storeUri, AuthorityMatches("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) {
EXPECT_THROW(
Machine::parseConfig({}, "nix@scratchy.labs.cs.uu.nl - - eight"),
FormatError);
EXPECT_THROW(
Machine::parseConfig({}, "nix@scratchy.labs.cs.uu.nl - - -1"),
FormatError);
EXPECT_THROW(
Machine::parseConfig({}, "nix@scratchy.labs.cs.uu.nl - - 8 three"),
FormatError);
EXPECT_THROW(
Machine::parseConfig({}, "nix@scratchy.labs.cs.uu.nl - - 8 -3"),
UsageError);
EXPECT_THROW(
Machine::parseConfig({}, "nix@scratchy.labs.cs.uu.nl - - 8 3 - - BAD_BASE64"),
FormatError);
}
TEST(machines, getMachinesWithCorrectFileReference) {
auto path = absPath(getUnitTestData() + "/machines/valid");
ASSERT_TRUE(pathExists(path));
auto actual = Machine::parseConfig({}, "@" + path);
ASSERT_THAT(actual, SizeIs(3));
EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, AuthorityMatches("nix@scratchy.labs.cs.uu.nl"))));
EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, AuthorityMatches("nix@itchy.labs.cs.uu.nl"))));
EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, AuthorityMatches("nix@poochie.labs.cs.uu.nl"))));
}
TEST(machines, getMachinesWithCorrectFileReferenceToEmptyFile) {
auto path = "/dev/null";
ASSERT_TRUE(pathExists(path));
auto actual = Machine::parseConfig({}, std::string{"@"} + path);
ASSERT_THAT(actual, SizeIs(0));
}
TEST(machines, getMachinesWithIncorrectFileReference) {
auto actual = Machine::parseConfig({}, "@" + absPath("/not/a/file"));
ASSERT_THAT(actual, SizeIs(0));
}
TEST(machines, getMachinesWithCorrectFileReferenceToIncorrectFile) {
EXPECT_THROW(
Machine::parseConfig({}, "@" + absPath(getUnitTestData() + "/machines/bad_format")),
FormatError);
}

View file

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

View file

@ -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() + "/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::NixArchive,
.hash = hashString(HashAlgorithm::SHA256, "(...)"),
.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)
}

Some files were not shown because too many files have changed in this diff Show more