killbill-uncached

util: fix ClockMock implementation The clock was stuck in

4/26/2013 2:33:37 PM

Details

diff --git a/server/src/test/java/com/ning/billing/jaxrs/TestJaxrsBase.java b/server/src/test/java/com/ning/billing/jaxrs/TestJaxrsBase.java
index e132e4e..62e7f91 100644
--- a/server/src/test/java/com/ning/billing/jaxrs/TestJaxrsBase.java
+++ b/server/src/test/java/com/ning/billing/jaxrs/TestJaxrsBase.java
@@ -220,7 +220,7 @@ public class TestJaxrsBase extends KillbillClient {
     public void beforeMethod() throws Exception {
         super.beforeMethod();
         busHandler.reset();
-        clock.reset();
+        clock.resetDeltaFromReality();
         clock.setDay(new LocalDate(2012, 8, 25));
     }
 
diff --git a/util/src/test/java/com/ning/billing/util/clock/ClockMock.java b/util/src/test/java/com/ning/billing/util/clock/ClockMock.java
index 5891471..1661769 100644
--- a/util/src/test/java/com/ning/billing/util/clock/ClockMock.java
+++ b/util/src/test/java/com/ning/billing/util/clock/ClockMock.java
@@ -21,7 +21,6 @@ import org.joda.time.DateTimeZone;
 import org.joda.time.Days;
 import org.joda.time.LocalDate;
 import org.joda.time.Months;
-import org.joda.time.MutablePeriod;
 import org.joda.time.Period;
 import org.joda.time.ReadablePeriod;
 import org.joda.time.Weeks;
@@ -29,18 +28,16 @@ import org.joda.time.Years;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.ning.billing.catalog.api.Duration;
-import com.ning.billing.catalog.api.TimeUnit;
-
 public class ClockMock implements Clock {
 
-    private MutablePeriod delta = new MutablePeriod();
-
-
-    private DateTime mockDateTime = now();
+    private static final Logger log = LoggerFactory.getLogger(ClockMock.class);
 
+    private DateTime mockDateTime;
+    private long initialDeltaMillis;
 
-    private static final Logger log = LoggerFactory.getLogger(ClockMock.class);
+    public ClockMock() {
+        reset();
+    }
 
     @Override
     public synchronized DateTime getNow(final DateTimeZone tz) {
@@ -49,7 +46,7 @@ public class ClockMock implements Clock {
 
     @Override
     public synchronized DateTime getUTCNow() {
-        return truncate(adjust(now()));
+        return truncate(mockDateTime.plus(System.currentTimeMillis() - initialDeltaMillis));
     }
 
     @Override
@@ -62,26 +59,12 @@ public class ClockMock implements Clock {
         return new LocalDate(getUTCNow(), timeZone);
     }
 
-    private DateTime adjust(final DateTime now) {
-        //return now.plus(delta);
-        return mockDateTime;
-    }
-
-    public synchronized void setTime(final DateTime time) {
-        final DateTime prev = getUTCNow();
-        delta = new MutablePeriod(now(), time);
-
-        mockDateTime = time;
-
-        logChange(prev);
-    }
-
-    public synchronized void setDay(final LocalDate date) {
-        setTime(date.toDateTimeAtStartOfDay(DateTimeZone.UTC));
+    @Override
+    public String toString() {
+        return getUTCNow().toString();
     }
 
     public synchronized void addDays(final int days) {
-
         adjustTo(Days.days(days));
     }
 
@@ -97,84 +80,54 @@ public class ClockMock implements Clock {
         adjustTo(Years.years(years));
     }
 
-    public synchronized void reset() {
-        mockDateTime = now();
-        delta = new MutablePeriod();
+    public synchronized void setDeltaFromReality(final long delta) {
+        resetDeltaFromReality();
+        addDeltaFromReality(delta);
     }
 
-    @Override
-    public String toString() {
-        return getUTCNow().toString();
+    public synchronized void addDeltaFromReality(final long delta) {
+        adjustTo(new Period(delta));
     }
 
-    private void adjustTo(final ReadablePeriod period) {
-        final DateTime prev = getUTCNow();
+    public synchronized void setDay(final LocalDate date) {
+        setTime(date.toDateTimeAtStartOfDay(DateTimeZone.UTC));
+    }
 
-        //deltaFromDelta
-        delta.add(period);
-        mockDateTime =  mockDateTime.plus(period);
+    public synchronized void setTime(final DateTime time) {
+        final DateTime prev = getUTCNow();
+        reset(time);
         logChange(prev);
     }
 
-    private void logChange(final DateTime prev) {
-        final DateTime now = getUTCNow();
-        log.info(String.format("            ************      ADJUSTING CLOCK FROM %s to %s     ********************", prev, now));
+    public synchronized void resetDeltaFromReality() {
+        reset();
     }
 
-    private DateTime now() {
-        return new DateTime(DateTimeZone.UTC);
+    private synchronized void reset() {
+        reset(realNow());
     }
 
-    private DateTime truncate(final DateTime time) {
-        return time.minus(time.getMillisOfSecond());
+    private void reset(final DateTime time) {
+        mockDateTime = time;
+        initialDeltaMillis = System.currentTimeMillis();
     }
 
-    //
-    //Backward compatibility stuff
-    //
-    public synchronized void setDeltaFromReality(final Duration duration, final long epsilon) {
+    private void adjustTo(final ReadablePeriod period) {
         final DateTime prev = getUTCNow();
-        delta.addMillis((int) epsilon);
-
-        mockDateTime = mockDateTime.plus(epsilon);
-
-        addDeltaFromReality(duration);
+        mockDateTime = mockDateTime.plus(period);
         logChange(prev);
-
     }
 
-    public synchronized void addDeltaFromReality(final Duration delta) {
-        adjustTo(periodFromDuration(delta));
-    }
-
-    public synchronized void setDeltaFromReality(final long delta) {
-        adjustTo(new Period(delta));
-    }
-
-    public synchronized void addDeltaFromReality(final long delta) {
-        adjustTo(new Period(delta));
+    private void logChange(final DateTime prev) {
+        final DateTime now = getUTCNow();
+        log.info(String.format("            ************      ADJUSTING CLOCK FROM %s to %s     ********************", prev, now));
     }
 
-    public synchronized void resetDeltaFromReality() {
-        reset();
+    private DateTime truncate(final DateTime time) {
+        return time.minus(time.getMillisOfSecond());
     }
 
-    public ReadablePeriod periodFromDuration(final Duration duration) {
-        if (duration.getUnit() != TimeUnit.UNLIMITED) {
-            return new Period();
-        }
-
-        switch (duration.getUnit()) {
-            case DAYS:
-                return Days.days(duration.getNumber());
-            case MONTHS:
-                return Months.months(duration.getNumber());
-            case YEARS:
-                return Years.years(duration.getNumber());
-            case UNLIMITED:
-                return Years.years(100);
-            default:
-                return new Period();
-        }
+    private DateTime realNow() {
+        return new DateTime(DateTimeZone.UTC);
     }
 }
diff --git a/util/src/test/java/com/ning/billing/util/clock/TestClockMock.java b/util/src/test/java/com/ning/billing/util/clock/TestClockMock.java
new file mode 100644
index 0000000..ad5e9db
--- /dev/null
+++ b/util/src/test/java/com/ning/billing/util/clock/TestClockMock.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright 2010-2013 Ning, Inc.
+ *
+ * Ning 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.ning.billing.util.clock;
+
+import java.util.concurrent.Callable;
+
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+import org.joda.time.LocalDate;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.ning.billing.util.UtilTestSuiteNoDB;
+
+import com.jayway.awaitility.Awaitility;
+
+import static java.util.concurrent.TimeUnit.MILLISECONDS;
+
+public class TestClockMock extends UtilTestSuiteNoDB {
+
+    @Test(groups = "fast")
+    public void testBasicClockOperations() throws Exception {
+        final ClockMock clock = new ClockMock();
+
+        final DateTime startingTime = new DateTime(DateTimeZone.UTC);
+        // Lame, but required due to the truncation magic
+        Awaitility.await().atMost(999, MILLISECONDS).until(new Callable<Boolean>() {
+            @Override
+            public Boolean call() throws Exception {
+                return clock.getUTCNow().isAfter(startingTime);
+            }
+        });
+
+        clock.setTime(new DateTime(2012, 5, 1, 1, 2, 3, DateTimeZone.UTC));
+        Assert.assertEquals(clock.getUTCToday(), new LocalDate(2012, 5, 1));
+        final DateTime utcNowAfterSetTime = clock.getUTCNow();
+        Assert.assertEquals(utcNowAfterSetTime.getHourOfDay(), 1);
+        Assert.assertEquals(utcNowAfterSetTime.getMinuteOfHour(), 2);
+        Assert.assertEquals(utcNowAfterSetTime.getSecondOfMinute(), 3);
+
+        clock.addDays(1);
+        Assert.assertEquals(clock.getUTCToday(), new LocalDate(2012, 5, 2));
+
+        clock.addMonths(1);
+        Assert.assertEquals(clock.getUTCToday(), new LocalDate(2012, 6, 2));
+
+        clock.addYears(1);
+        Assert.assertEquals(clock.getUTCToday(), new LocalDate(2013, 6, 2));
+
+        clock.setDay(new LocalDate(2045, 12, 12));
+        Assert.assertEquals(clock.getUTCToday(), new LocalDate(2045, 12, 12));
+
+        clock.resetDeltaFromReality();
+        Assert.assertTrue(clock.getUTCNow().isAfter(startingTime));
+        Assert.assertTrue(clock.getUTCNow().isBefore(startingTime.plusMinutes(1)));
+    }
+}