Fix issue 1958. Make sure duration and size values are always separated from their unit by a single space. For example, the value 5 seconds should be displayed as "5 s" and not "5s".
| | |
| | | // Encode the size value using the base unit. |
| | | StringBuilder builder = new StringBuilder(); |
| | | builder.append(value); |
| | | builder.append(' '); |
| | | builder.append(baseUnit.toString()); |
| | | return builder.toString(); |
| | | } |
| | |
| | | |
| | | /** |
| | | * Parse the provided duration string and return its equivalent |
| | | * duration in milli-seconds. The duration string must specify the |
| | | * duration in milliseconds. The duration string must specify the |
| | | * unit e.g. "10s". This method will parse duration string |
| | | * representations produced from the {@link #toString(long)} method. |
| | | * Therefore, a duration can comprise of multiple duration |
| | |
| | | * |
| | | * @param s |
| | | * The duration string to be parsed. |
| | | * @return Returns the parsed duration in milli-seconds. |
| | | * @return Returns the parsed duration in milliseconds. |
| | | * @throws NumberFormatException |
| | | * If the provided duration string could not be parsed. |
| | | * @see #toString(long) |
| | |
| | | |
| | | /** |
| | | * Parse the provided duration string and return its equivalent |
| | | * duration in milli-seconds. This method will parse duration string |
| | | * duration in milliseconds. This method will parse duration string |
| | | * representations produced from the {@link #toString(long)} method. |
| | | * Therefore, a duration can comprise of multiple duration |
| | | * specifiers, for example <code>1d15m25s</code>. |
| | |
| | | * The default unit to use if there is no unit specified in |
| | | * the duration string, or <code>null</code> if the |
| | | * string must always contain a unit. |
| | | * @return Returns the parsed duration in milli-seconds. |
| | | * @return Returns the parsed duration in milliseconds. |
| | | * @throws NumberFormatException |
| | | * If the provided duration string could not be parsed. |
| | | * @see #toString(long) |
| | |
| | | throw new NumberFormatException("Empty duration value \"" + s + "\""); |
| | | } |
| | | |
| | | Pattern p1 = Pattern.compile("^((\\d+)w)?" + "((\\d+)d)?" |
| | | + "((\\d+)h)?" + "((\\d+)m)?" + "((\\d+)s)?" + "((\\d+)ms)?$", |
| | | Pattern.CASE_INSENSITIVE); |
| | | Pattern p1 = Pattern.compile("^\\s*((\\d+)\\s*w)?" + "\\s*((\\d+)\\s*d)?" |
| | | + "\\s*((\\d+)\\s*h)?" + "\\s*((\\d+)\\s*m)?" + "\\s*((\\d+)\\s*s)?" |
| | | + "\\s*((\\d+)\\s*ms)?\\s*$", Pattern.CASE_INSENSITIVE); |
| | | Matcher m1 = p1.matcher(ns); |
| | | if (m1.matches()) { |
| | | // Value must be of the form produced by toString(long). |
| | |
| | | return duration; |
| | | } else { |
| | | // Value must be a floating point number followed by a unit. |
| | | Pattern p2 = Pattern.compile("^(\\d+(\\.\\d+)?)\\s*(\\w+)?$"); |
| | | Pattern p2 = Pattern.compile("^\\s*(\\d+(\\.\\d+)?)\\s*(\\w+)?\\s*$"); |
| | | Matcher m2 = p2.matcher(ns); |
| | | |
| | | if (!m2.matches()) { |
| | |
| | | * string representation can be parsed using the |
| | | * {@link #parseValue(String)} method. The string representation is |
| | | * comprised of one or more of the number of weeks, days, hours, |
| | | * minutes, seconds, and milli-seconds. Here are some examples: |
| | | * minutes, seconds, and milliseconds. Here are some examples: |
| | | * |
| | | * <pre> |
| | | * toString(0) // 0ms |
| | | * toString(999) // 999ms |
| | | * toString(1000) // 1s |
| | | * toString(1500) // 1s500ms |
| | | * toString(3650000) // 1h50s |
| | | * toString(3700000) // 1h1m40s |
| | | * toString(0) // 0 ms |
| | | * toString(999) // 999 ms |
| | | * toString(1000) // 1 s |
| | | * toString(1500) // 1 s 500 ms |
| | | * toString(3650000) // 1 h 50 s |
| | | * toString(3700000) // 1 h 1 m 40 s |
| | | * </pre> |
| | | * |
| | | * @param duration |
| | | * The duration in milli-seconds. |
| | | * The duration in milliseconds. |
| | | * @return Returns a string representation of the provided duration. |
| | | * @throws IllegalArgumentException |
| | | * If the provided duration is negative. |
| | |
| | | } |
| | | |
| | | if (duration == 0) { |
| | | return "0ms"; |
| | | return "0 ms"; |
| | | } |
| | | |
| | | DurationUnit[] units = new DurationUnit[] { WEEKS, DAYS, HOURS, MINUTES, |
| | | SECONDS, MILLI_SECONDS }; |
| | | long remainder = duration; |
| | | StringBuilder builder = new StringBuilder(); |
| | | boolean isFirst = true; |
| | | for (DurationUnit unit : units) { |
| | | long count = remainder / unit.getDuration(); |
| | | if (count > 0) { |
| | | if (!isFirst) { |
| | | builder.append(' '); |
| | | } |
| | | builder.append(count); |
| | | builder.append(' '); |
| | | builder.append(unit.getShortName()); |
| | | remainder = remainder - (count * unit.getDuration()); |
| | | isFirst = false; |
| | | } |
| | | } |
| | | return builder.toString(); |
| | |
| | | // The abbreviation of the unit. |
| | | private final String shortName; |
| | | |
| | | // The size of the unit in milli-seconds. |
| | | // The size of the unit in milliseconds. |
| | | private final long sz; |
| | | |
| | | |
| | |
| | | |
| | | |
| | | /** |
| | | * Converts the specified duration in milli-seconds to this unit. |
| | | * Converts the specified duration in milliseconds to this unit. |
| | | * |
| | | * @param duration |
| | | * The duration in milli-seconds. |
| | | * @return Returns milli-seconds in this unit. |
| | | * The duration in milliseconds. |
| | | * @return Returns milliseconds in this unit. |
| | | */ |
| | | public double fromMilliSeconds(long duration) { |
| | | return ((double) duration / sz); |
| | |
| | | |
| | | |
| | | /** |
| | | * Get the number of milli-seconds that this unit represents. |
| | | * Get the number of milliseconds that this unit represents. |
| | | * |
| | | * @return Returns the number of milli-seconds that this unit |
| | | * @return Returns the number of milliseconds that this unit |
| | | * represents. |
| | | */ |
| | | public long getDuration() { |
| | |
| | | |
| | | |
| | | /** |
| | | * Converts the specified duration in this unit to milli-seconds. |
| | | * Converts the specified duration in this unit to milliseconds. |
| | | * |
| | | * @param duration |
| | | * The duration as a quantity of this unit. |
| | | * @return Returns the number of milli-seconds that the duration |
| | | * @return Returns the number of milliseconds that the duration |
| | | * represents. |
| | | */ |
| | | public long toMilliSeconds(double duration) { |
| | |
| | | // Cast to a long to remove fractional part (which should not be there |
| | | // anyway as the best-fit unit should result in an exact conversion). |
| | | builder.append((long) unit.fromBytes(value)); |
| | | |
| | | builder.append(' '); |
| | | builder.append(unit.toString()); |
| | | return builder.toString(); |
| | | } |
| | |
| | | |
| | | import static org.testng.Assert.*; |
| | | |
| | | import org.opends.server.TestCaseUtils; |
| | | import org.opends.server.admin.std.meta.RootCfgDefn; |
| | | import org.testng.annotations.BeforeClass; |
| | | import org.testng.annotations.DataProvider; |
| | | import org.testng.annotations.Test; |
| | | |
| | |
| | | public class DurationPropertyDefinitionTest { |
| | | |
| | | /** |
| | | * Sets up tests |
| | | * |
| | | * @throws Exception |
| | | * If the server could not be initialized. |
| | | */ |
| | | @BeforeClass |
| | | public void setUp() throws Exception { |
| | | // This test suite depends on having the schema available, so |
| | | // we'll start the server. |
| | | TestCaseUtils.startServer(); |
| | | } |
| | | |
| | | /** |
| | | * Tests creation of builder succeeds |
| | | */ |
| | | @Test |
| | |
| | | DurationPropertyDefinition spd = buildTestDefinition(builder); |
| | | assertEquals(spd.getLowerLimit(), expectedValue); |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Creates data for testing string-based limit values |
| | | * |
| | | * |
| | | * @return data |
| | | */ |
| | | @DataProvider(name = "stringLimitData") |
| | |
| | | { "m", "10s", 10000 } |
| | | }; |
| | | } |
| | | |
| | | |
| | | /** |
| | | * Tests setting/getting of lower limit as String. |
| | | * |
| | | * |
| | | * @param unit |
| | | * The unit. |
| | | * @param value |
| | |
| | | public Object[][] createEncodeValueData() { |
| | | return new Object[][]{ |
| | | {-1L, "unlimited"}, |
| | | {0L, "0s"}, |
| | | {1L, "1s"}, |
| | | {2L, "2s"}, |
| | | {999L, "999s"}, |
| | | {1000L, "1000s"}, |
| | | {1001L, "1001s"}, |
| | | {1023L, "1023s"}, |
| | | {1024L, "1024s"}, |
| | | {1025L, "1025s"}, |
| | | {1000L * 1000L, "1000000s"}, |
| | | {0L, "0 s"}, |
| | | {1L, "1 s"}, |
| | | {2L, "2 s"}, |
| | | {999L, "999 s"}, |
| | | {1000L, "1000 s"}, |
| | | {1001L, "1001 s"}, |
| | | {1023L, "1023 s"}, |
| | | {1024L, "1024 s"}, |
| | | {1025L, "1025 s"}, |
| | | {1000L * 1000L, "1000000 s"}, |
| | | }; |
| | | } |
| | | |
| | |
| | | { "1h60m", 2L }, |
| | | { "1d10h", 34L }, |
| | | { "4d600m", 106L }, |
| | | |
| | | |
| | | // conversion tests |
| | | {"1 d", 24L}, |
| | | {"2 d", 48L}, |
| | |
| | | @DataProvider(name = "testToString") |
| | | public Object[][] createToStringData() { |
| | | return new Object[][]{ |
| | | { 0L, "0ms" }, |
| | | { 1L, "1ms" }, |
| | | { 999L, "999ms" }, |
| | | { 1000L, "1s" }, |
| | | { 1001L, "1s1ms" }, |
| | | { 59999L, "59s999ms" }, |
| | | { 60000L, "1m" }, |
| | | { 3599999L, "59m59s999ms" }, |
| | | { 3600000L, "1h" } |
| | | { 0L, "0 ms" }, |
| | | { 1L, "1 ms" }, |
| | | { 999L, "999 ms" }, |
| | | { 1000L, "1 s" }, |
| | | { 1001L, "1 s 1 ms" }, |
| | | { 59999L, "59 s 999 ms" }, |
| | | { 60000L, "1 m" }, |
| | | { 3599999L, "59 m 59 s 999 ms" }, |
| | | { 3600000L, "1 h" } |
| | | }; |
| | | } |
| | | |
| | |
| | | |
| | | import static org.testng.Assert.*; |
| | | |
| | | import org.opends.server.TestCaseUtils; |
| | | import org.opends.server.admin.std.meta.RootCfgDefn; |
| | | import org.testng.annotations.BeforeClass; |
| | | import org.testng.annotations.DataProvider; |
| | | import org.testng.annotations.Test; |
| | | |
| | |
| | | public class SizePropertyDefinitionTest { |
| | | |
| | | /** |
| | | * Sets up tests |
| | | * |
| | | * @throws Exception |
| | | * If the server could not be initialized. |
| | | */ |
| | | @BeforeClass |
| | | public void setUp() throws Exception { |
| | | // This test suite depends on having the schema available, so |
| | | // we'll start the server. |
| | | TestCaseUtils.startServer(); |
| | | } |
| | | |
| | | /** |
| | | * Tests creation of builder succeeds |
| | | */ |
| | | @Test |
| | |
| | | public Object[][] createEncodeValueData() { |
| | | return new Object[][]{ |
| | | {-1L, "unlimited"}, |
| | | {0L, "0b"}, |
| | | {1L, "1b"}, |
| | | {2L, "2b"}, |
| | | {999L, "999b"}, |
| | | {1000L, "1kb"}, |
| | | {1001L, "1001b"}, |
| | | {1023L, "1023b"}, |
| | | {1024L, "1kib"}, |
| | | {1025L, "1025b"}, |
| | | {1000L * 1000L, "1mb"}, |
| | | {1000L * 1000L * 1000L, "1gb"}, |
| | | {1024L * 1024L * 1024L, "1gib"}, |
| | | {1000L * 1000L * 1000L * 1000L, "1tb"} |
| | | {0L, "0 b"}, |
| | | {1L, "1 b"}, |
| | | {2L, "2 b"}, |
| | | {999L, "999 b"}, |
| | | {1000L, "1 kb"}, |
| | | {1001L, "1001 b"}, |
| | | {1023L, "1023 b"}, |
| | | {1024L, "1 kib"}, |
| | | {1025L, "1025 b"}, |
| | | {1000L * 1000L, "1 mb"}, |
| | | {1000L * 1000L * 1000L, "1 gb"}, |
| | | {1024L * 1024L * 1024L, "1 gib"}, |
| | | {1000L * 1000L * 1000L * 1000L, "1 tb"} |
| | | |
| | | }; |
| | | } |