support assert range conditions (#41)

add methods to Assert class:
  assertGt()
  assertGte()
  assertLt()
  assertLte()
  assertContains()

Change-Id: If4c5df19c937a8bb06fcdd60122ac54ab04f501b
diff --git a/pom.xml b/pom.xml
index cf64766..9ad4475 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
 
     <groupId>com.baidu.hugegraph</groupId>
     <artifactId>hugegraph-common</artifactId>
-    <version>1.7.0</version>
+    <version>1.7.1</version>
 
     <name>hugegraph-common</name>
     <url>https://github.com/hugegraph/hugegraph-common</url>
@@ -218,7 +218,7 @@
                         <manifestEntries>
                             <!-- Must be on one line, otherwise the automatic
                                  upgrade script cannot replace the version number -->
-                            <Implementation-Version>1.7.0.0</Implementation-Version>
+                            <Implementation-Version>1.7.1.0</Implementation-Version>
                         </manifestEntries>
                     </archive>
                 </configuration>
diff --git a/src/main/java/com/baidu/hugegraph/testutil/Assert.java b/src/main/java/com/baidu/hugegraph/testutil/Assert.java
index 188d0fe..535f41e 100644
--- a/src/main/java/com/baidu/hugegraph/testutil/Assert.java
+++ b/src/main/java/com/baidu/hugegraph/testutil/Assert.java
@@ -20,6 +20,11 @@
 package com.baidu.hugegraph.testutil;
 
 import java.util.function.Consumer;
+import java.util.function.Function;
+
+import org.hamcrest.BaseMatcher;
+import org.hamcrest.CoreMatchers;
+import org.hamcrest.Description;
 
 public class Assert extends org.junit.Assert {
 
@@ -43,17 +48,17 @@
             runnable.run();
             fail = true;
         } catch (Throwable e) {
-            exceptionConsumer.accept(e);
             if (!throwable.isInstance(e)) {
                 Assert.fail(String.format(
-                            "Bad exception type %s(expect %s)",
-                            e.getClass(), throwable));
+                            "Bad exception type %s(expected %s)",
+                            e.getClass().getName(), throwable.getName()));
             }
+            exceptionConsumer.accept(e);
         }
         if (fail) {
             Assert.fail(String.format(
-                        "No exception was thrown(expect %s)",
-                        throwable));
+                        "No exception was thrown(expected %s)",
+                        throwable.getName()));
         }
     }
 
@@ -84,4 +89,65 @@
     public static void assertEquals(double expected, Object actual) {
         org.junit.Assert.assertEquals(expected, actual);
     }
+
+    public static void assertGt(Number expected, Object actual) {
+        org.junit.Assert.assertThat(actual, new NumberMatcher(expected, cmp -> {
+            return cmp > 0;
+        }, ">"));
+    }
+
+    public static void assertGte(Number expected, Object actual) {
+        org.junit.Assert.assertThat(actual, new NumberMatcher(expected, cmp -> {
+            return cmp >= 0;
+        }, ">="));
+    }
+
+    public static void assertLt(Number expected, Object actual) {
+        org.junit.Assert.assertThat(actual, new NumberMatcher(expected, cmp -> {
+            return cmp < 0;
+        }, "<"));
+    }
+
+    public static void assertLte(Number expected, Object actual) {
+        org.junit.Assert.assertThat(actual, new NumberMatcher(expected, cmp -> {
+            return cmp <= 0;
+        }, "<="));
+    }
+
+    public static void assertContains(String sub, String actual) {
+        org.junit.Assert.assertThat(actual, CoreMatchers.containsString(sub));
+    }
+
+    public static void assertInstanceOf(Class<?> clazz, Object object) {
+        org.junit.Assert.assertThat(object, CoreMatchers.instanceOf(clazz));
+    }
+
+    private static class NumberMatcher extends BaseMatcher<Object> {
+
+        private final String symbol;
+        private final Number expected;
+        private final Function<Integer, Boolean> cmp;
+
+        public NumberMatcher(Number expected, Function<Integer, Boolean> cmp,
+                             String symbol) {
+            this.expected = expected;
+            this.cmp = cmp;
+            this.symbol = symbol;
+        }
+
+        @SuppressWarnings("unchecked")
+        @Override
+        public boolean matches(Object actual) {
+            Assert.assertInstanceOf(this.expected.getClass(), actual);
+            Assert.assertInstanceOf(Comparable.class, actual);
+            int cmp = ((Comparable<Number>) actual).compareTo(this.expected);
+            return this.cmp.apply(cmp);
+        }
+
+        @Override
+        public void describeTo(Description desc) {
+            desc.appendText("a number ").appendText(this.symbol)
+                .appendText(" ").appendText(this.expected.toString());
+        }
+    }
 }
diff --git a/src/main/java/com/baidu/hugegraph/version/CommonVersion.java b/src/main/java/com/baidu/hugegraph/version/CommonVersion.java
index 27048fd..5bfcbcb 100644
--- a/src/main/java/com/baidu/hugegraph/version/CommonVersion.java
+++ b/src/main/java/com/baidu/hugegraph/version/CommonVersion.java
@@ -27,5 +27,5 @@
 
     // The second parameter of Version.of() is for all-in-one JAR
     public static final Version VERSION = Version.of(CommonVersion.class,
-                                                     "1.7.0");
+                                                     "1.7.1");
 }
diff --git a/src/test/java/com/baidu/hugegraph/testutil/AssertTest.java b/src/test/java/com/baidu/hugegraph/testutil/AssertTest.java
index 480842e..91b7ee4 100644
--- a/src/test/java/com/baidu/hugegraph/testutil/AssertTest.java
+++ b/src/test/java/com/baidu/hugegraph/testutil/AssertTest.java
@@ -37,6 +37,138 @@
     }
 
     @Test
+    public void testAssertEqualsWithError() {
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertEquals((byte) 1, "1");
+        }, e -> {
+            Assert.assertContains("expected: java.lang.Byte",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertEquals((short) 1, "1");
+        }, e -> {
+            Assert.assertContains("expected: java.lang.Short",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertEquals('1', "1");
+        }, e -> {
+            Assert.assertContains("expected: java.lang.Character",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertEquals(1, "1");
+        }, e -> {
+            Assert.assertContains("expected: java.lang.Integer",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertEquals(1L, "1");
+        }, e -> {
+            Assert.assertContains("expected: java.lang.Long",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertEquals(1f, "1.0");
+        }, e -> {
+            Assert.assertContains("expected: java.lang.Float",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertEquals(1d, "1.0");
+        }, e -> {
+            Assert.assertContains("expected: java.lang.Double",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertEquals(1f, "1");
+        }, e -> {
+            Assert.assertContains("expected:<1.0> but was:<1>",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertEquals(1d, "1");
+        }, e -> {
+            Assert.assertContains("expected:<1.0> but was:<1>",
+                                  e.getMessage());
+        });
+    }
+
+    @Test
+    public void testAssertEqualsOfIntWithError() {
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertEquals(1, (Byte) (byte) 1);
+        }, e -> {
+            Assert.assertContains("expected: java.lang.Integer",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertEquals(1, (Short) (short) 1);
+        }, e -> {
+            Assert.assertContains("expected: java.lang.Integer",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertEquals(1, (Character) '1');
+        }, e -> {
+            Assert.assertContains("expected: java.lang.Integer",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertEquals(1, (Long) 1l);
+        }, e -> {
+            Assert.assertContains("expected: java.lang.Integer",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertEquals(1, (Float) 1f);
+        }, e -> {
+            Assert.assertContains("expected:<1> but was:<1.0>",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertEquals(1, (Double) 1d);
+        }, e -> {
+            Assert.assertContains("expected:<1> but was:<1.0>",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertEquals(1, "1.0");
+        }, e -> {
+            Assert.assertContains("expected:<1> but was:<1.0>",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertEquals(1, (Byte) (byte) 2);
+        }, e -> {
+            Assert.assertContains("expected:<1> but was:<2>",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertEquals(1, null);
+        }, e -> {
+            Assert.assertContains("expected:<1> but was:<null>",
+                                  e.getMessage());
+        });
+    }
+
+    @Test
     public void testAssertThrows() {
         Assert.assertThrows(NullPointerException.class, () -> {
             throw new NullPointerException();
@@ -61,7 +193,7 @@
             Assert.fail("Expect error");
         } catch (AssertionError e) {
             Assert.assertEquals("No exception was thrown" +
-                                "(expect class java.lang.NullPointerException)",
+                                "(expected java.lang.NullPointerException)",
                                 e.getMessage());
         }
 
@@ -71,10 +203,228 @@
             });
             Assert.fail("Expect error");
         } catch (AssertionError e) {
-            Assert.assertEquals("Bad exception type class " +
+            Assert.assertEquals("Bad exception type " +
                                 "java.lang.RuntimeException" +
-                                "(expect class java.lang.NullPointerException)",
+                                "(expected java.lang.NullPointerException)",
                                 e.getMessage());
         }
     }
+
+    @Test
+    public void testAssertGt() {
+        Assert.assertGt((byte) 1, Byte.valueOf("2"));
+        Assert.assertGt((short) 1, Short.valueOf("2"));
+        Assert.assertGt(1, Integer.valueOf("2"));
+        Assert.assertGt(1L, Long.valueOf("2"));
+        Assert.assertGt(1f, Float.valueOf("1.01"));
+        Assert.assertGt(1d, Double.valueOf("1.01"));
+
+        Assert.assertGt((byte) 1, (byte) 2);
+        Assert.assertGt((short) 1, (short) 2);
+        Assert.assertGt(1, 2);
+        Assert.assertGt(1L, 2L);
+        Assert.assertGt(1f, 1.01f);
+        Assert.assertGt(1d, 1.01d);
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertGt(1, 0);
+        }, e -> {
+            Assert.assertContains("Expected: a number > 1", e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertGt(1, null);
+        }, e -> {
+            Assert.assertContains("Expected: an instance of java.lang.Integer",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertGt(1, (byte) 2);
+        }, e -> {
+            Assert.assertContains("Expected: an instance of java.lang.Integer",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertGt(1, 1.1);
+        }, e -> {
+            Assert.assertContains("Expected: an instance of java.lang.Integer",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertGt(1, Character.valueOf('2'));
+        }, e -> {
+            Assert.assertContains("Expected: an instance of java.lang.Integer",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertGt(0.9, 1);
+        }, e -> {
+            Assert.assertContains("Expected: an instance of java.lang.Double",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertGt(0.9d, 0.98f);
+        }, e -> {
+            Assert.assertContains("Expected: an instance of java.lang.Double",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertGt(0.9f, 0.98d);
+        }, e -> {
+            Assert.assertContains("Expected: an instance of java.lang.Float",
+                                  e.getMessage());
+        });
+    }
+
+    @Test
+    public void testAssertGte() {
+        Assert.assertGte((byte) 1, Byte.valueOf("2"));
+        Assert.assertGte((short) 1, Short.valueOf("2"));
+        Assert.assertGte(1, Integer.valueOf("2"));
+        Assert.assertGte(1L, Long.valueOf("2"));
+        Assert.assertGte(1f, Float.valueOf("1.01"));
+        Assert.assertGte(1d, Double.valueOf("1.01"));
+
+        Assert.assertGte((byte) 1, Byte.valueOf("1"));
+        Assert.assertGte((short) 1, Short.valueOf("1"));
+        Assert.assertGte(1, Integer.valueOf("1"));
+        Assert.assertGte(1L, Long.valueOf("1"));
+        Assert.assertGte(1f, Float.valueOf("1"));
+        Assert.assertGte(1d, Double.valueOf("1"));
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertGte(1, 0);
+        }, e -> {
+            Assert.assertContains("Expected: a number >= 1", e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertGte(1, 1.1);
+        }, e -> {
+            Assert.assertContains("Expected: an instance of java.lang.Integer",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertGte(1, Character.valueOf('2'));
+        }, e -> {
+            Assert.assertContains("Expected: an instance of java.lang.Integer",
+                                  e.getMessage());
+        });
+    }
+
+    @Test
+    public void testAssertLt() {
+        Assert.assertLt((byte) 1, Byte.valueOf("0"));
+        Assert.assertLt((short) 1, Short.valueOf("0"));
+        Assert.assertLt(1, Integer.valueOf("0"));
+        Assert.assertLt(1L, Long.valueOf("0"));
+        Assert.assertLt(1f, Float.valueOf("0.99"));
+        Assert.assertLt(1d, Double.valueOf("0.99"));
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertLt(1, 2);
+        }, e -> {
+            Assert.assertContains("Expected: a number < 1", e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertGt(1, 0.9);
+        }, e -> {
+            Assert.assertContains("Expected: an instance of java.lang.Integer",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertGt(1, Character.valueOf('0'));
+        }, e -> {
+            Assert.assertContains("Expected: an instance of java.lang.Integer",
+                                  e.getMessage());
+        });
+    }
+
+    @Test
+    public void testAssertLte() {
+        Assert.assertLte((byte) 1, Byte.valueOf("0"));
+        Assert.assertLte((short) 1, Short.valueOf("0"));
+        Assert.assertLte(1, Integer.valueOf("0"));
+        Assert.assertLte(1L, Long.valueOf("0"));
+        Assert.assertLte(1f, Float.valueOf("0.99"));
+        Assert.assertLte(1d, Double.valueOf("0.99"));
+
+        Assert.assertLte((byte) 1, Byte.valueOf("1"));
+        Assert.assertLte((short) 1, Short.valueOf("1"));
+        Assert.assertLte(1, Integer.valueOf("1"));
+        Assert.assertLte(1L, Long.valueOf("1"));
+        Assert.assertLte(1f, Float.valueOf("1"));
+        Assert.assertLte(1d, Double.valueOf("1"));
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertLte(1, 2);
+        }, e -> {
+            Assert.assertContains("Expected: a number <= 1", e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertLte(1, 0.9);
+        }, e -> {
+            Assert.assertContains("Expected: an instance of java.lang.Integer",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertLte(1, Character.valueOf('0'));
+        }, e -> {
+            Assert.assertContains("Expected: an instance of java.lang.Integer",
+                                  e.getMessage());
+        });
+    }
+
+    @Test
+    public void testAssertContains() {
+        Assert.assertContains("test", "test");
+        Assert.assertContains("test", "hellotest");
+        Assert.assertContains("test", "test123");
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertContains("test123", "test");
+        }, e -> {
+            Assert.assertContains("Expected: a string containing",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertContains("null", null);
+        }, e -> {
+            Assert.assertContains("Expected: a string containing",
+                                  e.getMessage());
+        });
+
+        Assert.assertThrows(NullPointerException.class, () -> {
+            Assert.assertContains(null, "null");
+        }, e -> {
+            Assert.assertNull(e.getMessage());
+        });
+    }
+
+    @Test
+    public void testAssertInstanceOf() {
+        Assert.assertInstanceOf(Integer.class, 1);
+        Assert.assertInstanceOf(Double.class, 1.0);
+        Assert.assertInstanceOf(String.class, "1.0");
+        Assert.assertInstanceOf(BaseUnitTest.class, this);
+
+        Assert.assertThrows(AssertionError.class, () -> {
+            Assert.assertInstanceOf(Float.class, 1);
+        }, e -> {
+            Assert.assertContains("Expected: an instance of java.lang.Float",
+                                  e.getMessage());
+        });
+    }
 }