1c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffinpackage org.hamcrest.number; 2c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin 3c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffinimport org.hamcrest.Description; 4c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffinimport org.hamcrest.Matcher; 5c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffinimport org.hamcrest.TypeSafeMatcher; 6c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin 7c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffinimport java.math.BigDecimal; 8c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffinimport java.math.MathContext; 9c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin 10c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffinpublic class BigDecimalCloseTo extends TypeSafeMatcher<BigDecimal> { 11c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin 12c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin private final BigDecimal delta; 13c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin private final BigDecimal value; 14c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin 15c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin public BigDecimalCloseTo(BigDecimal value, BigDecimal error) { 16c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin this.delta = error; 17c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin this.value = value; 18c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin } 19c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin 20c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin @Override 21c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin public boolean matchesSafely(BigDecimal item) { 22c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin return actualDelta(item).compareTo(BigDecimal.ZERO) <= 0; 23c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin } 24c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin 25c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin @Override 26c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin public void describeMismatchSafely(BigDecimal item, Description mismatchDescription) { 27c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin mismatchDescription.appendValue(item) 28c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin .appendText(" differed by ") 29c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin .appendValue(actualDelta(item)) 30c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin .appendText(" more than delta ") 31c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin .appendValue(delta); 32c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin } 33c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin 34c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin @Override 35c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin public void describeTo(Description description) { 36c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin description.appendText("a numeric value within ") 37c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin .appendValue(delta) 38c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin .appendText(" of ") 39c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin .appendValue(value); 40c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin } 41c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin 42c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin private BigDecimal actualDelta(BigDecimal item) { 43c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin return item.subtract(value, MathContext.DECIMAL128).abs().subtract(delta, MathContext.DECIMAL128).stripTrailingZeros(); 44c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin } 45c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin 46c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin /** 47c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin * Creates a matcher of {@link java.math.BigDecimal}s that matches when an examined BigDecimal is equal 48c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin * to the specified <code>operand</code>, within a range of +/- <code>error</code>. The comparison for equality 49c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin * is done by BigDecimals {@link java.math.BigDecimal#compareTo(java.math.BigDecimal)} method. 50c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin * For example: 51c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin * <pre>assertThat(new BigDecimal("1.03"), is(closeTo(new BigDecimal("1.0"), new BigDecimal("0.03"))))</pre> 52c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin * 53c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin * @param operand 54c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin * the expected value of matching BigDecimals 55c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin * @param error 56c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin * the delta (+/-) within which matches will be allowed 57c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin */ 58c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin public static Matcher<BigDecimal> closeTo(BigDecimal operand, BigDecimal error) { 59c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin return new BigDecimalCloseTo(operand, error); 60c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin } 61c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin 62c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin} 63c1dbb44e71e47410ad5685aba3ef3fccb095a2b4Paul Duffin 64