1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-07-10 04:43:53 +02:00

Merge remote-tracking branch 'origin/master' into large-path-warning

This commit is contained in:
Eelco Dolstra 2024-06-03 15:32:27 +02:00
commit 7f5b57d18f
435 changed files with 6086 additions and 2767 deletions

View file

@ -38,3 +38,8 @@ libexpr-tests_LIBS = \
libexpr libexprc libfetchers libstore libstorec libutil libutilc
libexpr-tests_LDFLAGS := -lrapidcheck $(GTEST_LIBS) -lgmock
ifdef HOST_WINDOWS
# Increase the default reserved stack size to 65 MB so Nix doesn't run out of space
libexpr-tests_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024)))
endif

View file

@ -191,4 +191,212 @@ TEST_F(nix_api_expr_test, nix_expr_realise_context)
nix_realised_string_free(r);
}
const char * SAMPLE_USER_DATA = "whatever";
static void primop_square(void * user_data, nix_c_context * context, EvalState * state, Value ** args, Value * ret)
{
assert(context);
assert(state);
assert(user_data == SAMPLE_USER_DATA);
auto i = nix_get_int(context, args[0]);
nix_init_int(context, ret, i * i);
}
TEST_F(nix_api_expr_test, nix_expr_primop)
{
PrimOp * primop =
nix_alloc_primop(ctx, primop_square, 1, "square", nullptr, "square an integer", (void *) SAMPLE_USER_DATA);
assert_ctx_ok();
Value * primopValue = nix_alloc_value(ctx, state);
assert_ctx_ok();
nix_init_primop(ctx, primopValue, primop);
assert_ctx_ok();
Value * three = nix_alloc_value(ctx, state);
assert_ctx_ok();
nix_init_int(ctx, three, 3);
assert_ctx_ok();
Value * result = nix_alloc_value(ctx, state);
assert_ctx_ok();
nix_value_call(ctx, state, primopValue, three, result);
assert_ctx_ok();
auto r = nix_get_int(ctx, result);
ASSERT_EQ(9, r);
}
static void primop_repeat(void * user_data, nix_c_context * context, EvalState * state, Value ** args, Value * ret)
{
assert(context);
assert(state);
assert(user_data == SAMPLE_USER_DATA);
// Get the string to repeat
std::string s;
if (nix_get_string(context, args[0], OBSERVE_STRING(s)) != NIX_OK)
return;
// Get the number of times to repeat
auto n = nix_get_int(context, args[1]);
if (nix_err_code(context) != NIX_OK)
return;
// Repeat the string
std::string result;
for (int i = 0; i < n; ++i)
result += s;
nix_init_string(context, ret, result.c_str());
}
TEST_F(nix_api_expr_test, nix_expr_primop_arity_2_multiple_calls)
{
PrimOp * primop =
nix_alloc_primop(ctx, primop_repeat, 2, "repeat", nullptr, "repeat a string", (void *) SAMPLE_USER_DATA);
assert_ctx_ok();
Value * primopValue = nix_alloc_value(ctx, state);
assert_ctx_ok();
nix_init_primop(ctx, primopValue, primop);
assert_ctx_ok();
Value * hello = nix_alloc_value(ctx, state);
assert_ctx_ok();
nix_init_string(ctx, hello, "hello");
assert_ctx_ok();
Value * three = nix_alloc_value(ctx, state);
assert_ctx_ok();
nix_init_int(ctx, three, 3);
assert_ctx_ok();
Value * partial = nix_alloc_value(ctx, state);
assert_ctx_ok();
nix_value_call(ctx, state, primopValue, hello, partial);
assert_ctx_ok();
Value * result = nix_alloc_value(ctx, state);
assert_ctx_ok();
nix_value_call(ctx, state, partial, three, result);
assert_ctx_ok();
std::string r;
nix_get_string(ctx, result, OBSERVE_STRING(r));
ASSERT_STREQ("hellohellohello", r.c_str());
}
TEST_F(nix_api_expr_test, nix_expr_primop_arity_2_single_call)
{
PrimOp * primop =
nix_alloc_primop(ctx, primop_repeat, 2, "repeat", nullptr, "repeat a string", (void *) SAMPLE_USER_DATA);
assert_ctx_ok();
Value * primopValue = nix_alloc_value(ctx, state);
assert_ctx_ok();
nix_init_primop(ctx, primopValue, primop);
assert_ctx_ok();
Value * hello = nix_alloc_value(ctx, state);
assert_ctx_ok();
nix_init_string(ctx, hello, "hello");
assert_ctx_ok();
Value * three = nix_alloc_value(ctx, state);
assert_ctx_ok();
nix_init_int(ctx, three, 3);
assert_ctx_ok();
Value * result = nix_alloc_value(ctx, state);
assert_ctx_ok();
NIX_VALUE_CALL(ctx, state, result, primopValue, hello, three);
assert_ctx_ok();
std::string r;
nix_get_string(ctx, result, OBSERVE_STRING(r));
assert_ctx_ok();
ASSERT_STREQ("hellohellohello", r.c_str());
}
static void
primop_bad_no_return(void * user_data, nix_c_context * context, EvalState * state, Value ** args, Value * ret)
{
}
TEST_F(nix_api_expr_test, nix_expr_primop_bad_no_return)
{
PrimOp * primop =
nix_alloc_primop(ctx, primop_bad_no_return, 1, "badNoReturn", nullptr, "a broken primop", nullptr);
assert_ctx_ok();
Value * primopValue = nix_alloc_value(ctx, state);
assert_ctx_ok();
nix_init_primop(ctx, primopValue, primop);
assert_ctx_ok();
Value * three = nix_alloc_value(ctx, state);
assert_ctx_ok();
nix_init_int(ctx, three, 3);
assert_ctx_ok();
Value * result = nix_alloc_value(ctx, state);
assert_ctx_ok();
nix_value_call(ctx, state, primopValue, three, result);
ASSERT_EQ(ctx->last_err_code, NIX_ERR_NIX_ERROR);
ASSERT_THAT(
ctx->last_err,
testing::Optional(
testing::HasSubstr("Implementation error in custom function: return value was not initialized")));
ASSERT_THAT(ctx->last_err, testing::Optional(testing::HasSubstr("badNoReturn")));
}
static void
primop_bad_return_thunk(void * user_data, nix_c_context * context, EvalState * state, Value ** args, Value * ret)
{
nix_init_apply(context, ret, args[0], args[1]);
}
TEST_F(nix_api_expr_test, nix_expr_primop_bad_return_thunk)
{
PrimOp * primop =
nix_alloc_primop(ctx, primop_bad_return_thunk, 2, "badReturnThunk", nullptr, "a broken primop", nullptr);
assert_ctx_ok();
Value * primopValue = nix_alloc_value(ctx, state);
assert_ctx_ok();
nix_init_primop(ctx, primopValue, primop);
assert_ctx_ok();
Value * toString = nix_alloc_value(ctx, state);
assert_ctx_ok();
nix_expr_eval_from_string(ctx, state, "builtins.toString", ".", toString);
assert_ctx_ok();
Value * four = nix_alloc_value(ctx, state);
assert_ctx_ok();
nix_init_int(ctx, four, 4);
assert_ctx_ok();
Value * result = nix_alloc_value(ctx, state);
assert_ctx_ok();
NIX_VALUE_CALL(ctx, state, result, primopValue, toString, four);
ASSERT_EQ(ctx->last_err_code, NIX_ERR_NIX_ERROR);
ASSERT_THAT(
ctx->last_err,
testing::Optional(
testing::HasSubstr("Implementation error in custom function: return value must not be a thunk")));
ASSERT_THAT(ctx->last_err, testing::Optional(testing::HasSubstr("badReturnThunk")));
}
TEST_F(nix_api_expr_test, nix_value_call_multi_no_args)
{
Value * n = nix_alloc_value(ctx, state);
nix_init_int(ctx, n, 3);
assert_ctx_ok();
Value * r = nix_alloc_value(ctx, state);
nix_value_call_multi(ctx, state, n, 0, nullptr, r);
assert_ctx_ok();
auto rInt = nix_get_int(ctx, r);
assert_ctx_ok();
ASSERT_EQ(3, rInt);
}
} // namespace nixC

View file

@ -256,10 +256,13 @@ TEST_F(nix_api_expr_test, nix_value_init)
Value * f = nix_alloc_value(ctx, state);
nix_expr_eval_from_string(
ctx, state, R"(
ctx,
state,
R"(
a: a * a
)",
"<test>", f);
"<test>",
f);
// Test
@ -325,20 +328,26 @@ TEST_F(nix_api_expr_test, nix_value_init_apply_lazy_arg)
Value * f = nix_alloc_value(ctx, state);
nix_expr_eval_from_string(
ctx, state, R"(
ctx,
state,
R"(
a: { foo = a; }
)",
"<test>", f);
"<test>",
f);
assert_ctx_ok();
Value * e = nix_alloc_value(ctx, state);
{
Value * g = nix_alloc_value(ctx, state);
nix_expr_eval_from_string(
ctx, state, R"(
ctx,
state,
R"(
_ignore: throw "error message for test case nix_value_init_apply_lazy_arg"
)",
"<test>", g);
"<test>",
g);
assert_ctx_ok();
nix_init_apply(ctx, e, g, g);

View file

@ -30,3 +30,8 @@ libfetchers-tests_LIBS = \
libfetchers libstore libutil
libfetchers-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
libfetchers-tests_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024)))
endif

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -0,0 +1 @@
auto

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -31,3 +31,8 @@ libstore-tests_LIBS = \
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,46 +1,29 @@
#include "machines.hh"
#include "globals.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::EndsWith;
using testing::Eq;
using testing::Field;
using testing::SizeIs;
using nix::absPath;
using nix::FormatError;
using nix::UsageError;
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);
using namespace nix;
TEST(machines, getMachinesWithEmptyBuilders) {
settings.builders = "";
Machines actual = getMachines();
auto actual = Machine::parseConfig({}, "");
ASSERT_THAT(actual, SizeIs(0));
}
TEST(machines, getMachinesUriOnly) {
settings.builders = "nix@scratchy.labs.cs.uu.nl";
Machines actual = getMachines();
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("ssh://nix@scratchy.labs.cs.uu.nl")));
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)));
@ -51,10 +34,9 @@ TEST(machines, getMachinesUriOnly) {
}
TEST(machines, getMachinesDefaults) {
settings.builders = "nix@scratchy.labs.cs.uu.nl - - - - - - -";
Machines actual = getMachines();
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("ssh://nix@scratchy.labs.cs.uu.nl")));
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)));
@ -64,29 +46,38 @@ TEST(machines, getMachinesDefaults) {
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) {
settings.builders = "nix@scratchy.labs.cs.uu.nl\nnix@itchy.labs.cs.uu.nl";
Machines actual = getMachines();
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, 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, AuthorityMatches("nix@scratchy.labs.cs.uu.nl"))));
EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, AuthorityMatches("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();
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, 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, AuthorityMatches("nix@scratchy.labs.cs.uu.nl"))));
EXPECT_THAT(actual, Contains(Field(&Machine::storeUri, AuthorityMatches("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();
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, EndsWith("nix@scratchy.labs.cs.uu.nl")));
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)));
@ -98,13 +89,12 @@ TEST(machines, getMachinesWithCorrectCompleteSingleBuilder) {
TEST(machines,
getMachinesWithCorrectCompleteSingleBuilderWithTabColumnDelimiter) {
settings.builders =
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==";
Machines actual = getMachines();
"KEY+BASE64+ENCODED==");
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::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)));
@ -115,58 +105,61 @@ TEST(machines,
}
TEST(machines, getMachinesWithMultiOptions) {
settings.builders = "nix@scratchy.labs.cs.uu.nl Arch1,Arch2 - - - "
"SupportedFeature1,SupportedFeature2 "
"MandatoryFeature1,MandatoryFeature2";
Machines actual = getMachines();
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, EndsWith("nix@scratchy.labs.cs.uu.nl")));
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) {
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(), UsageError);
settings.builders = "nix@scratchy.labs.cs.uu.nl - - 8 3 - - BAD_BASE64";
EXPECT_THROW(getMachines(), FormatError);
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("tests/unit/libstore/test-data/machines.valid");
auto path = absPath(getUnitTestData() + "/machines/valid");
ASSERT_TRUE(pathExists(path));
settings.builders = std::string("@") + path;
Machines actual = getMachines();
auto actual = Machine::parseConfig({}, "@" + path);
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"))));
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));
settings.builders = std::string("@") + path;
Machines actual = getMachines();
auto actual = Machine::parseConfig({}, std::string{"@"} + path);
ASSERT_THAT(actual, SizeIs(0));
}
TEST(machines, getMachinesWithIncorrectFileReference) {
settings.builders = std::string("@") + absPath("/not/a/file");
Machines actual = getMachines();
auto actual = Machine::parseConfig({}, "@" + absPath("/not/a/file"));
ASSERT_THAT(actual, SizeIs(0));
}
TEST(machines, getMachinesWithCorrectFileReferenceToIncorrectFile) {
settings.builders = std::string("@") + absPath("tests/unit/libstore/test-data/machines.bad_format");
EXPECT_THROW(getMachines(), FormatError);
EXPECT_THROW(
Machine::parseConfig({}, "@" + absPath(getUnitTestData() + "/machines/bad_format")),
FormatError);
}

View file

@ -19,7 +19,15 @@ class PathInfoTest : public CharacterizationTest, public LibStoreTest
}
};
static UnkeyedValidPathInfo makePathInfo(const Store & store, bool includeImpureInfo) {
static UnkeyedValidPathInfo makeEmpty()
{
return {
Hash::parseSRI("sha256-FePFYIlMuycIXPZbWi7LGEiMmZSX9FMbaQenWBzm1Sc="),
};
}
static UnkeyedValidPathInfo makeFull(const Store & store, bool includeImpureInfo)
{
UnkeyedValidPathInfo info = ValidPathInfo {
store,
"foo",
@ -50,22 +58,21 @@ static UnkeyedValidPathInfo makePathInfo(const Store & store, bool includeImpure
return info;
}
#define JSON_TEST(STEM, PURE) \
#define JSON_TEST(STEM, OBJ, PURE) \
TEST_F(PathInfoTest, PathInfo_ ## STEM ## _from_json) { \
readTest(#STEM, [&](const auto & encoded_) { \
auto encoded = json::parse(encoded_); \
UnkeyedValidPathInfo got = UnkeyedValidPathInfo::fromJSON( \
*store, \
encoded); \
auto expected = makePathInfo(*store, PURE); \
auto expected = OBJ; \
ASSERT_EQ(got, expected); \
}); \
} \
\
TEST_F(PathInfoTest, PathInfo_ ## STEM ## _to_json) { \
writeTest(#STEM, [&]() -> json { \
return makePathInfo(*store, PURE) \
.toJSON(*store, PURE, HashFormat::SRI); \
return OBJ.toJSON(*store, PURE, HashFormat::SRI); \
}, [](const auto & file) { \
return json::parse(readFile(file)); \
}, [](const auto & file, const auto & got) { \
@ -73,7 +80,10 @@ static UnkeyedValidPathInfo makePathInfo(const Store & store, bool includeImpure
}); \
}
JSON_TEST(pure, false)
JSON_TEST(impure, true)
JSON_TEST(empty_pure, makeEmpty(), false)
JSON_TEST(empty_impure, makeEmpty(), true)
JSON_TEST(pure, makeFull(*store, false), false)
JSON_TEST(impure, makeFull(*store, true), true)
}

View file

@ -6,6 +6,7 @@
#include "serve-protocol.hh"
#include "serve-protocol-impl.hh"
#include "serve-protocol-connection.hh"
#include "build-result.hh"
#include "file-descriptor.hh"
#include "tests/protocol.hh"
@ -505,7 +506,8 @@ TEST_F(ServeProtoTest, handshake_client_corrupted_throws)
} else {
auto ver = ServeProto::BasicClientConnection::handshake(
nullSink, in, defaultVersion, "blah");
EXPECT_NE(ver, defaultVersion);
// `std::min` of this and the other version saves us
EXPECT_EQ(ver, defaultVersion);
}
}
});

View file

@ -0,0 +1,123 @@
#include <nlohmann/json.hpp>
#include <gtest/gtest.h>
#include "file-system.hh"
#include "store-reference.hh"
#include "tests/characterization.hh"
#include "tests/libstore.hh"
namespace nix {
using nlohmann::json;
class StoreReferenceTest : public CharacterizationTest, public LibStoreTest
{
Path unitTestData = getUnitTestData() + "/store-reference";
Path goldenMaster(PathView testStem) const override
{
return unitTestData + "/" + testStem + ".txt";
}
};
#define URI_TEST_READ(STEM, OBJ) \
TEST_F(StoreReferenceTest, PathInfo_##STEM##_from_uri) \
{ \
readTest(#STEM, ([&](const auto & encoded) { \
StoreReference expected = OBJ; \
auto got = StoreReference::parse(encoded); \
ASSERT_EQ(got, expected); \
})); \
}
#define URI_TEST_WRITE(STEM, OBJ) \
TEST_F(StoreReferenceTest, PathInfo_##STEM##_to_uri) \
{ \
writeTest( \
#STEM, \
[&]() -> StoreReference { return OBJ; }, \
[](const auto & file) { return StoreReference::parse(readFile(file)); }, \
[](const auto & file, const auto & got) { return writeFile(file, got.render()); }); \
}
#define URI_TEST(STEM, OBJ) \
URI_TEST_READ(STEM, OBJ) \
URI_TEST_WRITE(STEM, OBJ)
URI_TEST(
auto,
(StoreReference{
.variant = StoreReference::Auto{},
.params = {},
}))
URI_TEST(
auto_param,
(StoreReference{
.variant = StoreReference::Auto{},
.params =
{
{"root", "/foo/bar/baz"},
},
}))
static StoreReference localExample_1{
.variant =
StoreReference::Specified{
.scheme = "local",
},
.params =
{
{"root", "/foo/bar/baz"},
},
};
static StoreReference localExample_2{
.variant =
StoreReference::Specified{
.scheme = "local",
.authority = "/foo/bar/baz",
},
.params =
{
{"trusted", "true"},
},
};
URI_TEST(local_1, localExample_1)
URI_TEST(local_2, localExample_2)
URI_TEST_READ(local_shorthand_1, localExample_1)
URI_TEST_READ(local_shorthand_2, localExample_2)
static StoreReference unixExample{
.variant =
StoreReference::Specified{
.scheme = "unix",
},
.params =
{
{"max-connections", "7"},
{"trusted", "true"},
},
};
URI_TEST(unix, unixExample)
URI_TEST_READ(unix_shorthand, unixExample)
URI_TEST(
ssh,
(StoreReference{
.variant =
StoreReference::Specified{
.scheme = "ssh",
.authority = "localhost",
},
.params = {},
}))
}

View file

@ -4,6 +4,7 @@
#include <gtest/gtest.h>
#include "worker-protocol.hh"
#include "worker-protocol-connection.hh"
#include "worker-protocol-impl.hh"
#include "derived-path.hh"
#include "build-result.hh"
@ -18,9 +19,9 @@ struct WorkerProtoTest : VersionedProtoTest<WorkerProto, workerProtoDir>
{
/**
* For serializers that don't care about the minimum version, we
* used the oldest one: 1.0.
* used the oldest one: 1.10.
*/
WorkerProto::Version defaultVersion = 1 << 8 | 0;
WorkerProto::Version defaultVersion = 1 << 8 | 10;
};
@ -529,6 +530,17 @@ VERSIONED_CHARACTERIZATION_TEST(
}),
}))
VERSIONED_CHARACTERIZATION_TEST(
WorkerProtoTest,
buildMode,
"build-mode",
defaultVersion,
(std::tuple<BuildMode, BuildMode, BuildMode> {
bmNormal,
bmRepair,
bmCheck,
}))
VERSIONED_CHARACTERIZATION_TEST(
WorkerProtoTest,
optionalTrustedFlag,
@ -591,4 +603,152 @@ VERSIONED_CHARACTERIZATION_TEST(
},
}))
VERSIONED_CHARACTERIZATION_TEST(
WorkerProtoTest,
clientHandshakeInfo_1_30,
"client-handshake-info_1_30",
1 << 8 | 30,
(std::tuple<WorkerProto::ClientHandshakeInfo> {
{},
}))
VERSIONED_CHARACTERIZATION_TEST(
WorkerProtoTest,
clientHandshakeInfo_1_33,
"client-handshake-info_1_33",
1 << 8 | 33,
(std::tuple<WorkerProto::ClientHandshakeInfo, WorkerProto::ClientHandshakeInfo> {
{
.daemonNixVersion = std::optional { "foo" },
},
{
.daemonNixVersion = std::optional { "bar" },
},
}))
VERSIONED_CHARACTERIZATION_TEST(
WorkerProtoTest,
clientHandshakeInfo_1_35,
"client-handshake-info_1_35",
1 << 8 | 35,
(std::tuple<WorkerProto::ClientHandshakeInfo, WorkerProto::ClientHandshakeInfo> {
{
.daemonNixVersion = std::optional { "foo" },
.remoteTrustsUs = std::optional { NotTrusted },
},
{
.daemonNixVersion = std::optional { "bar" },
.remoteTrustsUs = std::optional { Trusted },
},
}))
TEST_F(WorkerProtoTest, handshake_log)
{
CharacterizationTest::writeTest("handshake-to-client", [&]() -> std::string {
StringSink toClientLog;
Pipe toClient, toServer;
toClient.create();
toServer.create();
WorkerProto::Version clientResult;
auto thread = std::thread([&]() {
FdSink out { toServer.writeSide.get() };
FdSource in0 { toClient.readSide.get() };
TeeSource in { in0, toClientLog };
clientResult = WorkerProto::BasicClientConnection::handshake(
out, in, defaultVersion);
});
{
FdSink out { toClient.writeSide.get() };
FdSource in { toServer.readSide.get() };
WorkerProto::BasicServerConnection::handshake(
out, in, defaultVersion);
};
thread.join();
return std::move(toClientLog.s);
});
}
/// Has to be a `BufferedSink` for handshake.
struct NullBufferedSink : BufferedSink {
void writeUnbuffered(std::string_view data) override { }
};
TEST_F(WorkerProtoTest, handshake_client_replay)
{
CharacterizationTest::readTest("handshake-to-client", [&](std::string toClientLog) {
NullBufferedSink nullSink;
StringSource in { toClientLog };
auto clientResult = WorkerProto::BasicClientConnection::handshake(
nullSink, in, defaultVersion);
EXPECT_EQ(clientResult, defaultVersion);
});
}
TEST_F(WorkerProtoTest, handshake_client_truncated_replay_throws)
{
CharacterizationTest::readTest("handshake-to-client", [&](std::string toClientLog) {
for (size_t len = 0; len < toClientLog.size(); ++len) {
NullBufferedSink nullSink;
StringSource in {
// truncate
toClientLog.substr(0, len)
};
if (len < 8) {
EXPECT_THROW(
WorkerProto::BasicClientConnection::handshake(
nullSink, in, defaultVersion),
EndOfFile);
} else {
// Not sure why cannot keep on checking for `EndOfFile`.
EXPECT_THROW(
WorkerProto::BasicClientConnection::handshake(
nullSink, in, defaultVersion),
Error);
}
}
});
}
TEST_F(WorkerProtoTest, handshake_client_corrupted_throws)
{
CharacterizationTest::readTest("handshake-to-client", [&](const std::string toClientLog) {
for (size_t idx = 0; idx < toClientLog.size(); ++idx) {
// corrupt a copy
std::string toClientLogCorrupt = toClientLog;
toClientLogCorrupt[idx] *= 4;
++toClientLogCorrupt[idx];
NullBufferedSink nullSink;
StringSource in { toClientLogCorrupt };
if (idx < 4 || idx == 9) {
// magic bytes don't match
EXPECT_THROW(
WorkerProto::BasicClientConnection::handshake(
nullSink, in, defaultVersion),
Error);
} else if (idx < 8 || idx >= 12) {
// Number out of bounds
EXPECT_THROW(
WorkerProto::BasicClientConnection::handshake(
nullSink, in, defaultVersion),
SerialisationError);
} else {
auto ver = WorkerProto::BasicClientConnection::handshake(
nullSink, in, defaultVersion);
// `std::min` of this and the other version saves us
EXPECT_EQ(ver, defaultVersion);
}
}
});
}
}

View file

@ -12,7 +12,7 @@ namespace nix {
* The path to the unit test data directory. See the contributing guide
* in the manual for further details.
*/
static Path getUnitTestData() {
static inline Path getUnitTestData() {
return getEnv("_NIX_TEST_UNIT_DATA").value();
}
@ -21,7 +21,7 @@ static Path getUnitTestData() {
* against them. See the contributing guide in the manual for further
* details.
*/
static bool testAccept() {
static inline bool testAccept() {
return getEnv("_NIX_TEST_ACCEPT") == "1";
}

View file

@ -175,13 +175,16 @@ TEST(optionalValueAt, empty) {
TEST(getNullable, null) {
auto json = R"(null)"_json;
ASSERT_EQ(getNullable(json), std::nullopt);
ASSERT_EQ(getNullable(json), nullptr);
}
TEST(getNullable, empty) {
auto json = R"({})"_json;
ASSERT_EQ(getNullable(json), std::optional { R"({})"_json });
auto * p = getNullable(json);
ASSERT_NE(p, nullptr);
ASSERT_EQ(*p, R"({})"_json);
}
} /* namespace nix */

View file

@ -27,6 +27,11 @@ libutil-tests_LIBS = libutil-test-support libutil libutilc
libutil-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
libutil-tests_LDFLAGS += -Wl,--stack,$(shell echo $$((65 * 1024 * 1024)))
endif
check: $(d)/data/git/check-data.sh.test
$(eval $(call run-test,$(d)/data/git/check-data.sh))