1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-12-15 21:41:04 +01:00

Merge pull request #14309 from obsidiansystems/json-schema-content-address

` nlohmann::json` instance and JSON Schema for `ContentAddress`
This commit is contained in:
John Ericson 2025-10-27 19:52:19 +00:00 committed by GitHub
commit 0c1be3aabe
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
18 changed files with 242 additions and 37 deletions

View file

@ -0,0 +1 @@
../../src/libstore-tests/data/content-address

View file

@ -30,6 +30,14 @@ schemas = [
'blake3-base64.json',
],
},
{
'stem' : 'content-address',
'schema' : schema_dir / 'content-address-v1.yaml',
'files' : [
'text.json',
'nar.json',
],
},
{
'stem' : 'derivation',
'schema' : schema_dir / 'derivation-v3.yaml',
@ -73,8 +81,6 @@ foreach schema : schemas
stem + '-schema-valid',
jv,
args : [
'--map',
'./hash-v1.yaml=' + schema_dir / 'hash-v1.yaml',
'http://json-schema.org/draft-04/schema',
schema_file,
],

View file

@ -21,6 +21,7 @@ mkMesonDerivation (finalAttrs: {
../../.version
../../doc/manual/source/protocols/json/schema
../../src/libutil-tests/data/hash
../../src/libstore-tests/data/content-address
../../src/libstore-tests/data/derivation
../../src/libstore-tests/data/derived-path
./.

View file

@ -1,6 +1,7 @@
#include <gtest/gtest.h>
#include "nix/store/content-address.hh"
#include "nix/util/tests/json-characterization.hh"
namespace nix {
@ -8,33 +9,93 @@ namespace nix {
* ContentAddressMethod::parse, ContentAddressMethod::render
* --------------------------------------------------------------------------*/
TEST(ContentAddressMethod, testRoundTripPrintParse_1)
static auto methods = ::testing::Values(
std::pair{ContentAddressMethod::Raw::Text, "text"},
std::pair{ContentAddressMethod::Raw::Flat, "flat"},
std::pair{ContentAddressMethod::Raw::NixArchive, "nar"},
std::pair{ContentAddressMethod::Raw::Git, "git"});
struct ContentAddressMethodTest : ::testing::Test,
::testing::WithParamInterface<std::pair<ContentAddressMethod, std::string_view>>
{};
TEST_P(ContentAddressMethodTest, testRoundTripPrintParse_1)
{
for (ContentAddressMethod cam : {
ContentAddressMethod::Raw::Text,
ContentAddressMethod::Raw::Flat,
ContentAddressMethod::Raw::NixArchive,
ContentAddressMethod::Raw::Git,
}) {
EXPECT_EQ(ContentAddressMethod::parse(cam.render()), cam);
}
auto & [cam, _] = GetParam();
EXPECT_EQ(ContentAddressMethod::parse(cam.render()), cam);
}
TEST(ContentAddressMethod, testRoundTripPrintParse_2)
TEST_P(ContentAddressMethodTest, testRoundTripPrintParse_2)
{
for (const std::string_view camS : {
"text",
"flat",
"nar",
"git",
}) {
EXPECT_EQ(ContentAddressMethod::parse(camS).render(), camS);
}
auto & [cam, camS] = GetParam();
EXPECT_EQ(ContentAddressMethod::parse(camS).render(), camS);
}
INSTANTIATE_TEST_SUITE_P(ContentAddressMethod, ContentAddressMethodTest, methods);
TEST(ContentAddressMethod, testParseContentAddressMethodOptException)
{
EXPECT_THROW(ContentAddressMethod::parse("narwhal"), UsageError);
}
/* ----------------------------------------------------------------------------
* JSON
* --------------------------------------------------------------------------*/
class ContentAddressTest : public virtual CharacterizationTest
{
std::filesystem::path unitTestData = getUnitTestData() / "content-address";
public:
/**
* 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;
std::filesystem::path goldenMaster(std::string_view testStem) const override
{
return unitTestData / testStem;
}
};
using nlohmann::json;
struct ContentAddressJsonTest : ContentAddressTest,
JsonCharacterizationTest<ContentAddress>,
::testing::WithParamInterface<std::pair<std::string_view, ContentAddress>>
{};
TEST_P(ContentAddressJsonTest, from_json)
{
auto & [name, expected] = GetParam();
readJsonTest(name, expected);
}
TEST_P(ContentAddressJsonTest, to_json)
{
auto & [name, value] = GetParam();
writeJsonTest(name, value);
}
INSTANTIATE_TEST_SUITE_P(
ContentAddressJSON,
ContentAddressJsonTest,
::testing::Values(
std::pair{
"text",
ContentAddress{
.method = ContentAddressMethod::Raw::Text,
.hash = hashString(HashAlgorithm::SHA256, "asdf"),
},
},
std::pair{
"nar",
ContentAddress{
.method = ContentAddressMethod::Raw::NixArchive,
.hash = hashString(HashAlgorithm::SHA256, "qwer"),
},
}));
} // namespace nix

View file

@ -0,0 +1,8 @@
{
"hash": {
"algorithm": "sha256",
"format": "base64",
"hash": "9vLqj0XYoFfJVmoz+ZR02i5camYE1zYSFlDicwxvsKM="
},
"method": "nar"
}

View file

@ -0,0 +1,8 @@
{
"hash": {
"algorithm": "sha256",
"format": "base64",
"hash": "8OTC92xYkW7CWPJGhRvqCR0U1CR6L8PhhpRGGxgW4Ts="
},
"method": "text"
}

View file

@ -1,6 +1,7 @@
#include "nix/util/args.hh"
#include "nix/store/content-address.hh"
#include "nix/util/split.hh"
#include "nix/util/json-utils.hh"
namespace nix {
@ -300,3 +301,36 @@ Hash ContentAddressWithReferences::getHash() const
}
} // namespace nix
namespace nlohmann {
using namespace nix;
ContentAddressMethod adl_serializer<ContentAddressMethod>::from_json(const json & json)
{
return ContentAddressMethod::parse(getString(json));
}
void adl_serializer<ContentAddressMethod>::to_json(json & json, const ContentAddressMethod & m)
{
json = m.render();
}
ContentAddress adl_serializer<ContentAddress>::from_json(const json & json)
{
auto obj = getObject(json);
return {
.method = adl_serializer<ContentAddressMethod>::from_json(valueAt(obj, "method")),
.hash = valueAt(obj, "hash"),
};
}
void adl_serializer<ContentAddress>::to_json(json & json, const ContentAddress & ca)
{
json = {
{"method", ca.method},
{"hash", ca.hash},
};
}
} // namespace nlohmann

View file

@ -6,6 +6,7 @@
#include "nix/store/path.hh"
#include "nix/util/file-content-address.hh"
#include "nix/util/variant-wrapper.hh"
#include "nix/util/json-impls.hh"
namespace nix {
@ -308,4 +309,15 @@ struct ContentAddressWithReferences
Hash getHash() const;
};
template<>
struct json_avoids_null<ContentAddressMethod> : std::true_type
{};
template<>
struct json_avoids_null<ContentAddress> : std::true_type
{};
} // namespace nix
JSON_IMPL(nix::ContentAddressMethod)
JSON_IMPL(nix::ContentAddress)