Move premium list static helper methods into their own class

It was kind of messy having all of that logic living alongside the
entities themselves.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=148498024
This commit is contained in:
mcilwain 2017-02-24 13:38:59 -08:00 committed by Ben McIlwain
parent 388dd1055e
commit ea4e471c04
12 changed files with 523 additions and 421 deletions

View file

@ -17,7 +17,7 @@ package google.registry.model.pricing;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Strings.emptyToNull;
import static google.registry.model.registry.Registry.TldState.SUNRISE;
import static google.registry.model.registry.label.PremiumList.getPremiumPrice;
import static google.registry.model.registry.label.PremiumListUtils.getPremiumPrice;
import static google.registry.model.registry.label.ReservationType.NAME_COLLISION;
import static google.registry.model.registry.label.ReservedList.getReservation;
import static google.registry.util.DomainNameUtils.getTldFromDomainName;

View file

@ -13,10 +13,7 @@
// limitations under the License.
package google.registry.model.registry.label;
import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.Iterables.partition;
import static com.google.common.hash.Funnels.unencodedCharsFunnel;
import static google.registry.config.RegistryConfig.getDomainLabelListCacheDuration;
import static google.registry.config.RegistryConfig.getSingletonCachePersistDuration;
@ -28,20 +25,15 @@ import static google.registry.model.ofy.Ofy.RECOMMENDED_MEMCACHE_EXPIRATION;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Splitter;
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.FluentIterable;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.hash.BloomFilter;
import com.google.common.util.concurrent.UncheckedExecutionException;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.VoidWork;
import com.googlecode.objectify.Work;
import com.googlecode.objectify.annotation.Cache;
import com.googlecode.objectify.annotation.Entity;
@ -55,13 +47,11 @@ import google.registry.model.registry.Registry;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import javax.annotation.Nullable;
import org.joda.money.Money;
import org.joda.time.DateTime;
/**
* A premium list entity, persisted to Datastore, that is used to check domain label prices.
@ -71,9 +61,6 @@ import org.joda.time.DateTime;
@Cache(expirationSeconds = RECOMMENDED_MEMCACHE_EXPIRATION)
public final class PremiumList extends BaseDomainLabelList<Money, PremiumList.PremiumListEntry> {
/** The number of premium list entry entities that are created and deleted per batch. */
private static final int TRANSACTION_BATCH_SIZE = 200;
/** Stores the revision key for the set of currently used premium list entry entities. */
Key<PremiumListRevision> revisionKey;
@ -139,7 +126,7 @@ public final class PremiumList extends BaseDomainLabelList<Money, PremiumList.Pr
* <p>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.
*/
private static final LoadingCache<String, PremiumList> cachePremiumLists =
static final LoadingCache<String, PremiumList> cachePremiumLists =
CacheBuilder.newBuilder()
.expireAfterWrite(getDomainLabelListCacheDuration().getMillis(), MILLISECONDS)
.build(new CacheLoader<String, PremiumList>() {
@ -163,7 +150,7 @@ public final class PremiumList extends BaseDomainLabelList<Money, PremiumList.Pr
* {@link PremiumListRevision} is immutable and cannot ever be changed once created, so its cache
* need not ever expire.
*/
private static final LoadingCache<Key<PremiumListRevision>, PremiumListRevision>
static final LoadingCache<Key<PremiumListRevision>, PremiumListRevision>
cachePremiumListRevisions =
CacheBuilder.newBuilder()
.expireAfterWrite(getSingletonCachePersistDuration().getMillis(), MILLISECONDS)
@ -214,67 +201,6 @@ public final class PremiumList extends BaseDomainLabelList<Money, PremiumList.Pr
}});
}});
/**
* Returns the premium price for the specified label and registry, or absent if the label is not
* premium.
*/
public static Optional<Money> getPremiumPrice(String label, Registry registry) {
// If the registry has no configured premium list, then no labels are premium.
if (registry.getPremiumList() == null) {
return Optional.<Money> absent();
}
String listName = registry.getPremiumList().getName();
Optional<PremiumList> optionalPremiumList = get(listName);
checkState(optionalPremiumList.isPresent(), "Could not load premium list '%s'", listName);
PremiumList premiumList = optionalPremiumList.get();
PremiumListRevision revision;
try {
revision = cachePremiumListRevisions.get(premiumList.getRevisionKey());
} catch (InvalidCacheLoadException | ExecutionException e) {
throw new RuntimeException(
"Could not load premium list revision " + premiumList.getRevisionKey(), e);
}
checkState(
revision.probablePremiumLabels != null,
"Probable premium labels bloom filter is null on revision '%s'",
premiumList.getRevisionKey());
if (revision.probablePremiumLabels.mightContain(label)) {
Key<PremiumListEntry> entryKey =
Key.create(premiumList.getRevisionKey(), PremiumListEntry.class, label);
try {
Optional<PremiumListEntry> entry = cachePremiumListEntries.get(entryKey);
return (entry.isPresent()) ? Optional.of(entry.get().getValue()) : Optional.<Money>absent();
} catch (InvalidCacheLoadException | ExecutionException e) {
throw new RuntimeException("Could not load premium list entry " + entryKey, e);
}
} else {
return Optional.<Money>absent();
}
}
/**
* Loads and returns the entire premium list map.
*
* <p>This load operation is quite expensive for large premium lists because each premium list
* entry is a separate Datastore entity, and loading them this way bypasses the in-memory caches.
* Do not use this method if all you need to do is check the price of a small number of labels!
*/
@VisibleForTesting
public Map<String, PremiumListEntry> loadPremiumListEntries() {
try {
ImmutableMap.Builder<String, PremiumListEntry> entriesMap = new ImmutableMap.Builder<>();
if (revisionKey != null) {
for (PremiumListEntry entry : queryEntriesForCurrentRevision()) {
entriesMap.put(entry.getLabel(), entry);
}
}
return entriesMap.build();
} catch (Exception e) {
throw new RuntimeException("Could not retrieve entries for premium list " + name, e);
}
}
@VisibleForTesting
public Key<PremiumListRevision> getRevisionKey() {
return revisionKey;
@ -291,11 +217,6 @@ public final class PremiumList extends BaseDomainLabelList<Money, PremiumList.Pr
}
}
/** Returns whether a PremiumList of the given name exists, bypassing the cache. */
public static boolean exists(String name) {
return ofy().load().key(Key.create(getCrossTldKey(), PremiumList.class, name)).now() != null;
}
/**
* A premium list entry entity, persisted to Datastore. Each instance represents the price of a
* single label on a given TLD.
@ -361,124 +282,12 @@ public final class PremiumList extends BaseDomainLabelList<Money, PremiumList.Pr
.build();
}
public static PremiumList saveWithEntries(
PremiumList premiumList, Iterable<String> premiumListLines) {
return saveWithEntries(premiumList, premiumList.parse(premiumListLines));
}
/** Re-parents the given {@link PremiumListEntry}s on the given {@link PremiumListRevision}. */
public static ImmutableSet<PremiumListEntry> parentEntriesOnRevision(
Iterable<PremiumListEntry> entries, final Key<PremiumListRevision> revisionKey) {
return FluentIterable.from(firstNonNull(entries, ImmutableSet.of()))
.transform(
new Function<PremiumListEntry, PremiumListEntry>() {
@Override
public PremiumListEntry apply(PremiumListEntry entry) {
return entry.asBuilder().setParent(revisionKey).build();
}
})
.toSet();
}
/**
* Persists a new or updated PremiumList object and its descendant entities to Datastore.
*
* <p>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.
*
* <p>This is the only valid way to save these kinds of entities!
*/
public static PremiumList saveWithEntries(
final PremiumList premiumList, ImmutableMap<String, PremiumListEntry> premiumListEntries) {
final Optional<PremiumList> oldPremiumList = get(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<PremiumListRevision> newRevisionKey = Key.create(newRevision);
ImmutableSet<PremiumListEntry> parentedEntries =
parentEntriesOnRevision(
firstNonNull(premiumListEntries.values(), ImmutableSet.of()), newRevisionKey);
// Save the new child entities in a series of transactions.
for (final List<PremiumListEntry> batch : partition(parentedEntries, TRANSACTION_BATCH_SIZE)) {
ofy().transactNew(new VoidWork() {
@Override
public void vrun() {
ofy().save().entities(batch);
}});
}
// Save the new PremiumList and revision itself.
PremiumList updated = ofy().transactNew(new Work<PremiumList>() {
@Override
public PremiumList run() {
DateTime now = ofy().getTransactionTime();
// Assert that the premium list hasn't been changed since we started this process.
PremiumList existing = ofy().load()
.type(PremiumList.class)
.parent(getCrossTldKey())
.id(premiumList.getName())
.now();
checkState(
Objects.equals(existing, oldPremiumList.orNull()),
"PremiumList was concurrently edited");
PremiumList newList = premiumList.asBuilder()
.setLastUpdateTime(now)
.setCreationTime(
oldPremiumList.isPresent() ? oldPremiumList.get().creationTime : now)
.setRevision(newRevisionKey)
.build();
ofy().save().entities(newList, newRevision);
return newList;
}});
// Update the cache.
cachePremiumLists.put(premiumList.getName(), updated);
// Delete the entities under the old PremiumList.
if (oldPremiumList.isPresent()) {
oldPremiumList.get().deleteRevisionAndEntries();
}
return updated;
}
@Override
public boolean refersToKey(Registry registry, Key<? extends BaseDomainLabelList<?, ?>> key) {
return Objects.equals(registry.getPremiumList(), key);
}
/** Deletes the PremiumList and all of its child entities. */
public void delete() {
ofy().transactNew(new VoidWork() {
@Override
public void vrun() {
ofy().delete().entity(PremiumList.this);
}});
deleteRevisionAndEntries();
cachePremiumLists.invalidate(name);
}
private void deleteRevisionAndEntries() {
if (revisionKey == null) {
return;
}
for (final List<Key<PremiumListEntry>> batch : partition(
queryEntriesForCurrentRevision().keys(),
TRANSACTION_BATCH_SIZE)) {
ofy().transactNew(new VoidWork() {
@Override
public void vrun() {
ofy().delete().keys(batch);
}});
}
ofy().transactNew(new VoidWork() {
@Override
public void vrun() {
ofy().delete().key(revisionKey);
}});
}
private Query<PremiumListEntry> queryEntriesForCurrentRevision() {
Query<PremiumListEntry> queryEntriesForCurrentRevision() {
return ofy().load().type(PremiumListEntry.class).ancestor(revisionKey);
}

View file

@ -0,0 +1,234 @@
// 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.base.MoreObjects.firstNonNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.Iterables.partition;
import static google.registry.model.common.EntityGroupRoot.getCrossTldKey;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.registry.label.PremiumList.cachePremiumListEntries;
import static google.registry.model.registry.label.PremiumList.cachePremiumListRevisions;
import static google.registry.model.registry.label.PremiumList.cachePremiumLists;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.cache.CacheLoader.InvalidCacheLoadException;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.VoidWork;
import com.googlecode.objectify.Work;
import google.registry.model.registry.Registry;
import google.registry.model.registry.label.PremiumList.PremiumListEntry;
import google.registry.model.registry.label.PremiumList.PremiumListRevision;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ExecutionException;
import org.joda.money.Money;
import org.joda.time.DateTime;
/** Static helper methods for working with {@link PremiumList}s. */
public final class PremiumListUtils {
/** The number of premium list entry entities that are created and deleted per batch. */
static final int TRANSACTION_BATCH_SIZE = 200;
/**
* Returns the premium price for the specified label and registry, or absent if the label is not
* premium.
*/
public static Optional<Money> getPremiumPrice(String label, Registry registry) {
// If the registry has no configured premium list, then no labels are premium.
if (registry.getPremiumList() == null) {
return Optional.<Money> absent();
}
String listName = registry.getPremiumList().getName();
Optional<PremiumList> optionalPremiumList = PremiumList.get(listName);
checkState(optionalPremiumList.isPresent(), "Could not load premium list '%s'", listName);
PremiumList premiumList = optionalPremiumList.get();
PremiumListRevision revision;
try {
revision = cachePremiumListRevisions.get(premiumList.getRevisionKey());
} catch (InvalidCacheLoadException | ExecutionException e) {
throw new RuntimeException(
"Could not load premium list revision " + premiumList.getRevisionKey(), e);
}
checkState(
revision.probablePremiumLabels != null,
"Probable premium labels bloom filter is null on revision '%s'",
premiumList.getRevisionKey());
if (revision.probablePremiumLabels.mightContain(label)) {
Key<PremiumListEntry> entryKey =
Key.create(premiumList.getRevisionKey(), PremiumListEntry.class, label);
try {
Optional<PremiumListEntry> entry = cachePremiumListEntries.get(entryKey);
return (entry.isPresent()) ? Optional.of(entry.get().getValue()) : Optional.<Money>absent();
} catch (InvalidCacheLoadException | ExecutionException e) {
throw new RuntimeException("Could not load premium list entry " + entryKey, e);
}
} else {
return Optional.<Money>absent();
}
}
/**
* Persists a new or updated PremiumList object and its descendant entities to Datastore.
*
* <p>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.
*
* <p>This is the only valid way to save these kinds of entities!
*/
public static PremiumList savePremiumListAndEntries(
final PremiumList premiumList,
ImmutableMap<String, PremiumListEntry> premiumListEntries) {
final Optional<PremiumList> oldPremiumList = PremiumList.get(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<PremiumListRevision> newRevisionKey = Key.create(newRevision);
ImmutableSet<PremiumListEntry> parentedEntries =
parentPremiumListEntriesOnRevision(
firstNonNull(premiumListEntries.values(), ImmutableSet.of()), newRevisionKey);
// Save the new child entities in a series of transactions.
for (final List<PremiumListEntry> batch :
partition(parentedEntries, TRANSACTION_BATCH_SIZE)) {
ofy().transactNew(new VoidWork() {
@Override
public void vrun() {
ofy().save().entities(batch);
}});
}
// Save the new PremiumList and revision itself.
PremiumList updated = ofy().transactNew(new Work<PremiumList>() {
@Override
public PremiumList run() {
DateTime now = ofy().getTransactionTime();
// Assert that the premium list hasn't been changed since we started this process.
PremiumList existing = ofy().load()
.type(PremiumList.class)
.parent(getCrossTldKey())
.id(premiumList.getName())
.now();
checkState(
Objects.equals(existing, oldPremiumList.orNull()),
"PremiumList was concurrently edited");
PremiumList newList = premiumList.asBuilder()
.setLastUpdateTime(now)
.setCreationTime(
oldPremiumList.isPresent() ? oldPremiumList.get().creationTime : now)
.setRevision(newRevisionKey)
.build();
ofy().save().entities(newList, newRevision);
return newList;
}});
// Update the cache.
cachePremiumLists.put(premiumList.getName(), updated);
// Delete the entities under the old PremiumList.
if (oldPremiumList.isPresent()) {
deleteRevisionAndEntriesOfPremiumList(oldPremiumList.get());
}
return updated;
}
public static PremiumList savePremiumListAndEntries(
PremiumList premiumList, Iterable<String> premiumListLines) {
return savePremiumListAndEntries(premiumList, premiumList.parse(premiumListLines));
}
/** Re-parents the given {@link PremiumListEntry}s on the given {@link PremiumListRevision}. */
public static ImmutableSet<PremiumListEntry> parentPremiumListEntriesOnRevision(
Iterable<PremiumListEntry> entries, final Key<PremiumListRevision> revisionKey) {
return FluentIterable.from(firstNonNull(entries, ImmutableSet.of()))
.transform(
new Function<PremiumListEntry, PremiumListEntry>() {
@Override
public PremiumListEntry apply(PremiumListEntry entry) {
return entry.asBuilder().setParent(revisionKey).build();
}
})
.toSet();
}
/** Deletes the PremiumList and all of its child entities. */
public static void deletePremiumList(final PremiumList premiumList) {
ofy().transactNew(new VoidWork() {
@Override
public void vrun() {
ofy().delete().entity(premiumList);
}});
deleteRevisionAndEntriesOfPremiumList(premiumList);
cachePremiumLists.invalidate(premiumList.getName());
}
static void deleteRevisionAndEntriesOfPremiumList(final PremiumList premiumList) {
if (premiumList.getRevisionKey() == null) {
return;
}
for (final List<Key<PremiumListEntry>> batch : partition(
premiumList.queryEntriesForCurrentRevision().keys(),
TRANSACTION_BATCH_SIZE)) {
ofy().transactNew(new VoidWork() {
@Override
public void vrun() {
ofy().delete().keys(batch);
}});
}
ofy().transactNew(new VoidWork() {
@Override
public void vrun() {
ofy().delete().key(premiumList.getRevisionKey());
}});
}
/** Returns whether a PremiumList of the given name exists, bypassing the cache. */
public static boolean doesPremiumListExist(String name) {
return ofy().load().key(Key.create(getCrossTldKey(), PremiumList.class, name)).now() != null;
}
/**
* Loads and returns the entire premium list map.
*
* <p>This load operation is quite expensive for large premium lists because each premium list
* entry is a separate Datastore entity, and loading them this way bypasses the in-memory caches.
* Do not use this method if all you need to do is check the price of a small number of labels!
*/
@VisibleForTesting
public static Map<String, PremiumListEntry> loadPremiumListEntries(PremiumList premiumList) {
try {
ImmutableMap.Builder<String, PremiumListEntry> entriesMap = new ImmutableMap.Builder<>();
if (premiumList.getRevisionKey() != null) {
for (PremiumListEntry entry : premiumList.queryEntriesForCurrentRevision()) {
entriesMap.put(entry.getLabel(), entry);
}
}
return entriesMap.build();
} catch (Exception e) {
throw new RuntimeException(
"Could not retrieve entries for premium list " + premiumList.getName(), e);
}
}
private PremiumListUtils() {}
}

View file

@ -15,6 +15,8 @@
package google.registry.tools;
import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.model.registry.label.PremiumListUtils.deletePremiumList;
import static google.registry.model.registry.label.PremiumListUtils.doesPremiumListExist;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;
@ -43,7 +45,7 @@ final class DeletePremiumListCommand extends ConfirmingCommand implements Remote
@Override
protected void init() throws Exception {
checkArgument(
PremiumList.exists(name),
doesPremiumListExist(name),
"Cannot delete the premium list %s because it doesn't exist.",
name);
premiumList = PremiumList.get(name).get();
@ -61,7 +63,7 @@ final class DeletePremiumListCommand extends ConfirmingCommand implements Remote
@Override
protected String execute() throws Exception {
premiumList.delete();
deletePremiumList(premiumList);
return String.format("Deleted premium list '%s'.\n", premiumList.getName());
}
}

View file

@ -16,7 +16,8 @@ package google.registry.tools.server;
import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.model.registry.Registries.assertTldExists;
import static google.registry.model.registry.label.PremiumList.saveWithEntries;
import static google.registry.model.registry.label.PremiumListUtils.doesPremiumListExist;
import static google.registry.model.registry.label.PremiumListUtils.savePremiumListAndEntries;
import static google.registry.request.Action.Method.POST;
import com.google.common.base.Splitter;
@ -43,8 +44,7 @@ public class CreatePremiumListAction extends CreateOrUpdatePremiumListAction {
@Override
protected void savePremiumList() {
checkArgument(
!PremiumList.exists(name),
"A premium list of this name already exists: %s.", name);
!doesPremiumListExist(name), "A premium list of this name already exists: %s.", name);
if (!override) {
assertTldExists(name);
}
@ -54,7 +54,7 @@ public class CreatePremiumListAction extends CreateOrUpdatePremiumListAction {
List<String> inputDataPreProcessed =
Splitter.on('\n').omitEmptyStrings().splitToList(inputData);
PremiumList premiumList = new PremiumList.Builder().setName(name).build();
saveWithEntries(premiumList, inputDataPreProcessed);
savePremiumListAndEntries(premiumList, inputDataPreProcessed);
String message =
String.format(

View file

@ -15,7 +15,7 @@
package google.registry.tools.server;
import static com.google.common.base.Preconditions.checkArgument;
import static google.registry.model.registry.label.PremiumList.saveWithEntries;
import static google.registry.model.registry.label.PremiumListUtils.savePremiumListAndEntries;
import static google.registry.request.Action.Method.POST;
import com.google.common.base.Optional;
@ -49,7 +49,8 @@ public class UpdatePremiumListAction extends CreateOrUpdatePremiumListAction {
logger.infofmt("Got the following input data: %s", inputData);
List<String> inputDataPreProcessed =
Splitter.on('\n').omitEmptyStrings().splitToList(inputData);
PremiumList newPremiumList = saveWithEntries(existingPremiumList.get(), inputDataPreProcessed);
PremiumList newPremiumList =
savePremiumListAndEntries(existingPremiumList.get(), inputDataPreProcessed);
String message =
String.format(

View file

@ -17,9 +17,6 @@ package google.registry.model.registry.label;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.registry.label.PremiumList.cachePremiumListEntries;
import static google.registry.model.registry.label.PremiumList.getPremiumPrice;
import static google.registry.model.registry.label.PremiumList.saveWithEntries;
import static google.registry.testing.DatastoreHelper.createTld;
import static google.registry.testing.DatastoreHelper.persistPremiumList;
import static google.registry.testing.DatastoreHelper.persistReservedList;
@ -28,14 +25,11 @@ import static google.registry.testing.DatastoreHelper.persistResource;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.googlecode.objectify.Key;
import google.registry.model.pricing.StaticPremiumListPricingEngine;
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.AppEngineRule;
import google.registry.testing.ExceptionRule;
import java.util.Map;
import org.joda.money.Money;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@ -46,19 +40,15 @@ import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public class PremiumListTest {
@Rule
public final ExceptionRule thrown = new ExceptionRule();
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
@Rule public final ExceptionRule thrown = new ExceptionRule();
@Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
@Before
public void before() throws Exception {
// createTld() overwrites the premium list, so call it first.
createTld("tld");
PremiumList pl = persistPremiumList(
PremiumList pl =
persistPremiumList(
"tld",
"lol,USD 999 # yup",
"rich,USD 1999 #tada",
@ -67,153 +57,6 @@ public class PremiumListTest {
persistResource(Registry.get("tld").asBuilder().setPremiumList(pl).build());
}
@Test
public void testGetPremiumPrice_returnsNoPriceWhenNoPremiumListConfigured() throws Exception {
createTld("ghost");
persistResource(
new Registry.Builder()
.setTldStr("ghost")
.setPremiumPricingEngine(StaticPremiumListPricingEngine.NAME)
.build());
assertThat(Registry.get("ghost").getPremiumList()).isNull();
assertThat(getPremiumPrice("blah", Registry.get("ghost"))).isAbsent();
}
@Test
public void testGetPremiumPrice_throwsExceptionWhenNonExistentPremiumListConfigured()
throws Exception {
PremiumList.get("tld").get().delete();
thrown.expect(IllegalStateException.class, "Could not load premium list 'tld'");
getPremiumPrice("blah", Registry.get("tld"));
}
@Test
public void testSave_largeNumberOfEntries_succeeds() throws Exception {
PremiumList premiumList = persistHumongousPremiumList("tld", 2500);
assertThat(premiumList.loadPremiumListEntries()).hasSize(2500);
assertThat(getPremiumPrice("7", Registry.get("tld"))).hasValue(Money.parse("USD 100"));
}
@Test
public void testSave_updateTime_isUpdatedOnEverySave() throws Exception {
PremiumList pl =
saveWithEntries(
new PremiumList.Builder().setName("tld3").build(), ImmutableList.of("slime,USD 10"));
PremiumList newPl =
saveWithEntries(
new PremiumList.Builder().setName(pl.getName()).build(),
ImmutableList.of("mutants,USD 20"));
assertThat(newPl.getLastUpdateTime()).isGreaterThan(pl.getLastUpdateTime());
}
@Test
public void testSave_creationTime_onlyUpdatedOnFirstCreation() throws Exception {
PremiumList pl = persistPremiumList("tld3", "sludge,JPY 1000");
PremiumList newPl = saveWithEntries(pl, ImmutableList.of("sleighbells,CHF 2000"));
assertThat(newPl.creationTime).isEqualTo(pl.creationTime);
}
@Test
public void testSave_removedPremiumListEntries_areNoLongerInDatastore() throws Exception {
Registry registry = Registry.get("tld");
PremiumList pl = persistPremiumList("tld", "genius,USD 10", "dolt,JPY 1000");
assertThat(getPremiumPrice("genius", registry)).hasValue(Money.parse("USD 10"));
assertThat(getPremiumPrice("dolt", registry)).hasValue(Money.parse("JPY 1000"));
assertThat(ofy()
.load()
.type(PremiumListEntry.class)
.parent(pl.getRevisionKey())
.id("dolt")
.now()
.price)
.isEqualTo(Money.parse("JPY 1000"));
PremiumList pl2 = saveWithEntries(pl, ImmutableList.of("genius,USD 10", "savant,USD 90"));
assertThat(getPremiumPrice("genius", registry)).hasValue(Money.parse("USD 10"));
assertThat(getPremiumPrice("savant", registry)).hasValue(Money.parse("USD 90"));
assertThat(getPremiumPrice("dolt", registry)).isAbsent();
assertThat(ofy()
.load()
.type(PremiumListEntry.class)
.parent(pl.getRevisionKey())
.id("dolt")
.now())
.isNull();
assertThat(ofy()
.load()
.type(PremiumListEntry.class)
.parent(pl2.getRevisionKey())
.id("dolt")
.now())
.isNull();
}
@Test
public void testGetPremiumPrice_allLabelsAreNonPremium_whenNotInList() throws Exception {
assertThat(getPremiumPrice("blah", Registry.get("tld"))).isAbsent();
assertThat(getPremiumPrice("slinge", Registry.get("tld"))).isAbsent();
}
@Test
public void testSave_simple() throws Exception {
PremiumList pl =
saveWithEntries(
new PremiumList.Builder().setName("tld2").build(),
ImmutableList.of("lol , USD 999 # yupper rooni "));
createTld("tld");
persistResource(Registry.get("tld").asBuilder().setPremiumList(pl).build());
assertThat(getPremiumPrice("lol", Registry.get("tld"))).hasValue(Money.parse("USD 999"));
assertThat(getPremiumPrice("lol ", Registry.get("tld"))).isAbsent();
Map<String, PremiumListEntry> entries =
PremiumList.get("tld2").get().loadPremiumListEntries();
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");
}
@Test
public void test_saveAndUpdateEntriesTwice() throws Exception {
PremiumList pl =
saveWithEntries(
new PremiumList.Builder().setName("pl").build(), ImmutableList.of("test,USD 1"));
Map<String, PremiumListEntry> entries = pl.loadPremiumListEntries();
assertThat(entries.keySet()).containsExactly("test");
assertThat(PremiumList.get("pl").get().loadPremiumListEntries()).isEqualTo(entries);
// Save again with no changes, and clear the cache to force a re-load from Datastore.
PremiumList resaved = saveWithEntries(pl, ImmutableList.of("test,USD 1"));
ofy().clearSessionCache();
Map<String, PremiumListEntry> entriesReloaded =
PremiumList.get("pl").get().loadPremiumListEntries();
assertThat(entriesReloaded).hasSize(1);
assertThat(entriesReloaded).containsKey("test");
assertThat(entriesReloaded.get("test").parent).isEqualTo(resaved.getRevisionKey());
}
@Test
public void testDelete() throws Exception {
persistPremiumList("gtld1", "trombone,USD 10");
assertThat(PremiumList.get("gtld1")).isPresent();
Key<PremiumListRevision> parent = PremiumList.get("gtld1").get().getRevisionKey();
PremiumList.get("gtld1").get().delete();
assertThat(PremiumList.get("gtld1")).isAbsent();
assertThat(ofy().load().type(PremiumListEntry.class).ancestor(parent).list()).isEmpty();
}
@Test
public void testDelete_largeNumberOfEntries_succeeds() {
persistHumongousPremiumList("ginormous", 2500);
PremiumList.get("ginormous").get().delete();
assertThat(PremiumList.get("ginormous")).isAbsent();
}
@Test
public void testDelete_failsWhenListDoesntExist() throws Exception {
thrown.expect(IllegalStateException.class);
PremiumList.get("tld-premium-blah").get().delete();
}
@Test
public void testSave_badSyntax() throws Exception {
thrown.expect(IllegalArgumentException.class);
@ -226,32 +69,6 @@ public class PremiumListTest {
persistReservedList("gtld1", "lol,XBTC 200");
}
@Test
public void testExists() throws Exception {
assertThat(PremiumList.exists("tld")).isTrue();
assertThat(PremiumList.exists("nonExistentPremiumList")).isFalse();
}
@Test
public void testGetPremiumPrice_comesFromBloomFilter() throws Exception {
PremiumList pl = PremiumList.get("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(getPremiumPrice("missingno", Registry.get("tld"))).isAbsent();
// However, if we manually query the cache to force an entity load, it should be found.
assertThat(
cachePremiumListEntries.get(
Key.create(pl.getRevisionKey(), PremiumListEntry.class, "missingno")))
.hasValue(entry);
}
@Test
public void testProbablePremiumLabels() throws Exception {
PremiumList pl = PremiumList.get("tld").get();
@ -276,15 +93,6 @@ public class PremiumListTest {
"lol,USD 100", "rofl,USD 90", "paper,USD 80", "wood,USD 70", "lol,USD 200"));
}
/** 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);
}
/** Gets the label of a premium list entry. */
public static final Function<Key<PremiumListEntry>, String> GET_ENTRY_NAME_FUNCTION =
new Function<Key<PremiumListEntry>, String>() {

View file

@ -0,0 +1,248 @@
// 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.truth.Truth.assertThat;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.registry.label.PremiumList.cachePremiumListEntries;
import static google.registry.model.registry.label.PremiumListUtils.deletePremiumList;
import static google.registry.model.registry.label.PremiumListUtils.doesPremiumListExist;
import static google.registry.model.registry.label.PremiumListUtils.getPremiumPrice;
import static google.registry.model.registry.label.PremiumListUtils.loadPremiumListEntries;
import static google.registry.model.registry.label.PremiumListUtils.savePremiumListAndEntries;
import static google.registry.testing.DatastoreHelper.createTld;
import static google.registry.testing.DatastoreHelper.persistPremiumList;
import static google.registry.testing.DatastoreHelper.persistResource;
import com.google.common.collect.ImmutableList;
import com.googlecode.objectify.Key;
import google.registry.model.pricing.StaticPremiumListPricingEngine;
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.AppEngineRule;
import google.registry.testing.ExceptionRule;
import java.util.Map;
import org.joda.money.Money;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;
/** Unit tests for {@link PremiumListUtils}. */
@RunWith(JUnit4.class)
public class PremiumListUtilsTest {
@Rule public final ExceptionRule thrown = new ExceptionRule();
@Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
@Before
public void before() throws Exception {
// createTld() overwrites the premium list, so call it first.
createTld("tld");
PremiumList 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());
}
@Test
public void testGetPremiumPrice_returnsNoPriceWhenNoPremiumListConfigured() throws Exception {
createTld("ghost");
persistResource(
new Registry.Builder()
.setTldStr("ghost")
.setPremiumPricingEngine(StaticPremiumListPricingEngine.NAME)
.build());
assertThat(Registry.get("ghost").getPremiumList()).isNull();
assertThat(getPremiumPrice("blah", Registry.get("ghost"))).isAbsent();
}
@Test
public void testGetPremiumPrice_throwsExceptionWhenNonExistentPremiumListConfigured()
throws Exception {
deletePremiumList(PremiumList.get("tld").get());
thrown.expect(IllegalStateException.class, "Could not load premium list 'tld'");
getPremiumPrice("blah", Registry.get("tld"));
}
@Test
public void testSave_largeNumberOfEntries_succeeds() throws Exception {
PremiumList premiumList = persistHumongousPremiumList("tld", 2500);
assertThat(loadPremiumListEntries(premiumList)).hasSize(2500);
assertThat(getPremiumPrice("7", Registry.get("tld"))).hasValue(Money.parse("USD 100"));
}
@Test
public void testSave_updateTime_isUpdatedOnEverySave() throws Exception {
PremiumList pl =
savePremiumListAndEntries(
new PremiumList.Builder().setName("tld3").build(), ImmutableList.of("slime,USD 10"));
PremiumList newPl =
savePremiumListAndEntries(
new PremiumList.Builder().setName(pl.getName()).build(),
ImmutableList.of("mutants,USD 20"));
assertThat(newPl.getLastUpdateTime()).isGreaterThan(pl.getLastUpdateTime());
}
@Test
public void testSave_creationTime_onlyUpdatedOnFirstCreation() throws Exception {
PremiumList pl = persistPremiumList("tld3", "sludge,JPY 1000");
PremiumList newPl = savePremiumListAndEntries(pl, ImmutableList.of("sleighbells,CHF 2000"));
assertThat(newPl.creationTime).isEqualTo(pl.creationTime);
}
@Test
public void testExists() throws Exception {
assertThat(doesPremiumListExist("tld")).isTrue();
assertThat(doesPremiumListExist("nonExistentPremiumList")).isFalse();
}
@Test
public void testGetPremiumPrice_comesFromBloomFilter() throws Exception {
PremiumList pl = PremiumList.get("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(getPremiumPrice("missingno", Registry.get("tld"))).isAbsent();
// However, if we manually query the cache to force an entity load, it should be found.
assertThat(
cachePremiumListEntries.get(
Key.create(pl.getRevisionKey(), PremiumListEntry.class, "missingno")))
.hasValue(entry);
}
@Test
public void testSave_removedPremiumListEntries_areNoLongerInDatastore() throws Exception {
Registry registry = Registry.get("tld");
PremiumList pl = persistPremiumList("tld", "genius,USD 10", "dolt,JPY 1000");
assertThat(getPremiumPrice("genius", registry)).hasValue(Money.parse("USD 10"));
assertThat(getPremiumPrice("dolt", registry)).hasValue(Money.parse("JPY 1000"));
assertThat(ofy()
.load()
.type(PremiumListEntry.class)
.parent(pl.getRevisionKey())
.id("dolt")
.now()
.price)
.isEqualTo(Money.parse("JPY 1000"));
PremiumList pl2 =
savePremiumListAndEntries(pl, ImmutableList.of("genius,USD 10", "savant,USD 90"));
assertThat(getPremiumPrice("genius", registry)).hasValue(Money.parse("USD 10"));
assertThat(getPremiumPrice("savant", registry)).hasValue(Money.parse("USD 90"));
assertThat(getPremiumPrice("dolt", registry)).isAbsent();
assertThat(ofy()
.load()
.type(PremiumListEntry.class)
.parent(pl.getRevisionKey())
.id("dolt")
.now())
.isNull();
assertThat(ofy()
.load()
.type(PremiumListEntry.class)
.parent(pl2.getRevisionKey())
.id("dolt")
.now())
.isNull();
}
@Test
public void testGetPremiumPrice_allLabelsAreNonPremium_whenNotInList() throws Exception {
assertThat(getPremiumPrice("blah", Registry.get("tld"))).isAbsent();
assertThat(getPremiumPrice("slinge", Registry.get("tld"))).isAbsent();
}
@Test
public void testSave_simple() throws Exception {
PremiumList pl =
savePremiumListAndEntries(
new PremiumList.Builder().setName("tld2").build(),
ImmutableList.of("lol , USD 999 # yupper rooni "));
createTld("tld");
persistResource(Registry.get("tld").asBuilder().setPremiumList(pl).build());
assertThat(getPremiumPrice("lol", Registry.get("tld"))).hasValue(Money.parse("USD 999"));
assertThat(getPremiumPrice("lol ", Registry.get("tld"))).isAbsent();
Map<String, PremiumListEntry> entries = loadPremiumListEntries(PremiumList.get("tld2").get());
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");
}
@Test
public void test_saveAndUpdateEntriesTwice() throws Exception {
PremiumList pl =
savePremiumListAndEntries(
new PremiumList.Builder().setName("pl").build(), ImmutableList.of("test,USD 1"));
Map<String, PremiumListEntry> entries = loadPremiumListEntries(pl);
assertThat(entries.keySet()).containsExactly("test");
assertThat(loadPremiumListEntries(PremiumList.get("pl").get())).isEqualTo(entries);
// Save again with no changes, and clear the cache to force a re-load from Datastore.
PremiumList resaved = savePremiumListAndEntries(pl, ImmutableList.of("test,USD 1"));
ofy().clearSessionCache();
Map<String, PremiumListEntry> entriesReloaded =
loadPremiumListEntries(PremiumList.get("pl").get());
assertThat(entriesReloaded).hasSize(1);
assertThat(entriesReloaded).containsKey("test");
assertThat(entriesReloaded.get("test").parent).isEqualTo(resaved.getRevisionKey());
}
@Test
public void testDelete() throws Exception {
persistPremiumList("gtld1", "trombone,USD 10");
assertThat(PremiumList.get("gtld1")).isPresent();
Key<PremiumListRevision> parent = PremiumList.get("gtld1").get().getRevisionKey();
deletePremiumList(PremiumList.get("gtld1").get());
assertThat(PremiumList.get("gtld1")).isAbsent();
assertThat(ofy().load().type(PremiumListEntry.class).ancestor(parent).list()).isEmpty();
}
@Test
public void testDelete_largeNumberOfEntries_succeeds() {
persistHumongousPremiumList("ginormous", 2500);
deletePremiumList(PremiumList.get("ginormous").get());
assertThat(PremiumList.get("ginormous")).isAbsent();
}
@Test
public void testDelete_failsWhenListDoesntExist() throws Exception {
thrown.expect(IllegalStateException.class);
deletePremiumList(PremiumList.get("tld-premium-blah").get());
}
/** 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);
}
}

View file

@ -27,7 +27,7 @@ import static google.registry.model.EppResourceUtils.createDomainRepoId;
import static google.registry.model.EppResourceUtils.createRepoId;
import static google.registry.model.domain.launch.ApplicationStatus.VALIDATED;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.registry.label.PremiumList.parentEntriesOnRevision;
import static google.registry.model.registry.label.PremiumListUtils.parentPremiumListEntriesOnRevision;
import static google.registry.pricing.PricingEngineProxy.getDomainRenewCost;
import static google.registry.util.CollectionUtils.difference;
import static google.registry.util.CollectionUtils.union;
@ -365,7 +365,7 @@ public class DatastoreHelper {
.now();
ofy()
.saveWithoutBackup()
.entities(parentEntriesOnRevision(entries.values(), Key.create(revision)))
.entities(parentPremiumListEntriesOnRevision(entries.values(), Key.create(revision)))
.now();
return ofy().load().entity(premiumList).now();
}

View file

@ -17,6 +17,7 @@ package google.registry.tools;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.model.registry.label.PremiumListUtils.loadPremiumListEntries;
import static google.registry.testing.DatastoreHelper.createTld;
import static google.registry.testing.DatastoreHelper.persistPremiumList;
import static google.registry.testing.DatastoreHelper.persistResource;
@ -32,7 +33,7 @@ public class DeletePremiumListCommandTest extends CommandTestCase<DeletePremiumL
@Test
public void testSuccess() throws Exception {
PremiumList premiumList = persistPremiumList("xn--q9jyb4c", "blah,USD 100");
assertThat(premiumList.loadPremiumListEntries()).hasSize(1);
assertThat(loadPremiumListEntries(premiumList)).hasSize(1);
runCommand("--force", "--name=xn--q9jyb4c");
assertThat(PremiumList.get("xn--q9jyb4c")).isAbsent();
@ -62,7 +63,8 @@ public class DeletePremiumListCommandTest extends CommandTestCase<DeletePremiumL
} catch (IllegalArgumentException e) {
assertThat(PremiumList.get(premiumList.getName())).isPresent();
assertThat(e)
.hasMessage("Cannot delete premium list because it is used on these tld(s): xn--q9jyb4c");
.hasMessageThat()
.isEqualTo("Cannot delete premium list because it is used on these tld(s): xn--q9jyb4c");
}
}
}

View file

@ -15,7 +15,9 @@
package google.registry.tools.server;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.model.registry.label.PremiumList.getPremiumPrice;
import static google.registry.model.registry.label.PremiumListUtils.deletePremiumList;
import static google.registry.model.registry.label.PremiumListUtils.getPremiumPrice;
import static google.registry.model.registry.label.PremiumListUtils.loadPremiumListEntries;
import static google.registry.testing.DatastoreHelper.createTlds;
import static javax.servlet.http.HttpServletResponse.SC_OK;
@ -37,13 +39,8 @@ import org.junit.runners.JUnit4;
@RunWith(JUnit4.class)
public class CreatePremiumListActionTest {
@Rule
public final AppEngineRule appEngine = AppEngineRule.builder()
.withDatastore()
.build();
@Rule
public final ExceptionRule thrown = new ExceptionRule();
@Rule public final AppEngineRule appEngine = AppEngineRule.builder().withDatastore().build();
@Rule public final ExceptionRule thrown = new ExceptionRule();
CreatePremiumListAction action;
FakeJsonResponse response;
@ -51,7 +48,7 @@ public class CreatePremiumListActionTest {
@Before
public void init() throws Exception {
createTlds("foo", "xn--q9jyb4c", "how");
PremiumList.get("foo").get().delete();
deletePremiumList(PremiumList.get("foo").get());
action = new CreatePremiumListAction();
response = new FakeJsonResponse();
action.response = response;
@ -83,7 +80,7 @@ public class CreatePremiumListActionTest {
action.override = true;
action.run();
assertThat(response.getStatus()).isEqualTo(SC_OK);
assertThat(PremiumList.get("zanzibar").get().loadPremiumListEntries()).hasSize(1);
assertThat(loadPremiumListEntries(PremiumList.get("zanzibar").get())).hasSize(1);
}
@Test
@ -92,7 +89,7 @@ public class CreatePremiumListActionTest {
action.inputData = "rich,USD 25\nricher,USD 1000\n";
action.run();
assertThat(response.getStatus()).isEqualTo(SC_OK);
assertThat(PremiumList.get("foo").get().loadPremiumListEntries()).hasSize(2);
assertThat(loadPremiumListEntries(PremiumList.get("foo").get())).hasSize(2);
assertThat(getPremiumPrice("rich", Registry.get("foo"))).hasValue(Money.parse("USD 25"));
assertThat(getPremiumPrice("diamond", Registry.get("foo"))).isAbsent();
}

View file

@ -15,7 +15,8 @@
package google.registry.tools.server;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.model.registry.label.PremiumList.getPremiumPrice;
import static google.registry.model.registry.label.PremiumListUtils.getPremiumPrice;
import static google.registry.model.registry.label.PremiumListUtils.loadPremiumListEntries;
import static google.registry.testing.DatastoreHelper.createTlds;
import static javax.servlet.http.HttpServletResponse.SC_OK;
@ -82,7 +83,7 @@ public class UpdatePremiumListActionTest {
action.run();
assertThat(response.getStatus()).isEqualTo(SC_OK);
Registry registry = Registry.get("foo");
assertThat(PremiumList.get("foo").get().loadPremiumListEntries()).hasSize(3);
assertThat(loadPremiumListEntries(PremiumList.get("foo").get())).hasSize(3);
assertThat(getPremiumPrice("rich", registry)).hasValue(Money.parse("USD 75"));
assertThat(getPremiumPrice("richer", registry)).hasValue(Money.parse("USD 5000"));
assertThat(getPremiumPrice("poor", registry)).hasValue(Money.parse("USD 0.99"));