|
| 1 | +#include <nlohmann/json.hpp> |
| 2 | +#include <gtest/gtest.h> |
| 3 | +#include <optional> |
| 4 | + |
| 5 | +#include "experimental-features.hh" |
| 6 | +#include "derivations.hh" |
| 7 | + |
| 8 | +#include "tests/libstore.hh" |
| 9 | +#include "tests/characterization.hh" |
| 10 | +#include "parsed-derivations.hh" |
| 11 | +#include "types.hh" |
| 12 | + |
| 13 | +namespace nix { |
| 14 | + |
| 15 | +using nlohmann::json; |
| 16 | + |
| 17 | +class DerivationAdvancedAttrsTest : public CharacterizationTest, public LibStoreTest |
| 18 | +{ |
| 19 | + Path unitTestData = getUnitTestData() + "/derivation"; |
| 20 | + |
| 21 | +public: |
| 22 | + Path goldenMaster(std::string_view testStem) const override |
| 23 | + { |
| 24 | + return unitTestData + "/" + testStem; |
| 25 | + } |
| 26 | +}; |
| 27 | + |
| 28 | +#define TEST_ATERM_JSON(STEM, NAME) \ |
| 29 | + TEST_F(DerivationAdvancedAttrsTest, Derivation_##STEM##_from_json) \ |
| 30 | + { \ |
| 31 | + readTest(NAME ".json", [&](const auto & encoded_) { \ |
| 32 | + auto encoded = json::parse(encoded_); \ |
| 33 | + /* Use DRV file instead of C++ literal as source of truth. */ \ |
| 34 | + auto aterm = readFile(goldenMaster(NAME ".drv")); \ |
| 35 | + auto expected = parseDerivation(*store, std::move(aterm), NAME); \ |
| 36 | + Derivation got = Derivation::fromJSON(*store, encoded); \ |
| 37 | + EXPECT_EQ(got, expected); \ |
| 38 | + }); \ |
| 39 | + } \ |
| 40 | + \ |
| 41 | + TEST_F(DerivationAdvancedAttrsTest, Derivation_##STEM##_to_json) \ |
| 42 | + { \ |
| 43 | + writeTest( \ |
| 44 | + NAME ".json", \ |
| 45 | + [&]() -> json { \ |
| 46 | + /* Use DRV file instead of C++ literal as source of truth. */ \ |
| 47 | + auto aterm = readFile(goldenMaster(NAME ".drv")); \ |
| 48 | + return parseDerivation(*store, std::move(aterm), NAME).toJSON(*store); \ |
| 49 | + }, \ |
| 50 | + [](const auto & file) { return json::parse(readFile(file)); }, \ |
| 51 | + [](const auto & file, const auto & got) { return writeFile(file, got.dump(2) + "\n"); }); \ |
| 52 | + } \ |
| 53 | + \ |
| 54 | + TEST_F(DerivationAdvancedAttrsTest, Derivation_##STEM##_from_aterm) \ |
| 55 | + { \ |
| 56 | + readTest(NAME ".drv", [&](auto encoded) { \ |
| 57 | + /* Use JSON file instead of C++ literal as source of truth. */ \ |
| 58 | + auto json = json::parse(readFile(goldenMaster(NAME ".json"))); \ |
| 59 | + auto expected = Derivation::fromJSON(*store, json); \ |
| 60 | + auto got = parseDerivation(*store, std::move(encoded), NAME); \ |
| 61 | + EXPECT_EQ(got.toJSON(*store), expected.toJSON(*store)); \ |
| 62 | + EXPECT_EQ(got, expected); \ |
| 63 | + }); \ |
| 64 | + } \ |
| 65 | + \ |
| 66 | + /* No corresponding write test, because we need to read the drv to write the json file */ |
| 67 | + |
| 68 | +TEST_ATERM_JSON(advancedAttributes_defaults, "advanced-attributes-defaults"); |
| 69 | +TEST_ATERM_JSON(advancedAttributes, "advanced-attributes-defaults"); |
| 70 | +TEST_ATERM_JSON(advancedAttributes_structuredAttrs_defaults, "advanced-attributes-structured-attrs"); |
| 71 | +TEST_ATERM_JSON(advancedAttributes_structuredAttrs, "advanced-attributes-structured-attrs-defaults"); |
| 72 | + |
| 73 | +#undef TEST_ATERM_JSON |
| 74 | + |
| 75 | +TEST_F(DerivationAdvancedAttrsTest, Derivation_advancedAttributes_defaults) |
| 76 | +{ |
| 77 | + readTest("advanced-attributes-defaults.drv", [&](auto encoded) { |
| 78 | + auto got = parseDerivation(*store, std::move(encoded), "foo"); |
| 79 | + |
| 80 | + auto drvPath = writeDerivation(*store, got, NoRepair, true); |
| 81 | + |
| 82 | + ParsedDerivation parsedDrv(drvPath, got); |
| 83 | + |
| 84 | + EXPECT_EQ(parsedDrv.getStringAttr("__sandboxProfile").value_or(""), ""); |
| 85 | + EXPECT_EQ(parsedDrv.getBoolAttr("__noChroot"), false); |
| 86 | + EXPECT_EQ(parsedDrv.getStringsAttr("__impureHostDeps").value_or(Strings()), Strings()); |
| 87 | + EXPECT_EQ(parsedDrv.getStringsAttr("impureEnvVars").value_or(Strings()), Strings()); |
| 88 | + EXPECT_EQ(parsedDrv.getBoolAttr("__darwinAllowLocalNetworking"), false); |
| 89 | + EXPECT_EQ(parsedDrv.getStringsAttr("allowedReferences"), std::nullopt); |
| 90 | + EXPECT_EQ(parsedDrv.getStringsAttr("allowedRequisites"), std::nullopt); |
| 91 | + EXPECT_EQ(parsedDrv.getStringsAttr("disallowedReferences"), std::nullopt); |
| 92 | + EXPECT_EQ(parsedDrv.getStringsAttr("disallowedRequisites"), std::nullopt); |
| 93 | + EXPECT_EQ(parsedDrv.getRequiredSystemFeatures(), StringSet()); |
| 94 | + EXPECT_EQ(parsedDrv.canBuildLocally(*store), false); |
| 95 | + EXPECT_EQ(parsedDrv.willBuildLocally(*store), false); |
| 96 | + EXPECT_EQ(parsedDrv.substitutesAllowed(), true); |
| 97 | + EXPECT_EQ(parsedDrv.useUidRange(), false); |
| 98 | + }); |
| 99 | +}; |
| 100 | + |
| 101 | +TEST_F(DerivationAdvancedAttrsTest, Derivation_advancedAttributes) |
| 102 | +{ |
| 103 | + readTest("advanced-attributes.drv", [&](auto encoded) { |
| 104 | + auto got = parseDerivation(*store, std::move(encoded), "foo"); |
| 105 | + |
| 106 | + auto drvPath = writeDerivation(*store, got, NoRepair, true); |
| 107 | + |
| 108 | + ParsedDerivation parsedDrv(drvPath, got); |
| 109 | + |
| 110 | + StringSet systemFeatures{"rainbow", "uid-range"}; |
| 111 | + |
| 112 | + EXPECT_EQ(parsedDrv.getStringAttr("__sandboxProfile").value_or(""), "sandcastle"); |
| 113 | + EXPECT_EQ(parsedDrv.getBoolAttr("__noChroot"), true); |
| 114 | + EXPECT_EQ(parsedDrv.getStringsAttr("__impureHostDeps").value_or(Strings()), Strings{"/usr/bin/ditto"}); |
| 115 | + EXPECT_EQ(parsedDrv.getStringsAttr("impureEnvVars").value_or(Strings()), Strings{"UNICORN"}); |
| 116 | + EXPECT_EQ(parsedDrv.getBoolAttr("__darwinAllowLocalNetworking"), true); |
| 117 | + EXPECT_EQ( |
| 118 | + parsedDrv.getStringsAttr("allowedReferences"), Strings{"/nix/store/3c08bzb71z4wiag719ipjxr277653ynp-foo"}); |
| 119 | + EXPECT_EQ( |
| 120 | + parsedDrv.getStringsAttr("allowedRequisites"), Strings{"/nix/store/3c08bzb71z4wiag719ipjxr277653ynp-foo"}); |
| 121 | + EXPECT_EQ( |
| 122 | + parsedDrv.getStringsAttr("disallowedReferences"), |
| 123 | + Strings{"/nix/store/7rhsm8i393hm1wcsmph782awg1hi2f7x-bar"}); |
| 124 | + EXPECT_EQ( |
| 125 | + parsedDrv.getStringsAttr("disallowedRequisites"), |
| 126 | + Strings{"/nix/store/7rhsm8i393hm1wcsmph782awg1hi2f7x-bar"}); |
| 127 | + EXPECT_EQ(parsedDrv.getRequiredSystemFeatures(), systemFeatures); |
| 128 | + EXPECT_EQ(parsedDrv.canBuildLocally(*store), false); |
| 129 | + EXPECT_EQ(parsedDrv.willBuildLocally(*store), false); |
| 130 | + EXPECT_EQ(parsedDrv.substitutesAllowed(), false); |
| 131 | + EXPECT_EQ(parsedDrv.useUidRange(), true); |
| 132 | + }); |
| 133 | +}; |
| 134 | + |
| 135 | +TEST_F(DerivationAdvancedAttrsTest, Derivation_advancedAttributes_structuredAttrs_defaults) |
| 136 | +{ |
| 137 | + readTest("advanced-attributes-structured-attrs-defaults.drv", [&](auto encoded) { |
| 138 | + auto got = parseDerivation(*store, std::move(encoded), "foo"); |
| 139 | + |
| 140 | + auto drvPath = writeDerivation(*store, got, NoRepair, true); |
| 141 | + |
| 142 | + ParsedDerivation parsedDrv(drvPath, got); |
| 143 | + |
| 144 | + EXPECT_EQ(parsedDrv.getStringAttr("__sandboxProfile").value_or(""), ""); |
| 145 | + EXPECT_EQ(parsedDrv.getBoolAttr("__noChroot"), false); |
| 146 | + EXPECT_EQ(parsedDrv.getStringsAttr("__impureHostDeps").value_or(Strings()), Strings()); |
| 147 | + EXPECT_EQ(parsedDrv.getStringsAttr("impureEnvVars").value_or(Strings()), Strings()); |
| 148 | + EXPECT_EQ(parsedDrv.getBoolAttr("__darwinAllowLocalNetworking"), false); |
| 149 | + |
| 150 | + { |
| 151 | + auto structuredAttrs_ = parsedDrv.getStructuredAttrs(); |
| 152 | + ASSERT_TRUE(structuredAttrs_); |
| 153 | + auto & structuredAttrs = *structuredAttrs_; |
| 154 | + |
| 155 | + auto outputChecks_ = get(structuredAttrs, "outputChecks"); |
| 156 | + ASSERT_FALSE(outputChecks_); |
| 157 | + } |
| 158 | + |
| 159 | + EXPECT_EQ(parsedDrv.getRequiredSystemFeatures(), StringSet()); |
| 160 | + EXPECT_EQ(parsedDrv.canBuildLocally(*store), false); |
| 161 | + EXPECT_EQ(parsedDrv.willBuildLocally(*store), false); |
| 162 | + EXPECT_EQ(parsedDrv.substitutesAllowed(), true); |
| 163 | + EXPECT_EQ(parsedDrv.useUidRange(), false); |
| 164 | + }); |
| 165 | +}; |
| 166 | + |
| 167 | +TEST_F(DerivationAdvancedAttrsTest, Derivation_advancedAttributes_structuredAttrs) |
| 168 | +{ |
| 169 | + readTest("advanced-attributes-structured-attrs.drv", [&](auto encoded) { |
| 170 | + auto got = parseDerivation(*store, std::move(encoded), "foo"); |
| 171 | + |
| 172 | + auto drvPath = writeDerivation(*store, got, NoRepair, true); |
| 173 | + |
| 174 | + ParsedDerivation parsedDrv(drvPath, got); |
| 175 | + |
| 176 | + StringSet systemFeatures{"rainbow", "uid-range"}; |
| 177 | + |
| 178 | + EXPECT_EQ(parsedDrv.getStringAttr("__sandboxProfile").value_or(""), "sandcastle"); |
| 179 | + EXPECT_EQ(parsedDrv.getBoolAttr("__noChroot"), true); |
| 180 | + EXPECT_EQ(parsedDrv.getStringsAttr("__impureHostDeps").value_or(Strings()), Strings{"/usr/bin/ditto"}); |
| 181 | + EXPECT_EQ(parsedDrv.getStringsAttr("impureEnvVars").value_or(Strings()), Strings{"UNICORN"}); |
| 182 | + EXPECT_EQ(parsedDrv.getBoolAttr("__darwinAllowLocalNetworking"), true); |
| 183 | + |
| 184 | + { |
| 185 | + auto structuredAttrs_ = parsedDrv.getStructuredAttrs(); |
| 186 | + ASSERT_TRUE(structuredAttrs_); |
| 187 | + auto & structuredAttrs = *structuredAttrs_; |
| 188 | + |
| 189 | + auto outputChecks_ = get(structuredAttrs, "outputChecks"); |
| 190 | + ASSERT_TRUE(outputChecks_); |
| 191 | + auto & outputChecks = *outputChecks_; |
| 192 | + |
| 193 | + { |
| 194 | + auto output_ = get(outputChecks, "out"); |
| 195 | + ASSERT_TRUE(output_); |
| 196 | + auto & output = *output_; |
| 197 | + EXPECT_EQ( |
| 198 | + get(output, "allowedReferences")->get<Strings>(), |
| 199 | + Strings{"/nix/store/3c08bzb71z4wiag719ipjxr277653ynp-foo"}); |
| 200 | + EXPECT_EQ( |
| 201 | + get(output, "allowedRequisites")->get<Strings>(), |
| 202 | + Strings{"/nix/store/3c08bzb71z4wiag719ipjxr277653ynp-foo"}); |
| 203 | + } |
| 204 | + |
| 205 | + { |
| 206 | + auto output_ = get(outputChecks, "bin"); |
| 207 | + ASSERT_TRUE(output_); |
| 208 | + auto & output = *output_; |
| 209 | + EXPECT_EQ( |
| 210 | + get(output, "disallowedReferences")->get<Strings>(), |
| 211 | + Strings{"/nix/store/7rhsm8i393hm1wcsmph782awg1hi2f7x-bar"}); |
| 212 | + EXPECT_EQ( |
| 213 | + get(output, "disallowedRequisites")->get<Strings>(), |
| 214 | + Strings{"/nix/store/7rhsm8i393hm1wcsmph782awg1hi2f7x-bar"}); |
| 215 | + } |
| 216 | + |
| 217 | + { |
| 218 | + auto output_ = get(outputChecks, "dev"); |
| 219 | + ASSERT_TRUE(output_); |
| 220 | + auto & output = *output_; |
| 221 | + EXPECT_EQ(get(output, "maxSize")->get<uint64_t>(), 789); |
| 222 | + EXPECT_EQ(get(output, "maxClosureSize")->get<uint64_t>(), 5909); |
| 223 | + } |
| 224 | + } |
| 225 | + |
| 226 | + EXPECT_EQ(parsedDrv.getRequiredSystemFeatures(), systemFeatures); |
| 227 | + EXPECT_EQ(parsedDrv.canBuildLocally(*store), false); |
| 228 | + EXPECT_EQ(parsedDrv.willBuildLocally(*store), false); |
| 229 | + EXPECT_EQ(parsedDrv.substitutesAllowed(), false); |
| 230 | + EXPECT_EQ(parsedDrv.useUidRange(), true); |
| 231 | + }); |
| 232 | +}; |
| 233 | + |
| 234 | +} |
0 commit comments