1#include <xrpl/beast/core/SemanticVersion.h>
3#include <gtest/gtest.h>
21identifierFor(std::string_view version)
23 std::string name{version};
34constexpr auto kValidPreRelease =
35 std::to_array<std::string_view>({
"",
"-1",
"-a",
"-a1",
"-a1.b1",
"-ab.cd",
"--"});
36constexpr auto kInvalidPreRelease =
37 std::to_array<std::string_view>({
"+",
"!",
"-",
"-!",
"-.",
"-a.!",
"-0.a"});
38constexpr auto kValidMetaData = std::to_array<std::string_view>({
"",
"+a",
"+1",
"+a.b",
"+ab.cd"});
39constexpr auto kInvalidMetaData =
40 std::to_array<std::string_view>({
"!",
"+",
"++",
"+!",
"+.",
"+a.!"});
46 std::string_view base,
47 std::string_view preRelease,
48 std::string_view metaData,
51 auto const input = std::string{base}.
append(preRelease).append(metaData);
52 SCOPED_TRACE(::testing::Message() <<
'"' << input <<
'"');
58 EXPECT_TRUE(v.parse(input));
59 EXPECT_EQ(v.print(), input);
63 EXPECT_FALSE(v.parse(input));
69 std::string_view testName;
70 std::string_view base;
75parseCaseName(::testing::TestParamInfo<ParseCase>
const& info)
77 return std::string{info.param.testName};
80constexpr auto kParseCases = std::to_array<ParseCase>({
81 {.testName =
"zeroes", .base =
"0.0.0", .shouldPass =
true},
82 {.testName =
"simple", .base =
"1.2.3", .shouldPass =
true},
83 {.testName =
"max_int", .base =
"2147483647.2147483647.2147483647", .shouldPass =
true},
86 {.testName =
"negative_major", .base =
"-1.2.3", .shouldPass =
false},
87 {.testName =
"negative_minor", .base =
"1.-2.3", .shouldPass =
false},
88 {.testName =
"negative_patch", .base =
"1.2.-3", .shouldPass =
false},
91 {.testName =
"empty", .base =
"", .shouldPass =
false},
92 {.testName =
"major_only", .base =
"1", .shouldPass =
false},
93 {.testName =
"major_then_dot", .base =
"1.", .shouldPass =
false},
94 {.testName =
"major_and_minor", .base =
"1.2", .shouldPass =
false},
95 {.testName =
"major_minor_then_dot", .base =
"1.2.", .shouldPass =
false},
96 {.testName =
"missing_major", .base =
".2.3", .shouldPass =
false},
99 {.testName =
"leading_space", .base =
" 1.2.3", .shouldPass =
false},
100 {.testName =
"space_after_major", .base =
"1 .2.3", .shouldPass =
false},
101 {.testName =
"space_after_minor", .base =
"1.2 .3", .shouldPass =
false},
102 {.testName =
"trailing_space", .base =
"1.2.3 ", .shouldPass =
false},
105 {.testName =
"leading_zero_in_major", .base =
"01.2.3", .shouldPass =
false},
106 {.testName =
"leading_zero_in_minor", .base =
"1.02.3", .shouldPass =
false},
107 {.testName =
"leading_zero_in_patch", .base =
"1.2.03", .shouldPass =
false},
112 std::string_view testName;
113 std::string_view input;
117 IdentifierList preReleaseIdentifiers{};
118 IdentifierList metaData{};
122valuesCaseName(::testing::TestParamInfo<ValuesCase>
const& info)
124 return std::string{info.param.testName};
127std::vector<ValuesCase>
const kValuesCases{
129 .testName =
"zero_major",
136 .testName =
"simple",
143 .testName =
"one_pre_release_identifier",
144 .input =
"1.2.3-rc1",
148 .preReleaseIdentifiers = {
"rc1"},
151 .testName =
"two_pre_release_identifiers",
152 .input =
"1.2.3-rc1.debug",
156 .preReleaseIdentifiers = {
"rc1",
"debug"},
159 .testName =
"three_pre_release_identifiers",
160 .input =
"1.2.3-rc1.debug.asm",
164 .preReleaseIdentifiers = {
"rc1",
"debug",
"asm"},
167 .testName =
"one_metadata_identifier",
168 .input =
"1.2.3+full",
172 .metaData = {
"full"},
175 .testName =
"two_metadata_identifiers",
176 .input =
"1.2.3+full.prod",
180 .metaData = {
"full",
"prod"},
183 .testName =
"three_metadata_identifiers",
184 .input =
"1.2.3+full.prod.x86",
188 .metaData = {
"full",
"prod",
"x86"},
191 .testName =
"pre_release_and_metadata",
192 .input =
"1.2.3-rc1.debug.asm+full.prod.x86",
196 .preReleaseIdentifiers = {
"rc1",
"debug",
"asm"},
197 .metaData = {
"full",
"prod",
"x86"},
203 std::string_view lesser;
204 std::string_view greater;
208orderCaseName(::testing::TestParamInfo<OrderCase>
const& info)
210 return identifierFor(info.param.lesser) +
"_below_" + identifierFor(info.param.greater);
213constexpr auto kOrderCases = std::to_array<OrderCase>({
214 {.lesser =
"1.0.0-alpha", .greater =
"1.0.0-alpha.1"},
215 {.lesser =
"1.0.0-alpha.1", .greater =
"1.0.0-alpha.beta"},
216 {.lesser =
"1.0.0-alpha.beta", .greater =
"1.0.0-beta"},
217 {.lesser =
"1.0.0-beta", .greater =
"1.0.0-beta.2"},
218 {.lesser =
"1.0.0-beta.2", .greater =
"1.0.0-beta.11"},
219 {.lesser =
"1.0.0-beta.11", .greater =
"1.0.0-rc.1"},
220 {.lesser =
"1.0.0-rc.1", .greater =
"1.0.0"},
221 {.lesser =
"0.9.9", .greater =
"1.0.0"},
234 auto const& [testName, base, shouldPass] = GetParam();
236 for (
auto const preRelease : kValidPreRelease)
238 for (
auto const metaData : kValidMetaData)
239 expectParse(base, preRelease, metaData, shouldPass);
241 for (
auto const metaData : kInvalidMetaData)
242 expectParse(base, preRelease, metaData,
false);
247 for (
auto const preRelease : kInvalidPreRelease)
249 for (
auto const metaData : kValidMetaData)
250 expectParse(base, preRelease, metaData,
false);
252 for (
auto const metaData : kInvalidMetaData)
253 expectParse(base, preRelease, metaData,
false);
260 ::testing::ValuesIn(kParseCases),
269 auto const& expected = GetParam();
272 EXPECT_TRUE(v.
parse(expected.input));
279 EXPECT_EQ(v.
metaData, expected.metaData);
285 ::testing::ValuesIn(kValuesCases),
294 auto const& [lesser, greater] = GetParam();
298 static constexpr auto kMetaData = std::to_array<std::string_view>({
"",
"+meta"});
300 for (
auto const lesserMetaData : kMetaData)
302 for (
auto const greaterMetaData : kMetaData)
307 ::testing::Message() <<
'"' << lesserInput <<
"\" < \"" << greaterInput <<
'"');
311 EXPECT_TRUE(lesserVersion.
parse(lesserInput));
312 EXPECT_TRUE(greaterVersion.
parse(greaterInput));
314 EXPECT_EQ(
compare(lesserVersion, lesserVersion), 0);
315 EXPECT_EQ(
compare(greaterVersion, greaterVersion), 0);
316 EXPECT_LT(
compare(lesserVersion, greaterVersion), 0);
317 EXPECT_GT(
compare(greaterVersion, lesserVersion), 0);
319 EXPECT_LT(lesserVersion, greaterVersion);
320 EXPECT_GT(greaterVersion, lesserVersion);
321 EXPECT_EQ(lesserVersion, lesserVersion);
322 EXPECT_EQ(greaterVersion, greaterVersion);
330 ::testing::ValuesIn(kOrderCases),
A Semantic Version number.
IdentifierList preReleaseIdentifiers
bool parse(std::string_view input)
Parse a semantic version string.
std::vector< std::string > IdentifierList
int compare(SemanticVersion const &lhs, SemanticVersion const &rhs)
Compare two SemanticVersions against each other.
INSTANTIATE_TEST_SUITE_P(Inputs, SemanticVersionParse, ::testing::ValuesIn(kParseCases), parseCaseName)
TEST_P(SemanticVersionParse, pre_release_and_metadata_combinations)