优化 VersionNumber (#2240)
* 优化 VersionNumber * Add more tests * update * update tests
This commit is contained in:
@@ -17,8 +17,6 @@
|
||||
*/
|
||||
package org.jackhuang.hmcl.util.versioning;
|
||||
|
||||
import org.jackhuang.hmcl.util.StringUtils;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.*;
|
||||
|
||||
@@ -29,7 +27,9 @@ import java.util.*;
|
||||
* Maybe we can migrate to org.jenkins-ci:version-number:1.7?
|
||||
* @see <a href="http://maven.apache.org/pom.html#Version_Order_Specification">Specification</a>
|
||||
*/
|
||||
public class VersionNumber implements Comparable<VersionNumber> {
|
||||
public final class VersionNumber implements Comparable<VersionNumber> {
|
||||
|
||||
public static final Comparator<String> VERSION_COMPARATOR = Comparator.comparing(VersionNumber::asVersion);
|
||||
|
||||
public static VersionNumber asVersion(String version) {
|
||||
Objects.requireNonNull(version);
|
||||
@@ -41,68 +41,85 @@ public class VersionNumber implements Comparable<VersionNumber> {
|
||||
}
|
||||
|
||||
public static boolean isIntVersionNumber(String version) {
|
||||
if (version.chars().noneMatch(ch -> ch != '.' && (ch < '0' || ch > '9'))
|
||||
&& !version.contains("..") && StringUtils.isNotBlank(version)) {
|
||||
String[] arr = version.split("\\.");
|
||||
for (String str : arr)
|
||||
if (str.length() > 9)
|
||||
// Numbers which are larger than 1e9 cannot be stored as integer.
|
||||
return false;
|
||||
return true;
|
||||
} else {
|
||||
if (version.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int idx = 0;
|
||||
boolean cont = true;
|
||||
do {
|
||||
int dotIndex = version.indexOf('.', idx);
|
||||
if (dotIndex == idx || dotIndex == version.length() - 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int endIndex;
|
||||
if (dotIndex < 0) {
|
||||
cont = false;
|
||||
endIndex = version.length();
|
||||
} else {
|
||||
endIndex = dotIndex;
|
||||
}
|
||||
|
||||
if (endIndex - idx > 9)
|
||||
// Numbers which are larger than 10^10 cannot be stored as integer
|
||||
return false;
|
||||
|
||||
for (int i = idx; i < endIndex; i++) {
|
||||
char ch = version.charAt(i);
|
||||
if (ch < '0' || ch > '9')
|
||||
return false;
|
||||
}
|
||||
|
||||
idx = endIndex + 1;
|
||||
} while (cont);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private String value;
|
||||
private String canonical;
|
||||
private ListItem items;
|
||||
|
||||
private interface Item {
|
||||
int INTEGER_ITEM = 0;
|
||||
int STRING_ITEM = 1;
|
||||
int LIST_ITEM = 2;
|
||||
int LONG_ITEM = 0;
|
||||
int BIGINTEGER_ITEM = 1;
|
||||
int STRING_ITEM = 2;
|
||||
int LIST_ITEM = 3;
|
||||
|
||||
int compareTo(Item item);
|
||||
|
||||
int getType();
|
||||
|
||||
boolean isNull();
|
||||
|
||||
void appendTo(StringBuilder buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a numeric item in the version item list.
|
||||
*/
|
||||
private static class IntegerItem
|
||||
implements Item {
|
||||
private final BigInteger value;
|
||||
private static final class LongItem implements Item {
|
||||
private final long value;
|
||||
|
||||
public static final IntegerItem ZERO = new IntegerItem();
|
||||
public static final LongItem ZERO = new LongItem(0L);
|
||||
|
||||
private IntegerItem() {
|
||||
this.value = BigInteger.ZERO;
|
||||
}
|
||||
|
||||
IntegerItem(String str) {
|
||||
this.value = new BigInteger(str);
|
||||
LongItem(long value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public int getType() {
|
||||
return INTEGER_ITEM;
|
||||
return LONG_ITEM;
|
||||
}
|
||||
|
||||
public boolean isNull() {
|
||||
return BigInteger.ZERO.equals(value);
|
||||
return value == 0L;
|
||||
}
|
||||
|
||||
public int compareTo(Item item) {
|
||||
if (item == null) {
|
||||
return BigInteger.ZERO.equals(value) ? 0 : 1; // 1.0 == 1, 1.1 > 1
|
||||
return value == 0L ? 0 : 1; // 1.0 == 1, 1.1 > 1
|
||||
}
|
||||
|
||||
switch (item.getType()) {
|
||||
case INTEGER_ITEM:
|
||||
return value.compareTo(((IntegerItem) item).value);
|
||||
case LONG_ITEM:
|
||||
long itemValue = ((LongItem) item).value;
|
||||
return Long.compare(value, itemValue);
|
||||
case BIGINTEGER_ITEM:
|
||||
return -1;
|
||||
|
||||
case STRING_ITEM:
|
||||
return 1; // 1.1 > 1-sp
|
||||
@@ -111,10 +128,68 @@ public class VersionNumber implements Comparable<VersionNumber> {
|
||||
return 1; // 1.1 > 1-1
|
||||
|
||||
default:
|
||||
throw new RuntimeException("invalid item: " + item.getClass());
|
||||
throw new AssertionError("invalid item: " + item.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendTo(StringBuilder buffer) {
|
||||
buffer.append(value);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return Long.toString(value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a numeric item in the version item list.
|
||||
*/
|
||||
private static final class BigIntegerItem implements Item {
|
||||
private final BigInteger value;
|
||||
|
||||
BigIntegerItem(String str) {
|
||||
this.value = new BigInteger(str);
|
||||
}
|
||||
|
||||
public int getType() {
|
||||
return BIGINTEGER_ITEM;
|
||||
}
|
||||
|
||||
public boolean isNull() {
|
||||
// Never be 0
|
||||
// return BigInteger.ZERO.equals(value);
|
||||
return false;
|
||||
}
|
||||
|
||||
public int compareTo(Item item) {
|
||||
if (item == null) {
|
||||
// return BigInteger.ZERO.equals(value) ? 0 : 1; // 1.0 == 1, 1.1 > 1
|
||||
return 1;
|
||||
}
|
||||
|
||||
switch (item.getType()) {
|
||||
case LONG_ITEM:
|
||||
return 1;
|
||||
case BIGINTEGER_ITEM:
|
||||
return value.compareTo(((BigIntegerItem) item).value);
|
||||
|
||||
case STRING_ITEM:
|
||||
return 1; // 1.1 > 1-sp
|
||||
|
||||
case LIST_ITEM:
|
||||
return 1; // 1.1 > 1-1
|
||||
|
||||
default:
|
||||
throw new AssertionError("invalid item: " + item.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendTo(StringBuilder buffer) {
|
||||
buffer.append(value);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return value.toString();
|
||||
}
|
||||
@@ -123,9 +198,8 @@ public class VersionNumber implements Comparable<VersionNumber> {
|
||||
/**
|
||||
* Represents a string in the version item list, usually a qualifier.
|
||||
*/
|
||||
private static class StringItem
|
||||
implements Item {
|
||||
private String value;
|
||||
private static final class StringItem implements Item {
|
||||
private final String value;
|
||||
|
||||
StringItem(String value) {
|
||||
this.value = value;
|
||||
@@ -145,7 +219,8 @@ public class VersionNumber implements Comparable<VersionNumber> {
|
||||
return 1;
|
||||
}
|
||||
switch (item.getType()) {
|
||||
case INTEGER_ITEM:
|
||||
case LONG_ITEM:
|
||||
case BIGINTEGER_ITEM:
|
||||
return -1; // 1.any < 1.1 ?
|
||||
|
||||
case STRING_ITEM:
|
||||
@@ -155,10 +230,15 @@ public class VersionNumber implements Comparable<VersionNumber> {
|
||||
return -1; // 1.any < 1-1
|
||||
|
||||
default:
|
||||
throw new RuntimeException("invalid item: " + item.getClass());
|
||||
throw new AssertionError("invalid item: " + item.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendTo(StringBuilder buffer) {
|
||||
buffer.append(value);
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return value;
|
||||
}
|
||||
@@ -168,14 +248,14 @@ public class VersionNumber implements Comparable<VersionNumber> {
|
||||
* Represents a version list item. This class is used both for the global item list and for sub-lists (which start
|
||||
* with '-(number)' in the version specification).
|
||||
*/
|
||||
private static class ListItem
|
||||
extends ArrayList<Item>
|
||||
implements Item {
|
||||
Character separator;
|
||||
private static final class ListItem extends ArrayList<Item> implements Item {
|
||||
private final Character separator;
|
||||
|
||||
public ListItem() {}
|
||||
ListItem() {
|
||||
this.separator = null;
|
||||
}
|
||||
|
||||
public ListItem(char separator) {
|
||||
ListItem(char separator) {
|
||||
this.separator = separator;
|
||||
}
|
||||
|
||||
@@ -184,7 +264,7 @@ public class VersionNumber implements Comparable<VersionNumber> {
|
||||
}
|
||||
|
||||
public boolean isNull() {
|
||||
return (size() == 0);
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
void normalize() {
|
||||
@@ -209,7 +289,8 @@ public class VersionNumber implements Comparable<VersionNumber> {
|
||||
return first.compareTo(null);
|
||||
}
|
||||
switch (item.getType()) {
|
||||
case INTEGER_ITEM:
|
||||
case LONG_ITEM:
|
||||
case BIGINTEGER_ITEM:
|
||||
return -1; // 1-1 < 1.0.x
|
||||
|
||||
case STRING_ITEM:
|
||||
@@ -234,36 +315,46 @@ public class VersionNumber implements Comparable<VersionNumber> {
|
||||
return 0;
|
||||
|
||||
default:
|
||||
throw new RuntimeException("invalid item: " + item.getClass());
|
||||
throw new AssertionError("invalid item: " + item.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendTo(StringBuilder buffer) {
|
||||
if (separator != null) {
|
||||
buffer.append((char) separator);
|
||||
}
|
||||
|
||||
final int initLength = buffer.length();
|
||||
|
||||
for (Item item : this) {
|
||||
if (buffer.length() > initLength) {
|
||||
if (!(item instanceof ListItem))
|
||||
buffer.append('.');
|
||||
}
|
||||
item.appendTo(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
for (Item item : this) {
|
||||
if (buffer.length() > 0) {
|
||||
if (!(item instanceof ListItem))
|
||||
buffer.append('.');
|
||||
}
|
||||
buffer.append(item);
|
||||
}
|
||||
if (separator != null)
|
||||
return separator + buffer.toString();
|
||||
else
|
||||
return buffer.toString();
|
||||
appendTo(buffer);
|
||||
return buffer.toString();
|
||||
}
|
||||
}
|
||||
|
||||
public VersionNumber(String version) {
|
||||
parseVersion(version);
|
||||
}
|
||||
private static final int MAX_LONGITEM_LENGTH = 18;
|
||||
|
||||
private void parseVersion(String version) {
|
||||
private final String value;
|
||||
public final ListItem items;
|
||||
private final String canonical;
|
||||
|
||||
private VersionNumber(String version) {
|
||||
this.value = version;
|
||||
|
||||
ListItem list = items = new ListItem();
|
||||
ListItem list = this.items = new ListItem();
|
||||
|
||||
Stack<Item> stack = new Stack<>();
|
||||
Deque<Item> stack = new ArrayDeque<>();
|
||||
stack.push(list);
|
||||
|
||||
boolean isDigit = false;
|
||||
@@ -275,14 +366,14 @@ public class VersionNumber implements Comparable<VersionNumber> {
|
||||
|
||||
if (c == '.') {
|
||||
if (i == startIndex) {
|
||||
list.add(IntegerItem.ZERO);
|
||||
list.add(LongItem.ZERO);
|
||||
} else {
|
||||
list.add(parseItem(version.substring(startIndex, i)));
|
||||
}
|
||||
startIndex = i + 1;
|
||||
} else if ("!\"#$%&'()*+,-/:;<=>?@[\\]^_`{|}~".indexOf(c) != -1) {
|
||||
if (i == startIndex) {
|
||||
list.add(IntegerItem.ZERO);
|
||||
list.add(LongItem.ZERO);
|
||||
} else {
|
||||
list.add(parseItem(version.substring(startIndex, i)));
|
||||
}
|
||||
@@ -290,7 +381,7 @@ public class VersionNumber implements Comparable<VersionNumber> {
|
||||
|
||||
list.add(list = new ListItem(c));
|
||||
stack.push(list);
|
||||
} else if (Character.isDigit(c)) {
|
||||
} else if (c >= '0' && c <= '9') {
|
||||
if (!isDigit && i > startIndex) {
|
||||
list.add(parseItem(version.substring(startIndex, i)));
|
||||
startIndex = i;
|
||||
@@ -322,11 +413,42 @@ public class VersionNumber implements Comparable<VersionNumber> {
|
||||
list.normalize();
|
||||
}
|
||||
|
||||
canonical = items.toString();
|
||||
this.canonical = items.toString();
|
||||
}
|
||||
|
||||
// For simple version
|
||||
private VersionNumber(String version, ListItem items) {
|
||||
this.value = version;
|
||||
this.items = items;
|
||||
this.canonical = version;
|
||||
}
|
||||
|
||||
private static Item parseItem(String buf) {
|
||||
return buf.chars().allMatch(Character::isDigit) ? new IntegerItem(buf) : new StringItem(buf);
|
||||
int numberLength = 0;
|
||||
boolean leadingZero = true;
|
||||
for (int i = 0; i < buf.length(); i++) {
|
||||
char ch = buf.charAt(i);
|
||||
if (ch >= '0' && ch <= '9') {
|
||||
if (ch != '0') {
|
||||
leadingZero = false;
|
||||
}
|
||||
|
||||
if (!leadingZero) {
|
||||
numberLength++;
|
||||
}
|
||||
} else {
|
||||
return new StringItem(buf);
|
||||
}
|
||||
}
|
||||
|
||||
if (numberLength == 0) {
|
||||
return LongItem.ZERO;
|
||||
} else if (numberLength <= MAX_LONGITEM_LENGTH) {
|
||||
// Numbers which are larger than 10^19 cannot be stored as long
|
||||
return new LongItem(Long.parseLong(buf));
|
||||
} else {
|
||||
return new BigIntegerItem(buf);
|
||||
}
|
||||
}
|
||||
|
||||
public int compareTo(String o) {
|
||||
@@ -364,6 +486,4 @@ public class VersionNumber implements Comparable<VersionNumber> {
|
||||
public int hashCode() {
|
||||
return canonical.hashCode();
|
||||
}
|
||||
|
||||
public static final Comparator<String> VERSION_COMPARATOR = Comparator.comparing(VersionNumber::asVersion);
|
||||
}
|
||||
|
||||
@@ -19,105 +19,135 @@ package org.jackhuang.hmcl.util.versioning;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import static org.jackhuang.hmcl.util.versioning.VersionNumber.isIntVersionNumber;
|
||||
import static org.jackhuang.hmcl.util.versioning.VersionNumber.normalize;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class VersionNumberTest {
|
||||
|
||||
@Test
|
||||
public void testCanonical() {
|
||||
VersionNumber u, v;
|
||||
assertEquals("3.2", normalize("3.2.0.0"));
|
||||
assertEquals("3.2-5", normalize("3.2.0.0-5"));
|
||||
assertEquals("3.2", normalize("3.2.0.0-0"));
|
||||
assertEquals("3.2", normalize("3.2--------"));
|
||||
assertEquals("3.2", normalize("3.0002"));
|
||||
assertEquals("1.7.2$%%^@&snapshot-3.1.1", normalize("1.7.2$%%^@&snapshot-3.1.1"));
|
||||
assertEquals("1.99999999999999999999", normalize("1.99999999999999999999"));
|
||||
assertEquals("1.99999999999999999999", normalize("1.0099999999999999999999"));
|
||||
assertEquals("1.99999999999999999999", normalize("1.99999999999999999999.0"));
|
||||
assertEquals("1.99999999999999999999", normalize("1.99999999999999999999--------"));
|
||||
}
|
||||
|
||||
v = VersionNumber.asVersion("3.2.0.0");
|
||||
assertEquals("3.2", v.getCanonical());
|
||||
@Test
|
||||
public void testIsIntVersion() {
|
||||
assertFalse(isIntVersionNumber(""));
|
||||
assertFalse(isIntVersionNumber(" "));
|
||||
assertFalse(isIntVersionNumber("."));
|
||||
assertFalse(isIntVersionNumber("1."));
|
||||
assertFalse(isIntVersionNumber(".1"));
|
||||
assertFalse(isIntVersionNumber(".1."));
|
||||
assertFalse(isIntVersionNumber("1..8"));
|
||||
assertFalse(isIntVersionNumber("1.8."));
|
||||
assertFalse(isIntVersionNumber(".1.8"));
|
||||
assertFalse(isIntVersionNumber("1.7.10forge1614_FTBInfinity"));
|
||||
assertFalse(isIntVersionNumber("3.2-5"));
|
||||
assertFalse(isIntVersionNumber("1.9999999999"));
|
||||
|
||||
v = VersionNumber.asVersion("3.2.0.0-5");
|
||||
assertEquals("3.2-5", v.getCanonical());
|
||||
assertTrue(isIntVersionNumber("0"));
|
||||
assertTrue(isIntVersionNumber("1"));
|
||||
assertTrue(isIntVersionNumber("0.1"));
|
||||
assertTrue(isIntVersionNumber("0.1.0"));
|
||||
assertTrue(isIntVersionNumber("1.8"));
|
||||
assertTrue(isIntVersionNumber("1.12.2"));
|
||||
assertTrue(isIntVersionNumber("1.13.1"));
|
||||
assertTrue(isIntVersionNumber("1.999999999"));
|
||||
assertTrue(isIntVersionNumber("999999999.0"));
|
||||
}
|
||||
|
||||
v = VersionNumber.asVersion("3.2.0.0-0");
|
||||
assertEquals("3.2", v.getCanonical());
|
||||
private static void assertLessThan(String s1, String s2) {
|
||||
Supplier<String> messageSupplier = () -> String.format("%s should be less than %s", s1, s2);
|
||||
|
||||
v = VersionNumber.asVersion("3.2--------");
|
||||
assertEquals("3.2", v.getCanonical());
|
||||
VersionNumber v1 = VersionNumber.asVersion(s1);
|
||||
VersionNumber v2 = VersionNumber.asVersion(s2);
|
||||
|
||||
v = VersionNumber.asVersion("1.7.2$%%^@&snapshot-3.1.1");
|
||||
assertEquals("1.7.2$%%^@&snapshot-3.1.1", v.getCanonical());
|
||||
assertTrue(v1.compareTo(v2) < 0, messageSupplier);
|
||||
assertTrue(v2.compareTo(v1) > 0, messageSupplier);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testComparator() {
|
||||
VersionNumber u, v;
|
||||
|
||||
u = VersionNumber.asVersion("1.7.10forge1614_FTBInfinity");
|
||||
v = VersionNumber.asVersion("1.12.2");
|
||||
assertTrue(u.compareTo(v) < 0);
|
||||
|
||||
u = VersionNumber.asVersion("1.8.0_51");
|
||||
v = VersionNumber.asVersion("1.8.0.51");
|
||||
assertTrue(u.compareTo(v) < 0);
|
||||
|
||||
u = VersionNumber.asVersion("1.8.0_151");
|
||||
v = VersionNumber.asVersion("1.8.0_77");
|
||||
assertTrue(u.compareTo(v) > 0);
|
||||
|
||||
u = VersionNumber.asVersion("1.6.0_22");
|
||||
v = VersionNumber.asVersion("1.8.0_11");
|
||||
assertTrue(u.compareTo(v) < 0);
|
||||
|
||||
u = VersionNumber.asVersion("1.7.0_22");
|
||||
v = VersionNumber.asVersion("1.7.99");
|
||||
assertTrue(u.compareTo(v) < 0);
|
||||
|
||||
u = VersionNumber.asVersion("1.12.2-14.23.5.2760");
|
||||
v = VersionNumber.asVersion("1.12.2-14.23.4.2739");
|
||||
assertTrue(u.compareTo(v) > 0);
|
||||
assertLessThan("1.7.10forge1614_FTBInfinity", "1.12.2");
|
||||
assertLessThan("1.8.0_51", "1.8.0.51");
|
||||
assertLessThan("1.8.0_77", "1.8.0_151");
|
||||
assertLessThan("1.6.0_22", "1.8.0_11");
|
||||
assertLessThan("1.7.0_22", "1.7.99");
|
||||
assertLessThan("1.12.2-14.23.4.2739", "1.12.2-14.23.5.2760");
|
||||
assertLessThan("1.9", "1.99999999999999999999");
|
||||
assertLessThan("1.99999999999999999999", "1.199999999999999999999");
|
||||
assertLessThan("1.99999999999999999999", "2");
|
||||
assertLessThan("1.99999999999999999999", "2.0");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSorting() {
|
||||
List<String> input = Arrays.asList(
|
||||
"1.10",
|
||||
"1.10.2",
|
||||
"1.10.2-All the Mods",
|
||||
"1.10.2-AOE",
|
||||
"1.10.2-AOE-1.1.5",
|
||||
"1.10.2-forge2511-Age_of_Progression",
|
||||
"1.10.2-forge2511-AOE-1.1.2",
|
||||
"1.10.2-forge2511-ATM-E",
|
||||
"1.10.2-forge2511-simple_life_2",
|
||||
"1.10.2-forge2511_bxztest",
|
||||
"1.10.2-forge2511_Farming_Valley",
|
||||
"1.10.2-forge2511中文",
|
||||
"1.10.2-FTB_Beyond",
|
||||
"1.10.2-LiteLoader1.10.2",
|
||||
"1.12.2",
|
||||
"1.12.2_Modern_Skyblock-3.4.2",
|
||||
"1.13.1",
|
||||
final Comparator<String> comparator = VersionNumber.VERSION_COMPARATOR.thenComparing(String::compareTo);
|
||||
final List<String> input = Collections.unmodifiableList(Arrays.asList(
|
||||
"0",
|
||||
"0.10.0",
|
||||
"1.6.4",
|
||||
"1.6.4-Forge9.11.1.1345",
|
||||
"1.7.10",
|
||||
"1.7.10-1614",
|
||||
"1.7.10-1614-test",
|
||||
"1.7.10Agrarian_Skies_2",
|
||||
"1.7.10-F1614-L",
|
||||
"1.7.10-FL1614_04",
|
||||
"1.7.10-Forge10.13.4.1614-1.7.10",
|
||||
"1.7.10-Forge1614",
|
||||
"1.7.10-Forge1614.1",
|
||||
"1.7.10Agrarian_Skies_2",
|
||||
"1.7.10forge1614test",
|
||||
"1.7.10forge1614_ATlauncher",
|
||||
"1.7.10forge1614_FTBInfinity",
|
||||
"1.7.10Forge1614_FTBInfinity-2.6.0",
|
||||
"1.7.10Forge1614_FTBInfinity-3.0.1",
|
||||
"1.7.10-Forge1614.1",
|
||||
"1.7.10forge1614_ATlauncher",
|
||||
"1.7.10forge1614_FTBInfinity",
|
||||
"1.7.10forge1614_FTBInfinity_server",
|
||||
"1.7.10forge1614test",
|
||||
"1.7.10-1614",
|
||||
"1.7.10-1614-test",
|
||||
"1.8",
|
||||
"1.8-forge1577",
|
||||
"1.8.9",
|
||||
"1.8.9-forge1902",
|
||||
"1.9");
|
||||
input.sort(Comparator.comparing(VersionNumber::asVersion));
|
||||
"1.9",
|
||||
"1.10",
|
||||
"1.10.2",
|
||||
"1.10.2-AOE",
|
||||
"1.10.2-AOE-1.1.5",
|
||||
"1.10.2-All the Mods",
|
||||
"1.10.2-FTB_Beyond",
|
||||
"1.10.2-LiteLoader1.10.2",
|
||||
"1.10.2-forge2511-AOE-1.1.2",
|
||||
"1.10.2-forge2511-ATM-E",
|
||||
"1.10.2-forge2511-Age_of_Progression",
|
||||
"1.10.2-forge2511_Farming_Valley",
|
||||
"1.10.2-forge2511_bxztest",
|
||||
"1.10.2-forge2511-simple_life_2",
|
||||
"1.10.2-forge2511中文",
|
||||
"1.12.2",
|
||||
"1.12.2_Modern_Skyblock-3.4.2",
|
||||
"1.13.1",
|
||||
"1.99999999999999999999",
|
||||
"2",
|
||||
"2.0",
|
||||
"2.1"));
|
||||
|
||||
List<String> output = new ArrayList<>(input);
|
||||
output.sort(comparator);
|
||||
assertIterableEquals(input, output);
|
||||
|
||||
Collections.shuffle(output, new Random(0));
|
||||
output.sort(comparator);
|
||||
assertIterableEquals(input, output);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user