aboutsummaryrefslogtreecommitdiff
path: root/tests/unit/libstore
diff options
context:
space:
mode:
authoreldritch horrors <pennae@lix.systems>2024-03-04 04:24:23 +0100
committereldritch horrors <pennae@lix.systems>2024-03-04 04:36:58 +0100
commit6897e238bd0c730af224b928ec8746781df67ad2 (patch)
tree50ce7ddeda203a12c7d67080ef611f56d59678c2 /tests/unit/libstore
parentda0aa66d98b8b46253dd968cfaae61d872569c9b (diff)
Merge pull request #9099 from obsidiansystems/common-proto
Factor out bits of the worker protocol to use elsewhere (cherry picked from commit 4b1a97338f517f45e6169d3d8845c5caa5724e97) Change-Id: If93afa0f8b1cf9b0e705b34fa71e6fd708752758
Diffstat (limited to 'tests/unit/libstore')
-rw-r--r--tests/unit/libstore/characterization.hh23
-rw-r--r--tests/unit/libstore/common-protocol.cc152
-rw-r--r--tests/unit/libstore/protocol.hh88
-rw-r--r--tests/unit/libstore/worker-protocol.cc90
4 files changed, 280 insertions, 73 deletions
diff --git a/tests/unit/libstore/characterization.hh b/tests/unit/libstore/characterization.hh
new file mode 100644
index 000000000..5f366cb42
--- /dev/null
+++ b/tests/unit/libstore/characterization.hh
@@ -0,0 +1,23 @@
+#pragma once
+///@file
+
+namespace nix {
+
+/**
+ * The path to the `unit-test-data` directory. See the contributing
+ * guide in the manual for further details.
+ */
+static Path getUnitTestData() {
+ return getEnv("_NIX_TEST_UNIT_DATA").value();
+}
+
+/**
+ * Whether we should update "golden masters" instead of running tests
+ * against them. See the contributing guide in the manual for further
+ * details.
+ */
+static bool testAccept() {
+ return getEnv("_NIX_TEST_ACCEPT") == "1";
+}
+
+}
diff --git a/tests/unit/libstore/common-protocol.cc b/tests/unit/libstore/common-protocol.cc
new file mode 100644
index 000000000..ee54b2cd9
--- /dev/null
+++ b/tests/unit/libstore/common-protocol.cc
@@ -0,0 +1,152 @@
+#include <regex>
+
+#include <nlohmann/json.hpp>
+#include <gtest/gtest.h>
+
+#include "common-protocol.hh"
+#include "common-protocol-impl.hh"
+#include "build-result.hh"
+#include "protocol.hh"
+#include "characterization.hh"
+
+namespace nix {
+
+const char commonProtoDir[] = "common-protocol";
+
+using CommonProtoTest = ProtoTest<CommonProto, commonProtoDir>;
+
+CHARACTERIZATION_TEST(
+ CommonProtoTest,
+ 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(
+ CommonProtoTest,
+ storePath,
+ "store-path",
+ (std::tuple<StorePath, StorePath> {
+ StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo" },
+ StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo-bar" },
+ }))
+
+CHARACTERIZATION_TEST(
+ CommonProtoTest,
+ contentAddress,
+ "content-address",
+ (std::tuple<ContentAddress, ContentAddress, ContentAddress> {
+ ContentAddress {
+ .method = TextIngestionMethod {},
+ .hash = hashString(HashType::htSHA256, "Derive(...)"),
+ },
+ ContentAddress {
+ .method = FileIngestionMethod::Flat,
+ .hash = hashString(HashType::htSHA1, "blob blob..."),
+ },
+ ContentAddress {
+ .method = FileIngestionMethod::Recursive,
+ .hash = hashString(HashType::htSHA256, "(...)"),
+ },
+ }))
+
+CHARACTERIZATION_TEST(
+ CommonProtoTest,
+ 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(
+ CommonProtoTest,
+ 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(
+ CommonProtoTest,
+ 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(
+ CommonProtoTest,
+ 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(
+ CommonProtoTest,
+ optionalStorePath,
+ "optional-store-path",
+ (std::tuple<std::optional<StorePath>, std::optional<StorePath>> {
+ std::nullopt,
+ std::optional {
+ StorePath { "g1w7hy3qg1w7hy3qg1w7hy3qg1w7hy3q-foo-bar" },
+ },
+ }))
+
+CHARACTERIZATION_TEST(
+ CommonProtoTest,
+ optionalContentAddress,
+ "optional-content-address",
+ (std::tuple<std::optional<ContentAddress>, std::optional<ContentAddress>> {
+ std::nullopt,
+ std::optional {
+ ContentAddress {
+ .method = FileIngestionMethod::Flat,
+ .hash = hashString(HashType::htSHA1, "blob blob..."),
+ },
+ },
+ }))
+
+}
diff --git a/tests/unit/libstore/protocol.hh b/tests/unit/libstore/protocol.hh
new file mode 100644
index 000000000..0df819090
--- /dev/null
+++ b/tests/unit/libstore/protocol.hh
@@ -0,0 +1,88 @@
+#include <nlohmann/json.hpp>
+#include <gtest/gtest.h>
+
+#include "tests/libstore.hh"
+#include "characterization.hh"
+
+namespace nix {
+
+template<class Proto, const char * protocolDir>
+class ProtoTest : public LibStoreTest
+{
+ /**
+ * Read this as simply `using S = Inner::Serialise;`.
+ *
+ * See `LengthPrefixedProtoHelper::S` for the same trick, and its
+ * rationale.
+ */
+ template<typename U> using S = typename Proto::template Serialise<U>;
+
+public:
+ Path unitTestData = getUnitTestData() + "/libstore/" + protocolDir;
+
+ Path goldenMaster(std::string_view testStem) {
+ return unitTestData + "/" + testStem + ".bin";
+ }
+
+ /**
+ * Golden test for `T` reading
+ */
+ template<typename T>
+ void readTest(PathView testStem, T value)
+ {
+ if (testAccept())
+ {
+ GTEST_SKIP() << "Cannot read golden master because another test is also updating it";
+ }
+ else
+ {
+ auto expected = readFile(goldenMaster(testStem));
+
+ T got = ({
+ StringSource from { expected };
+ S<T>::read(
+ *store,
+ typename Proto::ReadConn { .from = from });
+ });
+
+ ASSERT_EQ(got, value);
+ }
+ }
+
+ /**
+ * Golden test for `T` write
+ */
+ template<typename T>
+ void writeTest(PathView testStem, const T & value)
+ {
+ auto file = goldenMaster(testStem);
+
+ StringSink to;
+ Proto::write(
+ *store,
+ typename Proto::WriteConn { .to = to },
+ value);
+
+ if (testAccept())
+ {
+ createDirs(dirOf(file));
+ writeFile(file, to.s);
+ GTEST_SKIP() << "Updating golden master";
+ }
+ else
+ {
+ auto expected = readFile(file);
+ ASSERT_EQ(to.s, expected);
+ }
+ }
+};
+
+#define CHARACTERIZATION_TEST(FIXTURE, NAME, STEM, VALUE) \
+ TEST_F(FIXTURE, NAME ## _read) { \
+ readTest(STEM, VALUE); \
+ } \
+ TEST_F(FIXTURE, NAME ## _write) { \
+ writeTest(STEM, VALUE); \
+ }
+
+}
diff --git a/tests/unit/libstore/worker-protocol.cc b/tests/unit/libstore/worker-protocol.cc
index fa7cbe121..5c3faaae2 100644
--- a/tests/unit/libstore/worker-protocol.cc
+++ b/tests/unit/libstore/worker-protocol.cc
@@ -7,85 +7,17 @@
#include "worker-protocol-impl.hh"
#include "derived-path.hh"
#include "build-result.hh"
-#include "tests/libstore.hh"
+#include "protocol.hh"
+#include "characterization.hh"
namespace nix {
-class WorkerProtoTest : public LibStoreTest
-{
-public:
- Path unitTestData = getEnv("_NIX_TEST_UNIT_DATA").value() + "/libstore/worker-protocol";
+const char workerProtoDir[] = "worker-protocol";
- bool testAccept() {
- return getEnv("_NIX_TEST_ACCEPT") == "1";
- }
-
- Path goldenMaster(std::string_view testStem) {
- return unitTestData + "/" + testStem + ".bin";
- }
-
- /**
- * Golden test for `T` reading
- */
- template<typename T>
- void readTest(PathView testStem, T value)
- {
- if (testAccept())
- {
- GTEST_SKIP() << "Cannot read golden master because another test is also updating it";
- }
- else
- {
- auto expected = readFile(goldenMaster(testStem));
-
- T got = ({
- StringSource from { expected };
- WorkerProto::Serialise<T>::read(
- *store,
- WorkerProto::ReadConn { .from = from });
- });
-
- ASSERT_EQ(got, value);
- }
- }
-
- /**
- * Golden test for `T` write
- */
- template<typename T>
- void writeTest(PathView testStem, const T & value)
- {
- auto file = goldenMaster(testStem);
-
- StringSink to;
- WorkerProto::write(
- *store,
- WorkerProto::WriteConn { .to = to },
- value);
-
- if (testAccept())
- {
- createDirs(dirOf(file));
- writeFile(file, to.s);
- GTEST_SKIP() << "Updating golden master";
- }
- else
- {
- auto expected = readFile(file);
- ASSERT_EQ(to.s, expected);
- }
- }
-};
-
-#define CHARACTERIZATION_TEST(NAME, STEM, VALUE) \
- TEST_F(WorkerProtoTest, NAME ## _read) { \
- readTest(STEM, VALUE); \
- } \
- TEST_F(WorkerProtoTest, NAME ## _write) { \
- writeTest(STEM, VALUE); \
- }
+using WorkerProtoTest = ProtoTest<WorkerProto, workerProtoDir>;
CHARACTERIZATION_TEST(
+ WorkerProtoTest,
string,
"string",
(std::tuple<std::string, std::string, std::string, std::string, std::string> {
@@ -97,6 +29,7 @@ CHARACTERIZATION_TEST(
}))
CHARACTERIZATION_TEST(
+ WorkerProtoTest,
storePath,
"store-path",
(std::tuple<StorePath, StorePath> {
@@ -105,6 +38,7 @@ CHARACTERIZATION_TEST(
}))
CHARACTERIZATION_TEST(
+ WorkerProtoTest,
contentAddress,
"content-address",
(std::tuple<ContentAddress, ContentAddress, ContentAddress> {
@@ -123,6 +57,7 @@ CHARACTERIZATION_TEST(
}))
CHARACTERIZATION_TEST(
+ WorkerProtoTest,
derivedPath,
"derived-path",
(std::tuple<DerivedPath, DerivedPath> {
@@ -138,6 +73,7 @@ CHARACTERIZATION_TEST(
}))
CHARACTERIZATION_TEST(
+ WorkerProtoTest,
drvOutput,
"drv-output",
(std::tuple<DrvOutput, DrvOutput> {
@@ -152,6 +88,7 @@ CHARACTERIZATION_TEST(
}))
CHARACTERIZATION_TEST(
+ WorkerProtoTest,
realisation,
"realisation",
(std::tuple<Realisation, Realisation> {
@@ -183,6 +120,7 @@ CHARACTERIZATION_TEST(
}))
CHARACTERIZATION_TEST(
+ WorkerProtoTest,
buildResult,
"build-result",
({
@@ -240,6 +178,7 @@ CHARACTERIZATION_TEST(
}))
CHARACTERIZATION_TEST(
+ WorkerProtoTest,
keyedBuildResult,
"keyed-build-result",
({
@@ -275,6 +214,7 @@ CHARACTERIZATION_TEST(
}))
CHARACTERIZATION_TEST(
+ WorkerProtoTest,
optionalTrustedFlag,
"optional-trusted-flag",
(std::tuple<std::optional<TrustedFlag>, std::optional<TrustedFlag>, std::optional<TrustedFlag>> {
@@ -284,6 +224,7 @@ CHARACTERIZATION_TEST(
}))
CHARACTERIZATION_TEST(
+ WorkerProtoTest,
vector,
"vector",
(std::tuple<std::vector<std::string>, std::vector<std::string>, std::vector<std::string>, std::vector<std::vector<std::string>>> {
@@ -294,6 +235,7 @@ CHARACTERIZATION_TEST(
}))
CHARACTERIZATION_TEST(
+ WorkerProtoTest,
set,
"set",
(std::tuple<std::set<std::string>, std::set<std::string>, std::set<std::string>, std::set<std::set<std::string>>> {
@@ -304,6 +246,7 @@ CHARACTERIZATION_TEST(
}))
CHARACTERIZATION_TEST(
+ WorkerProtoTest,
optionalStorePath,
"optional-store-path",
(std::tuple<std::optional<StorePath>, std::optional<StorePath>> {
@@ -314,6 +257,7 @@ CHARACTERIZATION_TEST(
}))
CHARACTERIZATION_TEST(
+ WorkerProtoTest,
optionalContentAddress,
"optional-content-address",
(std::tuple<std::optional<ContentAddress>, std::optional<ContentAddress>> {