blob: a49533d086a71056479c9d980fba176d278467a2 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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
*
* http://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 org.apache.druid.java.util.common;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.druid.utils.CollectionUtils;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.groups.Default;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class HumanReadableBytesTest
{
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Test
public void testNumberString()
{
Assert.assertEquals(0, HumanReadableBytes.parse("0"));
Assert.assertEquals(1, HumanReadableBytes.parse("1"));
Assert.assertEquals(10000000, HumanReadableBytes.parse("10000000"));
}
@Test
public void testWithWhiteSpace()
{
Assert.assertEquals(12345, HumanReadableBytes.parse(" 12345 "));
Assert.assertEquals(12345, HumanReadableBytes.parse("\t12345\t"));
}
@Test
public void testK()
{
Assert.assertEquals(1000, HumanReadableBytes.parse("1k"));
Assert.assertEquals(1000, HumanReadableBytes.parse("1K"));
}
@Test
public void testM()
{
Assert.assertEquals(1000_000, HumanReadableBytes.parse("1m"));
Assert.assertEquals(1000_000, HumanReadableBytes.parse("1M"));
}
@Test
public void testG()
{
Assert.assertEquals(1000_000_000, HumanReadableBytes.parse("1g"));
Assert.assertEquals(1000_000_000, HumanReadableBytes.parse("1G"));
}
@Test
public void testT()
{
Assert.assertEquals(1000_000_000_000L, HumanReadableBytes.parse("1t"));
Assert.assertEquals(1000_000_000_000L, HumanReadableBytes.parse("1T"));
}
@Test
public void testKiB()
{
Assert.assertEquals(1024, HumanReadableBytes.parse("1kib"));
Assert.assertEquals(9 * 1024, HumanReadableBytes.parse("9KiB"));
Assert.assertEquals(9 * 1024, HumanReadableBytes.parse("9Kib"));
}
@Test
public void testMiB()
{
Assert.assertEquals(1024 * 1024, HumanReadableBytes.parse("1mib"));
Assert.assertEquals(9 * 1024 * 1024, HumanReadableBytes.parse("9MiB"));
Assert.assertEquals(9 * 1024 * 1024, HumanReadableBytes.parse("9Mib"));
}
@Test
public void testGiB()
{
Assert.assertEquals(1024 * 1024 * 1024, HumanReadableBytes.parse("1gib"));
Assert.assertEquals(1024 * 1024 * 1024, HumanReadableBytes.parse("1GiB"));
Assert.assertEquals(9L * 1024 * 1024 * 1024, HumanReadableBytes.parse("9Gib"));
}
@Test
public void testTiB()
{
Assert.assertEquals(1024L * 1024 * 1024 * 1024, HumanReadableBytes.parse("1tib"));
Assert.assertEquals(9L * 1024 * 1024 * 1024 * 1024, HumanReadableBytes.parse("9TiB"));
Assert.assertEquals(9L * 1024 * 1024 * 1024 * 1024, HumanReadableBytes.parse("9Tib"));
}
@Test
public void testPiB()
{
Assert.assertEquals(1024L * 1024 * 1024 * 1024 * 1024, HumanReadableBytes.parse("1pib"));
Assert.assertEquals(9L * 1024 * 1024 * 1024 * 1024 * 1024, HumanReadableBytes.parse("9PiB"));
Assert.assertEquals(9L * 1024 * 1024 * 1024 * 1024 * 1024, HumanReadableBytes.parse("9Pib"));
}
@Test
public void testDefault()
{
Assert.assertEquals(-123, HumanReadableBytes.parse(" ", -123));
Assert.assertEquals(-456, HumanReadableBytes.parse(null, -456));
Assert.assertEquals(-789, HumanReadableBytes.parse("\t", -789));
}
static class ExceptionMatcher implements Matcher
{
static ExceptionMatcher INVALIDFORMAT = new ExceptionMatcher("Invalid format");
static ExceptionMatcher OVERFLOW = new ExceptionMatcher("Number overflow");
private String prefix;
public ExceptionMatcher(String prefix)
{
this.prefix = prefix;
}
@Override
public boolean matches(Object item)
{
if (!(item instanceof IAE)) {
return false;
}
return ((IAE) item).getMessage().startsWith(prefix);
}
@Override
public void describeMismatch(Object item, Description mismatchDescription)
{
}
@Override
public void _dont_implement_Matcher___instead_extend_BaseMatcher_()
{
}
@Override
public void describeTo(Description description)
{
}
}
@Test
public void testNull()
{
expectedException.expect(ExceptionMatcher.INVALIDFORMAT);
HumanReadableBytes.parse(null);
}
@Test
public void testEmpty()
{
expectedException.expect(ExceptionMatcher.INVALIDFORMAT);
HumanReadableBytes.parse("");
}
@Test
public void testWhitespace()
{
expectedException.expect(ExceptionMatcher.INVALIDFORMAT);
HumanReadableBytes.parse(" ");
}
@Test
public void testNegative()
{
expectedException.expect(ExceptionMatcher.INVALIDFORMAT);
HumanReadableBytes.parse("-1");
}
@Test
public void testInvalidFormatOneChar()
{
expectedException.expect(ExceptionMatcher.INVALIDFORMAT);
HumanReadableBytes.parse("b");
}
@Test
public void testInvalidFormatOneChar2()
{
expectedException.expect(ExceptionMatcher.INVALIDFORMAT);
HumanReadableBytes.parse("B");
}
@Test
public void testInvalidFormatExtraSpace()
{
expectedException.expect(ExceptionMatcher.INVALIDFORMAT);
HumanReadableBytes.parse("1 b");
}
@Test
public void testInvalidFormat4()
{
expectedException.expect(ExceptionMatcher.INVALIDFORMAT);
HumanReadableBytes.parse("1b");
}
@Test
public void testInvalidFormatMiBExtraSpace()
{
expectedException.expect(ExceptionMatcher.INVALIDFORMAT);
HumanReadableBytes.parse("1 mib");
}
@Test
public void testInvalidFormatTiB()
{
expectedException.expect(ExceptionMatcher.INVALIDFORMAT);
HumanReadableBytes.parse("tib");
}
@Test
public void testInvalidFormatGiB()
{
expectedException.expect(ExceptionMatcher.INVALIDFORMAT);
HumanReadableBytes.parse("gib");
}
@Test
public void testInvalidFormatPiB()
{
expectedException.expect(ExceptionMatcher.INVALIDFORMAT);
HumanReadableBytes.parse(" pib");
}
@Test
public void testInvalidCharacter()
{
expectedException.expect(ExceptionMatcher.INVALIDFORMAT);
HumanReadableBytes.parse("c");
}
@Test
public void testExtraLargeNumber()
{
expectedException.expect(ExceptionMatcher.INVALIDFORMAT);
String extraLarge = Long.MAX_VALUE + "1";
HumanReadableBytes.parse(extraLarge);
}
@Test
public void testOverflowK()
{
expectedException.expect(ExceptionMatcher.OVERFLOW);
String overflow = (Long.MAX_VALUE / 1000 + 1) + "k";
HumanReadableBytes.parse(overflow);
}
@Test
public void testOverflowM()
{
expectedException.expect(ExceptionMatcher.OVERFLOW);
String overflow = (Long.MAX_VALUE / 1000_000 + 1) + "m";
HumanReadableBytes.parse(overflow);
}
@Test
public void testOverflowG()
{
expectedException.expect(ExceptionMatcher.OVERFLOW);
String overflow = (Long.MAX_VALUE / 1000_000_000L + 1) + "g";
HumanReadableBytes.parse(overflow);
}
@Test
public void testOverflowT()
{
expectedException.expect(ExceptionMatcher.OVERFLOW);
String overflow = (Long.MAX_VALUE / 1000_000_000_000L + 1) + "t";
HumanReadableBytes.parse(overflow);
}
@Test
public void testOverflowP()
{
expectedException.expect(ExceptionMatcher.OVERFLOW);
String overflow = (Long.MAX_VALUE / 1_000_000_000_000_000L + 1) + "p";
HumanReadableBytes.parse(overflow);
}
@Test
public void testOverflowKiB()
{
expectedException.expect(ExceptionMatcher.OVERFLOW);
String overflow = (Long.MAX_VALUE / 1024 + 1) + "KiB";
HumanReadableBytes.parse(overflow);
}
@Test
public void testOverflowMiB()
{
expectedException.expect(ExceptionMatcher.OVERFLOW);
String overflow = (Long.MAX_VALUE / (1024 * 1024) + 1) + "MiB";
HumanReadableBytes.parse(overflow);
}
@Test
public void testOverflowGiB()
{
expectedException.expect(ExceptionMatcher.OVERFLOW);
String overflow = (Long.MAX_VALUE / (1024L * 1024 * 1024) + 1) + "GiB";
HumanReadableBytes.parse(overflow);
}
@Test
public void testOverflowTiB()
{
expectedException.expect(ExceptionMatcher.OVERFLOW);
String overflow = (Long.MAX_VALUE / (1024L * 1024 * 1024 * 1024) + 1) + "TiB";
HumanReadableBytes.parse(overflow);
}
@Test
public void testOverflowPiB()
{
expectedException.expect(ExceptionMatcher.OVERFLOW);
String overflow = (Long.MAX_VALUE / (1024L * 1024 * 1024 * 1024 * 1024) + 1) + "PiB";
HumanReadableBytes.parse(overflow);
}
@Test
public void testJSON() throws JsonProcessingException
{
ObjectMapper mapper = new ObjectMapper();
HumanReadableBytes bytes = new HumanReadableBytes("5m");
String serialized = mapper.writeValueAsString(bytes);
HumanReadableBytes deserialized = mapper.readValue(serialized, HumanReadableBytes.class);
Assert.assertEquals(bytes, deserialized);
}
@Test
public void testGetInt()
{
expectedException.expectMessage("Number [2147483648] exceeds range of Integer.MAX_VALUE");
HumanReadableBytes bytes = new HumanReadableBytes("2GiB");
bytes.getBytesInInt();
}
static class TestBytesRange
{
@HumanReadableBytesRange(min = 0, max = 5)
HumanReadableBytes bytes;
public TestBytesRange(HumanReadableBytes bytes)
{
this.bytes = bytes;
}
}
@Test
public void testBytesRange()
{
String message = validate(new TestBytesRange(HumanReadableBytes.valueOf(-1)));
Assert.assertEquals("value must be in the range of [0, 5]", message);
message = validate(new TestBytesRange(HumanReadableBytes.valueOf(0)));
Assert.assertEquals(null, message);
message = validate(new TestBytesRange(HumanReadableBytes.valueOf(5)));
Assert.assertEquals(null, message);
message = validate(new TestBytesRange(HumanReadableBytes.valueOf(6)));
Assert.assertEquals("value must be in the range of [0, 5]", message);
}
@Test
public void testFormatInBinaryByte()
{
Assert.assertEquals("-8.00 EiB", HumanReadableBytes.format(Long.MIN_VALUE, 2, HumanReadableBytes.UnitSystem.BINARY_BYTE));
Assert.assertEquals("-8.000 EiB", HumanReadableBytes.format(Long.MIN_VALUE, 3, HumanReadableBytes.UnitSystem.BINARY_BYTE));
Assert.assertEquals("-2.00 GiB", HumanReadableBytes.format(Integer.MIN_VALUE, 2, HumanReadableBytes.UnitSystem.BINARY_BYTE));
Assert.assertEquals("-32.00 KiB", HumanReadableBytes.format(Short.MIN_VALUE, 2, HumanReadableBytes.UnitSystem.BINARY_BYTE));
Assert.assertEquals("-128 B", HumanReadableBytes.format(Byte.MIN_VALUE, 2, HumanReadableBytes.UnitSystem.BINARY_BYTE));
Assert.assertEquals("-1 B", HumanReadableBytes.format(-1, 2, HumanReadableBytes.UnitSystem.BINARY_BYTE));
Assert.assertEquals("0 B", HumanReadableBytes.format(0, 2, HumanReadableBytes.UnitSystem.BINARY_BYTE));
Assert.assertEquals("1 B", HumanReadableBytes.format(1, 2, HumanReadableBytes.UnitSystem.BINARY_BYTE));
Assert.assertEquals("1.00 KiB", HumanReadableBytes.format(1024L, 2, HumanReadableBytes.UnitSystem.BINARY_BYTE));
Assert.assertEquals("1.00 MiB", HumanReadableBytes.format(1024L * 1024, 2, HumanReadableBytes.UnitSystem.BINARY_BYTE));
Assert.assertEquals("1.00 GiB", HumanReadableBytes.format(1024L * 1024 * 1024, 2, HumanReadableBytes.UnitSystem.BINARY_BYTE));
Assert.assertEquals("1.00 TiB", HumanReadableBytes.format(1024L * 1024 * 1024 * 1024, 2, HumanReadableBytes.UnitSystem.BINARY_BYTE));
Assert.assertEquals("1.00 PiB", HumanReadableBytes.format(1024L * 1024 * 1024 * 1024 * 1024, 2, HumanReadableBytes.UnitSystem.BINARY_BYTE));
Assert.assertEquals("8.00 EiB", HumanReadableBytes.format(Long.MAX_VALUE, 2, HumanReadableBytes.UnitSystem.BINARY_BYTE));
}
@Test
public void testPrecisionInBinaryFormat()
{
Assert.assertEquals("1 KiB", HumanReadableBytes.format(1500, 0, HumanReadableBytes.UnitSystem.BINARY_BYTE));
Assert.assertEquals("1.5 KiB", HumanReadableBytes.format(1500, 1, HumanReadableBytes.UnitSystem.BINARY_BYTE));
Assert.assertEquals("1.46 KiB", HumanReadableBytes.format(1500, 2, HumanReadableBytes.UnitSystem.BINARY_BYTE));
Assert.assertEquals("1.465 KiB", HumanReadableBytes.format(1500, 3, HumanReadableBytes.UnitSystem.BINARY_BYTE));
}
@Test
public void testPrecisionInDecimalFormat()
{
Assert.assertEquals("1 KB", HumanReadableBytes.format(1456, 0, HumanReadableBytes.UnitSystem.DECIMAL_BYTE));
Assert.assertEquals("1.5 KB", HumanReadableBytes.format(1456, 1, HumanReadableBytes.UnitSystem.DECIMAL_BYTE));
Assert.assertEquals("1.46 KB", HumanReadableBytes.format(1456, 2, HumanReadableBytes.UnitSystem.DECIMAL_BYTE));
Assert.assertEquals("1.456 KB", HumanReadableBytes.format(1456, 3, HumanReadableBytes.UnitSystem.DECIMAL_BYTE));
}
@Test
public void testFormatInDecimalByte()
{
Assert.assertEquals("1 B", HumanReadableBytes.format(1, 2, HumanReadableBytes.UnitSystem.DECIMAL_BYTE));
Assert.assertEquals("1.00 KB", HumanReadableBytes.format(1000L, 2, HumanReadableBytes.UnitSystem.DECIMAL_BYTE));
Assert.assertEquals("1.00 MB", HumanReadableBytes.format(1000L * 1000, 2, HumanReadableBytes.UnitSystem.DECIMAL_BYTE));
Assert.assertEquals("1.00 GB", HumanReadableBytes.format(1000L * 1000 * 1000, 2, HumanReadableBytes.UnitSystem.DECIMAL_BYTE));
Assert.assertEquals("1.00 TB", HumanReadableBytes.format(1000L * 1000 * 1000 * 1000, 2, HumanReadableBytes.UnitSystem.DECIMAL_BYTE));
Assert.assertEquals("1.00 PB", HumanReadableBytes.format(1000L * 1000 * 1000 * 1000 * 1000, 2, HumanReadableBytes.UnitSystem.DECIMAL_BYTE));
Assert.assertEquals("9.22 EB", HumanReadableBytes.format(Long.MAX_VALUE, 2, HumanReadableBytes.UnitSystem.DECIMAL_BYTE));
Assert.assertEquals("100.00 KB", HumanReadableBytes.format(99999, 2, HumanReadableBytes.UnitSystem.DECIMAL_BYTE));
Assert.assertEquals("99.999 KB", HumanReadableBytes.format(99999, 3, HumanReadableBytes.UnitSystem.DECIMAL_BYTE));
Assert.assertEquals("999.9 PB", HumanReadableBytes.format(999_949_999_999_999_999L, 1, HumanReadableBytes.UnitSystem.DECIMAL_BYTE));
Assert.assertEquals("999.95 PB", HumanReadableBytes.format(999_949_999_999_999_999L, 2, HumanReadableBytes.UnitSystem.DECIMAL_BYTE));
Assert.assertEquals("999.949 PB", HumanReadableBytes.format(999_949_999_999_999_999L, 3, HumanReadableBytes.UnitSystem.DECIMAL_BYTE));
}
@Test
public void testFormatInDecimal()
{
Assert.assertEquals("1", HumanReadableBytes.format(1, 2, HumanReadableBytes.UnitSystem.DECIMAL));
Assert.assertEquals("999", HumanReadableBytes.format(999, 2, HumanReadableBytes.UnitSystem.DECIMAL));
Assert.assertEquals("-999", HumanReadableBytes.format(-999, 2, HumanReadableBytes.UnitSystem.DECIMAL));
Assert.assertEquals("-1.00 K", HumanReadableBytes.format(-1000, 2, HumanReadableBytes.UnitSystem.DECIMAL));
Assert.assertEquals("1.00 K", HumanReadableBytes.format(1000L, 2, HumanReadableBytes.UnitSystem.DECIMAL));
Assert.assertEquals("1.00 M", HumanReadableBytes.format(1000L * 1000, 2, HumanReadableBytes.UnitSystem.DECIMAL));
Assert.assertEquals("1.00 G", HumanReadableBytes.format(1000L * 1000 * 1000, 2, HumanReadableBytes.UnitSystem.DECIMAL));
Assert.assertEquals("1.00 T", HumanReadableBytes.format(1000L * 1000 * 1000 * 1000, 2, HumanReadableBytes.UnitSystem.DECIMAL));
Assert.assertEquals("1.00 P", HumanReadableBytes.format(1000L * 1000 * 1000 * 1000 * 1000, 2, HumanReadableBytes.UnitSystem.DECIMAL));
Assert.assertEquals("-9.22 E", HumanReadableBytes.format(Long.MIN_VALUE, 2, HumanReadableBytes.UnitSystem.DECIMAL));
Assert.assertEquals("9.22 E", HumanReadableBytes.format(Long.MAX_VALUE, 2, HumanReadableBytes.UnitSystem.DECIMAL));
}
@Test
public void testInvalidPrecisionArgumentLowerBound()
{
expectedException.expect(IAE.class);
expectedException.expectMessage("precision [-1] must be in the range of [0,3]");
Assert.assertEquals("1.00", HumanReadableBytes.format(1, -1, HumanReadableBytes.UnitSystem.DECIMAL));
}
@Test
public void testInvalidPrecisionArgumentUpperBound()
{
expectedException.expect(IAE.class);
expectedException.expectMessage("precision [4] must be in the range of [0,3]");
Assert.assertEquals("1", HumanReadableBytes.format(1, 3, HumanReadableBytes.UnitSystem.DECIMAL));
Assert.assertEquals("1", HumanReadableBytes.format(1, 4, HumanReadableBytes.UnitSystem.DECIMAL));
}
private static <T> String validate(T obj)
{
Validator validator = Validation.buildDefaultValidatorFactory()
.getValidator();
Map<String, StringBuilder> errorMap = new HashMap<>();
Set<ConstraintViolation<T>> set = validator.validate(obj, Default.class);
return CollectionUtils.isNullOrEmpty(set) ? null : set.stream().findFirst().get().getMessage();
}
}