This is an automated email from the ASF dual-hosted git repository.

cstamas pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven-resolver.git


The following commit(s) were added to refs/heads/master by this push:
     new d731dc44 [MRESOLVER-314] IAEx thrown when sorting versions with hex 
values (#249)
d731dc44 is described below

commit d731dc44c5cf3950846dc4cd055b0beda63928aa
Author: Tamas Cservenak <[email protected]>
AuthorDate: Fri Feb 17 09:17:38 2023 +0100

    [MRESOLVER-314] IAEx thrown when sorting versions with hex values (#249)
    
    Long outstanding problem: GenericVersion since long time had issue with 
sorting some peculiar version strings (well, parsing them and the producing 
comparable Version instances to be precise). One kind of these peculiar strings 
are hex strings, that we even encourage should be used on this page 
https://maven.apache.org/maven-ci-friendly.html Problems happen, when Maven 
decides to sort these versions, like it happened to user using 
`versions-maven-plugin:set-property` that involves ver [...]
    
    Origin of the problem is that GenericVersion instances, when parsed out of 
hex-like strings, produce instances that violate Comparable contract 
(comparison is transitive), hence Java throws `Caused by: 
java.lang.IllegalArgumentException: Comparison method violates its general 
contract!` just out of the blue. Moreover, this problem affects both set of 
users: those who produce hex-like versioned artifacts, but also those who 
consume them.
    
    Problem was compare padding: when a number and non-number was about to be 
compared, the comparePadding was invoked, that simply stopped when a number was 
followed by a non-number. Proper fix is to make iteration all way to the end, 
otherwise here we end up with compare result 0 that means "equals", which in 
fact is not.
    
    ---
    
    https://issues.apache.org/jira/browse/MRESOLVER-314
---
 .../aether/util/version/GenericVersion.java        |  13 ++-
 .../aether/util/version/GenericVersionTest.java    | 125 ++++++++++++++++++++-
 2 files changed, 132 insertions(+), 6 deletions(-)

diff --git 
a/maven-resolver-util/src/main/java/org/eclipse/aether/util/version/GenericVersion.java
 
b/maven-resolver-util/src/main/java/org/eclipse/aether/util/version/GenericVersion.java
index 10219185..b440dbc9 100644
--- 
a/maven-resolver-util/src/main/java/org/eclipse/aether/util/version/GenericVersion.java
+++ 
b/maven-resolver-util/src/main/java/org/eclipse/aether/util/version/GenericVersion.java
@@ -170,7 +170,8 @@ final class GenericVersion
             Item item = items.get( i );
             if ( number != null && number != item.isNumber() )
             {
-                break;
+                // do not stop here, but continue, skipping non-number members
+                continue;
             }
             rel = item.compareTo( null );
             if ( rel != 0 )
@@ -228,6 +229,8 @@ final class GenericVersion
 
         private final String version;
 
+        private final int versionLength;
+
         private int index;
 
         private String token;
@@ -239,12 +242,12 @@ final class GenericVersion
         Tokenizer( String version )
         {
             this.version = ( version.length() > 0 ) ? version : "0";
+            this.versionLength = this.version.length();
         }
 
         public boolean next()
         {
-            final int n = version.length();
-            if ( index >= n )
+            if ( index >= versionLength )
             {
                 return false;
             }
@@ -252,10 +255,10 @@ final class GenericVersion
             int state = -2;
 
             int start = index;
-            int end = n;
+            int end = versionLength;
             terminatedByNumber = false;
 
-            for ( ; index < n; index++ )
+            for ( ; index < versionLength; index++ )
             {
                 char c = version.charAt( index );
 
diff --git 
a/maven-resolver-util/src/test/java/org/eclipse/aether/util/version/GenericVersionTest.java
 
b/maven-resolver-util/src/test/java/org/eclipse/aether/util/version/GenericVersionTest.java
index 8d058e44..55fbc8c3 100644
--- 
a/maven-resolver-util/src/test/java/org/eclipse/aether/util/version/GenericVersionTest.java
+++ 
b/maven-resolver-util/src/test/java/org/eclipse/aether/util/version/GenericVersionTest.java
@@ -19,12 +19,19 @@ package org.eclipse.aether.util.version;
  * under the License.
  */
 
+import java.util.ArrayList;
+import java.util.Collections;
 import java.util.Locale;
+import java.util.UUID;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
-import org.eclipse.aether.util.version.GenericVersion;
 import org.eclipse.aether.version.Version;
 import org.junit.Test;
 
+import static java.util.stream.Collectors.toList;
+import static org.junit.Assert.fail;
+
 /**
  */
 public class GenericVersionTest
@@ -345,4 +352,120 @@ public class GenericVersionTest
         assertOrder( X_LT_Y, "1.max", "2.min" );
     }
 
+    /**
+     * UT for <a 
href="https://issues.apache.org/jira/browse/MRESOLVER-314";>MRESOLVER-314</a>.
+     *
+     * Generates random UUID string based versions and tries to sort them. 
While this test is not as reliable
+     * as {@link #testCompareUuidVersionStringStream()}, it covers broader 
range and in case it fails it records
+     * the failed array, so we can investigate more.
+     */
+    @Test
+    public void testCompareUuidRandom() {
+            for ( int j = 0; j < 32; j++ )
+            {
+                ArrayList<Version> versions = new ArrayList<>();
+                for ( int i = 0; i < 64; i++ )
+                {
+                    versions.add( newVersion( UUID.randomUUID().toString() ) );
+                }
+                try
+                {
+                    Collections.sort( versions );
+                }
+                catch ( Exception e )
+                {
+                    e.printStackTrace( System.err );
+                    System.err.println( "The UUIDs used" );
+                    System.err.println(
+                            versions.stream().map( Version::toString 
).collect( Collectors.joining( "\n" ) ) );
+                    fail( "unexpected exception" );
+                }
+            }
+    }
+
+    /**
+     * UT for <a 
href="https://issues.apache.org/jira/browse/MRESOLVER-314";>MRESOLVER-314</a>.
+     *
+     * Works on known set that failed before fix, provided by {@link 
#uuidVersionStringStream()}.
+     */
+    @Test
+    public void testCompareUuidVersionStringStream()
+    {
+        // this operation below fails with IAEx if comparison is unstable
+        uuidVersionStringStream()
+                .map( this::newVersion )
+                .sorted()
+                .collect( toList() );
+    }
+
+    private Stream<String> uuidVersionStringStream()
+    {
+        return Stream.of(
+                "e3f6b227-e09d-4461-a030-b8c1755834f7",
+                "dfdf5e15-b047-4fee-94e5-3ddf6fe90a0c",
+                "bcc15412-6817-4b64-acef-169d048626f6",
+                "76093f07-ab1c-4cdd-ae92-9bb500ceed84",
+                "7ca8dc9f-4e73-459b-8f30-06aa7972f486",
+                "93fee46b-2715-4abd-877a-4197eb8601aa",
+                "0379da36-84ee-4d06-9388-83d3aa6536b5",
+                "4bb2c7a8-cf68-4ca5-8024-72dc93506da9",
+                "9dcc4cd1-34d2-4499-8dab-3ef8bca9680d",
+                "ea53d552-83ab-4f7d-852d-98951201083d",
+                "0bc420d2-4089-468b-bc54-0a4e2835feed",
+                "318d2433-fe40-4f28-9f3a-4e3d66d9b5fb",
+                "447b456c-81a4-4f24-9d2e-e5091c39cd19",
+                "85741f6e-26fe-40d0-a73a-283315409ab2",
+                "3165b9b2-9f8e-4117-ac70-87056eb45745",
+                "9d534bf3-a3b0-4a19-9809-670934c10752",
+                "86d78bba-d84e-4349-aea6-850721e78188",
+                "06392b8c-e26c-4a83-8ec2-085415bc513d",
+                "1fb13754-90be-42cb-bc7f-9b9211494e92",
+                "3018965c-3330-402a-8075-caa7613ec4fa",
+                "7ecc912b-4938-4411-895e-8ca7cf22ce02",
+                "6580ada2-4764-45a2-9789-98217d7cf5b6",
+                "be9d0de4-4ba7-4fdd-8f76-cb579168c549",
+                "7a8236d6-6bec-4176-b6a1-f869c02183c3",
+                "089f4195-881c-4f9e-8bc1-124531dee977",
+                "46ffda62-768a-4864-9581-cc75eafe1a67",
+                "1d6226f6-dacc-42a9-bd88-7aab1f59df74",
+                "0948ed55-c25e-4319-9801-5f817bac09b5",
+                "2fd52f5e-b856-47ad-9e58-45c1d0ba437b",
+                "6c325bd0-ac6b-4391-a5c5-caa160972fa2",
+                "d213f6be-f56b-42d2-abda-4300742e0add",
+                "efaae115-cc21-4b2e-a150-fb4e0d807736",
+                "30f872e8-9cb5-4b22-b65c-6819ca7a14ba",
+                "d8e5fb54-6e90-4f74-adb3-451abfbe76a8",
+                "b47d62b8-9256-47a1-8e21-21ba9639c212",
+                "b25da555-e1f7-4bc5-92fe-4c895d9c70d8",
+                "088f0de7-5973-4c10-a7ff-9f3cd7718572",
+                "b161de76-e5d5-4224-883b-a749b147d63d",
+                "19b7de96-09fa-4276-843d-c0fbdaf07767",
+                "e0503f73-33fd-4f9c-812f-8cae3a128c28",
+                "b8c57488-a42c-43ed-bfb9-acd112d6b68f",
+                "25997299-0825-4c9b-b0ed-75f935c63fd7",
+                "2b2e2fcd-3988-45af-855b-7646c0cdbfb5",
+                "4e6e16b9-2ae4-4593-b907-1febaf3988dc",
+                "ac8bd519-7fd4-4b85-8154-9dbb87f6cd4f",
+                "61473b39-b620-468b-abcf-16fe6adfd5cb",
+                "18e7a548-3f0b-492b-bc19-dce3eec736fa",
+                "c4d82839-3c46-4eff-b10c-ec0b5bcc600b",
+                "48f6e90f-924b-4859-9763-3ffe661f5af6",
+                "48852d79-ba23-475e-b675-a413b989a2a7",
+                "f7ee0915-ff00-4404-9e9a-6e753d5ff767",
+                "d6462359-a4e2-45ab-aedc-3b1849b0e6ca",
+                "e66228de-d1ed-4973-a108-c181d5059fdb",
+                "d49672a7-177d-475d-aad0-aab0ff4a11b7",
+                "bfa9337a-0489-4cba-b2db-e0d9d2424e4f",
+                "dc9bbe34-3c54-4c0f-a3cd-00e96604ae23",
+                "a8119cf1-9694-4b24-923a-3fc729b5f809",
+                "5d29cf45-3b9c-4697-85b8-86c81c6ec0c9",
+                "e3dcb4c2-a867-40f7-a3b1-fb1058a041e5",
+                "ae240754-2ea2-409a-a92c-648fc7a7b70b",
+                "8c187383-d59b-4e49-8dfd-98aa5f01925a",
+                "9b100ee6-71ed-4746-92c2-b5fb02af7ebd",
+                "f95e94f7-2443-4b2f-a10d-059d8d224dd9",
+                "b558af80-78bc-43c7-b916-d635a23cc4b5");
+    }
+
+
 }

Reply via email to