killbill-memoizeit
Changes
.circleci/config.yml 219(+219 -0)
beatrix/src/test/java/org/killbill/billing/beatrix/integration/overdue/TestOverdueIntegration.java 7(+5 -2)
beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationInvoiceWithRepairLogic.java 6(+0 -6)
beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithFakeKPMPlugin.java 46(+19 -27)
beatrix/src/test/java/org/killbill/billing/beatrix/integration/usage/TestConsumableInArrear.java 5(+0 -5)
entitlement/src/main/java/org/killbill/billing/entitlement/engine/core/DefaultEventsStream.java 15(+15 -0)
entitlement/src/test/java/org/killbill/billing/entitlement/EntitlementTestSuiteWithEmbeddedDB.java 8(+1 -7)
junction/src/test/java/org/killbill/billing/junction/plumbing/billing/TestDefaultInternalBillingApi.java 1(+1 -0)
overdue/src/test/java/org/killbill/billing/overdue/notification/TestOverdueCheckNotifier.java 3(+2 -1)
pom.xml 2(+1 -1)
subscription/src/test/java/org/killbill/billing/subscription/SubscriptionTestSuiteNoDB.java 1(+1 -0)
subscription/src/test/java/org/killbill/billing/subscription/SubscriptionTestSuiteWithEmbeddedDB.java 7(+1 -6)
util/src/test/java/org/killbill/billing/util/callcontext/TestInternalCallContextFactory.java 8(+5 -3)
Details
.circleci/config.yml 219(+219 -0)
diff --git a/.circleci/config.yml b/.circleci/config.yml
new file mode 100644
index 0000000..ca7b9fc
--- /dev/null
+++ b/.circleci/config.yml
@@ -0,0 +1,219 @@
+defaults: &defaults
+ working_directory: ~/repo
+ environment:
+ MAVEN_OPTS: -server -showversion -XX:+PrintCommandLineFlags -XX:+UseCodeCacheFlushing -Xms1024M -Xmx2048M -XX:+CMSClassUnloadingEnabled -XX:-OmitStackTraceInFastThrow -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+CMSConcurrentMTEnabled -XX:+CMSParallelRemarkEnabled -XX:+UseCMSInitiatingOccupancyOnly -XX:CMSInitiatingOccupancyFraction=70 -XX:+ScavengeBeforeFullGC -XX:+CMSScavengeBeforeRemark -XX:NewSize=600m -XX:MaxNewSize=900m -XX:SurvivorRatio=10 -XX:+DisableExplicitGC -Djava.security.egd=file:/dev/./urandom
+
+version: 2
+jobs:
+ build:
+ <<: *defaults
+ docker:
+ - image: killbill/kbbuild:0.1.0
+ steps:
+ - checkout
+ - restore_cache:
+ key: v1-dependencies-{{ .Branch }}-{{ checksum "pom.xml" }}
+ - run:
+ name: Setup dependencies
+ command: |
+ if [ "${CIRCLE_BRANCH}" != "master" ]; then
+ for i in killbill-oss-parent killbill-api killbill-plugin-api killbill-commons killbill-platform; do
+ if [ -n "$(git ls-remote --heads https://github.com/killbill/$i.git ${CIRCLE_BRANCH})" ]; then
+ echo "*** Setting up $i"
+ mkdir -p /home/killbill/$i
+ git clone https://github.com/killbill/$i.git /home/killbill/$i
+ pushd /home/killbill/$i
+ git checkout -b ${CIRCLE_BRANCH} origin/${CIRCLE_BRANCH}
+ mvn clean install -DskipTests=true
+ popd
+ fi
+ done
+ fi
+ - run: mvn -DskipTests=true clean install dependency:go-offline
+ - save_cache:
+ paths:
+ - ~/.m2
+ key: v1-dependencies-{{ .Branch }}-{{ checksum "pom.xml" }}
+
+ test-h2:
+ <<: *defaults
+ docker:
+ - image: killbill/kbbuild:0.1.0
+ steps:
+ - checkout
+ - restore_cache:
+ key: v1-dependencies-{{ .Branch }}-{{ checksum "pom.xml" }}
+ - run: mvn clean install -Ptravis
+ - run:
+ name: Save test results
+ command: |
+ mkdir -p ~/junit/
+ find . -type f -regex ".*/target/surefire-reports/.*xml" -exec cp {} ~/junit/ \;
+ when: always
+ - store_test_results:
+ path: ~/junit
+ - store_artifacts:
+ path: ~/junit
+ test-mysql:
+ <<: *defaults
+ docker:
+ - image: killbill/kbbuild:0.1.0
+ - image: killbill/mariadb:0.18
+ environment:
+ - MYSQL_ROOT_PASSWORD=root
+ steps:
+ - checkout
+ - restore_cache:
+ key: v1-dependencies-{{ .Branch }}-{{ checksum "pom.xml" }}
+ - run:
+ name: Setup latest DDL
+ command: |
+ set +e
+ count=0
+ until mysqladmin ping -h 127.0.0.1 -u root --password=root --silent; do
+ if [[ "$count" == "25" ]]; then
+ exit 1
+ fi
+ (( count++ ))
+
+ printf '.'
+ sleep 5
+ done
+
+ set -e
+ ./bin/db-helper -a create --driver mysql -u root -p root -t yes -h 127.0.0.1
+ - run: mvn clean install -Plocaltest-mysql
+ - run:
+ name: Save test results
+ command: |
+ mkdir -p ~/junit/
+ find . -type f -regex ".*/target/surefire-reports/.*xml" -exec cp {} ~/junit/ \;
+ when: always
+ - store_test_results:
+ path: ~/junit
+ - store_artifacts:
+ path: ~/junit
+ test-postgresql:
+ <<: *defaults
+ docker:
+ - image: killbill/kbbuild:0.1.0
+ - image: killbill/postgresql:0.18
+ environment:
+ - POSTGRES_PASSWORD=postgres
+ steps:
+ - checkout
+ - restore_cache:
+ key: v1-dependencies-{{ .Branch }}-{{ checksum "pom.xml" }}
+ - run:
+ name: Setup latest DDL
+ command: ./bin/db-helper -a create --driver postgres -u postgres -p postgres -t yes
+ - run: mvn clean install -Plocaltest-postgresql
+ - run:
+ name: Save test results
+ command: |
+ mkdir -p ~/junit/
+ find . -type f -regex ".*/target/surefire-reports/.*xml" -exec cp {} ~/junit/ \;
+ when: always
+ - store_test_results:
+ path: ~/junit
+ - store_artifacts:
+ path: ~/junit
+
+ integration-tests:
+ <<: *defaults
+ docker:
+ - image: killbill/kbbuild:0.1.0
+ - image: killbill/mariadb:0.18
+ environment:
+ - MYSQL_ROOT_PASSWORD=root
+ steps:
+ - checkout
+ - restore_cache:
+ key: v1-dependencies-{{ .Branch }}-{{ checksum "pom.xml" }}
+ - run:
+ name: Setup latest DDL
+ command: ./bin/db-helper -a create --driver mysql -u root -p root -t yes -h 127.0.0.1
+ - run:
+ name: Run integration tests
+ command: |
+ set +e
+
+ mvn clean install -DskipTests=true
+ nohup ./bin/start-server -s &
+
+ mkdir -p /home/killbill/killbill-integration-tests
+ git clone https://github.com/killbill/killbill-integration-tests.git /home/killbill/killbill-integration-tests
+ pushd /home/killbill/killbill-integration-tests
+ if [ "${CIRCLE_BRANCH}" != "master" ]; then
+ if [ -n "$(git ls-remote --heads https://github.com/killbill/killbill-integration-tests.git ${CIRCLE_BRANCH})" ]; then
+ git checkout -b ${CIRCLE_BRANCH} origin/${CIRCLE_BRANCH}
+ fi
+ fi
+ bundle install
+
+ count=0
+ until $(curl --output /dev/null --silent --fail http://127.0.0.1:8080/1.0/healthcheck); do
+ if [[ "$count" == "25" ]]; then
+ exit 1
+ fi
+ (( count++ ))
+
+ printf '.'
+ sleep 5
+ done
+
+ set -e
+ mkdir -p /tmp/test-results
+ bundle exec rake test:core | tee /tmp/test-results/test.txt 2>&1
+ - store_test_results:
+ path: /tmp/test-results
+ - store_artifacts:
+ path: /tmp/test-results
+
+workflows:
+ version: 2
+ build-and-test:
+ jobs:
+ - build:
+ filters:
+ branches:
+ only:
+ - master
+ - work-for-release-0.19.x
+ - circle-ci-experiment
+ - test-h2:
+ requires:
+ - build
+ filters:
+ branches:
+ only:
+ - master
+ - circle-ci-experiment
+ - test-mysql:
+ requires:
+ - build
+ filters:
+ branches:
+ only:
+ - master
+ - work-for-release-0.19.x
+ - circle-ci-experiment
+ - test-postgresql:
+ requires:
+ - build
+ filters:
+ branches:
+ only:
+ - master
+ - circle-ci-experiment
+ - integration-tests:
+ requires:
+ - test-h2
+ - test-mysql
+ - test-postgresql
+ filters:
+ branches:
+ only:
+ - master
+ - work-for-release-0.19.x
+ - circle-ci-experiment
diff --git a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/overdue/TestOverdueIntegration.java b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/overdue/TestOverdueIntegration.java
index 7dd3961..6769325 100644
--- a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/overdue/TestOverdueIntegration.java
+++ b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/overdue/TestOverdueIntegration.java
@@ -29,6 +29,7 @@ import java.util.UUID;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.killbill.billing.ErrorCode;
+import org.killbill.billing.api.FlakyRetryAnalyzer;
import org.killbill.billing.api.TestApiListener.NextEvent;
import org.killbill.billing.beatrix.integration.BeatrixIntegrationModule;
import org.killbill.billing.beatrix.util.InvoiceChecker.ExpectedInvoiceItemCheck;
@@ -953,7 +954,8 @@ public class TestOverdueIntegration extends TestOverdueBase {
checkODState(OverdueWrapper.CLEAR_STATE_NAME);
}
- @Test(groups = "slow", description = "Test overdue state with number of unpaid invoices condition")
+ // Flaky, see https://github.com/killbill/killbill/issues/782
+ @Test(groups = "slow", description = "Test overdue state with number of unpaid invoices condition", retryAnalyzer = FlakyRetryAnalyzer.class)
public void testOverdueStateWithNumberOfUnpaidInvoicesCondition() throws Exception {
// 2012-05-01T00:03:42.000Z
clock.setTime(new DateTime(2012, 5, 1, 0, 3, 42, 0));
@@ -1025,7 +1027,8 @@ public class TestOverdueIntegration extends TestOverdueBase {
checkODState(OverdueWrapper.CLEAR_STATE_NAME);
}
- @Test(groups = "slow", description = "Test overdue state with total unpaid invoice balance condition")
+ // Flaky, see https://github.com/killbill/killbill/issues/782
+ @Test(groups = "slow", description = "Test overdue state with total unpaid invoice balance condition", retryAnalyzer = FlakyRetryAnalyzer.class)
public void testOverdueStateWithTotalUnpaidInvoiceBalanceCondition() throws Exception {
// 2012-05-01T00:03:42.000Z
clock.setTime(new DateTime(2012, 5, 1, 0, 3, 42, 0));
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 89507b5..5536865 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
@@ -421,49 +421,6 @@ public class TestIntegration extends TestIntegrationBase {
checkNoMoreInvoiceToGenerate(account);
}
- @Test(groups = {"stress"}, enabled = false)
- public void stressTest() throws Exception {
- final int maxIterations = 100;
- for (int curIteration = 0; curIteration < maxIterations; curIteration++) {
- if (curIteration != 0) {
- beforeMethod();
- }
-
- log.info("################################ ITERATION " + curIteration + " #########################");
- afterMethod();
- beforeMethod();
- testBasePlanCompleteWithBillingDayInPast();
- Thread.sleep(1000);
- afterMethod();
- beforeMethod();
- testBasePlanCompleteWithBillingDayAlignedWithTrial();
- Thread.sleep(1000);
- afterMethod();
- beforeMethod();
- testBasePlanCompleteWithBillingDayInFuture();
- if (curIteration < maxIterations - 1) {
- afterMethod();
- Thread.sleep(1000);
- }
- }
- }
-
- @Test(groups = {"stress"}, enabled = false)
- public void stressTestDebug() throws Exception {
- final int maxIterations = 100;
- for (int curIteration = 0; curIteration < maxIterations; curIteration++) {
- log.info("################################ ITERATION " + curIteration + " #########################");
- if (curIteration != 0) {
- beforeMethod();
- }
- testAddonsWithMultipleAlignments();
- if (curIteration < maxIterations - 1) {
- afterMethod();
- Thread.sleep(1000);
- }
- }
- }
-
@Test(groups = "slow")
public void testAddonsWithMultipleAlignments() throws Exception {
final DateTime initialDate = new DateTime(2012, 4, 25, 0, 13, 42, 0, testTimeZone);
diff --git a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationBase.java b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationBase.java
index 2969715..6c98b7a 100644
--- a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationBase.java
+++ b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationBase.java
@@ -18,15 +18,18 @@
package org.killbill.billing.beatrix.integration;
-import com.google.common.base.Function;
-import com.google.common.base.Joiner;
-import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.google.inject.Guice;
-import com.google.inject.Injector;
-import com.google.inject.Stage;
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.concurrent.Callable;
+
+import javax.annotation.Nullable;
+import javax.inject.Inject;
+import javax.inject.Named;
+
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalDate;
@@ -122,30 +125,31 @@ import org.skife.config.TimeSpan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.testng.Assert;
+import org.testng.IHookCallBack;
+import org.testng.IHookable;
+import org.testng.ITestResult;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeMethod;
-import javax.annotation.Nullable;
-import javax.inject.Inject;
-import javax.inject.Named;
-import java.math.BigDecimal;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.UUID;
-import java.util.concurrent.Callable;
+import com.google.common.base.Function;
+import com.google.common.base.Joiner;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+import com.google.inject.Stage;
-import static org.awaitility.Awaitility.await;
import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.awaitility.Awaitility.await;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
-
-public class TestIntegrationBase extends BeatrixTestSuiteWithEmbeddedDB {
+public class TestIntegrationBase extends BeatrixTestSuiteWithEmbeddedDB implements IHookable {
protected static final DateTimeZone testTimeZone = DateTimeZone.UTC;
protected static final Logger log = LoggerFactory.getLogger(TestIntegrationBase.class);
@@ -295,6 +299,7 @@ public class TestIntegrationBase extends BeatrixTestSuiteWithEmbeddedDB {
protected ConfigurableInvoiceConfig invoiceConfig;
+ @Override
protected void assertListenerStatus() {
busHandler.assertListenerStatus();
}
@@ -329,16 +334,10 @@ public class TestIntegrationBase extends BeatrixTestSuiteWithEmbeddedDB {
lifecycle.fireStartupSequencePostEventRegistration();
paymentPlugin.clear();
-
- // Make sure we start with a clean state
- assertListenerStatus();
}
@AfterMethod(groups = "slow")
public void afterMethod() throws Exception {
- // Make sure we finish in a clean state
- assertListenerStatus();
-
lifecycle.fireShutdownSequencePriorEventUnRegistration();
busService.getBus().unregister(busHandler);
lifecycle.fireShutdownSequencePostEventUnRegistration();
diff --git a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationInvoiceWithRepairLogic.java b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationInvoiceWithRepairLogic.java
index 18f2da2..a755f9c 100644
--- a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationInvoiceWithRepairLogic.java
+++ b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestIntegrationInvoiceWithRepairLogic.java
@@ -64,12 +64,6 @@ public class TestIntegrationInvoiceWithRepairLogic extends TestIntegrationBase {
@Inject
protected InvoiceDao invoiceDao;
-
- @AfterMethod(groups = "slow")
- public void afterMethod() throws Exception {
- super.afterMethod();
- }
-
@Test(groups = "slow")
public void testSimplePartialRepairWithItemAdjustment() throws Exception {
// We take april as it has 30 days (easier to play with BCD)
diff --git a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestPaymentRefund.java b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestPaymentRefund.java
index 86912e4..15d05da 100644
--- a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestPaymentRefund.java
+++ b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestPaymentRefund.java
@@ -152,7 +152,7 @@ public class TestPaymentRefund extends TestIntegrationBase {
// No end date for the trial item (fixed price of zero), and CTD should be today (i.e. when the trial started)
invoiceChecker.checkChargedThroughDate(bpEntitlement.getId(), clock.getUTCToday(), callContext);
- setDateAndCheckForCompletion(new DateTime(2012, 3, 2, 23, 59, 59, 0, testTimeZone), NextEvent.PHASE, NextEvent.INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
+ setDateAndCheckForCompletion(new DateTime(2012, 3, 2, 23, 59, 0, 0, testTimeZone), NextEvent.PHASE, NextEvent.INVOICE, NextEvent.PAYMENT, NextEvent.INVOICE_PAYMENT);
invoice = invoiceChecker.checkInvoice(account.getId(), ++invoiceItemCount, callContext, new ExpectedInvoiceItemCheck(new LocalDate(2012, 3, 2),
new LocalDate(2012, 3, 31), InvoiceItemType.RECURRING, new BigDecimal("233.82")));
payment = paymentChecker.checkPayment(account.getId(), 1, callContext, new ExpectedPaymentCheck(new LocalDate(2012, 3, 2), new BigDecimal("233.82"), TransactionStatus.SUCCESS, invoice.getId(), Currency.USD));
diff --git a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestPublicBus.java b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestPublicBus.java
index 353ae0d..288c217 100644
--- a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestPublicBus.java
+++ b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestPublicBus.java
@@ -24,13 +24,10 @@ import java.util.concurrent.Callable;
import java.util.concurrent.atomic.AtomicInteger;
import org.joda.time.DateTime;
-import org.killbill.billing.DBTestingHelper;
import org.killbill.billing.account.api.Account;
import org.killbill.billing.api.TestApiListener.NextEvent;
-import org.killbill.billing.beatrix.extbus.DefaultBusExternalEvent;
import org.killbill.billing.callcontext.DefaultCallContext;
import org.killbill.billing.catalog.api.BillingPeriod;
-import org.killbill.billing.catalog.api.PriceListSet;
import org.killbill.billing.catalog.api.ProductCategory;
import org.killbill.billing.entitlement.api.DefaultEntitlement;
import org.killbill.billing.notification.plugin.api.ExtBusEvent;
@@ -46,11 +43,6 @@ import org.killbill.billing.util.callcontext.CallContext;
import org.killbill.billing.util.callcontext.CallOrigin;
import org.killbill.billing.util.callcontext.UserType;
import org.killbill.billing.util.jackson.ObjectMapper;
-import org.killbill.billing.util.nodes.NodeCommand;
-import org.killbill.billing.util.nodes.NodeCommandMetadata;
-import org.killbill.billing.util.nodes.NodeCommandProperty;
-import org.killbill.billing.util.nodes.PluginNodeCommandMetadata;
-import org.killbill.billing.util.nodes.SystemNodeCommandType;
import org.testng.Assert;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
@@ -58,12 +50,11 @@ import org.testng.annotations.Test;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
-import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.eventbus.Subscribe;
-import static org.awaitility.Awaitility.await;
import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.awaitility.Awaitility.await;
import static org.testng.Assert.assertNotNull;
public class TestPublicBus extends TestIntegrationBase {
@@ -123,10 +114,7 @@ public class TestPublicBus extends TestIntegrationBase {
TODO modify sequence to allow optional registration of publicListener
*/
- try {
- DBTestingHelper.get().getInstance().cleanupAllTables();
- } catch (final Exception ignored) {
- }
+ cleanupAllTables();
log.debug("RESET TEST FRAMEWORK");
@@ -149,9 +137,6 @@ public class TestPublicBus extends TestIntegrationBase {
paymentPlugin.clear();
this.externalBusCount = new AtomicInteger(0);
-
- // Make sure we start with a clean state
- assertListenerStatus();
}
@AfterMethod(groups = "slow")
diff --git a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithFakeKPMPlugin.java b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithFakeKPMPlugin.java
index b239488..60e3176 100644
--- a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithFakeKPMPlugin.java
+++ b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestWithFakeKPMPlugin.java
@@ -1,6 +1,6 @@
/*
- * Copyright 2014-2015 Groupon, Inc
- * Copyright 2014-2015 The Billing Project, LLC
+ * 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
@@ -21,7 +21,6 @@ import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
@@ -38,12 +37,10 @@ import org.killbill.billing.notification.plugin.api.ExtBusEventType;
import org.killbill.billing.osgi.BundleRegistry;
import org.killbill.billing.osgi.BundleWithConfig;
import org.killbill.billing.osgi.FileInstall;
-import org.killbill.billing.osgi.PureOSGIBundleFinder;
import org.killbill.billing.osgi.api.PluginInfo;
import org.killbill.billing.osgi.api.PluginStateChange;
import org.killbill.billing.osgi.api.PluginsInfoApi;
import org.killbill.billing.osgi.api.config.PluginConfig;
-import org.killbill.billing.osgi.api.config.PluginConfigServiceApi;
import org.killbill.billing.osgi.api.config.PluginLanguage;
import org.killbill.billing.osgi.api.config.PluginType;
import org.killbill.billing.osgi.config.OSGIConfig;
@@ -51,7 +48,6 @@ import org.killbill.billing.osgi.pluginconf.PluginConfigException;
import org.killbill.billing.osgi.pluginconf.PluginFinder;
import org.killbill.billing.platform.api.KillbillConfigSource;
import org.killbill.billing.util.jackson.ObjectMapper;
-import org.killbill.billing.util.nodes.KillbillNodesApi;
import org.killbill.billing.util.nodes.NodeCommand;
import org.killbill.billing.util.nodes.NodeCommandMetadata;
import org.killbill.billing.util.nodes.NodeCommandProperty;
@@ -61,8 +57,10 @@ import org.killbill.billing.util.nodes.PluginNodeCommandMetadata;
import org.killbill.billing.util.nodes.SystemNodeCommandType;
import org.mockito.Mockito;
import org.osgi.framework.Bundle;
+import org.osgi.framework.launch.Framework;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import com.fasterxml.jackson.databind.SerializationFeature;
@@ -79,8 +77,10 @@ import com.google.inject.Module;
import com.google.inject.Stage;
import com.google.inject.util.Modules;
-import static org.awaitility.Awaitility.await;
import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.awaitility.Awaitility.await;
+import static org.mockito.Mockito.RETURNS_MOCKS;
+import static org.mockito.Mockito.withSettings;
public class TestWithFakeKPMPlugin extends TestIntegrationBase {
@@ -226,13 +226,16 @@ public class TestWithFakeKPMPlugin extends TestIntegrationBase {
@Inject
public FakeBundleRegistry() {
- super(null);
+ super(Mockito.mock(FileInstall.class, withSettings().defaultAnswer(RETURNS_MOCKS)));
bundles = new ArrayList<BundleWithMetadata>();
}
- public void installNewBundle(final String pluginName, @Nullable final String version, final PluginLanguage pluginLanguage) {
+ @Override
+ public void installBundles(final Framework framework) {
+ super.installBundles(framework);
+
final Bundle bundle = Mockito.mock(Bundle.class);
- Mockito.when(bundle.getSymbolicName()).thenReturn(pluginName);
+ Mockito.when(bundle.getSymbolicName()).thenReturn(NEW_PLUGIN_NAME);
final BundleWithConfig config = new BundleWithConfig(bundle, new PluginConfig() {
@Override
@@ -247,7 +250,7 @@ public class TestWithFakeKPMPlugin extends TestIntegrationBase {
@Override
public String getPluginName() {
- return pluginName;
+ return NEW_PLUGIN_NAME;
}
@Override
@@ -257,7 +260,7 @@ public class TestWithFakeKPMPlugin extends TestIntegrationBase {
@Override
public String getVersion() {
- return version;
+ return NEW_PLUGIN_VERSION;
}
@Override
@@ -272,7 +275,7 @@ public class TestWithFakeKPMPlugin extends TestIntegrationBase {
@Override
public PluginLanguage getPluginLanguage() {
- return pluginLanguage;
+ return PluginLanguage.JAVA;
}
@Override
@@ -296,10 +299,6 @@ public class TestWithFakeKPMPlugin extends TestIntegrationBase {
}
}).orNull();
}
-
- public Collection<BundleWithMetadata> getBundles() {
- return bundles;
- }
}
public static class OverrideModuleForOSGI implements Module {
@@ -317,16 +316,12 @@ public class TestWithFakeKPMPlugin extends TestIntegrationBase {
g.injectMembers(this);
}
- @BeforeClass(groups = "slow")
+ @BeforeMethod(groups = "slow")
public void beforeMethod() throws Exception {
-
- try {
- DBTestingHelper.get().getInstance().cleanupAllTables();
- } catch (final Exception ignored) {
- }
-
log.debug("RESET TEST FRAMEWORK");
+ cleanupAllTables();
+
clock.resetDeltaFromReality();
busHandler.reset();
@@ -335,9 +330,6 @@ public class TestWithFakeKPMPlugin extends TestIntegrationBase {
externalBus.register(new FakeKPMPlugin());
lifecycle.fireStartupSequencePostEventRegistration();
-
- // Make sure we start with a clean state
- assertListenerStatus();
}
@Test(groups = "slow")
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 9aa8eb1..52f5921 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
@@ -54,11 +54,6 @@ import com.google.common.collect.ImmutableList;
public class TestConsumableInArrear extends TestIntegrationBase {
- @BeforeMethod(groups = "slow")
- public void beforeMethod() throws Exception {
- super.beforeMethod();
- }
-
@Test(groups = "slow")
public void testWithNoUsageInPeriodAndOldUsage() throws Exception {
// We take april as it has 30 days (easier to play with BCD)
diff --git a/beatrix/src/test/java/org/killbill/billing/beatrix/util/PaymentChecker.java b/beatrix/src/test/java/org/killbill/billing/beatrix/util/PaymentChecker.java
index 03440c5..9925dde 100644
--- a/beatrix/src/test/java/org/killbill/billing/beatrix/util/PaymentChecker.java
+++ b/beatrix/src/test/java/org/killbill/billing/beatrix/util/PaymentChecker.java
@@ -93,7 +93,7 @@ public class PaymentChecker {
final PaymentTransaction transaction = getPurchaseTransaction(payment);
Assert.assertTrue(transaction.getAmount().compareTo(expected.getAmount()) == 0, "Actual amount " + transaction.getAmount() + ", expected amount " + expected.getAmount());
Assert.assertEquals(transaction.getTransactionStatus(), expected.getStatus());
- Assert.assertEquals(transaction.getEffectiveDate().toLocalDate().compareTo(expected.getPaymentDate()), 0);
+ Assert.assertEquals(transaction.getEffectiveDate().toLocalDate().compareTo(expected.getPaymentDate()), 0, "Actual date " + transaction.getEffectiveDate() + ", expected date " + expected.getPaymentDate());
auditChecker.checkPaymentCreated(payment, context);
}
diff --git a/entitlement/src/main/java/org/killbill/billing/entitlement/engine/core/DefaultEventsStream.java b/entitlement/src/main/java/org/killbill/billing/entitlement/engine/core/DefaultEventsStream.java
index c991055..7c84dac 100644
--- a/entitlement/src/main/java/org/killbill/billing/entitlement/engine/core/DefaultEventsStream.java
+++ b/entitlement/src/main/java/org/killbill/billing/entitlement/engine/core/DefaultEventsStream.java
@@ -91,6 +91,7 @@ public class DefaultEventsStream implements EventsStream {
final List<SubscriptionBase> allSubscriptionsForBundle,
final int defaultBillCycleDayLocal,
final InternalTenantContext contextWithValidAccountRecordId, final DateTime utcNow) {
+ sanityChecks(account, bundle, baseSubscription, subscription);
this.account = account;
this.bundle = bundle;
this.blockingStates = blockingStates;
@@ -106,6 +107,20 @@ public class DefaultEventsStream implements EventsStream {
setup();
}
+ private void sanityChecks(@Nullable final ImmutableAccountData account,
+ @Nullable final SubscriptionBaseBundle bundle,
+ @Nullable final SubscriptionBase baseSubscription,
+ @Nullable final SubscriptionBase subscription) {
+ for (final Object object : new Object[]{account, bundle, baseSubscription, subscription}) {
+ Preconditions.checkNotNull(object,
+ "accountId='%s', bundleId='%s', baseSubscriptionId='%s', subscriptionId='%s'",
+ account != null ? account.getId() : null,
+ bundle != null ? bundle.getId() : null,
+ baseSubscription != null ? baseSubscription.getId() : null,
+ subscription != null ? subscription.getId() : null);
+ }
+ }
+
@Override
public UUID getAccountId() {
return account.getId();
diff --git a/entitlement/src/test/java/org/killbill/billing/entitlement/EntitlementTestSuiteWithEmbeddedDB.java b/entitlement/src/test/java/org/killbill/billing/entitlement/EntitlementTestSuiteWithEmbeddedDB.java
index 9f6f218..120548c 100644
--- a/entitlement/src/test/java/org/killbill/billing/entitlement/EntitlementTestSuiteWithEmbeddedDB.java
+++ b/entitlement/src/test/java/org/killbill/billing/entitlement/EntitlementTestSuiteWithEmbeddedDB.java
@@ -140,9 +140,6 @@ public class EntitlementTestSuiteWithEmbeddedDB extends GuicyKillbillTestSuiteWi
startTestFamework(testListener, clock, busService, subscriptionBaseService, entitlementService);
this.catalog = initCatalog(catalogService);
- // Make sure we start with a clean state
- assertListenerStatus();
-
configureShiro();
login("EntitlementUser");
}
@@ -174,12 +171,8 @@ public class EntitlementTestSuiteWithEmbeddedDB extends GuicyKillbillTestSuiteWi
@AfterMethod(groups = "slow")
public void afterMethod() throws Exception {
-
securityApi.logout();
- // Make sure we finish in a clean state
- assertListenerStatus();
-
stopTestFramework(testListener, busService, subscriptionBaseService, entitlementService);
}
@@ -289,6 +282,7 @@ public class EntitlementTestSuiteWithEmbeddedDB extends GuicyKillbillTestSuiteWi
return account;
}
+ @Override
protected void assertListenerStatus() {
testListener.assertListenerStatus();
}
diff --git a/junction/src/test/java/org/killbill/billing/junction/JunctionTestSuiteWithEmbeddedDB.java b/junction/src/test/java/org/killbill/billing/junction/JunctionTestSuiteWithEmbeddedDB.java
index 4eced64..859d024 100644
--- a/junction/src/test/java/org/killbill/billing/junction/JunctionTestSuiteWithEmbeddedDB.java
+++ b/junction/src/test/java/org/killbill/billing/junction/JunctionTestSuiteWithEmbeddedDB.java
@@ -108,16 +108,10 @@ public abstract class JunctionTestSuiteWithEmbeddedDB extends GuicyKillbillTestS
super.beforeMethod();
startTestFamework();
this.catalog = initCatalog(catalogService);
-
- // Make sure we start with a clean state
- assertListenerStatus();
}
@AfterMethod(groups = "slow")
public void afterMethod() throws Exception {
- // Make sure we finish in a clean state
- assertListenerStatus();
-
stopTestFramework();
}
@@ -219,6 +213,7 @@ public abstract class JunctionTestSuiteWithEmbeddedDB extends GuicyKillbillTestS
return account;
}
+ @Override
protected void assertListenerStatus() {
testListener.assertListenerStatus();
}
diff --git a/junction/src/test/java/org/killbill/billing/junction/plumbing/billing/TestDefaultInternalBillingApi.java b/junction/src/test/java/org/killbill/billing/junction/plumbing/billing/TestDefaultInternalBillingApi.java
index c8c99f1..880e6c2 100644
--- a/junction/src/test/java/org/killbill/billing/junction/plumbing/billing/TestDefaultInternalBillingApi.java
+++ b/junction/src/test/java/org/killbill/billing/junction/plumbing/billing/TestDefaultInternalBillingApi.java
@@ -223,6 +223,7 @@ public class TestDefaultInternalBillingApi extends JunctionTestSuiteWithEmbedded
true,
block1Date);
blockingInternalApi.setBlockingState(state1, internalCallContext);
+ assertListenerStatus();
clock.addDays(1);
diff --git a/overdue/src/test/java/org/killbill/billing/overdue/notification/TestOverdueCheckNotifier.java b/overdue/src/test/java/org/killbill/billing/overdue/notification/TestOverdueCheckNotifier.java
index 162d756..4747620 100644
--- a/overdue/src/test/java/org/killbill/billing/overdue/notification/TestOverdueCheckNotifier.java
+++ b/overdue/src/test/java/org/killbill/billing/overdue/notification/TestOverdueCheckNotifier.java
@@ -69,9 +69,10 @@ public class TestOverdueCheckNotifier extends OverdueTestSuiteWithEmbeddedDB {
@Override
@BeforeMethod(groups = "slow")
public void beforeMethod() throws Exception {
- //super.beforeMethod();
// We override the parent method on purpose, because we want to register a different OverdueCheckNotifier
+ cleanupAllTables();
+
mockDispatcher = new OverdueDispatcherMock(internalCallContextFactory);
notifierForMock = new OverdueCheckNotifier(notificationQueueService, overdueProperties, internalCallContextFactory, mockDispatcher);
diff --git a/payment/src/test/java/org/killbill/billing/payment/TestJanitor.java b/payment/src/test/java/org/killbill/billing/payment/TestJanitor.java
index 73d4bbd..cc247ca 100644
--- a/payment/src/test/java/org/killbill/billing/payment/TestJanitor.java
+++ b/payment/src/test/java/org/killbill/billing/payment/TestJanitor.java
@@ -115,6 +115,11 @@ public class TestJanitor extends PaymentTestSuiteWithEmbeddedDB {
);
}
+ @Override
+ protected void assertListenerStatus() {
+ testListener.assertListenerStatus();
+ }
+
@BeforeClass(groups = "slow")
protected void beforeClass() throws Exception {
super.beforeClass();
@@ -133,16 +138,12 @@ public class TestJanitor extends PaymentTestSuiteWithEmbeddedDB {
eventBus.register(testListener);
mockPaymentProviderPlugin.clear();
account = testHelper.createTestAccount("bobo@gmail.com", true);
-
- testListener.assertListenerStatus();
}
@AfterMethod(groups = "slow")
public void afterMethod() throws Exception {
retryService.stop();
- testListener.assertListenerStatus();
-
eventBus.unregister(handler);
eventBus.unregister(testListener);
super.afterMethod();
pom.xml 2(+1 -1)
diff --git a/pom.xml b/pom.xml
index 6937aef..c9092c4 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.140.40</version>
+ <version>0.140.42</version>
</parent>
<artifactId>killbill</artifactId>
<version>0.18.14-SNAPSHOT</version>
diff --git a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestEntitlement.java b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestEntitlement.java
index 1378fd1..582bd90 100644
--- a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestEntitlement.java
+++ b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestEntitlement.java
@@ -22,6 +22,7 @@ import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
+import java.util.regex.Pattern;
import org.joda.time.DateTime;
import org.joda.time.Interval;
@@ -258,20 +259,20 @@ public class TestEntitlement extends TestJaxrsBase {
Assert.assertEquals(subscription.getEvents().size(), 3);
Assert.assertEquals(subscription.getEvents().get(0).getEventType(), SubscriptionEventType.START_ENTITLEMENT.name());
- Assert.assertEquals(subscription.getEvents().get(0).getPlan(), "shotgun-monthly-1");
- Assert.assertEquals(subscription.getEvents().get(0).getPhase(), "shotgun-monthly-1-trial");
+ assertMatches(subscription.getEvents().get(0).getPlan(), "shotgun-monthly-[1-9]+");
+ assertMatches(subscription.getEvents().get(0).getPhase(), "shotgun-monthly-[1-9]+-trial");
Assert.assertEquals(subscription.getEvents().get(0).getPriceList(), PriceListSet.DEFAULT_PRICELIST_NAME.toString());
Assert.assertEquals(subscription.getEvents().get(0).getProduct(), "Shotgun");
Assert.assertEquals(subscription.getEvents().get(1).getEventType(), SubscriptionEventType.START_BILLING.name());
- Assert.assertEquals(subscription.getEvents().get(1).getPlan(), "shotgun-monthly-1");
- Assert.assertEquals(subscription.getEvents().get(1).getPhase(), "shotgun-monthly-1-trial");
+ assertMatches(subscription.getEvents().get(1).getPlan(), "shotgun-monthly-[1-9]+");
+ assertMatches(subscription.getEvents().get(1).getPhase(), "shotgun-monthly-[1-9]+-trial");
Assert.assertEquals(subscription.getEvents().get(1).getPriceList(), PriceListSet.DEFAULT_PRICELIST_NAME.toString());
Assert.assertEquals(subscription.getEvents().get(1).getProduct(), "Shotgun");
Assert.assertEquals(subscription.getEvents().get(2).getEventType(), SubscriptionEventType.PHASE.name());
- Assert.assertEquals(subscription.getEvents().get(2).getPlan(), "shotgun-monthly-1");
- Assert.assertEquals(subscription.getEvents().get(2).getPhase(), "shotgun-monthly-1-evergreen");
+ assertMatches(subscription.getEvents().get(2).getPlan(), "shotgun-monthly-[1-9]+");
+ assertMatches(subscription.getEvents().get(2).getPhase(), "shotgun-monthly-[1-9]+-evergreen");
Assert.assertEquals(subscription.getEvents().get(2).getPriceList(), PriceListSet.DEFAULT_PRICELIST_NAME.toString());
Assert.assertEquals(subscription.getEvents().get(2).getProduct(), "Shotgun");
@@ -297,20 +298,20 @@ public class TestEntitlement extends TestJaxrsBase {
Assert.assertEquals(subscription3.getEvents().size(), 4);
Assert.assertEquals(subscription3.getEvents().get(0).getEventType(), SubscriptionEventType.START_ENTITLEMENT.name());
- Assert.assertEquals(subscription3.getEvents().get(0).getPlan(), "shotgun-monthly-1");
- Assert.assertEquals(subscription3.getEvents().get(0).getPhase(), "shotgun-monthly-1-trial");
+ assertMatches(subscription3.getEvents().get(0).getPlan(), "shotgun-monthly-[1-9]+");
+ assertMatches(subscription3.getEvents().get(0).getPhase(), "shotgun-monthly-[1-9]+-trial");
Assert.assertEquals(subscription3.getEvents().get(0).getPriceList(), PriceListSet.DEFAULT_PRICELIST_NAME.toString());
Assert.assertEquals(subscription3.getEvents().get(0).getProduct(), "Shotgun");
Assert.assertEquals(subscription3.getEvents().get(1).getEventType(), SubscriptionEventType.START_BILLING.name());
- Assert.assertEquals(subscription3.getEvents().get(1).getPlan(), "shotgun-monthly-1");
- Assert.assertEquals(subscription3.getEvents().get(1).getPhase(), "shotgun-monthly-1-trial");
+ assertMatches(subscription3.getEvents().get(1).getPlan(), "shotgun-monthly-[1-9]+");
+ assertMatches(subscription3.getEvents().get(1).getPhase(), "shotgun-monthly-[1-9]+-trial");
Assert.assertEquals(subscription3.getEvents().get(1).getPriceList(), PriceListSet.DEFAULT_PRICELIST_NAME.toString());
Assert.assertEquals(subscription3.getEvents().get(1).getProduct(), "Shotgun");
Assert.assertEquals(subscription3.getEvents().get(2).getEventType(), SubscriptionEventType.PHASE.name());
- Assert.assertEquals(subscription3.getEvents().get(2).getPlan(), "shotgun-monthly-1");
- Assert.assertEquals(subscription3.getEvents().get(2).getPhase(), "shotgun-monthly-1-evergreen");
+ assertMatches(subscription3.getEvents().get(2).getPlan(), "shotgun-monthly-[1-9]+");
+ assertMatches(subscription3.getEvents().get(2).getPhase(), "shotgun-monthly-[1-9]+-evergreen");
Assert.assertEquals(subscription3.getEvents().get(2).getPriceList(), PriceListSet.DEFAULT_PRICELIST_NAME.toString());
Assert.assertEquals(subscription3.getEvents().get(2).getProduct(), "Shotgun");
@@ -321,6 +322,10 @@ public class TestEntitlement extends TestJaxrsBase {
Assert.assertEquals(subscription3.getEvents().get(3).getProduct(), "Pistol");
}
+ private void assertMatches(final String actual, final String regexp) {
+ Assert.assertTrue(Pattern.compile(regexp).matcher(actual).matches(), String.format("%s doesn't match pattern %s", actual, regexp));
+ }
+
@Test(groups = "slow", description = "Create a base entitlement and also addOns entitlements under the same bundle")
public void testEntitlementWithAddOnsWithWRITTEN_OFF() throws Exception {
final DateTime initialDate = new DateTime(2012, 4, 25, 0, 3, 42, 0);
diff --git a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestInvoice.java b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestInvoice.java
index 389156a..d94d4d1 100644
--- a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestInvoice.java
+++ b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestInvoice.java
@@ -27,6 +27,7 @@ import java.util.UUID;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalDate;
+import org.killbill.billing.api.FlakyRetryAnalyzer;
import org.killbill.billing.catalog.api.BillingPeriod;
import org.killbill.billing.catalog.api.ProductCategory;
import org.killbill.billing.client.KillBillClientException;
@@ -492,7 +493,8 @@ public class TestInvoice extends TestJaxrsBase {
assertEquals(killBillClient.getInvoicesForAccount(accountJson.getAccountId()).size(), 3);
}
- @Test(groups = "slow", description = "Can create multiple external charges with same invoice and external keys")
+ // Flaky, see https://github.com/killbill/killbill/issues/801
+ @Test(groups = "slow", description = "Can create multiple external charges with same invoice and external keys", retryAnalyzer = FlakyRetryAnalyzer.class)
public void testExternalChargesWithSameInvoiceAndExternalKeys() throws Exception {
final Account accountJson = createAccountWithPMBundleAndSubscriptionAndWaitForFirstInvoice();
diff --git a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestJaxrsBase.java b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestJaxrsBase.java
index 66007ef..333cb3e 100644
--- a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestJaxrsBase.java
+++ b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestJaxrsBase.java
@@ -18,6 +18,9 @@
package org.killbill.billing.jaxrs;
+import java.lang.management.ManagementFactory;
+import java.lang.management.ThreadInfo;
+import java.lang.management.ThreadMXBean;
import java.util.EventListener;
import java.util.Iterator;
import java.util.List;
@@ -37,7 +40,6 @@ import org.killbill.billing.GuicyKillbillTestWithEmbeddedDBModule;
import org.killbill.billing.api.TestApiListener;
import org.killbill.billing.client.KillBillClient;
import org.killbill.billing.client.KillBillHttpClient;
-import org.killbill.billing.client.RequestOptions;
import org.killbill.billing.client.model.Payment;
import org.killbill.billing.client.model.PaymentTransaction;
import org.killbill.billing.client.model.Tenant;
@@ -61,6 +63,8 @@ import org.killbill.billing.util.config.definition.SecurityConfig;
import org.killbill.bus.api.PersistentBus;
import org.killbill.commons.jdbi.guice.DaoConfig;
import org.skife.config.ConfigurationObjectFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeClass;
@@ -77,6 +81,12 @@ import com.google.inject.util.Modules;
public class TestJaxrsBase extends KillbillClient {
+ private static final Logger log = LoggerFactory.getLogger(TestJaxrsBase.class);
+
+ protected final int DEFAULT_CONNECT_TIMEOUT_SEC = 10;
+ protected final int DEFAULT_READ_TIMEOUT_SEC = 60;
+ protected final int DEFAULT_REQUEST_TIMEOUT_SEC = DEFAULT_READ_TIMEOUT_SEC;
+
protected static final String PLUGIN_NAME = "noop";
@Inject
@@ -168,7 +178,12 @@ public class TestJaxrsBase extends KillbillClient {
username,
password,
apiKey,
- apiSecret);
+ apiSecret,
+ null,
+ null,
+ DEFAULT_CONNECT_TIMEOUT_SEC * 1000,
+ DEFAULT_READ_TIMEOUT_SEC * 1000,
+ DEFAULT_REQUEST_TIMEOUT_SEC * 1000);
killBillClient = new KillBillClient(killBillHttpClient);
}
@@ -294,4 +309,24 @@ public class TestJaxrsBase extends KillbillClient {
})));
}
+ protected void printThreadDump() {
+ final StringBuilder dump = new StringBuilder("Thread dump:\n");
+ final ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
+ final ThreadInfo[] threadInfos = threadMXBean.getThreadInfo(threadMXBean.getAllThreadIds(), 100);
+ for (final ThreadInfo threadInfo : threadInfos) {
+ dump.append('"');
+ dump.append(threadInfo.getThreadName());
+ dump.append("\" ");
+ final Thread.State state = threadInfo.getThreadState();
+ dump.append("\n java.lang.Thread.State: ");
+ dump.append(state);
+ final StackTraceElement[] stackTraceElements = threadInfo.getStackTrace();
+ for (final StackTraceElement stackTraceElement : stackTraceElements) {
+ dump.append("\n at ");
+ dump.append(stackTraceElement);
+ }
+ dump.append("\n\n");
+ }
+ log.warn(dump.toString());
+ }
}
diff --git a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestPushNotification.java b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestPushNotification.java
index 1c6b542..28eb1ee 100644
--- a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestPushNotification.java
+++ b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestPushNotification.java
@@ -1,7 +1,7 @@
/*
* Copyright 2010-2013 Ning, Inc.
- * Copyright 2014-2015 Groupon, Inc
- * Copyright 2014-2015 The Billing Project, LLC
+ * 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
@@ -74,8 +74,16 @@ public class TestPushNotification extends TestJaxrsBase {
callbackServer.stopServer();
}
+ private void assertAllCallbacksCompleted() throws InterruptedException {
+ final boolean waitForCallbacksToComplete = waitForCallbacksToComplete();
+ if (!waitForCallbacksToComplete) {
+ printThreadDump();
+ }
+ Assert.assertTrue(waitForCallbacksToComplete, "Fail to see push notification callbacks");
+ }
+
private boolean waitForCallbacksToComplete() throws InterruptedException {
- long remainingMs = 30000;
+ long remainingMs = DEFAULT_REQUEST_TIMEOUT_SEC * 1000;
do {
if (callbackCompleted) {
break;
@@ -107,10 +115,7 @@ public class TestPushNotification extends TestJaxrsBase {
// Create account to trigger a push notification
createAccount();
- final boolean success = waitForCallbacksToComplete();
- if (!success) {
- Assert.fail("Fail to see push notification callbacks after 5 sec");
- }
+ assertAllCallbacksCompleted();
if (callbackCompletedWithError) {
Assert.fail("Assertion during callback failed...");
@@ -135,7 +140,7 @@ public class TestPushNotification extends TestJaxrsBase {
final String callback = "http://127.0.0.1:" + SERVER_PORT + CALLBACK_ENDPOINT;
final TenantKey result0 = killBillClient.registerCallbackNotificationForTenant(callback, requestOptions);
- Assert.assertTrue(waitForCallbacksToComplete());
+ assertAllCallbacksCompleted();
Assert.assertTrue(callbackCompletedWithError); // expected true because is not an ACCOUNT_CREATION event
Assert.assertEquals(result0.getKey(), TenantKV.TenantKey.PUSH_NOTIFICATION_CB.toString());
@@ -167,7 +172,7 @@ public class TestPushNotification extends TestJaxrsBase {
// Create account to trigger a push notification
createAccount();
- Assert.assertTrue(waitForCallbacksToComplete());
+ assertAllCallbacksCompleted();
Assert.assertTrue(callbackCompletedWithError);
resetCallbackStatusProperties();
@@ -175,7 +180,7 @@ public class TestPushNotification extends TestJaxrsBase {
// move clock 15 minutes and get 1st retry
clock.addDeltaFromReality(900000);
- Assert.assertTrue(waitForCallbacksToComplete());
+ assertAllCallbacksCompleted();
Assert.assertTrue(callbackCompletedWithError);
resetCallbackStatusProperties();
@@ -183,7 +188,7 @@ public class TestPushNotification extends TestJaxrsBase {
// move clock an hour and get 2nd retry
clock.addDeltaFromReality(3600000);
- Assert.assertTrue(waitForCallbacksToComplete());
+ assertAllCallbacksCompleted();
Assert.assertTrue(callbackCompletedWithError);
resetCallbackStatusProperties();
@@ -194,7 +199,7 @@ public class TestPushNotification extends TestJaxrsBase {
// move clock a day, get 3rd retry and wait for a success push notification
clock.addDays(1);
- Assert.assertTrue(waitForCallbacksToComplete());
+ assertAllCallbacksCompleted();
Assert.assertFalse(callbackCompletedWithError);
unregisterTenantForCallback(callback);
@@ -221,7 +226,7 @@ public class TestPushNotification extends TestJaxrsBase {
// Create account to trigger a push notification
createAccount();
- Assert.assertTrue(waitForCallbacksToComplete());
+ assertAllCallbacksCompleted();
Assert.assertTrue(callbackCompletedWithError);
resetCallbackStatusProperties();
@@ -229,7 +234,7 @@ public class TestPushNotification extends TestJaxrsBase {
// move clock 15 minutes and get 1st retry
clock.addDeltaFromReality(900000);
- Assert.assertTrue(waitForCallbacksToComplete());
+ assertAllCallbacksCompleted();
Assert.assertTrue(callbackCompletedWithError);
resetCallbackStatusProperties();
@@ -237,7 +242,7 @@ public class TestPushNotification extends TestJaxrsBase {
// move clock an hour and get 2nd retry
clock.addDeltaFromReality(3600000);
- Assert.assertTrue(waitForCallbacksToComplete());
+ assertAllCallbacksCompleted();
Assert.assertTrue(callbackCompletedWithError);
resetCallbackStatusProperties();
@@ -245,7 +250,7 @@ public class TestPushNotification extends TestJaxrsBase {
// move clock a day and get 3rd retry
clock.addDays(1);
- Assert.assertTrue(waitForCallbacksToComplete());
+ assertAllCallbacksCompleted();
Assert.assertTrue(callbackCompletedWithError);
resetCallbackStatusProperties();
@@ -253,7 +258,7 @@ public class TestPushNotification extends TestJaxrsBase {
// move clock a day and get 4rd retry
clock.addDays(2);
- Assert.assertTrue(waitForCallbacksToComplete());
+ assertAllCallbacksCompleted();
Assert.assertTrue(callbackCompletedWithError);
resetCallbackStatusProperties();
diff --git a/subscription/src/test/java/org/killbill/billing/subscription/SubscriptionTestSuiteNoDB.java b/subscription/src/test/java/org/killbill/billing/subscription/SubscriptionTestSuiteNoDB.java
index b90587c..e42bc0d 100644
--- a/subscription/src/test/java/org/killbill/billing/subscription/SubscriptionTestSuiteNoDB.java
+++ b/subscription/src/test/java/org/killbill/billing/subscription/SubscriptionTestSuiteNoDB.java
@@ -151,6 +151,7 @@ public class SubscriptionTestSuiteNoDB extends GuicyKillbillTestSuiteNoDB {
subscriptionTestInitializer.stopTestFramework(testListener, busService, subscriptionBaseService);
}
+ @Override
protected void assertListenerStatus() {
testListener.assertListenerStatus();
}
diff --git a/subscription/src/test/java/org/killbill/billing/subscription/SubscriptionTestSuiteWithEmbeddedDB.java b/subscription/src/test/java/org/killbill/billing/subscription/SubscriptionTestSuiteWithEmbeddedDB.java
index e97f3e0..02ce1be 100644
--- a/subscription/src/test/java/org/killbill/billing/subscription/SubscriptionTestSuiteWithEmbeddedDB.java
+++ b/subscription/src/test/java/org/killbill/billing/subscription/SubscriptionTestSuiteWithEmbeddedDB.java
@@ -115,16 +115,10 @@ public class SubscriptionTestSuiteWithEmbeddedDB extends GuicyKillbillTestSuiteW
this.accountData = subscriptionTestInitializer.initAccountData();
final Account account = createAccount(accountData);
this.bundle = subscriptionTestInitializer.initBundle(account.getId(), subscriptionInternalApi, internalCallContext);
-
- // Make sure we start with a clean state
- assertListenerStatus();
}
@AfterMethod(groups = "slow")
public void afterMethod() throws Exception {
- // Make sure we finish in a clean state
- assertListenerStatus();
-
subscriptionTestInitializer.stopTestFramework(testListener, busService, subscriptionBaseService);
}
@@ -136,6 +130,7 @@ public class SubscriptionTestSuiteWithEmbeddedDB extends GuicyKillbillTestSuiteW
return account;
}
+ @Override
protected void assertListenerStatus() {
testListener.assertListenerStatus();
}
diff --git a/tenant/src/test/java/org/killbill/billing/tenant/TenantTestSuiteWithEmbeddedDb.java b/tenant/src/test/java/org/killbill/billing/tenant/TenantTestSuiteWithEmbeddedDb.java
index 060a087..45486dc 100644
--- a/tenant/src/test/java/org/killbill/billing/tenant/TenantTestSuiteWithEmbeddedDb.java
+++ b/tenant/src/test/java/org/killbill/billing/tenant/TenantTestSuiteWithEmbeddedDb.java
@@ -58,13 +58,4 @@ public class TenantTestSuiteWithEmbeddedDb extends GuicyKillbillTestSuiteWithEmb
final Injector injector = Guice.createInjector(new TestTenantModuleWithEmbeddedDB(configSource));
injector.injectMembers(this);
}
-
- @BeforeMethod(groups = "slow")
- public void beforeMethod() throws Exception {
- super.beforeMethod();
- }
-
- @AfterMethod(groups = "slow")
- public void afterMethod() {
- }
}
diff --git a/util/src/main/java/org/killbill/billing/util/cache/CacheControllerDispatcherProvider.java b/util/src/main/java/org/killbill/billing/util/cache/CacheControllerDispatcherProvider.java
index 7d9ce76..2ce2b6f 100644
--- a/util/src/main/java/org/killbill/billing/util/cache/CacheControllerDispatcherProvider.java
+++ b/util/src/main/java/org/killbill/billing/util/cache/CacheControllerDispatcherProvider.java
@@ -31,6 +31,8 @@ import org.killbill.billing.util.cache.Cachable.CacheType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.base.Preconditions;
+
// Build the abstraction layer between EhCache and Kill Bill
public class CacheControllerDispatcherProvider implements Provider<CacheControllerDispatcher> {
@@ -57,6 +59,7 @@ public class CacheControllerDispatcherProvider implements Provider<CacheControll
logger.warn("Cache for cacheName='{}' not configured - check your ehcache.xml", cacheLoader.getCacheType().getCacheName());
continue;
}
+ Preconditions.checkState(!cache.isClosed(), "Cache '%s' should not be closed", cacheType.getCacheName());
final CacheController<Object, Object> ehCacheBasedCacheController = new EhCacheBasedCacheController<Object, Object>(cache, cacheLoader);
cacheControllers.put(cacheType, ehCacheBasedCacheController);
diff --git a/util/src/main/java/org/killbill/billing/util/glue/CacheProviderBase.java b/util/src/main/java/org/killbill/billing/util/glue/CacheProviderBase.java
index 24f2dbf..222dc7f 100644
--- a/util/src/main/java/org/killbill/billing/util/glue/CacheProviderBase.java
+++ b/util/src/main/java/org/killbill/billing/util/glue/CacheProviderBase.java
@@ -32,6 +32,7 @@ import com.codahale.metrics.Metric;
import com.codahale.metrics.MetricFilter;
import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.jcache.JCacheGaugeSet;
+import com.google.common.base.Preconditions;
abstract class CacheProviderBase {
@@ -61,6 +62,7 @@ abstract class CacheProviderBase {
final MutableConfiguration<K, V> configuration = new MutableConfiguration<K, V>().setTypes(keyType, valueType)
.setStoreByValue(false); // Store by reference to avoid copying large objects (e.g. catalog)
final Cache<K, V> cache = cacheManager.createCache(cacheName, configuration);
+ Preconditions.checkState(!cache.isClosed(), "Cache '%s' should not be closed", cacheName);
// Re-create the metrics to support dynamically created caches (e.g. for Shiro)
metricRegistry.removeMatching(new MetricFilter() {
diff --git a/util/src/main/java/org/killbill/billing/util/glue/Eh107CacheManagerProvider.java b/util/src/main/java/org/killbill/billing/util/glue/Eh107CacheManagerProvider.java
index 005afa3..d5de5cc 100644
--- a/util/src/main/java/org/killbill/billing/util/glue/Eh107CacheManagerProvider.java
+++ b/util/src/main/java/org/killbill/billing/util/glue/Eh107CacheManagerProvider.java
@@ -27,6 +27,7 @@ import javax.cache.spi.CachingProvider;
import javax.inject.Inject;
import javax.inject.Provider;
+import org.ehcache.core.spi.store.InternalCacheManager;
import org.killbill.billing.util.cache.BaseCacheLoader;
import org.killbill.billing.util.config.definition.EhCacheConfig;
import org.slf4j.Logger;
@@ -38,6 +39,7 @@ import com.codahale.metrics.MetricRegistry;
public class Eh107CacheManagerProvider extends CacheProviderBase implements Provider<CacheManager> {
private static final Logger logger = LoggerFactory.getLogger(Eh107CacheManagerProvider.class);
+ private static final EhcacheLoggingListener ehcacheLoggingListener = new EhcacheLoggingListener();
private final Set<BaseCacheLoader> cacheLoaders;
@@ -65,6 +67,10 @@ public class Eh107CacheManagerProvider extends CacheProviderBase implements Prov
cacheManager = cachingProvider.getCacheManager();
}
+ // Make sure we start from a clean state - this is mainly useful for tests
+ cacheManager.unwrap(InternalCacheManager.class).deregisterListener(ehcacheLoggingListener);
+ cacheManager.unwrap(InternalCacheManager.class).registerListener(ehcacheLoggingListener);
+
for (final BaseCacheLoader<?, ?> cacheLoader : cacheLoaders) {
createCache(cacheManager,
cacheLoader.getCacheType().getCacheName(),
diff --git a/util/src/main/java/org/killbill/billing/util/glue/EhcacheLoggingListener.java b/util/src/main/java/org/killbill/billing/util/glue/EhcacheLoggingListener.java
new file mode 100644
index 0000000..721072e
--- /dev/null
+++ b/util/src/main/java/org/killbill/billing/util/glue/EhcacheLoggingListener.java
@@ -0,0 +1,44 @@
+/*
+ * 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.util.glue;
+
+import org.ehcache.Cache;
+import org.ehcache.Status;
+import org.ehcache.core.events.CacheManagerListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class EhcacheLoggingListener implements CacheManagerListener {
+
+ private static final Logger logger = LoggerFactory.getLogger(EhcacheLoggingListener.class);
+
+ @Override
+ public void cacheAdded(final String alias, final Cache<?, ?> cache) {
+ logger.info("Added Ehcache '{}'", alias);
+ }
+
+ @Override
+ public void cacheRemoved(final String alias, final Cache<?, ?> cache) {
+ logger.info("Removed Ehcache '{}'", alias);
+ }
+
+ @Override
+ public void stateTransition(final Status from, final Status to) {
+ logger.info("Transitioning Ehcache from '{}' to '{}'", from, to);
+ }
+}
diff --git a/util/src/test/java/org/killbill/billing/api/FlakyInvokedMethodListener.java b/util/src/test/java/org/killbill/billing/api/FlakyInvokedMethodListener.java
new file mode 100644
index 0000000..80ad169
--- /dev/null
+++ b/util/src/test/java/org/killbill/billing/api/FlakyInvokedMethodListener.java
@@ -0,0 +1,47 @@
+/*
+ * 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.api;
+
+import org.testng.IInvokedMethod;
+import org.testng.IInvokedMethodListener;
+import org.testng.IRetryAnalyzer;
+import org.testng.ITestResult;
+import org.testng.Reporter;
+
+public class FlakyInvokedMethodListener implements IInvokedMethodListener {
+
+ @Override
+ public void beforeInvocation(final IInvokedMethod method, final ITestResult testResult) {
+ }
+
+ @Override
+ public void afterInvocation(final IInvokedMethod method, final ITestResult testResult) {
+ if (testResult.getStatus() != ITestResult.FAILURE) {
+ return;
+ }
+
+ final IRetryAnalyzer retryAnalyzer = testResult.getMethod().getRetryAnalyzer();
+ if (retryAnalyzer != null &&
+ retryAnalyzer instanceof FlakyRetryAnalyzer &&
+ !((FlakyRetryAnalyzer) retryAnalyzer).shouldRetry()) {
+ // Don't fail the build (flaky test), mark it as SKIPPED
+ testResult.setStatus(ITestResult.SKIP);
+ Reporter.setCurrentTestResult(testResult);
+ }
+ }
+}
diff --git a/util/src/test/java/org/killbill/billing/api/FlakyRetryAnalyzer.java b/util/src/test/java/org/killbill/billing/api/FlakyRetryAnalyzer.java
new file mode 100644
index 0000000..9cacc19
--- /dev/null
+++ b/util/src/test/java/org/killbill/billing/api/FlakyRetryAnalyzer.java
@@ -0,0 +1,46 @@
+/*
+ * 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.api;
+
+import org.testng.IRetryAnalyzer;
+import org.testng.ITestResult;
+
+public class FlakyRetryAnalyzer implements IRetryAnalyzer {
+
+ private static final int MAX_RETRIES = 3;
+
+ private int count = 0;
+
+ @Override
+ public boolean retry(final ITestResult iTestResult) {
+ if (iTestResult.isSuccess()) {
+ return false;
+ }
+
+ if (shouldRetry()) {
+ count++;
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ public boolean shouldRetry() {
+ return count < MAX_RETRIES;
+ }
+}
diff --git a/util/src/test/java/org/killbill/billing/api/TestApiListener.java b/util/src/test/java/org/killbill/billing/api/TestApiListener.java
index 886dd99..fd0bc8c 100644
--- a/util/src/test/java/org/killbill/billing/api/TestApiListener.java
+++ b/util/src/test/java/org/killbill/billing/api/TestApiListener.java
@@ -63,7 +63,7 @@ public class TestApiListener {
private static final Joiner SPACE_JOINER = Joiner.on(" ");
- private static final long DELAY = 25000;
+ private static final long DELAY = 60000;
private final List<NextEvent> nextExpectedEvent;
private final IDBI idbi;
diff --git a/util/src/test/java/org/killbill/billing/DBTestingHelper.java b/util/src/test/java/org/killbill/billing/DBTestingHelper.java
index 7046879..de0640b 100644
--- a/util/src/test/java/org/killbill/billing/DBTestingHelper.java
+++ b/util/src/test/java/org/killbill/billing/DBTestingHelper.java
@@ -79,14 +79,16 @@ public class DBTestingHelper extends PlatformDBTestingHelper {
"CREATE TABLE accounts (\n" +
" record_id serial unique,\n" +
" id varchar(36) NOT NULL,\n" +
- " external_key varchar(128) NULL,\n" +
- " email varchar(128) NOT NULL,\n" +
- " name varchar(100) NOT NULL,\n" +
- " first_name_length int NOT NULL,\n" +
+ " external_key varchar(255) NULL,\n" +
+ " email varchar(128) DEFAULT NULL,\n" +
+ " name varchar(100) DEFAULT NULL,\n" +
+ " first_name_length int DEFAULT NULL,\n" +
" currency varchar(3) DEFAULT NULL,\n" +
" billing_cycle_day_local int DEFAULT NULL,\n" +
+ " parent_account_id varchar(36) DEFAULT NULL,\n" +
+ " is_payment_delegated_to_parent boolean DEFAULT FALSE,\n" +
" payment_method_id varchar(36) DEFAULT NULL,\n" +
- " time_zone varchar(50) DEFAULT NULL,\n" +
+ " time_zone varchar(50) NOT NULL,\n" +
" locale varchar(5) DEFAULT NULL,\n" +
" address1 varchar(100) DEFAULT NULL,\n" +
" address2 varchar(100) DEFAULT NULL,\n" +
@@ -96,6 +98,7 @@ public class DBTestingHelper extends PlatformDBTestingHelper {
" country varchar(50) DEFAULT NULL,\n" +
" postal_code varchar(16) DEFAULT NULL,\n" +
" phone varchar(25) DEFAULT NULL,\n" +
+ " notes varchar(4096) DEFAULT NULL,\n" +
" migrated boolean default false,\n" +
" is_notified_for_invoices boolean NOT NULL,\n" +
" created_date datetime NOT NULL,\n" +
@@ -109,7 +112,7 @@ public class DBTestingHelper extends PlatformDBTestingHelper {
"CREATE TABLE tenants (\n" +
" record_id serial unique,\n" +
" id varchar(36) NOT NULL,\n" +
- " external_key varchar(128) NULL,\n" +
+ " external_key varchar(255) NULL,\n" +
" api_key varchar(128) NULL,\n" +
" api_secret varchar(128) NULL,\n" +
" api_salt varchar(128) NULL,\n" +
@@ -125,9 +128,10 @@ public class DBTestingHelper extends PlatformDBTestingHelper {
"CREATE TABLE bundles (\n" +
" record_id serial unique,\n" +
" id varchar(36) NOT NULL,\n" +
- " external_key varchar(64) NOT NULL,\n" +
+ " external_key varchar(255) NOT NULL,\n" +
" account_id varchar(36) NOT NULL,\n" +
" last_sys_update_date datetime,\n" +
+ " original_created_date datetime NOT NULL,\n" +
" created_by varchar(50) NOT NULL,\n" +
" created_date datetime NOT NULL,\n" +
" updated_by varchar(50) NOT NULL,\n" +
@@ -144,9 +148,8 @@ public class DBTestingHelper extends PlatformDBTestingHelper {
" category varchar(32) NOT NULL,\n" +
" start_date datetime NOT NULL,\n" +
" bundle_start_date datetime NOT NULL,\n" +
- " active_version int DEFAULT 1,\n" +
" charged_through_date datetime DEFAULT NULL,\n" +
- " paid_through_date datetime DEFAULT NULL,\n" +
+ " migrated bool NOT NULL default FALSE,\n" +
" created_by varchar(50) NOT NULL,\n" +
" created_date datetime NOT NULL,\n" +
" updated_by varchar(50) NOT NULL,\n" +
@@ -162,12 +165,10 @@ public class DBTestingHelper extends PlatformDBTestingHelper {
" record_id serial unique,\n" +
" id varchar(36) NOT NULL,\n" +
" account_id varchar(36) NOT NULL,\n" +
- " invoice_id varchar(36) NOT NULL,\n" +
" payment_method_id varchar(36) NOT NULL,\n" +
- " amount numeric(15,9),\n" +
- " currency varchar(3),\n" +
- " effective_date datetime,\n" +
- " payment_status varchar(50),\n" +
+ " external_key varchar(255) NOT NULL,\n" +
+ " state_name varchar(64) DEFAULT NULL,\n" +
+ " last_success_state_name varchar(64) DEFAULT NULL,\n" +
" created_by varchar(50) NOT NULL,\n" +
" created_date datetime NOT NULL,\n" +
" updated_by varchar(50) NOT NULL,\n" +
diff --git a/util/src/test/java/org/killbill/billing/GuicyKillbillTestSuite.java b/util/src/test/java/org/killbill/billing/GuicyKillbillTestSuite.java
index c7ba40e..79008a6 100644
--- a/util/src/test/java/org/killbill/billing/GuicyKillbillTestSuite.java
+++ b/util/src/test/java/org/killbill/billing/GuicyKillbillTestSuite.java
@@ -1,7 +1,7 @@
/*
* Copyright 2010-2013 Ning, Inc.
- * Copyright 2014-2016 Groupon, Inc
- * Copyright 2014-2016 The Billing Project, LLC
+ * 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
@@ -23,6 +23,7 @@ import java.util.UUID;
import javax.inject.Inject;
+import org.killbill.billing.api.FlakyInvokedMethodListener;
import org.killbill.billing.callcontext.InternalTenantContext;
import org.killbill.billing.callcontext.MutableInternalCallContext;
import org.killbill.billing.platform.api.KillbillConfigSource;
@@ -35,13 +36,17 @@ import org.killbill.clock.ClockMock;
import org.skife.config.ConfigSource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.testng.IHookCallBack;
+import org.testng.IHookable;
import org.testng.ITestResult;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Listeners;
import com.google.common.collect.ImmutableMap;
-public class GuicyKillbillTestSuite {
+@Listeners(FlakyInvokedMethodListener.class)
+public class GuicyKillbillTestSuite implements IHookable {
// Use the simple name here to save screen real estate
protected static final Logger log = LoggerFactory.getLogger(KillbillTestSuite.class.getSimpleName());
@@ -143,6 +148,24 @@ public class GuicyKillbillTestSuite {
}
}
+ // Note: assertions should not be run in before / after hooks, as the associated test result won't be correctly updated.
+ // Use this wrapper instead.
+ @Override
+ public void run(final IHookCallBack callBack, final ITestResult testResult) {
+ // Make sure we start with a clean state
+ assertListenerStatus();
+
+ // Run the actual test
+ callBack.runTestMethod(testResult);
+
+ // Make sure we finish in a clean state
+ assertListenerStatus();
+ }
+
+ protected void assertListenerStatus() {
+ // No-op
+ }
+
public boolean hasFailed() {
return hasFailed;
}
diff --git a/util/src/test/java/org/killbill/billing/GuicyKillbillTestSuiteWithEmbeddedDB.java b/util/src/test/java/org/killbill/billing/GuicyKillbillTestSuiteWithEmbeddedDB.java
index 565027e..757b8d4 100644
--- a/util/src/test/java/org/killbill/billing/GuicyKillbillTestSuiteWithEmbeddedDB.java
+++ b/util/src/test/java/org/killbill/billing/GuicyKillbillTestSuiteWithEmbeddedDB.java
@@ -24,6 +24,7 @@ import org.killbill.commons.embeddeddb.EmbeddedDB;
import org.skife.jdbi.v2.IDBI;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.testng.Assert;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.BeforeSuite;
@@ -52,11 +53,16 @@ public class GuicyKillbillTestSuiteWithEmbeddedDB extends GuicyKillbillTestSuite
@BeforeMethod(groups = "slow")
public void beforeMethod() throws Exception {
+ cleanupAllTables();
+ controlCacheDispatcher.clearAll();
+ }
+
+ protected void cleanupAllTables() {
try {
DBTestingHelper.get().getInstance().cleanupAllTables();
- } catch (final Exception ignored) {
+ } catch (final Exception e) {
+ Assert.fail("Unable to clean database", e);
}
- controlCacheDispatcher.clearAll();
}
@AfterSuite(groups = "slow")
diff --git a/util/src/test/java/org/killbill/billing/util/callcontext/TestInternalCallContextFactory.java b/util/src/test/java/org/killbill/billing/util/callcontext/TestInternalCallContextFactory.java
index 40e940e..c13db83 100644
--- a/util/src/test/java/org/killbill/billing/util/callcontext/TestInternalCallContextFactory.java
+++ b/util/src/test/java/org/killbill/billing/util/callcontext/TestInternalCallContextFactory.java
@@ -53,9 +53,11 @@ public class TestInternalCallContextFactory extends UtilTestSuiteWithEmbeddedDB
" id varchar(36) NOT NULL,\n" +
" account_id varchar(36) NOT NULL,\n" +
" invoice_date date NOT NULL,\n" +
- " target_date date NOT NULL,\n" +
+ " target_date date,\n" +
" currency varchar(3) NOT NULL,\n" +
+ " status varchar(15) NOT NULL DEFAULT 'COMMITTED',\n" +
" migrated bool NOT NULL,\n" +
+ " parent_invoice bool NOT NULL DEFAULT FALSE,\n" +
" created_by varchar(50) NOT NULL,\n" +
" created_date datetime NOT NULL,\n" +
" account_record_id bigint /*! unsigned */ not null,\n" +
@@ -86,8 +88,8 @@ public class TestInternalCallContextFactory extends UtilTestSuiteWithEmbeddedDB
@Override
public Void withHandle(final Handle handle) throws Exception {
// Note: we always create an accounts table, see MysqlTestingHelper
- handle.execute("insert into accounts (record_id, id, email, name, first_name_length, is_notified_for_invoices, created_date, created_by, updated_date, updated_by) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
- accountRecordId, accountId.toString(), "yo@t.com", "toto", 4, false, new Date(), "i", new Date(), "j");
+ handle.execute("insert into accounts (record_id, id, email, name, first_name_length, time_zone, is_notified_for_invoices, created_date, created_by, updated_date, updated_by) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
+ accountRecordId, accountId.toString(), "yo@t.com", "toto", 4, "UTC", false, new Date(), "i", new Date(), "j");
return null;
}
});
diff --git a/util/src/test/java/org/killbill/billing/util/customfield/api/TestDefaultCustomFieldUserApi.java b/util/src/test/java/org/killbill/billing/util/customfield/api/TestDefaultCustomFieldUserApi.java
index ffe76e3..fcddf41 100644
--- a/util/src/test/java/org/killbill/billing/util/customfield/api/TestDefaultCustomFieldUserApi.java
+++ b/util/src/test/java/org/killbill/billing/util/customfield/api/TestDefaultCustomFieldUserApi.java
@@ -53,8 +53,8 @@ public class TestDefaultCustomFieldUserApi extends UtilTestSuiteWithEmbeddedDB {
@Override
public Void withHandle(final Handle handle) throws Exception {
// Note: we always create an accounts table, see MysqlTestingHelper
- handle.execute("insert into accounts (record_id, id, email, name, first_name_length, is_notified_for_invoices, created_date, created_by, updated_date, updated_by) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
- accountRecordId, accountId.toString(), "yo@t.com", "toto", 4, false, new Date(), "i", new Date(), "j");
+ handle.execute("insert into accounts (record_id, id, email, name, first_name_length, time_zone, is_notified_for_invoices, created_date, created_by, updated_date, updated_by) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
+ accountRecordId, accountId.toString(), "yo@t.com", "toto", 4, "UTC", false, new Date(), "i", new Date(), "j");
return null;
}
diff --git a/util/src/test/java/org/killbill/billing/util/dao/TestNonEntityDao.java b/util/src/test/java/org/killbill/billing/util/dao/TestNonEntityDao.java
index 8b9c231..2319573 100644
--- a/util/src/test/java/org/killbill/billing/util/dao/TestNonEntityDao.java
+++ b/util/src/test/java/org/killbill/billing/util/dao/TestNonEntityDao.java
@@ -96,8 +96,8 @@ public class TestNonEntityDao extends UtilTestSuiteWithEmbeddedDB {
@Override
public Void withHandle(final Handle handle) throws Exception {
// Note: we always create an accounts table, see MysqlTestingHelper
- handle.execute("insert into accounts (record_id, id, email, name, first_name_length, is_notified_for_invoices, created_date, created_by, updated_date, updated_by, tenant_record_id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
- accountRecordId, accountId.toString(), "zozo@tt.com", "zozo", 4, false, new Date(), "i", new Date(), "j", tenantRecordId);
+ handle.execute("insert into accounts (record_id, id, email, name, first_name_length, time_zone, is_notified_for_invoices, created_date, created_by, updated_date, updated_by, tenant_record_id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
+ accountRecordId, accountId.toString(), "zozo@tt.com", "zozo", 4, "UTC", false, new Date(), "i", new Date(), "j", tenantRecordId);
return null;
}
});
@@ -108,8 +108,8 @@ public class TestNonEntityDao extends UtilTestSuiteWithEmbeddedDB {
@Override
public Void withHandle(final Handle handle) throws Exception {
// Note: we always create an accounts table, see MysqlTestingHelper
- handle.execute("insert into account_history (record_id, id, email, name, first_name_length, is_notified_for_invoices, created_date, created_by, updated_date, updated_by, tenant_record_id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
- accountRecordId, accountId.toString(), "zozo@tt.com", "zozo", 4, false, new Date(), "i", new Date(), "j", tenantRecordId);
+ handle.execute("insert into account_history (record_id, id, email, name, first_name_length, time_zone, is_notified_for_invoices, created_date, created_by, updated_date, updated_by, tenant_record_id) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
+ accountRecordId, accountId.toString(), "zozo@tt.com", "zozo", 4, "UTC", false, new Date(), "i", new Date(), "j", tenantRecordId);
return null;
}
});
diff --git a/util/src/test/java/org/killbill/billing/util/export/dao/TestDatabaseExportDao.java b/util/src/test/java/org/killbill/billing/util/export/dao/TestDatabaseExportDao.java
index 01fe087..8c26cbe 100644
--- a/util/src/test/java/org/killbill/billing/util/export/dao/TestDatabaseExportDao.java
+++ b/util/src/test/java/org/killbill/billing/util/export/dao/TestDatabaseExportDao.java
@@ -46,6 +46,7 @@ public class TestDatabaseExportDao extends UtilTestSuiteWithEmbeddedDB {
final String accountEmail = UUID.randomUUID().toString().substring(0, 4) + '@' + UUID.randomUUID().toString().substring(0, 4);
final String accountName = UUID.randomUUID().toString().substring(0, 4);
final int firstNameLength = 4;
+ final String timeZone = "UTC";
final boolean isNotifiedForInvoices = false;
final Date createdDate = new Date(12421982000L);
final String createdBy = UUID.randomUUID().toString().substring(0, 4);
@@ -77,17 +78,17 @@ public class TestDatabaseExportDao extends UtilTestSuiteWithEmbeddedDB {
internalCallContext.getAccountRecordId(), internalCallContext.getTenantRecordId());
// Add row in accounts table
- handle.execute("insert into accounts (record_id, id, email, name, first_name_length, is_notified_for_invoices, created_date, created_by, updated_date, updated_by, tenant_record_id) " +
- "values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
- internalCallContext.getAccountRecordId(), accountId, accountEmail, accountName, firstNameLength, isNotifiedForInvoices, createdDate, createdBy, updatedDate, updatedBy, internalCallContext.getTenantRecordId());
+ handle.execute("insert into accounts (record_id, id, email, name, first_name_length, time_zone, is_notified_for_invoices, created_date, created_by, updated_date, updated_by, tenant_record_id) " +
+ "values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
+ internalCallContext.getAccountRecordId(), accountId, accountEmail, accountName, firstNameLength, timeZone, isNotifiedForInvoices, createdDate, createdBy, updatedDate, updatedBy, internalCallContext.getTenantRecordId());
return null;
}
});
// Verify new dump
final String newDump = getDump();
- Assert.assertEquals(newDump, "-- accounts record_id|id|external_key|email|name|first_name_length|currency|billing_cycle_day_local|payment_method_id|time_zone|locale|address1|address2|company_name|city|state_or_province|country|postal_code|phone|migrated|is_notified_for_invoices|created_date|created_by|updated_date|updated_by|tenant_record_id\n" +
- String.format("%s|%s||%s|%s|%s||||||||||||||false|%s|%s|%s|%s|%s|%s", internalCallContext.getAccountRecordId(), accountId, accountEmail, accountName, firstNameLength,
+ Assert.assertEquals(newDump, "-- accounts record_id|id|external_key|email|name|first_name_length|currency|billing_cycle_day_local|parent_account_id|is_payment_delegated_to_parent|payment_method_id|time_zone|locale|address1|address2|company_name|city|state_or_province|country|postal_code|phone|notes|migrated|is_notified_for_invoices|created_date|created_by|updated_date|updated_by|tenant_record_id\n" +
+ String.format("%s|%s||%s|%s|%s||||false||%s|||||||||||false|%s|%s|%s|%s|%s|%s", internalCallContext.getAccountRecordId(), accountId, accountEmail, accountName, firstNameLength, timeZone,
isNotifiedForInvoices, "1970-05-24T18:33:02.000+0000", createdBy, "1982-02-18T20:03:42.000+0000", updatedBy, internalCallContext.getTenantRecordId()) + "\n" +
"-- " + tableNameA + " record_id|a_column|blob_column|account_record_id|tenant_record_id\n" +
"1|a|WlYAAARjYWZl|" + internalCallContext.getAccountRecordId() + "|" + internalCallContext.getTenantRecordId() + "\n" +
diff --git a/util/src/test/java/org/killbill/billing/util/tag/api/TestDefaultTagUserApi.java b/util/src/test/java/org/killbill/billing/util/tag/api/TestDefaultTagUserApi.java
index bbdfb0f..290a472 100644
--- a/util/src/test/java/org/killbill/billing/util/tag/api/TestDefaultTagUserApi.java
+++ b/util/src/test/java/org/killbill/billing/util/tag/api/TestDefaultTagUserApi.java
@@ -52,8 +52,8 @@ public class TestDefaultTagUserApi extends UtilTestSuiteWithEmbeddedDB {
@Override
public Void withHandle(final Handle handle) throws Exception {
// Note: we always create an accounts table, see MysqlTestingHelper
- handle.execute("insert into accounts (record_id, id, email, name, first_name_length, is_notified_for_invoices, created_date, created_by, updated_date, updated_by) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
- accountRecordId, accountId.toString(), "yo@t.com", "toto", 4, false, new Date(), "i", new Date(), "j");
+ handle.execute("insert into accounts (record_id, id, email, name, first_name_length, time_zone, is_notified_for_invoices, created_date, created_by, updated_date, updated_by) values (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
+ accountRecordId, accountId.toString(), "yo@t.com", "toto", 4, "UTC", false, new Date(), "i", new Date(), "j");
return null;
}
diff --git a/util/src/test/java/org/killbill/billing/util/UtilTestSuiteWithEmbeddedDB.java b/util/src/test/java/org/killbill/billing/util/UtilTestSuiteWithEmbeddedDB.java
index 503a229..0569958 100644
--- a/util/src/test/java/org/killbill/billing/util/UtilTestSuiteWithEmbeddedDB.java
+++ b/util/src/test/java/org/killbill/billing/util/UtilTestSuiteWithEmbeddedDB.java
@@ -123,20 +123,15 @@ public abstract class UtilTestSuiteWithEmbeddedDB extends GuicyKillbillTestSuite
eventBus.start();
eventBus.register(eventsListener);
-
- // Make sure we start with a clean state
- assertListenerStatus();
}
@AfterMethod(groups = "slow")
public void afterMethod() throws Exception {
- // Make sure we finish in a clean state
- assertListenerStatus();
-
eventBus.unregister(eventsListener);
eventBus.stop();
}
+ @Override
protected void assertListenerStatus() {
eventsListener.assertListenerStatus();
}