Platform: build numbers: cleanup + additional tests for update checker

This commit is contained in:
Anton Makeev
2016-04-07 11:43:50 +02:00
parent 8ef1d93cc4
commit 4c428b5dc4
9 changed files with 148 additions and 55 deletions
@@ -112,7 +112,7 @@ class ResourceVersions implements PersistentStateComponent<ResourceVersions.Stat
ApplicationInfo appInfo = ApplicationInfo.getInstance();
BuildNumber build = appInfo.getBuild();
if (!build.isSnapshot()) return build.asStringWithAllDetails();
if (!build.isSnapshot()) return build.asString();
// There is no good way to decide whether to update resources or not when switching to a different development build.
return build.getProductCode() + "-" + build.getBaselineVersion() + "-" + appInfo.getBuildDate().getTimeInMillis();
@@ -177,7 +177,7 @@ public class ITNProxy {
params.put("app.compilation.timestamp", IdeaLogger.getOurCompilationTimestamp());
BuildNumber build = appInfo.getBuild();
String buildNumberWithAllDetails = build.asStringWithAllDetails();
String buildNumberWithAllDetails = build.asString();
params.put("app.product.code", build.getProductCode());
if (StringUtil.startsWith(buildNumberWithAllDetails, build.getProductCode() + "-")) {
buildNumberWithAllDetails = buildNumberWithAllDetails.substring(build.getProductCode().length() + 1);
@@ -157,7 +157,7 @@ public class IdeaLogger extends Log4jBasedLogger {
@Override
public String getInfo() {
final ApplicationInfoEx info = ApplicationInfoImpl.getShadowInstance();
return info.getFullApplicationName() + " " + "Build #" + info.getBuild().asStringWithAllDetails();
return info.getFullApplicationName() + " " + "Build #" + info.getBuild().asString();
}
};
}
@@ -415,7 +415,7 @@ public class StartupUtil {
ApplicationInfo appInfo = ApplicationInfoImpl.getShadowInstance();
ApplicationNamesInfo namesInfo = ApplicationNamesInfo.getInstance();
String buildDate = new SimpleDateFormat("dd MMM yyyy HH:ss", Locale.US).format(appInfo.getBuildDate().getTime());
log.info("IDE: " + namesInfo.getFullProductName() + " (build #" + appInfo.getBuild().asStringWithAllDetails() + ", " + buildDate + ")");
log.info("IDE: " + namesInfo.getFullProductName() + " (build #" + appInfo.getBuild().asString() + ", " + buildDate + ")");
log.info("OS: " + SystemInfoRt.OS_NAME + " (" + SystemInfoRt.OS_VERSION + ", " + SystemInfo.OS_ARCH + ")");
log.info("JRE: " + System.getProperty("java.runtime.version", "-") + " (" + System.getProperty("java.vendor", "-") + ")");
log.info("JVM: " + System.getProperty("java.vm.version", "-") + " (" + System.getProperty("java.vm.name", "-") + ")");
@@ -426,7 +426,7 @@ public class FlatWelcomeFrame extends JFrame implements IdeFrame, AccessibleCont
appName.setHorizontalAlignment(SwingConstants.CENTER);
String appVersion = "Version ";
if (app.getBuild().getFormat() == BuildNumber.Format.YEAR_BASED) {
if (app.getBuild().isYearBased()) {
appVersion += app.isEAP() ? (app.getBuild().asStringWithoutProductCode() + " EAP") : app.getFullVersion();
}
else {
@@ -75,6 +75,14 @@ public class PluginManagerTest {
assertCompatible("145.SNAPSHOT", null, "145.*");
}
@Test
public void compatibilityYearBased() throws Exception {
assertCompatible("2016.2", "2016.1", "2016.3");
assertCompatible("2016.2", "145.*", "2016.3");
assertCompatible("2016.2", null, "2016.10");
assertIncompatible("2016.2", null, "2015.10");
}
@Test
public void compatibilityYearBasedStar() throws Exception {
assertCompatible("2016.2", "2016.1.*", null);
@@ -145,6 +145,77 @@ class UpdateStrategyTest {
assertEquals("145.597", result.newBuild?.number.toString())
}
@Test fun `variable-length build numbers are supported`() {
var result = check("IU-143.2332", ChannelStatus.RELEASE, """
<channel id="IDEA_Release" status="release" licensing="release">
<build number="143.2332.10" version="15.0.5"/>
</channel>""")
assertEquals("143.2332.10", result.newBuild?.number.toString())
result = check("IU-143.2332.10", ChannelStatus.RELEASE, """
<channel id="IDEA_Release" status="release" licensing="release">
<build number="143.2333" version="15.0.5"/>
</channel>""")
assertEquals("143.2333", result.newBuild?.number.toString())
result = check("IU-143.2332.9", ChannelStatus.RELEASE, """
<channel id="IDEA_Release" status="release" licensing="release">
<build number="143.2332.10" version="15.0.5"/>
</channel>""")
assertEquals("143.2332.10", result.newBuild?.number.toString())
result = check("IU-143.2332.11", ChannelStatus.RELEASE, """
<channel id="IDEA_Release" status="release" licensing="release">
<build number="143.2332.10" version="15.0.5"/>
</channel>""")
assertNull(result.newBuild)
}
@Test fun `year-based build numbers are supported`() {
var result = check("IU-145.100", ChannelStatus.RELEASE, """
<channel id="IDEA_Release" status="release" licensing="release">
<build number="2016.1.10.10" version="15.0.5"/>
</channel>""")
assertEquals("2016.1.10.10", result.newBuild?.number.toString())
result = check("IU-2016.1.10.10", ChannelStatus.RELEASE, """
<channel id="IDEA_Release" status="release" licensing="release">
<build number="2017.1.1.1" version="15.0.5"/>
</channel>""")
assertEquals("2017.1.1.1", result.newBuild?.number.toString())
result = check("IU-2016.1.10.10", ChannelStatus.RELEASE, """
<channel id="IDEA_Release" status="release" licensing="release">
<build number="2016.2.10.10" version="15.0.5"/>
</channel>""")
assertEquals("2016.2.10.10", result.newBuild?.number.toString())
result = check("IU-2016.1.10.10", ChannelStatus.RELEASE, """
<channel id="IDEA_Release" status="release" licensing="release">
<build number="2016.1.11.10" version="15.0.5"/>
</channel>""")
assertEquals("2016.1.11.10", result.newBuild?.number.toString())
result = check("IU-2016.1.10.10", ChannelStatus.RELEASE, """
<channel id="IDEA_Release" status="release" licensing="release">
<build number="2016.1.10.11" version="15.0.5"/>
</channel>""")
assertEquals("2016.1.10.11", result.newBuild?.number.toString())
result = check("IU-2016.1.10.10", ChannelStatus.RELEASE, """
<channel id="IDEA_Release" status="release" licensing="release">
<build number="2016.1.10.9" version="15.0.5"/>
</channel>""")
assertNull(result.newBuild)
// e.g. android-studio format
result = check("IU-2016.1.10.10.20161111", ChannelStatus.RELEASE, """
<channel id="IDEA_Release" status="release" licensing="release">
<build number="IU-2016.1.10.10.20161112" version="15.0.5"/>
</channel>""")
assertEquals("IU-2016.1.10.10.20161112", result.newBuild?.number.toString())
}
private fun check(currentBuild: String,
selectedChannel: ChannelStatus,
testData: String,
@@ -18,6 +18,7 @@ package com.intellij.openapi.util;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import gnu.trove.TIntArrayList;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -30,8 +31,6 @@ import java.util.List;
* @author max
*/
public class BuildNumber implements Comparable<BuildNumber> {
public enum Format { HISTORIC, BRANCH_BASED, YEAR_BASED }
private static final String BUILD_NUMBER = "__BUILD_NUMBER__";
private static final String STAR = "*";
private static final String SNAPSHOT = "SNAPSHOT";
@@ -44,16 +43,14 @@ public class BuildNumber implements Comparable<BuildNumber> {
}
@NotNull private final String myProductCode;
@NotNull private final Format myFormat;
private final int[] myComponents;
public BuildNumber(@NotNull String productCode, int baselineVersion, int buildNumber) {
this(productCode, Format.BRANCH_BASED, baselineVersion, buildNumber);
this(productCode, new int[]{baselineVersion, buildNumber});
}
BuildNumber(@NotNull String productCode, @NotNull Format format, int... components) {
public BuildNumber(@NotNull String productCode, int... components) {
myProductCode = productCode;
myFormat = format;
myComponents = components;
}
@@ -61,10 +58,6 @@ public class BuildNumber implements Comparable<BuildNumber> {
return asString(true, true);
}
public String asStringWithAllDetails() {
return asString(true, true);
}
public String asStringWithoutProductCode() {
return asString(false, true);
}
@@ -103,7 +96,7 @@ public class BuildNumber implements Comparable<BuildNumber> {
if (BUILD_NUMBER.equals(version) || SNAPSHOT.equals(version)) {
final String productCode = name != null ? name : "";
return new BuildNumber(productCode, Holder.CURRENT_VERSION.getFormat(), Holder.CURRENT_VERSION.myComponents);
return new BuildNumber(productCode, Holder.CURRENT_VERSION.myComponents);
}
String code = version;
@@ -131,14 +124,22 @@ public class BuildNumber implements Comparable<BuildNumber> {
throw new RuntimeException("Invalid version number: " + version + "; plugin name: " + name);
}
if (baselineVersion >= 2016) {
if (isYearBased(baselineVersion)) {
List<String> stringComponents = StringUtil.split(code, ".");
int[] intComponents = new int[stringComponents.size()];
for (int i = 0; i < stringComponents.size(); i++) {
intComponents[i] = parseBuildNumber(version, stringComponents.get(i), name);
TIntArrayList intComponentsList = new TIntArrayList();
for (String stringComponent : stringComponents) {
int comp = parseBuildNumber(version, stringComponent, name);
intComponentsList.add(comp);
if (comp == SNAPSHOT_VALUE) break;
}
return new BuildNumber(productCode, Format.YEAR_BASED, intComponents);
int[] intComponents = intComponentsList.toNativeArray();
if (intComponents[1] != SNAPSHOT_VALUE) {
intComponents[1] = normalizedYearRevision(intComponents);
}
return new BuildNumber(productCode, intComponents);
}
else {
code = code.substring(baselineVersionSeparator + 1);
@@ -153,10 +154,10 @@ public class BuildNumber implements Comparable<BuildNumber> {
buildNumber = parseBuildNumber(version, code, name);
if (attemptInfo != null) {
return new BuildNumber(productCode, Format.BRANCH_BASED, baselineVersion, buildNumber, attemptInfo);
return new BuildNumber(productCode, baselineVersion, buildNumber, attemptInfo);
}
else {
return new BuildNumber(productCode, Format.BRANCH_BASED, baselineVersion, buildNumber);
return new BuildNumber(productCode, baselineVersion, buildNumber);
}
}
}
@@ -165,15 +166,15 @@ public class BuildNumber implements Comparable<BuildNumber> {
if (buildNumber <= 2000) {
// it's probably a baseline, not a build number
return new BuildNumber(productCode, Format.BRANCH_BASED, buildNumber, 0);
return new BuildNumber(productCode, buildNumber, 0);
}
if (buildNumber >= 2016 && buildNumber <= 2999) {
return new BuildNumber(productCode, Format.YEAR_BASED, buildNumber, 0);
if (isYearBased(buildNumber)) {
return new BuildNumber(productCode, buildNumber, 0);
}
baselineVersion = getBaseLineForHistoricBuilds(buildNumber);
return new BuildNumber(productCode, Format.HISTORIC, baselineVersion, buildNumber);
return new BuildNumber(productCode, baselineVersion, buildNumber);
}
}
@@ -238,21 +239,28 @@ public class BuildNumber implements Comparable<BuildNumber> {
}
public int getBaselineVersion() {
return myFormat == Format.YEAR_BASED ? (myComponents[0] * 10 + myComponents[1]) : myComponents[0];
return isYearBased() ? (myComponents[0] * 10 + normalizedYearRevision(myComponents)) : myComponents[0];
}
private static int normalizedYearRevision(int[] components) {
return Math.min(components[1], 9);
}
@Deprecated
public int getBuildNumber() {
return myFormat == Format.YEAR_BASED ? -1 : myComponents[1];
return isYearBased() ? -1 : myComponents[1];
}
public int[] getComponents() {
return myComponents;
}
@NotNull
public Format getFormat() {
return myFormat;
public boolean isYearBased() {
return isYearBased(myComponents[0]);
}
private static boolean isYearBased(int buildNumber) {
return buildNumber >= 2016 && buildNumber <= 2999;
}
@Override
@@ -262,7 +270,6 @@ public class BuildNumber implements Comparable<BuildNumber> {
BuildNumber that = (BuildNumber)o;
if (myFormat != that.myFormat) return false;
if (!myProductCode.equals(that.myProductCode)) return false;
if (!Arrays.equals(myComponents, that.myComponents)) return false;
@@ -273,7 +280,6 @@ public class BuildNumber implements Comparable<BuildNumber> {
public int hashCode() {
int result = myProductCode.hashCode();
result = 31 * result + Arrays.hashCode(myComponents);
result = 31 * result + myFormat.hashCode();
return result;
}
@@ -28,40 +28,48 @@ public class BuildNumberTest {
@Test
public void historicBuild() {
assertEquals(new BuildNumber("", BuildNumber.Format.HISTORIC, 75, 7512), BuildNumber.fromString("7512"));
assertEquals(new BuildNumber("", 75, 7512), BuildNumber.fromString("7512"));
assertEquals("75.7512", BuildNumber.fromString("7512").asString());
}
@Test
public void branchBasedBuild() throws Exception {
assertParsed(BuildNumber.fromString("145"), 145, 0, BuildNumber.Format.BRANCH_BASED, "145.0");
assertParsed(BuildNumber.fromString("145.1"), 145, 1, BuildNumber.Format.BRANCH_BASED, "145.1");
assertParsed(BuildNumber.fromString("145.1.2"), 145, 1, BuildNumber.Format.BRANCH_BASED, "145.1.2");
assertParsed(BuildNumber.fromString("IU-145.1.2"), 145, 1, BuildNumber.Format.BRANCH_BASED, "IU-145.1.2");
assertParsed(BuildNumber.fromString("IU-145.SNAPSHOT"), 145, BuildNumber.SNAPSHOT_VALUE, BuildNumber.Format.BRANCH_BASED, "IU-145.SNAPSHOT");
assertParsed(BuildNumber.fromString("IU-145.1.SNAPSHOT"), 145, 1, BuildNumber.Format.BRANCH_BASED, "IU-145.1.SNAPSHOT");
assertParsed(BuildNumber.fromString("145"), 145, 0, false, "145.0");
assertParsed(BuildNumber.fromString("145.1"), 145, 1, false, "145.1");
assertParsed(BuildNumber.fromString("145.1.2"), 145, 1, false, "145.1.2");
assertParsed(BuildNumber.fromString("IU-145.1.2"), 145, 1, false, "IU-145.1.2");
assertParsed(BuildNumber.fromString("IU-145.SNAPSHOT"), 145, BuildNumber.SNAPSHOT_VALUE, false, "IU-145.SNAPSHOT");
assertParsed(BuildNumber.fromString("IU-145.1.SNAPSHOT"), 145, 1, false, "IU-145.1.SNAPSHOT");
}
@Test
public void yearBasedBuild() throws Exception {
assertParsed(BuildNumber.fromString("2016"), 20160, -1, BuildNumber.Format.YEAR_BASED, "2016.0");
assertParsed(BuildNumber.fromString("2016.1"), 20161, -1, BuildNumber.Format.YEAR_BASED, "2016.1");
assertParsed(BuildNumber.fromString("2016.1.2"), 20161, -1, BuildNumber.Format.YEAR_BASED, "2016.1.2");
assertParsed(BuildNumber.fromString("IU-2016.1.2"), 20161, -1, BuildNumber.Format.YEAR_BASED, "IU-2016.1.2");
assertParsed(BuildNumber.fromString("2016.1.2.3"), 20161, -1, BuildNumber.Format.YEAR_BASED, "2016.1.2.3");
assertParsed(BuildNumber.fromString("IU-2016.1.2.3"), 20161, -1, BuildNumber.Format.YEAR_BASED, "IU-2016.1.2.3");
assertParsed(BuildNumber.fromString("2016.1.2.3.4"), 20161, -1, BuildNumber.Format.YEAR_BASED, "2016.1.2.3.4");
assertParsed(BuildNumber.fromString("IU-2016.1.2.3.4"), 20161, -1, BuildNumber.Format.YEAR_BASED, "IU-2016.1.2.3.4");
assertParsed(BuildNumber.fromString("2016"), 20160, -1, true, "2016.0");
assertParsed(BuildNumber.fromString("2016.1"), 20161, -1, true, "2016.1");
assertParsed(BuildNumber.fromString("2016.1.2"), 20161, -1, true, "2016.1.2");
assertParsed(BuildNumber.fromString("IU-2016.1.2"), 20161, -1, true, "IU-2016.1.2");
assertParsed(BuildNumber.fromString("2016.1.2.3"), 20161, -1, true, "2016.1.2.3");
assertParsed(BuildNumber.fromString("IU-2016.1.2.3"), 20161, -1, true, "IU-2016.1.2.3");
assertParsed(BuildNumber.fromString("2016.1.2.3.4"), 20161, -1, true, "2016.1.2.3.4");
assertParsed(BuildNumber.fromString("IU-2016.1.2.3.4"), 20161, -1, true, "IU-2016.1.2.3.4");
assertParsed(BuildNumber.fromString("IU-2016.1.SNAPSHOT"), 20161, -1, BuildNumber.Format.YEAR_BASED, "IU-2016.1.SNAPSHOT");
assertParsed(BuildNumber.fromString("IU-2016.1.SNAPSHOT.1"), 20161, -1, BuildNumber.Format.YEAR_BASED, "IU-2016.1.SNAPSHOT.1");
assertParsed(BuildNumber.fromString("IU-2016.1.SNAPSHOT"), 20161, -1, true, "IU-2016.1.SNAPSHOT");
assertParsed(BuildNumber.fromString("IU-2016.1.SNAPSHOT.1"), 20161, -1, true, "IU-2016.1.SNAPSHOT");
assertParsed(BuildNumber.fromString("IU-2016.*"), 20169, -1, true, "IU-2016.SNAPSHOT");
assertParsed(BuildNumber.fromString("IU-2016.SNAPSHOT"), 20169, -1, true, "IU-2016.SNAPSHOT");
assertParsed(BuildNumber.fromString("IU-2016.9"), 20169, -1, true, "IU-2016.9");
assertParsed(BuildNumber.fromString("IU-2016.10"), 20169, -1, true, "IU-2016.9");
assertParsed(BuildNumber.fromString("IU-2016.100"), 20169, -1, true, "IU-2016.9");
assertParsed(BuildNumber.fromString("IU-2016.1000.1000.1000"), 20169, -1, true, "IU-2016.9.1000.1000");
}
private static void assertParsed(BuildNumber n, int expectedBaseline, int expectedBuildNumber, BuildNumber.Format based, String asString) {
private static void assertParsed(BuildNumber n, int expectedBaseline, int expectedBuildNumber, boolean yearBased, String asString) {
assertEquals(expectedBaseline, n.getBaselineVersion());
assertEquals(expectedBuildNumber, n.getBuildNumber());
assertEquals(asString, n.asString());
assertEquals(based, n.getFormat());
assertEquals(yearBased, n.isYearBased());
}
@Test
@@ -164,8 +172,8 @@ public class BuildNumberTest {
@Test
public void fallbackVersion() throws Exception {
assertParsed(BuildNumber.fallback(), 29991, -1, BuildNumber.Format.YEAR_BASED, "2999.1.SNAPSHOT");
assertEquals(BuildNumber.Format.YEAR_BASED, BuildNumber.fallback().getFormat());
assertParsed(BuildNumber.fallback(), 29991, -1, true, "2999.1.SNAPSHOT");
assertTrue(BuildNumber.fallback().isYearBased());
assertTrue(BuildNumber.fallback().isSnapshot());
assertTrue(BuildNumber.fallback().compareTo(BuildNumber.fromString("7512")) > 0);