diff --git a/payment/src/test/java/org/killbill/billing/payment/TestRetryService.java b/payment/src/test/java/org/killbill/billing/payment/TestRetryService.java
index 2c46cfc..33b1484 100644
--- a/payment/src/test/java/org/killbill/billing/payment/TestRetryService.java
+++ b/payment/src/test/java/org/killbill/billing/payment/TestRetryService.java
@@ -91,25 +91,229 @@ public class TestRetryService extends PaymentTestSuiteNoDB {
// PLUGIN_EXCEPTION will lead to UNKNOWN row that will not be retried by the plugin
@Test(groups = "fast")
public void testAbortedPlugin() throws Exception {
- testSchedulesRetryInternal(0, false, FailureType.PLUGIN_EXCEPTION);
+
+ final Account account = testHelper.createTestAccount("yiyi.gmail.com", true);
+ final Invoice invoice = testHelper.createTestInvoice(account, clock.getUTCToday(), Currency.USD);
+ final BigDecimal amount = new BigDecimal("10.00");
+ final UUID subscriptionId = UUID.randomUUID();
+ final UUID bundleId = UUID.randomUUID();
+
+ final LocalDate startDate = clock.getUTCToday();
+ final LocalDate endDate = startDate.plusMonths(1);
+ invoice.addInvoiceItem(new MockRecurringInvoiceItem(invoice.getId(),
+ account.getId(),
+ subscriptionId,
+ bundleId,
+ "test plan", "test phase", null,
+ startDate,
+ endDate,
+ amount,
+ new BigDecimal("1.0"),
+ Currency.USD));
+ setPaymentFailure(FailureType.PLUGIN_EXCEPTION);
+
+ boolean failed = false;
+ final String paymentExternalKey = UUID.randomUUID().toString();
+ final String transactionExternalKey = UUID.randomUUID().toString();
+ try {
+ pluginControlPaymentProcessor.createPurchase(false, account, account.getPaymentMethodId(), null, amount, Currency.USD, paymentExternalKey, transactionExternalKey,
+ createPropertiesForInvoice(invoice), ImmutableList.<String>of(InvoicePaymentControlPluginApi.PLUGIN_NAME), callContext, internalCallContext);
+ } catch (final PaymentApiException e) {
+ failed = true;
+ }
+ assertTrue(failed);
+
+ Payment payment = getPaymentForExternalKey(paymentExternalKey);
+ List<PaymentAttemptModelDao> attempts = paymentDao.getPaymentAttempts(paymentExternalKey, internalCallContext);
+ assertEquals(attempts.size(), 1);
+
+ final List<PaymentTransactionModelDao> transactions = paymentDao.getTransactionsForPayment(payment.getId(), internalCallContext);
+ assertEquals(transactions.size(), 1);
+
+ attempts = paymentDao.getPaymentAttempts(payment.getExternalKey(), internalCallContext);
+ final int expectedAttempts = 1;
+ assertEquals(attempts.size(), expectedAttempts);
+ assertEquals(attempts.get(0).getStateName(), "ABORTED");
}
@Test(groups = "fast")
public void testFailedPaymentWithOneSuccessfulRetry() throws Exception {
- testSchedulesRetryInternal(1, true, FailureType.PAYMENT_FAILURE);
+
+ final Account account = testHelper.createTestAccount("yiyi.gmail.com", true);
+ final Invoice invoice = testHelper.createTestInvoice(account, clock.getUTCToday(), Currency.USD);
+ final BigDecimal amount = new BigDecimal("10.00");
+ final UUID subscriptionId = UUID.randomUUID();
+ final UUID bundleId = UUID.randomUUID();
+
+ final LocalDate startDate = clock.getUTCToday();
+ final LocalDate endDate = startDate.plusMonths(1);
+ invoice.addInvoiceItem(new MockRecurringInvoiceItem(invoice.getId(),
+ account.getId(),
+ subscriptionId,
+ bundleId,
+ "test plan", "test phase", null,
+ startDate,
+ endDate,
+ amount,
+ new BigDecimal("1.0"),
+ Currency.USD));
+ setPaymentFailure(FailureType.PAYMENT_FAILURE);
+
+ boolean failed = false;
+ final String paymentExternalKey = UUID.randomUUID().toString();
+ final String transactionExternalKey = UUID.randomUUID().toString();
+ try {
+ pluginControlPaymentProcessor.createPurchase(false, account, account.getPaymentMethodId(), null, amount, Currency.USD, paymentExternalKey, transactionExternalKey,
+ createPropertiesForInvoice(invoice), ImmutableList.<String>of(InvoicePaymentControlPluginApi.PLUGIN_NAME), callContext, internalCallContext);
+ } catch (final PaymentApiException e) {
+ failed = true;
+ }
+ assertTrue(failed);
+
+ Payment payment = getPaymentForExternalKey(paymentExternalKey);
+ List<PaymentAttemptModelDao> attempts = paymentDao.getPaymentAttempts(paymentExternalKey, internalCallContext);
+ assertEquals(attempts.size(), 1);
+
+ final List<PaymentTransactionModelDao> transactions = paymentDao.getTransactionsForPayment(payment.getId(), internalCallContext);
+ assertEquals(transactions.size(), 1);
+
+ moveClockForFailureType(FailureType.PAYMENT_FAILURE, 0);
+
+ try {
+ await().atMost(5, SECONDS).until(new Callable<Boolean>() {
+ @Override
+ public Boolean call() throws Exception {
+ final List<PaymentAttemptModelDao> attempts = paymentDao.getPaymentAttempts(paymentExternalKey, internalCallContext);
+ final List<PaymentAttemptModelDao> filteredAttempts = ImmutableList.copyOf(Iterables.filter(attempts, new Predicate<PaymentAttemptModelDao>() {
+ @Override
+ public boolean apply(final PaymentAttemptModelDao input) {
+ return input.getStateName().equals("SUCCESS") ||
+ input.getStateName().equals("RETRIED") ||
+ input.getStateName().equals("ABORTED");
+ }
+ }));
+ return filteredAttempts.size() == 2;
+ }
+ });
+ } catch (final TimeoutException e) {
+ fail("Timeout ");
+ }
+
+ attempts = paymentDao.getPaymentAttempts(payment.getExternalKey(), internalCallContext);
+ final int expectedAttempts = 2;
+ assertEquals(attempts.size(), expectedAttempts);
+ Collections.sort(attempts, new Comparator<PaymentAttemptModelDao>() {
+ @Override
+ public int compare(final PaymentAttemptModelDao o1, final PaymentAttemptModelDao o2) {
+ return o1.getCreatedDate().compareTo(o2.getCreatedDate());
+ }
+ });
+
+ for (int i = 0; i < attempts.size(); i++) {
+ final PaymentAttemptModelDao cur = attempts.get(i);
+ if (i < attempts.size() - 1) {
+ assertEquals(cur.getStateName(), "RETRIED");
+ } else {
+ assertEquals(cur.getStateName(), "SUCCESS");
+ }
+ }
}
@Test(groups = "fast")
public void testFailedPaymentWithLastRetrySuccess() throws Exception {
- testSchedulesRetryInternal(paymentConfig.getPaymentFailureRetryDays().size(), true, FailureType.PAYMENT_FAILURE);
+
+ final Account account = testHelper.createTestAccount("yiyi.gmail.com", true);
+ final Invoice invoice = testHelper.createTestInvoice(account, clock.getUTCToday(), Currency.USD);
+ final BigDecimal amount = new BigDecimal("10.00");
+ final UUID subscriptionId = UUID.randomUUID();
+ final UUID bundleId = UUID.randomUUID();
+
+ final LocalDate startDate = clock.getUTCToday();
+ final LocalDate endDate = startDate.plusMonths(1);
+ invoice.addInvoiceItem(new MockRecurringInvoiceItem(invoice.getId(),
+ account.getId(),
+ subscriptionId,
+ bundleId,
+ "test plan", "test phase", null,
+ startDate,
+ endDate,
+ amount,
+ new BigDecimal("1.0"),
+ Currency.USD));
+ setPaymentFailure(FailureType.PAYMENT_FAILURE);
+
+ boolean failed = false;
+ final String paymentExternalKey = UUID.randomUUID().toString();
+ final String transactionExternalKey = UUID.randomUUID().toString();
+ try {
+ pluginControlPaymentProcessor.createPurchase(false, account, account.getPaymentMethodId(), null, amount, Currency.USD, paymentExternalKey, transactionExternalKey,
+ createPropertiesForInvoice(invoice), ImmutableList.<String>of(InvoicePaymentControlPluginApi.PLUGIN_NAME), callContext, internalCallContext);
+ } catch (final PaymentApiException e) {
+ failed = true;
+ }
+ assertTrue(failed);
+
+ Payment payment = getPaymentForExternalKey(paymentExternalKey);
+ List<PaymentAttemptModelDao> attempts = paymentDao.getPaymentAttempts(paymentExternalKey, internalCallContext);
+ assertEquals(attempts.size(), 1);
+
+ final List<PaymentTransactionModelDao> transactions = paymentDao.getTransactionsForPayment(payment.getId(), internalCallContext);
+ assertEquals(transactions.size(), 1);
+
+ int maxTries = paymentConfig.getPaymentFailureRetryDays().size();
+ for (int curFailure = 0; curFailure < maxTries; curFailure++) {
+
+ // Set plugin to fail with specific type unless this is the last attempt and we want a success
+ if (curFailure < (maxTries - 1)) {
+ setPaymentFailure(FailureType.PAYMENT_FAILURE);
+ }
+
+ moveClockForFailureType(FailureType.PAYMENT_FAILURE, curFailure);
+ final int curFailureCondition = curFailure;
+
+ try {
+ await().atMost(5, SECONDS).until(new Callable<Boolean>() {
+ @Override
+ public Boolean call() throws Exception {
+ final List<PaymentAttemptModelDao> attempts = paymentDao.getPaymentAttempts(paymentExternalKey, internalCallContext);
+ final List<PaymentAttemptModelDao> filteredAttempts = ImmutableList.copyOf(Iterables.filter(attempts, new Predicate<PaymentAttemptModelDao>() {
+ @Override
+ public boolean apply(final PaymentAttemptModelDao input) {
+ return input.getStateName().equals("SUCCESS") ||
+ input.getStateName().equals("RETRIED") ||
+ input.getStateName().equals("ABORTED");
+ }
+ }));
+ return filteredAttempts.size() == curFailureCondition + 2;
+ }
+ });
+ } catch (final TimeoutException e) {
+ fail("Timeout curFailure = " + curFailureCondition);
+ }
+ }
+ attempts = paymentDao.getPaymentAttempts(payment.getExternalKey(), internalCallContext);
+ final int expectedAttempts = maxTries + 1;
+ assertEquals(attempts.size(), expectedAttempts);
+ Collections.sort(attempts, new Comparator<PaymentAttemptModelDao>() {
+ @Override
+ public int compare(final PaymentAttemptModelDao o1, final PaymentAttemptModelDao o2) {
+ return o1.getCreatedDate().compareTo(o2.getCreatedDate());
+ }
+ });
+
+ for (int i = 0; i < attempts.size(); i++) {
+ final PaymentAttemptModelDao cur = attempts.get(i);
+ if (i < attempts.size() - 1) {
+ assertEquals(cur.getStateName(), "RETRIED");
+ } else {
+ assertEquals(cur.getStateName(), "SUCCESS");
+ }
+ }
+
}
@Test(groups = "fast")
public void testAbortedPayment() throws Exception {
- testSchedulesRetryInternal(paymentConfig.getPaymentFailureRetryDays().size(), false, FailureType.PAYMENT_FAILURE);
- }
-
- private void testSchedulesRetryInternal(final int maxTries, final boolean lastSuccess, final FailureType failureType) throws Exception {
final Account account = testHelper.createTestAccount("yiyi.gmail.com", true);
final Invoice invoice = testHelper.createTestInvoice(account, clock.getUTCToday(), Currency.USD);
@@ -129,7 +333,7 @@ public class TestRetryService extends PaymentTestSuiteNoDB {
amount,
new BigDecimal("1.0"),
Currency.USD));
- setPaymentFailure(failureType);
+ setPaymentFailure(FailureType.PAYMENT_FAILURE);
boolean failed = false;
final String paymentExternalKey = UUID.randomUUID().toString();
@@ -149,15 +353,13 @@ public class TestRetryService extends PaymentTestSuiteNoDB {
final List<PaymentTransactionModelDao> transactions = paymentDao.getTransactionsForPayment(payment.getId(), internalCallContext);
assertEquals(transactions.size(), 1);
+ int maxTries = paymentConfig.getPaymentFailureRetryDays().size();
for (int curFailure = 0; curFailure < maxTries; curFailure++) {
// Set plugin to fail with specific type unless this is the last attempt and we want a success
- if (curFailure < (maxTries - 1) || !lastSuccess) {
- setPaymentFailure(failureType);
- }
+ setPaymentFailure(FailureType.PAYMENT_FAILURE);
-
- moveClockForFailureType(failureType, curFailure);
+ moveClockForFailureType(FailureType.PAYMENT_FAILURE, curFailure);
final int curFailureCondition = curFailure;
try {
@@ -181,8 +383,7 @@ public class TestRetryService extends PaymentTestSuiteNoDB {
}
}
attempts = paymentDao.getPaymentAttempts(payment.getExternalKey(), internalCallContext);
- final int expectedAttempts = maxTries < getMaxRetrySizeForFailureType(failureType) ?
- maxTries + 1 : getMaxRetrySizeForFailureType(failureType) + 1;
+ final int expectedAttempts = maxTries + 1;
assertEquals(attempts.size(), expectedAttempts);
Collections.sort(attempts, new Comparator<PaymentAttemptModelDao>() {
@Override
@@ -196,11 +397,7 @@ public class TestRetryService extends PaymentTestSuiteNoDB {
if (i < attempts.size() - 1) {
assertEquals(cur.getStateName(), "RETRIED");
} else {
- if (lastSuccess) {
- assertEquals(cur.getStateName(), "SUCCESS");
- } else {
- assertEquals(cur.getStateName(), "ABORTED");
- }
+ assertEquals(cur.getStateName(), "ABORTED");
}
}
}