View Javadoc
1   package org.apache.maven.artifact.versioning;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import java.util.Locale;
23  
24  import junit.framework.TestCase;
25  
26  /**
27   * Test ComparableVersion.
28   *
29   * @author <a href="mailto:hboutemy@apache.org">Hervé Boutemy</a>
30   */
31  @SuppressWarnings( "unchecked" )
32  public class ComparableVersionTest
33      extends TestCase
34  {
35      private Comparable newComparable( String version )
36      {
37          ComparableVersion ret = new ComparableVersion( version );
38          String canonical = ret.getCanonical();
39          String parsedCanonical = new ComparableVersion( canonical ).getCanonical();
40  
41          System.out.println( "canonical( " + version + " ) = " + canonical );
42          assertEquals( "canonical( " + version + " ) = " + canonical + " -> canonical: " + parsedCanonical, canonical,
43                        parsedCanonical );
44  
45          return ret;
46      }
47  
48      private static final String[] VERSIONS_QUALIFIER =
49          { "1-alpha2snapshot", "1-alpha2", "1-alpha-123", "1-beta-2", "1-beta123", "1-m2", "1-m11", "1-rc", "1-cr2",
50              "1-rc123", "1-SNAPSHOT", "1", "1-sp", "1-sp2", "1-sp123", "1-abc", "1-def", "1-pom-1", "1-1-snapshot",
51              "1-1", "1-2", "1-123" };
52  
53      private static final String[] VERSIONS_NUMBER =
54          { "2.0", "2-1", "2.0.a", "2.0.0.a", "2.0.2", "2.0.123", "2.1.0", "2.1-a", "2.1b", "2.1-c", "2.1-1", "2.1.0.1",
55              "2.2", "2.123", "11.a2", "11.a11", "11.b2", "11.b11", "11.m2", "11.m11", "11", "11.a", "11b", "11c", "11m" };
56  
57      private void checkVersionsOrder( String[] versions )
58      {
59          Comparable[] c = new Comparable[versions.length];
60          for ( int i = 0; i < versions.length; i++ )
61          {
62              c[i] = newComparable( versions[i] );
63          }
64  
65          for ( int i = 1; i < versions.length; i++ )
66          {
67              Comparable low = c[i - 1];
68              for ( int j = i; j < versions.length; j++ )
69              {
70                  Comparable high = c[j];
71                  assertTrue( "expected " + low + " < " + high, low.compareTo( high ) < 0 );
72                  assertTrue( "expected " + high + " > " + low, high.compareTo( low ) > 0 );
73              }
74          }
75      }
76  
77      private void checkVersionsEqual( String v1, String v2 )
78      {
79          Comparable c1 = newComparable( v1 );
80          Comparable c2 = newComparable( v2 );
81          assertTrue( "expected " + v1 + " == " + v2, c1.compareTo( c2 ) == 0 );
82          assertTrue( "expected " + v2 + " == " + v1, c2.compareTo( c1 ) == 0 );
83          assertTrue( "expected same hashcode for " + v1 + " and " + v2, c1.hashCode() == c2.hashCode() );
84          assertTrue( "expected " + v1 + ".equals( " + v2 + " )", c1.equals( c2 ) );
85          assertTrue( "expected " + v2 + ".equals( " + v1 + " )", c2.equals( c1 ) );
86      }
87  
88      private void checkVersionsArrayEqual( String[] array )
89      {
90          // compare against each other (including itself)
91          for ( int i = 0; i < array.length; ++i )
92              for ( int j = i; j < array.length; ++j )
93                  checkVersionsEqual( array[i], array[j] );
94      }
95  
96      private void checkVersionsOrder( String v1, String v2 )
97      {
98          Comparable c1 = newComparable( v1 );
99          Comparable c2 = newComparable( v2 );
100         assertTrue( "expected " + v1 + " < " + v2, c1.compareTo( c2 ) < 0 );
101         assertTrue( "expected " + v2 + " > " + v1, c2.compareTo( c1 ) > 0 );
102     }
103 
104     public void testVersionsQualifier()
105     {
106         checkVersionsOrder( VERSIONS_QUALIFIER );
107     }
108 
109     public void testVersionsNumber()
110     {
111         checkVersionsOrder( VERSIONS_NUMBER );
112     }
113 
114     public void testVersionsEqual()
115     {
116         newComparable( "1.0-alpha" );
117         checkVersionsEqual( "1", "1" );
118         checkVersionsEqual( "1", "1.0" );
119         checkVersionsEqual( "1", "1.0.0" );
120         checkVersionsEqual( "1.0", "1.0.0" );
121         checkVersionsEqual( "1", "1-0" );
122         checkVersionsEqual( "1", "1.0-0" );
123         checkVersionsEqual( "1.0", "1.0-0" );
124         // no separator between number and character
125         checkVersionsEqual( "1a", "1-a" );
126         checkVersionsEqual( "1a", "1.0-a" );
127         checkVersionsEqual( "1a", "1.0.0-a" );
128         checkVersionsEqual( "1.0a", "1-a" );
129         checkVersionsEqual( "1.0.0a", "1-a" );
130         checkVersionsEqual( "1x", "1-x" );
131         checkVersionsEqual( "1x", "1.0-x" );
132         checkVersionsEqual( "1x", "1.0.0-x" );
133         checkVersionsEqual( "1.0x", "1-x" );
134         checkVersionsEqual( "1.0.0x", "1-x" );
135 
136         // aliases
137         checkVersionsEqual( "1ga", "1" );
138         checkVersionsEqual( "1release", "1" );
139         checkVersionsEqual( "1final", "1" );
140         checkVersionsEqual( "1cr", "1rc" );
141 
142         // special "aliases" a, b and m for alpha, beta and milestone
143         checkVersionsEqual( "1a1", "1-alpha-1" );
144         checkVersionsEqual( "1b2", "1-beta-2" );
145         checkVersionsEqual( "1m3", "1-milestone-3" );
146 
147         // case insensitive
148         checkVersionsEqual( "1X", "1x" );
149         checkVersionsEqual( "1A", "1a" );
150         checkVersionsEqual( "1B", "1b" );
151         checkVersionsEqual( "1M", "1m" );
152         checkVersionsEqual( "1Ga", "1" );
153         checkVersionsEqual( "1GA", "1" );
154         checkVersionsEqual( "1RELEASE", "1" );
155         checkVersionsEqual( "1release", "1" );
156         checkVersionsEqual( "1RELeaSE", "1" );
157         checkVersionsEqual( "1Final", "1" );
158         checkVersionsEqual( "1FinaL", "1" );
159         checkVersionsEqual( "1FINAL", "1" );
160         checkVersionsEqual( "1Cr", "1Rc" );
161         checkVersionsEqual( "1cR", "1rC" );
162         checkVersionsEqual( "1m3", "1Milestone3" );
163         checkVersionsEqual( "1m3", "1MileStone3" );
164         checkVersionsEqual( "1m3", "1MILESTONE3" );
165     }
166 
167     public void testVersionComparing()
168     {
169         checkVersionsOrder( "1", "2" );
170         checkVersionsOrder( "1.5", "2" );
171         checkVersionsOrder( "1", "2.5" );
172         checkVersionsOrder( "1.0", "1.1" );
173         checkVersionsOrder( "1.1", "1.2" );
174         checkVersionsOrder( "1.0.0", "1.1" );
175         checkVersionsOrder( "1.0.1", "1.1" );
176         checkVersionsOrder( "1.1", "1.2.0" );
177 
178         checkVersionsOrder( "1.0-alpha-1", "1.0" );
179         checkVersionsOrder( "1.0-alpha-1", "1.0-alpha-2" );
180         checkVersionsOrder( "1.0-alpha-1", "1.0-beta-1" );
181 
182         checkVersionsOrder( "1.0-beta-1", "1.0-SNAPSHOT" );
183         checkVersionsOrder( "1.0-SNAPSHOT", "1.0" );
184         checkVersionsOrder( "1.0-alpha-1-SNAPSHOT", "1.0-alpha-1" );
185 
186         checkVersionsOrder( "1.0", "1.0-1" );
187         checkVersionsOrder( "1.0-1", "1.0-2" );
188         checkVersionsOrder( "1.0.0", "1.0-1" );
189 
190         checkVersionsOrder( "2.0-1", "2.0.1" );
191         checkVersionsOrder( "2.0.1-klm", "2.0.1-lmn" );
192         checkVersionsOrder( "2.0.1", "2.0.1-xyz" );
193 
194         checkVersionsOrder( "2.0.1", "2.0.1-123" );
195         checkVersionsOrder( "2.0.1-xyz", "2.0.1-123" );
196     }
197 
198     /**
199      * Test <a href="https://issues.apache.org/jira/browse/MNG-5568">MNG-5568</a> edge case
200      * which was showing transitive inconsistency: since A &gt; B and B &gt; C then we should have A &gt; C
201      * otherwise sorting a list of ComparableVersions() will in some cases throw runtime exception;
202      * see Netbeans issues <a href="https://netbeans.org/bugzilla/show_bug.cgi?id=240845">240845</a> and
203      * <a href="https://netbeans.org/bugzilla/show_bug.cgi?id=226100">226100</a>
204      */
205     public void testMng5568()
206     {
207         String a = "6.1.0";
208         String b = "6.1.0rc3";
209         String c = "6.1H.5-beta"; // this is the unusual version string, with 'H' in the middle
210 
211         checkVersionsOrder( b, a ); // classical
212         checkVersionsOrder( b, c ); // now b < c, but before MNG-5568, we had b > c
213         checkVersionsOrder( a, c );
214     }
215 
216     /**
217      * Test <a href="https://jira.apache.org/jira/browse/MNG-6572">MNG-6572</a> optimization.
218      */
219     public void testMng6572()
220     {
221         String a = "20190126.230843"; // resembles a SNAPSHOT
222         String b = "1234567890.12345"; // 10 digit number
223         String c = "123456789012345.1H.5-beta"; // 15 digit number
224         String d = "12345678901234567890.1H.5-beta"; // 20 digit number
225 
226         checkVersionsOrder( a, b );
227         checkVersionsOrder( b, c );
228         checkVersionsOrder( a, c );
229         checkVersionsOrder( c, d );
230         checkVersionsOrder( b, d );
231         checkVersionsOrder( a, d );
232     }
233 
234     /**
235      * Test all versions are equal when starting with many leading zeroes regardless of string length
236      * (related to MNG-6572 optimization)
237      */
238     public void testVersionEqualWithLeadingZeroes()
239     {
240         // versions with string lengths from 1 to 19
241         String[] arr = new String[] {
242             "0000000000000000001",
243             "000000000000000001",
244             "00000000000000001",
245             "0000000000000001",
246             "000000000000001",
247             "00000000000001",
248             "0000000000001",
249             "000000000001",
250             "00000000001",
251             "0000000001",
252             "000000001",
253             "00000001",
254             "0000001",
255             "000001",
256             "00001",
257             "0001",
258             "001",
259             "01",
260             "1"
261         };
262 
263         checkVersionsArrayEqual( arr );
264     }
265 
266     /**
267      * Test all "0" versions are equal when starting with many leading zeroes regardless of string length
268      * (related to MNG-6572 optimization)
269      */
270     public void testVersionZeroEqualWithLeadingZeroes()
271     {
272         // versions with string lengths from 1 to 19
273         String[] arr = new String[] {
274             "0000000000000000000",
275             "000000000000000000",
276             "00000000000000000",
277             "0000000000000000",
278             "000000000000000",
279             "00000000000000",
280             "0000000000000",
281             "000000000000",
282             "00000000000",
283             "0000000000",
284             "000000000",
285             "00000000",
286             "0000000",
287             "000000",
288             "00000",
289             "0000",
290             "000",
291             "00",
292             "0"
293         };
294 
295         checkVersionsArrayEqual( arr );
296     }
297 
298     public void testLocaleIndependent()
299     {
300         Locale orig = Locale.getDefault();
301         Locale[] locales = { Locale.ENGLISH, new Locale( "tr" ), Locale.getDefault() };
302         try
303         {
304             for ( Locale locale : locales )
305             {
306                 Locale.setDefault( locale );
307                 checkVersionsEqual( "1-abcdefghijklmnopqrstuvwxyz", "1-ABCDEFGHIJKLMNOPQRSTUVWXYZ" );
308             }
309         }
310         finally
311         {
312             Locale.setDefault( orig );
313         }
314     }
315 
316     public void testReuse()
317     {
318         ComparableVersion c1 = new ComparableVersion( "1" );
319         c1.parseVersion( "2" );
320 
321         Comparable c2 = newComparable( "2" );
322 
323         assertEquals( "reused instance should be equivalent to new instance", c1, c2 );
324     }
325 }