From b7c8bc6e27dc92b1b1ab39c2131da55f9a61fa03 Mon Sep 17 00:00:00 2001 From: mcilwain Date: Tue, 19 Dec 2017 13:42:34 -0800 Subject: [PATCH] Add an EPP lifecycle test verifying that EAP fees are not refunded This also incorporates general improvements and additions to the existing EPP lifecycle tests around domain deletion. As a refresher: There is a 5 day add grace period (AGP) following domain creation. Domains that are deleted during that period have their create costs (but not EAP costs) refunded. This deletion takes place immediately. Refunds are implemented by issuing a Cancellation for the associated OneTime billing event. Domains that are deleted after AGP ends first go through a 30 day redemption grace period followed by a 5 day pending deletion period. No create fees are refunded in this case. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=179597874 --- .../registry/model/billing/BillingEvent.java | 14 +- .../flows/EppLifecycleDomainTest.java | 320 ++++++++++++++---- .../google/registry/flows/FlowTestCase.java | 4 +- .../flows/testdata/domain_create_eap_fee.xml | 24 ++ .../domain_create_response_eap_fee.xml | 25 ++ .../testdata/domain_delete_response_fee.xml | 18 + .../domain_info_response_nonexistent.xml | 12 + ....xml => domain_info_response_wildcard.xml} | 2 +- .../registry/testing/DatastoreHelper.java | 25 +- 9 files changed, 360 insertions(+), 84 deletions(-) create mode 100644 javatests/google/registry/flows/testdata/domain_create_eap_fee.xml create mode 100644 javatests/google/registry/flows/testdata/domain_create_response_eap_fee.xml create mode 100644 javatests/google/registry/flows/testdata/domain_delete_response_fee.xml create mode 100644 javatests/google/registry/flows/testdata/domain_info_response_nonexistent.xml rename javatests/google/registry/flows/testdata/{domain_info_response_pendingdelete.xml => domain_info_response_wildcard.xml} (96%) diff --git a/java/google/registry/model/billing/BillingEvent.java b/java/google/registry/model/billing/BillingEvent.java index e37bd408f..d0cfcfeb6 100644 --- a/java/google/registry/model/billing/BillingEvent.java +++ b/java/google/registry/model/billing/BillingEvent.java @@ -189,11 +189,11 @@ public abstract class BillingEvent extends ImmutableObject @Override public T build() { T instance = getInstance(); - checkNotNull(instance.reason); - checkNotNull(instance.clientId); - checkNotNull(instance.eventTime); - checkNotNull(instance.targetId); - checkNotNull(instance.parent); + checkNotNull(instance.reason, "Reason must be set"); + checkNotNull(instance.clientId, "Client ID must be set"); + checkNotNull(instance.eventTime, "Event time must be set"); + checkNotNull(instance.targetId, "Target ID must be set"); + checkNotNull(instance.parent, "Parent must be set"); return super.build(); } } @@ -502,8 +502,8 @@ public abstract class BillingEvent extends ImmutableObject @Override public Cancellation build() { Cancellation instance = getInstance(); - checkNotNull(instance.billingTime); - checkNotNull(instance.reason); + checkNotNull(instance.billingTime, "Must set billing time"); + checkNotNull(instance.reason, "Must set reason"); checkState((instance.refOneTime == null) != (instance.refRecurring == null), "Cancellations must have exactly one billing event key set"); return super.build(); diff --git a/javatests/google/registry/flows/EppLifecycleDomainTest.java b/javatests/google/registry/flows/EppLifecycleDomainTest.java index 8167e8d0f..70bf3d738 100644 --- a/javatests/google/registry/flows/EppLifecycleDomainTest.java +++ b/javatests/google/registry/flows/EppLifecycleDomainTest.java @@ -14,20 +14,40 @@ package google.registry.flows; +import static com.google.common.truth.Truth8.assertThat; +import static google.registry.model.EppResourceUtils.loadByForeignKey; import static google.registry.model.eppoutput.Result.Code.SUCCESS; import static google.registry.model.eppoutput.Result.Code.SUCCESS_AND_CLOSE; import static google.registry.model.eppoutput.Result.Code.SUCCESS_WITH_ACTION_PENDING; +import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.testing.DatastoreHelper.assertBillingEventsForResource; import static google.registry.testing.DatastoreHelper.createTld; import static google.registry.testing.DatastoreHelper.createTlds; +import static google.registry.testing.DatastoreHelper.getOnlyHistoryEntryOfType; +import static google.registry.testing.DatastoreHelper.persistResource; +import static google.registry.testing.DatastoreHelper.stripBillingEventId; import static google.registry.testing.EppMetricSubject.assertThat; import static google.registry.util.DateTimeUtils.START_OF_TIME; +import static org.joda.money.CurrencyUnit.USD; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSortedMap; import com.google.re2j.Matcher; import com.google.re2j.Pattern; +import com.googlecode.objectify.Key; +import google.registry.model.billing.BillingEvent; +import google.registry.model.billing.BillingEvent.Flag; +import google.registry.model.billing.BillingEvent.OneTime; +import google.registry.model.billing.BillingEvent.Reason; +import google.registry.model.domain.DomainResource; +import google.registry.model.registry.Registry; import google.registry.model.registry.Registry.TldState; +import google.registry.model.reporting.HistoryEntry.Type; import google.registry.testing.AppEngineRule; +import java.util.Objects; +import java.util.Optional; +import org.joda.money.Money; import org.joda.time.DateTime; import org.junit.Before; import org.junit.Rule; @@ -50,31 +70,37 @@ public class EppLifecycleDomainTest extends EppTestCase { /** Create the two administrative contacts and two hosts. */ void createContactsAndHosts() throws Exception { - DateTime startTime = DateTime.parse("2000-06-01T00:00:00Z"); - assertCommandAndResponse( - "contact_create_sh8013.xml", - ImmutableMap.of(), - "contact_create_response_sh8013.xml", - ImmutableMap.of("CRDATE", "2000-06-01T00:00:00Z"), - startTime); - assertCommandAndResponse( - "contact_create_jd1234.xml", - "contact_create_response_jd1234.xml", - startTime.plusMinutes(1)); + DateTime createTime = DateTime.parse("2000-06-01T00:00:00Z"); + createContacts(createTime); assertCommandAndResponse( "host_create.xml", ImmutableMap.of("HOSTNAME", "ns1.example.external"), "host_create_response.xml", ImmutableMap.of( - "HOSTNAME", "ns1.example.external", "CRDATE", startTime.plusMinutes(2).toString()), - startTime.plusMinutes(2)); + "HOSTNAME", "ns1.example.external", "CRDATE", createTime.plusMinutes(2).toString()), + createTime.plusMinutes(2)); assertCommandAndResponse( "host_create.xml", ImmutableMap.of("HOSTNAME", "ns2.example.external"), "host_create_response.xml", ImmutableMap.of( - "HOSTNAME", "ns2.example.external", "CRDATE", startTime.plusMinutes(3).toString()), - startTime.plusMinutes(3)); + "HOSTNAME", "ns2.example.external", "CRDATE", createTime.plusMinutes(3).toString()), + createTime.plusMinutes(3)); + } + + private void createContacts(DateTime createTime) throws Exception { + assertCommandAndResponse( + "contact_create_sh8013.xml", + ImmutableMap.of(), + "contact_create_response_sh8013.xml", + ImmutableMap.of("CRDATE", createTime.toString()), + createTime); + assertCommandAndResponse( + "contact_create_jd1234.xml", + ImmutableMap.of(), + "contact_create_response_jd1234.xml", + ImmutableMap.of("CRDATE", createTime.plusMinutes(1).toString()), + createTime.plusMinutes(1)); } /** Creates the domain fakesite.example with two nameservers on it. */ @@ -117,18 +143,7 @@ public class EppLifecycleDomainTest extends EppTestCase { @Test public void testDomainDeleteRestore() throws Exception { assertCommandAndResponse("login_valid.xml", "login_response.xml"); - - // Create contacts sh8013 and jd1234. - assertCommandAndResponse( - "contact_create_sh8013.xml", - null, - "contact_create_response_sh8013.xml", - ImmutableMap.of("CRDATE", "2000-06-01T00:00:00Z"), - DateTime.parse("2000-06-01T00:00:00Z")); - assertCommandAndResponse( - "contact_create_jd1234.xml", - "contact_create_response_jd1234.xml", - DateTime.parse("2000-06-01T00:01:00Z")); + createContacts(DateTime.parse("2000-06-01T00:00:00Z")); // Create domain example.tld assertCommandAndResponse( @@ -152,42 +167,237 @@ public class EppLifecycleDomainTest extends EppTestCase { } @Test - public void testDomainDeletion_withinAddGracePeriod() throws Exception { + public void testDomainDeletion_withinAddGracePeriod_deletesImmediately() throws Exception { assertCommandAndResponse("login_valid.xml", "login_response.xml"); + createContacts(DateTime.parse("2000-06-01T00:00:00Z")); - // Create contacts sh8013 and jd1234. + // Create domain example.tld + DateTime createTime = DateTime.parse("2000-06-01T00:02:00Z"); assertCommandAndResponse( - "contact_create_sh8013.xml", - null, - "contact_create_response_sh8013.xml", - ImmutableMap.of("CRDATE", "2000-06-01T00:00:00Z"), - DateTime.parse("2000-06-01T00:00:00Z")); - assertCommandAndResponse( - "contact_create_jd1234.xml", - "contact_create_response_jd1234.xml", - DateTime.parse("2000-06-01T00:01:00Z")); + "domain_create_no_hosts_or_dsdata.xml", + "domain_create_response.xml", + createTime); + DomainResource domain = + loadByForeignKey(DomainResource.class, "example.tld", createTime.plusHours(1)); + + // Delete domain example.tld within the add grace period. + DateTime deleteTime = createTime.plusDays(1); + assertCommandAndResponse( + "domain_delete.xml", + "generic_success_response.xml", + deleteTime); + + // Verify that it is immediately non-existent. + assertCommandAndResponse( + "domain_info.xml", + "domain_info_response_nonexistent.xml", + deleteTime.plusSeconds(1)); + + // The expected one-time billing event, that should have an associated Cancellation. + OneTime oneTimeCreateBillingEvent = makeOneTimeCreateBillingEvent(domain, createTime); + // Verify that the OneTime billing event associated with the domain creation is canceled. + assertBillingEventsForResource( + domain, + // Check the existence of the expected create one-time billing event. + oneTimeCreateBillingEvent, + makeRecurringCreateBillingEvent(domain, createTime, deleteTime), + // Check for the existence of a cancellation for the given one-time billing event. + makeCancellationBillingEventFor( + domain, oneTimeCreateBillingEvent, createTime, deleteTime)); + + assertCommandAndResponse("logout.xml", "logout_response.xml"); + } + + @Test + public void testDomainDeletion_outsideAddGracePeriod_showsRedemptionPeriod() throws Exception { + assertCommandAndResponse("login_valid.xml", "login_response.xml"); + createContacts(DateTime.parse("2000-06-01T00:00:00Z")); + + DateTime createTime = DateTime.parse("2000-06-01T00:02:00Z"); // Create domain example.tld assertCommandAndResponse( "domain_create_no_hosts_or_dsdata.xml", "domain_create_response.xml", - DateTime.parse("2000-06-01T00:02:00Z")); + createTime); + DateTime deleteTime = DateTime.parse("2000-07-07T00:02:00Z"); // 1 month and 6 days after // Delete domain example.tld after its add grace period has expired. assertCommandAndResponse( "domain_delete.xml", "generic_success_action_pending_response.xml", - DateTime.parse("2000-07-01T00:02:00Z")); + deleteTime); - // Poke the domain a little at various times to see its status + // Verify that domain shows redemptionPeriod soon after deletion. assertCommandAndResponse( "domain_info.xml", - "domain_info_response_pendingdelete.xml", - DateTime.parse("2000-08-01T00:02:00Z")); // 1 day out. + ImmutableMap.of(), + "domain_info_response_wildcard.xml", + ImmutableMap.of("STATUS", "redemptionPeriod"), + DateTime.parse("2000-07-08T00:00:00Z")); + + // Verify that the domain shows pendingDelete next. + assertCommandAndResponse( + "domain_info.xml", + ImmutableMap.of(), + "domain_info_response_wildcard.xml", + ImmutableMap.of("STATUS", "pendingDelete"), + DateTime.parse("2000-08-08T00:00:00Z")); + + // Verify that the domain is non-existent (available for registration) later. + assertCommandAndResponse( + "domain_info.xml", + "domain_info_response_nonexistent.xml", + DateTime.parse("2000-09-01T00:00:00Z")); + + DomainResource domain = + loadByForeignKey( + DomainResource.class, "example.tld", DateTime.parse("2000-08-01T00:02:00Z")); + // Verify that the autorenew was ended and that the one-time billing event is not canceled. + assertBillingEventsForResource( + domain, + makeOneTimeCreateBillingEvent(domain, createTime), + makeRecurringCreateBillingEvent(domain, createTime, deleteTime)); assertCommandAndResponse("logout.xml", "logout_response.xml"); } + @Test + public void testEapDomainDeletion_withinAddGracePeriod_eapFeeIsNotRefunded() throws Exception { + assertCommandAndResponse("login_valid_fee_extension.xml", "login_response.xml"); + createContacts(DateTime.parse("2000-06-01T00:00:00Z")); + + // Set the EAP schedule. + persistResource( + Registry.get("tld") + .asBuilder() + .setEapFeeSchedule( + ImmutableSortedMap.of( + START_OF_TIME, Money.of(USD, 0), + DateTime.parse("2000-06-01T00:00:00Z"), Money.of(USD, 100), + DateTime.parse("2000-06-02T00:00:00Z"), Money.of(USD, 0))) + .build()); + + // Create domain example.tld, which should have an EAP fee of USD 100. + DateTime createTime = DateTime.parse("2000-06-01T00:02:00Z"); + assertCommandAndResponse( + "domain_create_eap_fee.xml", + "domain_create_response_eap_fee.xml", + createTime); + + DomainResource domain = + loadByForeignKey( + DomainResource.class, "example.tld", DateTime.parse("2000-06-01T00:03:00Z")); + + // Delete domain example.tld within the add grade period. + DateTime deleteTime = createTime.plusDays(1); + assertCommandAndResponse( + "domain_delete.xml", + "domain_delete_response_fee.xml", + deleteTime); + + // Verify that the OneTime billing event associated with the base fee of domain registration and + // is canceled and the autorenew is ended, but that the EAP fee is not canceled. + OneTime expectedCreateEapBillingEvent = + new BillingEvent.OneTime.Builder() + .setReason(Reason.FEE_EARLY_ACCESS) + .setTargetId("example.tld") + .setClientId("NewRegistrar") + .setCost(Money.parse("USD 100.00")) + .setEventTime(createTime) + .setBillingTime(createTime.plus(Registry.get("tld").getRenewGracePeriodLength())) + .setParent(getOnlyHistoryEntryOfType(domain, Type.DOMAIN_CREATE)) + .build(); + + // The expected one-time billing event, that should have an associated Cancellation. + OneTime expectedOneTimeCreateBillingEvent = makeOneTimeCreateBillingEvent(domain, createTime); + assertBillingEventsForResource( + domain, + // Check for the expected create one-time billing event ... + expectedOneTimeCreateBillingEvent, + // ... and the expected one-time EAP fee billing event ... + expectedCreateEapBillingEvent, + makeRecurringCreateBillingEvent(domain, createTime, deleteTime), + // ... and verify that the create one-time billing event was canceled ... + makeCancellationBillingEventFor( + domain, expectedOneTimeCreateBillingEvent, createTime, deleteTime)); + // ... but there was NOT a Cancellation for the EAP fee, as this would fail if additional + // billing events were present. + + assertCommandAndResponse("logout.xml", "logout_response.xml"); + } + + /** Makes a one-time billing event corresponding to the given domain's creation. */ + private static BillingEvent.OneTime makeOneTimeCreateBillingEvent( + DomainResource domain, DateTime createTime) { + return new BillingEvent.OneTime.Builder() + .setReason(Reason.CREATE) + .setTargetId(domain.getFullyQualifiedDomainName()) + .setClientId(domain.getCurrentSponsorClientId()) + .setCost(Money.parse("USD 26.00")) + .setPeriodYears(2) + .setEventTime(createTime) + .setBillingTime(createTime.plus(Registry.get(domain.getTld()).getRenewGracePeriodLength())) + .setParent(getOnlyHistoryEntryOfType(domain, Type.DOMAIN_CREATE)) + .build(); + } + + /** Makes a recurring billing event corresponding to the given domain's creation. */ + private static BillingEvent.Recurring makeRecurringCreateBillingEvent( + DomainResource domain, DateTime createTime, DateTime endTime) { + return new BillingEvent.Recurring.Builder() + .setReason(Reason.RENEW) + .setFlags(ImmutableSet.of(Flag.AUTO_RENEW)) + .setTargetId(domain.getFullyQualifiedDomainName()) + .setClientId(domain.getCurrentSponsorClientId()) + .setEventTime(createTime.plusYears(2)) + .setRecurrenceEndTime(endTime) + .setParent(getOnlyHistoryEntryOfType(domain, Type.DOMAIN_CREATE)) + .build(); + } + + /** Makes a cancellation billing event cancelling out the given domain create billing event. */ + private static BillingEvent.Cancellation makeCancellationBillingEventFor( + DomainResource domain, + OneTime billingEventToCancel, + DateTime createTime, + DateTime deleteTime) { + return new BillingEvent.Cancellation.Builder() + .setTargetId(domain.getFullyQualifiedDomainName()) + .setClientId(domain.getCurrentSponsorClientId()) + .setEventTime(deleteTime) + .setOneTimeEventKey(findKeyToActualOneTimeBillingEvent(billingEventToCancel)) + .setBillingTime(createTime.plus(Registry.get(domain.getTld()).getRenewGracePeriodLength())) + .setReason(Reason.CREATE) + .setParent(getOnlyHistoryEntryOfType(domain, Type.DOMAIN_DELETE)) + .build(); + } + + /** + * Finds the Key to the actual one-time create billing event associated with a domain's creation. + * + *

This is used in the situation where we have created an expected billing event associated + * with the domain's creation (which is passed as the parameter here), then need to locate the key + * to the actual billing event in Datastore that would be seen on a Cancellation billing event. + * This is necessary because the ID will be different even though all the rest of the fields are + * the same. + */ + private static Key findKeyToActualOneTimeBillingEvent(OneTime expectedBillingEvent) { + Optional actualCreateBillingEvent = + ofy() + .load() + .type(BillingEvent.OneTime.class) + .list() + .stream() + .filter( + b -> + Objects.equals( + stripBillingEventId(b), stripBillingEventId(expectedBillingEvent))) + .findFirst(); + assertThat(actualCreateBillingEvent).isPresent(); + return Key.create(actualCreateBillingEvent.get()); + } + @Test public void testDomainDeletionWithSubordinateHost_fails() throws Exception { assertCommandAndResponse("login_valid.xml", "login_response.xml"); @@ -751,17 +961,7 @@ public class EppLifecycleDomainTest extends EppTestCase { createTlds("bar.foo.tld", "foo.tld"); assertCommandAndResponse("login_valid.xml", "login_response.xml"); - - assertCommandAndResponse( - "contact_create_sh8013.xml", - null, - "contact_create_response_sh8013.xml", - ImmutableMap.of("CRDATE", "2000-06-01T00:00:00Z"), - DateTime.parse("2000-06-01T00:00:00Z")); - assertCommandAndResponse( - "contact_create_jd1234.xml", - "contact_create_response_jd1234.xml", - DateTime.parse("2000-06-01T00:01:00Z")); + createContacts(DateTime.parse("2000-06-01T00:00:00Z")); // Create domain example.bar.foo.tld assertCommandAndResponse( @@ -795,17 +995,7 @@ public class EppLifecycleDomainTest extends EppTestCase { createTld("tld.foo"); assertCommandAndResponse("login_valid.xml", "login_response.xml"); - - assertCommandAndResponse( - "contact_create_sh8013.xml", - null, - "contact_create_response_sh8013.xml", - ImmutableMap.of("CRDATE", "2000-06-01T00:00:00Z"), - DateTime.parse("2000-06-01T00:00:00Z")); - assertCommandAndResponse( - "contact_create_jd1234.xml", - "contact_create_response_jd1234.xml", - DateTime.parse("2000-06-01T00:01:00Z")); + createContacts(DateTime.parse("2000-06-01T00:00:00Z")); // Create domain example.tld.foo assertCommandAndResponse( diff --git a/javatests/google/registry/flows/FlowTestCase.java b/javatests/google/registry/flows/FlowTestCase.java index f9f27f99e..7acc28150 100644 --- a/javatests/google/registry/flows/FlowTestCase.java +++ b/javatests/google/registry/flows/FlowTestCase.java @@ -21,9 +21,9 @@ import static com.google.common.collect.Sets.difference; import static com.google.common.truth.Truth.assertThat; import static google.registry.flows.EppXmlTransformer.marshal; import static google.registry.model.ofy.ObjectifyService.ofy; -import static google.registry.testing.DatastoreHelper.BILLING_EVENT_ID_STRIPPER; import static google.registry.testing.DatastoreHelper.POLL_MESSAGE_ID_STRIPPER; import static google.registry.testing.DatastoreHelper.getPollMessages; +import static google.registry.testing.DatastoreHelper.stripBillingEventId; import static google.registry.xml.XmlTestUtils.assertXmlEquals; import static java.nio.charset.StandardCharsets.UTF_8; import static org.joda.time.DateTimeZone.UTC; @@ -215,7 +215,7 @@ public abstract class FlowTestCase extends ShardableTestCase { gracePeriod.getClientId(), null)) .apply(entry.getKey()), - BILLING_EVENT_ID_STRIPPER.apply(entry.getValue())); + stripBillingEventId(entry.getValue())); } return builder.build(); } diff --git a/javatests/google/registry/flows/testdata/domain_create_eap_fee.xml b/javatests/google/registry/flows/testdata/domain_create_eap_fee.xml new file mode 100644 index 000000000..ee41134ac --- /dev/null +++ b/javatests/google/registry/flows/testdata/domain_create_eap_fee.xml @@ -0,0 +1,24 @@ + + + + + example.tld + 2 + jd1234 + sh8013 + sh8013 + + 2fooBAR + + + + + + USD + 26.00 + 100.00 + + + ABC-12345 + + diff --git a/javatests/google/registry/flows/testdata/domain_create_response_eap_fee.xml b/javatests/google/registry/flows/testdata/domain_create_response_eap_fee.xml new file mode 100644 index 000000000..a80bc2292 --- /dev/null +++ b/javatests/google/registry/flows/testdata/domain_create_response_eap_fee.xml @@ -0,0 +1,25 @@ + + + + Command completed successfully + + + + example.tld + 2000-06-01T00:02:00Z + 2002-06-01T00:02:00Z + + + + + USD + 26.00 + 100.00 + + + + ABC-12345 + server-trid + + + diff --git a/javatests/google/registry/flows/testdata/domain_delete_response_fee.xml b/javatests/google/registry/flows/testdata/domain_delete_response_fee.xml new file mode 100644 index 000000000..d1498878d --- /dev/null +++ b/javatests/google/registry/flows/testdata/domain_delete_response_fee.xml @@ -0,0 +1,18 @@ + + + + Command completed successfully + + + + USD + -26.00 + + + + ABC-12345 + server-trid + + + diff --git a/javatests/google/registry/flows/testdata/domain_info_response_nonexistent.xml b/javatests/google/registry/flows/testdata/domain_info_response_nonexistent.xml new file mode 100644 index 000000000..e2672146e --- /dev/null +++ b/javatests/google/registry/flows/testdata/domain_info_response_nonexistent.xml @@ -0,0 +1,12 @@ + + + + The domain with given ID (example.tld) doesn't exist. + + + ABC-12345 + server-trid + + + diff --git a/javatests/google/registry/flows/testdata/domain_info_response_pendingdelete.xml b/javatests/google/registry/flows/testdata/domain_info_response_wildcard.xml similarity index 96% rename from javatests/google/registry/flows/testdata/domain_info_response_pendingdelete.xml rename to javatests/google/registry/flows/testdata/domain_info_response_wildcard.xml index 8471fda0b..c10ba4b5e 100644 --- a/javatests/google/registry/flows/testdata/domain_info_response_pendingdelete.xml +++ b/javatests/google/registry/flows/testdata/domain_info_response_wildcard.xml @@ -25,7 +25,7 @@ - + diff --git a/javatests/google/registry/testing/DatastoreHelper.java b/javatests/google/registry/testing/DatastoreHelper.java index 81cde7d83..8f79ef987 100644 --- a/javatests/google/registry/testing/DatastoreHelper.java +++ b/javatests/google/registry/testing/DatastoreHelper.java @@ -660,16 +660,20 @@ public class DatastoreHelper { /** Assert that the actual billing event matches the expected one, ignoring IDs. */ public static void assertBillingEventsEqual(BillingEvent actual, BillingEvent expected) { - assertThat(BILLING_EVENT_ID_STRIPPER.apply(actual)) - .isEqualTo(BILLING_EVENT_ID_STRIPPER.apply(expected)); + assertThat(stripBillingEventId(actual)).isEqualTo(stripBillingEventId(expected)); } /** Assert that the actual billing events match the expected ones, ignoring IDs and order. */ public static void assertBillingEventsEqual( Iterable actual, Iterable expected) { - assertThat(Streams.stream(actual).map(BILLING_EVENT_ID_STRIPPER).collect(toImmutableList())) + assertThat( + Streams.stream(actual) + .map(DatastoreHelper::stripBillingEventId) + .collect(toImmutableList())) .containsExactlyElementsIn( - Streams.stream(expected).map(BILLING_EVENT_ID_STRIPPER).collect(toImmutableList())); + Streams.stream(expected) + .map(DatastoreHelper::stripBillingEventId) + .collect(toImmutableList())); } /** Assert that the expected billing events are exactly the ones found in the fake Datastore. */ @@ -689,10 +693,12 @@ public class DatastoreHelper { EppResource resource, BillingEvent... expected) throws Exception { assertThat( Streams.stream(getBillingEvents(resource)) - .map(BILLING_EVENT_ID_STRIPPER) + .map(DatastoreHelper::stripBillingEventId) .collect(toImmutableList())) .containsExactlyElementsIn( - Arrays.stream(expected).map(BILLING_EVENT_ID_STRIPPER).collect(toImmutableList())); + Arrays.stream(expected) + .map(DatastoreHelper::stripBillingEventId) + .collect(toImmutableList())); } /** Assert that there are no billing events. */ @@ -700,9 +706,10 @@ public class DatastoreHelper { assertThat(getBillingEvents()).isEmpty(); } - /** Helper to effectively erase the billing event ID to facilitate comparison. */ - public static final Function BILLING_EVENT_ID_STRIPPER = - billingEvent -> billingEvent.asBuilder().setId(1L).build(); + /** Strips the billing event ID (really, sets it to a constant value) to facilitate comparison. */ + public static BillingEvent stripBillingEventId(BillingEvent billingEvent) { + return billingEvent.asBuilder().setId(1L).build(); + } /** Assert that the actual poll message matches the expected one, ignoring IDs. */ public static void assertPollMessagesEqual(PollMessage actual, PollMessage expected) {