From 72231250ed81e10d66bfe70701e64fa5fe50f712 Mon Sep 17 00:00:00 2001 From: Jon Bratseth Date: Wed, 15 Jun 2016 23:09:44 +0200 Subject: Publish --- testutil/.gitignore | 2 + testutil/OWNERS | 1 + testutil/README | 1 + testutil/pom.xml | 47 ++++++++++ .../com/yahoo/test/CollectionPatternMatcher.java | 45 +++++++++ .../java/com/yahoo/test/LinePatternMatcher.java | 43 +++++++++ .../src/main/java/com/yahoo/test/ManualClock.java | 36 +++++++ .../src/main/java/com/yahoo/test/Matchers.java | 104 +++++++++++++++++++++ .../src/main/java/com/yahoo/test/OrderTester.java | 73 +++++++++++++++ .../java/com/yahoo/test/PartialOrderTester.java | 29 ++++++ .../main/java/com/yahoo/test/PatternMatcher.java | 38 ++++++++ .../main/java/com/yahoo/test/TotalOrderTester.java | 37 ++++++++ .../test/java/com/yahoo/test/MatchersTestCase.java | 33 +++++++ .../test/java/com/yahoo/test/OrderTesterTest.java | 76 +++++++++++++++ .../com/yahoo/test/PatternMatchersTestCase.java | 40 ++++++++ 15 files changed, 605 insertions(+) create mode 100644 testutil/.gitignore create mode 100644 testutil/OWNERS create mode 100644 testutil/README create mode 100644 testutil/pom.xml create mode 100644 testutil/src/main/java/com/yahoo/test/CollectionPatternMatcher.java create mode 100644 testutil/src/main/java/com/yahoo/test/LinePatternMatcher.java create mode 100644 testutil/src/main/java/com/yahoo/test/ManualClock.java create mode 100644 testutil/src/main/java/com/yahoo/test/Matchers.java create mode 100644 testutil/src/main/java/com/yahoo/test/OrderTester.java create mode 100644 testutil/src/main/java/com/yahoo/test/PartialOrderTester.java create mode 100644 testutil/src/main/java/com/yahoo/test/PatternMatcher.java create mode 100644 testutil/src/main/java/com/yahoo/test/TotalOrderTester.java create mode 100644 testutil/src/test/java/com/yahoo/test/MatchersTestCase.java create mode 100644 testutil/src/test/java/com/yahoo/test/OrderTesterTest.java create mode 100644 testutil/src/test/java/com/yahoo/test/PatternMatchersTestCase.java (limited to 'testutil') diff --git a/testutil/.gitignore b/testutil/.gitignore new file mode 100644 index 00000000000..3cc25b51fc4 --- /dev/null +++ b/testutil/.gitignore @@ -0,0 +1,2 @@ +/pom.xml.build +/target diff --git a/testutil/OWNERS b/testutil/OWNERS new file mode 100644 index 00000000000..3b2ba1ede81 --- /dev/null +++ b/testutil/OWNERS @@ -0,0 +1 @@ +gjoranv diff --git a/testutil/README b/testutil/README new file mode 100644 index 00000000000..be3aed80ec4 --- /dev/null +++ b/testutil/README @@ -0,0 +1 @@ +Module for shared Java test utilities that require a compile scope dependency on Junit. \ No newline at end of file diff --git a/testutil/pom.xml b/testutil/pom.xml new file mode 100644 index 00000000000..cd20d0db597 --- /dev/null +++ b/testutil/pom.xml @@ -0,0 +1,47 @@ + + + + 4.0.0 + + com.yahoo.vespa + parent + 6-SNAPSHOT + ../parent/pom.xml + + testutil + jar + 6-SNAPSHOT + ${project.artifactId} + Library of useful Hamcrest matchers. + + + org.hamcrest + hamcrest-core + compile + + + org.hamcrest + hamcrest-library + compile + + + junit + junit + compile + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + -Xlint:all + + + + + + diff --git a/testutil/src/main/java/com/yahoo/test/CollectionPatternMatcher.java b/testutil/src/main/java/com/yahoo/test/CollectionPatternMatcher.java new file mode 100644 index 00000000000..12cf0f671f9 --- /dev/null +++ b/testutil/src/main/java/com/yahoo/test/CollectionPatternMatcher.java @@ -0,0 +1,45 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.test; + +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; +import org.hamcrest.Factory; +import org.hamcrest.Matcher; + +import java.util.Collection; + +/** + * Checks if a collection of strings contains at least one string with the expected regex pattern. + * + * @author gjoranv + * @since 5.1.8 + */ +public class CollectionPatternMatcher extends BaseMatcher> { + + private final String pattern; + + public CollectionPatternMatcher(String pattern) { + this.pattern = pattern; + } + + @Override + public void describeTo(Description description) { + description.appendText("contains a string that matches expression '" + pattern + "'"); + } + + @Override + public boolean matches(Object o) { + @SuppressWarnings("unchecked") + Collection strings = (Collection) o; + for (String s : strings) + if (s.matches(pattern)) + return true; + return false; + } + + @Factory + public static Matcher> containsStringWithPattern(String pattern) { + return new CollectionPatternMatcher(pattern); + } + +} diff --git a/testutil/src/main/java/com/yahoo/test/LinePatternMatcher.java b/testutil/src/main/java/com/yahoo/test/LinePatternMatcher.java new file mode 100644 index 00000000000..c1cb8e4032c --- /dev/null +++ b/testutil/src/main/java/com/yahoo/test/LinePatternMatcher.java @@ -0,0 +1,43 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.test; + +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; +import org.hamcrest.Factory; +import org.hamcrest.Matcher; + +/** + * Checks if a multi-line string contains at least one line with the expected regex pattern. + * + * @author gjoranv + * @since 5.1.7 + */ +public class LinePatternMatcher extends BaseMatcher { + + private final String pattern; + + public LinePatternMatcher(String pattern) { + this.pattern = pattern; + } + + @Override + public void describeTo(Description description) { + description.appendText("contains a line that matches expression '" + pattern + "'"); + } + + @Override + public boolean matches(Object o) { + String s = (String)o; + String[] lines = s.split("\n"); + for (String line : lines) + if (line.matches(pattern)) + return true; + return false; + } + + @Factory + public static Matcher containsLineWithPattern(String pattern) { + return new LinePatternMatcher(pattern); + } + +} \ No newline at end of file diff --git a/testutil/src/main/java/com/yahoo/test/ManualClock.java b/testutil/src/main/java/com/yahoo/test/ManualClock.java new file mode 100644 index 00000000000..b8325b3e3fc --- /dev/null +++ b/testutil/src/main/java/com/yahoo/test/ManualClock.java @@ -0,0 +1,36 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.test; + +import java.time.Clock; +import java.time.Instant; +import java.time.ZoneId; +import java.time.temporal.TemporalAmount; + +/** A clock which initially has the time of its creation but can only be advanced by calling advance */ +public class ManualClock extends Clock { + + private Instant currentTime = Instant.now(); + + public ManualClock() {} + + public ManualClock(Instant currentTime) { + this.currentTime = currentTime; + } + + public void advance(TemporalAmount temporal) { + currentTime = currentTime.plus(temporal); + } + + @Override + public Instant instant() { return currentTime; } + + @Override + public ZoneId getZone() { return null; } + + @Override + public Clock withZone(ZoneId zone) { return null; } + + @Override + public long millis() { return currentTime.toEpochMilli(); } + +} diff --git a/testutil/src/main/java/com/yahoo/test/Matchers.java b/testutil/src/main/java/com/yahoo/test/Matchers.java new file mode 100644 index 00000000000..80e01b43a18 --- /dev/null +++ b/testutil/src/main/java/com/yahoo/test/Matchers.java @@ -0,0 +1,104 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.test; + +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; + +import java.lang.reflect.Method; + +/** + * Some useful matchers. + * + * @author Einar M R Rosenvinge + */ +public final class Matchers { + + /** + * A match is found if at least one item in the Iterable has the given method, and the return value + * when calling it equals the given expected value. + * + * @param expected The expected value. + * @param methodName The name of the method to call. The method must take no parameters. + * @return A Matcher to match against an Iterable. + */ + @SuppressWarnings("rawtypes") + public static org.hamcrest.Matcher hasItemWithMethod(final Object expected, final String methodName) { + return hasItemWithMethod(new MethodResult(methodName, expected)); + } + + /** + * A match is found if at least one item in the Iterable has all given methods, and + * the return values when calling them equals the given expected values. + * + * @param results The pairs of method names and expected results to compare. + * @return A Matcher to match against an Iterable. + */ + @SuppressWarnings("rawtypes") + public static org.hamcrest.Matcher hasItemWithMethod(final MethodResult... results) { + return new BaseMatcher() { + @Override + public boolean matches(Object item) { + Iterable components = (Iterable) item; + if (!components.iterator().hasNext()) { + //empty collection + return false; + } + for (Object componentInList : components) { + boolean allMethodsMatch = false; + for (MethodResult result : results) { + Object strToMatch; + try { + Method method = componentInList.getClass().getMethod(result.getMethodName()); + strToMatch = method.invoke(componentInList); + } catch (Exception e) { + allMethodsMatch = false; + break; + } + if (result.getExpectedResult().equals(strToMatch)) { + allMethodsMatch = true; + } else { + allMethodsMatch = false; + break; + } + } + if (allMethodsMatch) { + return true; + } + } + return false; + } + + @Override + public void describeTo(Description description) { + StringBuilder b = new StringBuilder(); + for (MethodResult result : results) { + b.append(result).append(". "); + } + description.appendText(b.toString()); + } + }; + } + + public static final class MethodResult { + private final String methodName; + private final Object expectedResult; + + public MethodResult(String methodName, Object expectedResult) { + this.methodName = methodName; + this.expectedResult = expectedResult; + } + + public Object getExpectedResult() { + return expectedResult; + } + + public String getMethodName() { + return methodName; + } + + @Override + public String toString() { + return "Method: '" + methodName + "\', expected result: '" + expectedResult + '\''; + } + } +} diff --git a/testutil/src/main/java/com/yahoo/test/OrderTester.java b/testutil/src/main/java/com/yahoo/test/OrderTester.java new file mode 100644 index 00000000000..8e001761164 --- /dev/null +++ b/testutil/src/main/java/com/yahoo/test/OrderTester.java @@ -0,0 +1,73 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * OrderTester is a an abstract helper class in the spirit of EqualsTester that + * tests an objects total or partial ordering with respect to T#compareTo. + * + * @author Vegard Sjonfjell + * @see com.yahoo.test.TotalOrderTester + * @see com.yahoo.test.PartialOrderTester + * + */ + +public abstract class OrderTester> { + private ArrayList> groups = new ArrayList<>(); + + abstract protected void lessTest(T a, T b); + abstract protected void greaterTest(T a, T b); + abstract protected void equalTest(T a, T b); + + @SafeVarargs + private final OrderTester addGroup(T... group) { + groups.add(Arrays.asList(group)); + return this; + } + + /** + * Add group of objects being "less" (wrt. compareTo) than all the objects which follow. + * @param group group of objects + * @return the {@link OrderTester} instance, for method chaining + */ + @SafeVarargs + public final OrderTester theseObjects(T... group) { + return addGroup(group); + } + + /** + * Add group of objects being "less" (wrt. compareTo) than all the objects which follow. + * @param group group of objects + * @return the {@link OrderTester} instance, for method chaining + */ + @SafeVarargs + public final OrderTester areLessThan(T... group) { + return addGroup(group); + } + + /** + * Test the ordering defined with {@link OrderTester#theseObjects} and {@link OrderTester#areLessThan} + * with respect to T#compareTo and the {@link OrderTester} subclass (e.g. {@link com.yahoo.test.TotalOrderTester}). + */ + public void testOrdering() { + for (int i = 0; i < groups.size(); i++) { + for (T item : groups.get(i)) { + for (T otherItem : groups.get(i)) { + equalTest(item, otherItem); + } + } + + for (int j = i+1; j < groups.size(); j++) { + for (T lessItem : groups.get(i)) { + for (T greaterItem : groups.get(j)) { + lessTest(lessItem, greaterItem); + greaterTest(greaterItem, lessItem); + } + } + } + } + } +} diff --git a/testutil/src/main/java/com/yahoo/test/PartialOrderTester.java b/testutil/src/main/java/com/yahoo/test/PartialOrderTester.java new file mode 100644 index 00000000000..61ee538a815 --- /dev/null +++ b/testutil/src/main/java/com/yahoo/test/PartialOrderTester.java @@ -0,0 +1,29 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.test; + +import static org.junit.Assert.assertThat; +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.Matchers.lessThanOrEqualTo; +import static org.hamcrest.Matchers.greaterThanOrEqualTo; + +/** + * PartialOrderTester implements a partial order test for OrderTester + * + * Usage: see {@link com.yahoo.test.TotalOrderTester} + * + * @author Vegard Sjonfjell + */ + +public class PartialOrderTester> extends OrderTester { + protected void lessTest(T a, T b) throws AssertionError { + assertThat(a + " must be less than or equal to " + b, a.compareTo(b), lessThanOrEqualTo(0)); + } + + protected void greaterTest(T a, T b) throws AssertionError { + assertThat(a + " must be greater than or equal to " + b, a.compareTo(b), greaterThanOrEqualTo(0)); + } + + protected void equalTest(T a, T b) throws AssertionError { + assertThat(a + " must be compared equal to " + b, a.compareTo(b), is(0)); + } +} diff --git a/testutil/src/main/java/com/yahoo/test/PatternMatcher.java b/testutil/src/main/java/com/yahoo/test/PatternMatcher.java new file mode 100644 index 00000000000..84cc94e32a2 --- /dev/null +++ b/testutil/src/main/java/com/yahoo/test/PatternMatcher.java @@ -0,0 +1,38 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.test; + +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; +import org.hamcrest.Factory; +import org.hamcrest.Matcher; + +/** + * Matches a string against an expected regex pattern. + * + * @author gjoranv + * @since 5.1.7 + */ +public class PatternMatcher extends BaseMatcher { + + private final String pattern; + + public PatternMatcher(String pattern) { + this.pattern = pattern; + } + + @Override + public void describeTo(Description description) { + description.appendText("matches expression '" + pattern + "'"); + } + + @Override + public boolean matches(Object o) { + return ((String)o).matches(pattern); + } + + @Factory + public static Matcher matchesPattern(String pattern) { + return new PatternMatcher(pattern); + } + +} \ No newline at end of file diff --git a/testutil/src/main/java/com/yahoo/test/TotalOrderTester.java b/testutil/src/main/java/com/yahoo/test/TotalOrderTester.java new file mode 100644 index 00000000000..bc9bb1494fa --- /dev/null +++ b/testutil/src/main/java/com/yahoo/test/TotalOrderTester.java @@ -0,0 +1,37 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.test; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.hamcrest.Matchers.lessThanOrEqualTo; +import static org.hamcrest.Matchers.greaterThanOrEqualTo; + +/** + * TotalOrderTester implements a total order test for OrderTester + * + * Usage: + * + * new TotalOrderTester<Integer>() + * .theseObjects(3, 3) + * .areLessThan(4) + * .areLessThan(5) + * .areLessThan(6) + * .testOrdering(); + * + * + * @author Vegard Sjonfjell + */ + +public class TotalOrderTester> extends OrderTester { + protected void lessTest(T a, T b) throws AssertionError { + assertThat(a + " must be less than " + b, a.compareTo(b), lessThanOrEqualTo(-1)); + } + + protected void greaterTest(T a, T b) throws AssertionError { + assertThat(a + " must be greater than " + b, a.compareTo(b), greaterThanOrEqualTo(1)); + } + + protected void equalTest(T a, T b) throws AssertionError { + assertThat(a + " must be compared equal to " + b, a.compareTo(b), is(0)); + } +} diff --git a/testutil/src/test/java/com/yahoo/test/MatchersTestCase.java b/testutil/src/test/java/com/yahoo/test/MatchersTestCase.java new file mode 100644 index 00000000000..c560a0e0624 --- /dev/null +++ b/testutil/src/test/java/com/yahoo/test/MatchersTestCase.java @@ -0,0 +1,33 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.test; + +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; + +import org.hamcrest.Matcher; +import org.junit.Test; + +/** + * Tests for com.yahoo.test.Matchers. + * + * @author Steinar Knutsen + */ +public class MatchersTestCase { + + @Test + public final void testHasItemWithMethodObjectString() { + @SuppressWarnings("rawtypes") + final Matcher m = Matchers.hasItemWithMethod("nalle", + "toLowerCase"); + assertEquals( + false, + m.matches(Arrays.asList(new Object[] { Integer.valueOf(1), + Character.valueOf('c'), "blbl" }))); + assertEquals( + true, + m.matches(Arrays.asList(new Object[] { Character.valueOf('c'), + "NALLE" }))); + } + +} diff --git a/testutil/src/test/java/com/yahoo/test/OrderTesterTest.java b/testutil/src/test/java/com/yahoo/test/OrderTesterTest.java new file mode 100644 index 00000000000..a9e4212ffc7 --- /dev/null +++ b/testutil/src/test/java/com/yahoo/test/OrderTesterTest.java @@ -0,0 +1,76 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.test; + +import org.junit.Test; + +/** + * @author Vegard Sjonfjell + */ +public class OrderTesterTest { + private class PartialInt implements Comparable { + int value; + + public PartialInt(int value) { + this.value = value; + } + + @Override + public int compareTo(PartialInt other) { + if (Math.abs(value - other.value) < 3) { + return 0; + } + else if (value > other.value) { + return 1; + } + else if (value < other.value) { + return 1; + } + + return 0; + } + + @Override + public String toString() { + return Integer.toString(value); + } + } + + @Test + public void testTotalOrderTester() { + new TotalOrderTester() + .theseObjects(3, 3) + .areLessThan(4) + .areLessThan(5) + .areLessThan(6) + .testOrdering(); + } + + @Test + public void testPartialOrderTester() { + new PartialOrderTester() + .theseObjects(new PartialInt(3)) + .areLessThan(new PartialInt(3), new PartialInt(3)) + .areLessThan(new PartialInt(4)) + .areLessThan(new PartialInt(4)) + .areLessThan(new PartialInt(5)) + .testOrdering(); + } + + @Test (expected = AssertionError.class) + public void testTotalOrderTesterFailsOnIncorrectOrdering() { + new TotalOrderTester() + .theseObjects(3) + .areLessThan(2) + .areLessThan(5) + .testOrdering(); + } + + @Test (expected = AssertionError.class) + public void testPartialOrderTesterFailsOnIncorrectOrdering() { + new PartialOrderTester() + .theseObjects(new PartialInt(6)) + .areLessThan(new PartialInt(2)) + .areLessThan(new PartialInt(3)) + .testOrdering(); + } +} diff --git a/testutil/src/test/java/com/yahoo/test/PatternMatchersTestCase.java b/testutil/src/test/java/com/yahoo/test/PatternMatchersTestCase.java new file mode 100644 index 00000000000..6c9eac53fb1 --- /dev/null +++ b/testutil/src/test/java/com/yahoo/test/PatternMatchersTestCase.java @@ -0,0 +1,40 @@ +// Copyright 2016 Yahoo Inc. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.test; + +import static org.junit.Assert.*; + +import java.util.Arrays; + +import org.junit.Test; + +/** + * Check CollectionPatternMatcher, LinePatternMatcher and PatternMatcher. + * + * @author Steinar Knutsen + */ +public class PatternMatchersTestCase { + + @Test + public final void testCollections() { + CollectionPatternMatcher cm = new CollectionPatternMatcher("a.*"); + String[] coll = new String[] {}; + assertEquals(false, cm.matches(Arrays.asList(coll))); + coll = new String[] { "ba", "ab" }; + assertEquals(true, cm.matches(Arrays.asList(coll))); + } + + @Test + public final void testLines() { + LinePatternMatcher lp = new LinePatternMatcher("a"); + assertEquals(true, lp.matches("a\nab")); + assertEquals(false, lp.matches("ab\nb")); + } + + @Test + public final void testPatterns() { + PatternMatcher m = new PatternMatcher(".*a.*"); + assertEquals(true, m.matches("ab")); + assertEquals(false, m.matches("b")); + } + +} -- cgit v1.2.3