Skip to content

Commit 1177d65

Browse files
committed
Properly check xp features when deserializing deriving paths
1 parent a2c6f38 commit 1177d65

File tree

3 files changed

+69
-36
lines changed

3 files changed

+69
-36
lines changed

src/libstore-tests/derived-path.cc

Lines changed: 50 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@
33
#include <gtest/gtest.h>
44
#include <rapidcheck/gtest.h>
55

6-
#include "nix/util/tests/characterization.hh"
6+
#include "nix/util/tests/json-characterization.hh"
77
#include "nix/store/tests/derived-path.hh"
88
#include "nix/store/tests/libstore.hh"
99

1010
namespace nix {
1111

12-
class DerivedPathTest : public CharacterizationTest, public LibStoreTest
12+
class DerivedPathTest : public virtual CharacterizationTest, public LibStoreTest
1313
{
1414
std::filesystem::path unitTestData = getUnitTestData() / "derived-path";
1515

@@ -123,25 +123,51 @@ RC_GTEST_FIXTURE_PROP(DerivedPathTest, prop_round_rip, (const DerivedPath & o))
123123

124124
using nlohmann::json;
125125

126-
#define TEST_JSON(TYPE, NAME, VAL) \
127-
static const TYPE NAME = VAL; \
128-
\
129-
TEST_F(DerivedPathTest, NAME##_from_json) \
130-
{ \
131-
readTest(#NAME ".json", [&](const auto & encoded_) { \
132-
auto encoded = json::parse(encoded_); \
133-
TYPE got = static_cast<TYPE>(encoded); \
134-
ASSERT_EQ(got, NAME); \
135-
}); \
136-
} \
137-
\
138-
TEST_F(DerivedPathTest, NAME##_to_json) \
139-
{ \
140-
writeTest( \
141-
#NAME ".json", \
142-
[&]() -> json { return static_cast<json>(NAME); }, \
143-
[](const auto & file) { return json::parse(readFile(file)); }, \
144-
[](const auto & file, const auto & got) { return writeFile(file, got.dump(2) + "\n"); }); \
126+
struct SingleDerivedPathJsonTest : DerivedPathTest,
127+
JsonCharacterizationTest<SingleDerivedPath>,
128+
::testing::WithParamInterface<SingleDerivedPath>
129+
{};
130+
131+
struct DerivedPathJsonTest : DerivedPathTest,
132+
JsonCharacterizationTest<DerivedPath>,
133+
::testing::WithParamInterface<DerivedPath>
134+
{};
135+
136+
#define TEST_JSON(TYPE, NAME, VAL) \
137+
static const TYPE NAME = VAL; \
138+
\
139+
TEST_F(TYPE##JsonTest, NAME##_from_json) \
140+
{ \
141+
readJsonTest(#NAME, NAME); \
142+
} \
143+
\
144+
TEST_F(TYPE##JsonTest, NAME##_to_json) \
145+
{ \
146+
writeJsonTest(#NAME, NAME); \
147+
}
148+
149+
#define TEST_JSON_XP_DYN(TYPE, NAME, VAL) \
150+
static const TYPE NAME = VAL; \
151+
\
152+
TEST_F(TYPE##JsonTest, NAME##_from_json_throws_without_xp) \
153+
{ \
154+
std::optional<json> ret; \
155+
readTest(#NAME ".json", [&](const auto & encoded_) { ret = json::parse(encoded_); }); \
156+
if (ret) { \
157+
EXPECT_THROW(nlohmann::adl_serializer<TYPE>::from_json(*ret), MissingExperimentalFeature); \
158+
} \
159+
} \
160+
\
161+
TEST_F(TYPE##JsonTest, NAME##_from_json) \
162+
{ \
163+
ExperimentalFeatureSettings xpSettings; \
164+
xpSettings.set("experimental-features", "dynamic-derivations"); \
165+
readJsonTest(#NAME, NAME, xpSettings); \
166+
} \
167+
\
168+
TEST_F(TYPE##JsonTest, NAME##_to_json) \
169+
{ \
170+
writeJsonTest(#NAME, NAME); \
145171
}
146172

147173
TEST_JSON(
@@ -156,7 +182,7 @@ TEST_JSON(
156182
.output = "bar",
157183
}));
158184

159-
TEST_JSON(
185+
TEST_JSON_XP_DYN(
160186
SingleDerivedPath,
161187
single_built_built,
162188
(SingleDerivedPath::Built{
@@ -179,7 +205,7 @@ TEST_JSON(
179205
.outputs = OutputsSpec::Names{"bar", "baz"},
180206
}));
181207

182-
TEST_JSON(
208+
TEST_JSON_XP_DYN(
183209
DerivedPath,
184210
multi_built_built,
185211
(DerivedPath::Built{
@@ -191,7 +217,7 @@ TEST_JSON(
191217
.outputs = OutputsSpec::Names{"baz", "quux"},
192218
}));
193219

194-
TEST_JSON(
220+
TEST_JSON_XP_DYN(
195221
DerivedPath,
196222
multi_built_built_wildcard,
197223
(DerivedPath::Built{

src/libstore/derived-path.cc

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -252,20 +252,26 @@ void adl_serializer<DerivedPath::Built>::to_json(json & json, const DerivedPath:
252252
};
253253
}
254254

255-
SingleDerivedPath::Built adl_serializer<SingleDerivedPath::Built>::from_json(const json & json0)
255+
SingleDerivedPath::Built
256+
adl_serializer<SingleDerivedPath::Built>::from_json(const json & json0, const ExperimentalFeatureSettings & xpSettings)
256257
{
257258
auto & json = getObject(json0);
259+
auto drvPath = make_ref<SingleDerivedPath>(static_cast<SingleDerivedPath>(valueAt(json, "drvPath")));
260+
drvRequireExperiment(*drvPath, xpSettings);
258261
return {
259-
.drvPath = make_ref<SingleDerivedPath>(static_cast<SingleDerivedPath>(valueAt(json, "drvPath"))),
262+
.drvPath = std::move(drvPath),
260263
.output = getString(valueAt(json, "output")),
261264
};
262265
}
263266

264-
DerivedPath::Built adl_serializer<DerivedPath::Built>::from_json(const json & json0)
267+
DerivedPath::Built
268+
adl_serializer<DerivedPath::Built>::from_json(const json & json0, const ExperimentalFeatureSettings & xpSettings)
265269
{
266270
auto & json = getObject(json0);
271+
auto drvPath = make_ref<SingleDerivedPath>(static_cast<SingleDerivedPath>(valueAt(json, "drvPath")));
272+
drvRequireExperiment(*drvPath, xpSettings);
267273
return {
268-
.drvPath = make_ref<SingleDerivedPath>(static_cast<SingleDerivedPath>(valueAt(json, "drvPath"))),
274+
.drvPath = std::move(drvPath),
269275
.outputs = adl_serializer<OutputsSpec>::from_json(valueAt(json, "outputs")),
270276
};
271277
}
@@ -280,20 +286,21 @@ void adl_serializer<DerivedPath>::to_json(json & json, const DerivedPath & sdp)
280286
std::visit([&](const auto & buildable) { json = buildable; }, sdp.raw());
281287
}
282288

283-
SingleDerivedPath adl_serializer<SingleDerivedPath>::from_json(const json & json)
289+
SingleDerivedPath
290+
adl_serializer<SingleDerivedPath>::from_json(const json & json, const ExperimentalFeatureSettings & xpSettings)
284291
{
285292
if (json.is_string())
286293
return static_cast<SingleDerivedPath::Opaque>(json);
287294
else
288-
return static_cast<SingleDerivedPath::Built>(json);
295+
return adl_serializer<SingleDerivedPath::Built>::from_json(json, xpSettings);
289296
}
290297

291-
DerivedPath adl_serializer<DerivedPath>::from_json(const json & json)
298+
DerivedPath adl_serializer<DerivedPath>::from_json(const json & json, const ExperimentalFeatureSettings & xpSettings)
292299
{
293300
if (json.is_string())
294301
return static_cast<DerivedPath::Opaque>(json);
295302
else
296-
return static_cast<DerivedPath::Built>(json);
303+
return adl_serializer<DerivedPath::Built>::from_json(json, xpSettings);
297304
}
298305

299306
} // namespace nlohmann

src/libstore/include/nix/store/derived-path.hh

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ void drvRequireExperiment(
299299
} // namespace nix
300300

301301
JSON_IMPL(nix::SingleDerivedPath::Opaque)
302-
JSON_IMPL(nix::SingleDerivedPath::Built)
303-
JSON_IMPL(nix::SingleDerivedPath)
304-
JSON_IMPL(nix::DerivedPath::Built)
305-
JSON_IMPL(nix::DerivedPath)
302+
JSON_IMPL_WITH_XP_FEATURES(nix::SingleDerivedPath::Built)
303+
JSON_IMPL_WITH_XP_FEATURES(nix::SingleDerivedPath)
304+
JSON_IMPL_WITH_XP_FEATURES(nix::DerivedPath::Built)
305+
JSON_IMPL_WITH_XP_FEATURES(nix::DerivedPath)

0 commit comments

Comments
 (0)