diff --git a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java index eb9c3eb4984b..7a72f80f1e00 100644 --- a/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java +++ b/platform/smRunner/src/com/intellij/execution/testframework/sm/runner/SMTestProxy.java @@ -386,8 +386,10 @@ public class SMTestProxy extends AbstractTestProxy { public String getDurationString(TestConsoleProperties consoleProperties) { switch (getMagnitudeInfo()) { case PASSED_INDEX: - case RUNNING_INDEX: return !isSubjectToHide(consoleProperties) ? getDurationString() : null; + case RUNNING_INDEX: + // pad duration with zeros, like "1m 02 s 003 ms" to avoid annoying flickering + return !isSubjectToHide(consoleProperties) ? getDurationPaddedString() : null; case COMPLETE_INDEX: case FAILED_INDEX: case ERROR_INDEX: @@ -408,6 +410,10 @@ public class SMTestProxy extends AbstractTestProxy { final Long duration = getDuration(); return duration != null ? StringUtil.formatDuration(duration.longValue(), "\u2009") : null; } + private String getDurationPaddedString() { + final Long duration = getDuration(); + return duration != null ? StringUtil.formatDurationPadded(duration.longValue(), "\u2009") : null; + } @Override public boolean shouldSkipRootNodeForExport() { diff --git a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java index 4de60ba37b4c..02cbceff490d 100644 --- a/platform/util/src/com/intellij/openapi/util/text/StringUtil.java +++ b/platform/util/src/com/intellij/openapi/util/text/StringUtil.java @@ -1591,8 +1591,8 @@ public class StringUtil extends StringUtilRt { return formatDuration(duration, " "); } - private static final String[] TIME_UNITS = {"ms", "s", "m", "h", "d", "mo", "yr", "c", "ml", "ep"}; - private static final long[] TIME_MULTIPLIERS = {1, 1000, 60, 60, 24, 30, 12, 100, 10, 10000}; + private static final String[] TIME_UNITS = {"ms", "s", "m", "h", "d"}; + private static final long[] TIME_MULTIPLIERS = {1, 1000, 60, 60, 24}; /** Formats given duration as a sum of time units (example: {@code formatDuration(123456, "") = "2m 3s 456ms"}). */ @NotNull @@ -1647,6 +1647,36 @@ public class StringUtil extends StringUtilRt { return result.toString(); } + private static final String[] PADDED_FORMATS = {"%03d", "%02d", "%02d", "%02d", "%d"}; + /** + * Formats 234523598 like "2 d 03 h 11 min 04 sec 004 ms" padded accordingly with zeros except the most significant unit, e.g. "days" here. + */ + @NotNull + @Contract(pure = true) + public static String formatDurationPadded(long millis, @NotNull String unitSeparator) { + StringBuilder result = new StringBuilder(); + + long millisIn = 1; + int i; + for (i=1; i < TIME_MULTIPLIERS.length; i++) { + long multiplier = TIME_MULTIPLIERS[i]; + millisIn *= multiplier; + if (millis < millisIn) { + break; + } + } + long d = millis; + for (i-=1; i >= 0; i--) { + long multiplier = i==TIME_MULTIPLIERS.length-1 ? 1 : TIME_MULTIPLIERS[i+1]; + millisIn /= multiplier; + long value = d / millisIn; + d = d % millisIn; + String format = result.length() == 0 ? "%d" : PADDED_FORMATS[i]; // do not pad the most significant unit + if (result.length() != 0) result.append(" "); + result.append(String.format(format, value)).append(unitSeparator).append(TIME_UNITS[i]); + } + return result.toString(); + } /** * Formats given duration as a sum of time units with at most two units * (example: {@code formatDuration(123456, "") = "2m 3s"}). diff --git a/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java b/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java index 14c191cdf18c..289c69db6b72 100644 --- a/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java +++ b/platform/util/testSrc/com/intellij/util/text/StringUtilTest.java @@ -22,6 +22,7 @@ import java.nio.CharBuffer; import java.util.Arrays; import java.util.Collections; import java.util.List; +import java.util.concurrent.TimeUnit; import static java.util.Collections.singletonList; import static org.junit.Assert.*; @@ -564,7 +565,7 @@ public class StringUtilTest { assertEquals("0 ms", StringUtil.formatDuration(0)); assertEquals("1 ms", StringUtil.formatDuration(1)); assertEquals("24 d 20 h 31 m 23 s 647 ms", StringUtil.formatDuration(Integer.MAX_VALUE)); - assertEquals("29 ep 6533 ml 3 c 8 yr 9 mo 17 d 7 h 12 m 55 s 807 ms", StringUtil.formatDuration(Long.MAX_VALUE)); + assertEquals("82 d 17 h 24 m 43 s 647 ms", StringUtil.formatDuration(Integer.MAX_VALUE+5000000000L)); assertEquals("1 m 0 s 100 ms", StringUtil.formatDuration(60100)); @@ -576,7 +577,7 @@ public class StringUtilTest { assertEquals("1 d 10 h 17 m 36 s 789 ms", StringUtil.formatDuration(123456789)); assertEquals("14 d 6 h 56 m 7 s 890 ms", StringUtil.formatDuration(1234567890)); - assertEquals("1 yr 1 mo 1 d 1 h 1 m 1 s 1 ms", StringUtil.formatDuration(33786061001L)); + assertEquals("39 d 2 h 30 m 6 s 101 ms", StringUtil.formatDuration(3378606101L)); } @Test @@ -588,7 +589,18 @@ public class StringUtilTest { assertEquals("1 h 1 m", StringUtil.formatDurationApproximate(3659009)); assertEquals("2 h", StringUtil.formatDurationApproximate(7199000)); assertEquals("1 d", StringUtil.formatDurationApproximate((23 * 60 * 60 + 59 * 60 + 59) * 1000L)); - assertEquals("1 yr 1 mo", StringUtil.formatDurationApproximate(33786061001L)); + assertEquals("391 d 1 h", StringUtil.formatDurationApproximate(33786061001L)); + } + + @Test + public void testFormatDurationPadded() { + assertEquals("0 ms", StringUtil.formatDurationPadded(0, " ")); + assertEquals("1 s 000 ms", StringUtil.formatDurationPadded(1000, " ")); + assertEquals("1 s 001 ms", StringUtil.formatDurationPadded(1001, " ")); + assertEquals("2 m 00 s 000 ms", StringUtil.formatDurationPadded(TimeUnit.MINUTES.toMillis(2), " ")); + assertEquals("2 h 00 m 00 s 000 ms", StringUtil.formatDurationPadded(TimeUnit.HOURS.toMillis(2), " ")); + assertEquals("2 d 00 h 00 m 00 s 000 ms", StringUtil.formatDurationPadded(TimeUnit.DAYS.toMillis(2), " ")); + assertEquals("1434852 d 16 h 13 m 50 s 987 ms", StringUtil.formatDurationPadded(123971271230987L, " ")); } @Test