View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.eclipse.aether.util.version;
20  
21  import java.util.*;
22  import java.util.stream.Collectors;
23  import java.util.stream.Stream;
24  
25  import org.eclipse.aether.version.Version;
26  import org.junit.jupiter.api.Test;
27  
28  import static java.util.stream.Collectors.toList;
29  import static org.junit.jupiter.api.Assertions.*;
30  
31  /**
32   */
33  public class GenericVersionTest extends AbstractVersionTest {
34  
35      protected Version newVersion(String version) {
36          return new GenericVersion(version);
37      }
38  
39      @Test
40      void testEmptyVersion() {
41          assertOrder(X_EQ_Y, "0", "");
42      }
43  
44      // Block of tests from https://issues.apache.org/jira/browse/MRESOLVER-336
45      @Test
46      void testTrimPadding() {
47          // 1.0.0 -> 1
48          List<GenericVersion.Item> items = new ArrayList<>(Arrays.asList(
49                  new GenericVersion.Item(GenericVersion.Item.KIND_INT, 1),
50                  new GenericVersion.Item(GenericVersion.Item.KIND_INT, 0),
51                  new GenericVersion.Item(GenericVersion.Item.KIND_INT, 0)));
52          assertEquals(3, items.size());
53          GenericVersion.trimPadding(items);
54          assertEquals(1, items.size());
55      }
56  
57      @Test
58      void testTrimPaddingNotNeededString() {
59          // 1.0.0.string -> 1.string
60          List<GenericVersion.Item> items = new ArrayList<>(Arrays.asList(
61                  new GenericVersion.Item(GenericVersion.Item.KIND_INT, 1),
62                  new GenericVersion.Item(GenericVersion.Item.KIND_INT, 0),
63                  new GenericVersion.Item(GenericVersion.Item.KIND_INT, 0),
64                  new GenericVersion.Item(GenericVersion.Item.KIND_STRING, "string")));
65          assertEquals(4, items.size());
66          GenericVersion.trimPadding(items);
67          assertEquals(2, items.size());
68      }
69  
70      @Test
71      void testTrimPaddingNeededQualifier() {
72          // 1.0.0.ga -> 1
73          List<GenericVersion.Item> items = new ArrayList<>(Arrays.asList(
74                  new GenericVersion.Item(GenericVersion.Item.KIND_INT, 1),
75                  new GenericVersion.Item(GenericVersion.Item.KIND_INT, 0),
76                  new GenericVersion.Item(GenericVersion.Item.KIND_INT, 0),
77                  new GenericVersion.Item(GenericVersion.Item.KIND_QUALIFIER, 0)));
78          assertEquals(4, items.size());
79          GenericVersion.trimPadding(items);
80          assertEquals(1, items.size());
81      }
82  
83      @Test
84      void testTrimPaddingNeededQualifierMixed() {
85          // 1.0.0.string.0.ga -> 1.string
86          List<GenericVersion.Item> items = new ArrayList<>(Arrays.asList(
87                  new GenericVersion.Item(GenericVersion.Item.KIND_INT, 1),
88                  new GenericVersion.Item(GenericVersion.Item.KIND_INT, 0),
89                  new GenericVersion.Item(GenericVersion.Item.KIND_INT, 0),
90                  new GenericVersion.Item(GenericVersion.Item.KIND_STRING, "string"),
91                  new GenericVersion.Item(GenericVersion.Item.KIND_INT, 0),
92                  new GenericVersion.Item(GenericVersion.Item.KIND_QUALIFIER, 0)));
93          assertEquals(6, items.size());
94          GenericVersion.trimPadding(items);
95          assertEquals(2, items.size());
96      }
97  
98      @Test
99      void testTrimPaddingNeededQualifierMixedInBetweenGa() {
100         // 1.0.ga.0.string.0.ga -> 1.ga.0.string
101         List<GenericVersion.Item> items = new ArrayList<>(Arrays.asList(
102                 new GenericVersion.Item(GenericVersion.Item.KIND_INT, 1),
103                 new GenericVersion.Item(GenericVersion.Item.KIND_INT, 0),
104                 new GenericVersion.Item(GenericVersion.Item.KIND_QUALIFIER, 0),
105                 new GenericVersion.Item(GenericVersion.Item.KIND_INT, 0),
106                 new GenericVersion.Item(GenericVersion.Item.KIND_STRING, "string"),
107                 new GenericVersion.Item(GenericVersion.Item.KIND_INT, 0),
108                 new GenericVersion.Item(GenericVersion.Item.KIND_QUALIFIER, 0)));
109         assertEquals(7, items.size());
110         GenericVersion.trimPadding(items);
111         assertEquals(4, items.size());
112     }
113 
114     @Test
115     void testEdgeCase_1_1() {
116         Version v1 = newVersion("0.0.0.ga.ga.foo");
117         Version v2 = newVersion("foo");
118         // they were equal in Resolver 1.x
119         assertNotEquals(v1, v2);
120     }
121 
122     @Test
123     void testEdgeCase_1_2() {
124         // as expected
125         assertOrder(X_LT_Y, "ga.ga.foo", "foo");
126     }
127 
128     @Test
129     void testEdgeCase_2_1() {
130         assertOrder(X_GT_Y, "0.foo.1.2.3", "foo.1.2.3");
131         // they were equal in Resolver 1.x
132         assertOrder(X_GT_Y, "0.foo", "foo");
133         assertOrder(X_EQ_Y, "1.0.0-foo", "1-foo");
134         // but "foo" != "ga" (string > qualifier)
135         assertOrder(X_LT_Y, "1.0.0-ga-foo", "1-foo");
136         assertOrder(X_EQ_Y, "1.0.0-ga-foo", "1-ga-foo");
137         assertOrder(X_LT_Y, "1.0.0.final-foo", "1-foo");
138         assertOrder(X_EQ_Y, "1.0.0.final-foo", "1-final-foo");
139     }
140 
141     @Test
142     void testEdgeCase_2_2() {
143         Version v1 = newVersion("0.0.0.ga.ga.foo");
144         Version v2 = newVersion("foo");
145         Version v3 = newVersion("0.0.0.0.0.foo");
146         // they were equal in Resolver 1.x
147         assertNotEquals(v1, v2);
148         // they were equal in Resolver 1.x
149         assertNotEquals(v2, v3);
150         // but "0" != "ga"
151         assertNotEquals(v1, v3);
152     }
153 
154     @Test
155     void testEdgeCase_2_3() {
156         // 1.ga trimmed to 1 == 1.0.0.0.0.0...
157         assertOrder(X_EQ_Y, "1.ga", "1.0");
158         // ga.1 is not trimmed < 0.1 (as qualifier < number)
159         assertOrder(X_LT_Y, "ga.1", "0.1");
160         // 1.ga.1 is not trimmed < 1.0.1 (as qualifier < number)
161         assertOrder(X_LT_Y, "1.ga.1", "1.0.1");
162     }
163 
164     @Test
165     void testEdgeCase_2_4() {
166         assertOrder(X_LT_Y, "1.0.final.1", "1.0.1.final");
167     }
168 
169     @Test
170     void testQualifier() {
171         String ver = "1.0.0";
172         assertOrder(X_LT_Y, ver + ".a1", ver + ".b1");
173         assertOrder(X_LT_Y, ver + ".b1", ver + ".m1");
174         assertOrder(X_LT_Y, ver + ".m1", ver + ".rc");
175         assertOrder(X_LT_Y, ver + ".rc", ver + "-SNAPSHOT");
176         assertOrder(X_LT_Y, ver + "-SNAPSHOT", ver);
177         assertOrder(X_EQ_Y, ver + ".ga", ver + ".final");
178         assertOrder(X_EQ_Y, ver + ".final", ver + ".release");
179         assertOrder(X_LT_Y, ver + ".final", ver + ".sp");
180         assertOrder(X_LT_Y, ver, ver + ".sp");
181     }
182 
183     @Test
184     void testTransition() {
185         GenericVersion v;
186         v = (GenericVersion) newVersion("1.0.0");
187         assertEquals(1, v.asItems().size()); // trailing zero padding trimmed
188         v = (GenericVersion) newVersion("1.2.3");
189         assertEquals(3, v.asItems().size());
190         v = (GenericVersion) newVersion("1a0");
191         assertEquals(2, v.asItems().size()); // trailing zero padding trimmed
192         v = (GenericVersion) newVersion("1a2");
193         assertEquals(3, v.asItems().size()); // trailing zero padding trimmed
194     }
195 
196     // End of https://issues.apache.org/jira/browse/MRESOLVER-336
197 
198     @Test
199     void testNumericOrdering() {
200         assertOrder(X_LT_Y, "2", "10");
201         assertOrder(X_LT_Y, "1.2", "1.10");
202         assertOrder(X_LT_Y, "1.0.2", "1.0.10");
203         assertOrder(X_LT_Y, "1.0.0.2", "1.0.0.10");
204         assertOrder(X_LT_Y, "1.0.20101206.111434.1", "1.0.20101206.111435.1");
205         assertOrder(X_LT_Y, "1.0.20101206.111434.2", "1.0.20101206.111434.10");
206     }
207 
208     @Test
209     void testDelimiters() {
210         assertOrder(X_EQ_Y, "1.0", "1-0");
211         assertOrder(X_EQ_Y, "1.0", "1_0");
212         assertOrder(X_EQ_Y, "1.a", "1a");
213     }
214 
215     @Test
216     void testLeadingZerosAreSemanticallyIrrelevant() {
217         assertOrder(X_EQ_Y, "1", "01");
218         assertOrder(X_EQ_Y, "1.2", "1.002");
219         assertOrder(X_EQ_Y, "1.2.3", "1.2.0003");
220         assertOrder(X_EQ_Y, "1.2.3.4", "1.2.3.00004");
221     }
222 
223     @Test
224     void testTrailingZerosAreSemanticallyIrrelevant() {
225         assertOrder(X_EQ_Y, "1", "1.0.0.0.0.0.0.0.0.0.0.0.0.0");
226         assertOrder(X_EQ_Y, "1", "1-0-0-0-0-0-0-0-0-0-0-0-0-0");
227         assertOrder(X_EQ_Y, "1", "1.0-0.0-0.0-0.0-0.0-0.0-0.0");
228         assertOrder(X_EQ_Y, "1", "1.0000000000000");
229         assertOrder(X_EQ_Y, "1.0", "1.0.0");
230     }
231 
232     @Test
233     void testTrailingZerosBeforeQualifierAreSemanticallyIrrelevant() {
234         assertOrder(X_EQ_Y, "1.0_ga", "1.0.0_ga");
235         assertOrder(X_EQ_Y, "1.0-ga", "1.0.0-ga");
236         assertOrder(X_EQ_Y, "1.0.ga", "1.0.0.ga");
237         assertOrder(X_EQ_Y, "1.0ga", "1.0.0ga");
238 
239         assertOrder(X_EQ_Y, "1.0-alpha", "1.0.0-alpha");
240         assertOrder(X_EQ_Y, "1.0.alpha", "1.0.0.alpha");
241         assertOrder(X_EQ_Y, "1.0alpha", "1.0.0alpha");
242         assertOrder(X_EQ_Y, "1.0-alpha-snapshot", "1.0.0-alpha-snapshot");
243         assertOrder(X_EQ_Y, "1.0.alpha.snapshot", "1.0.0.alpha.snapshot");
244 
245         assertOrder(X_EQ_Y, "1.x.0-alpha", "1.x.0.0-alpha");
246         assertOrder(X_EQ_Y, "1.x.0.alpha", "1.x.0.0.alpha");
247         assertOrder(X_EQ_Y, "1.x.0-alpha-snapshot", "1.x.0.0-alpha-snapshot");
248         assertOrder(X_EQ_Y, "1.x.0.alpha.snapshot", "1.x.0.0.alpha.snapshot");
249     }
250 
251     @Test
252     void testTrailingDelimitersAreSemanticallyIrrelevant() {
253         assertOrder(X_EQ_Y, "1", "1.............");
254         assertOrder(X_EQ_Y, "1", "1-------------");
255         assertOrder(X_EQ_Y, "1.0", "1.............");
256         assertOrder(X_EQ_Y, "1.0", "1-------------");
257         assertOrder(X_EQ_Y, "1.0", "1_______");
258     }
259 
260     @Test
261     void testInitialDelimiters() {
262         assertOrder(X_EQ_Y, "0.1", ".1");
263         assertOrder(X_EQ_Y, "0.0.1", "..1");
264         assertOrder(X_EQ_Y, "0.1", "-1");
265         assertOrder(X_EQ_Y, "0.0.1", "--1");
266         assertOrder(X_EQ_Y, "0.1", "_1");
267     }
268 
269     @Test
270     void testConsecutiveDelimiters() {
271         assertOrder(X_EQ_Y, "1.0.1", "1..1");
272         assertOrder(X_EQ_Y, "1.0.0.1", "1...1");
273         assertOrder(X_EQ_Y, "1.0.1", "1--1");
274         assertOrder(X_EQ_Y, "1.0.0.1", "1---1");
275     }
276 
277     @Test
278     void testUnlimitedNumberOfVersionComponents() {
279         assertOrder(X_GT_Y, "1.0.1.2.3.4.5.6.7.8.9.0.1.2.10", "1.0.1.2.3.4.5.6.7.8.9.0.1.2.3");
280     }
281 
282     @Test
283     void testUnlimitedNumberOfDigitsInNumericComponent() {
284         assertOrder(X_GT_Y, "1.1234567890123456789012345678901", "1.123456789012345678901234567891");
285     }
286 
287     @Test
288     void testTransitionFromDigitToLetterAndViceVersaIsEquivalentToDelimiter() {
289         assertOrder(X_EQ_Y, "1alpha10", "1.alpha.10");
290         assertOrder(X_EQ_Y, "1alpha10", "1-alpha-10");
291 
292         assertOrder(X_GT_Y, "1.alpha10", "1.alpha2");
293         assertOrder(X_GT_Y, "10alpha", "1alpha");
294     }
295 
296     @Test
297     void testWellKnownQualifierOrdering() {
298         assertOrder(X_EQ_Y, "1-alpha1", "1-a1");
299         assertOrder(X_LT_Y, "1-alpha", "1-beta");
300         assertOrder(X_EQ_Y, "1-beta1", "1-b1");
301         assertOrder(X_LT_Y, "1-beta", "1-milestone");
302         assertOrder(X_EQ_Y, "1-milestone1", "1-m1");
303         assertOrder(X_LT_Y, "1-milestone", "1-rc");
304         assertOrder(X_EQ_Y, "1-rc", "1-cr");
305         assertOrder(X_LT_Y, "1-rc", "1-snapshot");
306         assertOrder(X_LT_Y, "1-snapshot", "1");
307         assertOrder(X_EQ_Y, "1", "1-ga");
308         assertOrder(X_EQ_Y, "1", "1.ga.0.ga");
309         assertOrder(X_EQ_Y, "1.0", "1-ga");
310         assertOrder(X_EQ_Y, "1", "1-ga.ga");
311         assertOrder(X_EQ_Y, "1", "1-ga-ga");
312         assertOrder(X_EQ_Y, "A", "A.ga.ga");
313         assertOrder(X_EQ_Y, "A", "A-ga-ga");
314         assertOrder(X_EQ_Y, "1", "1-final");
315         assertOrder(X_EQ_Y, "1", "1-release");
316         assertOrder(X_LT_Y, "1", "1-sp");
317 
318         assertOrder(X_LT_Y, "A.rc.1", "A.ga.1");
319         assertOrder(X_GT_Y, "A.sp.1", "A.ga.1");
320         assertOrder(X_LT_Y, "A.rc.x", "A.ga.x");
321         assertOrder(X_GT_Y, "A.sp.x", "A.ga.x");
322     }
323 
324     @Test
325     void testWellKnownQualifierVersusUnknownQualifierOrdering() {
326         assertOrder(X_GT_Y, "1-abc", "1-alpha");
327         assertOrder(X_GT_Y, "1-abc", "1-beta");
328         assertOrder(X_GT_Y, "1-abc", "1-milestone");
329         assertOrder(X_GT_Y, "1-abc", "1-rc");
330         assertOrder(X_GT_Y, "1-abc", "1-snapshot");
331         assertOrder(X_GT_Y, "1-abc", "1");
332         assertOrder(X_GT_Y, "1-abc", "1-sp");
333     }
334 
335     @Test
336     void testWellKnownSingleCharQualifiersOnlyRecognizedIfImmediatelyFollowedByNumber() {
337         assertOrder(X_GT_Y, "1.0a", "1.0");
338         assertOrder(X_GT_Y, "1.0-a", "1.0");
339         assertOrder(X_GT_Y, "1.0.a", "1.0");
340         assertOrder(X_GT_Y, "1.0b", "1.0");
341         assertOrder(X_GT_Y, "1.0-b", "1.0");
342         assertOrder(X_GT_Y, "1.0.b", "1.0");
343         assertOrder(X_GT_Y, "1.0m", "1.0");
344         assertOrder(X_GT_Y, "1.0-m", "1.0");
345         assertOrder(X_GT_Y, "1.0.m", "1.0");
346 
347         assertOrder(X_LT_Y, "1.0a1", "1.0");
348         assertOrder(X_LT_Y, "1.0-a1", "1.0");
349         assertOrder(X_LT_Y, "1.0.a1", "1.0");
350         assertOrder(X_LT_Y, "1.0b1", "1.0");
351         assertOrder(X_LT_Y, "1.0-b1", "1.0");
352         assertOrder(X_LT_Y, "1.0.b1", "1.0");
353         assertOrder(X_LT_Y, "1.0m1", "1.0");
354         assertOrder(X_LT_Y, "1.0-m1", "1.0");
355         assertOrder(X_LT_Y, "1.0.m1", "1.0");
356 
357         assertOrder(X_GT_Y, "1.0a.1", "1.0");
358         assertOrder(X_GT_Y, "1.0a-1", "1.0");
359         assertOrder(X_GT_Y, "1.0b.1", "1.0");
360         assertOrder(X_GT_Y, "1.0b-1", "1.0");
361         assertOrder(X_GT_Y, "1.0m.1", "1.0");
362         assertOrder(X_GT_Y, "1.0m-1", "1.0");
363     }
364 
365     @Test
366     void testUnknownQualifierOrdering() {
367         assertOrder(X_LT_Y, "1-abc", "1-abcd");
368         assertOrder(X_LT_Y, "1-abc", "1-bcd");
369         assertOrder(X_GT_Y, "1-abc", "1-aac");
370     }
371 
372     @Test
373     void testCaseInsensitiveOrderingOfQualifiers() {
374         assertOrder(X_EQ_Y, "1.alpha", "1.ALPHA");
375         assertOrder(X_EQ_Y, "1.alpha", "1.Alpha");
376 
377         assertOrder(X_EQ_Y, "1.beta", "1.BETA");
378         assertOrder(X_EQ_Y, "1.beta", "1.Beta");
379 
380         assertOrder(X_EQ_Y, "1.milestone", "1.MILESTONE");
381         assertOrder(X_EQ_Y, "1.milestone", "1.Milestone");
382 
383         assertOrder(X_EQ_Y, "1.rc", "1.RC");
384         assertOrder(X_EQ_Y, "1.rc", "1.Rc");
385         assertOrder(X_EQ_Y, "1.cr", "1.CR");
386         assertOrder(X_EQ_Y, "1.cr", "1.Cr");
387 
388         assertOrder(X_EQ_Y, "1.snapshot", "1.SNAPSHOT");
389         assertOrder(X_EQ_Y, "1.snapshot", "1.Snapshot");
390 
391         assertOrder(X_EQ_Y, "1.ga", "1.GA");
392         assertOrder(X_EQ_Y, "1.ga", "1.Ga");
393         assertOrder(X_EQ_Y, "1.final", "1.FINAL");
394         assertOrder(X_EQ_Y, "1.final", "1.Final");
395         assertOrder(X_EQ_Y, "1.release", "1.RELEASE");
396         assertOrder(X_EQ_Y, "1.release", "1.Release");
397 
398         assertOrder(X_EQ_Y, "1.sp", "1.SP");
399         assertOrder(X_EQ_Y, "1.sp", "1.Sp");
400 
401         assertOrder(X_EQ_Y, "1.unknown", "1.UNKNOWN");
402         assertOrder(X_EQ_Y, "1.unknown", "1.Unknown");
403     }
404 
405     @Test
406     void testHypenBeforeUnderscoreDotOrder() {
407         assertOrder(X_EQ_Y, "1.0.0-1", "1.0.0_1");
408         assertOrder(X_EQ_Y, "1.0.0-1", "1.0.0.1");
409         assertOrder(X_EQ_Y, "1.0.0_1", "1.0.0.1");
410     }
411 
412     @Test
413     void testCaseInsensitiveOrderingOfQualifiersIsLocaleIndependent() {
414         Locale orig = Locale.getDefault();
415         try {
416             Locale[] locales = {Locale.ENGLISH, new Locale("tr")};
417             for (Locale locale : locales) {
418                 Locale.setDefault(locale);
419                 assertOrder(X_EQ_Y, "1-abcdefghijklmnopqrstuvwxyz", "1-ABCDEFGHIJKLMNOPQRSTUVWXYZ");
420             }
421         } finally {
422             Locale.setDefault(orig);
423         }
424     }
425 
426     @Test
427     void testQualifierVersusNumberOrdering() {
428         assertOrder(X_LT_Y, "1-ga", "1-1");
429         assertOrder(X_LT_Y, "1.ga", "1.1");
430         assertOrder(X_EQ_Y, "1-ga", "1.0");
431         assertOrder(X_EQ_Y, "1.ga", "1.0");
432 
433         assertOrder(X_LT_Y, "1-ga-1", "1-0-1");
434         assertOrder(X_LT_Y, "1.ga.1", "1.0.1");
435 
436         assertOrder(X_GT_Y, "1.sp", "1.0");
437         assertOrder(X_LT_Y, "1.sp", "1.1");
438 
439         assertOrder(X_LT_Y, "1-abc", "1-1");
440         assertOrder(X_LT_Y, "1.abc", "1.1");
441 
442         assertOrder(X_LT_Y, "1-xyz", "1-1");
443         assertOrder(X_LT_Y, "1.xyz", "1.1");
444     }
445 
446     @Test
447     void testVersionEvolution() {
448         assertSequence(
449                 "0.9.9-SNAPSHOT",
450                 "0.9.9",
451                 "0.9.10-SNAPSHOT",
452                 "0.9.10",
453                 "1.0-alpha-2-SNAPSHOT",
454                 "1.0-alpha-2",
455                 "1.0-alpha-10-SNAPSHOT",
456                 "1.0-alpha-10",
457                 "1.0-beta-1-SNAPSHOT",
458                 "1.0-beta-1",
459                 "1.0-rc-1-SNAPSHOT",
460                 "1.0-rc-1",
461                 "1.0-SNAPSHOT",
462                 "1.0",
463                 "1.0-sp-1-SNAPSHOT",
464                 "1.0-sp-1",
465                 "1.0.1-alpha-1-SNAPSHOT",
466                 "1.0.1-alpha-1",
467                 "1.0.1-beta-1-SNAPSHOT",
468                 "1.0.1-beta-1",
469                 "1.0.1-rc-1-SNAPSHOT",
470                 "1.0.1-rc-1",
471                 "1.0.1-SNAPSHOT",
472                 "1.0.1",
473                 "1.1-SNAPSHOT",
474                 "1.1");
475 
476         assertSequence("1.0-alpha", "1.0", "1.0-1");
477         assertSequence("1.0.alpha", "1.0", "1.0-1");
478         assertSequence("1.0-alpha", "1.0", "1.0.1");
479         assertSequence("1.0.alpha", "1.0", "1.0.1");
480     }
481 
482     @Test
483     void testMinimumSegment() {
484         assertOrder(X_LT_Y, "1.min", "1.0-alpha-1");
485         assertOrder(X_LT_Y, "1.min", "1.0-SNAPSHOT");
486         assertOrder(X_LT_Y, "1.min", "1.0");
487         assertOrder(X_LT_Y, "1.min", "1.9999999999");
488 
489         assertOrder(X_EQ_Y, "1.min", "1.MIN");
490 
491         assertOrder(X_GT_Y, "1.min", "0.99999");
492         assertOrder(X_GT_Y, "1.min", "0.max");
493     }
494 
495     @Test
496     void testMaximumSegment() {
497         assertOrder(X_GT_Y, "1.max", "1.0-alpha-1");
498         assertOrder(X_GT_Y, "1.max", "1.0-SNAPSHOT");
499         assertOrder(X_GT_Y, "1.max", "1.0");
500         assertOrder(X_GT_Y, "1.max", "1.9999999999");
501 
502         assertOrder(X_EQ_Y, "1.max", "1.MAX");
503 
504         assertOrder(X_LT_Y, "1.max", "2.0-alpha-1");
505         assertOrder(X_LT_Y, "1.max", "2.min");
506     }
507 
508     @Test
509     void testCompareLettersToNumbers() {
510         assertOrder(X_GT_Y, "1.7", "J");
511     }
512 
513     @Test
514     void testCompareDigitToLetter() {
515         assertOrder(X_GT_Y, "7", "J");
516         assertOrder(X_GT_Y, "7", "c");
517     }
518 
519     @Test
520     void testNonAsciiDigits() { // These should not be treated as digits.
521         String arabicEight = "\u0668";
522         assertOrder(X_GT_Y, "1", arabicEight);
523         assertOrder(X_GT_Y, "9", arabicEight);
524     }
525 
526     @Test
527     void testLexicographicOrder() {
528         assertOrder(X_GT_Y, "zebra", "aardvark");
529         assertOrder(X_GT_Y, "ζέβρα", "zebra");
530     }
531 
532     /**
533      * Test for <a href="https://issues.apache.org/jira/browse/MRESOLVER-314">MRESOLVER-314</a>.
534      *
535      * Generates random UUID string based versions and tries to sort them. While this test is not as reliable
536      * as {@link #testCompareUuidVersionStringStream()}, it covers broader range and in case it fails it records
537      * the failed array, so we can investigate more.
538      */
539     @Test
540     void testCompareUuidRandom() {
541         for (int j = 0; j < 32; j++) {
542             ArrayList<Version> versions = new ArrayList<>();
543             for (int i = 0; i < 64; i++) {
544                 versions.add(newVersion(UUID.randomUUID().toString()));
545             }
546             try {
547                 Collections.sort(versions);
548             } catch (Exception e) {
549                 e.printStackTrace(System.err);
550                 System.err.println("The UUIDs used");
551                 System.err.println(versions.stream().map(Version::toString).collect(Collectors.joining("\n")));
552                 fail("unexpected exception");
553             }
554         }
555     }
556 
557     /**
558      * UT for <a href="https://issues.apache.org/jira/browse/MRESOLVER-314">MRESOLVER-314</a>.
559      *
560      * Works on known set that failed before fix, provided by {@link #uuidVersionStringStream()}.
561      */
562     @Test
563     void testCompareUuidVersionStringStream() {
564         // this operation below fails with IAEx if comparison is unstable
565         uuidVersionStringStream().map(this::newVersion).sorted().collect(toList());
566     }
567 
568     private Stream<String> uuidVersionStringStream() {
569         return Stream.of(
570                 "e3f6b227-e09d-4461-a030-b8c1755834f7",
571                 "dfdf5e15-b047-4fee-94e5-3ddf6fe90a0c",
572                 "bcc15412-6817-4b64-acef-169d048626f6",
573                 "76093f07-ab1c-4cdd-ae92-9bb500ceed84",
574                 "7ca8dc9f-4e73-459b-8f30-06aa7972f486",
575                 "93fee46b-2715-4abd-877a-4197eb8601aa",
576                 "0379da36-84ee-4d06-9388-83d3aa6536b5",
577                 "4bb2c7a8-cf68-4ca5-8024-72dc93506da9",
578                 "9dcc4cd1-34d2-4499-8dab-3ef8bca9680d",
579                 "ea53d552-83ab-4f7d-852d-98951201083d",
580                 "0bc420d2-4089-468b-bc54-0a4e2835feed",
581                 "318d2433-fe40-4f28-9f3a-4e3d66d9b5fb",
582                 "447b456c-81a4-4f24-9d2e-e5091c39cd19",
583                 "85741f6e-26fe-40d0-a73a-283315409ab2",
584                 "3165b9b2-9f8e-4117-ac70-87056eb45745",
585                 "9d534bf3-a3b0-4a19-9809-670934c10752",
586                 "86d78bba-d84e-4349-aea6-850721e78188",
587                 "06392b8c-e26c-4a83-8ec2-085415bc513d",
588                 "1fb13754-90be-42cb-bc7f-9b9211494e92",
589                 "3018965c-3330-402a-8075-caa7613ec4fa",
590                 "7ecc912b-4938-4411-895e-8ca7cf22ce02",
591                 "6580ada2-4764-45a2-9789-98217d7cf5b6",
592                 "be9d0de4-4ba7-4fdd-8f76-cb579168c549",
593                 "7a8236d6-6bec-4176-b6a1-f869c02183c3",
594                 "089f4195-881c-4f9e-8bc1-124531dee977",
595                 "46ffda62-768a-4864-9581-cc75eafe1a67",
596                 "1d6226f6-dacc-42a9-bd88-7aab1f59df74",
597                 "0948ed55-c25e-4319-9801-5f817bac09b5",
598                 "2fd52f5e-b856-47ad-9e58-45c1d0ba437b",
599                 "6c325bd0-ac6b-4391-a5c5-caa160972fa2",
600                 "d213f6be-f56b-42d2-abda-4300742e0add",
601                 "efaae115-cc21-4b2e-a150-fb4e0d807736",
602                 "30f872e8-9cb5-4b22-b65c-6819ca7a14ba",
603                 "d8e5fb54-6e90-4f74-adb3-451abfbe76a8",
604                 "b47d62b8-9256-47a1-8e21-21ba9639c212",
605                 "b25da555-e1f7-4bc5-92fe-4c895d9c70d8",
606                 "088f0de7-5973-4c10-a7ff-9f3cd7718572",
607                 "b161de76-e5d5-4224-883b-a749b147d63d",
608                 "19b7de96-09fa-4276-843d-c0fbdaf07767",
609                 "e0503f73-33fd-4f9c-812f-8cae3a128c28",
610                 "b8c57488-a42c-43ed-bfb9-acd112d6b68f",
611                 "25997299-0825-4c9b-b0ed-75f935c63fd7",
612                 "2b2e2fcd-3988-45af-855b-7646c0cdbfb5",
613                 "4e6e16b9-2ae4-4593-b907-1febaf3988dc",
614                 "ac8bd519-7fd4-4b85-8154-9dbb87f6cd4f",
615                 "61473b39-b620-468b-abcf-16fe6adfd5cb",
616                 "18e7a548-3f0b-492b-bc19-dce3eec736fa",
617                 "c4d82839-3c46-4eff-b10c-ec0b5bcc600b",
618                 "48f6e90f-924b-4859-9763-3ffe661f5af6",
619                 "48852d79-ba23-475e-b675-a413b989a2a7",
620                 "f7ee0915-ff00-4404-9e9a-6e753d5ff767",
621                 "d6462359-a4e2-45ab-aedc-3b1849b0e6ca",
622                 "e66228de-d1ed-4973-a108-c181d5059fdb",
623                 "d49672a7-177d-475d-aad0-aab0ff4a11b7",
624                 "bfa9337a-0489-4cba-b2db-e0d9d2424e4f",
625                 "dc9bbe34-3c54-4c0f-a3cd-00e96604ae23",
626                 "a8119cf1-9694-4b24-923a-3fc729b5f809",
627                 "5d29cf45-3b9c-4697-85b8-86c81c6ec0c9",
628                 "e3dcb4c2-a867-40f7-a3b1-fb1058a041e5",
629                 "ae240754-2ea2-409a-a92c-648fc7a7b70b",
630                 "8c187383-d59b-4e49-8dfd-98aa5f01925a",
631                 "9b100ee6-71ed-4746-92c2-b5fb02af7ebd",
632                 "f95e94f7-2443-4b2f-a10d-059d8d224dd9",
633                 "b558af80-78bc-43c7-b916-d635a23cc4b5");
634     }
635 }