add PerfUtil.clear()/Bytes.concat()/CollectionUtil.randomSet()

also add some unit tests: HugeConfigTest, PerfUtilTest,
NumericUtilTest, ReflectionUtilTest and TimeUtilTest.

Change-Id: Ida64154a0bdee62e281585836c5e7ccfc6061c06
This commit is contained in:
Zhangmei Li 2019-02-27 21:48:21 +08:00 committed by Linary
parent 5bac575b29
commit 95530cc4b3
19 changed files with 849 additions and 70 deletions

View File

@ -6,7 +6,7 @@
<groupId>com.baidu.hugegraph</groupId>
<artifactId>hugegraph-common</artifactId>
<version>1.5.7</version>
<version>1.5.8</version>
<name>hugegraph-common</name>
<url>https://github.com/hugegraph/hugegraph-common</url>
@ -60,8 +60,8 @@
<commons.configuration.version>1.10</commons.configuration.version>
<commons.configuration2.version>2.1.1</commons.configuration2.version>
<commons.collections.version>3.2.2</commons.collections.version>
<commons.io.version>20030203.000550</commons.io.version>
<commons.codec.version>20041127.091804</commons.codec.version>
<commons.io.version>2.4</commons.io.version>
<commons.codec.version>1.11</commons.codec.version>
<guava.version>19.0</guava.version>
<javax.json.version>1.0</javax.json.version>
<jsr305.version>3.0.1</jsr305.version>
@ -146,6 +146,7 @@
<version>${javassist.version}</version>
</dependency>
<!-- jersey -->
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
@ -198,7 +199,7 @@
<manifestEntries>
<!-- Must be on one line, otherwise the automatic
upgrade script cannot replace the version number -->
<Implementation-Version>1.5.6.0</Implementation-Version>
<Implementation-Version>1.5.8.0</Implementation-Version>
</manifestEntries>
</archive>
</configuration>

View File

@ -60,30 +60,31 @@ public class HugeConfig extends PropertiesConfiguration {
this(loadConfigFile(configFile));
}
private void reloadIfNeed(Configuration config) {
if (config instanceof AbstractFileConfiguration) {
AbstractFileConfiguration fileConfig =
(AbstractFileConfiguration) config;
private void reloadIfNeed(Configuration conf) {
if (!(conf instanceof AbstractFileConfiguration)) {
return;
}
File file = fileConfig.getFile();
if (file != null) {
// May need to use the original file
this.setFile(file);
}
AbstractFileConfiguration fileConfig = (AbstractFileConfiguration) conf;
if (!fileConfig.isDelimiterParsingDisabled()) {
/*
* PropertiesConfiguration will parse the containing comma
* config options into list directly, but we want to do
* this work by ourselves, so reload it and parse into `String`
*/
fileConfig.setDelimiterParsingDisabled(true);
try {
fileConfig.refresh();
} catch (ConfigurationException e) {
throw new ConfigException("Unable to load config file: %s",
e, file);
}
File file = fileConfig.getFile();
if (file != null) {
// May need to use the original file
this.setFile(file);
}
if (!fileConfig.isDelimiterParsingDisabled()) {
/*
* PropertiesConfiguration will parse the containing comma
* config options into list directly, but we want to do
* this work by ourselves, so reload it and parse into `String`
*/
fileConfig.setDelimiterParsingDisabled(true);
try {
fileConfig.refresh();
} catch (ConfigurationException e) {
throw new ConfigException("Unable to load config file: %s",
e, file);
}
}
}

View File

@ -26,8 +26,8 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.security.InvalidParameterException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@ -39,6 +39,7 @@ import java.util.stream.Stream;
import org.slf4j.Logger;
import com.baidu.hugegraph.func.TriFunction;
import com.baidu.hugegraph.util.E;
import com.baidu.hugegraph.util.Log;
import com.baidu.hugegraph.util.ReflectionUtil;
import com.google.common.reflect.ClassPath.ClassInfo;
@ -52,10 +53,10 @@ import javassist.NotFoundException;
public class PerfUtil {
private static final Logger LOG = Log.logger(PerfUtil.class);
private static ThreadLocal<PerfUtil> instance = new ThreadLocal<>();
private static final ThreadLocal<PerfUtil> INSTANCE = new ThreadLocal<>();
private Map<String, Stopwatch> stopwatches;
private Stack<String> callStack;
private final Map<String, Stopwatch> stopwatches;
private final Stack<String> callStack;
private PerfUtil() {
this.stopwatches = new HashMap<>();
@ -63,10 +64,10 @@ public class PerfUtil {
}
public static PerfUtil instance() {
PerfUtil p = instance.get();
PerfUtil p = INSTANCE.get();
if (p == null) {
p = new PerfUtil();
instance.set(p);
INSTANCE.set(p);
}
return p;
}
@ -89,6 +90,7 @@ public class PerfUtil {
}
public boolean end(String name) {
long time = now();
String current = this.callStack.pop();
assert current.endsWith(name);
@ -97,15 +99,21 @@ public class PerfUtil {
if (item == null) {
throw new InvalidParameterException(name);
}
item.endTime(now());
item.endTime(time);
return true;
}
public void profilePackage(String... packages) throws
NotFoundException, CannotCompileException,
ClassNotFoundException, IOException {
Set<String> loadedClasses = new LinkedHashSet<>();
public void clear() {
E.checkState(this.callStack.empty(),
"Can't be cleared when the call has not ended yet");
this.stopwatches.clear();
}
public void profilePackage(String... packages)
throws NotFoundException, IOException,
ClassNotFoundException, CannotCompileException {
Set<String> loadedClasses = new HashSet<>();
Iterator<ClassInfo> classes = ReflectionUtil.classes(packages);
while (classes.hasNext()) {
@ -125,8 +133,9 @@ public class PerfUtil {
}
}
public void profileClass(String... classes) throws
NotFoundException, CannotCompileException, ClassNotFoundException {
public void profileClass(String... classes)
throws NotFoundException, CannotCompileException,
ClassNotFoundException {
ClassPool classPool = ClassPool.getDefault();
for (String cls : classes) {
@ -145,7 +154,7 @@ public class PerfUtil {
}
private void profile(CtMethod ctMethod)
throws CannotCompileException, ClassNotFoundException {
throws CannotCompileException, ClassNotFoundException {
final String START =
"com.baidu.hugegraph.perf.PerfUtil.instance().start(\"%s\");";
final String END =

View File

@ -26,12 +26,12 @@ public class Whitebox {
public static void setInternalState(Object target, String fieldName,
Object value) {
try {
Field field = target.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
field.set(target, value);
Field f = getFieldFromHierarchy(target.getClass(), fieldName);
f.setAccessible(true);
f.set(target, value);
} catch (Exception e) {
Assert.fail(String.format("Can't change value of '%s' against " +
"target '%s'", fieldName, target));
"target '%s': %s", fieldName, target, e));
}
}

View File

@ -44,6 +44,13 @@ public final class Bytes {
return CMP.compare(bytes1, bytes2);
}
public static byte[] concat(byte[] bytes1, byte[] bytes2) {
byte[] result = new byte[bytes1.length + bytes2.length];
System.arraycopy(bytes1, 0, result, 0, bytes1.length);
System.arraycopy(bytes2, 0, result, bytes1.length, bytes2.length);
return result;
}
public static boolean prefixWith(byte[] bytes, byte[] prefix) {
if (bytes.length < prefix.length) {
return false;

View File

@ -29,6 +29,7 @@ import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ThreadLocalRandom;
public final class CollectionUtil {
@ -68,6 +69,18 @@ public final class CollectionUtil {
return true;
}
public static Set<Integer> randomSet(int min, int max, int count) {
E.checkArgument(max > min, "Invalid min/max: %s/%s", min, max);
E.checkArgument(0 < count && count <= max - min,
"Invalid count %s", count);
Set<Integer> randoms = new HashSet<>();
while (randoms.size() < count) {
randoms.add(ThreadLocalRandom.current().nextInt(min, max));
}
return randoms;
}
public static boolean allUnique(Collection<?> collection) {
return collection.stream().allMatch(new HashSet<>()::add);
}

View File

@ -90,7 +90,7 @@ public final class NumericUtil {
* @return The sortable long value
*/
public static long sortableDoubleBits(long bits) {
return bits ^ (bits >> 63) & 0x7fffffffffffffffL;
return bits ^ ((bits >> 63) & 0x7fffffffffffffffL);
}
/**
@ -100,7 +100,12 @@ public final class NumericUtil {
* @return The sortable int value
*/
public static int sortableFloatBits(int bits) {
return bits ^ (bits >> 31) & 0x7fffffff;
/*
* Convert to its inverse digits if negative else keep the origin
* NOTE: (bits >> 31) is 0x00000000 if bits >= 0
* (bits >> 31) is 0xFFFFFFFF if bits < 0
*/
return bits ^ ((bits >> 31) & 0x7fffffff);
}
public static long numberToSortableLong(Number number) {

View File

@ -42,6 +42,7 @@ public final class ReflectionUtil {
if (type.isPrimitive() ||
type.equals(String.class) ||
type.equals(Boolean.class) ||
type.equals(Character.class) ||
NumericUtil.isNumber(type)) {
return true;
}
@ -49,9 +50,9 @@ public final class ReflectionUtil {
}
public static List<Method> getMethodsAnnotatedWith(
Class<?> type,
Class<? extends Annotation> annotation,
boolean withSuperClass) {
Class<?> type,
Class<? extends Annotation> annotation,
boolean withSuperClass) {
final List<Method> methods = new LinkedList<>();
Class<?> klass = type;
do {
@ -66,9 +67,10 @@ public final class ReflectionUtil {
}
public static List<CtMethod> getMethodsAnnotatedWith(
CtClass type,
Class<? extends Annotation> annotation,
boolean withSuperClass) throws NotFoundException {
CtClass type,
Class<? extends Annotation> annotation,
boolean withSuperClass)
throws NotFoundException {
final List<CtMethod> methods = new LinkedList<>();
CtClass klass = type;
@ -84,7 +86,7 @@ public final class ReflectionUtil {
}
public static Iterator<ClassInfo> classes(String... packages)
throws IOException {
throws IOException {
ClassPath path = ClassPath.from(ReflectionUtil.class.getClassLoader());
ExtendableIterator<ClassInfo> results = new ExtendableIterator<>();
for (String p : packages) {
@ -94,7 +96,7 @@ public final class ReflectionUtil {
}
public static List<String> superClasses(String clazz)
throws NotFoundException {
throws NotFoundException {
CtClass klass = ClassPool.getDefault().get(clazz);
klass = klass.getSuperclass();

View File

@ -27,5 +27,5 @@ public class CommonVersion {
// The second parameter of Version.of() is for all-in-one JAR
public static final Version VERSION = Version.of(CommonVersion.class,
"1.5.7");
"1.5.8");
}

View File

@ -0,0 +1,53 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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 com.baidu.hugegraph.testclass;
import com.baidu.hugegraph.perf.PerfUtil.Watched;
public class TestClass {
public static class Foo {
@Watched
public void foo() {
this.bar();
}
@Watched
public void bar() {}
}
public static class Base {
@Watched
public void func() {}
}
public static class Sub extends Base {
@Watched
public void func1() {}
public void func2() {}
@Watched
public void func3() {}
}
}

View File

@ -22,24 +22,31 @@ package com.baidu.hugegraph.unit;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
import com.baidu.hugegraph.unit.config.HugeConfigTest;
import com.baidu.hugegraph.unit.event.EventHubTest;
import com.baidu.hugegraph.unit.iterator.ExtendableIteratorTest;
import com.baidu.hugegraph.unit.iterator.FilterIteratorTest;
import com.baidu.hugegraph.unit.iterator.FlatMapperFilterIteratorTest;
import com.baidu.hugegraph.unit.iterator.FlatMapperIteratorTest;
import com.baidu.hugegraph.unit.iterator.MapperIteratorTest;
import com.baidu.hugegraph.unit.perf.PerfUtilTest;
import com.baidu.hugegraph.unit.util.BytesTest;
import com.baidu.hugegraph.unit.util.CollectionUtilTest;
import com.baidu.hugegraph.unit.util.HashUtilTest;
import com.baidu.hugegraph.unit.util.InsertionOrderUtilTest;
import com.baidu.hugegraph.unit.util.LongEncodingTest;
import com.baidu.hugegraph.unit.util.NumericUtilTest;
import com.baidu.hugegraph.unit.util.ReflectionUtilTest;
import com.baidu.hugegraph.unit.util.TimeUtilTest;
import com.baidu.hugegraph.unit.util.VersionUtilTest;
import com.baidu.hugegraph.unit.version.VersionTest;
@RunWith(Suite.class)
@Suite.SuiteClasses({
VersionTest.class,
HugeConfigTest.class,
EventHubTest.class,
PerfUtilTest.class,
VersionTest.class,
ExtendableIteratorTest.class,
FilterIteratorTest.class,
@ -51,6 +58,9 @@ import com.baidu.hugegraph.unit.version.VersionTest;
CollectionUtilTest.class,
HashUtilTest.class,
InsertionOrderUtilTest.class,
NumericUtilTest.class,
ReflectionUtilTest.class,
TimeUtilTest.class,
VersionUtilTest.class,
LongEncodingTest.class
})

View File

@ -0,0 +1,232 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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 com.baidu.hugegraph.unit.config;
import static com.baidu.hugegraph.config.OptionChecker.allowValues;
import static com.baidu.hugegraph.config.OptionChecker.disallowEmpty;
import static com.baidu.hugegraph.config.OptionChecker.nonNegativeInt;
import static com.baidu.hugegraph.config.OptionChecker.positiveInt;
import static com.baidu.hugegraph.config.OptionChecker.rangeDouble;
import static com.baidu.hugegraph.config.OptionChecker.rangeInt;
import java.util.Arrays;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.junit.BeforeClass;
import org.junit.Test;
import com.baidu.hugegraph.config.ConfigListOption;
import com.baidu.hugegraph.config.ConfigOption;
import com.baidu.hugegraph.config.HugeConfig;
import com.baidu.hugegraph.config.OptionHolder;
import com.baidu.hugegraph.config.OptionSpace;
import com.baidu.hugegraph.testutil.Assert;
import com.baidu.hugegraph.testutil.Whitebox;
import com.baidu.hugegraph.unit.BaseUnitTest;
import com.google.common.collect.ImmutableMap;
public class HugeConfigTest extends BaseUnitTest {
private static final String CONF =
"src/test/java/com/baidu/hugegraph/unit/config/test.conf";
@BeforeClass
public static void init() {
OptionSpace.register("test", TestOptions.class.getName());
}
@Test
public void testHugeConfig() throws Exception {
Configuration conf = new PropertiesConfiguration();
Whitebox.setInternalState(conf, "delimiterParsingDisabled", true);
HugeConfig config = new HugeConfig(conf);
Assert.assertEquals("text1-value", config.get(TestOptions.text1));
Assert.assertEquals("text2-value", config.get(TestOptions.text2));
Assert.assertEquals("CHOICE-1", config.get(TestOptions.text3));
Assert.assertEquals(1, (int) config.get(TestOptions.int1));
Assert.assertEquals(10, (int) config.get(TestOptions.int2));
Assert.assertEquals(10, (int) config.get(TestOptions.int3));
Assert.assertEquals(100L, (long) config.get(TestOptions.long1));
Assert.assertEquals(100.0f, config.get(TestOptions.float1), 0f);
Assert.assertEquals(100.0f, config.get(TestOptions.double1), 0d);
Assert.assertEquals(true, config.get(TestOptions.bool));
Assert.assertEquals(Arrays.asList("list-value1", "list-value2"),
config.get(TestOptions.list));
Assert.assertEquals(ImmutableMap.of("key1", "value1", "key2", "value2"),
config.getMap(TestOptions.map));
}
@Test
public void testHugeConfigWithFile() throws Exception {
HugeConfig config = new HugeConfig(CONF);
Assert.assertEquals("file-text1-value", config.get(TestOptions.text1));
Assert.assertEquals("file-text2-value", config.get(TestOptions.text2));
Assert.assertEquals("CHOICE-3", config.get(TestOptions.text3));
Assert.assertEquals(2, (int) config.get(TestOptions.int1));
Assert.assertEquals(0, (int) config.get(TestOptions.int2));
Assert.assertEquals(1, (int) config.get(TestOptions.int3));
Assert.assertEquals(99L, (long) config.get(TestOptions.long1));
Assert.assertEquals(66.0f, config.get(TestOptions.float1), 0f);
Assert.assertEquals(66.0f, config.get(TestOptions.double1), 0d);
Assert.assertEquals(false, config.get(TestOptions.bool));
Assert.assertEquals(Arrays.asList("file-v1", "file-v2", "file-v3"),
config.get(TestOptions.list));
Assert.assertEquals(ImmutableMap.of("key1", "value1", "key3", "value3"),
config.getMap(TestOptions.map));
}
@Test
public void testHugeConfigWithConfiguration() throws Exception {
HugeConfig config = new HugeConfig(new PropertiesConfiguration(CONF));
Assert.assertEquals("file-text1-value", config.get(TestOptions.text1));
Assert.assertEquals("file-text2-value", config.get(TestOptions.text2));
Assert.assertEquals("CHOICE-3", config.get(TestOptions.text3));
}
public static final class TestOptions extends OptionHolder {
private static volatile TestOptions instance;
public static synchronized TestOptions instance() {
if (instance == null) {
instance = new TestOptions();
instance.registerOptions();
}
return instance;
}
public static final ConfigOption<String> text1 =
new ConfigOption<>(
"group1.text1",
"description of group1.text1",
disallowEmpty(),
"text1-value"
);
public static final ConfigOption<String> text2 =
new ConfigOption<>(
"group1.text2",
"description of group1.text2",
disallowEmpty(),
"text2-value"
);
public static final ConfigOption<String> text3 =
new ConfigOption<>(
"group1.text3",
"description of group1.text3",
allowValues("CHOICE-1", "CHOICE-2", "CHOICE-3"),
"CHOICE-1"
);
public static final ConfigOption<Integer> int1 =
new ConfigOption<>(
"group1.int1",
"description of group1.int1",
rangeInt(1, 100),
1
);
public static final ConfigOption<Integer> int2 =
new ConfigOption<>(
"group1.int2",
"description of group1.int2",
nonNegativeInt(),
10
);
public static final ConfigOption<Integer> int3 =
new ConfigOption<>(
"group1.int3",
"description of group1.int3",
positiveInt(),
10
);
public static final ConfigOption<Long> long1 =
new ConfigOption<>(
"group1.long1",
"description of group1.long1",
rangeInt(1L, 100L),
100L
);
public static final ConfigOption<Float> float1 =
new ConfigOption<>(
"group1.float1",
"description of group1.float1",
rangeDouble(1.0f, 100.0f),
100.0f
);
public static final ConfigOption<Double> double1 =
new ConfigOption<>(
"group1.double1",
"description of group1.double1",
rangeDouble(1.0, 100.0),
100.0
);
public static final ConfigOption<Boolean> bool =
new ConfigOption<>(
"group1.bool",
"description of group1.bool",
disallowEmpty(),
true
);
public static final ConfigListOption<String> list =
new ConfigListOption<>(
"group1.list",
false,
"description of group1.list",
disallowEmpty(),
String.class,
"list-value1", "list-value2"
);
public static final ConfigListOption<String> map =
new ConfigListOption<>(
"group1.map",
false,
"description of group1.map",
disallowEmpty(),
String.class,
"key1:value1", "key2:value2"
);
}
}

View File

@ -0,0 +1,16 @@
group1.text1=file-text1-value
group1.text2=file-text2-value
group1.text3=CHOICE-3
group1.int1=2
group1.int2=0
group1.int3=1
group1.long1=99
group1.float1=66
group1.double1=66
group1.bool=false
group1.list=[file-v1, file-v2, file-v3]
group1.map=[key1:value1, key3:value3]

View File

@ -0,0 +1,112 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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 com.baidu.hugegraph.unit.perf;
import java.io.IOException;
import java.util.Map;
import org.junit.After;
import org.junit.Test;
import com.baidu.hugegraph.perf.PerfUtil;
import com.baidu.hugegraph.testclass.TestClass.Foo;
import com.baidu.hugegraph.testclass.TestClass.Sub;
import com.baidu.hugegraph.testutil.Assert;
import com.baidu.hugegraph.unit.BaseUnitTest;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class PerfUtilTest extends BaseUnitTest {
private static final PerfUtil perf = PerfUtil.instance();
@After
public void teardown() {
perf.clear();
}
@Test
public void testPerfUtil() throws Exception {
/*
* TODO: call profilePackage("com.baidu.hugegraph.testclass") and
* remove class Foo. now exception "duplicate class definition" throws
* since JUnit loaded class TestClass before testPerfUtil()
*/
perf.profilePackage("com.baidu.hugegraph.testclass");
perf.profileClass("com.baidu.hugegraph.testclass.TestClass$Foo");
Foo obj = new Foo();
obj.foo();
perf.toString();
perf.toECharts();
String json = perf.toJson();
assertContains(json, "foo.times", 1);
assertContains(json, "foo/bar.times", 1);
perf.clear();
obj.foo();
obj.foo();
perf.toString();
perf.toECharts();
json = perf.toJson();
assertContains(json, "foo.times", 2);
assertContains(json, "foo/bar.times", 2);
}
@Test
public void testPerfUtilWithProfileClass() throws Exception {
perf.profileClass("com.baidu.hugegraph.testclass.TestClass$Base");
perf.profileClass("com.baidu.hugegraph.testclass.TestClass$Sub");
Sub obj = new Sub();
obj.func();
obj.func1();
obj.func2();
obj.func3();
obj.func3();
obj.func3();
String json = perf.toJson();
assertContains(json, "func.times", 1);
assertContains(json, "func1.times", 1);
assertContains(json, "func3.times", 3);
}
private static void assertContains(String json, String key, Object value)
throws JsonParseException, JsonMappingException, IOException {
ObjectMapper mapper = new ObjectMapper();
Map<?, ?> map = mapper.readValue(json, Map.class);
String[] keys = key.split("\\.");
Object actual = null;
for (String k : keys) {
actual = map.get(k);
if (actual instanceof Map) {
map = (Map<?, ?>) actual;
}
}
Assert.assertEquals(value, actual);
}
}

View File

@ -30,8 +30,8 @@ public class BytesTest extends BaseUnitTest {
@Test
public void testBytesEquals() {
Assert.assertTrue(Bytes.equals("12345678".getBytes(),
"12345678".getBytes()));
Assert.assertTrue(Bytes.equals(b("12345678"),
b("12345678")));
Assert.assertTrue(Bytes.equals(new byte[]{1, 3, 5, 7},
new byte[]{1, 3, 5, 7}));
@ -43,10 +43,8 @@ public class BytesTest extends BaseUnitTest {
@Test
public void testBytesPrefixWith() {
Assert.assertTrue(Bytes.prefixWith("12345678".getBytes(),
"12345678".getBytes()));
Assert.assertTrue(Bytes.prefixWith("12345678".getBytes(),
"1234567".getBytes()));
Assert.assertTrue(Bytes.prefixWith(b("12345678"), b("12345678")));
Assert.assertTrue(Bytes.prefixWith(b("12345678"), b("1234567")));
Assert.assertTrue(Bytes.prefixWith(new byte[]{1, 3, 5, 7},
new byte[]{1, 3, 5, 7}));
@ -65,12 +63,9 @@ public class BytesTest extends BaseUnitTest {
@Test
public void testBytesCompare() {
Assert.assertTrue(Bytes.compare("12345678".getBytes(),
"12345678".getBytes()) == 0);
Assert.assertTrue(Bytes.compare("12345678".getBytes(),
"1234567".getBytes()) > 0);
Assert.assertTrue(Bytes.compare("12345678".getBytes(),
"12345679".getBytes()) < 0);
Assert.assertTrue(Bytes.compare(b("12345678"), b("12345678")) == 0);
Assert.assertTrue(Bytes.compare(b("12345678"), b("1234567")) > 0);
Assert.assertTrue(Bytes.compare(b("12345678"), b("12345679")) < 0);
Assert.assertTrue(Bytes.compare(new byte[]{1, 3, 5, 7},
new byte[]{1, 3, 5, 7}) == 0);
@ -113,15 +108,29 @@ public class BytesTest extends BaseUnitTest {
}
@Test
public void testBytesTohex() {
public void testBytesConcat() {
Assert.assertArrayEquals(b("12345678"),
Bytes.concat(b("1234"), b("5678")));
Assert.assertArrayEquals(b("12345678"),
Bytes.concat(b("12345678"), b("")));
Assert.assertArrayEquals(b("12345678"),
Bytes.concat(b(""), b("12345678")));
}
@Test
public void testBytesToHex() {
int value = 0x0103807f;
byte[] bytes = NumericUtil.intToBytes(value);
Assert.assertEquals("0103807f", Bytes.toHex(bytes));
}
@Test
public void testBytesFromhex() {
public void testBytesFromHex() {
Assert.assertEquals(0x0103807f,
NumericUtil.bytesToInt(Bytes.fromHex("0103807f")));
}
private static byte[] b(String string) {
return string.getBytes();
}
}

View File

@ -73,6 +73,29 @@ public class CollectionUtilTest extends BaseUnitTest {
Assert.assertFalse(CollectionUtil.prefixOf(list4, list));
}
@Test
public void testRandomSet() {
Set<Integer> set = CollectionUtil.randomSet(0, 100, 10);
for (int i : set) {
Assert.assertTrue(0 <= i && i < 100);
}
// invalid min
Assert.assertThrows(IllegalArgumentException.class, () -> {
CollectionUtil.randomSet(200, 100, 10);
});
// invalid count = 0
Assert.assertThrows(IllegalArgumentException.class, () -> {
CollectionUtil.randomSet(1, 100, 0);
});
// invalid count > max - min
Assert.assertThrows(IllegalArgumentException.class, () -> {
CollectionUtil.randomSet(1, 100, 100);
});
}
@Test
public void testAllUnique() {
List<Integer> list = ImmutableList.of();

View File

@ -0,0 +1,109 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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 com.baidu.hugegraph.unit.util;
import java.math.BigDecimal;
import org.junit.Test;
import com.baidu.hugegraph.testutil.Assert;
import com.baidu.hugegraph.unit.BaseUnitTest;
import com.baidu.hugegraph.util.Bytes;
import com.baidu.hugegraph.util.NumericUtil;
public class NumericUtilTest extends BaseUnitTest {
@Test
public void testNumberToSortableBytes() {
// byte
byte[] bytes = NumericUtil.numberToSortableBytes((byte) 0x33);
assertEquals(new byte[]{0x33}, bytes);
// short
bytes = NumericUtil.numberToSortableBytes((short) 0x11223344);
assertEquals(new byte[]{0, 0, 0x33, 0x44}, bytes);
// int
bytes = NumericUtil.numberToSortableBytes(0x11223344);
assertEquals(new byte[]{0x11, 0x22, 0x33, 0x44}, bytes);
// long
bytes = NumericUtil.numberToSortableBytes(0x1122334455L);
assertEquals(new byte[]{0, 0, 0, 0x11, 0x22, 0x33, 0x44, 0x55}, bytes);
// float
bytes = NumericUtil.numberToSortableBytes(3.14f);
assertEquals(new byte[]{0x40, 0x48, (byte) 0xf5, (byte) 0xc3}, bytes);
// double
bytes = NumericUtil.numberToSortableBytes(3.1415926d);
assertEquals(new byte[]{0x40, 0x09, 0x21, (byte) 0xfb,
0x4d, 0x12, (byte) 0xd8, 0x4a}, bytes);
// BigDecimal
Assert.assertThrows(IllegalArgumentException.class, () -> {
NumericUtil.numberToSortableBytes(new BigDecimal(123));
});
}
@Test
public void testSortableBytesToNumber() {
// byte
Number value = NumericUtil.sortableBytesToNumber(new byte[]{0x33},
Byte.class);
Assert.assertEquals(value, (byte) 0x33);
// short
value = NumericUtil.sortableBytesToNumber(new byte[]{0, 0, 0x33, 0x44},
Short.class);
Assert.assertEquals((short) 0x3344, value);
// int
value = NumericUtil.sortableBytesToNumber(
new byte[]{0x11, 0x22, 0x33, 0x44}, Integer.class);
Assert.assertEquals(0x11223344, value);
// long
value = NumericUtil.sortableBytesToNumber(
new byte[]{0, 0, 0, 0x11, 0x22, 0x33, 0x44, 0x55}, Long.class);
Assert.assertEquals(0x1122334455L, value);
// float
value = NumericUtil.sortableBytesToNumber(
new byte[]{0x40, 0x48, (byte) 0xf5, (byte) 0xc3}, Float.class);
Assert.assertEquals(3.14f, value);
// double
value = NumericUtil.sortableBytesToNumber(
new byte[]{0x40, 0x09, 0x21, (byte) 0xfb,
0x4d, 0x12, (byte) 0xd8, 0x4a},
Double.class);
Assert.assertEquals(3.1415926d, value);
// BigDecimal
Assert.assertThrows(IllegalArgumentException.class, () -> {
NumericUtil.sortableBytesToNumber(new byte[123], BigDecimal.class);
});
}
private static void assertEquals(byte[] bytes1, byte[] bytes2) {
Assert.assertTrue(Bytes.toHex(bytes1) + " != " + Bytes.toHex(bytes2),
Bytes.equals(bytes1, bytes2));
}
}

View File

@ -0,0 +1,114 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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 com.baidu.hugegraph.unit.util;
import java.io.IOException;
import java.lang.reflect.Method;
import java.util.List;
import org.apache.commons.collections.IteratorUtils;
import org.junit.Test;
import com.baidu.hugegraph.perf.PerfUtil.Watched;
import com.baidu.hugegraph.testclass.TestClass.Base;
import com.baidu.hugegraph.testclass.TestClass.Sub;
import com.baidu.hugegraph.testutil.Assert;
import com.baidu.hugegraph.unit.BaseUnitTest;
import com.baidu.hugegraph.util.ReflectionUtil;
import com.google.common.reflect.ClassPath.ClassInfo;
import javassist.NotFoundException;
public class ReflectionUtilTest extends BaseUnitTest {
@Test
public void testIsSimpleType() {
Assert.assertTrue(ReflectionUtil.isSimpleType(byte.class));
Assert.assertTrue(ReflectionUtil.isSimpleType(char.class));
Assert.assertTrue(ReflectionUtil.isSimpleType(short.class));
Assert.assertTrue(ReflectionUtil.isSimpleType(int.class));
Assert.assertTrue(ReflectionUtil.isSimpleType(long.class));
Assert.assertTrue(ReflectionUtil.isSimpleType(float.class));
Assert.assertTrue(ReflectionUtil.isSimpleType(double.class));
Assert.assertTrue(ReflectionUtil.isSimpleType(boolean.class));
Assert.assertTrue(ReflectionUtil.isSimpleType(Byte.class));
Assert.assertTrue(ReflectionUtil.isSimpleType(Character.class));
Assert.assertTrue(ReflectionUtil.isSimpleType(Short.class));
Assert.assertTrue(ReflectionUtil.isSimpleType(Integer.class));
Assert.assertTrue(ReflectionUtil.isSimpleType(Long.class));
Assert.assertTrue(ReflectionUtil.isSimpleType(Float.class));
Assert.assertTrue(ReflectionUtil.isSimpleType(Double.class));
Assert.assertTrue(ReflectionUtil.isSimpleType(Boolean.class));
Assert.assertTrue(ReflectionUtil.isSimpleType(String.class));
Assert.assertFalse(ReflectionUtil.isSimpleType(Object.class));
Assert.assertFalse(ReflectionUtil.isSimpleType(BaseUnitTest.class));
}
@Test
public void testGetMethodsAnnotatedWith() {
List<Method> methods;
methods = ReflectionUtil.getMethodsAnnotatedWith(Sub.class,
Watched.class,
false);
methods.sort((m1, m2) -> m1.getName().compareTo(m2.getName()));
Assert.assertEquals(2, methods.size());
Assert.assertEquals("func1", methods.get(0).getName());
Assert.assertEquals("func3", methods.get(1).getName());
methods = ReflectionUtil.getMethodsAnnotatedWith(Sub.class,
Watched.class,
true);
methods.sort((m1, m2) -> m1.getName().compareTo(m2.getName()));
Assert.assertEquals(3, methods.size());
Assert.assertEquals("func", methods.get(0).getName());
Assert.assertEquals("func1", methods.get(1).getName());
Assert.assertEquals("func3", methods.get(2).getName());
}
@Test
public void testClasses() throws IOException {
@SuppressWarnings("unchecked")
List<ClassInfo> classes = IteratorUtils.toList(ReflectionUtil.classes(
"com.baidu.hugegraph.util"));
Assert.assertEquals(13, classes.size());
classes.sort((c1, c2) -> c1.getName().compareTo(c2.getName()));
Assert.assertEquals("com.baidu.hugegraph.util.Bytes",
classes.get(0).getName());
Assert.assertEquals("com.baidu.hugegraph.util.CheckSocket",
classes.get(1).getName());
Assert.assertEquals("com.baidu.hugegraph.util.CollectionUtil",
classes.get(2).getName());
Assert.assertEquals("com.baidu.hugegraph.util.VersionUtil",
classes.get(12).getName());
}
@Test
public void testSuperClasses() throws NotFoundException {
List<String> classes = ReflectionUtil.superClasses(Sub.class.getName());
Assert.assertEquals(2, classes.size());
classes.sort((c1, c2) -> c1.compareTo(c2));
Assert.assertEquals(Base.class.getName(), classes.get(0));
Assert.assertEquals(Object.class.getName(), classes.get(1));
}
}

View File

@ -0,0 +1,63 @@
/*
* Copyright 2017 HugeGraph Authors
*
* 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 com.baidu.hugegraph.unit.util;
import java.util.Date;
import org.junit.Test;
import com.baidu.hugegraph.testutil.Assert;
import com.baidu.hugegraph.unit.BaseUnitTest;
import com.baidu.hugegraph.util.TimeUtil;
public class TimeUtilTest extends BaseUnitTest {
@Test
public void testTimeGen() {
long time = TimeUtil.timeGen();
long base = TimeUtil.BASE_TIME;
long difference = time - base - System.currentTimeMillis();
Assert.assertTrue(difference < 1000);
}
@Test
public void testTimeGenWithDate() {
@SuppressWarnings("deprecation")
Date date = new Date(2019 - 1900, 2, 28);
long time = TimeUtil.timeGen(date);
Assert.assertEquals(41904000000L, time);
}
@Test
public void testTimeGenWithLong() {
long date = TimeUtil.BASE_TIME + 123L;
long time = TimeUtil.timeGen(date);
Assert.assertEquals(123L, time);
}
@Test
public void testTillNextMillis() {
for (int i = 0; i < 100; i++) {
long lastTimestamp = TimeUtil.timeGen();
long time = TimeUtil.tillNextMillis(lastTimestamp);
Assert.assertNotEquals(lastTimestamp, time);
}
}
}