diff --git a/core/src/main/java/google/registry/model/ImmutableObject.java b/core/src/main/java/google/registry/model/ImmutableObject.java
index b17af27ea..31407dec7 100644
--- a/core/src/main/java/google/registry/model/ImmutableObject.java
+++ b/core/src/main/java/google/registry/model/ImmutableObject.java
@@ -61,7 +61,17 @@ public abstract class ImmutableObject implements Cloneable {
private boolean equalsImmutableObject(ImmutableObject other) {
return getClass().equals(other.getClass())
&& hashCode() == other.hashCode()
- && ModelUtils.getFieldValues(this).equals(ModelUtils.getFieldValues(other));
+ && getSignificantFields().equals(other.getSignificantFields());
+ }
+
+ /**
+ * Returns the map of significant fields (fields that we care about for purposes of comparison and
+ * display).
+ *
+ *
Isolated into a method so that derived classes can override it.
+ */
+ protected Map getSignificantFields() {
+ return ModelUtils.getFieldValues(this);
}
@Override
@@ -72,7 +82,7 @@ public abstract class ImmutableObject implements Cloneable {
@Override
public int hashCode() {
if (hashCode == null) {
- hashCode = Arrays.hashCode(ModelUtils.getFieldValues(this).values().toArray());
+ hashCode = Arrays.hashCode(getSignificantFields().values().toArray());
}
return hashCode;
}
@@ -111,7 +121,7 @@ public abstract class ImmutableObject implements Cloneable {
@Override
public String toString() {
NavigableMap sortedFields = new TreeMap<>();
- for (Entry entry : ModelUtils.getFieldValues(this).entrySet()) {
+ for (Entry entry : getSignificantFields().entrySet()) {
sortedFields.put(entry.getKey().getName(), entry.getValue());
}
return toStringHelper(sortedFields);
@@ -121,7 +131,7 @@ public abstract class ImmutableObject implements Cloneable {
public String toHydratedString() {
// We can't use ImmutableSortedMap because we need to allow null values.
NavigableMap sortedFields = new TreeMap<>();
- for (Entry entry : ModelUtils.getFieldValues(this).entrySet()) {
+ for (Entry entry : getSignificantFields().entrySet()) {
Field field = entry.getKey();
Object value = entry.getValue();
sortedFields.put(
@@ -161,7 +171,7 @@ public abstract class ImmutableObject implements Cloneable {
// LinkedHashMap to preserve field ordering and because ImmutableMap forbids null
// values.
Map result = new LinkedHashMap<>();
- for (Entry entry : ModelUtils.getFieldValues(o).entrySet()) {
+ for (Entry entry : ((ImmutableObject) o).getSignificantFields().entrySet()) {
Field field = entry.getKey();
if (!field.isAnnotationPresent(IgnoredInDiffableMap.class)) {
result.put(field.getName(), toMapRecursive(entry.getValue()));
diff --git a/core/src/main/java/google/registry/model/ModelUtils.java b/core/src/main/java/google/registry/model/ModelUtils.java
index a69ceb577..14e62c0dc 100644
--- a/core/src/main/java/google/registry/model/ModelUtils.java
+++ b/core/src/main/java/google/registry/model/ModelUtils.java
@@ -194,7 +194,7 @@ public class ModelUtils {
* returned map in its implementation of {@link ImmutableObject#toString} and {@link
* ImmutableObject#equals}, which work by comparing and printing these maps.
*/
- static Map getFieldValues(Object instance) {
+ public static Map getFieldValues(Object instance) {
// Don't make this ImmutableMap because field values can be null.
Map values = new LinkedHashMap<>();
for (Field field : getAllFields(instance.getClass()).values()) {
diff --git a/core/src/main/java/google/registry/model/domain/DomainContent.java b/core/src/main/java/google/registry/model/domain/DomainContent.java
index db381600a..6fbb2d626 100644
--- a/core/src/main/java/google/registry/model/domain/DomainContent.java
+++ b/core/src/main/java/google/registry/model/domain/DomainContent.java
@@ -303,14 +303,13 @@ public class DomainContent extends EppResource
allContacts.stream().map(DesignatedContact::reconstitute).collect(toImmutableSet());
setContactFields(allContacts, true);
- // We have to return the cloned object here because the original object's
- // hashcode is not correct due to the change to its domainRepoId. The cloned
- // object will have a null hashcode so that it can get a recalculated hashcode
- // when its hashCode() is invoked.
+ // We have to return the cloned object here because the original object's hashcode is not
+ // correct due to the change to its domainRepoId and history ids. The cloned object will have a
+ // null hashcode so that it can get a recalculated hashcode when its hashCode() is invoked.
// TODO(b/162739503): Remove this after fully migrating to Cloud SQL.
gracePeriods =
nullToEmptyImmutableCopy(gracePeriods).stream()
- .map(gracePeriod -> gracePeriod.cloneWithDomainRepoId(getRepoId()))
+ .map(gracePeriod -> gracePeriod.cloneAfterOfyLoad(getRepoId()))
.collect(toImmutableSet());
// Restore history record ids.
diff --git a/core/src/main/java/google/registry/model/domain/GracePeriod.java b/core/src/main/java/google/registry/model/domain/GracePeriod.java
index 9070aa157..dcc52e641 100644
--- a/core/src/main/java/google/registry/model/domain/GracePeriod.java
+++ b/core/src/main/java/google/registry/model/domain/GracePeriod.java
@@ -21,6 +21,7 @@ import com.googlecode.objectify.annotation.Embed;
import google.registry.model.billing.BillingEvent;
import google.registry.model.billing.BillingEvent.Recurring;
import google.registry.model.domain.rgp.GracePeriodStatus;
+import google.registry.model.ofy.ObjectifyService;
import google.registry.persistence.VKey;
import google.registry.schema.replay.DatastoreAndSqlEntity;
import javax.annotation.Nullable;
@@ -53,12 +54,15 @@ public class GracePeriod extends GracePeriodBase implements DatastoreAndSqlEntit
(billingEventRecurring != null) == GracePeriodStatus.AUTO_RENEW.equals(type),
"Recurring billing events must be present on (and only on) autorenew grace periods");
GracePeriod instance = new GracePeriod();
+ instance.id = ObjectifyService.allocateId();
instance.type = checkArgumentNotNull(type);
instance.domainRepoId = checkArgumentNotNull(domainRepoId);
instance.expirationTime = checkArgumentNotNull(expirationTime);
instance.clientId = checkArgumentNotNull(clientId);
instance.billingEventOneTime = billingEventOneTime;
+ instance.billingEventOneTimeHistoryId = DomainBase.getHistoryId(billingEventOneTime);
instance.billingEventRecurring = billingEventRecurring;
+ instance.billingEventRecurringHistoryId = DomainBase.getHistoryId(billingEventRecurring);
return instance;
}
@@ -108,14 +112,16 @@ public class GracePeriod extends GracePeriodBase implements DatastoreAndSqlEntit
}
/**
- * Returns a clone of this {@link GracePeriod} with {@link #domainRepoId} set to the given value.
+ * Returns a clone of this {@link GracePeriod} with {@link #domainRepoId} set to the given value
+ * and reconstructed history ids.
*
*
TODO(b/162739503): Remove this function after fully migrating to Cloud SQL.
*/
- public GracePeriod cloneWithDomainRepoId(String domainRepoId) {
+ public GracePeriod cloneAfterOfyLoad(String domainRepoId) {
GracePeriod clone = clone(this);
+ clone.id = ObjectifyService.allocateId();
clone.domainRepoId = checkArgumentNotNull(domainRepoId);
+ clone.restoreHistoryIds();
return clone;
}
-
}
diff --git a/core/src/main/java/google/registry/model/domain/GracePeriodBase.java b/core/src/main/java/google/registry/model/domain/GracePeriodBase.java
index cca2db53b..64f1ede7f 100644
--- a/core/src/main/java/google/registry/model/domain/GracePeriodBase.java
+++ b/core/src/main/java/google/registry/model/domain/GracePeriodBase.java
@@ -14,18 +14,21 @@
package google.registry.model.domain;
+import com.googlecode.objectify.Key;
import com.googlecode.objectify.annotation.Embed;
import com.googlecode.objectify.annotation.Ignore;
import google.registry.model.ImmutableObject;
+import google.registry.model.ModelUtils;
import google.registry.model.billing.BillingEvent;
import google.registry.model.billing.BillingEvent.OneTime;
import google.registry.model.domain.rgp.GracePeriodStatus;
import google.registry.persistence.VKey;
+import java.lang.reflect.Field;
+import java.util.LinkedHashMap;
+import java.util.Map;
import javax.persistence.Column;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
import javax.persistence.MappedSuperclass;
import org.joda.time.DateTime;
@@ -36,7 +39,6 @@ public class GracePeriodBase extends ImmutableObject {
/** Unique id required for hibernate representation. */
@javax.persistence.Id
- @GeneratedValue(strategy = GenerationType.IDENTITY)
@Ignore
Long id;
@@ -67,6 +69,10 @@ public class GracePeriodBase extends ImmutableObject {
@Column(name = "billing_event_id")
VKey billingEventOneTime = null;
+ @Ignore
+ @Column(name = "billing_event_history_id")
+ Long billingEventOneTimeHistoryId;
+
/**
* The recurring billing event corresponding to the action that triggered this grace period, if
* applicable - i.e. if the action was an autorenew - or null in all other cases.
@@ -75,6 +81,14 @@ public class GracePeriodBase extends ImmutableObject {
@Column(name = "billing_recurrence_id")
VKey billingEventRecurring = null;
+ @Ignore
+ @Column(name = "billing_recurrence_history_id")
+ Long billingEventRecurringHistoryId;
+
+ public long getId() {
+ return id;
+ }
+
public GracePeriodStatus getType() {
return type;
}
@@ -101,6 +115,7 @@ public class GracePeriodBase extends ImmutableObject {
* period is not AUTO_RENEW.
*/
public VKey getOneTimeBillingEvent() {
+ restoreOfyKeys();
return billingEventOneTime;
}
@@ -109,6 +124,63 @@ public class GracePeriodBase extends ImmutableObject {
* period is AUTO_RENEW.
*/
public VKey getRecurringBillingEvent() {
+ restoreOfyKeys();
return billingEventRecurring;
}
+
+ /**
+ * Restores history ids for composite VKeys after a load from datastore.
+ *
+ *
For use by DomainContent.load() ONLY.
+ */
+ protected void restoreHistoryIds() {
+ billingEventOneTimeHistoryId = DomainBase.getHistoryId(billingEventOneTime);
+ billingEventRecurringHistoryId = DomainBase.getHistoryId(billingEventRecurring);
+ }
+
+ /**
+ * Override {@link ImmutableObject#getSignificantFields()} to exclude "id", which breaks equality
+ * testing in the unit tests.
+ */
+ @Override
+ protected Map getSignificantFields() {
+ restoreOfyKeys();
+ // Can't use streams or ImmutableMap because we can have null values.
+ Map result = new LinkedHashMap();
+ for (Map.Entry entry : ModelUtils.getFieldValues(this).entrySet()) {
+ if (!entry.getKey().getName().equals("id")) {
+ result.put(entry.getKey(), entry.getValue());
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Restores Ofy keys in the billing events.
+ *
+ *
This must be called by all methods that access the one time or recurring billing event keys.
+ * When the billing event keys are loaded from SQL, they are loaded as asymmetric keys because the
+ * database columns that we load them from do not contain all of the information necessary to
+ * reconsitute the Ofy side of the key. In other cases, we restore the Ofy key during the
+ * hibernate {@link javax.persistence.PostLoad} method from the other fields of the object, but we
+ * have been unable to make this work with hibernate's internal persistence model in this case
+ * because the {@link GracePeriod}'s hash code is evaluated prior to these calls, and would be
+ * invalidated by changing the fields.
+ */
+ private final synchronized void restoreOfyKeys() {
+ if (billingEventOneTime != null && !billingEventOneTime.maybeGetOfyKey().isPresent()) {
+ billingEventOneTime =
+ DomainBase.restoreOfyFrom(
+ Key.create(DomainBase.class, domainRepoId),
+ billingEventOneTime,
+ billingEventOneTimeHistoryId);
+ }
+ if (billingEventRecurring != null && !billingEventRecurring.maybeGetOfyKey().isPresent()) {
+ billingEventRecurring =
+ DomainBase.restoreOfyFrom(
+ Key.create(DomainBase.class, domainRepoId),
+ billingEventRecurring,
+ billingEventRecurringHistoryId);
+ }
+ }
}
diff --git a/core/src/test/java/google/registry/flows/EppLifecycleDomainTest.java b/core/src/test/java/google/registry/flows/EppLifecycleDomainTest.java
index 5641cdfdf..756833072 100644
--- a/core/src/test/java/google/registry/flows/EppLifecycleDomainTest.java
+++ b/core/src/test/java/google/registry/flows/EppLifecycleDomainTest.java
@@ -805,30 +805,35 @@ class EppLifecycleDomainTest extends EppTestCase {
// As the losing registrar, read the request poll message, and then ack it.
assertThatLoginSucceeds("NewRegistrar", "foo-BAR2");
+ String messageId = "1-C-EXAMPLE-20-26-2001";
assertThatCommand("poll.xml")
.atTime("2001-01-01T00:01:00Z")
- .hasResponse("poll_response_domain_transfer_request.xml");
- assertThatCommand("poll_ack.xml", ImmutableMap.of("ID", "1-C-EXAMPLE-17-23-2001"))
+ .hasResponse("poll_response_domain_transfer_request.xml", ImmutableMap.of("ID", messageId));
+ assertThatCommand("poll_ack.xml", ImmutableMap.of("ID", messageId))
.atTime("2001-01-01T00:01:00Z")
.hasResponse("poll_ack_response_empty.xml");
// Five days in the future, expect a server approval poll message to the loser, and ack it.
+ messageId = "1-C-EXAMPLE-20-25-2001";
assertThatCommand("poll.xml")
.atTime("2001-01-06T00:01:00Z")
- .hasResponse("poll_response_domain_transfer_server_approve_loser.xml");
- assertThatCommand("poll_ack.xml", ImmutableMap.of("ID", "1-C-EXAMPLE-17-22-2001"))
+ .hasResponse(
+ "poll_response_domain_transfer_server_approve_loser.xml",
+ ImmutableMap.of("ID", messageId));
+ assertThatCommand("poll_ack.xml", ImmutableMap.of("ID", messageId))
.atTime("2001-01-06T00:01:00Z")
.hasResponse("poll_ack_response_empty.xml");
assertThatLogoutSucceeds();
// Also expect a server approval poll message to the winner, with the transfer request trid.
+ messageId = "1-C-EXAMPLE-20-24-2001";
assertThatLoginSucceeds("TheRegistrar", "password2");
assertThatCommand("poll.xml")
.atTime("2001-01-06T00:02:00Z")
.hasResponse(
"poll_response_domain_transfer_server_approve_winner.xml",
- ImmutableMap.of("SERVER_TRID", transferRequestTrid));
- assertThatCommand("poll_ack.xml", ImmutableMap.of("ID", "1-C-EXAMPLE-17-21-2001"))
+ ImmutableMap.of("SERVER_TRID", transferRequestTrid, "ID", messageId));
+ assertThatCommand("poll_ack.xml", ImmutableMap.of("ID", messageId))
.atTime("2001-01-06T00:02:00Z")
.hasResponse("poll_ack_response_empty.xml");
assertThatLogoutSucceeds();
diff --git a/core/src/test/java/google/registry/model/domain/DomainBaseSqlTest.java b/core/src/test/java/google/registry/model/domain/DomainBaseSqlTest.java
index 2eaa3248c..0ed048390 100644
--- a/core/src/test/java/google/registry/model/domain/DomainBaseSqlTest.java
+++ b/core/src/test/java/google/registry/model/domain/DomainBaseSqlTest.java
@@ -78,6 +78,7 @@ public class DomainBaseSqlTest {
private HostResource host;
private ContactResource contact;
private ContactResource contact2;
+ private ImmutableSet gracePeriods;
@BeforeEach
void setUp() {
@@ -506,6 +507,20 @@ public class DomainBaseSqlTest {
.setServerApproveAutorenewEvent(billEvent.createVKey())
.setServerApproveAutorenewPollMessage(autorenewPollMessage.createVKey())
.build();
+ gracePeriods =
+ ImmutableSet.of(
+ GracePeriod.create(
+ GracePeriodStatus.ADD,
+ "4-COM",
+ END_OF_TIME,
+ "registrar1",
+ oneTimeBillingEvent.createVKey()),
+ GracePeriod.createForRecurring(
+ GracePeriodStatus.AUTO_RENEW,
+ "4-COM",
+ END_OF_TIME,
+ "registrar1",
+ billEvent.createVKey()));
jpaTm().insert(contact);
jpaTm().insert(contact2);
@@ -517,6 +532,7 @@ public class DomainBaseSqlTest {
.setAutorenewPollMessage(autorenewPollMessage.createVKey())
.setDeletePollMessage(deletePollMessage.createVKey())
.setTransferData(transferData)
+ .setGracePeriods(gracePeriods)
.build();
historyEntry = historyEntry.asBuilder().setDomainContent(domain).build();
jpaTm().insert(historyEntry);
@@ -553,6 +569,7 @@ public class DomainBaseSqlTest {
.isEqualTo(originalTransferData.getServerApproveAutorenewEvent());
assertThat(persistedTransferData.getServerApproveAutorenewPollMessage())
.isEqualTo(originalTransferData.getServerApproveAutorenewPollMessage());
+ assertThat(persisted.getGracePeriods()).isEqualTo(gracePeriods);
}
@Test
@@ -624,6 +641,21 @@ public class DomainBaseSqlTest {
createLegacyVKey(
PollMessage.Autorenew.class, autorenewPollMessage.getId()))
.build();
+ gracePeriods =
+ ImmutableSet.of(
+ GracePeriod.create(
+ GracePeriodStatus.ADD,
+ "4-COM",
+ END_OF_TIME,
+ "registrar1",
+ createLegacyVKey(
+ BillingEvent.OneTime.class, oneTimeBillingEvent.getId())),
+ GracePeriod.createForRecurring(
+ GracePeriodStatus.AUTO_RENEW,
+ "4-COM",
+ END_OF_TIME,
+ "registrar1",
+ createLegacyVKey(BillingEvent.Recurring.class, billEvent.getId())));
jpaTm().insert(contact);
jpaTm().insert(contact2);
@@ -639,6 +671,7 @@ public class DomainBaseSqlTest {
.setDeletePollMessage(
createLegacyVKey(PollMessage.OneTime.class, deletePollMessage.getId()))
.setTransferData(transferData)
+ .setGracePeriods(gracePeriods)
.build();
historyEntry = historyEntry.asBuilder().setDomainContent(domain).build();
jpaTm().insert(historyEntry);
@@ -675,6 +708,7 @@ public class DomainBaseSqlTest {
.isEqualTo(originalTransferData.getServerApproveAutorenewEvent());
assertThat(persistedTransferData.getServerApproveAutorenewPollMessage())
.isEqualTo(originalTransferData.getServerApproveAutorenewPollMessage());
+ assertThat(domain.getGracePeriods()).isEqualTo(gracePeriods);
}
private VKey createLegacyVKey(Class clazz, long id) {
diff --git a/core/src/test/java/google/registry/model/domain/DomainBaseTest.java b/core/src/test/java/google/registry/model/domain/DomainBaseTest.java
index 03b473218..f93b720fc 100644
--- a/core/src/test/java/google/registry/model/domain/DomainBaseTest.java
+++ b/core/src/test/java/google/registry/model/domain/DomainBaseTest.java
@@ -38,6 +38,7 @@ import com.google.common.collect.Ordering;
import com.google.common.collect.Streams;
import com.googlecode.objectify.Key;
import google.registry.model.EntityTestCase;
+import google.registry.model.ImmutableObject;
import google.registry.model.billing.BillingEvent;
import google.registry.model.billing.BillingEvent.Reason;
import google.registry.model.contact.ContactResource;
@@ -830,4 +831,63 @@ public class DomainBaseTest extends EntityTestCase {
assertThat(getOnlyElement(clone.getGracePeriods()).getType())
.isEqualTo(GracePeriodStatus.TRANSFER);
}
+
+ @Test
+ void testHistoryIdRestoration() {
+ // Verify that history ids for billing events are restored during load from datastore. History
+ // ids are not used by business code or persisted in datastore, but only to reconstruct
+ // objectify keys when loading from SQL.
+ DateTime now = fakeClock.nowUtc();
+ domain =
+ persistResource(
+ domain
+ .asBuilder()
+ .setRegistrationExpirationTime(now.plusYears(1))
+ .setGracePeriods(
+ ImmutableSet.of(
+ GracePeriod.createForRecurring(
+ GracePeriodStatus.AUTO_RENEW,
+ domain.getRepoId(),
+ now.plusDays(1),
+ "NewRegistrar",
+ recurringBillKey),
+ GracePeriod.create(
+ GracePeriodStatus.RENEW,
+ domain.getRepoId(),
+ now.plusDays(1),
+ "NewRegistrar",
+ oneTimeBillKey)))
+ .build());
+ ImmutableSet historyIds =
+ domain.getGracePeriods().stream()
+ .map(
+ gp ->
+ new BillEventInfo(
+ gp.getRecurringBillingEvent(), gp.billingEventRecurringHistoryId,
+ gp.getOneTimeBillingEvent(), gp.billingEventOneTimeHistoryId))
+ .collect(toImmutableSet());
+ assertThat(historyIds)
+ .isEqualTo(
+ ImmutableSet.of(
+ new BillEventInfo(null, null, oneTimeBillKey, historyEntryKey.getId()),
+ new BillEventInfo(recurringBillKey, historyEntryKey.getId(), null, null)));
+ }
+
+ static class BillEventInfo extends ImmutableObject {
+ VKey billingEventRecurring;
+ Long billingEventRecurringHistoryId;
+ VKey billingEventOneTime;
+ Long billingEventOneTimeHistoryId;
+
+ BillEventInfo(
+ VKey billingEventRecurring,
+ Long billingEventRecurringHistoryId,
+ VKey billingEventOneTime,
+ Long billingEventOneTimeHistoryId) {
+ this.billingEventRecurring = billingEventRecurring;
+ this.billingEventRecurringHistoryId = billingEventRecurringHistoryId;
+ this.billingEventOneTime = billingEventOneTime;
+ this.billingEventOneTimeHistoryId = billingEventOneTimeHistoryId;
+ }
+ }
}
diff --git a/core/src/test/java/google/registry/model/domain/GracePeriodTest.java b/core/src/test/java/google/registry/model/domain/GracePeriodTest.java
index 3ae94f976..13dffc2be 100644
--- a/core/src/test/java/google/registry/model/domain/GracePeriodTest.java
+++ b/core/src/test/java/google/registry/model/domain/GracePeriodTest.java
@@ -44,6 +44,7 @@ public class GracePeriodTest {
private final DateTime now = DateTime.now(UTC);
private BillingEvent.OneTime onetime;
+ private VKey recurringKey;
@BeforeEach
void before() {
@@ -59,6 +60,14 @@ public class GracePeriodTest {
.setPeriodYears(1)
.setTargetId("foo.google")
.build();
+ recurringKey =
+ VKey.create(
+ Recurring.class,
+ 12345,
+ Key.create(
+ Key.create(Key.create(DomainBase.class, "1-TEST"), HistoryEntry.class, 343L),
+ Recurring.class,
+ 12345));
}
@Test
@@ -71,6 +80,24 @@ public class GracePeriodTest {
assertThat(gracePeriod.getClientId()).isEqualTo("TheRegistrar");
assertThat(gracePeriod.getExpirationTime()).isEqualTo(now.plusDays(1));
assertThat(gracePeriod.hasBillingEvent()).isTrue();
+ assertThat(gracePeriod.billingEventOneTimeHistoryId).isEqualTo(12345L);
+ assertThat(gracePeriod.billingEventRecurringHistoryId).isNull();
+ }
+
+ @Test
+ void testSuccess_forRecurringEvent() {
+ GracePeriod gracePeriod =
+ GracePeriod.createForRecurring(
+ GracePeriodStatus.AUTO_RENEW, "1-TEST", now.plusDays(1), "TheRegistrar", recurringKey);
+ assertThat(gracePeriod.getType()).isEqualTo(GracePeriodStatus.AUTO_RENEW);
+ assertThat(gracePeriod.getDomainRepoId()).isEqualTo("1-TEST");
+ assertThat(gracePeriod.getOneTimeBillingEvent()).isNull();
+ assertThat(gracePeriod.getRecurringBillingEvent()).isEqualTo(recurringKey);
+ assertThat(gracePeriod.getClientId()).isEqualTo("TheRegistrar");
+ assertThat(gracePeriod.getExpirationTime()).isEqualTo(now.plusDays(1));
+ assertThat(gracePeriod.hasBillingEvent()).isTrue();
+ assertThat(gracePeriod.billingEventOneTimeHistoryId).isNull();
+ assertThat(gracePeriod.billingEventRecurringHistoryId).isEqualTo(343L);
}
@Test
@@ -98,11 +125,6 @@ public class GracePeriodTest {
@Test
void testFailure_createForRecurring_notAutoRenew() {
- Key recurringKey =
- Key.create(
- Key.create(Key.create(DomainBase.class, "1-TEST"), HistoryEntry.class, 343L),
- Recurring.class,
- 12345);
IllegalArgumentException thrown =
assertThrows(
IllegalArgumentException.class,
@@ -112,7 +134,7 @@ public class GracePeriodTest {
"1-TEST",
now.plusDays(1),
"TheRegistrar",
- VKey.create(Recurring.class, 12345, recurringKey)));
+ recurringKey));
assertThat(thrown).hasMessageThat().contains("autorenew");
}
}
diff --git a/core/src/test/java/google/registry/tools/EppLifecycleToolsTest.java b/core/src/test/java/google/registry/tools/EppLifecycleToolsTest.java
index 3fa7b0cb4..ddfc50d2d 100644
--- a/core/src/test/java/google/registry/tools/EppLifecycleToolsTest.java
+++ b/core/src/test/java/google/registry/tools/EppLifecycleToolsTest.java
@@ -108,7 +108,7 @@ class EppLifecycleToolsTest extends EppTestCase {
.atTime("2001-06-08T00:00:00Z")
.hasResponse("poll_response_unrenew.xml");
- assertThatCommand("poll_ack.xml", ImmutableMap.of("ID", "1-8-TLD-17-18-2001"))
+ assertThatCommand("poll_ack.xml", ImmutableMap.of("ID", "1-8-TLD-23-24-2001"))
.atTime("2001-06-08T00:00:01Z")
.hasResponse("poll_ack_response_empty.xml");
@@ -129,7 +129,7 @@ class EppLifecycleToolsTest extends EppTestCase {
.hasResponse(
"poll_response_autorenew.xml",
ImmutableMap.of(
- "ID", "1-8-TLD-17-20-2003",
+ "ID", "1-8-TLD-23-26-2003",
"QDATE", "2003-06-01T00:02:00Z",
"DOMAIN", "example.tld",
"EXDATE", "2004-06-01T00:02:00Z"));
diff --git a/core/src/test/resources/google/registry/flows/poll_response_domain_transfer_request.xml b/core/src/test/resources/google/registry/flows/poll_response_domain_transfer_request.xml
index 0f19e13b6..35ae1cf8c 100644
--- a/core/src/test/resources/google/registry/flows/poll_response_domain_transfer_request.xml
+++ b/core/src/test/resources/google/registry/flows/poll_response_domain_transfer_request.xml
@@ -3,7 +3,7 @@
Command completed successfully; ack to dequeue
-
+ 2001-01-01T00:00:00ZTransfer requested.
diff --git a/core/src/test/resources/google/registry/flows/poll_response_domain_transfer_server_approve_loser.xml b/core/src/test/resources/google/registry/flows/poll_response_domain_transfer_server_approve_loser.xml
index a12a093f3..f85fbc526 100644
--- a/core/src/test/resources/google/registry/flows/poll_response_domain_transfer_server_approve_loser.xml
+++ b/core/src/test/resources/google/registry/flows/poll_response_domain_transfer_server_approve_loser.xml
@@ -3,7 +3,7 @@
Command completed successfully; ack to dequeue
-
+ 2001-01-06T00:00:00ZTransfer approved.
diff --git a/core/src/test/resources/google/registry/flows/poll_response_domain_transfer_server_approve_winner.xml b/core/src/test/resources/google/registry/flows/poll_response_domain_transfer_server_approve_winner.xml
index bf4411bff..d9a089d88 100644
--- a/core/src/test/resources/google/registry/flows/poll_response_domain_transfer_server_approve_winner.xml
+++ b/core/src/test/resources/google/registry/flows/poll_response_domain_transfer_server_approve_winner.xml
@@ -4,7 +4,7 @@
Command completed successfully; ack to dequeue
-
+ 2001-01-06T00:00:00ZTransfer approved.
diff --git a/core/src/test/resources/google/registry/flows/poll_response_unrenew.xml b/core/src/test/resources/google/registry/flows/poll_response_unrenew.xml
index 704fcc389..112faf222 100644
--- a/core/src/test/resources/google/registry/flows/poll_response_unrenew.xml
+++ b/core/src/test/resources/google/registry/flows/poll_response_unrenew.xml
@@ -3,7 +3,7 @@
Command completed successfully; ack to dequeue
-
+ 2001-06-07T00:00:00ZDomain example.tld was unrenewed by 3 years; now expires at 2003-06-01T00:02:00.000Z.
diff --git a/db/src/main/resources/sql/er_diagram/brief_er_diagram.html b/db/src/main/resources/sql/er_diagram/brief_er_diagram.html
index d26bf52e5..2e4b1fe7f 100644
--- a/db/src/main/resources/sql/er_diagram/brief_er_diagram.html
+++ b/db/src/main/resources/sql/er_diagram/brief_er_diagram.html
@@ -261,59 +261,59 @@ td.section {