Convert more classes to using SQL / TM (#1067)

* Convert more classes to using SQL / TM

Nothing much particularly crazy here
This commit is contained in:
gbrodman 2021-04-14 16:45:06 -04:00 committed by GitHub
parent eff79e9c99
commit 87d511d5e3
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 137 additions and 99 deletions

View file

@ -17,6 +17,7 @@ package google.registry.model;
import static com.google.common.collect.Iterables.transform; import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Maps.transformValues; import static com.google.common.collect.Maps.transformValues;
import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.FIELD;
import static java.lang.annotation.RetentionPolicy.RUNTIME; import static java.lang.annotation.RetentionPolicy.RUNTIME;
import static java.util.stream.Collectors.toCollection; import static java.util.stream.Collectors.toCollection;
@ -187,7 +188,10 @@ public abstract class ImmutableObject implements Cloneable {
/** Helper function to recursively hydrate an ImmutableObject. */ /** Helper function to recursively hydrate an ImmutableObject. */
private static Object hydrate(Object value) { private static Object hydrate(Object value) {
if (value instanceof Key) { if (value instanceof Key) {
return hydrate(ofy().load().key((Key<?>) value).now()); if (tm().isOfy()) {
return hydrate(ofy().load().key((Key<?>) value).now());
}
return value;
} else if (value instanceof Map) { } else if (value instanceof Map) {
return transformValues((Map<?, ?>) value, ImmutableObject::hydrate); return transformValues((Map<?, ?>) value, ImmutableObject::hydrate);
} else if (value instanceof Collection) { } else if (value instanceof Collection) {

View file

@ -17,7 +17,6 @@ package google.registry.model;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Preconditions.checkState;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm; import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
@ -107,14 +106,14 @@ public final class ResourceTransferUtils {
/** Update the relevant {@link ForeignKeyIndex} to cache the new deletion time. */ /** Update the relevant {@link ForeignKeyIndex} to cache the new deletion time. */
public static <R extends EppResource> void updateForeignKeyIndexDeletionTime(R resource) { public static <R extends EppResource> void updateForeignKeyIndexDeletionTime(R resource) {
if (resource instanceof ForeignKeyedEppResource) { if (resource instanceof ForeignKeyedEppResource) {
ofy().save().entity(ForeignKeyIndex.create(resource, resource.getDeletionTime())); tm().insert(ForeignKeyIndex.create(resource, resource.getDeletionTime()));
} }
} }
/** If there is a transfer out, delete the server-approve entities and enqueue a poll message. */ /** If there is a transfer out, delete the server-approve entities and enqueue a poll message. */
public static <R extends EppResource & ResourceWithTransferData> public static <R extends EppResource & ResourceWithTransferData>
void handlePendingTransferOnDelete( void handlePendingTransferOnDelete(
R resource, R newResource, DateTime now, HistoryEntry historyEntry) { R resource, R newResource, DateTime now, HistoryEntry historyEntry) {
if (resource.getStatusValues().contains(StatusValue.PENDING_TRANSFER)) { if (resource.getStatusValues().contains(StatusValue.PENDING_TRANSFER)) {
TransferData oldTransferData = resource.getTransferData(); TransferData oldTransferData = resource.getTransferData();
tm().delete(oldTransferData.getServerApproveEntities()); tm().delete(oldTransferData.getServerApproveEntities());

View file

@ -18,7 +18,8 @@ import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Preconditions.checkState;
import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.persistence.transaction.TransactionManagerUtil.transactIfJpaTm;
import static google.registry.util.CollectionUtils.forceEmptyToNull; import static google.registry.util.CollectionUtils.forceEmptyToNull;
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy; import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
import static google.registry.util.DateTimeUtils.END_OF_TIME; import static google.registry.util.DateTimeUtils.END_OF_TIME;
@ -772,10 +773,10 @@ public abstract class BillingEvent extends ImmutableObject
Modification instance = getInstance(); Modification instance = getInstance();
checkNotNull(instance.reason); checkNotNull(instance.reason);
checkNotNull(instance.eventRef); checkNotNull(instance.eventRef);
BillingEvent.OneTime billingEvent = ofy().load().key(instance.eventRef).now(); BillingEvent.OneTime billingEvent =
checkArgument(Objects.equals( transactIfJpaTm(() -> tm().loadByKey(VKey.from(instance.eventRef)));
instance.cost.getCurrencyUnit(), checkArgument(
billingEvent.cost.getCurrencyUnit()), Objects.equals(instance.cost.getCurrencyUnit(), billingEvent.cost.getCurrencyUnit()),
"Referenced billing event is in a different currency"); "Referenced billing event is in a different currency");
return super.build(); return super.build();
} }

View file

@ -20,8 +20,8 @@ import static google.registry.flows.domain.DomainFlowUtils.newAutorenewBillingEv
import static google.registry.flows.domain.DomainFlowUtils.newAutorenewPollMessage; import static google.registry.flows.domain.DomainFlowUtils.newAutorenewPollMessage;
import static google.registry.flows.domain.DomainFlowUtils.updateAutorenewRecurrenceEndTime; import static google.registry.flows.domain.DomainFlowUtils.updateAutorenewRecurrenceEndTime;
import static google.registry.model.EppResourceUtils.loadByForeignKey; import static google.registry.model.EppResourceUtils.loadByForeignKey;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm; import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.util.DateTimeUtils.START_OF_TIME;
import static google.registry.util.DateTimeUtils.isBeforeOrAt; import static google.registry.util.DateTimeUtils.isBeforeOrAt;
import static google.registry.util.DateTimeUtils.leapSafeSubtractYears; import static google.registry.util.DateTimeUtils.leapSafeSubtractYears;
@ -33,12 +33,12 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import google.registry.model.billing.BillingEvent; import google.registry.model.billing.BillingEvent;
import google.registry.model.domain.DomainBase; import google.registry.model.domain.DomainBase;
import google.registry.model.domain.DomainHistory;
import google.registry.model.domain.Period; import google.registry.model.domain.Period;
import google.registry.model.domain.Period.Unit; import google.registry.model.domain.Period.Unit;
import google.registry.model.eppcommon.StatusValue; import google.registry.model.eppcommon.StatusValue;
import google.registry.model.index.ForeignKeyIndex.ForeignKeyDomainIndex; import google.registry.model.index.ForeignKeyIndex;
import google.registry.model.poll.PollMessage; import google.registry.model.poll.PollMessage;
import google.registry.model.reporting.HistoryEntry;
import google.registry.model.reporting.HistoryEntry.Type; import google.registry.model.reporting.HistoryEntry.Type;
import google.registry.util.Clock; import google.registry.util.Clock;
import google.registry.util.NonFinalForTesting; import google.registry.util.NonFinalForTesting;
@ -87,7 +87,7 @@ class UnrenewDomainCommand extends ConfirmingCommand implements CommandWithRemot
new ImmutableMap.Builder<>(); new ImmutableMap.Builder<>();
for (String domainName : mainParameters) { for (String domainName : mainParameters) {
if (ofy().load().type(ForeignKeyDomainIndex.class).id(domainName).now() == null) { if (ForeignKeyIndex.load(DomainBase.class, domainName, START_OF_TIME) == null) {
domainsNonexistentBuilder.add(domainName); domainsNonexistentBuilder.add(domainName);
continue; continue;
} }
@ -183,8 +183,8 @@ class UnrenewDomainCommand extends ConfirmingCommand implements CommandWithRemot
DateTime newExpirationTime = DateTime newExpirationTime =
leapSafeSubtractYears(domain.getRegistrationExpirationTime(), period); leapSafeSubtractYears(domain.getRegistrationExpirationTime(), period);
HistoryEntry historyEntry = DomainHistory domainHistory =
new HistoryEntry.Builder() new DomainHistory.Builder()
.setParent(domain) .setParent(domain)
.setModificationTime(now) .setModificationTime(now)
.setBySuperuser(true) .setBySuperuser(true)
@ -201,19 +201,19 @@ class UnrenewDomainCommand extends ConfirmingCommand implements CommandWithRemot
String.format( String.format(
"Domain %s was unrenewed by %d years; now expires at %s.", "Domain %s was unrenewed by %d years; now expires at %s.",
domainName, period, newExpirationTime)) domainName, period, newExpirationTime))
.setParent(historyEntry) .setParent(domainHistory)
.setEventTime(now) .setEventTime(now)
.build(); .build();
// Create a new autorenew billing event and poll message starting at the new expiration time. // Create a new autorenew billing event and poll message starting at the new expiration time.
BillingEvent.Recurring newAutorenewEvent = BillingEvent.Recurring newAutorenewEvent =
newAutorenewBillingEvent(domain) newAutorenewBillingEvent(domain)
.setEventTime(newExpirationTime) .setEventTime(newExpirationTime)
.setParent(historyEntry) .setParent(domainHistory)
.build(); .build();
PollMessage.Autorenew newAutorenewPollMessage = PollMessage.Autorenew newAutorenewPollMessage =
newAutorenewPollMessage(domain) newAutorenewPollMessage(domain)
.setEventTime(newExpirationTime) .setEventTime(newExpirationTime)
.setParent(historyEntry) .setParent(domainHistory)
.build(); .build();
// End the old autorenew billing event and poll message now. // End the old autorenew billing event and poll message now.
updateAutorenewRecurrenceEndTime(domain, now); updateAutorenewRecurrenceEndTime(domain, now);
@ -229,11 +229,9 @@ class UnrenewDomainCommand extends ConfirmingCommand implements CommandWithRemot
// In order to do it'll need to write out a new HistoryEntry (likely of type SYNTHETIC), a new // In order to do it'll need to write out a new HistoryEntry (likely of type SYNTHETIC), a new
// autorenew billing event and poll message, and a new one time poll message at the present time // autorenew billing event and poll message, and a new one time poll message at the present time
// informing the registrar of this out-of-band change. // informing the registrar of this out-of-band change.
ofy() tm().putAll(
.save()
.entities(
newDomain, newDomain,
historyEntry, domainHistory,
oneTimePollMessage, oneTimePollMessage,
newAutorenewEvent, newAutorenewEvent,
newAutorenewPollMessage); newAutorenewPollMessage);

View file

@ -19,6 +19,7 @@ import static com.google.common.collect.ImmutableListMultimap.flatteningToImmuta
import static com.google.common.collect.ImmutableSet.toImmutableSet; import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm; import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import com.beust.jcommander.Parameter; import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters; import com.beust.jcommander.Parameters;
@ -135,12 +136,7 @@ public class BackfillSpec11ThreatMatchesCommand extends ConfirmingCommand
flatteningToImmutableListMultimap( flatteningToImmutableListMultimap(
Function.identity(), Function.identity(),
(domainName) -> { (domainName) -> {
List<DomainBase> domains = List<DomainBase> domains = loadDomainsForFqdn(domainName);
ofy()
.load()
.type(DomainBase.class)
.filter("fullyQualifiedDomainName", domainName)
.list();
domains.sort(Comparator.comparing(DomainBase::getCreationTime).reversed()); domains.sort(Comparator.comparing(DomainBase::getCreationTime).reversed());
checkState( checkState(
!domains.isEmpty(), !domains.isEmpty(),
@ -150,6 +146,25 @@ public class BackfillSpec11ThreatMatchesCommand extends ConfirmingCommand
})); }));
} }
/** Loads in all {@link DomainBase} objects for a given FQDN. */
private List<DomainBase> loadDomainsForFqdn(String fullyQualifiedDomainName) {
if (tm().isOfy()) {
return ofy()
.load()
.type(DomainBase.class)
.filter("fullyQualifiedDomainName", fullyQualifiedDomainName)
.list();
} else {
return jpaTm()
.transact(
() ->
jpaTm()
.query("FROM Domain WHERE fullyQualifiedDomainName = :fqdn", DomainBase.class)
.setParameter("fqdn", fullyQualifiedDomainName)
.getResultList());
}
}
/** Converts the previous {@link ThreatMatch} object to {@link Spec11ThreatMatch}. */ /** Converts the previous {@link ThreatMatch} object to {@link Spec11ThreatMatch}. */
private Spec11ThreatMatch threatMatchToCloudSqlObject( private Spec11ThreatMatch threatMatchToCloudSqlObject(
ThreatMatch threatMatch, ThreatMatch threatMatch,

View file

@ -15,8 +15,6 @@
package google.registry.tools.javascrap; package google.registry.tools.javascrap;
import static com.google.common.base.MoreObjects.firstNonNull; import static com.google.common.base.MoreObjects.firstNonNull;
import static google.registry.model.common.EntityGroupRoot.getCrossTldKey;
import static google.registry.model.ofy.ObjectifyService.ofy;
import com.beust.jcommander.Parameters; import com.beust.jcommander.Parameters;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
@ -38,7 +36,7 @@ public class PopulateNullRegistrarFieldsCommand extends MutatingCommand {
@Override @Override
protected void init() { protected void init() {
for (Registrar registrar : ofy().load().type(Registrar.class).ancestor(getCrossTldKey())) { for (Registrar registrar : Registrar.loadAll()) {
Registrar.Builder changeBuilder = registrar.asBuilder(); Registrar.Builder changeBuilder = registrar.asBuilder();
changeBuilder.setRegistrarName( changeBuilder.setRegistrarName(
firstNonNull(registrar.getRegistrarName(), registrar.getClientId())); firstNonNull(registrar.getRegistrarName(), registrar.getClientId()));

View file

@ -14,13 +14,15 @@
package google.registry.tools.javascrap; package google.registry.tools.javascrap;
import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.persistence.transaction.TransactionManagerUtil.transactIfJpaTm;
import static java.nio.charset.StandardCharsets.UTF_8; import static java.nio.charset.StandardCharsets.UTF_8;
import com.beust.jcommander.Parameter; import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters; import com.beust.jcommander.Parameters;
import com.google.template.soy.data.SoyMapData; import com.google.template.soy.data.SoyMapData;
import google.registry.model.host.HostResource; import google.registry.model.host.HostResource;
import google.registry.persistence.VKey;
import google.registry.tools.MutatingEppToolCommand; import google.registry.tools.MutatingEppToolCommand;
import google.registry.tools.params.PathParameter; import google.registry.tools.params.PathParameter;
import google.registry.tools.soy.RemoveIpAddressSoyInfo; import google.registry.tools.soy.RemoveIpAddressSoyInfo;
@ -30,6 +32,7 @@ import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Optional;
/** /**
* Command to remove external IP Addresses from HostResources identified by text file listing * Command to remove external IP Addresses from HostResources identified by text file listing
@ -56,14 +59,15 @@ public class RemoveIpAddressCommand extends MutatingEppToolCommand {
for (String roid : roids) { for (String roid : roids) {
// Look up the HostResource from its roid. // Look up the HostResource from its roid.
HostResource host = ofy().load().type(HostResource.class).id(roid).now(); Optional<HostResource> host =
if (host == null) { transactIfJpaTm(() -> tm().loadByKeyIfPresent(VKey.create(HostResource.class, roid)));
if (!host.isPresent()) {
System.err.printf("Record for %s not found.\n", roid); System.err.printf("Record for %s not found.\n", roid);
continue; continue;
} }
ArrayList<SoyMapData> ipAddresses = new ArrayList<>(); ArrayList<SoyMapData> ipAddresses = new ArrayList<>();
for (InetAddress address : host.getInetAddresses()) { for (InetAddress address : host.get().getInetAddresses()) {
SoyMapData dataMap = new SoyMapData( SoyMapData dataMap = new SoyMapData(
"address", address.getHostAddress(), "address", address.getHostAddress(),
"version", address instanceof Inet6Address ? "v6" : "v4"); "version", address instanceof Inet6Address ? "v6" : "v4");
@ -76,7 +80,7 @@ public class RemoveIpAddressCommand extends MutatingEppToolCommand {
addSoyRecord( addSoyRecord(
registrarId, registrarId,
new SoyMapData( new SoyMapData(
"name", host.getHostName(), "name", host.get().getHostName(),
"ipAddresses", ipAddresses, "ipAddresses", ipAddresses,
"requestedByRegistrar", registrarId)); "requestedByRegistrar", registrarId));
} }

View file

@ -34,6 +34,8 @@ import google.registry.model.registrar.RegistrarContact;
import google.registry.model.registry.Registry; import google.registry.model.registry.Registry;
import google.registry.model.registry.Registry.TldState; import google.registry.model.registry.Registry.TldState;
import google.registry.testing.AppEngineExtension; import google.registry.testing.AppEngineExtension;
import google.registry.testing.DualDatabaseTest;
import google.registry.testing.TestOfyAndSql;
import google.registry.util.CidrAddressBlock; import google.registry.util.CidrAddressBlock;
import google.registry.util.SystemClock; import google.registry.util.SystemClock;
import org.joda.money.Money; import org.joda.money.Money;
@ -41,16 +43,16 @@ import org.joda.time.DateTime;
import org.joda.time.DateTimeZone; import org.joda.time.DateTimeZone;
import org.joda.time.Duration; import org.joda.time.Duration;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.api.extension.RegisterExtension;
@DualDatabaseTest
public final class OteAccountBuilderTest { public final class OteAccountBuilderTest {
@RegisterExtension @RegisterExtension
public final AppEngineExtension appEngine = public final AppEngineExtension appEngine =
AppEngineExtension.builder().withDatastoreAndCloudSql().build(); AppEngineExtension.builder().withDatastoreAndCloudSql().build();
@Test @TestOfyAndSql
void testGetRegistrarToTldMap() { void testGetRegistrarToTldMap() {
assertThat(OteAccountBuilder.forClientId("myclientid").getClientIdToTldMap()) assertThat(OteAccountBuilder.forClientId("myclientid").getClientIdToTldMap())
.containsExactly( .containsExactly(
@ -102,7 +104,7 @@ public final class OteAccountBuilderTest {
assertThat(contact.getGaeUserId()).isNotEmpty(); assertThat(contact.getGaeUserId()).isNotEmpty();
} }
@Test @TestOfyAndSql
void testCreateOteEntities_success() { void testCreateOteEntities_success() {
OteAccountBuilder.forClientId("myclientid").addContact("email@example.com").buildAndPersist(); OteAccountBuilder.forClientId("myclientid").addContact("email@example.com").buildAndPersist();
@ -119,7 +121,7 @@ public final class OteAccountBuilderTest {
assertContactExists("myclientid-5", "email@example.com"); assertContactExists("myclientid-5", "email@example.com");
} }
@Test @TestOfyAndSql
void testCreateOteEntities_multipleContacts_success() { void testCreateOteEntities_multipleContacts_success() {
OteAccountBuilder.forClientId("myclientid") OteAccountBuilder.forClientId("myclientid")
.addContact("email@example.com") .addContact("email@example.com")
@ -148,7 +150,7 @@ public final class OteAccountBuilderTest {
assertContactExists("myclientid-5", "someone@example.com"); assertContactExists("myclientid-5", "someone@example.com");
} }
@Test @TestOfyAndSql
void testCreateOteEntities_setPassword() { void testCreateOteEntities_setPassword() {
OteAccountBuilder.forClientId("myclientid").setPassword("myPassword").buildAndPersist(); OteAccountBuilder.forClientId("myclientid").setPassword("myPassword").buildAndPersist();
@ -156,7 +158,7 @@ public final class OteAccountBuilderTest {
.isTrue(); .isTrue();
} }
@Test @TestOfyAndSql
void testCreateOteEntities_setCertificate() { void testCreateOteEntities_setCertificate() {
OteAccountBuilder.forClientId("myclientid") OteAccountBuilder.forClientId("myclientid")
.setCertificate(SAMPLE_CERT, new SystemClock().nowUtc()) .setCertificate(SAMPLE_CERT, new SystemClock().nowUtc())
@ -168,7 +170,7 @@ public final class OteAccountBuilderTest {
.hasValue(SAMPLE_CERT); .hasValue(SAMPLE_CERT);
} }
@Test @TestOfyAndSql
void testCreateOteEntities_setIpAllowList() { void testCreateOteEntities_setIpAllowList() {
OteAccountBuilder.forClientId("myclientid") OteAccountBuilder.forClientId("myclientid")
.setIpAllowList(ImmutableList.of("1.1.1.0/24")) .setIpAllowList(ImmutableList.of("1.1.1.0/24"))
@ -178,7 +180,7 @@ public final class OteAccountBuilderTest {
.containsExactly(CidrAddressBlock.create("1.1.1.0/24")); .containsExactly(CidrAddressBlock.create("1.1.1.0/24"));
} }
@Test @TestOfyAndSql
void testCreateOteEntities_invalidClientId_fails() { void testCreateOteEntities_invalidClientId_fails() {
assertThat( assertThat(
assertThrows( assertThrows(
@ -187,7 +189,7 @@ public final class OteAccountBuilderTest {
.isEqualTo("Invalid registrar name: 3blo-bio"); .isEqualTo("Invalid registrar name: 3blo-bio");
} }
@Test @TestOfyAndSql
void testCreateOteEntities_clientIdTooShort_fails() { void testCreateOteEntities_clientIdTooShort_fails() {
assertThat( assertThat(
assertThrows(IllegalArgumentException.class, () -> OteAccountBuilder.forClientId("bl"))) assertThrows(IllegalArgumentException.class, () -> OteAccountBuilder.forClientId("bl")))
@ -195,7 +197,7 @@ public final class OteAccountBuilderTest {
.isEqualTo("Invalid registrar name: bl"); .isEqualTo("Invalid registrar name: bl");
} }
@Test @TestOfyAndSql
void testCreateOteEntities_clientIdTooLong_fails() { void testCreateOteEntities_clientIdTooLong_fails() {
assertThat( assertThat(
assertThrows( assertThrows(
@ -205,7 +207,7 @@ public final class OteAccountBuilderTest {
.isEqualTo("Invalid registrar name: blobiotoooolong"); .isEqualTo("Invalid registrar name: blobiotoooolong");
} }
@Test @TestOfyAndSql
void testCreateOteEntities_clientIdBadCharacter_fails() { void testCreateOteEntities_clientIdBadCharacter_fails() {
assertThat( assertThat(
assertThrows( assertThrows(
@ -214,7 +216,7 @@ public final class OteAccountBuilderTest {
.isEqualTo("Invalid registrar name: blo#bio"); .isEqualTo("Invalid registrar name: blo#bio");
} }
@Test @TestOfyAndSql
void testCreateOteEntities_registrarExists_failsWhenNotReplaceExisting() { void testCreateOteEntities_registrarExists_failsWhenNotReplaceExisting() {
persistSimpleResource(makeRegistrar1().asBuilder().setClientId("myclientid-1").build()); persistSimpleResource(makeRegistrar1().asBuilder().setClientId("myclientid-1").build());
@ -225,7 +227,7 @@ public final class OteAccountBuilderTest {
.contains("Found existing object(s) conflicting with OT&E objects"); .contains("Found existing object(s) conflicting with OT&E objects");
} }
@Test @TestOfyAndSql
void testCreateOteEntities_tldExists_failsWhenNotReplaceExisting() { void testCreateOteEntities_tldExists_failsWhenNotReplaceExisting() {
createTld("myclientid-ga", START_DATE_SUNRISE); createTld("myclientid-ga", START_DATE_SUNRISE);
@ -236,7 +238,7 @@ public final class OteAccountBuilderTest {
.contains("Found existing object(s) conflicting with OT&E objects"); .contains("Found existing object(s) conflicting with OT&E objects");
} }
@Test @TestOfyAndSql
void testCreateOteEntities_entitiesExist_succeedsWhenReplaceExisting() { void testCreateOteEntities_entitiesExist_succeedsWhenReplaceExisting() {
persistSimpleResource(makeRegistrar1().asBuilder().setClientId("myclientid-1").build()); persistSimpleResource(makeRegistrar1().asBuilder().setClientId("myclientid-1").build());
// we intentionally create the -ga TLD with the wrong state, to make sure it's overwritten. // we intentionally create the -ga TLD with the wrong state, to make sure it's overwritten.
@ -251,7 +253,7 @@ public final class OteAccountBuilderTest {
assertRegistrarExists("myclientid-3", "myclientid-ga"); assertRegistrarExists("myclientid-3", "myclientid-ga");
} }
@Test @TestOfyAndSql
void testCreateOteEntities_doubleCreation_actuallyReplaces() { void testCreateOteEntities_doubleCreation_actuallyReplaces() {
OteAccountBuilder.forClientId("myclientid") OteAccountBuilder.forClientId("myclientid")
.setPassword("oldPassword") .setPassword("oldPassword")
@ -273,7 +275,7 @@ public final class OteAccountBuilderTest {
.isTrue(); .isTrue();
} }
@Test @TestOfyAndSql
void testCreateOteEntities_doubleCreation_keepsOldContacts() { void testCreateOteEntities_doubleCreation_keepsOldContacts() {
OteAccountBuilder.forClientId("myclientid").addContact("email@example.com").buildAndPersist(); OteAccountBuilder.forClientId("myclientid").addContact("email@example.com").buildAndPersist();
@ -288,7 +290,7 @@ public final class OteAccountBuilderTest {
assertContactExists("myclientid-3", "email@example.com"); assertContactExists("myclientid-3", "email@example.com");
} }
@Test @TestOfyAndSql
void testCreateClientIdToTldMap_validEntries() { void testCreateClientIdToTldMap_validEntries() {
assertThat(OteAccountBuilder.createClientIdToTldMap("myclientid")) assertThat(OteAccountBuilder.createClientIdToTldMap("myclientid"))
.containsExactly( .containsExactly(
@ -298,7 +300,7 @@ public final class OteAccountBuilderTest {
"myclientid-5", "myclientid-eap"); "myclientid-5", "myclientid-eap");
} }
@Test @TestOfyAndSql
void testCreateClientIdToTldMap_invalidId() { void testCreateClientIdToTldMap_invalidId() {
IllegalArgumentException exception = IllegalArgumentException exception =
assertThrows( assertThrows(
@ -306,12 +308,12 @@ public final class OteAccountBuilderTest {
assertThat(exception).hasMessageThat().isEqualTo("Invalid registrar name: a"); assertThat(exception).hasMessageThat().isEqualTo("Invalid registrar name: a");
} }
@Test @TestOfyAndSql
void testGetBaseClientId_validOteId() { void testGetBaseClientId_validOteId() {
assertThat(OteAccountBuilder.getBaseClientId("myclientid-4")).isEqualTo("myclientid"); assertThat(OteAccountBuilder.getBaseClientId("myclientid-4")).isEqualTo("myclientid");
} }
@Test @TestOfyAndSql
void testGetBaseClientId_invalidInput_malformed() { void testGetBaseClientId_invalidInput_malformed() {
assertThat( assertThat(
assertThrows( assertThrows(
@ -321,7 +323,7 @@ public final class OteAccountBuilderTest {
.isEqualTo("Invalid OT&E client ID: myclientid"); .isEqualTo("Invalid OT&E client ID: myclientid");
} }
@Test @TestOfyAndSql
void testGetBaseClientId_invalidInput_wrongForBase() { void testGetBaseClientId_invalidInput_wrongForBase() {
assertThat( assertThat(
assertThrows( assertThrows(

View file

@ -18,13 +18,13 @@ import static com.google.common.truth.Truth.assertThat;
import static google.registry.model.EppResourceUtils.loadByForeignKey; import static google.registry.model.EppResourceUtils.loadByForeignKey;
import static google.registry.model.eppcommon.StatusValue.PENDING_DELETE; import static google.registry.model.eppcommon.StatusValue.PENDING_DELETE;
import static google.registry.model.eppcommon.StatusValue.PENDING_TRANSFER; import static google.registry.model.eppcommon.StatusValue.PENDING_TRANSFER;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.reporting.HistoryEntry.Type.SYNTHETIC; import static google.registry.model.reporting.HistoryEntry.Type.SYNTHETIC;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.testing.DatabaseHelper.assertBillingEventsEqual; import static google.registry.testing.DatabaseHelper.assertBillingEventsEqual;
import static google.registry.testing.DatabaseHelper.assertPollMessagesEqual; import static google.registry.testing.DatabaseHelper.assertPollMessagesEqual;
import static google.registry.testing.DatabaseHelper.createTld; import static google.registry.testing.DatabaseHelper.createTld;
import static google.registry.testing.DatabaseHelper.getOnlyHistoryEntryOfType; import static google.registry.testing.DatabaseHelper.getOnlyHistoryEntryOfType;
import static google.registry.testing.DatabaseHelper.getPollMessages;
import static google.registry.testing.DatabaseHelper.loadByKey;
import static google.registry.testing.DatabaseHelper.newDomainBase; import static google.registry.testing.DatabaseHelper.newDomainBase;
import static google.registry.testing.DatabaseHelper.persistActiveContact; import static google.registry.testing.DatabaseHelper.persistActiveContact;
import static google.registry.testing.DatabaseHelper.persistActiveDomain; import static google.registry.testing.DatabaseHelper.persistActiveDomain;
@ -45,64 +45,79 @@ import google.registry.model.eppcommon.StatusValue;
import google.registry.model.ofy.Ofy; import google.registry.model.ofy.Ofy;
import google.registry.model.poll.PollMessage; import google.registry.model.poll.PollMessage;
import google.registry.model.reporting.HistoryEntry; import google.registry.model.reporting.HistoryEntry;
import google.registry.testing.FakeClock; import google.registry.testing.DualDatabaseTest;
import google.registry.testing.InjectExtension; import google.registry.testing.InjectExtension;
import google.registry.testing.TestOfyAndSql;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension; import org.junit.jupiter.api.extension.RegisterExtension;
/** Unit tests for {@link UnrenewDomainCommand}. */ /** Unit tests for {@link UnrenewDomainCommand}. */
@DualDatabaseTest
public class UnrenewDomainCommandTest extends CommandTestCase<UnrenewDomainCommand> { public class UnrenewDomainCommandTest extends CommandTestCase<UnrenewDomainCommand> {
@RegisterExtension public final InjectExtension inject = new InjectExtension(); @RegisterExtension public final InjectExtension inject = new InjectExtension();
private final FakeClock clock = new FakeClock(DateTime.parse("2016-12-06T13:55:01Z"));
@BeforeEach @BeforeEach
void beforeEach() { void beforeEach() {
createTld("tld"); createTld("tld");
inject.setStaticField(Ofy.class, "clock", clock); fakeClock.setTo(DateTime.parse("2016-12-06T13:55:01Z"));
command.clock = clock; inject.setStaticField(Ofy.class, "clock", fakeClock);
command.clock = fakeClock;
} }
@Test @TestOfyAndSql
void test_unrenewTwoDomains_worksSuccessfully() throws Exception { void test_unrenewTwoDomains_worksSuccessfully() throws Exception {
ContactResource contact = persistActiveContact("jd1234"); ContactResource contact = persistActiveContact("jd1234");
clock.advanceOneMilli(); fakeClock.advanceOneMilli();
persistDomainWithDependentResources( persistDomainWithDependentResources(
"foo", "tld", contact, clock.nowUtc(), clock.nowUtc(), clock.nowUtc().plusYears(5)); "foo",
clock.advanceOneMilli(); "tld",
contact,
fakeClock.nowUtc(),
fakeClock.nowUtc(),
fakeClock.nowUtc().plusYears(5));
fakeClock.advanceOneMilli();
persistDomainWithDependentResources( persistDomainWithDependentResources(
"bar", "tld", contact, clock.nowUtc(), clock.nowUtc(), clock.nowUtc().plusYears(4)); "bar",
clock.advanceOneMilli(); "tld",
contact,
fakeClock.nowUtc(),
fakeClock.nowUtc(),
fakeClock.nowUtc().plusYears(4));
fakeClock.advanceOneMilli();
runCommandForced("-p", "2", "foo.tld", "bar.tld"); runCommandForced("-p", "2", "foo.tld", "bar.tld");
clock.advanceOneMilli(); fakeClock.advanceOneMilli();
assertThat( assertThat(
loadByForeignKey(DomainBase.class, "foo.tld", clock.nowUtc()) loadByForeignKey(DomainBase.class, "foo.tld", fakeClock.nowUtc())
.get() .get()
.getRegistrationExpirationTime()) .getRegistrationExpirationTime())
.isEqualTo(DateTime.parse("2019-12-06T13:55:01.001Z")); .isEqualTo(DateTime.parse("2019-12-06T13:55:01.001Z"));
assertThat( assertThat(
loadByForeignKey(DomainBase.class, "bar.tld", clock.nowUtc()) loadByForeignKey(DomainBase.class, "bar.tld", fakeClock.nowUtc())
.get() .get()
.getRegistrationExpirationTime()) .getRegistrationExpirationTime())
.isEqualTo(DateTime.parse("2018-12-06T13:55:01.002Z")); .isEqualTo(DateTime.parse("2018-12-06T13:55:01.002Z"));
assertInStdout("Successfully unrenewed all domains."); assertInStdout("Successfully unrenewed all domains.");
} }
@Test @TestOfyAndSql
void test_unrenewDomain_savesDependentEntitiesCorrectly() throws Exception { void test_unrenewDomain_savesDependentEntitiesCorrectly() throws Exception {
ContactResource contact = persistActiveContact("jd1234"); ContactResource contact = persistActiveContact("jd1234");
clock.advanceOneMilli(); fakeClock.advanceOneMilli();
persistDomainWithDependentResources( persistDomainWithDependentResources(
"foo", "tld", contact, clock.nowUtc(), clock.nowUtc(), clock.nowUtc().plusYears(5)); "foo",
DateTime newExpirationTime = clock.nowUtc().plusYears(3); "tld",
clock.advanceOneMilli(); contact,
fakeClock.nowUtc(),
fakeClock.nowUtc(),
fakeClock.nowUtc().plusYears(5));
DateTime newExpirationTime = fakeClock.nowUtc().plusYears(3);
fakeClock.advanceOneMilli();
runCommandForced("-p", "2", "foo.tld"); runCommandForced("-p", "2", "foo.tld");
DateTime unrenewTime = clock.nowUtc(); DateTime unrenewTime = fakeClock.nowUtc();
clock.advanceOneMilli(); fakeClock.advanceOneMilli();
DomainBase domain = loadByForeignKey(DomainBase.class, "foo.tld", clock.nowUtc()).get(); DomainBase domain = loadByForeignKey(DomainBase.class, "foo.tld", fakeClock.nowUtc()).get();
assertAboutHistoryEntries() assertAboutHistoryEntries()
.that(getOnlyHistoryEntryOfType(domain, SYNTHETIC)) .that(getOnlyHistoryEntryOfType(domain, SYNTHETIC))
@ -120,7 +135,7 @@ public class UnrenewDomainCommandTest extends CommandTestCase<UnrenewDomainComma
HistoryEntry synthetic = getOnlyHistoryEntryOfType(domain, SYNTHETIC); HistoryEntry synthetic = getOnlyHistoryEntryOfType(domain, SYNTHETIC);
assertBillingEventsEqual( assertBillingEventsEqual(
tm().loadByKey(domain.getAutorenewBillingEvent()), loadByKey(domain.getAutorenewBillingEvent()),
new BillingEvent.Recurring.Builder() new BillingEvent.Recurring.Builder()
.setParent(synthetic) .setParent(synthetic)
.setReason(Reason.RENEW) .setReason(Reason.RENEW)
@ -130,7 +145,7 @@ public class UnrenewDomainCommandTest extends CommandTestCase<UnrenewDomainComma
.setEventTime(newExpirationTime) .setEventTime(newExpirationTime)
.build()); .build());
assertPollMessagesEqual( assertPollMessagesEqual(
ofy().load().type(PollMessage.class).ancestor(synthetic).list(), getPollMessages(domain),
ImmutableSet.of( ImmutableSet.of(
new PollMessage.OneTime.Builder() new PollMessage.OneTime.Builder()
.setParent(synthetic) .setParent(synthetic)
@ -156,7 +171,7 @@ public class UnrenewDomainCommandTest extends CommandTestCase<UnrenewDomainComma
assertThat(domain.getLastEppUpdateClientId()).isEqualTo("TheRegistrar"); assertThat(domain.getLastEppUpdateClientId()).isEqualTo("TheRegistrar");
} }
@Test @TestOfyAndSql
void test_periodTooLow_fails() { void test_periodTooLow_fails() {
IllegalArgumentException thrown = IllegalArgumentException thrown =
assertThrows( assertThrows(
@ -164,7 +179,7 @@ public class UnrenewDomainCommandTest extends CommandTestCase<UnrenewDomainComma
assertThat(thrown).hasMessageThat().isEqualTo("Period must be in the range 1-9"); assertThat(thrown).hasMessageThat().isEqualTo("Period must be in the range 1-9");
} }
@Test @TestOfyAndSql
void test_periodTooHigh_fails() { void test_periodTooHigh_fails() {
IllegalArgumentException thrown = IllegalArgumentException thrown =
assertThrows( assertThrows(
@ -172,9 +187,9 @@ public class UnrenewDomainCommandTest extends CommandTestCase<UnrenewDomainComma
assertThat(thrown).hasMessageThat().isEqualTo("Period must be in the range 1-9"); assertThat(thrown).hasMessageThat().isEqualTo("Period must be in the range 1-9");
} }
@Test @TestOfyAndSql
void test_varietyOfInvalidDomains_displaysErrors() { void test_varietyOfInvalidDomains_displaysErrors() {
DateTime now = clock.nowUtc(); DateTime now = fakeClock.nowUtc();
persistResource( persistResource(
newDomainBase("deleting.tld") newDomainBase("deleting.tld")
.asBuilder() .asBuilder()

View file

@ -37,14 +37,16 @@ import google.registry.model.domain.DomainBase;
import google.registry.model.reporting.Spec11ThreatMatch; import google.registry.model.reporting.Spec11ThreatMatch;
import google.registry.model.reporting.Spec11ThreatMatch.ThreatType; import google.registry.model.reporting.Spec11ThreatMatch.ThreatType;
import google.registry.reporting.spec11.Spec11RegistrarThreatMatchesParser; import google.registry.reporting.spec11.Spec11RegistrarThreatMatchesParser;
import google.registry.testing.DualDatabaseTest;
import google.registry.testing.TestOfyAndSql;
import google.registry.tools.CommandTestCase; import google.registry.tools.CommandTestCase;
import java.io.IOException; import java.io.IOException;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.joda.time.LocalDate; import org.joda.time.LocalDate;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
/** Tests for {@link BackfillSpec11ThreatMatchesCommand}. */ /** Tests for {@link BackfillSpec11ThreatMatchesCommand}. */
@DualDatabaseTest
public class BackfillSpec11ThreatMatchesCommandTest public class BackfillSpec11ThreatMatchesCommandTest
extends CommandTestCase<BackfillSpec11ThreatMatchesCommand> { extends CommandTestCase<BackfillSpec11ThreatMatchesCommand> {
@ -67,7 +69,7 @@ public class BackfillSpec11ThreatMatchesCommandTest
.thenReturn(ImmutableSet.of()); .thenReturn(ImmutableSet.of());
} }
@Test @TestOfyAndSql
void testSuccess_singleFile() throws Exception { void testSuccess_singleFile() throws Exception {
when(threatMatchesParser.getRegistrarThreatMatches(CURRENT_DATE)) when(threatMatchesParser.getRegistrarThreatMatches(CURRENT_DATE))
.thenReturn(sampleThreatMatches()); .thenReturn(sampleThreatMatches());
@ -77,7 +79,7 @@ public class BackfillSpec11ThreatMatchesCommandTest
verifyExactlyThreeEntriesInDbFromLastDay(); verifyExactlyThreeEntriesInDbFromLastDay();
} }
@Test @TestOfyAndSql
void testSuccess_sameDomain_multipleDays() throws Exception { void testSuccess_sameDomain_multipleDays() throws Exception {
// If the same domains show up on multiple days, there should be multiple entries for them // If the same domains show up on multiple days, there should be multiple entries for them
when(threatMatchesParser.getRegistrarThreatMatches(CURRENT_DATE)) when(threatMatchesParser.getRegistrarThreatMatches(CURRENT_DATE))
@ -106,14 +108,14 @@ public class BackfillSpec11ThreatMatchesCommandTest
}); });
} }
@Test @TestOfyAndSql
void testSuccess_empty() throws Exception { void testSuccess_empty() throws Exception {
runCommandForced(); runCommandForced();
assertInStdout("Backfill Spec11 results from 692 files?"); assertInStdout("Backfill Spec11 results from 692 files?");
assertInStdout("Successfully parsed through 692 files with 0 threats."); assertInStdout("Successfully parsed through 692 files with 0 threats.");
} }
@Test @TestOfyAndSql
void testSuccess_sameDayTwice() throws Exception { void testSuccess_sameDayTwice() throws Exception {
when(threatMatchesParser.getRegistrarThreatMatches(CURRENT_DATE)) when(threatMatchesParser.getRegistrarThreatMatches(CURRENT_DATE))
.thenReturn(sampleThreatMatches()); .thenReturn(sampleThreatMatches());
@ -122,7 +124,7 @@ public class BackfillSpec11ThreatMatchesCommandTest
verifyExactlyThreeEntriesInDbFromLastDay(); verifyExactlyThreeEntriesInDbFromLastDay();
} }
@Test @TestOfyAndSql
void testSuccess_threeDomainsForDomainName() throws Exception { void testSuccess_threeDomainsForDomainName() throws Exception {
// We should use the repo ID from the proper DomainBase object at the scan's point in time. // We should use the repo ID from the proper DomainBase object at the scan's point in time.
// First, domain was created at START_OF_TIME and deleted one year ago // First, domain was created at START_OF_TIME and deleted one year ago
@ -161,7 +163,7 @@ public class BackfillSpec11ThreatMatchesCommandTest
assertThat(threatMatchRepoId).isNotEqualTo(thirdSave.getRepoId()); assertThat(threatMatchRepoId).isNotEqualTo(thirdSave.getRepoId());
} }
@Test @TestOfyAndSql
void testSuccess_skipsExistingDatesWithoutOverwrite() throws Exception { void testSuccess_skipsExistingDatesWithoutOverwrite() throws Exception {
when(threatMatchesParser.getRegistrarThreatMatches(CURRENT_DATE)) when(threatMatchesParser.getRegistrarThreatMatches(CURRENT_DATE))
.thenReturn(sampleThreatMatches()); .thenReturn(sampleThreatMatches());
@ -183,7 +185,7 @@ public class BackfillSpec11ThreatMatchesCommandTest
.isEqualExceptFields(previous, "id"); .isEqualExceptFields(previous, "id");
} }
@Test @TestOfyAndSql
void testSuccess_overwritesExistingDatesWhenSpecified() throws Exception { void testSuccess_overwritesExistingDatesWhenSpecified() throws Exception {
when(threatMatchesParser.getRegistrarThreatMatches(CURRENT_DATE)) when(threatMatchesParser.getRegistrarThreatMatches(CURRENT_DATE))
.thenReturn(sampleThreatMatches()); .thenReturn(sampleThreatMatches());
@ -201,7 +203,7 @@ public class BackfillSpec11ThreatMatchesCommandTest
verifyExactlyThreeEntriesInDbFromLastDay(); verifyExactlyThreeEntriesInDbFromLastDay();
} }
@Test @TestOfyAndSql
void testFailure_oneFileFails() throws Exception { void testFailure_oneFileFails() throws Exception {
// If there are any exceptions, we should fail loud and fast // If there are any exceptions, we should fail loud and fast
when(threatMatchesParser.getRegistrarThreatMatches(CURRENT_DATE)) when(threatMatchesParser.getRegistrarThreatMatches(CURRENT_DATE))
@ -215,7 +217,7 @@ public class BackfillSpec11ThreatMatchesCommandTest
jpaTm().transact(() -> assertThat(jpaTm().loadAllOf(Spec11ThreatMatch.class)).isEmpty()); jpaTm().transact(() -> assertThat(jpaTm().loadAllOf(Spec11ThreatMatch.class)).isEmpty());
} }
@Test @TestOfyAndSql
void testFailure_noDomainForDomainName() throws Exception { void testFailure_noDomainForDomainName() throws Exception {
deleteResource(domainA); deleteResource(domainA);
when(threatMatchesParser.getRegistrarThreatMatches(CURRENT_DATE)) when(threatMatchesParser.getRegistrarThreatMatches(CURRENT_DATE))
@ -225,7 +227,7 @@ public class BackfillSpec11ThreatMatchesCommandTest
.isEqualTo("Domain name a.com had no associated DomainBase objects."); .isEqualTo("Domain name a.com had no associated DomainBase objects.");
} }
@Test @TestOfyAndSql
void testFailure_noDomainAtTimeOfScan() throws Exception { void testFailure_noDomainAtTimeOfScan() throws Exception {
// If the domain existed at some point(s) in time but not the time of the scan, fail. // If the domain existed at some point(s) in time but not the time of the scan, fail.
// First, domain was created at START_OF_TIME and deleted one year ago // First, domain was created at START_OF_TIME and deleted one year ago