killbill-memoizeit

Merge branch 'fix-for-1038' into fix-for-1038-on-0.20 Signed-off-by:

9/7/2018 5:14:35 AM

Details

diff --git a/payment/src/main/java/org/killbill/billing/payment/core/PaymentRefresher.java b/payment/src/main/java/org/killbill/billing/payment/core/PaymentRefresher.java
index 19e097d..d3e8d4c 100644
--- a/payment/src/main/java/org/killbill/billing/payment/core/PaymentRefresher.java
+++ b/payment/src/main/java/org/killbill/billing/payment/core/PaymentRefresher.java
@@ -49,7 +49,6 @@ import org.killbill.billing.payment.dao.PaymentModelDao;
 import org.killbill.billing.payment.dao.PaymentTransactionModelDao;
 import org.killbill.billing.payment.dao.PluginPropertySerializer;
 import org.killbill.billing.payment.dao.PluginPropertySerializer.PluginPropertySerializerException;
-import org.killbill.billing.payment.glue.DefaultPaymentService;
 import org.killbill.billing.payment.plugin.api.PaymentPluginApi;
 import org.killbill.billing.payment.plugin.api.PaymentPluginApiException;
 import org.killbill.billing.payment.plugin.api.PaymentTransactionInfoPlugin;
@@ -77,10 +76,12 @@ import com.google.common.base.Function;
 import com.google.common.base.Optional;
 import com.google.common.base.Predicate;
 import com.google.common.collect.Collections2;
+import com.google.common.collect.HashMultimap;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
+import com.google.common.collect.Multimap;
 import com.google.common.collect.Ordering;
 
 import static org.killbill.billing.util.entity.dao.DefaultPaginationHelper.getEntityPagination;
@@ -338,42 +339,30 @@ public class PaymentRefresher extends ProcessorBase {
                                               final boolean withAttempts, final Iterable<PluginProperty> properties, final TenantContext tenantContext, final InternalTenantContext internalTenantContext) throws PaymentApiException {
         final PaymentPluginApi pluginApi = getPaymentPluginApi(pluginName);
 
-        return getEntityPagination(limit,
-                                   new SourcePaginationBuilder<PaymentTransactionInfoPlugin, PaymentApiException>() {
-                                       @Override
-                                       public Pagination<PaymentTransactionInfoPlugin> build() throws PaymentApiException {
-                                           try {
-                                               return pluginApi.searchPayments(searchKey, offset, limit, properties, tenantContext);
-                                           } catch (final PaymentPluginApiException e) {
-                                               throw new PaymentApiException(e, ErrorCode.PAYMENT_PLUGIN_SEARCH_PAYMENTS, pluginName, searchKey);
-                                           }
-                                       }
+        final Pagination<PaymentTransactionInfoPlugin> paymentTransactionInfoPlugins;
+        try {
+            paymentTransactionInfoPlugins = pluginApi.searchPayments(searchKey, offset, limit, properties, tenantContext);
+        } catch (final PaymentPluginApiException e) {
+            throw new PaymentApiException(e, ErrorCode.PAYMENT_PLUGIN_SEARCH_PAYMENTS, pluginName, searchKey);
+        }
 
-                                   },
-                                   new Function<PaymentTransactionInfoPlugin, Payment>() {
-                                       final List<PaymentTransactionInfoPlugin> cachedPaymentTransactions = new LinkedList<PaymentTransactionInfoPlugin>();
+        // Cannot easily stream here unfortunately, since we need to merge PaymentTransactionInfoPlugin into Payment (no order assumed)
+        final Multimap<UUID, PaymentTransactionInfoPlugin> payments = HashMultimap.<UUID, PaymentTransactionInfoPlugin>create();
+        for (final PaymentTransactionInfoPlugin paymentTransactionInfoPlugin : paymentTransactionInfoPlugins) {
+            payments.put(paymentTransactionInfoPlugin.getKbPaymentId(), paymentTransactionInfoPlugin);
+        }
 
-                                       @Override
-                                       public Payment apply(final PaymentTransactionInfoPlugin pluginTransaction) {
-                                           if (pluginTransaction.getKbPaymentId() == null) {
-                                               // Garbage from the plugin?
-                                               log.debug("Plugin {} returned a payment without a kbPaymentId for searchKey {}", pluginName, searchKey);
-                                               return null;
-                                           }
+        final Collection<Payment> results = new LinkedList<Payment>();
+        for (final UUID paymentId : payments.keys()) {
+            final Payment result = toPayment(paymentId, withPluginInfo ? payments.get(paymentId) : ImmutableList.<PaymentTransactionInfoPlugin>of(), withAttempts, internalTenantContext);
+            if (result != null) {
+                results.add(result);
+            }
+        }
 
-                                           if (cachedPaymentTransactions.isEmpty() ||
-                                               (cachedPaymentTransactions.get(0).getKbPaymentId().equals(pluginTransaction.getKbPaymentId()))) {
-                                               cachedPaymentTransactions.add(pluginTransaction);
-                                               return null;
-                                           } else {
-                                               final Payment result = toPayment(pluginTransaction.getKbPaymentId(), withPluginInfo ? ImmutableList.<PaymentTransactionInfoPlugin>copyOf(cachedPaymentTransactions) : ImmutableList.<PaymentTransactionInfoPlugin>of(), withAttempts, internalTenantContext);
-                                               cachedPaymentTransactions.clear();
-                                               cachedPaymentTransactions.add(pluginTransaction);
-                                               return result;
-                                           }
-                                       }
-                                   }
-                                  );
+        return new DefaultPagination<Payment>(paymentTransactionInfoPlugins,
+                                              limit,
+                                              results.iterator());
     }
 
     // Used in bulk get APIs (getPayments / searchPayments)
diff --git a/payment/src/main/java/org/killbill/billing/payment/provider/DefaultNoOpPaymentInfoPlugin.java b/payment/src/main/java/org/killbill/billing/payment/provider/DefaultNoOpPaymentInfoPlugin.java
index 54b5848..02e383f 100644
--- a/payment/src/main/java/org/killbill/billing/payment/provider/DefaultNoOpPaymentInfoPlugin.java
+++ b/payment/src/main/java/org/killbill/billing/payment/provider/DefaultNoOpPaymentInfoPlugin.java
@@ -41,9 +41,28 @@ public class DefaultNoOpPaymentInfoPlugin implements PaymentTransactionInfoPlugi
     private final String gatewayErrorCode;
     private final Currency currency;
     private final TransactionType transactionType;
+    private final String firstPaymentReferenceId;
+    private final String secondPaymentReferenceId;
+    private final List<PluginProperty> pluginProperties;
 
     public DefaultNoOpPaymentInfoPlugin(final UUID kbPaymentId, final UUID kbTransactionPaymentId, final TransactionType transactionType, final BigDecimal amount, final Currency currency, final DateTime effectiveDate,
                                         final DateTime createdDate, final PaymentPluginStatus status, final String gatewayErrorCode, final String gatewayError) {
+        this(kbPaymentId, kbTransactionPaymentId, transactionType, amount, currency, effectiveDate, createdDate, status, gatewayErrorCode, gatewayError, null, null, ImmutableList.<PluginProperty>of());
+    }
+
+    public DefaultNoOpPaymentInfoPlugin(final UUID kbPaymentId,
+                                        final UUID kbTransactionPaymentId,
+                                        final TransactionType transactionType,
+                                        final BigDecimal amount,
+                                        final Currency currency,
+                                        final DateTime effectiveDate,
+                                        final DateTime createdDate,
+                                        final PaymentPluginStatus status,
+                                        final String gatewayErrorCode,
+                                        final String gatewayError,
+                                        final String firstPaymentReferenceId,
+                                        final String secondPaymentReferenceId,
+                                        final List<PluginProperty> pluginProperties) {
         this.kbPaymentId = kbPaymentId;
         this.kbTransactionPaymentId = kbTransactionPaymentId;
         this.transactionType = transactionType;
@@ -54,6 +73,9 @@ public class DefaultNoOpPaymentInfoPlugin implements PaymentTransactionInfoPlugi
         this.gatewayErrorCode = gatewayErrorCode;
         this.gatewayError = gatewayError;
         this.currency = currency;
+        this.firstPaymentReferenceId = firstPaymentReferenceId;
+        this.secondPaymentReferenceId = secondPaymentReferenceId;
+        this.pluginProperties = pluginProperties;
     }
 
     @Override
@@ -108,29 +130,35 @@ public class DefaultNoOpPaymentInfoPlugin implements PaymentTransactionInfoPlugi
 
     @Override
     public String getFirstPaymentReferenceId() {
-        return null;
+        return firstPaymentReferenceId;
     }
 
     @Override
     public String getSecondPaymentReferenceId() {
-        return null;
+        return secondPaymentReferenceId;
     }
 
     @Override
     public List<PluginProperty> getProperties() {
-        return ImmutableList.<PluginProperty>of();
+        return pluginProperties;
     }
 
     @Override
     public String toString() {
         final StringBuilder sb = new StringBuilder("DefaultNoOpPaymentInfoPlugin{");
         sb.append("kbPaymentId=").append(kbPaymentId);
+        sb.append(", kbTransactionPaymentId=").append(kbTransactionPaymentId);
         sb.append(", amount=").append(amount);
         sb.append(", effectiveDate=").append(effectiveDate);
         sb.append(", createdDate=").append(createdDate);
         sb.append(", status=").append(status);
-        sb.append(", error='").append(gatewayError).append('\'');
+        sb.append(", gatewayError='").append(gatewayError).append('\'');
+        sb.append(", gatewayErrorCode='").append(gatewayErrorCode).append('\'');
         sb.append(", currency=").append(currency);
+        sb.append(", transactionType=").append(transactionType);
+        sb.append(", firstPaymentReferenceId='").append(firstPaymentReferenceId).append('\'');
+        sb.append(", secondPaymentReferenceId='").append(secondPaymentReferenceId).append('\'');
+        sb.append(", pluginProperties=").append(pluginProperties);
         sb.append('}');
         return sb.toString();
     }
@@ -176,6 +204,15 @@ public class DefaultNoOpPaymentInfoPlugin implements PaymentTransactionInfoPlugi
         if (status != that.status) {
             return false;
         }
+        if (firstPaymentReferenceId != null ? !firstPaymentReferenceId.equals(that.firstPaymentReferenceId) : that.firstPaymentReferenceId != null) {
+            return false;
+        }
+        if (secondPaymentReferenceId != null ? !secondPaymentReferenceId.equals(that.secondPaymentReferenceId) : that.secondPaymentReferenceId != null) {
+            return false;
+        }
+        if (pluginProperties != null ? !pluginProperties.equals(that.pluginProperties) : that.pluginProperties != null) {
+            return false;
+        }
 
         return true;
     }
@@ -192,6 +229,9 @@ public class DefaultNoOpPaymentInfoPlugin implements PaymentTransactionInfoPlugi
         result = 31 * result + (gatewayError != null ? gatewayError.hashCode() : 0);
         result = 31 * result + (gatewayErrorCode != null ? gatewayErrorCode.hashCode() : 0);
         result = 31 * result + (currency != null ? currency.hashCode() : 0);
+        result = 31 * result + (firstPaymentReferenceId != null ? firstPaymentReferenceId.hashCode() : 0);
+        result = 31 * result + (secondPaymentReferenceId != null ? secondPaymentReferenceId.hashCode() : 0);
+        result = 31 * result + (pluginProperties != null ? pluginProperties.hashCode() : 0);
         return result;
     }
 }
diff --git a/payment/src/test/java/org/killbill/billing/payment/api/TestPaymentApi.java b/payment/src/test/java/org/killbill/billing/payment/api/TestPaymentApi.java
index ec94497..0c2f21a 100644
--- a/payment/src/test/java/org/killbill/billing/payment/api/TestPaymentApi.java
+++ b/payment/src/test/java/org/killbill/billing/payment/api/TestPaymentApi.java
@@ -43,6 +43,7 @@ import org.killbill.billing.payment.dao.PaymentSqlDao;
 import org.killbill.billing.payment.invoice.InvoicePaymentControlPluginApi;
 import org.killbill.billing.payment.plugin.api.PaymentPluginApiException;
 import org.killbill.billing.payment.plugin.api.PaymentPluginStatus;
+import org.killbill.billing.payment.provider.DefaultNoOpPaymentMethodPlugin;
 import org.killbill.billing.payment.provider.ExternalPaymentProviderPlugin;
 import org.killbill.billing.payment.provider.MockPaymentControlProviderPlugin;
 import org.killbill.billing.payment.provider.MockPaymentProviderPlugin;
@@ -64,10 +65,6 @@ import static org.testng.Assert.fail;
 
 public class TestPaymentApi extends PaymentTestSuiteWithEmbeddedDB {
 
-    private MockPaymentProviderPlugin mockPaymentProviderPlugin;
-
-    private MockPaymentControlProviderPlugin mockPaymentControlProviderPlugin;
-
     final PaymentOptions INVOICE_PAYMENT = new PaymentOptions() {
         @Override
         public boolean isExternalPayment() {
@@ -79,7 +76,6 @@ public class TestPaymentApi extends PaymentTestSuiteWithEmbeddedDB {
             return ImmutableList.<String>of(InvoicePaymentControlPluginApi.PLUGIN_NAME);
         }
     };
-
     final PaymentOptions CONTROL_PLUGIN_OPTIONS = new PaymentOptions() {
         @Override
         public boolean isExternalPayment() {
@@ -91,7 +87,8 @@ public class TestPaymentApi extends PaymentTestSuiteWithEmbeddedDB {
             return Arrays.asList(MockPaymentControlProviderPlugin.PLUGIN_NAME);
         }
     };
-
+    private MockPaymentProviderPlugin mockPaymentProviderPlugin;
+    private MockPaymentControlProviderPlugin mockPaymentControlProviderPlugin;
     private Account account;
 
     @BeforeClass(groups = "slow")
@@ -198,7 +195,7 @@ public class TestPaymentApi extends PaymentTestSuiteWithEmbeddedDB {
         checkPaymentMethodPagination(paymentMethodId, baseNbRecords + 1, false);
     }
 
-    @Test(groups = "slow", description="Verify we can make a refund on  payment whose original payment method was deleted. See 694")
+    @Test(groups = "slow", description = "Verify we can make a refund on  payment whose original payment method was deleted. See 694")
     public void testRefundAfterDeletedPaymentMethod() throws PaymentApiException {
 
         final BigDecimal requestedAmount = BigDecimal.TEN;
@@ -213,7 +210,6 @@ public class TestPaymentApi extends PaymentTestSuiteWithEmbeddedDB {
 
     @Test(groups = "slow")
     public void testCreateSuccessPurchase() throws PaymentApiException {
-
         final BigDecimal requestedAmount = BigDecimal.TEN;
 
         final String paymentExternalKey = "bwwrr";
@@ -294,7 +290,6 @@ public class TestPaymentApi extends PaymentTestSuiteWithEmbeddedDB {
 
     }
 
-
     @Test(groups = "slow")
     public void testCreateCancelledPurchase() throws PaymentApiException {
 
@@ -365,7 +360,8 @@ public class TestPaymentApi extends PaymentTestSuiteWithEmbeddedDB {
         mockPaymentProviderPlugin.makeNextPaymentFailWithException();
 
         final BigDecimal requestedAmount = BigDecimal.TEN;
-        final String paymentExternalKey = "pay controle external key";;
+        final String paymentExternalKey = "pay controle external key";
+
         final String transactionExternalKey = "txn control external key";
         try {
             paymentApi.createPurchaseWithPaymentControl(
@@ -382,7 +378,8 @@ public class TestPaymentApi extends PaymentTestSuiteWithEmbeddedDB {
         mockPaymentControlProviderPlugin.throwsException(new PaymentControlApiException());
 
         final BigDecimal requestedAmount = BigDecimal.TEN;
-        final String paymentExternalKey = "pay controle external key";;
+        final String paymentExternalKey = "pay controle external key";
+
         final String transactionExternalKey = "txn control external key";
         try {
             paymentApi.createPurchaseWithPaymentControl(
@@ -399,7 +396,8 @@ public class TestPaymentApi extends PaymentTestSuiteWithEmbeddedDB {
         mockPaymentControlProviderPlugin.throwsException(new IllegalStateException());
 
         final BigDecimal requestedAmount = BigDecimal.TEN;
-        final String paymentExternalKey = "pay controle external key";;
+        final String paymentExternalKey = "pay controle external key";
+
         final String transactionExternalKey = "txn control external key";
         try {
             paymentApi.createPurchaseWithPaymentControl(
@@ -976,7 +974,6 @@ public class TestPaymentApi extends PaymentTestSuiteWithEmbeddedDB {
             assertTrue(true);
         }
 
-
         final List<Payment> accountPayments = paymentApi.getAccountPayments(account.getId(), false, false, ImmutableList.<PluginProperty>of(), callContext);
         assertEquals(accountPayments.size(), 1);
         final Payment payment = accountPayments.get(0);
@@ -1001,7 +998,6 @@ public class TestPaymentApi extends PaymentTestSuiteWithEmbeddedDB {
         assertEquals(payment.getTransactions().get(0).getTransactionType(), TransactionType.PURCHASE);
     }
 
-
     @Test(groups = "slow")
     public void testCreateCancelledPurchaseWithPaymentControl() throws PaymentApiException, InvoiceApiException, EventBusException {
 
@@ -1043,7 +1039,6 @@ public class TestPaymentApi extends PaymentTestSuiteWithEmbeddedDB {
             assertTrue(true);
         }
 
-
         final List<Payment> accountPayments = paymentApi.getAccountPayments(account.getId(), false, false, ImmutableList.<PluginProperty>of(), callContext);
         assertEquals(accountPayments.size(), 1);
         final Payment payment = accountPayments.get(0);
@@ -1096,7 +1091,6 @@ public class TestPaymentApi extends PaymentTestSuiteWithEmbeddedDB {
 
     }
 
-
     @Test(groups = "slow")
     public void testCreateAbortedPurchaseWithPaymentControl() throws InvoiceApiException, EventBusException {
 
@@ -2503,6 +2497,83 @@ public class TestPaymentApi extends PaymentTestSuiteWithEmbeddedDB {
         Assert.assertNotEquals(failedAuthorization4.getTransactions().get(3).getExternalKey(), authKey);
     }
 
+    @Test(groups = "slow")
+    public void testSearchPayments() throws Exception {
+        // Add a second, non-default, payment method
+        final PaymentMethodPlugin pm = new DefaultNoOpPaymentMethodPlugin(UUID.randomUUID().toString(), false, null);
+        final UUID secondPmId = testHelper.addTestPaymentMethod(MockPaymentProviderPlugin.PLUGIN_NAME + "2", account, pm, ImmutableList.<PluginProperty>of());
+
+        Pagination<Payment> foundPayments = paymentApi.searchPayments("all", 0L, 10L, true, false, ImmutableList.<PluginProperty>of(), callContext);
+        Assert.assertFalse(foundPayments.iterator().hasNext());
+        Assert.assertEquals(foundPayments.getMaxNbRecords(), (Long) 0L);
+        Assert.assertEquals(foundPayments.getTotalNbRecords(), (Long) 0L);
+
+        foundPayments = paymentApi.searchPayments("A", 0L, 10L, true, false, ImmutableList.<PluginProperty>of(), callContext);
+        Assert.assertFalse(foundPayments.iterator().hasNext());
+        Assert.assertEquals(foundPayments.getMaxNbRecords(), (Long) 0L);
+        Assert.assertEquals(foundPayments.getTotalNbRecords(), (Long) 0L);
+
+        foundPayments = paymentApi.searchPayments("B", 0L, 10L, true, false, ImmutableList.<PluginProperty>of(), callContext);
+        Assert.assertFalse(foundPayments.iterator().hasNext());
+        Assert.assertEquals(foundPayments.getMaxNbRecords(), (Long) 0L);
+        Assert.assertEquals(foundPayments.getTotalNbRecords(), (Long) 0L);
+
+        final Payment payment1 = paymentApi.createPurchase(account,
+                                                           account.getPaymentMethodId(),
+                                                           null,
+                                                           BigDecimal.TEN,
+                                                           Currency.USD,
+                                                           clock.getUTCNow(),
+                                                           UUID.randomUUID().toString(),
+                                                           UUID.randomUUID().toString(),
+                                                           ImmutableList.<PluginProperty>of(new PluginProperty("group", "all", false), new PluginProperty("marker", "A", false)),
+                                                           callContext);
+
+        foundPayments = paymentApi.searchPayments("all", 0L, 10L, true, false, ImmutableList.<PluginProperty>of(), callContext);
+        Assert.assertTrue(foundPayments.iterator().hasNext());
+        Assert.assertEquals(foundPayments.getMaxNbRecords(), (Long) 1L);
+        Assert.assertEquals(foundPayments.getTotalNbRecords(), (Long) 1L);
+
+        foundPayments = paymentApi.searchPayments("A", 0L, 10L, true, false, ImmutableList.<PluginProperty>of(), callContext);
+        Assert.assertTrue(foundPayments.iterator().hasNext());
+        Assert.assertEquals(foundPayments.getMaxNbRecords(), (Long) 1L);
+        Assert.assertEquals(foundPayments.getTotalNbRecords(), (Long) 1L);
+        Assert.assertEquals(foundPayments.iterator().next().getId(), payment1.getId());
+
+        foundPayments = paymentApi.searchPayments("B", 0L, 10L, true, false, ImmutableList.<PluginProperty>of(), callContext);
+        Assert.assertFalse(foundPayments.iterator().hasNext());
+        Assert.assertEquals(foundPayments.getMaxNbRecords(), (Long) 1L);
+        Assert.assertEquals(foundPayments.getTotalNbRecords(), (Long) 0L);
+
+        final Payment payment2 = paymentApi.createPurchase(account,
+                                                           secondPmId,
+                                                           null,
+                                                           BigDecimal.TEN,
+                                                           Currency.USD,
+                                                           clock.getUTCNow(),
+                                                           UUID.randomUUID().toString(),
+                                                           UUID.randomUUID().toString(),
+                                                           ImmutableList.<PluginProperty>of(new PluginProperty("group", "all", false), new PluginProperty("marker", "B", false)),
+                                                           callContext);
+
+        foundPayments = paymentApi.searchPayments("all", 0L, 10L, true, false, ImmutableList.<PluginProperty>of(), callContext);
+        Assert.assertTrue(foundPayments.iterator().hasNext());
+        Assert.assertEquals(foundPayments.getMaxNbRecords(), (Long) 2L);
+        Assert.assertEquals(foundPayments.getTotalNbRecords(), (Long) 2L);
+
+        foundPayments = paymentApi.searchPayments("A", 0L, 10L, true, false, ImmutableList.<PluginProperty>of(), callContext);
+        Assert.assertTrue(foundPayments.iterator().hasNext());
+        Assert.assertEquals(foundPayments.getMaxNbRecords(), (Long) 2L);
+        Assert.assertEquals(foundPayments.getTotalNbRecords(), (Long) 1L);
+        Assert.assertEquals(foundPayments.iterator().next().getId(), payment1.getId());
+
+        foundPayments = paymentApi.searchPayments("B", 0L, 10L, true, false, ImmutableList.<PluginProperty>of(), callContext);
+        Assert.assertTrue(foundPayments.iterator().hasNext());
+        Assert.assertEquals(foundPayments.getMaxNbRecords(), (Long) 2L);
+        Assert.assertEquals(foundPayments.getTotalNbRecords(), (Long) 1L);
+        Assert.assertEquals(foundPayments.iterator().next().getId(), payment2.getId());
+    }
+
     private void verifyRefund(final Payment refund, final String paymentExternalKey, final String paymentTransactionExternalKey, final String refundTransactionExternalKey, final BigDecimal requestedAmount, final BigDecimal refundAmount, final TransactionStatus transactionStatus) {
         Assert.assertEquals(refund.getExternalKey(), paymentExternalKey);
         Assert.assertEquals(refund.getTransactions().size(), 2);
diff --git a/payment/src/test/java/org/killbill/billing/payment/glue/TestPaymentModule.java b/payment/src/test/java/org/killbill/billing/payment/glue/TestPaymentModule.java
index a4bc6e9..447cd34 100644
--- a/payment/src/test/java/org/killbill/billing/payment/glue/TestPaymentModule.java
+++ b/payment/src/test/java/org/killbill/billing/payment/glue/TestPaymentModule.java
@@ -54,6 +54,8 @@ public class TestPaymentModule extends PaymentModule {
     @Override
     protected void installPaymentProviderPlugins(final PaymentConfig config) {
         install(new MockPaymentProviderPluginModule(MockPaymentProviderPlugin.PLUGIN_NAME, clock, configSource));
+        // Install a second instance, to test codepaths with multiple plugins (e.g. search)
+        install(new MockPaymentProviderPluginModule(MockPaymentProviderPlugin.PLUGIN_NAME + "2", clock, configSource));
     }
 
     private void installExternalApis() {
diff --git a/payment/src/test/java/org/killbill/billing/payment/provider/MockPaymentProviderPlugin.java b/payment/src/test/java/org/killbill/billing/payment/provider/MockPaymentProviderPlugin.java
index 78004a5..6306541 100644
--- a/payment/src/test/java/org/killbill/billing/payment/provider/MockPaymentProviderPlugin.java
+++ b/payment/src/test/java/org/killbill/billing/payment/provider/MockPaymentProviderPlugin.java
@@ -330,7 +330,21 @@ public class MockPaymentProviderPlugin implements PaymentPluginApi {
     @Override
     public Pagination<PaymentTransactionInfoPlugin> searchPayments(final String searchKey, final Long offset, final Long limit, final Iterable<PluginProperty> properties, final TenantContext tenantContext) throws PaymentPluginApiException {
         updateLastThreadState();
-        throw new IllegalStateException("Not implemented");
+
+        final ImmutableList<PaymentTransactionInfoPlugin> results = ImmutableList.<PaymentTransactionInfoPlugin>copyOf(Iterables.<PaymentTransactionInfoPlugin>filter(Iterables.<PaymentTransactionInfoPlugin>concat(paymentTransactions.values()), new Predicate<PaymentTransactionInfoPlugin>() {
+            @Override
+            public boolean apply(final PaymentTransactionInfoPlugin input) {
+                if (input.getProperties() !=  null) {
+                    for (final PluginProperty cur : input.getProperties()) {
+                        if (cur.getValue().equals(searchKey)) {
+                            return true;
+                        }
+                    }
+                }
+                return (input.getKbPaymentId().toString().equals(searchKey));
+            }
+        }));
+        return DefaultPagination.<PaymentTransactionInfoPlugin>build(offset, limit, paymentTransactions.size(), results);
     }
 
     @Override
@@ -492,7 +506,7 @@ public class MockPaymentProviderPlugin implements PaymentPluginApi {
             processedCurrency = currency;
         }
 
-        final PaymentTransactionInfoPlugin result = new DefaultNoOpPaymentInfoPlugin(kbPaymentId, kbTransactionId, type, processedAmount, processedCurrency, clock.getUTCNow(), clock.getUTCNow(), status, errorCode, error);
+        final PaymentTransactionInfoPlugin result = new DefaultNoOpPaymentInfoPlugin(kbPaymentId, kbTransactionId, type, processedAmount, processedCurrency, clock.getUTCNow(), clock.getUTCNow(), status, errorCode, error, null, null, ImmutableList.<PluginProperty>copyOf(pluginProperties));
         List<PaymentTransactionInfoPlugin> existingTransactions = paymentTransactions.get(kbPaymentId.toString());
         if (existingTransactions == null) {
             existingTransactions = new ArrayList<PaymentTransactionInfoPlugin>();
diff --git a/payment/src/test/java/org/killbill/billing/payment/TestPaymentHelper.java b/payment/src/test/java/org/killbill/billing/payment/TestPaymentHelper.java
index 1f7271d..6183c76 100644
--- a/payment/src/test/java/org/killbill/billing/payment/TestPaymentHelper.java
+++ b/payment/src/test/java/org/killbill/billing/payment/TestPaymentHelper.java
@@ -172,15 +172,19 @@ public class TestPaymentHelper {
     }
 
     public Account addTestPaymentMethod(final Account account, final PaymentMethodPlugin paymentMethodInfo, final Iterable<PluginProperty> pluginProperties) throws Exception {
-        final UUID paymentMethodId = paymentApi.addPaymentMethod(account, paymentMethodInfo.getExternalPaymentMethodId(), MockPaymentProviderPlugin.PLUGIN_NAME, true, paymentMethodInfo, pluginProperties, context);
-        if (isFastTest()) {
+        final UUID pmId = addTestPaymentMethod(MockPaymentProviderPlugin.PLUGIN_NAME, account, paymentMethodInfo, pluginProperties);
+        // To reflect the payment method id change
+        return accountApi.getAccountById(account.getId(), context);
+    }
+
+    public UUID addTestPaymentMethod(final String pluginName, final Account account, final PaymentMethodPlugin paymentMethodInfo, final Iterable<PluginProperty> pluginProperties) throws Exception {
+        final boolean setDefault = paymentMethodInfo.isDefaultPaymentMethod();
+        final UUID paymentMethodId = paymentApi.addPaymentMethod(account, paymentMethodInfo.getExternalPaymentMethodId(), pluginName, setDefault, paymentMethodInfo, pluginProperties, context);
+        if (isFastTest() && setDefault) {
             final Account account1 = new MockAccountBuilder(account).paymentMethodId(paymentMethodId).build();
-            accountApi.updateAccount(account, context);
-            return account1;
-        } else {
-            // To reflect the payment method id change
-            return accountApi.getAccountById(account.getId(), context);
+            accountApi.updateAccount(account1, context);
         }
+        return paymentMethodId;
     }
 
     // Unfortunately, this helper is shared across fast and slow tests
diff --git a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestPayment.java b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestPayment.java
index 6665751..940e2d4 100644
--- a/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestPayment.java
+++ b/profiles/killbill/src/test/java/org/killbill/billing/jaxrs/TestPayment.java
@@ -19,7 +19,6 @@ package org.killbill.billing.jaxrs;
 
 import java.math.BigDecimal;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
 import java.util.List;
@@ -27,6 +26,7 @@ import java.util.Map;
 import java.util.UUID;
 
 import javax.annotation.Nullable;
+import javax.ws.rs.HEAD;
 
 import org.joda.time.DateTime;
 import org.killbill.billing.ObjectType;
@@ -963,7 +963,7 @@ public class TestPayment extends TestJaxrsBase {
         assertEquals(Payments.size(), paymentNb);
         assertEquals(Payments.get(paymentNb - 1), payment);
 
-        final Payment retrievedPayment = paymentApi.getPayment(payment.getPaymentId(), NULL_PLUGIN_PROPERTIES, requestOptions);
+        final Payment retrievedPayment = paymentApi.getPayment(payment.getPaymentId(), false, false, NULL_PLUGIN_PROPERTIES, AuditLevel.NONE, requestOptions);
         assertEquals(retrievedPayment, payment);
 
         final Payments paymentsForAccount = accountApi.getPaymentsForAccount(account.getAccountId(), NULL_PLUGIN_PROPERTIES, requestOptions);