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 37142f4..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,8 @@ 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;
@@ -303,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 3c2e38a..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,6 +74,14 @@ 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 = DEFAULT_REQUEST_TIMEOUT_SEC * 1000;
do {
@@ -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();