mirror of
https://github.com/google/nomulus.git
synced 2025-07-09 04:33:28 +02:00
Convert (most) HistoryEntry ofy calls to tm (#933)
* Convert (most) HistoryEntry ofy calls to tm As part of this change, it was necessary to do changes in the JPATM that are similar (but the opposite) of the changes that we did in DatastoreTM with regards to converting HistoryEntries to and from the *History classes. We leave the ofy() calls in the MapReduce ResaveAllHistoryEntriesAction for now; that can be converted during the Beam pipeline transition. Some other tests required registrar-name fixes as well -- because *History objects have a foreign key on the Registrar table, we have to use a "real" registrar name in tests. * Add simple HistoryEntryDaoTest
This commit is contained in:
parent
08cec96a93
commit
73210e4b09
26 changed files with 477 additions and 124 deletions
|
@ -30,6 +30,7 @@ import com.google.common.collect.Streams;
|
|||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.Result;
|
||||
import google.registry.model.contact.ContactHistory;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.host.HostHistory;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.persistence.VKey;
|
||||
|
@ -292,6 +293,21 @@ public class DatastoreTransactionManager implements TransactionManager {
|
|||
getOfy().clearSessionCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the given {@link Result} instance synchronously if not in a transaction.
|
||||
*
|
||||
* <p>The {@link Result} instance contains a task that will be executed by Objectify
|
||||
* asynchronously. If it is in a transaction, we don't need to execute the task immediately
|
||||
* because it is guaranteed to be done by the end of the transaction. However, if it is not in a
|
||||
* transaction, we need to execute it in case the following code expects that happens before
|
||||
* themselves.
|
||||
*/
|
||||
private void syncIfTransactionless(Result<?> result) {
|
||||
if (!inTransaction()) {
|
||||
result.now();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The following three methods exist due to the migration to Cloud SQL.
|
||||
*
|
||||
|
@ -309,34 +325,23 @@ public class DatastoreTransactionManager implements TransactionManager {
|
|||
syncIfTransactionless(getOfy().save().entity(entity));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T toChildHistoryEntryIfPossible(@Nullable T obj) {
|
||||
// NB: The Key of the object in question may not necessarily be the resulting class that we
|
||||
// wish to have. Because all *History classes are @EntitySubclasses, their Keys will have type
|
||||
// HistoryEntry -- even if you create them based off the *History class.
|
||||
if (obj != null && HistoryEntry.class.isAssignableFrom(obj.getClass())) {
|
||||
return (T) ((HistoryEntry) obj).toChildHistoryEntity();
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private <T> T loadNullable(VKey<T> key) {
|
||||
return toChildHistoryEntryIfPossible(getOfy().load().key(key.getOfyKey()).now());
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the given {@link Result} instance synchronously if not in a transaction.
|
||||
*
|
||||
* <p>The {@link Result} instance contains a task that will be executed by Objectify
|
||||
* asynchronously. If it is in a transaction, we don't need to execute the task immediately
|
||||
* because it is guaranteed to be done by the end of the transaction. However, if it is not in a
|
||||
* transaction, we need to execute it in case the following code expects that happens before
|
||||
* themselves.
|
||||
*/
|
||||
private void syncIfTransactionless(Result<?> result) {
|
||||
if (!inTransaction()) {
|
||||
result.now();
|
||||
/** Converts a nonnull {@link HistoryEntry} to the child format, e.g. {@link DomainHistory} */
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T toChildHistoryEntryIfPossible(@Nullable T obj) {
|
||||
// NB: The Key of the object in question may not necessarily be the resulting class that we
|
||||
// wish to have. Because all *History classes are @EntitySubclasses, their Keys will have type
|
||||
// HistoryEntry -- even if you create them based off the *History class.
|
||||
if (obj instanceof HistoryEntry
|
||||
&& !(obj instanceof ContactHistory)
|
||||
&& !(obj instanceof DomainHistory)
|
||||
&& !(obj instanceof HostHistory)) {
|
||||
return (T) ((HistoryEntry) obj).toChildHistoryEntity();
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,144 @@
|
|||
// Copyright 2020 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.model.reporting;
|
||||
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
|
||||
import com.google.common.collect.Iterables;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.contact.ContactHistory;
|
||||
import google.registry.model.contact.ContactResource;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.host.HostHistory;
|
||||
import google.registry.model.host.HostResource;
|
||||
import google.registry.persistence.VKey;
|
||||
import java.util.Comparator;
|
||||
import javax.persistence.EntityManager;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/**
|
||||
* Retrieves {@link HistoryEntry} descendants (e.g. {@link DomainHistory}).
|
||||
*
|
||||
* <p>This class is configured to retrieve either from Datastore or SQL, depending on which database
|
||||
* is currently considered the primary database.
|
||||
*/
|
||||
public class HistoryEntryDao {
|
||||
|
||||
/** Loads all history objects in the times specified, including all types. */
|
||||
public static Iterable<? extends HistoryEntry> loadAllHistoryObjects(
|
||||
DateTime afterTime, DateTime beforeTime) {
|
||||
if (tm().isOfy()) {
|
||||
return ofy()
|
||||
.load()
|
||||
.type(HistoryEntry.class)
|
||||
.order("modificationTime")
|
||||
.filter("modificationTime >=", afterTime)
|
||||
.filter("modificationTime <=", beforeTime);
|
||||
} else {
|
||||
return jpaTm()
|
||||
.transact(
|
||||
() ->
|
||||
Iterables.concat(
|
||||
loadAllHistoryObjectsFromSql(ContactHistory.class, afterTime, beforeTime),
|
||||
loadAllHistoryObjectsFromSql(DomainHistory.class, afterTime, beforeTime),
|
||||
loadAllHistoryObjectsFromSql(HostHistory.class, afterTime, beforeTime)));
|
||||
}
|
||||
}
|
||||
|
||||
/** Loads all history objects corresponding to the given {@link EppResource}. */
|
||||
public static Iterable<? extends HistoryEntry> loadHistoryObjectsForResource(
|
||||
VKey<? extends EppResource> parentKey) {
|
||||
return loadHistoryObjectsForResource(parentKey, START_OF_TIME, END_OF_TIME);
|
||||
}
|
||||
|
||||
/** Loads all history objects in the time period specified for the given {@link EppResource}. */
|
||||
public static Iterable<? extends HistoryEntry> loadHistoryObjectsForResource(
|
||||
VKey<? extends EppResource> parentKey, DateTime afterTime, DateTime beforeTime) {
|
||||
if (tm().isOfy()) {
|
||||
return ofy()
|
||||
.load()
|
||||
.type(HistoryEntry.class)
|
||||
.ancestor(parentKey.getOfyKey())
|
||||
.order("modificationTime")
|
||||
.filter("modificationTime >=", afterTime)
|
||||
.filter("modificationTime <=", beforeTime);
|
||||
} else {
|
||||
return jpaTm()
|
||||
.transact(() -> loadHistoryObjectsForResourceFromSql(parentKey, afterTime, beforeTime));
|
||||
}
|
||||
}
|
||||
|
||||
private static Iterable<? extends HistoryEntry> loadHistoryObjectsForResourceFromSql(
|
||||
VKey<? extends EppResource> parentKey, DateTime afterTime, DateTime beforeTime) {
|
||||
Class<? extends HistoryEntry> historyClass = getHistoryClassFromParent(parentKey.getKind());
|
||||
String repoIdFieldName = getRepoIdFieldNameFromHistoryClass(historyClass);
|
||||
EntityManager entityManager = jpaTm().getEntityManager();
|
||||
String tableName = entityManager.getMetamodel().entity(historyClass).getName();
|
||||
String queryString =
|
||||
String.format(
|
||||
"SELECT entry FROM %s entry WHERE entry.modificationTime >= :afterTime AND "
|
||||
+ "entry.modificationTime <= :beforeTime AND entry.%s = :parentKey",
|
||||
tableName, repoIdFieldName);
|
||||
return entityManager
|
||||
.createQuery(queryString, historyClass)
|
||||
.setParameter("afterTime", afterTime)
|
||||
.setParameter("beforeTime", beforeTime)
|
||||
.setParameter("parentKey", parentKey.getSqlKey().toString())
|
||||
.getResultStream()
|
||||
.sorted(Comparator.comparing(HistoryEntry::getModificationTime))
|
||||
.collect(toImmutableList());
|
||||
}
|
||||
|
||||
private static Class<? extends HistoryEntry> getHistoryClassFromParent(
|
||||
Class<? extends EppResource> parent) {
|
||||
if (parent.equals(ContactResource.class)) {
|
||||
return ContactHistory.class;
|
||||
} else if (parent.equals(DomainBase.class)) {
|
||||
return DomainHistory.class;
|
||||
} else if (parent.equals(HostResource.class)) {
|
||||
return HostHistory.class;
|
||||
}
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Unknown history type for parent %s", parent.getName()));
|
||||
}
|
||||
|
||||
private static String getRepoIdFieldNameFromHistoryClass(
|
||||
Class<? extends HistoryEntry> historyClass) {
|
||||
return historyClass.equals(ContactHistory.class)
|
||||
? "contactRepoId"
|
||||
: historyClass.equals(DomainHistory.class) ? "domainRepoId" : "hostRepoId";
|
||||
}
|
||||
|
||||
private static Iterable<? extends HistoryEntry> loadAllHistoryObjectsFromSql(
|
||||
Class<? extends HistoryEntry> historyClass, DateTime afterTime, DateTime beforeTime) {
|
||||
EntityManager entityManager = jpaTm().getEntityManager();
|
||||
return entityManager
|
||||
.createQuery(
|
||||
String.format(
|
||||
"SELECT entry FROM %s entry WHERE entry.modificationTime >= :afterTime AND "
|
||||
+ "entry.modificationTime <= :beforeTime",
|
||||
entityManager.getMetamodel().entity(historyClass).getName()),
|
||||
historyClass)
|
||||
.setParameter("afterTime", afterTime)
|
||||
.setParameter("beforeTime", beforeTime)
|
||||
.getResultList();
|
||||
}
|
||||
}
|
|
@ -18,6 +18,7 @@ import static com.google.common.base.Preconditions.checkArgument;
|
|||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static com.google.common.collect.ImmutableMap.toImmutableMap;
|
||||
import static com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static google.registry.model.ofy.DatastoreTransactionManager.toChildHistoryEntryIfPossible;
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
import static java.util.AbstractMap.SimpleEntry;
|
||||
import static java.util.stream.Collectors.joining;
|
||||
|
@ -34,6 +35,7 @@ import google.registry.model.index.EppResourceIndex;
|
|||
import google.registry.model.index.ForeignKeyIndex.ForeignKeyContactIndex;
|
||||
import google.registry.model.index.ForeignKeyIndex.ForeignKeyDomainIndex;
|
||||
import google.registry.model.index.ForeignKeyIndex.ForeignKeyHostIndex;
|
||||
import google.registry.model.ofy.DatastoreTransactionManager;
|
||||
import google.registry.persistence.JpaRetries;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.util.Clock;
|
||||
|
@ -250,8 +252,10 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager {
|
|||
return;
|
||||
}
|
||||
assertInTransaction();
|
||||
getEntityManager().persist(entity);
|
||||
transactionInfo.get().addUpdate(entity);
|
||||
// Necessary due to the changes in HistoryEntry representation during the migration to SQL
|
||||
Object toPersist = toChildHistoryEntryIfPossible(entity);
|
||||
getEntityManager().persist(toPersist);
|
||||
transactionInfo.get().addUpdate(toPersist);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -278,8 +282,10 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager {
|
|||
return;
|
||||
}
|
||||
assertInTransaction();
|
||||
getEntityManager().merge(entity);
|
||||
transactionInfo.get().addUpdate(entity);
|
||||
// Necessary due to the changes in HistoryEntry representation during the migration to SQL
|
||||
Object toPersist = toChildHistoryEntryIfPossible(entity);
|
||||
getEntityManager().merge(toPersist);
|
||||
transactionInfo.get().addUpdate(toPersist);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -307,8 +313,10 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager {
|
|||
}
|
||||
assertInTransaction();
|
||||
checkArgument(exists(entity), "Given entity does not exist");
|
||||
getEntityManager().merge(entity);
|
||||
transactionInfo.get().addUpdate(entity);
|
||||
// Necessary due to the changes in HistoryEntry representation during the migration to SQL
|
||||
Object toPersist = toChildHistoryEntryIfPossible(entity);
|
||||
getEntityManager().merge(toPersist);
|
||||
transactionInfo.get().addUpdate(toPersist);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -339,6 +347,7 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager {
|
|||
@Override
|
||||
public boolean exists(Object entity) {
|
||||
checkArgumentNotNull(entity, "entity must be specified");
|
||||
entity = toChildHistoryEntryIfPossible(entity);
|
||||
EntityType<?> entityType = getEntityType(entity.getClass());
|
||||
ImmutableSet<EntityId> entityIds = getEntityIdsFromEntity(entityType, entity);
|
||||
return exists(entityType.getName(), entityIds);
|
||||
|
@ -382,6 +391,7 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager {
|
|||
@Override
|
||||
public <T> ImmutableList<T> loadByEntitiesIfPresent(Iterable<T> entities) {
|
||||
return Streams.stream(entities)
|
||||
.map(DatastoreTransactionManager::toChildHistoryEntryIfPossible)
|
||||
.filter(this::exists)
|
||||
.map(this::loadByEntity)
|
||||
.collect(toImmutableList());
|
||||
|
@ -416,9 +426,14 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager {
|
|||
public <T> T loadByEntity(T entity) {
|
||||
checkArgumentNotNull(entity, "entity must be specified");
|
||||
assertInTransaction();
|
||||
entity = toChildHistoryEntryIfPossible(entity);
|
||||
// If the caller requested a HistoryEntry, load the corresponding *History class
|
||||
T possibleChild = toChildHistoryEntryIfPossible(entity);
|
||||
return (T)
|
||||
loadByKey(
|
||||
VKey.createSql(entity.getClass(), emf.getPersistenceUnitUtil().getIdentifier(entity)));
|
||||
VKey.createSql(
|
||||
possibleChild.getClass(),
|
||||
emf.getPersistenceUnitUtil().getIdentifier(possibleChild)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -469,6 +484,7 @@ public class JpaTransactionManagerImpl implements JpaTransactionManager {
|
|||
return;
|
||||
}
|
||||
assertInTransaction();
|
||||
entity = toChildHistoryEntryIfPossible(entity);
|
||||
Object managedEntity = entity;
|
||||
if (!getEntityManager().contains(entity)) {
|
||||
managedEntity = getEntityManager().merge(entity);
|
||||
|
|
|
@ -52,6 +52,7 @@ import google.registry.model.registrar.Registrar;
|
|||
import google.registry.model.registrar.RegistrarAddress;
|
||||
import google.registry.model.registrar.RegistrarContact;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.model.reporting.HistoryEntryDao;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.rdap.RdapDataStructures.Event;
|
||||
import google.registry.rdap.RdapDataStructures.EventAction;
|
||||
|
@ -880,8 +881,9 @@ public class RdapJsonFormatter {
|
|||
// 2.3.2.3 An event of *eventAction* type *transfer*, with the last date and time that the
|
||||
// domain was transferred. The event of *eventAction* type *transfer* MUST be omitted if the
|
||||
// domain name has not been transferred since it was created.
|
||||
for (HistoryEntry historyEntry :
|
||||
ofy().load().type(HistoryEntry.class).ancestor(resource).order("modificationTime")) {
|
||||
Iterable<? extends HistoryEntry> historyEntries =
|
||||
HistoryEntryDao.loadHistoryObjectsForResource(resource.createVKey());
|
||||
for (HistoryEntry historyEntry : historyEntries) {
|
||||
EventAction rdapEventAction =
|
||||
HISTORY_ENTRY_TYPE_TO_RDAP_EVENT_ACTION_MAP.get(historyEntry.getType());
|
||||
// Only save the historyEntries if this is a type we care about.
|
||||
|
@ -930,13 +932,9 @@ public class RdapJsonFormatter {
|
|||
return eventsBuilder.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an RDAP event object as defined by RFC 7483.
|
||||
*/
|
||||
/** Creates an RDAP event object as defined by RFC 7483. */
|
||||
private static Event makeEvent(
|
||||
EventAction eventAction,
|
||||
@Nullable String eventActor,
|
||||
DateTime eventDate) {
|
||||
EventAction eventAction, @Nullable String eventActor, DateTime eventDate) {
|
||||
Event.Builder builder = Event.builder()
|
||||
.setEventAction(eventAction)
|
||||
.setEventDate(eventDate);
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
package google.registry.tools;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
import static google.registry.util.PreconditionsUtils.checkArgumentNotNull;
|
||||
|
@ -25,14 +24,16 @@ import com.beust.jcommander.Parameter;
|
|||
import com.beust.jcommander.Parameters;
|
||||
import google.registry.model.EppResource;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.model.reporting.HistoryEntryDao;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.tools.CommandUtilities.ResourceType;
|
||||
import google.registry.xml.XmlTransformer;
|
||||
import org.joda.time.DateTime;
|
||||
|
||||
/** Command to show history entries. */
|
||||
@Parameters(separators = " =",
|
||||
commandDescription = "Show history entries that occurred in a given time range")
|
||||
@Parameters(
|
||||
separators = " =",
|
||||
commandDescription = "Show history entries that occurred in a given time range")
|
||||
final class GetHistoryEntriesCommand implements CommandWithRemoteApi {
|
||||
|
||||
@Parameter(
|
||||
|
@ -45,33 +46,26 @@ final class GetHistoryEntriesCommand implements CommandWithRemoteApi {
|
|||
description = "Only show history entries that occurred at or before this time")
|
||||
private DateTime before = END_OF_TIME;
|
||||
|
||||
@Parameter(
|
||||
names = "--type",
|
||||
description = "Resource type.")
|
||||
@Parameter(names = "--type", description = "Resource type.")
|
||||
private ResourceType type;
|
||||
|
||||
@Parameter(
|
||||
names = "--id",
|
||||
description = "Foreign key of the resource.")
|
||||
@Parameter(names = "--id", description = "Foreign key of the resource.")
|
||||
private String uniqueId;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
VKey<? extends EppResource> parentKey = null;
|
||||
Iterable<? extends HistoryEntry> historyEntries;
|
||||
if (type != null || uniqueId != null) {
|
||||
checkArgument(
|
||||
type != null && uniqueId != null,
|
||||
"If either of 'type' or 'id' are set then both must be");
|
||||
parentKey = type.getKey(uniqueId, DateTime.now(UTC));
|
||||
VKey<? extends EppResource> parentKey = type.getKey(uniqueId, DateTime.now(UTC));
|
||||
checkArgumentNotNull(parentKey, "Invalid resource ID");
|
||||
historyEntries = HistoryEntryDao.loadHistoryObjectsForResource(parentKey, after, before);
|
||||
} else {
|
||||
historyEntries = HistoryEntryDao.loadAllHistoryObjects(after, before);
|
||||
}
|
||||
for (HistoryEntry entry :
|
||||
(parentKey == null
|
||||
? ofy().load().type(HistoryEntry.class)
|
||||
: ofy().load().type(HistoryEntry.class).ancestor(parentKey.getOfyKey()))
|
||||
.order("modificationTime")
|
||||
.filter("modificationTime >=", after)
|
||||
.filter("modificationTime <=", before)) {
|
||||
for (HistoryEntry entry : historyEntries) {
|
||||
System.out.printf(
|
||||
"Client: %s\nTime: %s\nClient TRID: %s\nServer TRID: %s\n%s\n",
|
||||
entry.getClientId(),
|
||||
|
|
|
@ -16,20 +16,24 @@ package google.registry.tools.javascrap;
|
|||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.persistence.transaction.TransactionManagerUtil.transactIfJpaTm;
|
||||
import static google.registry.tools.LockOrUnlockDomainCommand.REGISTRY_LOCK_STATUSES;
|
||||
|
||||
import com.beust.jcommander.Parameter;
|
||||
import com.beust.jcommander.Parameters;
|
||||
import com.google.common.collect.ImmutableCollection;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Streams;
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.registry.RegistryLockDao;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.model.reporting.HistoryEntryDao;
|
||||
import google.registry.persistence.VKey;
|
||||
import google.registry.schema.domain.RegistryLock;
|
||||
import google.registry.tools.CommandWithRemoteApi;
|
||||
import google.registry.tools.ConfirmingCommand;
|
||||
|
@ -130,7 +134,7 @@ public class BackfillRegistryLocksCommand extends ConfirmingCommand
|
|||
private DateTime getLockCompletionTimestamp(DomainBase domainBase, DateTime now) {
|
||||
// Best-effort, if a domain was URS-locked we should use that time
|
||||
// If we can't find that, return now.
|
||||
return ofy().load().type(HistoryEntry.class).ancestor(domainBase).list().stream()
|
||||
return Streams.stream(HistoryEntryDao.loadHistoryObjectsForResource(domainBase.createVKey()))
|
||||
// sort by modification time descending so we get the most recent one if it was locked twice
|
||||
.sorted(Comparator.comparing(HistoryEntry::getModificationTime).reversed())
|
||||
.filter(entry -> entry.getReason().equals("Uniform Rapid Suspension"))
|
||||
|
@ -140,18 +144,14 @@ public class BackfillRegistryLocksCommand extends ConfirmingCommand
|
|||
}
|
||||
|
||||
private ImmutableList<DomainBase> getLockedDomainsWithoutLocks(DateTime now) {
|
||||
return ImmutableList.copyOf(
|
||||
ofy()
|
||||
.load()
|
||||
.keys(
|
||||
roids.stream()
|
||||
.map(roid -> Key.create(DomainBase.class, roid))
|
||||
.collect(toImmutableList()))
|
||||
.values()
|
||||
.stream()
|
||||
.filter(d -> d.getDeletionTime().isAfter(now))
|
||||
.filter(d -> d.getStatusValues().containsAll(REGISTRY_LOCK_STATUSES))
|
||||
.filter(d -> !RegistryLockDao.getMostRecentByRepoId(d.getRepoId()).isPresent())
|
||||
.collect(toImmutableList()));
|
||||
ImmutableList<VKey<DomainBase>> domainKeys =
|
||||
roids.stream().map(roid -> VKey.create(DomainBase.class, roid)).collect(toImmutableList());
|
||||
ImmutableCollection<DomainBase> domains =
|
||||
transactIfJpaTm(() -> tm().loadByKeys(domainKeys)).values();
|
||||
return domains.stream()
|
||||
.filter(d -> d.getDeletionTime().isAfter(now))
|
||||
.filter(d -> d.getStatusValues().containsAll(REGISTRY_LOCK_STATUSES))
|
||||
.filter(d -> RegistryLockDao.getMostRecentByRepoId(d.getRepoId()).isEmpty())
|
||||
.collect(toImmutableList());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -525,8 +525,7 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
|
|||
clock.advanceOneMilli();
|
||||
runFlow();
|
||||
assertSuccessfulCreate("tld", ImmutableSet.of(), token);
|
||||
HistoryEntry historyEntry =
|
||||
ofy().load().type(HistoryEntry.class).ancestor(reloadResourceByForeignKey()).first().now();
|
||||
HistoryEntry historyEntry = getHistoryEntries(reloadResourceByForeignKey()).get(0);
|
||||
assertThat(ofy().load().entity(token).now().getRedemptionHistoryEntry())
|
||||
.hasValue(HistoryEntry.createVKey(Key.create(historyEntry)));
|
||||
}
|
||||
|
|
|
@ -0,0 +1,127 @@
|
|||
// Copyright 2020 The Nomulus Authors. All Rights Reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package google.registry.model.reporting;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.model.ImmutableObjectSubject.immutableObjectCorrespondence;
|
||||
import static google.registry.persistence.transaction.TransactionManagerUtil.transactIfJpaTm;
|
||||
import static google.registry.testing.DatabaseHelper.createTld;
|
||||
import static google.registry.testing.DatabaseHelper.newDomainBase;
|
||||
import static google.registry.testing.DatabaseHelper.persistActiveDomain;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
import static google.registry.util.DateTimeUtils.END_OF_TIME;
|
||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import google.registry.model.EntityTestCase;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.domain.Period;
|
||||
import google.registry.model.eppcommon.Trid;
|
||||
import google.registry.model.reporting.DomainTransactionRecord.TransactionReportField;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
|
||||
@DualDatabaseTest
|
||||
public class HistoryEntryDaoTest extends EntityTestCase {
|
||||
|
||||
private DomainBase domain;
|
||||
private HistoryEntry historyEntry;
|
||||
|
||||
@BeforeEach
|
||||
void beforeEach() {
|
||||
fakeClock.setTo(DateTime.parse("2020-10-01T00:00:00Z"));
|
||||
createTld("foobar");
|
||||
domain = persistActiveDomain("foo.foobar");
|
||||
DomainTransactionRecord transactionRecord =
|
||||
new DomainTransactionRecord.Builder()
|
||||
.setTld("foobar")
|
||||
.setReportingTime(fakeClock.nowUtc())
|
||||
.setReportField(TransactionReportField.NET_ADDS_1_YR)
|
||||
.setReportAmount(1)
|
||||
.build();
|
||||
// Set up a new persisted HistoryEntry entity.
|
||||
historyEntry =
|
||||
new DomainHistory.Builder()
|
||||
.setParent(domain)
|
||||
.setType(HistoryEntry.Type.DOMAIN_CREATE)
|
||||
.setPeriod(Period.create(1, Period.Unit.YEARS))
|
||||
.setXmlBytes("<xml></xml>".getBytes(UTF_8))
|
||||
.setModificationTime(fakeClock.nowUtc())
|
||||
.setClientId("TheRegistrar")
|
||||
.setOtherClientId("otherClient")
|
||||
.setTrid(Trid.create("ABC-123", "server-trid"))
|
||||
.setBySuperuser(false)
|
||||
.setReason("reason")
|
||||
.setRequestedByRegistrar(false)
|
||||
.setDomainTransactionRecords(ImmutableSet.of(transactionRecord))
|
||||
.build();
|
||||
persistResource(historyEntry);
|
||||
}
|
||||
|
||||
@TestOfyAndSql
|
||||
void testSimpleLoadAll() {
|
||||
assertThat(HistoryEntryDao.loadAllHistoryObjects(START_OF_TIME, END_OF_TIME))
|
||||
.comparingElementsUsing(immutableObjectCorrespondence("nsHosts"))
|
||||
.containsExactly(historyEntry);
|
||||
}
|
||||
|
||||
@TestOfyAndSql
|
||||
void testSkips_tooEarly() {
|
||||
assertThat(HistoryEntryDao.loadAllHistoryObjects(fakeClock.nowUtc().plusMillis(1), END_OF_TIME))
|
||||
.isEmpty();
|
||||
}
|
||||
|
||||
@TestOfyAndSql
|
||||
void testSkips_tooLate() {
|
||||
assertThat(
|
||||
HistoryEntryDao.loadAllHistoryObjects(START_OF_TIME, fakeClock.nowUtc().minusMillis(1)))
|
||||
.isEmpty();
|
||||
}
|
||||
|
||||
@TestOfyAndSql
|
||||
void testLoadByResource() {
|
||||
transactIfJpaTm(
|
||||
() ->
|
||||
assertThat(HistoryEntryDao.loadHistoryObjectsForResource(domain.createVKey()))
|
||||
.comparingElementsUsing(immutableObjectCorrespondence("nsHosts"))
|
||||
.containsExactly(historyEntry));
|
||||
}
|
||||
|
||||
@TestOfyAndSql
|
||||
void testLoadByResource_skips_tooEarly() {
|
||||
assertThat(
|
||||
HistoryEntryDao.loadHistoryObjectsForResource(
|
||||
domain.createVKey(), fakeClock.nowUtc().plusMillis(1), END_OF_TIME))
|
||||
.isEmpty();
|
||||
}
|
||||
|
||||
@TestOfyAndSql
|
||||
void testLoadByResource_skips_tooLate() {
|
||||
assertThat(
|
||||
HistoryEntryDao.loadHistoryObjectsForResource(
|
||||
domain.createVKey(), START_OF_TIME, fakeClock.nowUtc().minusMillis(1)))
|
||||
.isEmpty();
|
||||
}
|
||||
|
||||
@TestOfyAndSql
|
||||
void testLoadByResource_noEntriesForResource() {
|
||||
DomainBase newDomain = persistResource(newDomainBase("new.foobar"));
|
||||
assertThat(HistoryEntryDao.loadHistoryObjectsForResource(newDomain.createVKey())).isEmpty();
|
||||
}
|
||||
}
|
|
@ -14,22 +14,29 @@
|
|||
|
||||
package google.registry.model.reporting;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.model.ImmutableObjectSubject.assertAboutImmutableObjects;
|
||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||
import static google.registry.persistence.transaction.TransactionManagerUtil.transactIfJpaTm;
|
||||
import static google.registry.testing.DatabaseHelper.createTld;
|
||||
import static google.registry.testing.DatabaseHelper.newDomainBase;
|
||||
import static google.registry.testing.DatabaseHelper.persistActiveDomain;
|
||||
import static google.registry.testing.DatabaseHelper.persistResource;
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import google.registry.model.EntityTestCase;
|
||||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.domain.DomainHistory;
|
||||
import google.registry.model.domain.Period;
|
||||
import google.registry.model.eppcommon.Trid;
|
||||
import google.registry.model.reporting.DomainTransactionRecord.TransactionReportField;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import google.registry.testing.TestOfyOnly;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Unit tests for {@link HistoryEntry}. */
|
||||
@DualDatabaseTest
|
||||
class HistoryEntryTest extends EntityTestCase {
|
||||
|
||||
private HistoryEntry historyEntry;
|
||||
|
@ -37,6 +44,7 @@ class HistoryEntryTest extends EntityTestCase {
|
|||
@BeforeEach
|
||||
void setUp() {
|
||||
createTld("foobar");
|
||||
DomainBase domain = persistActiveDomain("foo.foobar");
|
||||
DomainTransactionRecord transactionRecord =
|
||||
new DomainTransactionRecord.Builder()
|
||||
.setTld("foobar")
|
||||
|
@ -46,13 +54,13 @@ class HistoryEntryTest extends EntityTestCase {
|
|||
.build();
|
||||
// Set up a new persisted HistoryEntry entity.
|
||||
historyEntry =
|
||||
new HistoryEntry.Builder()
|
||||
.setParent(newDomainBase("foo.foobar"))
|
||||
new DomainHistory.Builder()
|
||||
.setParent(domain)
|
||||
.setType(HistoryEntry.Type.DOMAIN_CREATE)
|
||||
.setPeriod(Period.create(1, Period.Unit.YEARS))
|
||||
.setXmlBytes("<xml></xml>".getBytes(UTF_8))
|
||||
.setModificationTime(fakeClock.nowUtc())
|
||||
.setClientId("foo")
|
||||
.setClientId("TheRegistrar")
|
||||
.setOtherClientId("otherClient")
|
||||
.setTrid(Trid.create("ABC-123", "server-trid"))
|
||||
.setBySuperuser(false)
|
||||
|
@ -63,13 +71,23 @@ class HistoryEntryTest extends EntityTestCase {
|
|||
persistResource(historyEntry);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testPersistence() {
|
||||
assertThat(ofy().load().entity(historyEntry).now()).isEqualTo(historyEntry);
|
||||
transactIfJpaTm(
|
||||
() -> {
|
||||
HistoryEntry fromDatabase = tm().loadByEntity(historyEntry);
|
||||
assertAboutImmutableObjects()
|
||||
.that(fromDatabase)
|
||||
.isEqualExceptFields(historyEntry, "nsHosts", "domainTransactionRecords");
|
||||
assertAboutImmutableObjects()
|
||||
.that(Iterables.getOnlyElement(fromDatabase.getDomainTransactionRecords()))
|
||||
.isEqualExceptFields(
|
||||
Iterables.getOnlyElement(historyEntry.getDomainTransactionRecords()), "id");
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyOnly
|
||||
void testIndexing() throws Exception {
|
||||
verifyIndexing(historyEntry, "modificationTime", "clientId");
|
||||
verifyIndexing(historyEntry.asHistoryEntry(), "modificationTime", "clientId");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,7 +95,7 @@ class RdapDomainActionTest extends RdapActionBaseTestCase<RdapDomainAction> {
|
|||
registrarLol)
|
||||
.asBuilder()
|
||||
.setCreationTimeForTest(clock.nowUtc().minusYears(3))
|
||||
.setCreationClientId("foo")
|
||||
.setCreationClientId("TheRegistrar")
|
||||
.build());
|
||||
|
||||
// deleted domain in lol
|
||||
|
@ -128,7 +128,7 @@ class RdapDomainActionTest extends RdapActionBaseTestCase<RdapDomainAction> {
|
|||
registrarLol)
|
||||
.asBuilder()
|
||||
.setCreationTimeForTest(clock.nowUtc().minusYears(3))
|
||||
.setCreationClientId("foo")
|
||||
.setCreationClientId("TheRegistrar")
|
||||
.setDeletionTime(clock.nowUtc().minusDays(1))
|
||||
.build());
|
||||
// cat.みんな
|
||||
|
@ -168,7 +168,7 @@ class RdapDomainActionTest extends RdapActionBaseTestCase<RdapDomainAction> {
|
|||
registrarIdn)
|
||||
.asBuilder()
|
||||
.setCreationTimeForTest(clock.nowUtc().minusYears(3))
|
||||
.setCreationClientId("foo")
|
||||
.setCreationClientId("TheRegistrar")
|
||||
.build());
|
||||
|
||||
// 1.tld
|
||||
|
@ -208,7 +208,7 @@ class RdapDomainActionTest extends RdapActionBaseTestCase<RdapDomainAction> {
|
|||
registrar1Tld)
|
||||
.asBuilder()
|
||||
.setCreationTimeForTest(clock.nowUtc().minusYears(3))
|
||||
.setCreationClientId("foo")
|
||||
.setCreationClientId("TheRegistrar")
|
||||
.build());
|
||||
|
||||
// history entries
|
||||
|
|
|
@ -176,7 +176,7 @@ class RdapDomainSearchActionTest extends RdapSearchActionTestCase<RdapDomainSear
|
|||
.asBuilder()
|
||||
.setSubordinateHosts(ImmutableSet.of("ns1.cat.lol", "ns2.cat.lol"))
|
||||
.setCreationTimeForTest(clock.nowUtc().minusYears(3))
|
||||
.setCreationClientId("foo")
|
||||
.setCreationClientId("TheRegistrar")
|
||||
.build());
|
||||
persistResource(
|
||||
hostNs1CatLol.asBuilder().setSuperordinateDomain(domainCatLol.createVKey()).build());
|
||||
|
@ -216,7 +216,7 @@ class RdapDomainSearchActionTest extends RdapSearchActionTestCase<RdapDomainSear
|
|||
registrar)
|
||||
.asBuilder()
|
||||
.setCreationTimeForTest(clock.nowUtc().minusYears(3))
|
||||
.setCreationClientId("foo")
|
||||
.setCreationClientId("TheRegistrar")
|
||||
.build());
|
||||
// cat.example
|
||||
createTld("example");
|
||||
|
@ -255,7 +255,7 @@ class RdapDomainSearchActionTest extends RdapSearchActionTestCase<RdapDomainSear
|
|||
registrar)
|
||||
.asBuilder()
|
||||
.setCreationTimeForTest(clock.nowUtc().minusYears(3))
|
||||
.setCreationClientId("foo")
|
||||
.setCreationClientId("TheRegistrar")
|
||||
.build());
|
||||
// cat.みんな
|
||||
createTld("xn--q9jyb4c");
|
||||
|
@ -294,7 +294,7 @@ class RdapDomainSearchActionTest extends RdapSearchActionTestCase<RdapDomainSear
|
|||
registrar)
|
||||
.asBuilder()
|
||||
.setCreationTimeForTest(clock.nowUtc().minusYears(3))
|
||||
.setCreationClientId("foo")
|
||||
.setCreationClientId("TheRegistrar")
|
||||
.build());
|
||||
// cat.1.test
|
||||
createTld("1.test");
|
||||
|
@ -334,7 +334,7 @@ class RdapDomainSearchActionTest extends RdapSearchActionTestCase<RdapDomainSear
|
|||
.asBuilder()
|
||||
.setSubordinateHosts(ImmutableSet.of("ns1.cat.1.test"))
|
||||
.setCreationTimeForTest(clock.nowUtc().minusYears(3))
|
||||
.setCreationClientId("foo")
|
||||
.setCreationClientId("TheRegistrar")
|
||||
.build());
|
||||
|
||||
persistResource(makeRegistrar("otherregistrar", "other", Registrar.State.ACTIVE));
|
||||
|
@ -430,7 +430,7 @@ class RdapDomainSearchActionTest extends RdapSearchActionTestCase<RdapDomainSear
|
|||
.asBuilder()
|
||||
.setNameservers(hostKeys)
|
||||
.setCreationTimeForTest(clock.nowUtc().minusYears(3))
|
||||
.setCreationClientId("foo");
|
||||
.setCreationClientId("TheRegistrar");
|
||||
if (domainName.equals(mainDomainName)) {
|
||||
builder.setSubordinateHosts(subordinateHostnamesBuilder.build());
|
||||
}
|
||||
|
|
|
@ -191,7 +191,6 @@ class RdapJsonFormatterTest {
|
|||
hostResourceIpv6,
|
||||
registrar)
|
||||
.asBuilder()
|
||||
.setCreationClientId("foo")
|
||||
.setCreationTimeForTest(clock.nowUtc().minusMonths(4))
|
||||
.setLastEppUpdateTime(clock.nowUtc().minusMonths(3))
|
||||
.build());
|
||||
|
@ -206,7 +205,6 @@ class RdapJsonFormatterTest {
|
|||
null,
|
||||
registrar)
|
||||
.asBuilder()
|
||||
.setCreationClientId("foo")
|
||||
.setCreationTimeForTest(clock.nowUtc())
|
||||
.setLastEppUpdateTime(null)
|
||||
.build());
|
||||
|
|
|
@ -313,7 +313,7 @@ class RdapTestHelper {
|
|||
}
|
||||
builder.append(
|
||||
String.format(
|
||||
"Different: %s -> %s\ninstead of %s\n\n",
|
||||
"Actual: %s -> %s\nExpected: %s\n\n",
|
||||
name, jsonifyAndIndent(actual), jsonifyAndIndent(expected)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -398,7 +398,7 @@ public final class FullFieldsTestEntityHelper {
|
|||
.setPeriod(period)
|
||||
.setXmlBytes("<xml></xml>".getBytes(UTF_8))
|
||||
.setModificationTime(modificationTime)
|
||||
.setClientId("foo")
|
||||
.setClientId(resource.getPersistedCurrentSponsorClientId())
|
||||
.setTrid(Trid.create("ABC-123", "server-trid"))
|
||||
.setBySuperuser(false)
|
||||
.setReason(reason)
|
||||
|
|
|
@ -22,12 +22,14 @@ import static google.registry.testing.FullFieldsTestEntityHelper.makeHistoryEntr
|
|||
import google.registry.model.domain.DomainBase;
|
||||
import google.registry.model.domain.Period;
|
||||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.FakeClock;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import org.joda.time.DateTime;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Unit tests for {@link GetClaimsListCommand}. */
|
||||
@DualDatabaseTest
|
||||
class GetHistoryEntriesCommandTest extends CommandTestCase<GetHistoryEntriesCommand> {
|
||||
|
||||
private final FakeClock clock = new FakeClock(DateTime.parse("2000-01-01T00:00:00Z"));
|
||||
|
@ -40,7 +42,7 @@ class GetHistoryEntriesCommandTest extends CommandTestCase<GetHistoryEntriesComm
|
|||
domain = persistActiveDomain("example.tld");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testSuccess_works() throws Exception {
|
||||
persistResource(
|
||||
makeHistoryEntry(
|
||||
|
@ -51,7 +53,7 @@ class GetHistoryEntriesCommandTest extends CommandTestCase<GetHistoryEntriesComm
|
|||
clock.nowUtc()));
|
||||
runCommand("--id=example.tld", "--type=DOMAIN");
|
||||
assertStdoutIs(
|
||||
"Client: foo\n"
|
||||
"Client: TheRegistrar\n"
|
||||
+ "Time: 2000-01-01T00:00:00.000Z\n"
|
||||
+ "Client TRID: ABC-123\n"
|
||||
+ "Server TRID: server-trid\n"
|
||||
|
@ -60,7 +62,57 @@ class GetHistoryEntriesCommandTest extends CommandTestCase<GetHistoryEntriesComm
|
|||
+ "\n");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testSuccess_nothingBefore() throws Exception {
|
||||
persistResource(
|
||||
makeHistoryEntry(
|
||||
domain,
|
||||
HistoryEntry.Type.DOMAIN_CREATE,
|
||||
Period.create(1, Period.Unit.YEARS),
|
||||
"created",
|
||||
clock.nowUtc()));
|
||||
runCommand("--before", clock.nowUtc().minusMinutes(1).toString());
|
||||
assertStdoutIs("");
|
||||
}
|
||||
|
||||
@TestOfyAndSql
|
||||
void testSuccess_nothingAfter() throws Exception {
|
||||
persistResource(
|
||||
makeHistoryEntry(
|
||||
domain,
|
||||
HistoryEntry.Type.DOMAIN_CREATE,
|
||||
Period.create(1, Period.Unit.YEARS),
|
||||
"created",
|
||||
clock.nowUtc()));
|
||||
runCommand("--after", clock.nowUtc().plusMinutes(1).toString());
|
||||
assertStdoutIs("");
|
||||
}
|
||||
|
||||
@TestOfyAndSql
|
||||
void testSuccess_withinRange() throws Exception {
|
||||
persistResource(
|
||||
makeHistoryEntry(
|
||||
domain,
|
||||
HistoryEntry.Type.DOMAIN_CREATE,
|
||||
Period.create(1, Period.Unit.YEARS),
|
||||
"created",
|
||||
clock.nowUtc()));
|
||||
runCommand(
|
||||
"--after",
|
||||
clock.nowUtc().minusMinutes(1).toString(),
|
||||
"--before",
|
||||
clock.nowUtc().plusMinutes(1).toString());
|
||||
assertStdoutIs(
|
||||
"Client: TheRegistrar\n"
|
||||
+ "Time: 2000-01-01T00:00:00.000Z\n"
|
||||
+ "Client TRID: ABC-123\n"
|
||||
+ "Server TRID: server-trid\n"
|
||||
+ "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n"
|
||||
+ "<xml/>\n"
|
||||
+ "\n");
|
||||
}
|
||||
|
||||
@TestOfyAndSql
|
||||
void testSuccess_noTrid() throws Exception {
|
||||
persistResource(
|
||||
makeHistoryEntry(
|
||||
|
@ -74,7 +126,7 @@ class GetHistoryEntriesCommandTest extends CommandTestCase<GetHistoryEntriesComm
|
|||
.build());
|
||||
runCommand("--id=example.tld", "--type=DOMAIN");
|
||||
assertStdoutIs(
|
||||
"Client: foo\n"
|
||||
"Client: TheRegistrar\n"
|
||||
+ "Time: 2000-01-01T00:00:00.000Z\n"
|
||||
+ "Client TRID: null\n"
|
||||
+ "Server TRID: null\n"
|
||||
|
|
|
@ -37,15 +37,17 @@ import google.registry.model.registrar.Registrar;
|
|||
import google.registry.model.reporting.HistoryEntry;
|
||||
import google.registry.schema.domain.RegistryLock;
|
||||
import google.registry.testing.DeterministicStringGenerator;
|
||||
import google.registry.testing.DualDatabaseTest;
|
||||
import google.registry.testing.TestOfyAndSql;
|
||||
import google.registry.tools.CommandTestCase;
|
||||
import google.registry.util.StringGenerator.Alphabets;
|
||||
import java.util.Optional;
|
||||
import org.joda.time.DateTime;
|
||||
import org.joda.time.Duration;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/** Unit tests for {@link BackfillRegistryLocksCommand}. */
|
||||
@DualDatabaseTest
|
||||
class BackfillRegistryLocksCommandTest extends CommandTestCase<BackfillRegistryLocksCommand> {
|
||||
|
||||
@BeforeEach
|
||||
|
@ -57,7 +59,7 @@ class BackfillRegistryLocksCommandTest extends CommandTestCase<BackfillRegistryL
|
|||
command.stringGenerator = new DeterministicStringGenerator(Alphabets.BASE_58);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testSimpleBackfill() throws Exception {
|
||||
DomainBase domain = persistLockedDomain("example.tld");
|
||||
Truth8.assertThat(getMostRecentRegistryLockByRepoId(domain.getRepoId())).isEmpty();
|
||||
|
@ -69,7 +71,7 @@ class BackfillRegistryLocksCommandTest extends CommandTestCase<BackfillRegistryL
|
|||
Truth8.assertThat(lockOptional.get().getLockCompletionTimestamp()).isPresent();
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testBackfill_onlyLockedDomains() throws Exception {
|
||||
DomainBase neverLockedDomain = persistActiveDomain("neverlocked.tld");
|
||||
DomainBase previouslyLockedDomain = persistLockedDomain("unlocked.tld");
|
||||
|
@ -89,7 +91,7 @@ class BackfillRegistryLocksCommandTest extends CommandTestCase<BackfillRegistryL
|
|||
assertThat(Iterables.getOnlyElement(locks).getDomainName()).isEqualTo("locked.tld");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testBackfill_skipsDeletedDomains() throws Exception {
|
||||
DomainBase domain = persistDeletedDomain("example.tld", fakeClock.nowUtc());
|
||||
persistResource(domain.asBuilder().setStatusValues(REGISTRY_LOCK_STATUSES).build());
|
||||
|
@ -98,7 +100,7 @@ class BackfillRegistryLocksCommandTest extends CommandTestCase<BackfillRegistryL
|
|||
Truth8.assertThat(getMostRecentRegistryLockByRepoId(domain.getRepoId())).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testBackfill_skipsDomains_ifLockAlreadyExists() throws Exception {
|
||||
DomainBase domain = persistLockedDomain("example.tld");
|
||||
|
||||
|
@ -123,7 +125,7 @@ class BackfillRegistryLocksCommandTest extends CommandTestCase<BackfillRegistryL
|
|||
.isEqualTo(previousLock.getLockCompletionTimestamp());
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testBackfill_usesUrsTime_ifExists() throws Exception {
|
||||
DateTime ursTime = fakeClock.nowUtc();
|
||||
DomainBase ursDomain = persistLockedDomain("urs.tld");
|
||||
|
@ -151,7 +153,7 @@ class BackfillRegistryLocksCommandTest extends CommandTestCase<BackfillRegistryL
|
|||
assertThat(nonUrsLock.getLockCompletionTimestamp()).hasValue(fakeClock.nowUtc());
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestOfyAndSql
|
||||
void testFailure_mustProvideDomainRoids() {
|
||||
assertThat(assertThrows(IllegalArgumentException.class, this::runCommandForced))
|
||||
.hasMessageThat()
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
"events": [
|
||||
{
|
||||
"eventAction": "registration",
|
||||
"eventActor": "foo",
|
||||
"eventActor": "TheRegistrar",
|
||||
"eventDate": "1997-01-01T00:00:00.000Z"
|
||||
},
|
||||
{
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
"events": [
|
||||
{
|
||||
"eventAction": "registration",
|
||||
"eventActor": "foo",
|
||||
"eventActor": "TheRegistrar",
|
||||
"eventDate": "1997-01-01T00:00:00.000Z"
|
||||
},
|
||||
{
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
"events": [
|
||||
{
|
||||
"eventAction": "registration",
|
||||
"eventActor": "foo",
|
||||
"eventActor": "TheRegistrar",
|
||||
"eventDate": "1997-01-01T00:00:00.000Z"
|
||||
},
|
||||
{
|
||||
|
@ -47,7 +47,7 @@
|
|||
},
|
||||
{
|
||||
"eventAction": "deletion",
|
||||
"eventActor": "foo",
|
||||
"eventActor": "evilregistrar",
|
||||
"eventDate": "1999-07-01T00:00:00.000Z"
|
||||
},
|
||||
{
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
"events": [
|
||||
{
|
||||
"eventAction": "registration",
|
||||
"eventActor": "foo",
|
||||
"eventActor": "TheRegistrar",
|
||||
"eventDate": "1997-01-01T00:00:00.000Z"
|
||||
},
|
||||
{
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
"events": [
|
||||
{
|
||||
"eventAction": "registration",
|
||||
"eventActor": "foo",
|
||||
"eventActor": "TheRegistrar",
|
||||
"eventDate": "1997-01-01T00:00:00.000Z"
|
||||
},
|
||||
{
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
"events": [
|
||||
{
|
||||
"eventAction": "registration",
|
||||
"eventActor": "foo",
|
||||
"eventActor": "TheRegistrar",
|
||||
"eventDate": "1997-01-01T00:00:00.000Z"
|
||||
},
|
||||
{
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
"events": [
|
||||
{
|
||||
"eventAction": "registration",
|
||||
"eventActor": "foo",
|
||||
"eventActor": "unicoderegistrar",
|
||||
"eventDate": "1999-09-01T00:00:00.000Z"
|
||||
},
|
||||
{
|
||||
|
@ -44,7 +44,7 @@
|
|||
},
|
||||
{
|
||||
"eventAction": "transfer",
|
||||
"eventActor": "foo",
|
||||
"eventActor": "unicoderegistrar",
|
||||
"eventDate": "1999-12-01T00:00:00.000Z"
|
||||
},
|
||||
{
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
"events": [
|
||||
{
|
||||
"eventAction": "registration",
|
||||
"eventActor": "foo",
|
||||
"eventActor": "unicoderegistrar",
|
||||
"eventDate": "1999-09-01T00:00:00.000Z"
|
||||
},
|
||||
{
|
||||
|
@ -44,7 +44,7 @@
|
|||
},
|
||||
{
|
||||
"eventAction": "transfer",
|
||||
"eventActor": "foo",
|
||||
"eventActor": "unicoderegistrar",
|
||||
"eventDate": "1999-12-01T00:00:00.000Z"
|
||||
},
|
||||
{
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
"events": [
|
||||
{
|
||||
"eventAction": "registration",
|
||||
"eventActor": "foo",
|
||||
"eventActor": "unicoderegistrar",
|
||||
"eventDate": "2000-01-01T00:00:00.000Z"
|
||||
},
|
||||
{
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
"events": [
|
||||
{
|
||||
"eventAction": "registration",
|
||||
"eventActor": "foo",
|
||||
"eventActor": "TheRegistrar",
|
||||
"eventDate": "1999-01-01T00:00:00.000Z"
|
||||
},
|
||||
{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue