|
16 | 16 | import static org.junit.jupiter.api.Assertions.assertNull; |
17 | 17 | import static org.junit.jupiter.api.Assertions.assertTrue; |
18 | 18 |
|
| 19 | +import java.util.Arrays; |
| 20 | +import java.util.Collections; |
| 21 | +import java.util.List; |
| 22 | +import java.util.stream.Collectors; |
| 23 | + |
19 | 24 | import org.junit.jupiter.api.Test; |
20 | 25 | import org.springframework.ide.vscode.commons.Version.ReleaseType; |
21 | 26 |
|
@@ -281,4 +286,138 @@ void toMajorMinorVersionStr() { |
281 | 286 | void toMajorMinorPatchVersionStr() { |
282 | 287 | assertEquals("3.3.0", Version.parse("3.3.0-M1").toMajorMinorPatchVersionStr()); |
283 | 288 | } |
| 289 | + |
| 290 | + // ---- comprehensive sort-based comparison tests ---- |
| 291 | + |
| 292 | + @Test |
| 293 | + void sortAllThreePartVersionVariants() { |
| 294 | + // Covers every qualifier type, both short aliases (A/B/CR) and full names, |
| 295 | + // numeric progression within a qualifier (M1<M2, RC1<RC2, SP1<SP2). |
| 296 | + assertSortedOrder( |
| 297 | + "3.3.0-A1", // alpha (short alias) |
| 298 | + "3.3.0-ALPHA1", // alpha |
| 299 | + "3.3.0-B1", // beta (short alias) |
| 300 | + "3.3.0-BETA1", // beta |
| 301 | + "3.3.0-M1", // milestone |
| 302 | + "3.3.0-M2", // milestone, higher qualifier number |
| 303 | + "3.3.0-CR1", // rc (alias; CR < RC lexicographically) |
| 304 | + "3.3.0-RC1", // rc |
| 305 | + "3.3.0-RC2", // rc, higher qualifier number |
| 306 | + "3.3.0-SNAPSHOT", // snapshot |
| 307 | + "3.3.0", // release (GA) |
| 308 | + "3.3.0-SP1", // service pack |
| 309 | + "3.3.0-SP2" // service pack, higher qualifier number |
| 310 | + ); |
| 311 | + } |
| 312 | + |
| 313 | + @Test |
| 314 | + void sortAllFourPartVersionVariants() { |
| 315 | + // Same qualifier coverage as the 3-part test but with a 4th numeric component. |
| 316 | + assertSortedOrder( |
| 317 | + "3.3.0.1-A1", |
| 318 | + "3.3.0.1-ALPHA1", |
| 319 | + "3.3.0.1-B1", |
| 320 | + "3.3.0.1-BETA1", |
| 321 | + "3.3.0.1-M1", |
| 322 | + "3.3.0.1-M2", |
| 323 | + "3.3.0.1-CR1", |
| 324 | + "3.3.0.1-RC1", |
| 325 | + "3.3.0.1-RC2", |
| 326 | + "3.3.0.1-SNAPSHOT", |
| 327 | + "3.3.0.1", |
| 328 | + "3.3.0.1-SP1", |
| 329 | + "3.3.0.1-SP2" |
| 330 | + ); |
| 331 | + } |
| 332 | + |
| 333 | + @Test |
| 334 | + void sortThreeAndFourPartVersionsMixed() { |
| 335 | + // All 3-part and 4-part variants interleaved in one list. |
| 336 | + // The critical boundary is 3.3.0-SP2 < 3.3.0.1-A1: the 4th numeric |
| 337 | + // component (build=1 vs 0) dominates even the highest 3-part qualifier. |
| 338 | + assertSortedOrder( |
| 339 | + "3.3.0-A1", |
| 340 | + "3.3.0-ALPHA1", |
| 341 | + "3.3.0-B1", |
| 342 | + "3.3.0-BETA1", |
| 343 | + "3.3.0-M1", |
| 344 | + "3.3.0-M2", |
| 345 | + "3.3.0-CR1", |
| 346 | + "3.3.0-RC1", |
| 347 | + "3.3.0-RC2", |
| 348 | + "3.3.0-SNAPSHOT", |
| 349 | + "3.3.0", |
| 350 | + "3.3.0-SP1", |
| 351 | + "3.3.0-SP2", |
| 352 | + "3.3.0.1-A1", |
| 353 | + "3.3.0.1-ALPHA1", |
| 354 | + "3.3.0.1-B1", |
| 355 | + "3.3.0.1-BETA1", |
| 356 | + "3.3.0.1-M1", |
| 357 | + "3.3.0.1-M2", |
| 358 | + "3.3.0.1-CR1", |
| 359 | + "3.3.0.1-RC1", |
| 360 | + "3.3.0.1-RC2", |
| 361 | + "3.3.0.1-SNAPSHOT", |
| 362 | + "3.3.0.1", |
| 363 | + "3.3.0.1-SP1", |
| 364 | + "3.3.0.1-SP2" |
| 365 | + ); |
| 366 | + } |
| 367 | + |
| 368 | + @Test |
| 369 | + void numericComponentsDominateQualifier() { |
| 370 | + // A strictly higher numeric component (build, patch, minor, major) always |
| 371 | + // wins over qualifier, so alpha of the next tier > SP of the prior tier. |
| 372 | + assertSortedOrder( |
| 373 | + "3.3.0-SP2", // highest 3-part qualifier |
| 374 | + "3.3.0.1-A1", // 4th numeric component beats any 3-part qualifier |
| 375 | + "3.3.0.1-SP2", // highest 4-part qualifier |
| 376 | + "3.3.1-A1", // higher patch beats any build/qualifier |
| 377 | + "3.3.1-SP2", |
| 378 | + "3.4.0-A1", // higher minor beats any patch/qualifier |
| 379 | + "3.4.0-SP2", |
| 380 | + "4.0.0-A1", // higher major beats everything |
| 381 | + "4.0.0-SP2" |
| 382 | + ); |
| 383 | + } |
| 384 | + |
| 385 | + @Test |
| 386 | + void gaAliasesCompareEqualToPlainRelease() { |
| 387 | + Version plain = Version.parse("3.3.0"); |
| 388 | + assertEquals(0, plain.compareTo(Version.parse("3.3.0.RELEASE"))); |
| 389 | + assertEquals(0, plain.compareTo(Version.parse("3.3.0.GA"))); |
| 390 | + assertEquals(0, plain.compareTo(Version.parse("3.3.0.FINAL"))); |
| 391 | + assertEquals(0, Version.parse("3.3.0.RELEASE").compareTo(Version.parse("3.3.0.GA"))); |
| 392 | + assertEquals(0, Version.parse("3.3.0.GA").compareTo(Version.parse("3.3.0.FINAL"))); |
| 393 | + } |
| 394 | + |
| 395 | + @Test |
| 396 | + void dotSeparatorQualifiersRespectPriority() { |
| 397 | + // Old-style dot-separated qualifiers observe the same priority order. |
| 398 | + assertTrue(Version.parse("3.3.0.M1").compareTo(Version.parse("3.3.0.RC1")) < 0); |
| 399 | + assertTrue(Version.parse("3.3.0.RC1").compareTo(Version.parse("3.3.0.SNAPSHOT")) < 0); |
| 400 | + // Dot separator ('.' = 46) > hyphen ('-' = 45), so when qualifier priority |
| 401 | + // ties the fallback string comparison puts dot-style after hyphen-style: |
| 402 | + // "3.3.0.M1" > "3.3.0-M2" even though M2 > M1 numerically. |
| 403 | + assertTrue(Version.parse("3.3.0-M2").compareTo(Version.parse("3.3.0.M1")) < 0); |
| 404 | + } |
| 405 | + |
| 406 | + @Test |
| 407 | + void caseInsensitiveVersionStringsCompareEqual() { |
| 408 | + // Identical strings differing only in case short-circuit to 0 without parsing. |
| 409 | + assertEquals(0, Version.parse("3.3.0-SNAPSHOT").compareTo(Version.parse("3.3.0-snapshot"))); |
| 410 | + assertEquals(0, Version.parse("3.3.0-RC1").compareTo(Version.parse("3.3.0-rc1"))); |
| 411 | + assertEquals(0, Version.parse("3.3.0-M1").compareTo(Version.parse("3.3.0-m1"))); |
| 412 | + } |
| 413 | + |
| 414 | + private void assertSortedOrder(String... expectedOrder) { |
| 415 | + List<Version> versions = Arrays.stream(expectedOrder) |
| 416 | + .map(Version::parse) |
| 417 | + .collect(Collectors.toList()); |
| 418 | + Collections.reverse(versions); |
| 419 | + versions.sort(null); |
| 420 | + List<String> actual = versions.stream().map(Version::toString).collect(Collectors.toList()); |
| 421 | + assertEquals(List.of(expectedOrder), actual); |
| 422 | + } |
284 | 423 | } |
0 commit comments