diff options
author | Griffin Smith <grfn@gws.fyi> | 2020-08-02T17·28-0400 |
---|---|---|
committer | glittershark <grfn@gws.fyi> | 2020-08-02T20·00+0000 |
commit | cc82d6e3605d428a93cdd7063edc30034816df6f (patch) | |
tree | 050c6f8fe315a132e836822f9b3b293b8e613813 /third_party/nix | |
parent | 7aebba7531c0e29baba1c8c3725ac3597ad859ee (diff) |
test(3p/nix): Add test for derivation parse/serialize r/1548
Add a rapidcheck test covering roundtrip parse and serialize for Nix derivations. This covers a bug we discovered in ef54f5d which broke this roundtrip. Change-Id: I72d140334b5f24f79e82e34f98609c695dbfbf93 Reviewed-on: https://cl.tvl.fyi/c/depot/+/1582 Tested-by: BuildkiteCI Reviewed-by: kanepyork <rikingcoding@gmail.com>
Diffstat (limited to 'third_party/nix')
-rw-r--r-- | third_party/nix/src/libstore/derivations.cc | 2 | ||||
-rw-r--r-- | third_party/nix/src/libstore/derivations.hh | 4 | ||||
-rw-r--r-- | third_party/nix/src/tests/CMakeLists.txt | 11 | ||||
-rw-r--r-- | third_party/nix/src/tests/derivations_test.cc | 106 |
4 files changed, 121 insertions, 2 deletions
diff --git a/third_party/nix/src/libstore/derivations.cc b/third_party/nix/src/libstore/derivations.cc index 29f929270e9b..8a50f3c85b4d 100644 --- a/third_party/nix/src/libstore/derivations.cc +++ b/third_party/nix/src/libstore/derivations.cc @@ -144,7 +144,7 @@ static StringSet parseStrings(std::istream& str, bool arePaths) { return res; } -static Derivation parseDerivation(const std::string& s) { +Derivation parseDerivation(const std::string& s) { Derivation drv; istringstream_nocopy str(s); expect(str, "Derive(["); diff --git a/third_party/nix/src/libstore/derivations.hh b/third_party/nix/src/libstore/derivations.hh index 21ef71372e05..38877780e0c1 100644 --- a/third_party/nix/src/libstore/derivations.hh +++ b/third_party/nix/src/libstore/derivations.hh @@ -16,10 +16,10 @@ const std::string drvExtension = ".drv"; struct DerivationOutput { Path path; + // TODO(grfn): make these two fields a Hash std::string hashAlgo; /* hash used for expected hash computation */ std::string hash; /* expected hash, may be null */ DerivationOutput() {} - // TODO(grfn): Make explicit DerivationOutput(Path path, std::string hashAlgo, std::string hash) { this->path = path; this->hashAlgo = hashAlgo; @@ -92,6 +92,8 @@ Path writeDerivation(const ref<Store>& store, const Derivation& drv, /* Read a derivation from a file. */ Derivation readDerivation(const Path& drvPath); +Derivation parseDerivation(const std::string& s); + /* Check whether a file name ends with the extension for derivations. */ bool isDerivation(const std::string& fileName); diff --git a/third_party/nix/src/tests/CMakeLists.txt b/third_party/nix/src/tests/CMakeLists.txt index 724a7a95b519..33f4f774a61b 100644 --- a/third_party/nix/src/tests/CMakeLists.txt +++ b/third_party/nix/src/tests/CMakeLists.txt @@ -11,6 +11,17 @@ target_link_libraries(attr-set gtest_discover_tests(attr-set) +add_executable(derivations_test derivations_test.cc) +target_link_libraries(derivations_test + nixexpr + nixstore + rapidcheck + rapidcheck_gtest + GTest::gtest_main +) + +gtest_discover_tests(derivations_test) + add_executable(hash_test hash_test.cc) target_link_libraries(hash_test nixutil diff --git a/third_party/nix/src/tests/derivations_test.cc b/third_party/nix/src/tests/derivations_test.cc new file mode 100644 index 000000000000..e026fbe3b11c --- /dev/null +++ b/third_party/nix/src/tests/derivations_test.cc @@ -0,0 +1,106 @@ +#include "libstore/derivations.hh" + +#include <memory> + +#include <absl/strings/str_cat.h> +#include <gtest/gtest.h> +#include <rapidcheck.h> +#include <rapidcheck/Assertions.h> +#include <rapidcheck/gen/Arbitrary.h> +#include <rapidcheck/gen/Build.h> +#include <rapidcheck/gen/Container.h> +#include <rapidcheck/gen/Tuple.h> +#include <rapidcheck/gtest.h> +#include <rapidcheck/state.h> + +#include "libexpr/eval.hh" +#include "libutil/hash.hh" +#include "libutil/types.hh" + +namespace rc { + +using nix::Derivation; +using nix::DerivationOutput; + +template <> +struct Arbitrary<nix::Base> { + static Gen<nix::Base> arbitrary() { + return gen::element(nix::Base16, nix::Base32, nix::Base64); + } +}; + +template <> +struct Arbitrary<DerivationOutput> { + static Gen<DerivationOutput> arbitrary() { + return gen::apply( + [](std::string content, std::string path, std::string hash_algo, + bool recursive, bool include_algo_in_hash, nix::Base base) { + auto hash_type = nix::parseHashType(hash_algo); + auto hash = nix::hashString(hash_type, content); + return DerivationOutput( + path, recursive ? absl::StrCat("r:", hash_algo) : hash_algo, + hash.to_string(base, include_algo_in_hash)); + }, + gen::arbitrary<std::string>(), + gen::map(gen::arbitrary<std::string>(), + [](std::string s) { return absl::StrCat("/", s); }), + gen::element<std::string>("md5", "sha1", "sha256", "sha512"), + gen::arbitrary<bool>(), gen::arbitrary<bool>(), + gen::arbitrary<nix::Base>()); + } +}; + +template <> +struct Arbitrary<Derivation> { + static Gen<Derivation> arbitrary() { + auto gen_path = gen::map(gen::arbitrary<std::string>(), [](std::string s) { + return absl::StrCat("/", s); + }); + + return gen::build<Derivation>( + gen::set(&nix::BasicDerivation::outputs), + gen::set(&nix::BasicDerivation::inputSrcs, + gen::container<nix::PathSet>(gen_path)), + gen::set(&nix::BasicDerivation::platform), + gen::set(&nix::BasicDerivation::builder, gen_path), + gen::set(&nix::BasicDerivation::args), + gen::set(&nix::BasicDerivation::env), + gen::set(&Derivation::inputDrvs, + gen::container<nix::DerivationInputs>( + gen_path, gen::arbitrary<nix::StringSet>()))); + } +}; + +} // namespace rc + +namespace nix { + +void AssertDerivationsEqual(const Derivation& lhs, const Derivation& rhs) { + RC_ASSERT(lhs.outputs.size() == rhs.outputs.size()); + for (const auto& [k, lhs_v] : lhs.outputs) { + auto rhs_v = rhs.outputs.find(k); + RC_ASSERT(rhs_v != rhs.outputs.end()); + RC_ASSERT(lhs_v.path == rhs_v->second.path); + RC_ASSERT(lhs_v.hashAlgo == rhs_v->second.hashAlgo); + RC_ASSERT(lhs_v.hash == rhs_v->second.hash); + } + + RC_ASSERT(lhs.inputSrcs == rhs.inputSrcs); + RC_ASSERT(lhs.platform == rhs.platform); + RC_ASSERT(lhs.builder == rhs.builder); + RC_ASSERT(lhs.args == rhs.args); + RC_ASSERT(lhs.env == rhs.env); + RC_ASSERT(lhs.inputDrvs == rhs.inputDrvs); +} + +class DerivationsTest : public ::testing::Test {}; + +// NOLINTNEXTLINE +RC_GTEST_FIXTURE_PROP(DerivationsTest, UnparseParseRoundTrip, + (Derivation && drv)) { + auto unparsed = drv.unparse(); + auto parsed = parseDerivation(unparsed); + AssertDerivationsEqual(drv, parsed); +} + +} // namespace nix |