IsActualWithinToleranceOfExpectedTimestampValueComparer.java

  1. package org.dbunit.assertion.comparer.value;

  2. import static org.junit.jupiter.api.Assertions.assertNotNull;

  3. import java.sql.Timestamp;

  4. import org.dbunit.DatabaseUnitException;
  5. import org.dbunit.dataset.ITable;
  6. import org.dbunit.dataset.datatype.DataType;
  7. import org.dbunit.dataset.datatype.TypeCastException;
  8. import org.slf4j.Logger;
  9. import org.slf4j.LoggerFactory;

  10. /**
  11.  * {@link ValueComparer} implementation for {@link Timestamp}s that verifies
  12.  * actual value is within a low and high milliseconds tolerance range of
  13.  * expected value.
  14.  *
  15.  * Note: If actual and expected values are both null, the comparison passes.
  16.  *
  17.  * @author Jeff Jensen
  18.  * @since 2.6.0
  19.  */
  20. public class IsActualWithinToleranceOfExpectedTimestampValueComparer
  21.         extends ValueComparerTemplateBase
  22. {
  23.     private final Logger log = LoggerFactory.getLogger(getClass());

  24.     public static final long ONE_SECOND_IN_MILLIS = 1000;
  25.     public static final long TWO_SECONDS_IN_MILLIS = ONE_SECOND_IN_MILLIS * 2;
  26.     public static final long THREE_SECONDS_IN_MILLIS = ONE_SECOND_IN_MILLIS * 3;
  27.     public static final long FOUR_SECONDS_IN_MILLIS = ONE_SECOND_IN_MILLIS * 4;
  28.     public static final long FIVE_SECONDS_IN_MILLIS = ONE_SECOND_IN_MILLIS * 5;

  29.     public static final long ONE_MINUTE_IN_MILLIS = ONE_SECOND_IN_MILLIS * 60;
  30.     public static final long TWO_MINUTES_IN_MILLIS = ONE_MINUTE_IN_MILLIS * 2;
  31.     public static final long THREE_MINUTES_IN_MILLIS = ONE_MINUTE_IN_MILLIS * 3;
  32.     public static final long FOUR_MINUTES_IN_MILLIS = ONE_MINUTE_IN_MILLIS * 4;
  33.     public static final long FIVE_MINUTES_IN_MILLIS = ONE_MINUTE_IN_MILLIS * 5;
  34.     public static final long TEN_MINUTES_IN_MILLIS = ONE_MINUTE_IN_MILLIS * 10;

  35.     private long lowToleranceValueInMillis;
  36.     private long highToleranceValueInMillis;

  37.     /**
  38.      * Create instance specifying the allowed actual time difference range from
  39.      * expected.
  40.      *
  41.      * @param lowToleranceValueInMillis
  42.      *            The minimum time difference allowed.
  43.      * @param highToleranceValueInMillis
  44.      *            The maximum time difference allowed.
  45.      */
  46.     public IsActualWithinToleranceOfExpectedTimestampValueComparer(
  47.             final long lowToleranceValueInMillis,
  48.             final long highToleranceValueInMillis)
  49.     {
  50.         this.lowToleranceValueInMillis = lowToleranceValueInMillis;
  51.         this.highToleranceValueInMillis = highToleranceValueInMillis;
  52.     }

  53.     @Override
  54.     protected boolean isExpected(final ITable expectedTable,
  55.             final ITable actualTable, final int rowNum, final String columnName,
  56.             final DataType dataType, final Object expectedValue,
  57.             final Object actualValue) throws DatabaseUnitException
  58.     {
  59.         final boolean isExpected;

  60.         // handle nulls: prevent NPE and isExpected=true when both null
  61.         if (expectedValue == null || actualValue == null)
  62.         {
  63.             isExpected = isExpectedWithNull(expectedValue, actualValue);
  64.         } else
  65.         {
  66.             isExpected =
  67.                     isExpectedWithoutNull(expectedValue, actualValue, dataType);
  68.         }

  69.         return isExpected;
  70.     }

  71.     /** Since one is a known null, isExpected=true when they equal. */
  72.     protected boolean isExpectedWithNull(final Object expectedValue,
  73.             final Object actualValue)
  74.     {
  75.         final boolean isExpected = expectedValue == actualValue;

  76.         log.debug("isExpectedWithNull: {}, actualValue={}, expectedValue={}",
  77.                 isExpected, actualValue, expectedValue);

  78.         return isExpected;
  79.     }

  80.     /** Neither is null so compare values with tolerance. */
  81.     protected boolean isExpectedWithoutNull(final Object expectedValue, final Object actualValue,
  82.             final DataType dataType) throws TypeCastException {
  83.         assertNotNull(expectedValue, "expectedValue is null.");
  84.         assertNotNull(actualValue, "actualValue is null.");

  85.         final Object actualTimestamp = getCastedValue(actualValue, dataType);
  86.         final long actualTime = convertValueToTimeInMillis(actualTimestamp);

  87.         final Object expectedTimestamp =
  88.                 getCastedValue(expectedValue, dataType);
  89.         final long expectedTime = convertValueToTimeInMillis(expectedTimestamp);

  90.         final long diffTime = calcTimeDifference(actualTime, expectedTime);
  91.         return isTolerant(diffTime);
  92.     }

  93.     protected Object getCastedValue(final Object value, final DataType type)
  94.             throws TypeCastException
  95.     {
  96.         final Object castedValue;

  97.         if (type == null || type == DataType.UNKNOWN)
  98.         {
  99.             castedValue = value;
  100.         } else
  101.         {
  102.             castedValue = type.typeCast(value);
  103.         }

  104.         return castedValue;
  105.     }

  106.     protected boolean isTolerant(final long diffTime)
  107.     {
  108.         final boolean isLowTolerant = diffTime >= lowToleranceValueInMillis;
  109.         final boolean isHighTolerant = diffTime <= highToleranceValueInMillis;
  110.         final boolean isTolerant = isLowTolerant && isHighTolerant;

  111.         log.debug(
  112.                 "isTolerant: {},"
  113.                         + " diffTime={}, lowToleranceValueInMillis={},"
  114.                         + " highToleranceValueInMillis={}",
  115.                 isTolerant, diffTime, lowToleranceValueInMillis,
  116.                 highToleranceValueInMillis);

  117.         return isTolerant;
  118.     }

  119.     protected long convertValueToTimeInMillis(final Object timestampValue)
  120.     {
  121.         final Timestamp timestamp = (Timestamp) timestampValue;
  122.         return timestamp.getTime();
  123.     }

  124.     protected long calcTimeDifference(final long actualTimeInMillis,
  125.             final long expectedTimeInMillis)
  126.     {
  127.         final long diffTime = actualTimeInMillis - expectedTimeInMillis;
  128.         final long diffTimeAbs = Math.abs(diffTime);
  129.         log.debug(
  130.                 "calcTimeDifference: "
  131.                         + "actualTimeInMillis={}, expectedTimeInMillis={},"
  132.                         + " diffInMillisTime={}, diffTimeInMillisAbs={}",
  133.                 actualTimeInMillis, expectedTimeInMillis, diffTime,
  134.                 diffTimeAbs);

  135.         return diffTimeAbs;
  136.     }

  137.     @Override
  138.     protected String getFailPhrase()
  139.     {
  140.         return "not within tolerance range of " + lowToleranceValueInMillis
  141.                 + " - " + highToleranceValueInMillis + " milliseconds of";
  142.     }
  143. }