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");
+ }
+
+
}