2023-01-10 16:27:19 +00:00
|
|
|
#include "outputs-spec.hh"
|
2022-04-22 13:17:01 +00:00
|
|
|
|
2023-01-13 03:05:55 +00:00
|
|
|
#include <nlohmann/json.hpp>
|
2022-04-22 13:17:01 +00:00
|
|
|
#include <gtest/gtest.h>
|
2023-01-29 18:52:38 +00:00
|
|
|
#include <rapidcheck/gtest.h>
|
2022-04-22 13:17:01 +00:00
|
|
|
|
|
|
|
namespace nix {
|
|
|
|
|
2023-01-13 01:41:29 +00:00
|
|
|
#ifndef NDEBUG
|
|
|
|
TEST(OutputsSpec, no_empty_names) {
|
|
|
|
ASSERT_DEATH(OutputsSpec::Names { std::set<std::string> { } }, "");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2023-01-11 22:31:32 +00:00
|
|
|
#define TEST_DONT_PARSE(NAME, STR) \
|
|
|
|
TEST(OutputsSpec, bad_ ## NAME) { \
|
|
|
|
std::optional OutputsSpecOpt = \
|
|
|
|
OutputsSpec::parseOpt(STR); \
|
|
|
|
ASSERT_FALSE(OutputsSpecOpt); \
|
2023-01-11 23:57:18 +00:00
|
|
|
}
|
|
|
|
|
2023-01-11 22:31:32 +00:00
|
|
|
TEST_DONT_PARSE(empty, "")
|
|
|
|
TEST_DONT_PARSE(garbage, "&*()")
|
|
|
|
TEST_DONT_PARSE(double_star, "**")
|
|
|
|
TEST_DONT_PARSE(star_first, "*,foo")
|
|
|
|
TEST_DONT_PARSE(star_second, "foo,*")
|
2023-01-11 23:57:18 +00:00
|
|
|
|
2023-01-11 22:31:32 +00:00
|
|
|
#undef TEST_DONT_PARSE
|
2023-01-11 23:57:18 +00:00
|
|
|
|
2023-01-11 22:31:32 +00:00
|
|
|
TEST(OutputsSpec, all) {
|
|
|
|
std::string_view str = "*";
|
|
|
|
OutputsSpec expected = OutputsSpec::All { };
|
|
|
|
ASSERT_EQ(OutputsSpec::parse(str), expected);
|
|
|
|
ASSERT_EQ(expected.to_string(), str);
|
2023-01-11 23:57:18 +00:00
|
|
|
}
|
|
|
|
|
2023-01-11 22:31:32 +00:00
|
|
|
TEST(OutputsSpec, names_out) {
|
|
|
|
std::string_view str = "out";
|
|
|
|
OutputsSpec expected = OutputsSpec::Names { "out" };
|
|
|
|
ASSERT_EQ(OutputsSpec::parse(str), expected);
|
|
|
|
ASSERT_EQ(expected.to_string(), str);
|
|
|
|
}
|
2023-01-11 23:57:18 +00:00
|
|
|
|
2023-01-18 15:34:37 +00:00
|
|
|
TEST(OutputsSpec, names_underscore) {
|
|
|
|
std::string_view str = "a_b";
|
|
|
|
OutputsSpec expected = OutputsSpec::Names { "a_b" };
|
|
|
|
ASSERT_EQ(OutputsSpec::parse(str), expected);
|
|
|
|
ASSERT_EQ(expected.to_string(), str);
|
|
|
|
}
|
|
|
|
|
2023-01-19 05:26:06 +00:00
|
|
|
TEST(OutputsSpec, names_numberic) {
|
|
|
|
std::string_view str = "01";
|
|
|
|
OutputsSpec expected = OutputsSpec::Names { "01" };
|
|
|
|
ASSERT_EQ(OutputsSpec::parse(str), expected);
|
|
|
|
ASSERT_EQ(expected.to_string(), str);
|
|
|
|
}
|
|
|
|
|
2023-01-11 22:31:32 +00:00
|
|
|
TEST(OutputsSpec, names_out_bin) {
|
|
|
|
OutputsSpec expected = OutputsSpec::Names { "out", "bin" };
|
|
|
|
ASSERT_EQ(OutputsSpec::parse("out,bin"), expected);
|
|
|
|
// N.B. This normalization is OK.
|
|
|
|
ASSERT_EQ(expected.to_string(), "bin,out");
|
|
|
|
}
|
2022-04-22 13:17:01 +00:00
|
|
|
|
2023-01-13 01:33:50 +00:00
|
|
|
#define TEST_SUBSET(X, THIS, THAT) \
|
|
|
|
X((OutputsSpec { THIS }).isSubsetOf(THAT));
|
|
|
|
|
|
|
|
TEST(OutputsSpec, subsets_all_all) {
|
|
|
|
TEST_SUBSET(ASSERT_TRUE, OutputsSpec::All { }, OutputsSpec::All { });
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(OutputsSpec, subsets_names_all) {
|
|
|
|
TEST_SUBSET(ASSERT_TRUE, OutputsSpec::Names { "a" }, OutputsSpec::All { });
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(OutputsSpec, subsets_names_names_eq) {
|
|
|
|
TEST_SUBSET(ASSERT_TRUE, OutputsSpec::Names { "a" }, OutputsSpec::Names { "a" });
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(OutputsSpec, subsets_names_names_noneq) {
|
|
|
|
TEST_SUBSET(ASSERT_TRUE, OutputsSpec::Names { "a" }, (OutputsSpec::Names { "a", "b" }));
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(OutputsSpec, not_subsets_all_names) {
|
|
|
|
TEST_SUBSET(ASSERT_FALSE, OutputsSpec::All { }, OutputsSpec::Names { "a" });
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(OutputsSpec, not_subsets_names_names) {
|
|
|
|
TEST_SUBSET(ASSERT_FALSE, (OutputsSpec::Names { "a", "b" }), (OutputsSpec::Names { "a" }));
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef TEST_SUBSET
|
|
|
|
|
|
|
|
#define TEST_UNION(RES, THIS, THAT) \
|
|
|
|
ASSERT_EQ(OutputsSpec { RES }, (OutputsSpec { THIS }).union_(THAT));
|
|
|
|
|
|
|
|
TEST(OutputsSpec, union_all_all) {
|
|
|
|
TEST_UNION(OutputsSpec::All { }, OutputsSpec::All { }, OutputsSpec::All { });
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(OutputsSpec, union_all_names) {
|
|
|
|
TEST_UNION(OutputsSpec::All { }, OutputsSpec::All { }, OutputsSpec::Names { "a" });
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(OutputsSpec, union_names_all) {
|
|
|
|
TEST_UNION(OutputsSpec::All { }, OutputsSpec::Names { "a" }, OutputsSpec::All { });
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(OutputsSpec, union_names_names) {
|
|
|
|
TEST_UNION((OutputsSpec::Names { "a", "b" }), OutputsSpec::Names { "a" }, OutputsSpec::Names { "b" });
|
|
|
|
}
|
|
|
|
|
|
|
|
#undef TEST_UNION
|
2022-04-22 13:17:01 +00:00
|
|
|
|
2023-01-11 22:31:32 +00:00
|
|
|
#define TEST_DONT_PARSE(NAME, STR) \
|
|
|
|
TEST(ExtendedOutputsSpec, bad_ ## NAME) { \
|
|
|
|
std::optional extendedOutputsSpecOpt = \
|
|
|
|
ExtendedOutputsSpec::parseOpt(STR); \
|
|
|
|
ASSERT_FALSE(extendedOutputsSpecOpt); \
|
2022-04-22 13:17:01 +00:00
|
|
|
}
|
|
|
|
|
2023-01-11 22:31:32 +00:00
|
|
|
TEST_DONT_PARSE(carot_empty, "^")
|
|
|
|
TEST_DONT_PARSE(prefix_carot_empty, "foo^")
|
2023-01-13 03:05:55 +00:00
|
|
|
TEST_DONT_PARSE(garbage, "^&*()")
|
|
|
|
TEST_DONT_PARSE(double_star, "^**")
|
|
|
|
TEST_DONT_PARSE(star_first, "^*,foo")
|
|
|
|
TEST_DONT_PARSE(star_second, "^foo,*")
|
2022-04-22 13:17:01 +00:00
|
|
|
|
2023-01-11 22:31:32 +00:00
|
|
|
#undef TEST_DONT_PARSE
|
|
|
|
|
|
|
|
TEST(ExtendedOutputsSpec, defeault) {
|
|
|
|
std::string_view str = "foo";
|
|
|
|
auto [prefix, extendedOutputsSpec] = ExtendedOutputsSpec::parse(str);
|
|
|
|
ASSERT_EQ(prefix, "foo");
|
|
|
|
ExtendedOutputsSpec expected = ExtendedOutputsSpec::Default { };
|
|
|
|
ASSERT_EQ(extendedOutputsSpec, expected);
|
|
|
|
ASSERT_EQ(std::string { prefix } + expected.to_string(), str);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(ExtendedOutputsSpec, all) {
|
|
|
|
std::string_view str = "foo^*";
|
|
|
|
auto [prefix, extendedOutputsSpec] = ExtendedOutputsSpec::parse(str);
|
|
|
|
ASSERT_EQ(prefix, "foo");
|
|
|
|
ExtendedOutputsSpec expected = OutputsSpec::All { };
|
|
|
|
ASSERT_EQ(extendedOutputsSpec, expected);
|
|
|
|
ASSERT_EQ(std::string { prefix } + expected.to_string(), str);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(ExtendedOutputsSpec, out) {
|
|
|
|
std::string_view str = "foo^out";
|
|
|
|
auto [prefix, extendedOutputsSpec] = ExtendedOutputsSpec::parse(str);
|
|
|
|
ASSERT_EQ(prefix, "foo");
|
|
|
|
ExtendedOutputsSpec expected = OutputsSpec::Names { "out" };
|
|
|
|
ASSERT_EQ(extendedOutputsSpec, expected);
|
|
|
|
ASSERT_EQ(std::string { prefix } + expected.to_string(), str);
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(ExtendedOutputsSpec, out_bin) {
|
|
|
|
auto [prefix, extendedOutputsSpec] = ExtendedOutputsSpec::parse("foo^out,bin");
|
|
|
|
ASSERT_EQ(prefix, "foo");
|
|
|
|
ExtendedOutputsSpec expected = OutputsSpec::Names { "out", "bin" };
|
|
|
|
ASSERT_EQ(extendedOutputsSpec, expected);
|
|
|
|
ASSERT_EQ(std::string { prefix } + expected.to_string(), "foo^bin,out");
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST(ExtendedOutputsSpec, many_carrot) {
|
|
|
|
auto [prefix, extendedOutputsSpec] = ExtendedOutputsSpec::parse("foo^bar^out,bin");
|
|
|
|
ASSERT_EQ(prefix, "foo^bar");
|
|
|
|
ExtendedOutputsSpec expected = OutputsSpec::Names { "out", "bin" };
|
|
|
|
ASSERT_EQ(extendedOutputsSpec, expected);
|
|
|
|
ASSERT_EQ(std::string { prefix } + expected.to_string(), "foo^bar^bin,out");
|
2022-04-22 13:17:01 +00:00
|
|
|
}
|
|
|
|
|
2023-01-13 03:05:55 +00:00
|
|
|
|
|
|
|
#define TEST_JSON(TYPE, NAME, STR, VAL) \
|
|
|
|
\
|
|
|
|
TEST(TYPE, NAME ## _to_json) { \
|
|
|
|
using nlohmann::literals::operator "" _json; \
|
|
|
|
ASSERT_EQ( \
|
|
|
|
STR ## _json, \
|
|
|
|
((nlohmann::json) TYPE { VAL })); \
|
|
|
|
} \
|
|
|
|
\
|
|
|
|
TEST(TYPE, NAME ## _from_json) { \
|
|
|
|
using nlohmann::literals::operator "" _json; \
|
|
|
|
ASSERT_EQ( \
|
|
|
|
TYPE { VAL }, \
|
|
|
|
(STR ## _json).get<TYPE>()); \
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_JSON(OutputsSpec, all, R"(["*"])", OutputsSpec::All { })
|
|
|
|
TEST_JSON(OutputsSpec, name, R"(["a"])", OutputsSpec::Names { "a" })
|
|
|
|
TEST_JSON(OutputsSpec, names, R"(["a","b"])", (OutputsSpec::Names { "a", "b" }))
|
|
|
|
|
|
|
|
TEST_JSON(ExtendedOutputsSpec, def, R"(null)", ExtendedOutputsSpec::Default { })
|
|
|
|
TEST_JSON(ExtendedOutputsSpec, all, R"(["*"])", ExtendedOutputsSpec::Explicit { OutputsSpec::All { } })
|
|
|
|
TEST_JSON(ExtendedOutputsSpec, name, R"(["a"])", ExtendedOutputsSpec::Explicit { OutputsSpec::Names { "a" } })
|
|
|
|
TEST_JSON(ExtendedOutputsSpec, names, R"(["a","b"])", (ExtendedOutputsSpec::Explicit { OutputsSpec::Names { "a", "b" } }))
|
|
|
|
|
|
|
|
#undef TEST_JSON
|
|
|
|
|
2022-04-22 13:17:01 +00:00
|
|
|
}
|
2023-01-29 18:52:38 +00:00
|
|
|
|
|
|
|
namespace rc {
|
|
|
|
using namespace nix;
|
|
|
|
|
|
|
|
Gen<OutputsSpec> Arbitrary<OutputsSpec>::arbitrary()
|
|
|
|
{
|
2023-05-12 03:22:35 +00:00
|
|
|
switch (*gen::inRange<uint8_t>(0, std::variant_size_v<OutputsSpec::Raw>)) {
|
2023-01-29 18:52:38 +00:00
|
|
|
case 0:
|
|
|
|
return gen::just((OutputsSpec) OutputsSpec::All { });
|
2023-05-12 03:22:35 +00:00
|
|
|
case 1:
|
2023-01-29 18:52:38 +00:00
|
|
|
return gen::just((OutputsSpec) OutputsSpec::Names {
|
|
|
|
*gen::nonEmpty(gen::container<StringSet>(gen::map(
|
|
|
|
gen::arbitrary<StorePathName>(),
|
|
|
|
[](StorePathName n) { return n.name; }))),
|
|
|
|
});
|
2023-05-12 03:22:35 +00:00
|
|
|
default:
|
|
|
|
assert(false);
|
2023-01-29 18:52:38 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
namespace nix {
|
|
|
|
|
2023-09-19 14:04:00 +00:00
|
|
|
#ifndef COVERAGE
|
|
|
|
|
2023-01-29 18:52:38 +00:00
|
|
|
RC_GTEST_PROP(
|
|
|
|
OutputsSpec,
|
|
|
|
prop_round_rip,
|
|
|
|
(const OutputsSpec & o))
|
|
|
|
{
|
|
|
|
RC_ASSERT(o == OutputsSpec::parse(o.to_string()));
|
|
|
|
}
|
|
|
|
|
2023-09-19 14:04:00 +00:00
|
|
|
#endif
|
|
|
|
|
2023-01-29 18:52:38 +00:00
|
|
|
}
|