killbill-aplcache

beatrix: add integration test for DST gap Signed-off-by:

2/16/2016 1:54:36 PM

Details

diff --git a/api/src/main/java/org/killbill/billing/callcontext/TimeAwareContext.java b/api/src/main/java/org/killbill/billing/callcontext/TimeAwareContext.java
index ca38a75..1f913d0 100644
--- a/api/src/main/java/org/killbill/billing/callcontext/TimeAwareContext.java
+++ b/api/src/main/java/org/killbill/billing/callcontext/TimeAwareContext.java
@@ -64,7 +64,7 @@ public class TimeAwareContext {
                                           getReferenceTime().getSecondOfMinute(),
                                           getFixedOffsetTimeZone());
         } catch (final IllegalInstantException e) {
-            // DST gap
+            // DST gap (shouldn't happen when using fixed offset timezones)
             targetDateTime = localDate.toDateTimeAtStartOfDay(getFixedOffsetTimeZone());
         }
 
diff --git a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithTimeZones.java b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithTimeZones.java
index e3bb373..2a5335b 100644
--- a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithTimeZones.java
+++ b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithTimeZones.java
@@ -24,6 +24,7 @@ import java.util.UUID;
 
 import org.joda.time.DateTime;
 import org.joda.time.DateTimeZone;
+import org.joda.time.IllegalInstantException;
 import org.joda.time.LocalDate;
 import org.killbill.billing.account.api.Account;
 import org.killbill.billing.account.api.AccountData;
@@ -197,4 +198,44 @@ public class TestWithTimeZones extends TestIntegrationBase {
         final List<Invoice> invoices = invoiceUserApi.getInvoicesByAccount(account.getId(), callContext);
         Assert.assertEquals(invoices.size(), 1);
     }
+
+    @Test(groups = "slow")
+    public void testReferenceTimeInDSTGap() throws Exception {
+        final DateTimeZone tz = DateTimeZone.forID("America/Los_Angeles");
+        clock.setTime(new DateTime(2015, 3, 7, 2, 0, 0, tz));
+
+        final AccountData accountData = new MockAccountBuilder().currency(Currency.USD)
+                                                                .timeZone(tz)
+                                                                .build();
+        final Account account = createAccountWithNonOsgiPaymentMethod(accountData);
+        accountChecker.checkAccount(account.getId(), accountData, callContext);
+        Assert.assertEquals(account.getTimeZone(), tz);
+        Assert.assertEquals(account.getFixedOffsetTimeZone(), DateTimeZone.forOffsetHours(-8));
+
+        // Note the gap: 2015-03-07T02:00:00.000-08:00 to 2015-03-08T03:00:00.000-07:00
+        clock.addDays(1);
+
+        try {
+            // See TimeAwareContext#toUTCDateTime (which uses account.getFixedOffsetTimeZone() instead)
+            new DateTime(clock.getUTCToday().getYear(),
+                         clock.getUTCToday().getMonthOfYear(),
+                         clock.getUTCToday().getDayOfMonth(),
+                         account.getReferenceTime().toDateTime(tz).getHourOfDay(),
+                         account.getReferenceTime().toDateTime(tz).getMinuteOfHour(),
+                         account.getReferenceTime().toDateTime(tz).getSecondOfMinute(),
+                         account.getTimeZone());
+            Assert.fail();
+        } catch (final IllegalInstantException e) {
+            // Illegal instant due to time zone offset transition (daylight savings time 'gap'): 2015-03-08T10:00:00.000 (America/Los_Angeles)
+        }
+
+        busHandler.pushExpectedEvents(NextEvent.CREATE, NextEvent.INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
+        final PlanPhaseSpecifier spec = new PlanPhaseSpecifier("Blowdart", ProductCategory.BASE, BillingPeriod.MONTHLY, "notrial", null);
+        // Pass a date of today, to trigger TimeAwareContext#toUTCDateTime
+        final Entitlement entitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, "Something", ImmutableList.<PlanPhasePriceOverride>of(), clock.getUTCToday(), ImmutableList.<PluginProperty>of(), callContext);
+        assertListenerStatus();
+
+        Assert.assertEquals(entitlement.getEffectiveStartDate().compareTo(new LocalDate("2015-03-08")), 0);
+        Assert.assertEquals(((DefaultEntitlement) entitlement).getBasePlanSubscriptionBase().getStartDate().compareTo(new DateTime("2015-03-08T02:00:00.000-08:00")), 0);
+    }
 }