From 8293e1e8079502b18afd797fbab62b08347b490b Mon Sep 17 00:00:00 2001 From: sarahcaseybot Date: Fri, 14 May 2021 16:13:05 -0400 Subject: [PATCH] Stop writing PremiumList to Datastore (#1160) * Stop writing PremiumList to Datastore * Fix formatting * Format fix * Rename the DAO * Fix merge conflicts and add comment --- .../export/ExportPremiumTermsAction.java | 7 +- .../registry/model/OteAccountBuilder.java | 4 +- .../StaticPremiumListPricingEngine.java | 5 +- .../model/registry/label/PremiumList.java | 4 +- .../label/PremiumListDatastoreDao.java | 375 ------------------ .../registry/label/PremiumListDualDao.java | 140 ------- ...iumListSqlDao.java => PremiumListDao.java} | 35 +- .../tools/ComparePremiumListsCommand.java | 105 ----- .../CreateOrUpdatePremiumListCommand.java | 4 +- .../tools/CreateOrUpdateTldCommand.java | 4 +- .../tools/CreatePremiumListCommand.java | 4 +- .../tools/DeletePremiumListCommand.java | 8 +- .../registry/tools/GetPremiumListCommand.java | 6 +- .../google/registry/tools/RegistryTool.java | 1 - .../tools/UpdatePremiumListCommand.java | 6 +- .../tools/server/CreatePremiumListAction.java | 8 +- .../tools/server/ListPremiumListsAction.java | 4 +- .../tools/server/UpdatePremiumListAction.java | 6 +- .../export/ExportPremiumTermsActionTest.java | 6 +- .../registry/model/registry/RegistryTest.java | 4 +- .../label/PremiumListDatastoreDaoTest.java | 326 --------------- .../label/PremiumListDualDaoTest.java | 111 ------ .../model/registry/label/PremiumListTest.java | 5 +- .../integration/SqlIntegrationTestSuite.java | 4 +- ...qlDaoTest.java => PremiumListDaoTest.java} | 62 ++- .../registry/testing/DatabaseHelper.java | 39 +- .../registry/testing/TestCacheExtension.java | 15 +- .../tools/ComparePremiumListsCommandTest.java | 86 ---- .../tools/CreateDomainCommandTest.java | 4 +- .../tools/CreatePremiumListCommandTest.java | 6 +- .../tools/DeletePremiumListCommandTest.java | 6 +- .../tools/UpdatePremiumListCommandTest.java | 4 +- .../server/CreatePremiumListActionTest.java | 13 +- .../server/UpdatePremiumListActionTest.java | 20 +- 34 files changed, 142 insertions(+), 1295 deletions(-) delete mode 100644 core/src/main/java/google/registry/model/registry/label/PremiumListDatastoreDao.java delete mode 100644 core/src/main/java/google/registry/model/registry/label/PremiumListDualDao.java rename core/src/main/java/google/registry/schema/tld/{PremiumListSqlDao.java => PremiumListDao.java} (87%) delete mode 100644 core/src/main/java/google/registry/tools/ComparePremiumListsCommand.java delete mode 100644 core/src/test/java/google/registry/model/registry/label/PremiumListDatastoreDaoTest.java delete mode 100644 core/src/test/java/google/registry/model/registry/label/PremiumListDualDaoTest.java rename core/src/test/java/google/registry/schema/tld/{PremiumListSqlDaoTest.java => PremiumListDaoTest.java} (78%) delete mode 100644 core/src/test/java/google/registry/tools/ComparePremiumListsCommandTest.java diff --git a/core/src/main/java/google/registry/export/ExportPremiumTermsAction.java b/core/src/main/java/google/registry/export/ExportPremiumTermsAction.java index a285e3029..0d64f8991 100644 --- a/core/src/main/java/google/registry/export/ExportPremiumTermsAction.java +++ b/core/src/main/java/google/registry/export/ExportPremiumTermsAction.java @@ -32,12 +32,12 @@ import com.google.common.net.MediaType; import google.registry.config.RegistryConfig.Config; import google.registry.model.registry.Registry; import google.registry.model.registry.label.PremiumList.PremiumListEntry; -import google.registry.model.registry.label.PremiumListDualDao; import google.registry.request.Action; import google.registry.request.Parameter; import google.registry.request.RequestParameters; import google.registry.request.Response; import google.registry.request.auth.Auth; +import google.registry.schema.tld.PremiumListDao; import google.registry.storage.drive.DriveConnection; import java.io.IOException; import java.util.Optional; @@ -139,9 +139,10 @@ public class ExportPremiumTermsAction implements Runnable { private String getFormattedPremiumTerms(Registry registry) { String premiumListName = registry.getPremiumList().getName(); checkState( - PremiumListDualDao.exists(premiumListName), "Could not load premium list for " + tld); + PremiumListDao.getLatestRevision(premiumListName).isPresent(), + "Could not load premium list for " + tld); SortedSet premiumTerms = - Streams.stream(PremiumListDualDao.loadAllPremiumListEntries(premiumListName)) + Streams.stream(PremiumListDao.loadAllPremiumListEntries(premiumListName)) .map(PremiumListEntry::toString) .collect(ImmutableSortedSet.toImmutableSortedSet(String::compareTo)); diff --git a/core/src/main/java/google/registry/model/OteAccountBuilder.java b/core/src/main/java/google/registry/model/OteAccountBuilder.java index 23ab6de5b..86574c110 100644 --- a/core/src/main/java/google/registry/model/OteAccountBuilder.java +++ b/core/src/main/java/google/registry/model/OteAccountBuilder.java @@ -39,8 +39,8 @@ import google.registry.model.registrar.RegistrarContact; import google.registry.model.registry.Registry; import google.registry.model.registry.Registry.TldState; import google.registry.model.registry.label.PremiumList; -import google.registry.model.registry.label.PremiumListDualDao; import google.registry.persistence.VKey; +import google.registry.schema.tld.PremiumListDao; import google.registry.util.CidrAddressBlock; import java.util.Collection; import java.util.Optional; @@ -295,7 +295,7 @@ public final class OteAccountBuilder { boolean isEarlyAccess, int roidSuffix) { String tldNameAlphaNumerical = tldName.replaceAll("[^a-z0-9]", ""); - Optional premiumList = PremiumListDualDao.getLatestRevision(DEFAULT_PREMIUM_LIST); + Optional premiumList = PremiumListDao.getLatestRevision(DEFAULT_PREMIUM_LIST); checkState(premiumList.isPresent(), "Couldn't find premium list %s.", DEFAULT_PREMIUM_LIST); Registry.Builder builder = new Registry.Builder() diff --git a/core/src/main/java/google/registry/model/pricing/StaticPremiumListPricingEngine.java b/core/src/main/java/google/registry/model/pricing/StaticPremiumListPricingEngine.java index c94d73492..529617101 100644 --- a/core/src/main/java/google/registry/model/pricing/StaticPremiumListPricingEngine.java +++ b/core/src/main/java/google/registry/model/pricing/StaticPremiumListPricingEngine.java @@ -19,7 +19,7 @@ import static google.registry.util.DomainNameUtils.getTldFromDomainName; import com.google.common.net.InternetDomainName; import google.registry.model.registry.Registry; -import google.registry.model.registry.label.PremiumListDualDao; +import google.registry.schema.tld.PremiumListDao; import java.util.Optional; import javax.inject.Inject; import org.joda.money.Money; @@ -38,7 +38,8 @@ public final class StaticPremiumListPricingEngine implements PremiumPricingEngin String tld = getTldFromDomainName(fullyQualifiedDomainName); String label = InternetDomainName.from(fullyQualifiedDomainName).parts().get(0); Registry registry = Registry.get(checkNotNull(tld, "tld")); - Optional premiumPrice = PremiumListDualDao.getPremiumPrice(label, registry); + Optional premiumPrice = + PremiumListDao.getPremiumPrice(registry.getPremiumList().getName(), label); return DomainPrices.create( premiumPrice.isPresent(), premiumPrice.orElse(registry.getStandardCreateCost()), diff --git a/core/src/main/java/google/registry/model/registry/label/PremiumList.java b/core/src/main/java/google/registry/model/registry/label/PremiumList.java index 832e24133..09c05b9ee 100644 --- a/core/src/main/java/google/registry/model/registry/label/PremiumList.java +++ b/core/src/main/java/google/registry/model/registry/label/PremiumList.java @@ -36,7 +36,7 @@ import google.registry.model.annotations.ReportedOn; import google.registry.model.registry.Registry; import google.registry.schema.replay.DatastoreOnlyEntity; import google.registry.schema.replay.NonReplicatedEntity; -import google.registry.schema.tld.PremiumListSqlDao; +import google.registry.schema.tld.PremiumListDao; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.math.BigDecimal; @@ -173,7 +173,7 @@ public final class PremiumList extends BaseDomainLabelListNote that this is lazily loaded and thus will throw a {@link LazyInitializationException} if * used outside the transaction in which the given entity was loaded. You generally should not be * using this anyway as it's inefficient to load all of the PremiumEntry rows if you don't need - * them. To check prices, use {@link PremiumListSqlDao#getPremiumPrice} instead. + * them. To check prices, use {@link PremiumListDao#getPremiumPrice} instead. */ @Nullable public ImmutableMap getLabelsToPrices() { diff --git a/core/src/main/java/google/registry/model/registry/label/PremiumListDatastoreDao.java b/core/src/main/java/google/registry/model/registry/label/PremiumListDatastoreDao.java deleted file mode 100644 index a6fcc2be0..000000000 --- a/core/src/main/java/google/registry/model/registry/label/PremiumListDatastoreDao.java +++ /dev/null @@ -1,375 +0,0 @@ -// Copyright 2021 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.registry.label; - -import static com.google.common.base.Preconditions.checkState; -import static com.google.common.collect.ImmutableSet.toImmutableSet; -import static com.google.common.collect.Iterables.partition; -import static google.registry.config.RegistryConfig.getDomainLabelListCacheDuration; -import static google.registry.config.RegistryConfig.getSingletonCachePersistDuration; -import static google.registry.config.RegistryConfig.getStaticPremiumListMaxCachedEntries; -import static google.registry.model.common.EntityGroupRoot.getCrossTldKey; -import static google.registry.model.ofy.ObjectifyService.auditedOfy; -import static google.registry.model.registry.label.DomainLabelMetrics.PremiumListCheckOutcome.BLOOM_FILTER_NEGATIVE; -import static google.registry.model.registry.label.DomainLabelMetrics.PremiumListCheckOutcome.CACHED_NEGATIVE; -import static google.registry.model.registry.label.DomainLabelMetrics.PremiumListCheckOutcome.CACHED_POSITIVE; -import static google.registry.model.registry.label.DomainLabelMetrics.PremiumListCheckOutcome.UNCACHED_NEGATIVE; -import static google.registry.model.registry.label.DomainLabelMetrics.PremiumListCheckOutcome.UNCACHED_POSITIVE; -import static google.registry.persistence.transaction.TransactionManagerFactory.ofyTm; -import static google.registry.persistence.transaction.TransactionManagerFactory.tm; -import static org.joda.time.DateTimeZone.UTC; - -import com.google.auto.value.AutoValue; -import com.google.common.annotations.VisibleForTesting; -import com.google.common.cache.CacheBuilder; -import com.google.common.cache.CacheLoader; -import com.google.common.cache.CacheLoader.InvalidCacheLoadException; -import com.google.common.cache.LoadingCache; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Streams; -import com.googlecode.objectify.Key; -import google.registry.model.registry.label.DomainLabelMetrics.PremiumListCheckOutcome; -import google.registry.model.registry.label.PremiumList.PremiumListEntry; -import google.registry.model.registry.label.PremiumList.PremiumListRevision; -import google.registry.persistence.VKey; -import google.registry.util.NonFinalForTesting; -import java.util.List; -import java.util.Objects; -import java.util.Optional; -import java.util.concurrent.ExecutionException; -import org.joda.money.Money; -import org.joda.time.DateTime; -import org.joda.time.Duration; - -/** - * DAO for {@link PremiumList} objects stored in Datastore. - * - *

This class handles both the mapping from string to Datastore-level PremiumList objects as well - * as the mapping from PremiumList objects to the contents of those premium lists in the Datastore - * world. Specifically, this deals with retrieving the most recent revision for a given list and - * retrieving (or writing/deleting) all entries associated with that particular revision. The {@link - * PremiumList} object itself, in the Datastore world, does not store the premium pricing data. - */ -public class PremiumListDatastoreDao { - - /** The number of premium list entry entities that are created and deleted per batch. */ - private static final int TRANSACTION_BATCH_SIZE = 200; - - /** - * In-memory cache for premium lists. - * - *

This is cached for a shorter duration because we need to periodically reload this entity to - * check if a new revision has been published, and if so, then use that. - * - *

We also cache the absence of premium lists with a given name to avoid unnecessary pointless - * lookups. Note that this cache is only applicable to PremiumList objects stored in Datastore. - */ - @NonFinalForTesting - static LoadingCache> premiumListCache = - createPremiumListCache(getDomainLabelListCacheDuration()); - - @VisibleForTesting - public static void setPremiumListCacheForTest(Optional expiry) { - Duration effectiveExpiry = expiry.orElse(getSingletonCachePersistDuration()); - premiumListCache = createPremiumListCache(effectiveExpiry); - } - - @VisibleForTesting - public static LoadingCache> createPremiumListCache( - Duration cachePersistDuration) { - return CacheBuilder.newBuilder() - .expireAfterWrite(java.time.Duration.ofMillis(cachePersistDuration.getMillis())) - .build( - new CacheLoader>() { - @Override - public Optional load(final String name) { - return tm().doTransactionless(() -> getLatestRevisionUncached(name)); - } - }); - } - - /** - * In-memory cache for {@link PremiumListRevision}s, used for retrieving Bloom filters quickly. - * - *

This is cached for a long duration (essentially indefinitely) because a given {@link - * PremiumListRevision} is immutable and cannot ever be changed once created, so its cache need - * not ever expire. - */ - static final LoadingCache, PremiumListRevision> - premiumListRevisionsCache = - CacheBuilder.newBuilder() - .expireAfterWrite( - java.time.Duration.ofMillis(getSingletonCachePersistDuration().getMillis())) - .build( - new CacheLoader, PremiumListRevision>() { - @Override - public PremiumListRevision load(final Key revisionKey) { - return ofyTm() - .doTransactionless(() -> auditedOfy().load().key(revisionKey).now()); - } - }); - - /** - * In-memory cache for {@link PremiumListEntry}s for a given label and {@link PremiumListRevision} - * - *

Because the PremiumList itself makes up part of the PremiumListRevision's key, this is - * specific to a given premium list. Premium list entries might not be present, as indicated by - * the Optional wrapper, and we want to cache that as well. - * - *

This is cached for a long duration (essentially indefinitely) because a given {@link - * PremiumListRevision} and its child {@link PremiumListEntry}s are immutable and cannot ever be - * changed once created, so the cache need not ever expire. - * - *

A maximum size is set here on the cache because it can potentially grow too big to fit in - * memory if there are a large number of distinct premium list entries being queried (both those - * that exist, as well as those that might exist according to the Bloom filter, must be cached). - * The entries judged least likely to be accessed again will be evicted first. - */ - @NonFinalForTesting - static LoadingCache, Optional> premiumListEntriesCache = - createPremiumListEntriesCache(getSingletonCachePersistDuration()); - - @VisibleForTesting - public static void setPremiumListEntriesCacheForTest(Optional expiry) { - Duration effectiveExpiry = expiry.orElse(getSingletonCachePersistDuration()); - premiumListEntriesCache = createPremiumListEntriesCache(effectiveExpiry); - } - - @VisibleForTesting - static LoadingCache, Optional> - createPremiumListEntriesCache(Duration cachePersistDuration) { - return CacheBuilder.newBuilder() - .expireAfterWrite(java.time.Duration.ofMillis(cachePersistDuration.getMillis())) - .maximumSize(getStaticPremiumListMaxCachedEntries()) - .build( - new CacheLoader, Optional>() { - @Override - public Optional load(final Key entryKey) { - return ofyTm() - .doTransactionless( - () -> Optional.ofNullable(auditedOfy().load().key(entryKey).now())); - } - }); - } - - public static Optional getLatestRevision(String name) { - return premiumListCache.getUnchecked(name); - } - - /** - * Returns the premium price for the specified list, label, and TLD, or absent if the label is not - * premium. - */ - public static Optional getPremiumPrice(String premiumListName, String label, String tld) { - DateTime startTime = DateTime.now(UTC); - Optional maybePremumList = getLatestRevision(premiumListName); - if (!maybePremumList.isPresent()) { - return Optional.empty(); - } - PremiumList premiumList = maybePremumList.get(); - // If we're dealing with a list from SQL, reload from Datastore if necessary - if (premiumList.getRevisionKey() == null) { - Optional fromDatastore = getLatestRevision(premiumList.getName()); - if (fromDatastore.isPresent()) { - premiumList = fromDatastore.get(); - } else { - return Optional.empty(); - } - } - PremiumListRevision revision; - try { - revision = premiumListRevisionsCache.get(premiumList.getRevisionKey()); - } catch (InvalidCacheLoadException | ExecutionException e) { - throw new RuntimeException( - "Could not load premium list revision " + premiumList.getRevisionKey(), e); - } - checkState( - revision.getProbablePremiumLabels() != null, - "Probable premium labels Bloom filter is null on revision '%s'", - premiumList.getRevisionKey()); - - CheckResults checkResults = checkStatus(revision, label); - DomainLabelMetrics.recordPremiumListCheckOutcome( - tld, - premiumList.getName(), - checkResults.checkOutcome(), - DateTime.now(UTC).getMillis() - startTime.getMillis()); - - return checkResults.premiumPrice(); - } - - /** - * Persists a new or updated PremiumList object and its descendant entities to Datastore. - * - *

The flow here is: save the new premium list entries parented on that revision entity, - * save/update the PremiumList, and then delete the old premium list entries associated with the - * old revision. - * - *

This is the only valid way to save these kinds of entities! - */ - public static PremiumList save(String name, List inputData) { - PremiumList premiumList = new PremiumList.Builder().setName(name).build(); - ImmutableMap premiumListEntries = premiumList.parse(inputData); - final Optional oldPremiumList = getLatestRevisionUncached(premiumList.getName()); - - // Create the new revision (with its Bloom filter) and parent the entries on it. - final PremiumListRevision newRevision = - PremiumListRevision.create(premiumList, premiumListEntries.keySet()); - final Key newRevisionKey = Key.create(newRevision); - ImmutableSet parentedEntries = - parentPremiumListEntriesOnRevision(premiumListEntries.values(), newRevisionKey); - - // Save the new child entities in a series of transactions. - for (final List batch : partition(parentedEntries, TRANSACTION_BATCH_SIZE)) { - ofyTm().transactNew(() -> auditedOfy().save().entities(batch)); - } - - // Save the new PremiumList and revision itself. - return ofyTm() - .transactNew( - () -> { - DateTime now = ofyTm().getTransactionTime(); - // Assert that the premium list hasn't been changed since we started this process. - Key key = - Key.create(getCrossTldKey(), PremiumList.class, premiumList.getName()); - Optional existing = - ofyTm().loadByKeyIfPresent(VKey.createOfy(PremiumList.class, key)); - checkOfyFieldsEqual(existing, oldPremiumList); - PremiumList newList = - premiumList - .asBuilder() - .setLastUpdateTime(now) - .setCreationTime( - oldPremiumList.isPresent() ? oldPremiumList.get().creationTime : now) - .setRevision(newRevisionKey) - .build(); - auditedOfy().save().entities(newList, newRevision); - premiumListCache.invalidate(premiumList.getName()); - return newList; - }); - } - - public static void delete(PremiumList premiumList) { - ofyTm().transactNew(() -> auditedOfy().delete().entity(premiumList)); - if (premiumList.getRevisionKey() == null) { - return; - } - for (final List> batch : - partition( - auditedOfy() - .load() - .type(PremiumListEntry.class) - .ancestor(premiumList.revisionKey) - .keys(), - TRANSACTION_BATCH_SIZE)) { - ofyTm().transactNew(() -> auditedOfy().delete().keys(batch)); - batch.forEach(premiumListEntriesCache::invalidate); - } - ofyTm().transactNew(() -> auditedOfy().delete().key(premiumList.getRevisionKey())); - premiumListCache.invalidate(premiumList.getName()); - premiumListRevisionsCache.invalidate(premiumList.getRevisionKey()); - } - - /** Re-parents the given {@link PremiumListEntry}s on the given {@link PremiumListRevision}. */ - @VisibleForTesting - public static ImmutableSet parentPremiumListEntriesOnRevision( - Iterable entries, final Key revisionKey) { - return Streams.stream(entries) - .map((PremiumListEntry entry) -> entry.asBuilder().setParent(revisionKey).build()) - .collect(toImmutableSet()); - } - - /** - * Returns all {@link PremiumListEntry PremiumListEntries} in the given {@code premiumList}. - * - *

This is an expensive operation and should only be used when the entire list is required. - */ - public static Iterable loadPremiumListEntriesUncached(PremiumList premiumList) { - return auditedOfy() - .load() - .type(PremiumListEntry.class) - .ancestor(premiumList.revisionKey) - .iterable(); - } - - private static Optional getLatestRevisionUncached(String name) { - return Optional.ofNullable( - auditedOfy().load().key(Key.create(getCrossTldKey(), PremiumList.class, name)).now()); - } - - private static void checkOfyFieldsEqual( - Optional oneOptional, Optional twoOptional) { - if (!oneOptional.isPresent()) { - checkState(!twoOptional.isPresent(), "Premium list concurrently deleted"); - return; - } else { - checkState(twoOptional.isPresent(), "Premium list concurrently deleted"); - } - PremiumList one = oneOptional.get(); - PremiumList two = twoOptional.get(); - checkState( - Objects.equals(one.revisionKey, two.revisionKey), - "Premium list revision key concurrently edited"); - checkState(Objects.equals(one.name, two.name), "Premium list name concurrently edited"); - checkState(Objects.equals(one.parent, two.parent), "Premium list parent concurrently edited"); - checkState( - Objects.equals(one.creationTime, two.creationTime), - "Premium list creation time concurrently edited"); - } - - private static CheckResults checkStatus(PremiumListRevision premiumListRevision, String label) { - if (!premiumListRevision.getProbablePremiumLabels().mightContain(label)) { - return CheckResults.create(BLOOM_FILTER_NEGATIVE, Optional.empty()); - } - - Key entryKey = - Key.create(Key.create(premiumListRevision), PremiumListEntry.class, label); - try { - // getIfPresent() returns null if the key is not in the cache - Optional entry = premiumListEntriesCache.getIfPresent(entryKey); - if (entry != null) { - if (entry.isPresent()) { - return CheckResults.create(CACHED_POSITIVE, Optional.of(entry.get().getValue())); - } else { - return CheckResults.create(CACHED_NEGATIVE, Optional.empty()); - } - } - - entry = premiumListEntriesCache.get(entryKey); - if (entry.isPresent()) { - return CheckResults.create(UNCACHED_POSITIVE, Optional.of(entry.get().getValue())); - } else { - return CheckResults.create(UNCACHED_NEGATIVE, Optional.empty()); - } - } catch (InvalidCacheLoadException | ExecutionException e) { - throw new RuntimeException("Could not load premium list entry " + entryKey, e); - } - } - - /** Value type class used by {@link #checkStatus} to return the results of a premiumness check. */ - @AutoValue - abstract static class CheckResults { - static CheckResults create(PremiumListCheckOutcome checkOutcome, Optional premiumPrice) { - return new AutoValue_PremiumListDatastoreDao_CheckResults(checkOutcome, premiumPrice); - } - - abstract PremiumListCheckOutcome checkOutcome(); - - abstract Optional premiumPrice(); - } - - private PremiumListDatastoreDao() {} -} diff --git a/core/src/main/java/google/registry/model/registry/label/PremiumListDualDao.java b/core/src/main/java/google/registry/model/registry/label/PremiumListDualDao.java deleted file mode 100644 index dcf0d4fe9..000000000 --- a/core/src/main/java/google/registry/model/registry/label/PremiumListDualDao.java +++ /dev/null @@ -1,140 +0,0 @@ -// Copyright 2021 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.registry.label; - -import static com.google.common.base.Preconditions.checkState; -import static com.google.common.collect.ImmutableList.toImmutableList; -import static google.registry.model.DatabaseMigrationUtils.suppressExceptionUnlessInTest; - -import com.google.common.collect.Streams; -import google.registry.model.registry.Registry; -import google.registry.model.registry.label.PremiumList.PremiumListEntry; -import google.registry.schema.tld.PremiumListSqlDao; -import java.util.List; -import java.util.Optional; -import org.joda.money.BigMoney; -import org.joda.money.CurrencyUnit; -import org.joda.money.Money; - -/** - * DAO for {@link PremiumList} objects that handles the branching paths for SQL and Datastore. - * - *

For write actions, this class will perform the action against Cloud SQL then, after that - * success or failure, against Datastore. If Datastore fails, an error is logged (but not thrown). - * - *

For read actions, when retrieving a price, we will log if the primary and secondary databases - * have different values (or if the retrieval from Datastore fails). - */ -public class PremiumListDualDao { - - /** - * Retrieves from Cloud SQL and returns the most recent premium list with the given name, or - * absent if no such list exists. - */ - public static Optional getLatestRevision(String premiumListName) { - return PremiumListSqlDao.getLatestRevision(premiumListName); - } - - /** - * Returns the premium price for the specified label and registry. - * - *

Returns absent if the label is not premium or there is no premium list for this registry. - * - *

Retrieves the price from both primary and secondary databases, and logs in the event of a - * failure in Datastore (but does not throw an exception). - */ - public static Optional getPremiumPrice(String label, Registry registry) { - if (registry.getPremiumList() == null) { - return Optional.empty(); - } - String premiumListName = registry.getPremiumList().getName(); - Optional primaryResult; - primaryResult = PremiumListSqlDao.getPremiumPrice(premiumListName, label); - // Also load the value from Datastore, compare the two results, and log if different. - suppressExceptionUnlessInTest( - () -> { - Optional secondaryResult = - PremiumListDatastoreDao.getPremiumPrice(premiumListName, label, registry.getTldStr()); - checkState( - primaryResult.equals(secondaryResult), - "Unequal prices for domain %s.%s from primary SQL DB (%s) and secondary Datastore db" - + " (%s).", - label, - registry.getTldStr(), - primaryResult, - secondaryResult); - }, - String.format( - "Error loading price of domain %s.%s from Datastore.", label, registry.getTldStr())); - return primaryResult; - } - - /** - * Saves the given list data to both primary and secondary databases. - * - *

Logs but doesn't throw an exception in the event of a failure when writing to Datastore. - */ - public static PremiumList save(String name, List inputData) { - PremiumList result = PremiumListSqlDao.save(name, inputData); - suppressExceptionUnlessInTest( - () -> PremiumListDatastoreDao.save(name, inputData), - "Error when saving premium list to Datastore."); - return result; - } - - /** - * Deletes the premium list. - * - *

Logs but doesn't throw an exception in the event of a failure when deleting from Datastore. - */ - public static void delete(PremiumList premiumList) { - PremiumListSqlDao.delete(premiumList); - suppressExceptionUnlessInTest( - () -> PremiumListDatastoreDao.delete(premiumList), - "Error when deleting premium list from Datastore."); - } - - /** Returns whether or not there exists a premium list with the given name. */ - public static boolean exists(String premiumListName) { - // It may seem like overkill, but loading the list has ways been the way we check existence and - // given that we usually load the list around the time we check existence, we'll hit the cache - return PremiumListSqlDao.getLatestRevision(premiumListName).isPresent(); - } - - /** - * Returns all {@link PremiumListEntry PremiumListEntries} in the list with the given name. - * - *

This is an expensive operation and should only be used when the entire list is required. - */ - public static Iterable loadAllPremiumListEntries(String premiumListName) { - PremiumList premiumList = - getLatestRevision(premiumListName) - .orElseThrow( - () -> - new IllegalArgumentException( - String.format("No premium list with name %s.", premiumListName))); - CurrencyUnit currencyUnit = premiumList.getCurrency(); - return Streams.stream(PremiumListSqlDao.loadPremiumListEntriesUncached(premiumList)) - .map( - premiumEntry -> - new PremiumListEntry.Builder() - .setPrice(BigMoney.of(currencyUnit, premiumEntry.getPrice()).toMoney()) - .setLabel(premiumEntry.getDomainLabel()) - .build()) - .collect(toImmutableList()); - } - - private PremiumListDualDao() {} -} diff --git a/core/src/main/java/google/registry/schema/tld/PremiumListSqlDao.java b/core/src/main/java/google/registry/schema/tld/PremiumListDao.java similarity index 87% rename from core/src/main/java/google/registry/schema/tld/PremiumListSqlDao.java rename to core/src/main/java/google/registry/schema/tld/PremiumListDao.java index 8fee73919..782e10aed 100644 --- a/core/src/main/java/google/registry/schema/tld/PremiumListSqlDao.java +++ b/core/src/main/java/google/registry/schema/tld/PremiumListDao.java @@ -14,6 +14,7 @@ package google.registry.schema.tld; +import static com.google.common.collect.ImmutableList.toImmutableList; import static google.registry.config.RegistryConfig.getDomainLabelListCacheDuration; import static google.registry.config.RegistryConfig.getSingletonCachePersistDuration; import static google.registry.config.RegistryConfig.getStaticPremiumListMaxCachedEntries; @@ -25,6 +26,7 @@ import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.CacheLoader.InvalidCacheLoadException; import com.google.common.cache.LoadingCache; +import com.google.common.collect.Streams; import google.registry.model.registry.label.PremiumList; import google.registry.model.registry.label.PremiumList.PremiumListEntry; import google.registry.util.NonFinalForTesting; @@ -32,6 +34,8 @@ import java.math.BigDecimal; import java.util.List; import java.util.Optional; import java.util.concurrent.ExecutionException; +import org.joda.money.BigMoney; +import org.joda.money.CurrencyUnit; import org.joda.money.Money; import org.joda.time.Duration; @@ -43,7 +47,7 @@ import org.joda.time.Duration; * {@link PremiumList} object in SQL, and caching these entries so that future lookups can be * quicker. */ -public class PremiumListSqlDao { +public class PremiumListDao { /** * In-memory cache for premium lists. @@ -188,7 +192,7 @@ public class PremiumListSqlDao { * *

This is an expensive operation and should only be used when the entire list is required. */ - public static Iterable loadPremiumListEntriesUncached(PremiumList premiumList) { + public static Iterable loadPremiumListEntries(PremiumList premiumList) { return jpaTm() .transact( () -> @@ -220,6 +224,29 @@ public class PremiumListSqlDao { .findFirst()); } + /** + * Returns all {@link PremiumListEntry PremiumListEntries} in the list with the given name. + * + *

This is an expensive operation and should only be used when the entire list is required. + */ + public static Iterable loadAllPremiumListEntries(String premiumListName) { + PremiumList premiumList = + getLatestRevision(premiumListName) + .orElseThrow( + () -> + new IllegalArgumentException( + String.format("No premium list with name %s.", premiumListName))); + CurrencyUnit currencyUnit = premiumList.getCurrency(); + return Streams.stream(loadPremiumListEntries(premiumList)) + .map( + premiumEntry -> + new PremiumListEntry.Builder() + .setPrice(BigMoney.of(currencyUnit, premiumEntry.getPrice()).toMoney()) + .setLabel(premiumEntry.getDomainLabel()) + .build()) + .collect(toImmutableList()); + } + @AutoValue abstract static class RevisionIdAndLabel { abstract long revisionId(); @@ -227,9 +254,9 @@ public class PremiumListSqlDao { abstract String label(); static RevisionIdAndLabel create(long revisionId, String label) { - return new AutoValue_PremiumListSqlDao_RevisionIdAndLabel(revisionId, label); + return new AutoValue_PremiumListDao_RevisionIdAndLabel(revisionId, label); } } - private PremiumListSqlDao() {} + private PremiumListDao() {} } diff --git a/core/src/main/java/google/registry/tools/ComparePremiumListsCommand.java b/core/src/main/java/google/registry/tools/ComparePremiumListsCommand.java deleted file mode 100644 index b84b567ae..000000000 --- a/core/src/main/java/google/registry/tools/ComparePremiumListsCommand.java +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright 2021 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.tools; - -import static com.google.common.collect.ImmutableSet.toImmutableSet; -import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm; -import static google.registry.persistence.transaction.TransactionManagerFactory.ofyTm; - -import com.beust.jcommander.Parameters; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.Sets; -import com.google.common.collect.Streams; -import google.registry.model.registry.label.PremiumList; -import google.registry.model.registry.label.PremiumList.PremiumListEntry; -import google.registry.model.registry.label.PremiumListDatastoreDao; -import google.registry.schema.tld.PremiumEntry; -import google.registry.schema.tld.PremiumListSqlDao; -import java.util.Optional; -import org.joda.money.BigMoney; - -/** Command to compare all PremiumLists in Datastore to all PremiumLists in Cloud SQL. */ -@Parameters( - separators = " =", - commandDescription = "Compare all the PremiumLists in Datastore to those in Cloud SQL.") -final class ComparePremiumListsCommand implements CommandWithRemoteApi { - - @Override - public void run() { - ImmutableSet datastoreLists = - ofyTm().loadAllOf(PremiumList.class).stream() - .map(PremiumList::getName) - .collect(toImmutableSet()); - - ImmutableSet sqlLists = - jpaTm() - .transact( - () -> - jpaTm().loadAllOf(PremiumList.class).stream() - .map(PremiumList::getName) - .collect(toImmutableSet())); - - int listsWithDiffs = 0; - - for (String listName : Sets.difference(datastoreLists, sqlLists)) { - listsWithDiffs++; - System.out.printf( - "PremiumList '%s' is present in Datastore, but not in Cloud SQL.%n", listName); - } - for (String listName : Sets.difference(sqlLists, datastoreLists)) { - listsWithDiffs++; - System.out.printf( - "PremiumList '%s' is present in Cloud SQL, but not in Datastore.%n", listName); - } - - for (String listName : Sets.intersection(datastoreLists, sqlLists)) { - Optional sqlList = PremiumListSqlDao.getLatestRevision(listName); - - // Datastore and Cloud SQL use different objects to represent premium list entries - // so the best way to compare them is to compare their string representations. - ImmutableSet datastoreListStrings = - Streams.stream( - PremiumListDatastoreDao.loadPremiumListEntriesUncached( - PremiumListDatastoreDao.getLatestRevision(listName).get())) - .map(PremiumListEntry::toString) - .collect(toImmutableSet()); - - Iterable sqlListEntries = - jpaTm().transact(() -> PremiumListSqlDao.loadPremiumListEntriesUncached(sqlList.get())); - - ImmutableSet sqlListStrings = - Streams.stream(sqlListEntries) - .map( - premiumEntry -> - new PremiumListEntry.Builder() - .setPrice( - BigMoney.of(sqlList.get().getCurrency(), premiumEntry.getPrice()) - .toMoney()) - .setLabel(premiumEntry.getDomainLabel()) - .build() - .toString()) - .collect(toImmutableSet()); - - // This will only print out the name of the unequal list. GetPremiumListCommand - // should be used to determine what the actual differences are. - if (!datastoreListStrings.equals(sqlListStrings)) { - listsWithDiffs++; - System.out.printf("PremiumList '%s' has different entries in each database.%n", listName); - } - } - - System.out.printf("Found %d unequal list(s).%n", listsWithDiffs); - } -} diff --git a/core/src/main/java/google/registry/tools/CreateOrUpdatePremiumListCommand.java b/core/src/main/java/google/registry/tools/CreateOrUpdatePremiumListCommand.java index 575aae66d..8e827e99f 100644 --- a/core/src/main/java/google/registry/tools/CreateOrUpdatePremiumListCommand.java +++ b/core/src/main/java/google/registry/tools/CreateOrUpdatePremiumListCommand.java @@ -16,7 +16,7 @@ package google.registry.tools; import com.beust.jcommander.Parameter; import com.google.common.flogger.FluentLogger; -import google.registry.schema.tld.PremiumListSqlDao; +import google.registry.schema.tld.PremiumListDao; import google.registry.tools.params.PathParameter; import java.nio.file.Path; import java.util.List; @@ -51,7 +51,7 @@ abstract class CreateOrUpdatePremiumListCommand extends MutatingCommand { String message = String.format("Saved premium list %s with %d entries", name, inputData.size()); try { logger.atInfo().log("Saving premium list for TLD %s", name); - PremiumListSqlDao.save(name, inputData); + PremiumListDao.save(name, inputData); logger.atInfo().log(message); } catch (Throwable e) { message = "Unexpected error saving premium list from nomulus tool command"; diff --git a/core/src/main/java/google/registry/tools/CreateOrUpdateTldCommand.java b/core/src/main/java/google/registry/tools/CreateOrUpdateTldCommand.java index 693029185..fd5fdd612 100644 --- a/core/src/main/java/google/registry/tools/CreateOrUpdateTldCommand.java +++ b/core/src/main/java/google/registry/tools/CreateOrUpdateTldCommand.java @@ -31,7 +31,7 @@ import google.registry.model.registry.Registry; import google.registry.model.registry.Registry.TldState; import google.registry.model.registry.Registry.TldType; import google.registry.model.registry.label.PremiumList; -import google.registry.model.registry.label.PremiumListDualDao; +import google.registry.schema.tld.PremiumListDao; import google.registry.tools.params.OptionalStringParameter; import google.registry.tools.params.TransitionListParameter.BillingCostTransitions; import google.registry.tools.params.TransitionListParameter.TldStateTransitions; @@ -344,7 +344,7 @@ abstract class CreateOrUpdateTldCommand extends MutatingCommand { if (premiumListName != null) { if (premiumListName.isPresent()) { Optional premiumList = - PremiumListDualDao.getLatestRevision(premiumListName.get()); + PremiumListDao.getLatestRevision(premiumListName.get()); checkArgument( premiumList.isPresent(), String.format("The premium list '%s' doesn't exist", premiumListName.get())); diff --git a/core/src/main/java/google/registry/tools/CreatePremiumListCommand.java b/core/src/main/java/google/registry/tools/CreatePremiumListCommand.java index 0096bd896..693e709d8 100644 --- a/core/src/main/java/google/registry/tools/CreatePremiumListCommand.java +++ b/core/src/main/java/google/registry/tools/CreatePremiumListCommand.java @@ -25,7 +25,7 @@ import com.google.common.base.Strings; import com.googlecode.objectify.Key; import google.registry.model.registry.label.PremiumList; import google.registry.persistence.VKey; -import google.registry.schema.tld.PremiumListSqlDao; +import google.registry.schema.tld.PremiumListDao; import google.registry.schema.tld.PremiumListUtils; import java.nio.file.Files; @@ -43,7 +43,7 @@ public class CreatePremiumListCommand extends CreateOrUpdatePremiumListCommand { protected void init() throws Exception { name = Strings.isNullOrEmpty(name) ? convertFilePathToName(inputFile) : name; checkArgument( - !PremiumListSqlDao.getLatestRevision(name).isPresent(), + !PremiumListDao.getLatestRevision(name).isPresent(), "A premium list already exists by this name"); if (!override) { // refer to CreatePremiumListAction.java diff --git a/core/src/main/java/google/registry/tools/DeletePremiumListCommand.java b/core/src/main/java/google/registry/tools/DeletePremiumListCommand.java index e45313167..54481af5b 100644 --- a/core/src/main/java/google/registry/tools/DeletePremiumListCommand.java +++ b/core/src/main/java/google/registry/tools/DeletePremiumListCommand.java @@ -21,7 +21,7 @@ import com.beust.jcommander.Parameters; import com.google.common.base.Joiner; import com.google.common.collect.ImmutableSet; import google.registry.model.registry.label.PremiumList; -import google.registry.model.registry.label.PremiumListDualDao; +import google.registry.schema.tld.PremiumListDao; import javax.annotation.Nullable; /** @@ -42,10 +42,10 @@ final class DeletePremiumListCommand extends ConfirmingCommand implements Comman @Override protected void init() { checkArgument( - PremiumListDualDao.exists(name), + PremiumListDao.getLatestRevision(name).isPresent(), "Cannot delete the premium list %s because it doesn't exist.", name); - premiumList = PremiumListDualDao.getLatestRevision(name).get(); + premiumList = PremiumListDao.getLatestRevision(name).get(); ImmutableSet tldsUsedOn = premiumList.getReferencingTlds(); checkArgument( tldsUsedOn.isEmpty(), @@ -60,7 +60,7 @@ final class DeletePremiumListCommand extends ConfirmingCommand implements Comman @Override protected String execute() { - PremiumListDualDao.delete(premiumList); + PremiumListDao.delete(premiumList); return String.format("Deleted premium list '%s'.\n", premiumList.getName()); } } diff --git a/core/src/main/java/google/registry/tools/GetPremiumListCommand.java b/core/src/main/java/google/registry/tools/GetPremiumListCommand.java index 94b01aab6..3d1a5a87c 100644 --- a/core/src/main/java/google/registry/tools/GetPremiumListCommand.java +++ b/core/src/main/java/google/registry/tools/GetPremiumListCommand.java @@ -18,7 +18,7 @@ import com.beust.jcommander.Parameter; import com.beust.jcommander.Parameters; import com.google.common.collect.Streams; import google.registry.model.registry.label.PremiumList.PremiumListEntry; -import google.registry.model.registry.label.PremiumListDualDao; +import google.registry.schema.tld.PremiumListDao; import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; @@ -33,11 +33,11 @@ public class GetPremiumListCommand implements CommandWithRemoteApi { @Override public void run() { for (String premiumListName : mainParameters) { - if (PremiumListDualDao.exists(premiumListName)) { + if (PremiumListDao.getLatestRevision(premiumListName).isPresent()) { System.out.printf( "%s:\n%s\n", premiumListName, - Streams.stream(PremiumListDualDao.loadAllPremiumListEntries(premiumListName)) + Streams.stream(PremiumListDao.loadAllPremiumListEntries(premiumListName)) .sorted(Comparator.comparing(PremiumListEntry::getLabel)) .map(PremiumListEntry::toString) .collect(Collectors.joining("\n"))); diff --git a/core/src/main/java/google/registry/tools/RegistryTool.java b/core/src/main/java/google/registry/tools/RegistryTool.java index c09aaa925..ebfea9bde 100644 --- a/core/src/main/java/google/registry/tools/RegistryTool.java +++ b/core/src/main/java/google/registry/tools/RegistryTool.java @@ -38,7 +38,6 @@ public final class RegistryTool { .put("canonicalize_labels", CanonicalizeLabelsCommand.class) .put("check_domain", CheckDomainCommand.class) .put("check_domain_claims", CheckDomainClaimsCommand.class) - .put("compare_premium_lists", ComparePremiumListsCommand.class) .put("compare_reserved_lists", CompareReservedListsCommand.class) .put("convert_idn", ConvertIdnCommand.class) .put("count_domains", CountDomainsCommand.class) diff --git a/core/src/main/java/google/registry/tools/UpdatePremiumListCommand.java b/core/src/main/java/google/registry/tools/UpdatePremiumListCommand.java index aa1a33290..96cb83c2e 100644 --- a/core/src/main/java/google/registry/tools/UpdatePremiumListCommand.java +++ b/core/src/main/java/google/registry/tools/UpdatePremiumListCommand.java @@ -29,7 +29,7 @@ import google.registry.model.registry.label.PremiumList; import google.registry.model.registry.label.PremiumList.PremiumListEntry; import google.registry.persistence.VKey; import google.registry.schema.tld.PremiumEntry; -import google.registry.schema.tld.PremiumListSqlDao; +import google.registry.schema.tld.PremiumListDao; import google.registry.schema.tld.PremiumListUtils; import java.nio.file.Files; import java.util.List; @@ -79,12 +79,12 @@ class UpdatePremiumListCommand extends CreateOrUpdatePremiumListCommand { assertThat(persistedList.size()).isEqualTo(1); */ protected ImmutableSet getExistingPremiumListEntry(String name) { - Optional list = PremiumListSqlDao.getLatestRevision(name); + Optional list = PremiumListDao.getLatestRevision(name); checkArgument( list.isPresent(), String.format("Could not update premium list %s because it doesn't exist.", name)); Iterable sqlListEntries = - jpaTm().transact(() -> PremiumListSqlDao.loadPremiumListEntriesUncached(list.get())); + jpaTm().transact(() -> PremiumListDao.loadPremiumListEntries(list.get())); return Streams.stream(sqlListEntries) .map( premiumEntry -> diff --git a/core/src/main/java/google/registry/tools/server/CreatePremiumListAction.java b/core/src/main/java/google/registry/tools/server/CreatePremiumListAction.java index c67385904..894156eb1 100644 --- a/core/src/main/java/google/registry/tools/server/CreatePremiumListAction.java +++ b/core/src/main/java/google/registry/tools/server/CreatePremiumListAction.java @@ -21,10 +21,10 @@ import static google.registry.request.Action.Method.POST; import com.google.common.base.Splitter; import com.google.common.collect.ImmutableMap; import com.google.common.flogger.FluentLogger; -import google.registry.model.registry.label.PremiumListDualDao; import google.registry.request.Action; import google.registry.request.Parameter; import google.registry.request.auth.Auth; +import google.registry.schema.tld.PremiumListDao; import java.util.List; import javax.inject.Inject; @@ -51,7 +51,9 @@ public class CreatePremiumListAction extends CreateOrUpdatePremiumListAction { @Override protected void save() { checkArgument( - !PremiumListDualDao.exists(name), "A premium list of this name already exists: %s", name); + !PremiumListDao.getLatestRevision(name).isPresent(), + "A premium list of this name already exists: %s", + name); if (!override) { assertTldExists( name, @@ -62,7 +64,7 @@ public class CreatePremiumListAction extends CreateOrUpdatePremiumListAction { logInputData(); List inputDataPreProcessed = Splitter.on('\n').omitEmptyStrings().splitToList(inputData); - PremiumListDualDao.save(name, inputDataPreProcessed); + PremiumListDao.save(name, inputDataPreProcessed); String message = String.format("Saved premium list %s with %d entries", name, inputDataPreProcessed.size()); logger.atInfo().log(message); diff --git a/core/src/main/java/google/registry/tools/server/ListPremiumListsAction.java b/core/src/main/java/google/registry/tools/server/ListPremiumListsAction.java index 7c8baccd8..37298feb4 100644 --- a/core/src/main/java/google/registry/tools/server/ListPremiumListsAction.java +++ b/core/src/main/java/google/registry/tools/server/ListPremiumListsAction.java @@ -21,9 +21,9 @@ import static google.registry.request.Action.Method.POST; import com.google.common.collect.ImmutableSet; import google.registry.model.registry.label.PremiumList; -import google.registry.model.registry.label.PremiumListDualDao; import google.registry.request.Action; import google.registry.request.auth.Auth; +import google.registry.schema.tld.PremiumListDao; import java.util.Comparator; import java.util.Optional; import javax.inject.Inject; @@ -55,7 +55,7 @@ public final class ListPremiumListsAction extends ListObjectsAction () -> jpaTm().loadAllOf(PremiumList.class).stream() .map(PremiumList::getName) - .map(PremiumListDualDao::getLatestRevision) + .map(PremiumListDao::getLatestRevision) .filter(Optional::isPresent) .map(Optional::get) .peek(list -> Hibernate.initialize(list.getLabelsToPrices())) diff --git a/core/src/main/java/google/registry/tools/server/UpdatePremiumListAction.java b/core/src/main/java/google/registry/tools/server/UpdatePremiumListAction.java index af78b3b19..8c3a0e158 100644 --- a/core/src/main/java/google/registry/tools/server/UpdatePremiumListAction.java +++ b/core/src/main/java/google/registry/tools/server/UpdatePremiumListAction.java @@ -21,9 +21,9 @@ import com.google.common.base.Splitter; import com.google.common.collect.ImmutableMap; import com.google.common.flogger.FluentLogger; import google.registry.model.registry.label.PremiumList; -import google.registry.model.registry.label.PremiumListDualDao; import google.registry.request.Action; import google.registry.request.auth.Auth; +import google.registry.schema.tld.PremiumListDao; import java.util.List; import javax.inject.Inject; @@ -47,7 +47,7 @@ public class UpdatePremiumListAction extends CreateOrUpdatePremiumListAction { @Override protected void save() { checkArgument( - PremiumListDualDao.exists(name), + PremiumListDao.getLatestRevision(name).isPresent(), "Could not update premium list %s because it doesn't exist.", name); @@ -55,7 +55,7 @@ public class UpdatePremiumListAction extends CreateOrUpdatePremiumListAction { logInputData(); List inputDataPreProcessed = Splitter.on('\n').omitEmptyStrings().splitToList(inputData); - PremiumList newPremiumList = PremiumListDualDao.save(name, inputDataPreProcessed); + PremiumList newPremiumList = PremiumListDao.save(name, inputDataPreProcessed); String message = String.format( diff --git a/core/src/test/java/google/registry/export/ExportPremiumTermsActionTest.java b/core/src/test/java/google/registry/export/ExportPremiumTermsActionTest.java index caf0639b5..eba59e47e 100644 --- a/core/src/test/java/google/registry/export/ExportPremiumTermsActionTest.java +++ b/core/src/test/java/google/registry/export/ExportPremiumTermsActionTest.java @@ -37,8 +37,8 @@ import com.google.common.collect.ImmutableList; import com.google.common.net.MediaType; import google.registry.model.registry.Registry; import google.registry.model.registry.label.PremiumList; -import google.registry.model.registry.label.PremiumListDualDao; import google.registry.request.Response; +import google.registry.schema.tld.PremiumListDao; import google.registry.storage.drive.DriveConnection; import google.registry.testing.AppEngineExtension; import java.io.IOException; @@ -75,7 +75,7 @@ public class ExportPremiumTermsActionTest { @BeforeEach void beforeEach() throws Exception { createTld("tld"); - PremiumList pl = PremiumListDualDao.save("pl-name", PREMIUM_NAMES); + PremiumList pl = PremiumListDao.save("pl-name", PREMIUM_NAMES); persistResource( Registry.get("tld").asBuilder().setPremiumList(pl).setDriveFolderId("folder_id").build()); when(driveConnection.createOrUpdateFile( @@ -143,7 +143,7 @@ public class ExportPremiumTermsActionTest { @Test void test_exportPremiumTerms_failure_noPremiumList() { - PremiumListDualDao.delete(new PremiumList.Builder().setName("pl-name").build()); + PremiumListDao.delete(new PremiumList.Builder().setName("pl-name").build()); assertThrows(RuntimeException.class, () -> runAction("tld")); verifyNoInteractions(driveConnection); diff --git a/core/src/test/java/google/registry/model/registry/RegistryTest.java b/core/src/test/java/google/registry/model/registry/RegistryTest.java index 5948ace40..17dbbb358 100644 --- a/core/src/test/java/google/registry/model/registry/RegistryTest.java +++ b/core/src/test/java/google/registry/model/registry/RegistryTest.java @@ -42,8 +42,8 @@ import google.registry.model.EntityTestCase; import google.registry.model.registry.Registry.RegistryNotFoundException; import google.registry.model.registry.Registry.TldState; import google.registry.model.registry.label.PremiumList; -import google.registry.model.registry.label.PremiumListDualDao; import google.registry.model.registry.label.ReservedList; +import google.registry.schema.tld.PremiumListDao; import google.registry.testing.DatabaseHelper; import google.registry.testing.DualDatabaseTest; import google.registry.testing.TestOfyAndSql; @@ -251,7 +251,7 @@ public final class RegistryTest extends EntityTestCase { Registry registry = Registry.get("tld").asBuilder().setPremiumList(pl2).build(); Key plKey = registry.getPremiumList(); assertThat(plKey).isNotNull(); - PremiumList stored = PremiumListDualDao.getLatestRevision(plKey.getName()).get(); + PremiumList stored = PremiumListDao.getLatestRevision(plKey.getName()).get(); assertThat(stored.getName()).isEqualTo("tld2"); } diff --git a/core/src/test/java/google/registry/model/registry/label/PremiumListDatastoreDaoTest.java b/core/src/test/java/google/registry/model/registry/label/PremiumListDatastoreDaoTest.java deleted file mode 100644 index 5f560a6b9..000000000 --- a/core/src/test/java/google/registry/model/registry/label/PremiumListDatastoreDaoTest.java +++ /dev/null @@ -1,326 +0,0 @@ -// Copyright 2017 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.registry.label; - -import static com.google.common.collect.ImmutableMap.toImmutableMap; -import static com.google.common.truth.Truth.assertThat; -import static com.google.common.truth.Truth8.assertThat; -import static com.google.monitoring.metrics.contrib.DistributionMetricSubject.assertThat; -import static com.google.monitoring.metrics.contrib.LongMetricSubject.assertThat; -import static google.registry.model.ofy.ObjectifyService.auditedOfy; -import static google.registry.model.registry.label.DomainLabelMetrics.PremiumListCheckOutcome.BLOOM_FILTER_NEGATIVE; -import static google.registry.model.registry.label.DomainLabelMetrics.PremiumListCheckOutcome.CACHED_NEGATIVE; -import static google.registry.model.registry.label.DomainLabelMetrics.PremiumListCheckOutcome.CACHED_POSITIVE; -import static google.registry.model.registry.label.DomainLabelMetrics.PremiumListCheckOutcome.UNCACHED_NEGATIVE; -import static google.registry.model.registry.label.DomainLabelMetrics.PremiumListCheckOutcome.UNCACHED_POSITIVE; -import static google.registry.model.registry.label.DomainLabelMetrics.premiumListChecks; -import static google.registry.model.registry.label.DomainLabelMetrics.premiumListProcessingTime; -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.loadPremiumListEntries; -import static google.registry.testing.DatabaseHelper.persistPremiumList; -import static google.registry.testing.DatabaseHelper.persistResource; -import static org.joda.time.Duration.standardDays; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Streams; -import com.googlecode.objectify.Key; -import google.registry.model.registry.Registry; -import google.registry.model.registry.label.PremiumList.PremiumListEntry; -import google.registry.model.registry.label.PremiumList.PremiumListRevision; -import google.registry.testing.AppEngineExtension; -import google.registry.testing.TestCacheExtension; -import java.util.Map; -import java.util.Optional; -import java.util.function.Function; -import org.joda.money.Money; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -/** Unit tests for {@link PremiumListDatastoreDao}. */ -public class PremiumListDatastoreDaoTest { - - @RegisterExtension - public final AppEngineExtension appEngine = - AppEngineExtension.builder().withDatastoreAndCloudSql().build(); - - // Set long persist times on caches so they can be tested (cache times default to 0 in tests). - @RegisterExtension - public final TestCacheExtension testCacheExtension = - new TestCacheExtension.Builder() - .withPremiumListsCache(standardDays(1)) - .withPremiumListEntriesCache(standardDays(1)) - .build(); - - private PremiumList pl; - - @BeforeEach - void before() { - // createTld() overwrites the premium list, so call it before persisting pl. - createTld("tld"); - pl = - persistPremiumList( - "tld", - "lol,USD 999 # yup", - "rich,USD 1999 #tada", - "icann,JPY 100", - "johnny-be-goode,USD 20.50"); - persistResource(Registry.get("tld").asBuilder().setPremiumList(pl).build()); - premiumListChecks.reset(); - premiumListProcessingTime.reset(); - } - - void assertMetricOutcomeCount( - int checkCount, DomainLabelMetrics.PremiumListCheckOutcome outcome) { - assertThat(premiumListChecks) - .hasValueForLabels(checkCount, "tld", "tld", outcome.toString()) - .and() - .hasNoOtherValues(); - assertThat(premiumListProcessingTime) - .hasAnyValueForLabels("tld", "tld", outcome.toString()) - .and() - .hasNoOtherValues(); - } - - @Test - void testSave_largeNumberOfEntries_succeeds() { - PremiumList premiumList = persistHumongousPremiumList("tld", 2500); - assertThat(loadPremiumListEntries(premiumList)).hasSize(2500); - assertThat(PremiumListDatastoreDao.getPremiumPrice("tld", "7", "tld")) - .hasValue(Money.parse("USD 100")); - assertMetricOutcomeCount(1, UNCACHED_POSITIVE); - } - - @Test - void testSave_updateTime_isUpdatedOnEverySave() { - PremiumList pl = PremiumListDatastoreDao.save("tld3", ImmutableList.of("slime,USD 10")); - PremiumList newPl = PremiumListDatastoreDao.save("tld3", ImmutableList.of("mutants,USD 20")); - assertThat(newPl.getLastUpdateTime()).isGreaterThan(pl.getLastUpdateTime()); - } - - @Test - void testSave_creationTime_onlyUpdatedOnFirstCreation() { - PremiumList pl = persistPremiumList("tld3", "sludge,JPY 1000"); - PremiumList newPl = - PremiumListDatastoreDao.save("tld3", ImmutableList.of("sleighbells,CHF 2000")); - assertThat(newPl.creationTime).isEqualTo(pl.creationTime); - } - - @Test - void testExists() { - assertThat(PremiumListDatastoreDao.getLatestRevision("tld")).isPresent(); - assertThat(PremiumListDatastoreDao.getLatestRevision("nonExistentPremiumList")).isEmpty(); - } - - @Test - void testGetPremiumPrice_comesFromBloomFilter() throws Exception { - PremiumList pl = PremiumListDatastoreDao.getLatestRevision("tld").get(); - PremiumListEntry entry = - persistResource( - new PremiumListEntry.Builder() - .setParent(pl.getRevisionKey()) - .setLabel("missingno") - .setPrice(Money.parse("USD 1000")) - .build()); - // "missingno" shouldn't be in the Bloom filter, thus it should return not premium without - // attempting to load the entity that is actually present. - assertThat(PremiumListDatastoreDao.getPremiumPrice("tld", "missingno", "tld")).isEmpty(); - // However, if we manually query the cache to force an entity load, it should be found. - assertThat( - PremiumListDatastoreDao.premiumListEntriesCache.get( - Key.create(pl.getRevisionKey(), PremiumListEntry.class, "missingno"))) - .hasValue(entry); - assertMetricOutcomeCount(1, BLOOM_FILTER_NEGATIVE); - } - - @Test - void testGetPremiumPrice_cachedSecondTime() { - assertThat(PremiumListDatastoreDao.getPremiumPrice("tld", "rich", "tld")) - .hasValue(Money.parse("USD 1999")); - assertThat(PremiumListDatastoreDao.getPremiumPrice("tld", "rich", "tld")) - .hasValue(Money.parse("USD 1999")); - assertThat(premiumListChecks) - .hasValueForLabels(1, "tld", "tld", UNCACHED_POSITIVE.toString()) - .and() - .hasValueForLabels(1, "tld", "tld", CACHED_POSITIVE.toString()) - .and() - .hasNoOtherValues(); - assertThat(premiumListProcessingTime) - .hasAnyValueForLabels("tld", "tld", UNCACHED_POSITIVE.toString()) - .and() - .hasAnyValueForLabels("tld", "tld", CACHED_POSITIVE.toString()) - .and() - .hasNoOtherValues(); - } - - @Test - void testGetPremiumPrice_bloomFilterFalsePositive() { - // Remove one of the premium list entries from behind the Bloom filter's back. - tm().transactNew( - () -> - auditedOfy() - .delete() - .keys(Key.create(pl.getRevisionKey(), PremiumListEntry.class, "rich"))); - auditedOfy().clearSessionCache(); - - assertThat(PremiumListDatastoreDao.getPremiumPrice("tld", "rich", "tld")).isEmpty(); - assertThat(PremiumListDatastoreDao.getPremiumPrice("tld", "rich", "tld")).isEmpty(); - - assertThat(premiumListChecks) - .hasValueForLabels(1, "tld", "tld", UNCACHED_NEGATIVE.toString()) - .and() - .hasValueForLabels(1, "tld", "tld", CACHED_NEGATIVE.toString()) - .and() - .hasNoOtherValues(); - assertThat(premiumListProcessingTime) - .hasAnyValueForLabels("tld", "tld", UNCACHED_NEGATIVE.toString()) - .and() - .hasAnyValueForLabels("tld", "tld", CACHED_NEGATIVE.toString()) - .and() - .hasNoOtherValues(); - } - - @Test - void testSave_removedPremiumListEntries_areNoLongerInDatastore() { - PremiumList pl = persistPremiumList("tld", "genius,USD 10", "dolt,JPY 1000"); - assertThat(PremiumListDatastoreDao.getPremiumPrice("tld", "genius", "tld")) - .hasValue(Money.parse("USD 10")); - assertThat(PremiumListDatastoreDao.getPremiumPrice("tld", "dolt", "tld")) - .hasValue(Money.parse("JPY 1000")); - assertThat( - auditedOfy() - .load() - .type(PremiumListEntry.class) - .parent(pl.getRevisionKey()) - .id("dolt") - .now() - .price) - .isEqualTo(Money.parse("JPY 1000")); - PremiumListDatastoreDao.save("tld", ImmutableList.of("genius,USD 10", "savant,USD 90")); - assertThat(PremiumListDatastoreDao.getPremiumPrice("tld", "genius", "tld")) - .hasValue(Money.parse("USD 10")); - assertThat(PremiumListDatastoreDao.getPremiumPrice("tld", "savant", "tld")) - .hasValue(Money.parse("USD 90")); - assertThat(PremiumListDatastoreDao.getPremiumPrice("tld", "dolt", "tld")).isEmpty(); - // TODO(b/79888775): Assert that the old premium list is enqueued for later deletion. - assertThat(premiumListChecks) - .hasValueForLabels(4, "tld", "tld", UNCACHED_POSITIVE.toString()) - .and() - .hasValueForLabels(1, "tld", "tld", BLOOM_FILTER_NEGATIVE.toString()) - .and() - .hasNoOtherValues(); - assertThat(premiumListProcessingTime) - .hasAnyValueForLabels("tld", "tld", UNCACHED_POSITIVE.toString()) - .and() - .hasAnyValueForLabels("tld", "tld", BLOOM_FILTER_NEGATIVE.toString()) - .and() - .hasNoOtherValues(); - } - - @Test - void testGetPremiumPrice_allLabelsAreNonPremium_whenNotInList() { - assertThat(PremiumListDatastoreDao.getPremiumPrice("tld", "blah", "tld")).isEmpty(); - assertThat(PremiumListDatastoreDao.getPremiumPrice("tld", "slinge", "tld")).isEmpty(); - assertMetricOutcomeCount(2, BLOOM_FILTER_NEGATIVE); - } - - @Test - void testSave_simple() { - PremiumList pl = - PremiumListDatastoreDao.save("tld2", ImmutableList.of("lol , USD 999 # yupper rooni ")); - persistResource(Registry.get("tld").asBuilder().setPremiumList(pl).build()); - assertThat(PremiumListDatastoreDao.getPremiumPrice("tld2", "lol", "tld")) - .hasValue(Money.parse("USD 999")); - assertThat(PremiumListDatastoreDao.getPremiumPrice("tld2", "lol ", "tld")).isEmpty(); - ImmutableMap entries = - Streams.stream(PremiumListDatastoreDao.loadPremiumListEntriesUncached(pl)) - .collect(toImmutableMap(PremiumListEntry::getLabel, Function.identity())); - assertThat(entries.keySet()).containsExactly("lol"); - assertThat(entries).doesNotContainKey("lol "); - PremiumListEntry entry = entries.get("lol"); - assertThat(entry.comment).isEqualTo("yupper rooni"); - assertThat(entry.price).isEqualTo(Money.parse("USD 999")); - assertThat(entry.label).isEqualTo("lol"); - assertThat(premiumListChecks) - .hasValueForLabels(1, "tld", "tld2", UNCACHED_POSITIVE.toString()) - .and() - .hasValueForLabels(1, "tld", "tld2", BLOOM_FILTER_NEGATIVE.toString()) - .and() - .hasNoOtherValues(); - assertThat(premiumListProcessingTime) - .hasAnyValueForLabels("tld", "tld2", UNCACHED_POSITIVE.toString()) - .and() - .hasAnyValueForLabels("tld", "tld2", BLOOM_FILTER_NEGATIVE.toString()) - .and() - .hasNoOtherValues(); - } - - @Test - void test_saveAndUpdateEntriesTwice() { - PremiumList firstSave = PremiumListDatastoreDao.save("tld", ImmutableList.of("test,USD 1")); - ImmutableMap entries = - Streams.stream(PremiumListDatastoreDao.loadPremiumListEntriesUncached(firstSave)) - .collect(toImmutableMap(PremiumListEntry::getLabel, Function.identity())); - assertThat(entries.keySet()).containsExactly("test"); - // Save again with no changes, and clear the cache to force a re-load from Datastore. - PremiumList resaved = PremiumListDatastoreDao.save("tld", ImmutableList.of("test,USD 1")); - auditedOfy().clearSessionCache(); - Map entriesReloaded = - Streams.stream(PremiumListDatastoreDao.loadPremiumListEntriesUncached(resaved)) - .collect(toImmutableMap(PremiumListEntry::getLabel, Function.identity())); - assertThat(entriesReloaded).hasSize(1); - assertThat(entriesReloaded).containsKey("test"); - assertThat(entriesReloaded.get("test").parent).isEqualTo(resaved.getRevisionKey()); - } - - @Test - void testDelete() { - persistPremiumList("gtld1", "trombone,USD 10"); - Optional gtld1 = PremiumListDatastoreDao.getLatestRevision("gtld1"); - assertThat(gtld1).isPresent(); - Key parent = gtld1.get().getRevisionKey(); - PremiumListDatastoreDao.delete(gtld1.get()); - assertThat(PremiumListDatastoreDao.getLatestRevision("gtld1")).isEmpty(); - assertThat(auditedOfy().load().type(PremiumListEntry.class).ancestor(parent).list()).isEmpty(); - } - - @Test - void testDelete_largeNumberOfEntries_succeeds() { - PremiumList large = persistHumongousPremiumList("ginormous", 2500); - PremiumListDatastoreDao.delete(large); - assertThat(PremiumListDatastoreDao.getLatestRevision("ginormous")).isEmpty(); - } - - @Test - void test_savePremiumList_clearsCache() { - assertThat(PremiumListDatastoreDao.premiumListCache.getIfPresent("tld")).isNull(); - PremiumList pl = PremiumListDatastoreDao.getLatestRevision("tld").get(); - assertThat(PremiumListDatastoreDao.premiumListCache.getIfPresent("tld").get()).isEqualTo(pl); - transactIfJpaTm(() -> PremiumListDatastoreDao.save("tld", ImmutableList.of("test,USD 1"))); - assertThat(PremiumListDatastoreDao.premiumListCache.getIfPresent("tld")).isNull(); - } - - /** Persists a premium list with a specified number of nonsense entries. */ - private PremiumList persistHumongousPremiumList(String name, int size) { - String[] entries = new String[size]; - for (int i = 0; i < size; i++) { - entries[i] = String.format("%d,USD 100 # blahz", i); - } - return persistPremiumList(name, entries); - } -} diff --git a/core/src/test/java/google/registry/model/registry/label/PremiumListDualDaoTest.java b/core/src/test/java/google/registry/model/registry/label/PremiumListDualDaoTest.java deleted file mode 100644 index 1f98a9d8b..000000000 --- a/core/src/test/java/google/registry/model/registry/label/PremiumListDualDaoTest.java +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright 2021 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.registry.label; - -import static com.google.common.truth.Truth.assertThat; -import static google.registry.testing.DatabaseHelper.createTld; -import static google.registry.testing.DatabaseHelper.newRegistry; -import static google.registry.testing.DatabaseHelper.persistResource; -import static org.joda.time.Duration.standardDays; -import static org.junit.jupiter.api.Assertions.assertThrows; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.ImmutableSet; -import com.google.common.truth.Truth8; -import google.registry.dns.writer.VoidDnsWriter; -import google.registry.model.EntityTestCase; -import google.registry.model.pricing.StaticPremiumListPricingEngine; -import google.registry.model.registry.Registry; -import google.registry.testing.TestCacheExtension; -import org.junit.jupiter.api.AfterEach; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -/** Unit tests for {@link PremiumListDualDao}. */ -public class PremiumListDualDaoTest extends EntityTestCase { - - // Set long persist times on caches so they can be tested (cache times default to 0 in tests). - @RegisterExtension - public final TestCacheExtension testCacheExtension = - new TestCacheExtension.Builder() - .withPremiumListsCache(standardDays(1)) - .withPremiumListEntriesCache(standardDays(1)) - .build(); - - @BeforeEach - void before() { - createTld("tld"); - fakeClock.setAutoIncrementByOneMilli(); - } - - @AfterEach - void after() { - fakeClock.disableAutoIncrement(); - } - - @Test - void testGetPremiumPrice_secondaryLoadMissingOfy() { - PremiumList premiumList = PremiumListDatastoreDao.getLatestRevision("tld").get(); - PremiumListDatastoreDao.delete(premiumList); - assertThat( - assertThrows( - IllegalStateException.class, - () -> PremiumListDualDao.getPremiumPrice("brass", Registry.get("tld")))) - .hasMessageThat() - .isEqualTo( - "Unequal prices for domain brass.tld from primary SQL DB (Optional[USD 20.00]) " - + "and secondary Datastore db (Optional.empty)."); - } - - @Test - void testGetPremiumPrice_secondaryDifferentOfy() { - PremiumListDatastoreDao.save("tld", ImmutableList.of("brass,USD 50")); - assertThat( - assertThrows( - IllegalStateException.class, - () -> PremiumListDualDao.getPremiumPrice("brass", Registry.get("tld")))) - .hasMessageThat() - .isEqualTo( - "Unequal prices for domain brass.tld from primary SQL DB " - + "(Optional[USD 20.00]) and secondary Datastore db (Optional[USD 50.00])."); - } - - @Test - void testGetPremiumPrice_returnsNoPriceWhenNoPremiumListConfigured() { - createTld("ghost"); - persistResource( - new Registry.Builder() - .setTldStr("ghost") - .setPremiumPricingEngine(StaticPremiumListPricingEngine.NAME) - .setDnsWriters(ImmutableSet.of(VoidDnsWriter.NAME)) - .build()); - assertThat(Registry.get("ghost").getPremiumList()).isNull(); - Truth8.assertThat(PremiumListDualDao.getPremiumPrice("blah", Registry.get("ghost"))).isEmpty(); - } - - @Test - void testGetPremiumPrice_emptyWhenPremiumListDeleted() { - PremiumList toDelete = PremiumListDualDao.getLatestRevision("tld").get(); - PremiumListDualDao.delete(toDelete); - Truth8.assertThat(PremiumListDualDao.getPremiumPrice("blah", Registry.get("tld"))).isEmpty(); - } - - @Test - void getPremiumPrice_returnsNoneWhenNoPremiumListConfigured() { - persistResource(newRegistry("foobar", "FOOBAR").asBuilder().setPremiumList(null).build()); - Truth8.assertThat(PremiumListDualDao.getPremiumPrice("rich", Registry.get("foobar"))).isEmpty(); - } -} diff --git a/core/src/test/java/google/registry/model/registry/label/PremiumListTest.java b/core/src/test/java/google/registry/model/registry/label/PremiumListTest.java index ab7618bf2..d1243bf69 100644 --- a/core/src/test/java/google/registry/model/registry/label/PremiumListTest.java +++ b/core/src/test/java/google/registry/model/registry/label/PremiumListTest.java @@ -26,6 +26,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.hash.BloomFilter; import google.registry.model.registry.Registry; import google.registry.model.registry.label.PremiumList.PremiumListEntry; +import google.registry.schema.tld.PremiumListDao; import google.registry.testing.AppEngineExtension; import org.joda.money.Money; import org.junit.jupiter.api.BeforeEach; @@ -68,7 +69,7 @@ public class PremiumListTest { @Test void testBloomFilter() { - PremiumList pl = PremiumListDualDao.getLatestRevision("tld").get(); + PremiumList pl = PremiumListDao.getLatestRevision("tld").get(); BloomFilter bloomFilter = pl.getBloomFilter(); assertThat(bloomFilter.mightContain("notpremium")).isFalse(); for (String label : ImmutableList.of("rich", "lol", "johnny-be-goode", "icann")) { @@ -84,7 +85,7 @@ public class PremiumListTest { assertThrows( IllegalStateException.class, () -> - PremiumListDualDao.getLatestRevision("tld") + PremiumListDao.getLatestRevision("tld") .get() .parse( ImmutableList.of( diff --git a/core/src/test/java/google/registry/schema/integration/SqlIntegrationTestSuite.java b/core/src/test/java/google/registry/schema/integration/SqlIntegrationTestSuite.java index a1f8847bd..2c4215e1f 100644 --- a/core/src/test/java/google/registry/schema/integration/SqlIntegrationTestSuite.java +++ b/core/src/test/java/google/registry/schema/integration/SqlIntegrationTestSuite.java @@ -42,7 +42,7 @@ import google.registry.schema.integration.SqlIntegrationTestSuite.AfterSuiteTest import google.registry.schema.integration.SqlIntegrationTestSuite.BeforeSuiteTest; import google.registry.schema.registrar.RegistrarDaoTest; import google.registry.schema.replay.SqlReplayCheckpointTest; -import google.registry.schema.tld.PremiumListSqlDaoTest; +import google.registry.schema.tld.PremiumListDaoTest; import google.registry.testing.AppEngineExtension; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.BeforeAll; @@ -92,7 +92,7 @@ import org.junit.runner.RunWith; KmsSecretRevisionSqlDaoTest.class, LockTest.class, PollMessageTest.class, - PremiumListSqlDaoTest.class, + PremiumListDaoTest.class, RdeRevisionTest.class, RegistrarDaoTest.class, RegistryTest.class, diff --git a/core/src/test/java/google/registry/schema/tld/PremiumListSqlDaoTest.java b/core/src/test/java/google/registry/schema/tld/PremiumListDaoTest.java similarity index 78% rename from core/src/test/java/google/registry/schema/tld/PremiumListSqlDaoTest.java rename to core/src/test/java/google/registry/schema/tld/PremiumListDaoTest.java index f91cbb37e..763d10e84 100644 --- a/core/src/test/java/google/registry/schema/tld/PremiumListSqlDaoTest.java +++ b/core/src/test/java/google/registry/schema/tld/PremiumListDaoTest.java @@ -40,8 +40,8 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; -/** Unit tests for {@link PremiumListSqlDao}. */ -public class PremiumListSqlDaoTest { +/** Unit tests for {@link PremiumListDao}. */ +public class PremiumListDaoTest { private final FakeClock fakeClock = new FakeClock(); @@ -58,7 +58,6 @@ public class PremiumListSqlDaoTest { public final TestCacheExtension testCacheExtension = new TestCacheExtension.Builder() .withPremiumListsCache(standardDays(1)) - .withPremiumListEntriesCache(standardDays(1)) .build(); private ImmutableMap testPrices; @@ -86,12 +85,11 @@ public class PremiumListSqlDaoTest { @Test void saveNew_worksSuccessfully() { - PremiumListSqlDao.save(testList); + PremiumListDao.save(testList); jpaTm() .transact( () -> { - Optional persistedListOpt = - PremiumListSqlDao.getLatestRevision("testname"); + Optional persistedListOpt = PremiumListDao.getLatestRevision("testname"); assertThat(persistedListOpt).isPresent(); PremiumList persistedList = persistedListOpt.get(); assertThat(persistedList.getLabelsToPrices()).containsExactlyEntriesIn(testPrices); @@ -101,11 +99,11 @@ public class PremiumListSqlDaoTest { @Test void update_worksSuccessfully() { - PremiumListSqlDao.save(testList); - Optional persistedList = PremiumListSqlDao.getLatestRevision("testname"); + PremiumListDao.save(testList); + Optional persistedList = PremiumListDao.getLatestRevision("testname"); assertThat(persistedList).isPresent(); long firstRevisionId = persistedList.get().getRevisionId(); - PremiumListSqlDao.save( + PremiumListDao.save( new PremiumList.Builder() .setName("testname") .setCurrency(USD) @@ -122,7 +120,7 @@ public class PremiumListSqlDaoTest { jpaTm() .transact( () -> { - Optional savedListOpt = PremiumListSqlDao.getLatestRevision("testname"); + Optional savedListOpt = PremiumListDao.getLatestRevision("testname"); assertThat(savedListOpt).isPresent(); PremiumList savedList = savedListOpt.get(); assertThat(savedList.getLabelsToPrices()) @@ -142,26 +140,26 @@ public class PremiumListSqlDaoTest { @Test void checkExists_worksSuccessfully() { - assertThat(PremiumListSqlDao.getLatestRevision("testname")).isEmpty(); - PremiumListSqlDao.save(testList); - assertThat(PremiumListSqlDao.getLatestRevision("testname")).isPresent(); + assertThat(PremiumListDao.getLatestRevision("testname")).isEmpty(); + PremiumListDao.save(testList); + assertThat(PremiumListDao.getLatestRevision("testname")).isPresent(); } @Test void getLatestRevision_returnsEmptyForNonexistentList() { - assertThat(PremiumListSqlDao.getLatestRevision("nonexistentlist")).isEmpty(); + assertThat(PremiumListDao.getLatestRevision("nonexistentlist")).isEmpty(); } @Test void getLatestRevision_worksSuccessfully() { - PremiumListSqlDao.save( + PremiumListDao.save( new PremiumList.Builder() .setName("list1") .setCurrency(JPY) .setLabelsToPrices(ImmutableMap.of("wrong", BigDecimal.valueOf(1000.50))) .setCreationTime(fakeClock.nowUtc()) .build()); - PremiumListSqlDao.save( + PremiumListDao.save( new PremiumList.Builder() .setName("list1") .setCurrency(JPY) @@ -171,7 +169,7 @@ public class PremiumListSqlDaoTest { jpaTm() .transact( () -> { - Optional persistedList = PremiumListSqlDao.getLatestRevision("list1"); + Optional persistedList = PremiumListDao.getLatestRevision("list1"); assertThat(persistedList).isPresent(); assertThat(persistedList.get().getName()).isEqualTo("list1"); assertThat(persistedList.get().getCurrency()).isEqualTo(JPY); @@ -191,18 +189,16 @@ public class PremiumListSqlDaoTest { google.registry.model.registry.label.PremiumList.class, "premlist")) .build()); - PremiumListSqlDao.save( + PremiumListDao.save( new PremiumList.Builder() .setName("premlist") .setCurrency(USD) .setLabelsToPrices(testPrices) .setCreationTime(fakeClock.nowUtc()) .build()); - assertThat(PremiumListSqlDao.getPremiumPrice("premlist", "silver")) - .hasValue(Money.of(USD, 10.23)); - assertThat(PremiumListSqlDao.getPremiumPrice("premlist", "gold")) - .hasValue(Money.of(USD, 1305.47)); - assertThat(PremiumListSqlDao.getPremiumPrice("premlist", "zirconium")).isEmpty(); + assertThat(PremiumListDao.getPremiumPrice("premlist", "silver")).hasValue(Money.of(USD, 10.23)); + assertThat(PremiumListDao.getPremiumPrice("premlist", "gold")).hasValue(Money.of(USD, 1305.47)); + assertThat(PremiumListDao.getPremiumPrice("premlist", "zirconium")).isEmpty(); } @Test @@ -216,7 +212,7 @@ public class PremiumListSqlDaoTest { google.registry.model.registry.label.PremiumList.class, "premlist")) .build()); - PremiumListSqlDao.save( + PremiumListDao.save( new PremiumList.Builder() .setName("premlist") .setCurrency(JPY) @@ -230,20 +226,20 @@ public class PremiumListSqlDaoTest { BigDecimal.valueOf(15000))) .setCreationTime(fakeClock.nowUtc()) .build()); - assertThat(PremiumListSqlDao.getPremiumPrice("premlist", "silver")).hasValue(moneyOf(JPY, 10)); - assertThat(PremiumListSqlDao.getPremiumPrice("premlist", "gold")).hasValue(moneyOf(JPY, 1000)); - assertThat(PremiumListSqlDao.getPremiumPrice("premlist", "palladium")) + assertThat(PremiumListDao.getPremiumPrice("premlist", "silver")).hasValue(moneyOf(JPY, 10)); + assertThat(PremiumListDao.getPremiumPrice("premlist", "gold")).hasValue(moneyOf(JPY, 1000)); + assertThat(PremiumListDao.getPremiumPrice("premlist", "palladium")) .hasValue(moneyOf(JPY, 15000)); } @Test void test_savePremiumList_clearsCache() { - assertThat(PremiumListSqlDao.premiumListCache.getIfPresent("testname")).isNull(); - PremiumListSqlDao.save(testList); - PremiumList pl = PremiumListSqlDao.getLatestRevision("testname").get(); - assertThat(PremiumListSqlDao.premiumListCache.getIfPresent("testname").get()).isEqualTo(pl); - transactIfJpaTm(() -> PremiumListSqlDao.save("testname", ImmutableList.of("test,USD 1"))); - assertThat(PremiumListSqlDao.premiumListCache.getIfPresent("testname")).isNull(); + assertThat(PremiumListDao.premiumListCache.getIfPresent("testname")).isNull(); + PremiumListDao.save(testList); + PremiumList pl = PremiumListDao.getLatestRevision("testname").get(); + assertThat(PremiumListDao.premiumListCache.getIfPresent("testname").get()).isEqualTo(pl); + transactIfJpaTm(() -> PremiumListDao.save("testname", ImmutableList.of("test,USD 1"))); + assertThat(PremiumListDao.premiumListCache.getIfPresent("testname")).isNull(); } private static Money moneyOf(CurrencyUnit unit, double amount) { diff --git a/core/src/test/java/google/registry/testing/DatabaseHelper.java b/core/src/test/java/google/registry/testing/DatabaseHelper.java index 56501b852..b03e9118e 100644 --- a/core/src/test/java/google/registry/testing/DatabaseHelper.java +++ b/core/src/test/java/google/registry/testing/DatabaseHelper.java @@ -30,11 +30,10 @@ import static google.registry.model.EppResourceUtils.createRepoId; import static google.registry.model.ImmutableObjectSubject.assertAboutImmutableObjects; import static google.registry.model.ImmutableObjectSubject.immutableObjectCorrespondence; import static google.registry.model.ResourceTransferUtils.createTransferResponse; +import static google.registry.model.ofy.ObjectifyService.allocateId; import static google.registry.model.ofy.ObjectifyService.auditedOfy; import static google.registry.model.registry.Registry.TldState.GENERAL_AVAILABILITY; -import static google.registry.model.registry.label.PremiumListDatastoreDao.parentPremiumListEntriesOnRevision; import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm; -import static google.registry.persistence.transaction.TransactionManagerFactory.ofyTm; import static google.registry.persistence.transaction.TransactionManagerFactory.tm; import static google.registry.persistence.transaction.TransactionManagerUtil.ofyTmOrDoNothing; import static google.registry.persistence.transaction.TransactionManagerUtil.transactIfJpaTm; @@ -99,8 +98,6 @@ import google.registry.model.registry.Registry.TldState; import google.registry.model.registry.Registry.TldType; import google.registry.model.registry.label.PremiumList; import google.registry.model.registry.label.PremiumList.PremiumListEntry; -import google.registry.model.registry.label.PremiumList.PremiumListRevision; -import google.registry.model.registry.label.PremiumListDualDao; import google.registry.model.registry.label.ReservedList; import google.registry.model.registry.label.ReservedListDualDatabaseDao; import google.registry.model.reporting.HistoryEntry; @@ -110,6 +107,7 @@ import google.registry.model.transfer.DomainTransferData; import google.registry.model.transfer.TransferData; import google.registry.model.transfer.TransferStatus; import google.registry.persistence.VKey; +import google.registry.schema.tld.PremiumListDao; import google.registry.tmch.LordnTaskUtils; import java.lang.reflect.Field; import java.util.List; @@ -391,33 +389,14 @@ public class DatabaseHelper { toImmutableMap( Map.Entry::getKey, entry -> entry.getValue().getValue().getAmount()))) .build(); - PremiumListRevision revision = PremiumListRevision.create(premiumList, entries.keySet()); - - ImmutableList premiumListOfyObjects = - ImmutableList.of( - premiumList.asBuilder().setRevision(Key.create(revision)).build(), revision); - ImmutableSet entriesOnRevision = - parentPremiumListEntriesOnRevision(entries.values(), Key.create(revision)); - if (alwaysSaveWithBackup) { - ofyTm() - .transact( - () -> { - ofyTm().putAll(premiumListOfyObjects); - ofyTm().putAll(entriesOnRevision); - }); - } else { - ofyTm().putAllWithoutBackup(premiumListOfyObjects); - ofyTm().putAllWithoutBackup(entriesOnRevision); - } + // Since we used to persist a PremiumList to Datastore here, it is necessary to allocate an ID + // here to prevent breaking some of the hard-coded flow tests. IDs in tests are allocated in a + // strictly increasing sequence, if we don't pad out the ID here, we would have to renumber + // hundreds of unit tests. + allocateId(); jpaTm().transact(() -> jpaTm().insert(premiumList)); maybeAdvanceClock(); - // The above premiumList is in the session cache and it is different from the corresponding - // entity stored in Datastore because it has some @Ignore fields set dedicated for SQL. This - // breaks the assumption we have in our application code, see - // PremiumListUtils.savePremiumListAndEntries(). Clearing the session cache can help make sure - // we always get the same list. - tm().clearSessionCache(); - return transactIfJpaTm(() -> tm().loadByEntity(premiumList)); + return premiumList; } /** Creates and persists a tld. */ @@ -1243,7 +1222,7 @@ public class DatabaseHelper { /** Returns the entire map of {@link PremiumListEntry}s for the given {@link PremiumList}. */ public static ImmutableMap loadPremiumListEntries( PremiumList premiumList) { - return Streams.stream(PremiumListDualDao.loadAllPremiumListEntries(premiumList.getName())) + return Streams.stream(PremiumListDao.loadAllPremiumListEntries(premiumList.getName())) .collect(toImmutableMap(PremiumListEntry::getLabel, Function.identity())); } diff --git a/core/src/test/java/google/registry/testing/TestCacheExtension.java b/core/src/test/java/google/registry/testing/TestCacheExtension.java index 020c190a9..0bce2e0d2 100644 --- a/core/src/test/java/google/registry/testing/TestCacheExtension.java +++ b/core/src/test/java/google/registry/testing/TestCacheExtension.java @@ -18,8 +18,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.Maps; import google.registry.model.EppResource; import google.registry.model.index.ForeignKeyIndex; -import google.registry.model.registry.label.PremiumListDatastoreDao; -import google.registry.schema.tld.PremiumListSqlDao; +import google.registry.schema.tld.PremiumListDao; import java.util.Map; import java.util.Optional; import org.joda.time.Duration; @@ -72,17 +71,7 @@ public class TestCacheExtension implements BeforeEachCallback, AfterEachCallback public Builder withPremiumListsCache(Duration expiry) { cacheHandlerMap.put( "PremiumListSqlDao.premiumListCache", - new TestCacheHandler(PremiumListSqlDao::setPremiumListCacheForTest, expiry)); - cacheHandlerMap.put( - "PremiumListDatastoreDao.premiumListCache", - new TestCacheHandler(PremiumListDatastoreDao::setPremiumListCacheForTest, expiry)); - return this; - } - - public Builder withPremiumListEntriesCache(Duration expiry) { - cacheHandlerMap.put( - "PremiumList.cachePremiumListEntries", - new TestCacheHandler(PremiumListDatastoreDao::setPremiumListEntriesCacheForTest, expiry)); + new TestCacheHandler(PremiumListDao::setPremiumListCacheForTest, expiry)); return this; } diff --git a/core/src/test/java/google/registry/tools/ComparePremiumListsCommandTest.java b/core/src/test/java/google/registry/tools/ComparePremiumListsCommandTest.java deleted file mode 100644 index 0d27eb719..000000000 --- a/core/src/test/java/google/registry/tools/ComparePremiumListsCommandTest.java +++ /dev/null @@ -1,86 +0,0 @@ -// Copyright 2021 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.tools; - -import static com.google.common.truth.Truth.assertThat; -import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm; -import static google.registry.persistence.transaction.TransactionManagerFactory.ofyTm; -import static google.registry.testing.DatabaseHelper.persistPremiumList; -import static org.joda.money.CurrencyUnit.USD; - -import com.google.common.collect.ImmutableMap; -import google.registry.model.registry.label.PremiumList; -import google.registry.model.registry.label.PremiumListDatastoreDao; -import google.registry.schema.tld.PremiumListSqlDao; -import java.math.BigDecimal; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -public class ComparePremiumListsCommandTest extends CommandTestCase { - - @BeforeEach - void beforeEach() { - persistPremiumList("xn--q9jyb4c", "rich,USD 100"); - persistPremiumList("how", "richer,JPY 10000"); - } - - @Test - void test_success() throws Exception { - runCommand(); - assertThat(getStdoutAsString()).isEqualTo("Found 0 unequal list(s).\n"); - } - - @Test - void test_listMissingFromCloudSql() throws Exception { - jpaTm() - .transact( - () -> { - PremiumList premiumList = PremiumListSqlDao.getLatestRevision("how").get(); - PremiumListSqlDao.delete(premiumList); - }); - runCommand(); - assertThat(getStdoutAsString()) - .isEqualTo( - "PremiumList 'how' is present in Datastore, but not in Cloud SQL.\n" - + "Found 1 unequal list(s).\n"); - } - - @Test - void test_listMissingFromDatastore() throws Exception { - PremiumList premiumList = PremiumListDatastoreDao.getLatestRevision("how").get(); - ofyTm().transact(() -> ofyTm().delete(premiumList)); - runCommand(); - assertThat(getStdoutAsString()) - .isEqualTo( - "PremiumList 'how' is present in Cloud SQL, but not in Datastore.\n" - + "Found 1 unequal list(s).\n"); - } - - @Test - void test_listsDiffer() throws Exception { - PremiumListSqlDao.save( - new PremiumList.Builder() - .setName("how") - .setCurrency(USD) - .setLabelsToPrices(ImmutableMap.of("silver", BigDecimal.valueOf(30.03))) - .setCreationTime(fakeClock.nowUtc()) - .build()); - runCommand(); - assertThat(getStdoutAsString()) - .isEqualTo( - "PremiumList 'how' has different entries in each database.\n" - + "Found 1 unequal list(s).\n"); - } -} diff --git a/core/src/test/java/google/registry/tools/CreateDomainCommandTest.java b/core/src/test/java/google/registry/tools/CreateDomainCommandTest.java index 07da40141..b8a14d69a 100644 --- a/core/src/test/java/google/registry/tools/CreateDomainCommandTest.java +++ b/core/src/test/java/google/registry/tools/CreateDomainCommandTest.java @@ -22,7 +22,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import com.beust.jcommander.ParameterException; import google.registry.model.registry.Registry; -import google.registry.model.registry.label.PremiumListDualDao; +import google.registry.schema.tld.PremiumListDao; import google.registry.testing.DeterministicStringGenerator; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -101,7 +101,7 @@ class CreateDomainCommandTest extends EppToolCommandTestCase void verify_registryIsSetUpCorrectly() { // ensure that no premium list is created before running the command // this check also implicitly verifies the TLD is successfully created; - assertThat(PremiumListSqlDao.getLatestRevision(TLD_TEST).isPresent()).isFalse(); + assertThat(PremiumListDao.getLatestRevision(TLD_TEST).isPresent()).isFalse(); } @Test void commandRun_successCreateList() throws Exception { runCommandForced("--name=" + TLD_TEST, "--input=" + premiumTermsPath); assertThat(registry.getTld().toString()).isEqualTo(TLD_TEST); - assertThat(PremiumListSqlDao.getLatestRevision(TLD_TEST).isPresent()).isTrue(); + assertThat(PremiumListDao.getLatestRevision(TLD_TEST).isPresent()).isTrue(); } @Test diff --git a/core/src/test/java/google/registry/tools/DeletePremiumListCommandTest.java b/core/src/test/java/google/registry/tools/DeletePremiumListCommandTest.java index 3c0662af8..e9324d25d 100644 --- a/core/src/test/java/google/registry/tools/DeletePremiumListCommandTest.java +++ b/core/src/test/java/google/registry/tools/DeletePremiumListCommandTest.java @@ -24,7 +24,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import google.registry.model.registry.Registry; import google.registry.model.registry.label.PremiumList; -import google.registry.model.registry.label.PremiumListDualDao; +import google.registry.schema.tld.PremiumListDao; import org.junit.jupiter.api.Test; /** Unit tests for {@link DeletePremiumListCommand}. */ @@ -35,7 +35,7 @@ class DeletePremiumListCommandTest extends CommandTestCase runCommandForced("--name=" + premiumList.getName())); - assertThat(PremiumListDualDao.getLatestRevision(premiumList.getName())).isPresent(); + assertThat(PremiumListDao.getLatestRevision(premiumList.getName())).isPresent(); assertThat(thrown) .hasMessageThat() .isEqualTo("Cannot delete premium list because it is used on these tld(s): xn--q9jyb4c"); diff --git a/core/src/test/java/google/registry/tools/UpdatePremiumListCommandTest.java b/core/src/test/java/google/registry/tools/UpdatePremiumListCommandTest.java index 5ec85c9cc..8f01fed80 100644 --- a/core/src/test/java/google/registry/tools/UpdatePremiumListCommandTest.java +++ b/core/src/test/java/google/registry/tools/UpdatePremiumListCommandTest.java @@ -21,7 +21,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import com.google.common.collect.ImmutableSet; import com.google.common.io.Files; import google.registry.model.registry.Registry; -import google.registry.schema.tld.PremiumListSqlDao; +import google.registry.schema.tld.PremiumListDao; import java.io.File; import java.nio.file.Path; import java.nio.file.Paths; @@ -41,7 +41,7 @@ class UpdatePremiumListCommandTest @Test void verify_registryIsSetUpCorrectly() { // ensure that no premium list is created before running the command - assertThat(PremiumListSqlDao.getLatestRevision(TLD_TEST).isPresent()).isTrue(); + assertThat(PremiumListDao.getLatestRevision(TLD_TEST).isPresent()).isTrue(); // ensure that there's value in existing premium list; UpdatePremiumListCommand command = new UpdatePremiumListCommand(); ImmutableSet entries = command.getExistingPremiumListEntry(TLD_TEST); diff --git a/core/src/test/java/google/registry/tools/server/CreatePremiumListActionTest.java b/core/src/test/java/google/registry/tools/server/CreatePremiumListActionTest.java index 15f29ac05..6971710a3 100644 --- a/core/src/test/java/google/registry/tools/server/CreatePremiumListActionTest.java +++ b/core/src/test/java/google/registry/tools/server/CreatePremiumListActionTest.java @@ -20,9 +20,8 @@ import static google.registry.testing.DatabaseHelper.createTlds; import static google.registry.testing.DatabaseHelper.loadPremiumListEntries; import static javax.servlet.http.HttpServletResponse.SC_OK; -import google.registry.model.registry.Registry; import google.registry.model.registry.label.PremiumList; -import google.registry.model.registry.label.PremiumListDualDao; +import google.registry.schema.tld.PremiumListDao; import google.registry.testing.AppEngineExtension; import google.registry.testing.FakeJsonResponse; import org.joda.money.Money; @@ -45,7 +44,7 @@ public class CreatePremiumListActionTest { @BeforeEach void beforeEach() { createTlds("foo", "xn--q9jyb4c", "how"); - PremiumListDualDao.delete(PremiumListDualDao.getLatestRevision("foo").get()); + PremiumListDao.delete(PremiumListDao.getLatestRevision("foo").get()); action = new CreatePremiumListAction(); response = new FakeJsonResponse(); action.response = response; @@ -89,7 +88,7 @@ public class CreatePremiumListActionTest { action.override = true; action.run(); assertThat(response.getStatus()).isEqualTo(SC_OK); - assertThat(loadPremiumListEntries(PremiumListDualDao.getLatestRevision("zanzibar").get())) + assertThat(loadPremiumListEntries(PremiumListDao.getLatestRevision("zanzibar").get())) .hasSize(1); } @@ -99,10 +98,10 @@ public class CreatePremiumListActionTest { action.inputData = "rich,USD 25\nricher,USD 1000\n"; action.run(); assertThat(response.getStatus()).isEqualTo(SC_OK); - PremiumList premiumList = PremiumListDualDao.getLatestRevision("foo").get(); + PremiumList premiumList = PremiumListDao.getLatestRevision("foo").get(); assertThat(loadPremiumListEntries(premiumList)).hasSize(2); - assertThat(PremiumListDualDao.getPremiumPrice("rich", Registry.get("foo"))) + assertThat(PremiumListDao.getPremiumPrice(premiumList.getName(), "rich")) .hasValue(Money.parse("USD 25")); - assertThat(PremiumListDualDao.getPremiumPrice("diamond", Registry.get("foo"))).isEmpty(); + assertThat(PremiumListDao.getPremiumPrice(premiumList.getName(), "diamond")).isEmpty(); } } diff --git a/core/src/test/java/google/registry/tools/server/UpdatePremiumListActionTest.java b/core/src/test/java/google/registry/tools/server/UpdatePremiumListActionTest.java index 11f3f9130..47972821d 100644 --- a/core/src/test/java/google/registry/tools/server/UpdatePremiumListActionTest.java +++ b/core/src/test/java/google/registry/tools/server/UpdatePremiumListActionTest.java @@ -23,10 +23,8 @@ import static javax.servlet.http.HttpServletResponse.SC_OK; import com.google.common.base.Splitter; import com.google.common.truth.Truth8; -import google.registry.model.registry.Registry; import google.registry.model.registry.label.PremiumList; -import google.registry.model.registry.label.PremiumListDualDao; -import google.registry.schema.tld.PremiumListSqlDao; +import google.registry.schema.tld.PremiumListDao; import google.registry.testing.AppEngineExtension; import google.registry.testing.DatabaseHelper; import google.registry.testing.FakeJsonResponse; @@ -81,26 +79,24 @@ class UpdatePremiumListActionTest { .omitEmptyStrings() .splitToList( readResourceUtf8(DatabaseHelper.class, "default_premium_list_testdata.csv")); - PremiumListDualDao.save("foo", inputLines); + PremiumListDao.save("foo", inputLines); action.name = "foo"; action.inputData = "rich,USD 75\nricher,USD 5000\npoor, USD 0.99"; action.run(); assertThat(response.getStatus()).isEqualTo(SC_OK); - Registry registry = Registry.get("foo"); - assertThat(loadPremiumListEntries(PremiumListDualDao.getLatestRevision("foo").get())) - .hasSize(3); - Truth8.assertThat(PremiumListDualDao.getPremiumPrice("rich", registry)) + assertThat(loadPremiumListEntries(PremiumListDao.getLatestRevision("foo").get())).hasSize(3); + Truth8.assertThat(PremiumListDao.getPremiumPrice("foo", "rich")) .hasValue(Money.parse("USD 75")); - Truth8.assertThat(PremiumListDualDao.getPremiumPrice("richer", registry)) + Truth8.assertThat(PremiumListDao.getPremiumPrice("foo", "richer")) .hasValue(Money.parse("USD 5000")); - Truth8.assertThat(PremiumListDualDao.getPremiumPrice("poor", registry)) + Truth8.assertThat(PremiumListDao.getPremiumPrice("foo", "poor")) .hasValue(Money.parse("USD 0.99")); - Truth8.assertThat(PremiumListDualDao.getPremiumPrice("diamond", registry)).isEmpty(); + Truth8.assertThat(PremiumListDao.getPremiumPrice("foo", "diamond")).isEmpty(); jpaTm() .transact( () -> { - PremiumList persistedList = PremiumListSqlDao.getLatestRevision("foo").get(); + PremiumList persistedList = PremiumListDao.getLatestRevision("foo").get(); assertThat(persistedList.getLabelsToPrices()) .containsEntry("rich", new BigDecimal("75.00")); assertThat(persistedList.getLabelsToPrices())