killbill-memoizeit

subscription: Add unit tests for subscription BCD efective

1/4/2017 9:09:48 PM

Details

diff --git a/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java b/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java
index 877aeb1..b190af1 100644
--- a/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java
+++ b/subscription/src/main/java/org/killbill/billing/subscription/api/svcs/DefaultSubscriptionInternalApi.java
@@ -101,6 +101,7 @@ import org.killbill.notificationq.api.NotificationQueueService.NoSuchNotificatio
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Function;
 import com.google.common.base.Predicate;
 import com.google.common.collect.Collections2;
@@ -762,7 +763,8 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
         }
     }
 
-    private DateTime getEffectiveDateForNewBCD(final int bcd, @Nullable final LocalDate effectiveFromDate, final InternalCallContext internalCallContext) {
+    @VisibleForTesting
+    DateTime getEffectiveDateForNewBCD(final int bcd, @Nullable final LocalDate effectiveFromDate, final InternalCallContext internalCallContext) {
         if (internalCallContext.getAccountRecordId() == null) {
             throw new IllegalStateException("Need to have a valid context with accountRecordId");
         }
@@ -782,7 +784,7 @@ public class DefaultSubscriptionInternalApi extends SubscriptionApiBase implemen
             final int lastDayOfNextMonth = startDatePlusOneMonth.dayOfMonth().getMaximumValue();
             final int originalBCDORLastDayOfMonth = bcd <= lastDayOfNextMonth ? bcd : lastDayOfNextMonth;
             requestedDate = new LocalDate(startDatePlusOneMonth.getYear(), startDatePlusOneMonth.getMonthOfYear(), originalBCDORLastDayOfMonth);
-        } else if (bcd == currentDay) {
+        } else if (bcd == currentDay && effectiveFromDate == null) {
             // will default to immediate event
             requestedDate = null;
         } else if (bcd <= lastDayOfMonth) {
diff --git a/subscription/src/test/java/org/killbill/billing/subscription/api/svcs/TestEffectiveDateForNewBCD.java b/subscription/src/test/java/org/killbill/billing/subscription/api/svcs/TestEffectiveDateForNewBCD.java
new file mode 100644
index 0000000..f00851a
--- /dev/null
+++ b/subscription/src/test/java/org/killbill/billing/subscription/api/svcs/TestEffectiveDateForNewBCD.java
@@ -0,0 +1,234 @@
+/*
+ * Copyright 2014-2017 Groupon, Inc
+ * Copyright 2014-2017 The Billing Project, LLC
+ *
+ * The Billing Project 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 org.killbill.billing.subscription.api.svcs;
+
+import org.joda.time.DateTime;
+import org.joda.time.LocalDate;
+import org.killbill.billing.subscription.SubscriptionTestSuiteNoDB;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+//
+// Test all possible combinations of input effectiveDate and new BCD:
+// (We call ComputedEffectiveDay the original day in the month extracted from the input effectiveDate)
+//
+// - effectiveDate = {null (present), past, future}
+// - newBCD {< ComputedEffectiveDay, equals ComputedEffectiveDay, > ComputedEffectiveDay, > End Of Month}
+//
+//    => 12 possible tests
+//
+public class TestEffectiveDateForNewBCD extends SubscriptionTestSuiteNoDB {
+
+    @Test(groups = "fast")
+    public void testNullEffectiveDateWithBCDPriorComputedEffectiveDay() throws Exception {
+
+        // Set by test as : 2012-05-07T00:03:42.000Z
+        final DateTime now = clock.getUTCNow();
+
+        int newBCD = 3;
+        // effectiveDate = 2012-05-07T00:03:42.000Z => ComputedEffectiveDay = 7
+        LocalDate effectiveDate = null;
+
+        // newBCD < ComputedEffectiveDay
+        final DateTime result = ((DefaultSubscriptionInternalApi) subscriptionInternalApi).getEffectiveDateForNewBCD(newBCD, effectiveDate, internalCallContext);
+
+        Assert.assertEquals(result, internalCallContext.toUTCDateTime(new LocalDate("2012-06-03")));
+    }
+
+    @Test(groups = "fast")
+    public void testNullEffectiveDateWithBCDEqualsComputedEffectiveDay() throws Exception {
+
+        // Set by test as : 2012-05-07T00:03:42.000Z
+        final DateTime now = clock.getUTCNow();
+
+        int newBCD = 7;
+        // effectiveDate = 2012-05-07T00:03:42.000Z => ComputedEffectiveDay = 7
+        LocalDate effectiveDate = null;
+
+        // newBCD == ComputedEffectiveDay
+        final DateTime result = ((DefaultSubscriptionInternalApi) subscriptionInternalApi).getEffectiveDateForNewBCD(newBCD, effectiveDate, internalCallContext);
+
+        final DateTime nowAfterCall = clock.getUTCNow();
+
+        // In that case because we want the event to fire right NOW, we don't use the account reference time but instead use the clock.getUTCNOW(). In case test
+        // takes longer than 1 mSec we need to check a (very small) range of dates
+        Assert.assertTrue(result.compareTo(now) >= 0);
+        Assert.assertTrue(result.compareTo(nowAfterCall) <= 0);
+    }
+
+    @Test(groups = "fast")
+    public void testNullEffectiveDateWithBCDAfterComputedEffectiveDay() throws Exception {
+
+        // Set by test as : 2012-05-07T00:03:42.000Z => New time = 2012-06-07T00:03:42.000Z (and june only has 30 days)
+        clock.addMonths(1);
+
+        int newBCD = 31;
+        // effectiveDate = 2012-06-07T00:03:42.000Z => ComputedEffectiveDay = 7
+        LocalDate effectiveDate = null;
+
+        // newBCD > 30 (max day in June)
+        final DateTime result = ((DefaultSubscriptionInternalApi) subscriptionInternalApi).getEffectiveDateForNewBCD(newBCD, effectiveDate, internalCallContext);
+
+        Assert.assertEquals(result, internalCallContext.toUTCDateTime(new LocalDate("2012-06-30")));
+    }
+
+    @Test(groups = "fast")
+    public void testNullEffectiveDateWithBCDAfterEndOfTheMonth() throws Exception {
+
+        // Set by test as : 2012-05-07T00:03:42.000Z
+        final DateTime now = clock.getUTCNow();
+
+        int newBCD = 10;
+        // effectiveDate = 2012-05-07T00:03:42.000Z => ComputedEffectiveDay = 7
+        LocalDate effectiveDate = null;
+
+        // newBCD < ComputedEffectiveDay
+        final DateTime result = ((DefaultSubscriptionInternalApi) subscriptionInternalApi).getEffectiveDateForNewBCD(newBCD, effectiveDate, internalCallContext);
+
+        Assert.assertEquals(result, internalCallContext.toUTCDateTime(new LocalDate("2012-05-10")));
+    }
+
+    @Test(groups = "fast")
+    public void testFutureEffectiveDateWithBCDPriorComputedEffectiveDay() throws Exception {
+
+        // Set by test as : 2012-05-07T00:03:42.000Z
+        final DateTime now = clock.getUTCNow();
+
+        int newBCD = 3;
+        // effectiveDate = 2012-05-07T00:03:42.000Z => ComputedEffectiveDay = 7
+        LocalDate effectiveDate = new LocalDate(2012, 7, 7);
+
+        // newBCD < ComputedEffectiveDay
+        final DateTime result = ((DefaultSubscriptionInternalApi) subscriptionInternalApi).getEffectiveDateForNewBCD(newBCD, effectiveDate, internalCallContext);
+
+        Assert.assertEquals(result, internalCallContext.toUTCDateTime(new LocalDate("2012-08-03")));
+    }
+
+    @Test(groups = "fast")
+    public void testFutureEffectiveDateWithBCDEqualsComputedEffectiveDay() throws Exception {
+
+        // Set by test as : 2012-05-07T00:03:42.000Z
+        final DateTime now = clock.getUTCNow();
+
+        int newBCD = 3;
+        // effectiveDate = 2012-05-07T00:03:42.000Z => ComputedEffectiveDay = 7
+        LocalDate effectiveDate = new LocalDate(2012, 7, 3);
+
+        // newBCD == ComputedEffectiveDay
+        final DateTime result = ((DefaultSubscriptionInternalApi) subscriptionInternalApi).getEffectiveDateForNewBCD(newBCD, effectiveDate, internalCallContext);
+
+        Assert.assertEquals(result, internalCallContext.toUTCDateTime(new LocalDate("2012-07-03")));
+    }
+
+    @Test(groups = "fast")
+    public void testFutureEffectiveDateWithBCDAfterComputedEffectiveDay() throws Exception {
+
+        // Set by test as : 2012-05-07T00:03:42.000Z
+        final DateTime now = clock.getUTCNow();
+
+        int newBCD = 10;
+        // effectiveDate = 2012-05-07T00:03:42.000Z => ComputedEffectiveDay = 7
+        LocalDate effectiveDate = new LocalDate(2012, 7, 3);
+
+        // newBCD > ComputedEffectiveDay
+        final DateTime result = ((DefaultSubscriptionInternalApi) subscriptionInternalApi).getEffectiveDateForNewBCD(newBCD, effectiveDate, internalCallContext);
+
+        Assert.assertEquals(result, internalCallContext.toUTCDateTime(new LocalDate("2012-07-10")));
+    }
+
+    @Test(groups = "fast")
+    public void testFutureEffectiveDateWithBCDAfterEndOfTheMonth() throws Exception {
+
+        // Set by test as : 2012-05-07T00:03:42.000Z
+        final DateTime now = clock.getUTCNow();
+
+        int newBCD = 31;
+        // effectiveDate = 2012-06-03 => ComputedEffectiveDay = 3
+        LocalDate effectiveDate = new LocalDate(2012, 6, 3);
+
+        // newBCD > 30 (max day in June)
+        final DateTime result = ((DefaultSubscriptionInternalApi) subscriptionInternalApi).getEffectiveDateForNewBCD(newBCD, effectiveDate, internalCallContext);
+
+        Assert.assertEquals(result, internalCallContext.toUTCDateTime(new LocalDate("2012-06-30")));
+    }
+
+    @Test(groups = "fast")
+    public void testPastEffectiveDateWithBCDPriorComputedEffectiveDay() throws Exception {
+
+        // Set by test as : 2012-05-07T00:03:42.000Z
+        final DateTime now = clock.getUTCNow();
+
+        int newBCD = 3;
+        // effectiveDate = 2012-05-07T00:03:42.000Z => ComputedEffectiveDay = 7
+        LocalDate effectiveDate = new LocalDate(2012, 2, 7);
+
+        // newBCD < ComputedEffectiveDay
+        final DateTime result = ((DefaultSubscriptionInternalApi) subscriptionInternalApi).getEffectiveDateForNewBCD(newBCD, effectiveDate, internalCallContext);
+
+        Assert.assertEquals(result, internalCallContext.toUTCDateTime(new LocalDate("2012-03-03")));
+    }
+
+    @Test(groups = "fast")
+    public void testPastEffectiveDateWithBCDEqualsComputedEffectiveDay() throws Exception {
+
+        // Set by test as : 2012-05-07T00:03:42.000Z
+        final DateTime now = clock.getUTCNow();
+
+        int newBCD = 3;
+        // effectiveDate = 2012-05-07T00:03:42.000Z => ComputedEffectiveDay = 7
+        LocalDate effectiveDate = new LocalDate(2012, 2, 3);
+
+        // newBCD == ComputedEffectiveDay
+        final DateTime result = ((DefaultSubscriptionInternalApi) subscriptionInternalApi).getEffectiveDateForNewBCD(newBCD, effectiveDate, internalCallContext);
+
+        Assert.assertEquals(result, internalCallContext.toUTCDateTime(new LocalDate("2012-02-03")));
+    }
+
+    @Test(groups = "fast")
+    public void testPastEffectiveDateWithBCDAfterComputedEffectiveDay() throws Exception {
+
+        // Set by test as : 2012-05-07T00:03:42.000Z
+        final DateTime now = clock.getUTCNow();
+
+        int newBCD = 10;
+        // effectiveDate = 2012-05-07T00:03:42.000Z => ComputedEffectiveDay = 7
+        LocalDate effectiveDate = new LocalDate(2012, 2, 3);
+
+        // newBCD > ComputedEffectiveDay
+        final DateTime result = ((DefaultSubscriptionInternalApi) subscriptionInternalApi).getEffectiveDateForNewBCD(newBCD, effectiveDate, internalCallContext);
+
+        Assert.assertEquals(result, internalCallContext.toUTCDateTime(new LocalDate("2012-02-10")));
+    }
+
+    @Test(groups = "fast")
+    public void testPastEffectiveDateWithBCDAfterEndOfTheMonth() throws Exception {
+
+        // Set by test as : 2012-05-07T00:03:42.000Z
+        final DateTime now = clock.getUTCNow();
+
+        int newBCD = 31;
+        // effectiveDate = 2012-02-03 => ComputedEffectiveDay = 3
+        LocalDate effectiveDate = new LocalDate(2012, 2, 3);
+
+        // newBCD > 30 (max day in June)
+        final DateTime result = ((DefaultSubscriptionInternalApi) subscriptionInternalApi).getEffectiveDateForNewBCD(newBCD, effectiveDate, internalCallContext);
+
+        Assert.assertEquals(result, internalCallContext.toUTCDateTime(new LocalDate("2012-2-29")));
+    }
+
+}