TestSemVer.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248
  1. /*
  2. * Copyright (c) 2023, Gurkirat Singh <tbhaxor@gmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/StringView.h>
  7. #include <AK/Tuple.h>
  8. #include <AK/Vector.h>
  9. #include <LibSemVer/SemVer.h>
  10. #include <LibTest/TestCase.h>
  11. #define GET_SEMVER(expression) \
  12. ({ \
  13. auto r = (SemVer::from_string_view(expression)); \
  14. EXPECT(!r.is_error()); \
  15. r.value(); \
  16. })
  17. #define GET_STRING(expression) \
  18. ({ \
  19. auto r = (String::from_utf8(expression)); \
  20. EXPECT(!r.is_error()); \
  21. r.value(); \
  22. })
  23. #define IS_SAME_SCENARIO(x, y, op) \
  24. GET_SEMVER(x).is_same(GET_SEMVER(y), op)
  25. #define IS_GREATER_THAN_SCENARIO(x, y) \
  26. GET_SEMVER(x).is_greater_than(GET_SEMVER(y))
  27. #define IS_LESSER_THAN_SCENARIO(x, y) \
  28. GET_SEMVER(x).is_lesser_than(GET_SEMVER(y))
  29. TEST_CASE(to_string) // NOLINT(readability-function-cognitive-complexity, readability-function-size)
  30. {
  31. EXPECT_EQ(GET_SEMVER("1.2.3"sv).to_string(), GET_STRING("1.2.3"sv));
  32. EXPECT_EQ(GET_SEMVER("1.2.3"sv).to_string(), GET_STRING("1.2.3"sv));
  33. EXPECT_EQ(GET_SEMVER("10.20.30"sv).to_string(), GET_STRING("10.20.30"sv));
  34. EXPECT_EQ(GET_SEMVER("1.1.2-prerelease+meta"sv).to_string(), GET_STRING("1.1.2-prerelease+meta"sv));
  35. EXPECT_EQ(GET_SEMVER("1.1.2+meta"sv).to_string(), GET_STRING("1.1.2+meta"sv));
  36. EXPECT_EQ(GET_SEMVER("1.1.2+meta-valid"sv).to_string(), GET_STRING("1.1.2+meta-valid"sv));
  37. EXPECT_EQ(GET_SEMVER("1.0.0-alpha"sv).to_string(), GET_STRING("1.0.0-alpha"sv));
  38. EXPECT_EQ(GET_SEMVER("1.0.0-beta"sv).to_string(), GET_STRING("1.0.0-beta"sv));
  39. EXPECT_EQ(GET_SEMVER("1.0.0-alpha.beta"sv).to_string(), GET_STRING("1.0.0-alpha.beta"sv));
  40. EXPECT_EQ(GET_SEMVER("1.0.0-alpha.beta.1"sv).to_string(), GET_STRING("1.0.0-alpha.beta.1"sv));
  41. EXPECT_EQ(GET_SEMVER("1.0.0-alpha.1"sv).to_string(), GET_STRING("1.0.0-alpha.1"sv));
  42. EXPECT_EQ(GET_SEMVER("1.0.0-alpha0.valid"sv).to_string(), GET_STRING("1.0.0-alpha0.valid"sv));
  43. EXPECT_EQ(GET_SEMVER("1.0.0-alpha.0valid"sv).to_string(), GET_STRING("1.0.0-alpha.0valid"sv));
  44. EXPECT_EQ(GET_SEMVER("1.0.0-rc.1+build.1"sv).to_string(), GET_STRING("1.0.0-rc.1+build.1"sv));
  45. EXPECT_EQ(GET_SEMVER("2.0.0-rc.1+build.123"sv).to_string(), GET_STRING("2.0.0-rc.1+build.123"sv));
  46. EXPECT_EQ(GET_SEMVER("1.2.3-beta"sv).to_string(), GET_STRING("1.2.3-beta"sv));
  47. EXPECT_EQ(GET_SEMVER("10.2.3-DEV-SNAPSHOT"sv).to_string(), GET_STRING("10.2.3-DEV-SNAPSHOT"sv));
  48. EXPECT_EQ(GET_SEMVER("1.2.3-SNAPSHOT-123"sv).to_string(), GET_STRING("1.2.3-SNAPSHOT-123"sv));
  49. EXPECT_EQ(GET_SEMVER("1.0.0"sv).to_string(), GET_STRING("1.0.0"sv));
  50. EXPECT_EQ(GET_SEMVER("2.0.0"sv).to_string(), GET_STRING("2.0.0"sv));
  51. EXPECT_EQ(GET_SEMVER("1.1.7"sv).to_string(), GET_STRING("1.1.7"sv));
  52. EXPECT_EQ(GET_SEMVER("2.0.0+build.1848"sv).to_string(), GET_STRING("2.0.0+build.1848"sv));
  53. EXPECT_EQ(GET_SEMVER("2.0.1-alpha.1227"sv).to_string(), GET_STRING("2.0.1-alpha.1227"sv));
  54. EXPECT_EQ(GET_SEMVER("1.0.0-alpha+beta"sv).to_string(), GET_STRING("1.0.0-alpha+beta"sv));
  55. EXPECT_EQ(GET_SEMVER("1.0.0-alpha-a.b-c-somethinglong+build.1-aef.1-its-okay"sv).to_string(), GET_STRING("1.0.0-alpha-a.b-c-somethinglong+build.1-aef.1-its-okay"sv));
  56. EXPECT_EQ(GET_SEMVER("1.2.3----RC-SNAPSHOT.12.9.1--.12+788"sv).to_string(), GET_STRING("1.2.3----RC-SNAPSHOT.12.9.1--.12+788"sv));
  57. EXPECT_EQ(GET_SEMVER("1.2.3----RC-SNAPSHOT.12.9.1--"sv).to_string(), GET_STRING("1.2.3----RC-SNAPSHOT.12.9.1--"sv));
  58. EXPECT_EQ(GET_SEMVER("1.2.3----R-S.12.9.1--.12+meta"sv).to_string(), GET_STRING("1.2.3----R-S.12.9.1--.12+meta"sv));
  59. EXPECT_EQ(GET_SEMVER("1.2.3----RC-SNAPSHOT.12.9.1--.12"sv).to_string(), GET_STRING("1.2.3----RC-SNAPSHOT.12.9.1--.12"sv));
  60. EXPECT_EQ(GET_SEMVER("1.0.0+0.build.1-rc.10000aaa-kk-0.1"sv).to_string(), GET_STRING("1.0.0+0.build.1-rc.10000aaa-kk-0.1"sv));
  61. EXPECT_EQ(GET_SEMVER("1.0.0-0A.is.legal"sv).to_string(), GET_STRING("1.0.0-0A.is.legal"sv));
  62. }
  63. TEST_CASE(normal_bump) // NOLINT(readability-function-cognitive-complexity)
  64. {
  65. auto version = GET_SEMVER("1.1.2-prerelease+meta"sv);
  66. // normal bumps
  67. auto major_bump = version.bump(SemVer::BumpType::Major);
  68. EXPECT_EQ(major_bump.major(), version.major() + 1);
  69. EXPECT_EQ(major_bump.minor(), 0ul);
  70. EXPECT_EQ(major_bump.patch(), 0ul);
  71. EXPECT(major_bump.suffix().is_empty());
  72. auto minor_bump = version.bump(SemVer::BumpType::Minor);
  73. EXPECT_EQ(minor_bump.major(), version.major());
  74. EXPECT_EQ(minor_bump.minor(), version.minor() + 1);
  75. EXPECT_EQ(minor_bump.patch(), 0ul);
  76. EXPECT(minor_bump.suffix().is_empty());
  77. auto patch_bump = version.bump(SemVer::BumpType::Patch);
  78. EXPECT_EQ(patch_bump.major(), version.major());
  79. EXPECT_EQ(patch_bump.minor(), version.minor());
  80. EXPECT_EQ(patch_bump.patch(), version.patch() + 1);
  81. EXPECT(minor_bump.suffix().is_empty());
  82. }
  83. TEST_CASE(prerelease_bump_increment_numeric)
  84. {
  85. auto version = GET_SEMVER("1.1.2-0"sv);
  86. auto prerelease_bump = version.bump(SemVer::BumpType::Prerelease);
  87. EXPECT_EQ(prerelease_bump.major(), version.major());
  88. EXPECT_EQ(prerelease_bump.minor(), version.minor());
  89. EXPECT_EQ(prerelease_bump.patch(), version.patch());
  90. EXPECT_NE(prerelease_bump.prerelease(), version.prerelease());
  91. EXPECT(prerelease_bump.build_metadata().is_empty());
  92. auto version_prerelease_parts = version.prerelease_identifiers();
  93. auto bumped_prerelease_parts = prerelease_bump.prerelease_identifiers();
  94. EXPECT_EQ(bumped_prerelease_parts.size(), version_prerelease_parts.size());
  95. EXPECT_EQ(bumped_prerelease_parts[0], "1"_string);
  96. }
  97. TEST_CASE(prerelease_bump_rightmost_numeric_part)
  98. {
  99. auto version = GET_SEMVER("1.1.2-a.1.0.c"sv);
  100. auto prerelease_bump = version.bump(SemVer::BumpType::Prerelease);
  101. EXPECT_EQ(prerelease_bump.major(), version.major());
  102. EXPECT_EQ(prerelease_bump.minor(), version.minor());
  103. EXPECT_EQ(prerelease_bump.patch(), version.patch());
  104. EXPECT_NE(prerelease_bump.prerelease(), version.prerelease());
  105. EXPECT(prerelease_bump.build_metadata().is_empty());
  106. auto version_prerelease_parts = version.prerelease_identifiers();
  107. auto bumped_prerelease_parts = prerelease_bump.prerelease_identifiers();
  108. EXPECT_EQ(bumped_prerelease_parts.size(), version_prerelease_parts.size());
  109. EXPECT_EQ(bumped_prerelease_parts[2], "1"_string);
  110. }
  111. TEST_CASE(prerelease_bump_add_zero_if_no_numeric)
  112. {
  113. auto version = GET_SEMVER("1.1.2-only.strings"sv);
  114. auto prerelease_bump = version.bump(SemVer::BumpType::Prerelease);
  115. EXPECT_EQ(prerelease_bump.major(), version.major());
  116. EXPECT_EQ(prerelease_bump.minor(), version.minor());
  117. EXPECT_EQ(prerelease_bump.patch(), version.patch());
  118. EXPECT_NE(prerelease_bump.prerelease(), version.prerelease());
  119. EXPECT(prerelease_bump.build_metadata().is_empty());
  120. auto version_prerelease_parts = version.prerelease_identifiers();
  121. auto bumped_prerelease_parts = prerelease_bump.prerelease_identifiers();
  122. EXPECT(bumped_prerelease_parts.size() > version_prerelease_parts.size());
  123. EXPECT_EQ(bumped_prerelease_parts[2], "0"_string);
  124. }
  125. TEST_CASE(is_same) // NOLINT(readability-function-cognitive-complexity)
  126. {
  127. // exact match
  128. EXPECT(IS_SAME_SCENARIO("1.1.2-prerelease+meta"sv, "1.1.2-prerelease+meta"sv, SemVer::CompareType::Exact));
  129. EXPECT(!IS_SAME_SCENARIO("1.1.2-prerelease+meta"sv, "1.1.3-prerelease+meta"sv, SemVer::CompareType::Exact));
  130. EXPECT(!IS_SAME_SCENARIO("1.1.2-prerelease+meta"sv, "1.2.2-prerelease+meta"sv, SemVer::CompareType::Exact));
  131. EXPECT(!IS_SAME_SCENARIO("1.1.2-prerelease+meta"sv, "2.1.2-prerelease+meta"sv, SemVer::CompareType::Exact));
  132. EXPECT(!IS_SAME_SCENARIO("1.1.2-prerelease+meta"sv, "1.1.3-someother"sv, SemVer::CompareType::Exact));
  133. // major part match
  134. EXPECT(IS_SAME_SCENARIO("1.1.2"sv, "1.1.2"sv, SemVer::CompareType::Major));
  135. EXPECT(IS_SAME_SCENARIO("1.1.2"sv, "1.2.2"sv, SemVer::CompareType::Major));
  136. EXPECT(IS_SAME_SCENARIO("1.1.2"sv, "1.1.3"sv, SemVer::CompareType::Major));
  137. EXPECT(!IS_SAME_SCENARIO("1.1.2"sv, "2.1.2"sv, SemVer::CompareType::Major));
  138. // minor part match
  139. EXPECT(IS_SAME_SCENARIO("1.1.2"sv, "1.1.2"sv, SemVer::CompareType::Minor));
  140. EXPECT(IS_SAME_SCENARIO("1.1.2"sv, "1.1.3"sv, SemVer::CompareType::Minor));
  141. EXPECT(!IS_SAME_SCENARIO("1.1.2"sv, "1.2.2"sv, SemVer::CompareType::Minor));
  142. EXPECT(!IS_SAME_SCENARIO("1.1.2"sv, "2.1.2"sv, SemVer::CompareType::Minor));
  143. EXPECT(!IS_SAME_SCENARIO("1.1.2"sv, "2.2.2"sv, SemVer::CompareType::Minor));
  144. // patch part match
  145. EXPECT(IS_SAME_SCENARIO("1.1.2"sv, "1.1.2"sv, SemVer::CompareType::Patch));
  146. EXPECT(!IS_SAME_SCENARIO("1.1.2"sv, "1.1.3"sv, SemVer::CompareType::Patch));
  147. EXPECT(!IS_SAME_SCENARIO("1.1.2"sv, "1.2.2"sv, SemVer::CompareType::Patch));
  148. EXPECT(!IS_SAME_SCENARIO("1.1.2"sv, "2.1.2"sv, SemVer::CompareType::Patch));
  149. EXPECT(!IS_SAME_SCENARIO("1.1.2"sv, "1.2.2"sv, SemVer::CompareType::Patch));
  150. EXPECT(!IS_SAME_SCENARIO("1.1.2"sv, "2.1.2"sv, SemVer::CompareType::Patch));
  151. EXPECT(!IS_SAME_SCENARIO("1.1.2"sv, "2.2.2"sv, SemVer::CompareType::Patch));
  152. }
  153. TEST_CASE(is_greater_than) // NOLINT(readability-function-cognitive-complexity)
  154. {
  155. // Just normal versions
  156. EXPECT(IS_GREATER_THAN_SCENARIO("1.1.3"sv, "1.1.2"sv));
  157. EXPECT(IS_GREATER_THAN_SCENARIO("1.2.2"sv, "1.1.2"sv));
  158. EXPECT(IS_GREATER_THAN_SCENARIO("2.1.2"sv, "1.1.2"sv));
  159. EXPECT(IS_GREATER_THAN_SCENARIO("2.1.3"sv, "1.1.2"sv));
  160. EXPECT(IS_GREATER_THAN_SCENARIO("1.2.3"sv, "1.1.2"sv));
  161. EXPECT(IS_GREATER_THAN_SCENARIO("1.2.2"sv, "1.1.2"sv));
  162. EXPECT(!IS_GREATER_THAN_SCENARIO("1.1.2"sv, "1.1.2"sv));
  163. // Basic, imbalanced prereleased testing
  164. EXPECT(!IS_GREATER_THAN_SCENARIO("1.0.0-alpha"sv, "1.0.0-alpha"sv));
  165. EXPECT(!IS_GREATER_THAN_SCENARIO("1.0.0-alpha"sv, "1.0.0"sv));
  166. EXPECT(IS_GREATER_THAN_SCENARIO("1.0.0"sv, "1.0.0-0"sv));
  167. // Both versions have more than one identifiers
  168. // 1. All numeric
  169. EXPECT(IS_GREATER_THAN_SCENARIO("1.0.0-0.1.2"sv, "1.0.0-0.1.1"sv));
  170. EXPECT(IS_GREATER_THAN_SCENARIO("1.0.0-0.2.0"sv, "1.0.0-0.1.2"sv));
  171. EXPECT(!IS_GREATER_THAN_SCENARIO("1.0.0-0.1.2"sv, "1.0.0-0.1.2"sv));
  172. // 2. For non-numeric, lexical compare
  173. EXPECT(IS_GREATER_THAN_SCENARIO("1.0.0-beta"sv, "1.0.0-alpha"sv));
  174. EXPECT(IS_GREATER_THAN_SCENARIO("1.0.0-0.beta"sv, "1.0.0-0.alpha"sv));
  175. // 3. Either one is numeric, but not both, then numeric given low precendence
  176. EXPECT(IS_GREATER_THAN_SCENARIO("1.0.0-0.alpha"sv, "1.0.0-0.0"sv));
  177. EXPECT(!IS_GREATER_THAN_SCENARIO("1.0.0-0.0"sv, "1.0.0-0.alpha"sv));
  178. // 4. Prefix identifiers are same, larger has high precedence
  179. EXPECT(IS_GREATER_THAN_SCENARIO("1.0.0-alpha.beta.gamma"sv, "1.0.0-alpha"sv));
  180. }
  181. TEST_CASE(is_lesser_than) // NOLINT(readability-function-cognitive-complexity)
  182. {
  183. // This function depends on is_greater_than, so basic testing is OK
  184. EXPECT(IS_LESSER_THAN_SCENARIO("1.1.2"sv, "1.1.3"sv));
  185. EXPECT(IS_LESSER_THAN_SCENARIO("1.1.2"sv, "1.2.2"sv));
  186. EXPECT(IS_LESSER_THAN_SCENARIO("1.1.2"sv, "2.1.2"sv));
  187. EXPECT(IS_LESSER_THAN_SCENARIO("1.1.2"sv, "2.1.3"sv));
  188. EXPECT(IS_LESSER_THAN_SCENARIO("1.1.2"sv, "1.2.3"sv));
  189. EXPECT(IS_LESSER_THAN_SCENARIO("1.1.2"sv, "1.2.2"sv));
  190. EXPECT(!IS_LESSER_THAN_SCENARIO("1.1.2"sv, "1.1.2"sv));
  191. }
  192. TEST_CASE(satisfies) // NOLINT(readability-function-cognitive-complexity)
  193. {
  194. auto version = GET_SEMVER("1.1.2-prerelease+meta"sv);
  195. EXPECT(version.satisfies("1.1.2-prerelease+meta"sv));
  196. EXPECT(!version.satisfies("1.2.2-prerelease+meta"sv));
  197. EXPECT(!version.satisfies("!=1.1.2-prerelease+meta"sv));
  198. EXPECT(version.satisfies("!=1.2.2-prerelease+meta"sv));
  199. EXPECT(version.satisfies("=1.1.2"sv));
  200. EXPECT(version.satisfies("=1.1.2-prerelease+meta"sv));
  201. EXPECT(!version.satisfies("=1.1.3"sv));
  202. EXPECT(!version.satisfies("==1.1.3-prerelease+meta"sv));
  203. EXPECT(version.satisfies("==1.1.2-prerelease"sv));
  204. EXPECT(version.satisfies("==1.1.2-prerelease+meta"sv));
  205. EXPECT(!version.satisfies("<1.1.1-prerelease+meta"sv));
  206. EXPECT(!version.satisfies("<1.1.2-prerelease+meta"sv));
  207. EXPECT(version.satisfies("<1.1.3-prerelease+meta"sv));
  208. EXPECT(version.satisfies(">1.1.1-prerelease+meta"sv));
  209. EXPECT(!version.satisfies(">1.1.2-prerelease+meta"sv));
  210. EXPECT(!version.satisfies(">1.1.3-prerelease+meta"sv));
  211. EXPECT(version.satisfies(">=1.1.1-prerelease+meta"sv));
  212. EXPECT(version.satisfies(">=1.1.2-prerelease+meta"sv));
  213. EXPECT(!version.satisfies(">=1.1.3-prerelease+meta"sv));
  214. EXPECT(!version.satisfies("<=1.1.1-prerelease+meta"sv));
  215. EXPECT(version.satisfies("<=1.1.2-prerelease+meta"sv));
  216. EXPECT(version.satisfies("<=1.1.3-prerelease+meta"sv));
  217. EXPECT(!version.satisfies("HELLO1.1.2-prerelease+meta"sv));
  218. }