killbill-memoizeit

Merge remote-tracking branch 'killbill/work-for-release-0.19.x'

2/23/2018 11:21:06 AM

Details

diff --git a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegration.java b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegration.java
index 886beb1..fb33ba6 100644
--- a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegration.java
+++ b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegration.java
@@ -21,9 +21,11 @@ package org.killbill.billing.beatrix.integration;
 import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 import java.util.UUID;
 
 import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
 import org.joda.time.Interval;
 import org.joda.time.LocalDate;
 import org.killbill.billing.ErrorCode;
@@ -47,9 +49,12 @@ import org.killbill.billing.invoice.api.DryRunType;
 import org.killbill.billing.invoice.api.Invoice;
 import org.killbill.billing.invoice.api.InvoiceApiException;
 import org.killbill.billing.invoice.api.InvoiceItemType;
+import org.killbill.billing.mock.MockAccountBuilder;
 import org.killbill.billing.payment.api.PluginProperty;
 import org.killbill.billing.payment.api.TransactionStatus;
 import org.killbill.billing.subscription.api.user.DefaultSubscriptionBase;
+import org.skife.jdbi.v2.Handle;
+import org.skife.jdbi.v2.tweak.HandleCallback;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
@@ -928,4 +933,74 @@ public class TestIntegration extends TestIntegrationBase {
             startDateBase = endDateBase;
         }
     }
+
+
+    @Test(groups = "slow")
+    public void testWithDayLightSaving() throws Exception {
+        clock.setTime(new DateTime("2015-09-01T08:01:01.000Z"));
+
+        final DateTimeZone tz = DateTimeZone.forID("America/Juneau");
+        final AccountData accountData = new MockAccountBuilder().name(UUID.randomUUID().toString().substring(1, 8))
+                                                                .firstNameLength(6)
+                                                                .email(UUID.randomUUID().toString().substring(1, 8))
+                                                                .phone(UUID.randomUUID().toString().substring(1, 8))
+                                                                .migrated(false)
+                                                                .isNotifiedForInvoices(false)
+                                                                .externalKey(UUID.randomUUID().toString().substring(1, 8))
+                                                                .billingCycleDayLocal(1)
+                                                                .currency(Currency.USD)
+                                                                .paymentMethodId(UUID.randomUUID())
+                                                                .referenceTime(clock.getUTCNow())
+                                                                .timeZone(tz)
+                                                                .build();
+        final Account account = createAccountWithNonOsgiPaymentMethod(accountData);
+        accountChecker.checkAccount(account.getId(), accountData, callContext);
+
+        //
+        // CREATE SUBSCRIPTION AND EXPECT BOTH EVENTS: NextEvent.CREATE, NextEvent.BLOCK NextEvent.INVOICE
+        //
+        final DefaultEntitlement bpSubscription = createBaseEntitlementAndCheckForCompletion(account.getId(), "bundleKey", "Shotgun", ProductCategory.BASE, BillingPeriod.ANNUAL, NextEvent.CREATE, NextEvent.BLOCK, NextEvent.INVOICE);
+        // Check bundle after BP got created otherwise we get an error from auditApi.
+        subscriptionChecker.checkSubscriptionCreated(bpSubscription.getId(), internalCallContext);
+        invoiceChecker.checkInvoice(account.getId(), 1, callContext, new ExpectedInvoiceItemCheck(new LocalDate(2015, 9, 1), null, InvoiceItemType.FIXED, new BigDecimal("0")));
+        assertListenerStatus();
+
+        //
+        // ADD ADD_ON ON THE SAME DAY
+        //
+        final DefaultEntitlement aoSubscription = addAOEntitlementAndCheckForCompletion(bpSubscription.getBundleId(), "Bullets", ProductCategory.ADD_ON, BillingPeriod.NO_BILLING_PERIOD, NextEvent.CREATE, NextEvent.BLOCK, NextEvent.NULL_INVOICE);
+        assertListenerStatus();
+
+        busHandler.pushExpectedEvents(NextEvent.PHASE, NextEvent.NULL_INVOICE, NextEvent.INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
+        clock.addDays(30);
+        assertListenerStatus();
+        invoiceChecker.checkInvoice(account.getId(), 2, callContext,
+                                    new ExpectedInvoiceItemCheck(new LocalDate(2015, 10, 1), new LocalDate(2016, 10, 1), InvoiceItemType.RECURRING, new BigDecimal("2399.95")));
+
+        // 2015-11-1
+        busHandler.pushExpectedEvent(NextEvent.NULL_INVOICE);
+        clock.addMonths(1);
+        assertListenerStatus();
+
+        // 2015-12-1
+        busHandler.pushExpectedEvent(NextEvent.NULL_INVOICE);
+        clock.addMonths(1);
+        assertListenerStatus();
+
+        // We sleep to let system creates lots of notification if an infinite loop was indeed happening
+        Thread.sleep(3000);
+        // And then we check that we only have the expected number of notifications in the history table.
+        final Integer countNotifications = dbi.withHandle(new HandleCallback<Integer>() {
+                                                              @Override
+                                                              public Integer withHandle(final Handle handle) throws Exception {
+
+                                                                  List<Map<String, Object>> res = handle.select("select count(*) as count from notifications_history;");
+                                                                  final Integer count = Integer.valueOf(res.get(0).get("count").toString());
+                                                                  return count;
+                                                              }
+                                                          }
+                                                         );
+        Assert.assertEquals(countNotifications.intValue(), 4);
+    }
+
 }
diff --git a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/usage/TestConsumableInArrear.java b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/usage/TestConsumableInArrear.java
index b67a99a..607a2b6 100644
--- a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/usage/TestConsumableInArrear.java
+++ b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/usage/TestConsumableInArrear.java
@@ -120,6 +120,26 @@ public class TestConsumableInArrear extends TestIntegrationBase {
         invoiceChecker.checkInvoice(account.getId(), 4, callContext,
                                     new ExpectedInvoiceItemCheck(new LocalDate(2012, 5, 1), new LocalDate(2012, 6, 1), InvoiceItemType.USAGE, new BigDecimal("5.90")),
                                     new ExpectedInvoiceItemCheck(new LocalDate(2012, 7, 1), new LocalDate(2012, 8, 1), InvoiceItemType.USAGE, new BigDecimal("11.80")));
+
+
+        // Add a few more month of usage data and check correctness of invoice: iterate 8 times until 2013-4-1 (prior ANNUAL renewal)
+        LocalDate startDate = new LocalDate(2012, 8, 1);
+        int currentInvoice = 5;
+        for (int i = 0; i < 8; i++) {
+
+            setUsage(aoSubscription.getId(), "bullets", startDate.plusDays(15), 350L, callContext);
+
+            busHandler.pushExpectedEvents(NextEvent.INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
+            clock.addMonths(1);
+            assertListenerStatus();
+
+            invoiceChecker.checkInvoice(account.getId(), currentInvoice, callContext,
+                                        new ExpectedInvoiceItemCheck(startDate, startDate.plusMonths(1), InvoiceItemType.USAGE, new BigDecimal("11.80")));
+
+
+            startDate = startDate.plusMonths(1);
+            currentInvoice++;
+        }
     }
 
     @Test(groups = "slow")
@@ -174,74 +194,6 @@ public class TestConsumableInArrear extends TestIntegrationBase {
         assertListenerStatus();
     }
 
-    @Test(groups = "slow")
-    public void testWithDayLightSaving() throws Exception {
-        clock.setTime(new DateTime("2015-09-01T08:01:01.000Z"));
-
-        final DateTimeZone tz = DateTimeZone.forID("America/Juneau");
-        final AccountData accountData = new MockAccountBuilder().name(UUID.randomUUID().toString().substring(1, 8))
-                                                                .firstNameLength(6)
-                                                                .email(UUID.randomUUID().toString().substring(1, 8))
-                                                                .phone(UUID.randomUUID().toString().substring(1, 8))
-                                                                .migrated(false)
-                                                                .isNotifiedForInvoices(false)
-                                                                .externalKey(UUID.randomUUID().toString().substring(1, 8))
-                                                                .billingCycleDayLocal(1)
-                                                                .currency(Currency.USD)
-                                                                .paymentMethodId(UUID.randomUUID())
-                                                                .referenceTime(clock.getUTCNow())
-                                                                .timeZone(tz)
-                                                                .build();
-        final Account account = createAccountWithNonOsgiPaymentMethod(accountData);
-        accountChecker.checkAccount(account.getId(), accountData, callContext);
-
-        //
-        // CREATE SUBSCRIPTION AND EXPECT BOTH EVENTS: NextEvent.CREATE, NextEvent.BLOCK NextEvent.INVOICE
-        //
-        final DefaultEntitlement bpSubscription = createBaseEntitlementAndCheckForCompletion(account.getId(), "bundleKey", "Shotgun", ProductCategory.BASE, BillingPeriod.ANNUAL, NextEvent.CREATE, NextEvent.BLOCK, NextEvent.INVOICE);
-        // Check bundle after BP got created otherwise we get an error from auditApi.
-        subscriptionChecker.checkSubscriptionCreated(bpSubscription.getId(), internalCallContext);
-        invoiceChecker.checkInvoice(account.getId(), 1, callContext, new ExpectedInvoiceItemCheck(new LocalDate(2015, 9, 1), null, InvoiceItemType.FIXED, new BigDecimal("0")));
-        assertListenerStatus();
-
-        //
-        // ADD ADD_ON ON THE SAME DAY
-        //
-        final DefaultEntitlement aoSubscription = addAOEntitlementAndCheckForCompletion(bpSubscription.getBundleId(), "Bullets", ProductCategory.ADD_ON, BillingPeriod.NO_BILLING_PERIOD, NextEvent.CREATE, NextEvent.BLOCK, NextEvent.NULL_INVOICE);
-        assertListenerStatus();
-
-        busHandler.pushExpectedEvents(NextEvent.PHASE, NextEvent.NULL_INVOICE, NextEvent.INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
-        clock.addDays(30);
-        assertListenerStatus();
-        invoiceChecker.checkInvoice(account.getId(), 2, callContext,
-                                    new ExpectedInvoiceItemCheck(new LocalDate(2015, 10, 1), new LocalDate(2016, 10, 1), InvoiceItemType.RECURRING, new BigDecimal("2399.95")));
-
-        // 2015-11-1
-        busHandler.pushExpectedEvent(NextEvent.NULL_INVOICE);
-        clock.addMonths(1);
-        assertListenerStatus();
-
-        // 2015-12-1
-        busHandler.pushExpectedEvent(NextEvent.NULL_INVOICE);
-        clock.addMonths(1);
-        assertListenerStatus();
-
-        // We sleep to let system creates lots of notification if an infinite loop was indeed happening
-        Thread.sleep(3000);
-        // And then we check that we only have the expected number of notifications in the history table.
-        final Integer countNotifications = dbi.withHandle(new HandleCallback<Integer>() {
-                                                              @Override
-                                                              public Integer withHandle(final Handle handle) throws Exception {
-
-                                                                  List<Map<String, Object>> res = handle.select("select count(*) as count from notifications_history;");
-                                                                  final Integer count = Integer.valueOf(res.get(0).get("count").toString());
-                                                                  return count;
-                                                              }
-                                                          }
-                                                         );
-        Assert.assertEquals(countNotifications.intValue(), 4);
-    }
-
     private void setUsage(final UUID subscriptionId, final String unitType, final LocalDate startDate, final Long amount, final CallContext context) throws UsageApiException {
         final List<UsageRecord> usageRecords = new ArrayList<UsageRecord>();
         usageRecords.add(new UsageRecord(startDate, amount));
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/usage/RawUsageOptimizer.java b/invoice/src/main/java/org/killbill/billing/invoice/usage/RawUsageOptimizer.java
index 295c376..b0f27f8 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/usage/RawUsageOptimizer.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/usage/RawUsageOptimizer.java
@@ -134,7 +134,7 @@ public class RawUsageOptimizer {
             }
         }
 
-        final LocalDate result = targetStartDate.compareTo(firstEventStartDate) > 0 ? targetStartDate : firstEventStartDate;
+        final LocalDate result = targetStartDate != null && targetStartDate.compareTo(firstEventStartDate) > 0 ? targetStartDate : firstEventStartDate;
         return result;
     }
 
diff --git a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/AdminResource.java b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/AdminResource.java
index ecdc194..84e8926 100644
--- a/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/AdminResource.java
+++ b/jaxrs/src/main/java/org/killbill/billing/jaxrs/resources/AdminResource.java
@@ -428,7 +428,7 @@ public class AdminResource extends JaxRsResourceBase {
     @POST
     @Path("/" + HEALTHCHECK)
     @Produces(APPLICATION_JSON)
-    @ApiOperation(value = "Put the host out of rotation")
+    @ApiOperation(value = "Put the host back into of rotation")
     @ApiResponses(value = {})
     public Response putInRotation(@javax.ws.rs.core.Context final HttpServletRequest request) {
         killbillHealthcheck.putInRotation();

pom.xml 2(+1 -1)

diff --git a/pom.xml b/pom.xml
index e4dee05..ba61673 100644
--- a/pom.xml
+++ b/pom.xml
@@ -21,7 +21,7 @@
     <parent>
         <artifactId>killbill-oss-parent</artifactId>
         <groupId>org.kill-bill.billing</groupId>
-        <version>0.141.34</version>
+        <version>0.141.36</version>
     </parent>
     <artifactId>killbill</artifactId>
     <version>0.19.4-SNAPSHOT</version>
diff --git a/util/src/test/java/org/killbill/billing/util/listener/TestRetryableService.java b/util/src/test/java/org/killbill/billing/util/listener/TestRetryableService.java
index c33b881..e7e492d 100644
--- a/util/src/test/java/org/killbill/billing/util/listener/TestRetryableService.java
+++ b/util/src/test/java/org/killbill/billing/util/listener/TestRetryableService.java
@@ -1,6 +1,6 @@
 /*
- * Copyright 2014-2017 Groupon, Inc
- * Copyright 2014-2017 The Billing Project, LLC
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 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
@@ -26,6 +26,7 @@ import org.joda.time.DateTime;
 import org.joda.time.Period;
 import org.killbill.billing.ObjectType;
 import org.killbill.billing.account.api.ImmutableAccountData;
+import org.killbill.billing.api.FlakyRetryAnalyzer;
 import org.killbill.billing.callcontext.InternalTenantContext;
 import org.killbill.billing.events.BusInternalEvent;
 import org.killbill.billing.events.ControlTagCreationInternalEvent;
@@ -84,7 +85,8 @@ public class TestRetryableService extends UtilTestSuiteWithEmbeddedDB {
         testListener.stop();
     }
 
-    @Test(groups = "slow")
+    // Flaky, see https://github.com/killbill/killbill/issues/860
+    @Test(groups = "slow", retryAnalyzer = FlakyRetryAnalyzer.class)
     public void testFixUp() throws Exception {
         testListener.throwRetryableException = true;
 
@@ -114,7 +116,8 @@ public class TestRetryableService extends UtilTestSuiteWithEmbeddedDB {
         Assert.assertEquals(getFutureRetryableEvents().size(), 0);
     }
 
-    @Test(groups = "slow")
+    // Flaky, see https://github.com/killbill/killbill/issues/860
+    @Test(groups = "slow", retryAnalyzer = FlakyRetryAnalyzer.class)
     public void testGiveUp() throws Exception {
         testListener.throwRetryableException = true;