forked from plusone/plusone-commons
feat(model): 添加 SemVer 表示语义版本号 (!4 @Gitee)
- feat: 添加 `SemVer` 表示语义版本号 - test: 完善 `SemVer` 的单元测试
This commit is contained in:
@@ -9,6 +9,7 @@
|
||||
"aliyun",
|
||||
"baomidou",
|
||||
"Batis",
|
||||
"buildmetadata",
|
||||
"Consolas",
|
||||
"cspell",
|
||||
"databind",
|
||||
|
||||
@@ -0,0 +1,275 @@
|
||||
/*
|
||||
* Copyright 2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package xyz.zhouxy.plusone.commons.model;
|
||||
|
||||
|
||||
import static xyz.zhouxy.plusone.commons.util.AssertTools.checkArgument;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
import com.google.common.base.Splitter;
|
||||
|
||||
import xyz.zhouxy.plusone.commons.util.StringTools;
|
||||
|
||||
/**
|
||||
* SemVer 语义版本号
|
||||
*
|
||||
* @author ZhouXY108 <luquanlion@outlook.com>
|
||||
* @since 1.1.0
|
||||
*
|
||||
* @see <a href="https://semver.org/">Semantic Versioning 2.0.0</a>
|
||||
*/
|
||||
public class SemVer implements Comparable<SemVer>, Serializable {
|
||||
private static final long serialVersionUID = 458265121025514002L;
|
||||
|
||||
private final String value;
|
||||
|
||||
private final int[] versionNumbers;
|
||||
@Nullable
|
||||
private final String preReleaseVersion;
|
||||
@Nullable
|
||||
private final String buildMetadata;
|
||||
|
||||
private static final String VERSION_NUMBERS = "(?<numbers>(?<major>0|[1-9]\\d*)\\.(?<minor>0|[1-9]\\d*)\\.(?<patch>0|[1-9]\\d*)(\\.(0|[1-9]\\d*)){0,2})";
|
||||
private static final String PRE_RELEASE_VERSION = "(?:-(?<prerelease>(?:0|[1-9]\\d{0,41}|\\d{0,18}[a-zA-Z-][0-9a-zA-Z-]{0,18})(?:\\.(?:0|[1-9]\\d{0,41}|\\d{0,18}[a-zA-Z-][0-9a-zA-Z-]{0,18})){0,18}))?";
|
||||
private static final String BUILD_METADATA = "(?:\\+(?<buildmetadata>[0-9a-zA-Z-]{1,18}(?:\\.[0-9a-zA-Z-]{1,18}){0,18}))?";
|
||||
|
||||
private static final Pattern PATTERN = Pattern.compile(
|
||||
"^" + VERSION_NUMBERS + PRE_RELEASE_VERSION + BUILD_METADATA + "$");
|
||||
|
||||
/**
|
||||
* 创建语义化版本号的值对象
|
||||
*
|
||||
* @param value 字符串值
|
||||
* @param versionNumbers 主版本号、次版本号、修订号
|
||||
* @param preReleaseVersion 先行版本号
|
||||
* @param buildMetadata 版本编译信息
|
||||
*/
|
||||
private SemVer(String value,
|
||||
int[] versionNumbers,
|
||||
@Nullable String preReleaseVersion,
|
||||
@Nullable String buildMetadata) {
|
||||
this.value = value;
|
||||
this.versionNumbers = versionNumbers;
|
||||
this.preReleaseVersion = preReleaseVersion;
|
||||
this.buildMetadata = buildMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建 SemVer 对象
|
||||
*
|
||||
* @param value 语义化版本号
|
||||
* @return SemVer 对象
|
||||
*/
|
||||
public static SemVer of(final String value) {
|
||||
checkArgument(StringTools.isNotBlank(value), "版本号不能为空");
|
||||
final Matcher matcher = PATTERN.matcher(value);
|
||||
checkArgument(matcher.matches(), "版本号格式错误");
|
||||
// 数字版本部分
|
||||
final String versionNumbersPart = matcher.group("numbers");
|
||||
// 先行版本号部分
|
||||
final String preReleaseVersionPart = matcher.group("prerelease");
|
||||
// 版本编译信息部分
|
||||
final String buildMetadataPart = matcher.group("buildmetadata");
|
||||
|
||||
final int[] versionNumbers = Splitter.on('.')
|
||||
.splitToStream(versionNumbersPart)
|
||||
// 必须都是数字
|
||||
.mapToInt(Integer::parseInt)
|
||||
.toArray();
|
||||
return new SemVer(value, versionNumbers, preReleaseVersionPart, buildMetadataPart);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取主版本号
|
||||
*
|
||||
* @return 主版本号
|
||||
*/
|
||||
public int getMajor() {
|
||||
return this.versionNumbers[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取次版本号
|
||||
*
|
||||
* @return 次版本号
|
||||
*/
|
||||
public int getMinor() {
|
||||
return this.versionNumbers[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取修订号
|
||||
*
|
||||
* @return 修订号
|
||||
*/
|
||||
public int getPatch() {
|
||||
return this.versionNumbers[2];
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取先行版本号
|
||||
*
|
||||
* @return 先行版本号
|
||||
*/
|
||||
@Nullable
|
||||
public String getPreReleaseVersion() {
|
||||
return this.preReleaseVersion;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取版本编译信息
|
||||
*
|
||||
* @return 版本编译信息
|
||||
*/
|
||||
@Nullable
|
||||
public String getBuildMetadata() {
|
||||
return buildMetadata;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int compareTo(@SuppressWarnings("null") SemVer that) {
|
||||
if (this == that) {
|
||||
return 0;
|
||||
}
|
||||
int result = compareVersionNumbers(that);
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
return comparePreReleaseVersion(that);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取字符串值
|
||||
*
|
||||
* @return 版本字符串
|
||||
*/
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(value);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@Override
|
||||
public boolean equals(@Nullable Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (!(obj instanceof SemVer))
|
||||
return false;
|
||||
SemVer other = (SemVer) obj;
|
||||
return Objects.equals(value, other.value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 SemVer 的字符串表示。如 {@code v1.2.3-alpha.1+build.1234}
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return 'v' + value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 比较主版本号、次版本号、修订号
|
||||
*/
|
||||
private int compareVersionNumbers(SemVer that) {
|
||||
final int minLength = Integer.min(this.versionNumbers.length, that.versionNumbers.length);
|
||||
|
||||
for (int i = 0; i < minLength; i++) {
|
||||
final int currentVersionNumberOfThis = this.versionNumbers[i];
|
||||
final int currentVersionNumberOfThat = that.versionNumbers[i];
|
||||
if (currentVersionNumberOfThis != currentVersionNumberOfThat) {
|
||||
return currentVersionNumberOfThis - currentVersionNumberOfThat;
|
||||
}
|
||||
}
|
||||
return this.versionNumbers.length - that.versionNumbers.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* 比较先行版本号
|
||||
*/
|
||||
private int comparePreReleaseVersion(SemVer that) {
|
||||
int thisWithoutPreReleaseVersionFlag = bool2Int(this.preReleaseVersion == null);
|
||||
int thatWithoutPreReleaseVersionFlag = bool2Int(that.preReleaseVersion == null);
|
||||
if (isTrue(thisWithoutPreReleaseVersionFlag | thatWithoutPreReleaseVersionFlag)) {
|
||||
return thisWithoutPreReleaseVersionFlag - thatWithoutPreReleaseVersionFlag;
|
||||
}
|
||||
|
||||
Splitter splitter = Splitter.on('.');
|
||||
|
||||
final String[] preReleaseVersionOfThis = splitter
|
||||
.splitToStream(this.preReleaseVersion) // NOSONAR
|
||||
.toArray(String[]::new);
|
||||
final String[] preReleaseVersionOfThat = splitter
|
||||
.splitToStream(that.preReleaseVersion) // NOSONAR
|
||||
.toArray(String[]::new);
|
||||
final int minLength = Integer.min(preReleaseVersionOfThis.length, preReleaseVersionOfThat.length);
|
||||
for (int i = 0; i < minLength; i++) {
|
||||
int r = comparePartOfPreReleaseVersion(preReleaseVersionOfThis[i], preReleaseVersionOfThat[i]);
|
||||
if (r != 0) {
|
||||
return r;
|
||||
}
|
||||
}
|
||||
return preReleaseVersionOfThis.length - preReleaseVersionOfThat.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* 比较先行版本号的组成部分
|
||||
*/
|
||||
private static int comparePartOfPreReleaseVersion(String p1, String p2) {
|
||||
boolean p1IsNumber = isAllDigits(p1);
|
||||
boolean p2IsNumber = isAllDigits(p2);
|
||||
|
||||
if (p1IsNumber) {
|
||||
return p2IsNumber
|
||||
? Integer.parseInt(p1) - Integer.parseInt(p2) // 都是数字
|
||||
: -1; // p1 是数字,p2 是字符串
|
||||
}
|
||||
// 如果 p1 是字符串,p2 是数字,则返回 1(字符串优先于纯数字)
|
||||
return p2IsNumber ? 1 : p1.compareTo(p2);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断字符串是否全为数字
|
||||
*/
|
||||
private static boolean isAllDigits(String str) {
|
||||
for (int i = 0; i < str.length(); i++) {
|
||||
char c = str.charAt(i);
|
||||
if (c < '0' || c > '9') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static int bool2Int(boolean expression) {
|
||||
return expression ? 1 : 0;
|
||||
}
|
||||
|
||||
private static boolean isTrue(int b) {
|
||||
return b != 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,251 @@
|
||||
/*
|
||||
* Copyright 2025 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package xyz.zhouxy.plusone.commons.model;
|
||||
|
||||
import static org.apache.commons.lang3.ObjectUtils.compare;
|
||||
import static org.junit.jupiter.api.Assertions.assertAll;
|
||||
import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
public class SemVerTests {
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {
|
||||
"25.10.17",
|
||||
"25.10.17.11",
|
||||
"25.10.17.11.38",
|
||||
"25.10.17-RC1",
|
||||
"25.10.17.11-RC1",
|
||||
"25.10.17.11.38-RC1",
|
||||
"25.10.17+build.a20251017.1",
|
||||
"25.10.17.11+build.a20251017.1",
|
||||
"25.10.17.11.38+build.a20251017.1",
|
||||
"25.10.17-RC1+build.a20251017.1",
|
||||
"25.10.17.11-RC1+build.a20251017.1",
|
||||
"25.10.17.11.38-RC1+build.a20251017.1",
|
||||
})
|
||||
void test_of_success(String value) {
|
||||
assertDoesNotThrow(() -> SemVer.of(value));
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {
|
||||
"25",
|
||||
"25.10",
|
||||
"x.10.17",
|
||||
"25.x.17",
|
||||
"25.10.x",
|
||||
"25.10.17.11.38.20",
|
||||
"025.10.17",
|
||||
"25.010.17",
|
||||
"25.10.017",
|
||||
})
|
||||
void test_of_wrongValue(String value) {
|
||||
IllegalArgumentException e = assertThrows(IllegalArgumentException.class, () -> SemVer.of(value));
|
||||
assertEquals("版本号格式错误", e.getMessage());
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {
|
||||
"25.1.1",
|
||||
"25.1.1-RC1",
|
||||
"25.1.1+build.a20250101.1",
|
||||
"25.1.1-RC1+build.a20250101.1",
|
||||
})
|
||||
void compareTo_Major(String version_25_x_x) { // NOSONAR sonarqube(java:S117)
|
||||
assertTrue(compare(SemVer.of(version_25_x_x), SemVer.of("24.12.30")) > 0);
|
||||
assertTrue(compare(SemVer.of(version_25_x_x), SemVer.of("24.12.30.1")) > 0);
|
||||
assertTrue(compare(SemVer.of(version_25_x_x), SemVer.of("24.12.30-RC2")) > 0);
|
||||
assertTrue(compare(SemVer.of(version_25_x_x), SemVer.of("24.12.30+build.z20241230.1")) > 0);
|
||||
assertTrue(compare(SemVer.of(version_25_x_x), SemVer.of("24.12.30-RC2+build.z20241230.1")) > 0);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {
|
||||
"25.10.1",
|
||||
"25.10.1-RC1",
|
||||
"25.10.1+build.a20251001.1",
|
||||
"25.10.1-RC1+build.a20251001.1",
|
||||
})
|
||||
void compareTo_Minor(String version_25_10_x) { // NOSONAR sonarqube(java:S117)
|
||||
assertTrue(compare(SemVer.of(version_25_10_x), SemVer.of("25.9.30")) > 0);
|
||||
assertTrue(compare(SemVer.of(version_25_10_x), SemVer.of("25.9.30.1")) > 0);
|
||||
assertTrue(compare(SemVer.of(version_25_10_x), SemVer.of("25.9.30-RC2")) > 0);
|
||||
assertTrue(compare(SemVer.of(version_25_10_x), SemVer.of("25.9.30+build.z20250930.1")) > 0);
|
||||
assertTrue(compare(SemVer.of(version_25_10_x), SemVer.of("25.9.30-RC2+build.z20250930.1")) > 0);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {
|
||||
"25.10.17",
|
||||
"25.10.17-RC1",
|
||||
"25.10.17+build.a20251017.1",
|
||||
"25.10.17-RC1+build.a20251017.1",
|
||||
})
|
||||
void compareTo_Patch(String version_25_10_17) { // NOSONAR sonarqube(java:S117)
|
||||
|
||||
assertTrue(compare(SemVer.of(version_25_10_17), SemVer.of("25.10.16")) > 0);
|
||||
assertTrue(compare(SemVer.of(version_25_10_17), SemVer.of("25.10.16.1")) > 0);
|
||||
assertTrue(compare(SemVer.of(version_25_10_17), SemVer.of("25.10.16-RC2")) > 0);
|
||||
assertTrue(compare(SemVer.of(version_25_10_17), SemVer.of("25.10.16+build.z20251016.2")) > 0);
|
||||
assertTrue(compare(SemVer.of(version_25_10_17), SemVer.of("25.10.16-RC2+build.z20251016.2")) > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
void compareTo_MoreVersionNumber() {
|
||||
|
||||
assertTrue(compare(SemVer.of("25.10.17.1"), SemVer.of("25.10.17")) > 0);
|
||||
assertTrue(compare(SemVer.of("25.10.17.11"), SemVer.of("25.10.17.1")) > 0);
|
||||
assertEquals(0, compare(SemVer.of("25.10.17.11"), SemVer.of("25.10.17.11")));
|
||||
|
||||
assertTrue(compare(SemVer.of("25.10.17.11.1"), SemVer.of("25.10.17.11")) > 0);
|
||||
assertTrue(compare(SemVer.of("25.10.17.11.38"), SemVer.of("25.10.17.11.1")) > 0);
|
||||
assertEquals(0, compare(SemVer.of("25.10.17.11.38"), SemVer.of("25.10.17.11.38")));
|
||||
}
|
||||
|
||||
@Test
|
||||
void compareTo_PreReleaseVersion() {
|
||||
|
||||
// 先行版的优先级低于相关联的标准版本
|
||||
assertTrue(compare(SemVer.of("25.10.17"), SemVer.of("25.10.17-0")) > 0);
|
||||
assertTrue(compare(SemVer.of("25.10.17"), SemVer.of("25.10.17-RC1")) > 0);
|
||||
|
||||
// 只有数字的标识符以数值高低比较
|
||||
assertAll(
|
||||
() -> assertTrue(compare("25.10.17-RC.11", "25.10.17-RC.2") < 0),
|
||||
() -> assertTrue(compare(SemVer.of("25.10.17-RC.11"), SemVer.of("25.10.17-RC.2")) > 0)
|
||||
);
|
||||
|
||||
// 纯数字优先级低于非数字
|
||||
assertAll(
|
||||
() -> assertTrue(compare("25.10.17-999", "25.10.17-A") < 0),
|
||||
() -> assertTrue(compare(SemVer.of("25.10.17-A.A"), SemVer.of("25.10.17-A.99")) > 0)
|
||||
);
|
||||
|
||||
SemVer[] versions = {
|
||||
SemVer.of("25.10.17-a"),
|
||||
SemVer.of("25.10.17-aa"),
|
||||
SemVer.of("25.10.17-A"),
|
||||
SemVer.of("25.10.17-AA"),
|
||||
|
||||
SemVer.of("25.10.17--"),
|
||||
|
||||
SemVer.of("25.10.17-999"),
|
||||
|
||||
SemVer.of("25.10.17-z"),
|
||||
SemVer.of("25.10.17-zz"),
|
||||
SemVer.of("25.10.17-Z"),
|
||||
SemVer.of("25.10.17-ZZ"),
|
||||
};
|
||||
|
||||
assertArrayEquals(
|
||||
new SemVer[] {
|
||||
// 纯数字优先级低于非数字
|
||||
SemVer.of("25.10.17-999"),
|
||||
|
||||
// 有字母或连接号时逐字符以 ASCII 的排序比较
|
||||
SemVer.of("25.10.17--"),
|
||||
|
||||
SemVer.of("25.10.17-A"),
|
||||
SemVer.of("25.10.17-AA"),
|
||||
SemVer.of("25.10.17-Z"),
|
||||
SemVer.of("25.10.17-ZZ"),
|
||||
SemVer.of("25.10.17-a"),
|
||||
SemVer.of("25.10.17-aa"),
|
||||
SemVer.of("25.10.17-z"),
|
||||
SemVer.of("25.10.17-zz"),
|
||||
},
|
||||
Arrays.stream(versions)
|
||||
.sorted()
|
||||
.toArray(SemVer[]::new));
|
||||
|
||||
// 若开头的标识符都相同时,栏位比较多的先行版本号优先级比较高
|
||||
assertAll(
|
||||
() -> assertTrue(compare(SemVer.of("25.10.17-ABC.DEF.1"), SemVer.of("25.10.17-ABC.DEF")) > 0),
|
||||
() -> assertTrue(compare(SemVer.of("25.10.17-ABC.DEF.G"), SemVer.of("25.10.17-ABC.DEF")) > 0));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void compareTo_ignoreBuildMeta() {
|
||||
|
||||
assertNotEquals(SemVer.of("25.10.17"), SemVer.of("25.10.17+build.20251017.01"));
|
||||
assertTrue(compare(SemVer.of("25.10.17"), SemVer.of("25.10.17+build.20251017.01")) == 0); // NOSONAR sonarqube(java:S5785)
|
||||
|
||||
assertNotEquals(SemVer.of("25.10.17+build.20251017.02"), SemVer.of("25.10.17+build.20251017.01"));
|
||||
assertTrue(compare(SemVer.of("25.10.17+build.20251017.02"), SemVer.of("25.10.17+build.20251017.01")) == 0); // NOSONAR sonarqube(java:S5785)
|
||||
|
||||
assertNotEquals(SemVer.of("25.10.17-ABC.DEF"), SemVer.of("25.10.17-ABC.DEF+build.20251017.01"));
|
||||
assertTrue(compare(SemVer.of("25.10.17-ABC.DEF"), SemVer.of("25.10.17-ABC.DEF+build.20251017.01")) == 0); // NOSONAR sonarqube(java:S5785)
|
||||
|
||||
assertNotEquals(SemVer.of("25.10.17-ABC.DEF+build.20251017.02"), SemVer.of("25.10.17-ABC.DEF+build.20251017.01"));
|
||||
assertTrue(compare(SemVer.of("25.10.17-ABC.DEF+build.20251017.02"), SemVer.of("25.10.17-ABC.DEF+build.20251017.01")) == 0); // NOSONAR sonarqube(java:S5785)
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@ValueSource(strings = {
|
||||
"25.10.17",
|
||||
"25.10.17-ABC.DEF.1",
|
||||
"25.10.17+build.20251017.a2",
|
||||
"25.10.17-ABC.DEF.1+build.20251017.a2",
|
||||
})
|
||||
void test_equals(String value) {
|
||||
final SemVer v1 = SemVer.of(value);
|
||||
final SemVer v2 = SemVer.of(value);
|
||||
|
||||
assertTrue(v1.compareTo(v1) == 0); // NOSONAR sonarqube(java:S5785)
|
||||
assertTrue(v1.compareTo(v2) == 0); // NOSONAR sonarqube(java:S5785)
|
||||
|
||||
assertEquals(v1, v1);
|
||||
assertEquals(v1.hashCode(), v2.hashCode());
|
||||
assertEquals(v1, v2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void test_equals_null() {
|
||||
assertFalse(SemVer.of("25.10.17").equals(null)); // NOSONAR sonarqube(java:S5785)
|
||||
}
|
||||
|
||||
@Test
|
||||
void details() {
|
||||
final String s = "25.10.17-ABC.DEF.1+build.20251017.02";
|
||||
final SemVer v = SemVer.of(s);
|
||||
assertEquals(25, v.getMajor());
|
||||
assertEquals(10, v.getMinor());
|
||||
assertEquals(17, v.getPatch());
|
||||
|
||||
assertEquals("ABC.DEF.1", v.getPreReleaseVersion());
|
||||
assertEquals(s, v.getValue());
|
||||
assertEquals("v" + s, v.toString());
|
||||
|
||||
assertEquals("build.20251017.02", v.getBuildMetadata());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user