diff --git a/.gitignore b/.gitignore index e96f748ef..8df13bbd0 100644 --- a/.gitignore +++ b/.gitignore @@ -112,3 +112,7 @@ core/**/registrar_bin*.js core/**/registrar_dbg*.js core/**/registrar_bin*.css core/**/registrar_dbg*.css + +# Appengine generated files +core/WEB-INF/appengine-generated/*.bin +core/WEB-INF/appengine-generated/*.xml diff --git a/core/src/main/java/google/registry/export/ExportPremiumTermsAction.java b/core/src/main/java/google/registry/export/ExportPremiumTermsAction.java index 165f53178..2ad97c1b8 100644 --- a/core/src/main/java/google/registry/export/ExportPremiumTermsAction.java +++ b/core/src/main/java/google/registry/export/ExportPremiumTermsAction.java @@ -31,7 +31,7 @@ import com.google.common.flogger.FluentLogger; 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.PremiumList.PremiumEntry; import google.registry.request.Action; import google.registry.request.Parameter; import google.registry.request.RequestParameters; @@ -143,8 +143,8 @@ public class ExportPremiumTermsAction implements Runnable { PremiumListDao.getLatestRevision(premiumListName).isPresent(), "Could not load premium list for " + tld); SortedSet premiumTerms = - Streams.stream(PremiumListDao.loadAllPremiumListEntries(premiumListName)) - .map(PremiumListEntry::toString) + Streams.stream(PremiumListDao.loadAllPremiumEntries(premiumListName)) + .map(PremiumEntry::toString) .collect(ImmutableSortedSet.toImmutableSortedSet(String::compareTo)); return Joiner.on("\n") diff --git a/core/src/main/java/google/registry/export/ExportUtils.java b/core/src/main/java/google/registry/export/ExportUtils.java index 90b074acd..7173b34d6 100644 --- a/core/src/main/java/google/registry/export/ExportUtils.java +++ b/core/src/main/java/google/registry/export/ExportUtils.java @@ -48,7 +48,7 @@ public final class ExportUtils { String.format("Reserved list %s does not exist", reservedListName))); if (reservedList.getShouldPublish()) { for (ReservedListEntry entry : reservedList.getReservedListEntries().values()) { - reservedTerms.add(entry.getLabel()); + reservedTerms.add(entry.getDomainLabel()); } } } diff --git a/core/src/main/java/google/registry/model/EntityClasses.java b/core/src/main/java/google/registry/model/EntityClasses.java index 2ec069878..dfb373c7c 100644 --- a/core/src/main/java/google/registry/model/EntityClasses.java +++ b/core/src/main/java/google/registry/model/EntityClasses.java @@ -40,7 +40,6 @@ import google.registry.model.rde.RdeRevision; import google.registry.model.registrar.Registrar; import google.registry.model.registrar.RegistrarContact; import google.registry.model.registry.Registry; -import google.registry.model.registry.label.PremiumList; import google.registry.model.registry.label.ReservedList; import google.registry.model.reporting.HistoryEntry; import google.registry.model.server.Lock; @@ -91,9 +90,6 @@ public final class EntityClasses { PollMessage.class, PollMessage.Autorenew.class, PollMessage.OneTime.class, - PremiumList.class, - PremiumList.PremiumListEntry.class, - PremiumList.PremiumListRevision.class, RdeRevision.class, Registrar.class, RegistrarContact.class, diff --git a/core/src/main/java/google/registry/model/registry/label/BaseDomainLabelList.java b/core/src/main/java/google/registry/model/registry/label/BaseDomainLabelList.java index 9cbf743f5..e2f9b2d6c 100644 --- a/core/src/main/java/google/registry/model/registry/label/BaseDomainLabelList.java +++ b/core/src/main/java/google/registry/model/registry/label/BaseDomainLabelList.java @@ -74,14 +74,12 @@ public abstract class BaseDomainLabelList, R extends Dom @Parent @Transient Key parent = getCrossTldKey(); - @Transient DateTime creationTime; - // The list in Cloud SQL is immutable, we only have a creation_timestamp field and it should be // set to the timestamp when the list is created. In Datastore, we have two fields and the // lastUpdateTime is set to the current timestamp when creating and updating a list. So, we use // lastUpdateTime as the creation_timestamp column during the dual-write phase for compatibility. @Column(name = "creation_timestamp") - DateTime lastUpdateTime; + DateTime creationTimestamp; /** Returns the ID of this revision, or throws if null. */ public long getRevisionId() { @@ -97,12 +95,8 @@ public abstract class BaseDomainLabelList, R extends Dom } /** Returns the creation time of this revision of the reserved list. */ - public DateTime getCreationTime() { - return creationTime; - } - - public DateTime getLastUpdateTime() { - return lastUpdateTime; + public DateTime getCreationTimestamp() { + return creationTimestamp; } /** @@ -118,7 +112,7 @@ public abstract class BaseDomainLabelList, R extends Dom if (entry == null) { continue; } - String label = entry.getLabel(); + String label = entry.getDomainLabel(); // Check if the label was already processed for this list (which is an error), and if so, // accumulate it so that a list of all duplicates can be thrown. if (labelsToEntries.containsKey(label)) { @@ -196,13 +190,8 @@ public abstract class BaseDomainLabelList, R extends Dom return thisCastToDerived(); } - public B setCreationTime(DateTime creationTime) { - getInstance().creationTime = creationTime; - return thisCastToDerived(); - } - - public B setLastUpdateTime(DateTime lastUpdateTime) { - getInstance().lastUpdateTime = lastUpdateTime; + public B setCreationTimestamp(DateTime creationTime) { + getInstance().creationTimestamp = creationTime; return thisCastToDerived(); } diff --git a/core/src/main/java/google/registry/model/registry/label/DomainLabelEntry.java b/core/src/main/java/google/registry/model/registry/label/DomainLabelEntry.java index 3c857b8a3..b8c7902cc 100644 --- a/core/src/main/java/google/registry/model/registry/label/DomainLabelEntry.java +++ b/core/src/main/java/google/registry/model/registry/label/DomainLabelEntry.java @@ -37,17 +37,15 @@ public abstract class DomainLabelEntry, D extends Domain @Id @javax.persistence.Id - @Column(name = "domain_label", nullable = false) - String label; - - String comment; + @Column(name = "domainLabel", nullable = false) + String domainLabel; /** * Returns the label of the field, which also happens to be used as the key for the Map object * that is serialized from Datastore. */ - public String getLabel() { - return label; + public String getDomainLabel() { + return domainLabel; } /** @@ -72,30 +70,25 @@ public abstract class DomainLabelEntry, D extends Domain } public B setLabel(String label) { - getInstance().label = label; - return thisCastToDerived(); - } - - public B setComment(String comment) { - getInstance().comment = comment; + getInstance().domainLabel = label; return thisCastToDerived(); } @Override public T build() { - checkArgumentNotNull(emptyToNull(getInstance().label), "Label must be specified"); + checkArgumentNotNull(emptyToNull(getInstance().domainLabel), "Label must be specified"); checkArgument( - getInstance().label.equals(canonicalizeDomainName(getInstance().label)), + getInstance().domainLabel.equals(canonicalizeDomainName(getInstance().domainLabel)), "Label '%s' must be in puny-coded, lower-case form", - getInstance().label); + getInstance().domainLabel); checkArgumentNotNull(getInstance().getValue(), "Value must be specified"); // Verify that the label creates a valid SLD if we add a TLD to the end of it. // We require that the label is not already a full domain name including a dot. // Domain name validation is tricky, so let InternetDomainName handle it for us. checkArgument( - InternetDomainName.from(getInstance().label + ".tld").parts().size() == 2, + InternetDomainName.from(getInstance().domainLabel + ".tld").parts().size() == 2, "Label %s must not be a multi-level domain name", - getInstance().label); + getInstance().domainLabel); return super.build(); } } 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 e42583702..6d48aad4c 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 @@ -18,45 +18,27 @@ import static com.google.common.base.Charsets.US_ASCII; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.collect.ImmutableMap.toImmutableMap; import static com.google.common.hash.Funnels.stringFunnel; -import static com.google.common.hash.Funnels.unencodedCharsFunnel; -import static google.registry.model.IdService.allocateId; -import static google.registry.persistence.transaction.QueryComposer.Comparator.EQ; -import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm; -import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Splitter; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Streams; import com.google.common.hash.BloomFilter; -import com.googlecode.objectify.Key; -import com.googlecode.objectify.annotation.Entity; -import com.googlecode.objectify.annotation.Id; -import com.googlecode.objectify.annotation.Ignore; -import com.googlecode.objectify.annotation.Parent; import google.registry.model.Buildable; import google.registry.model.ImmutableObject; -import google.registry.model.annotations.InCrossTld; 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.PremiumEntry; +import google.registry.model.registry.label.PremiumList.PremiumEntry; +import google.registry.schema.replay.SqlOnlyEntity; import google.registry.schema.tld.PremiumListDao; -import java.io.ByteArrayOutputStream; -import java.io.IOException; +import java.io.Serializable; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Set; import javax.annotation.Nullable; import javax.persistence.Column; import javax.persistence.Index; -import javax.persistence.PostLoad; -import javax.persistence.PostPersist; -import javax.persistence.PostUpdate; -import javax.persistence.PrePersist; -import javax.persistence.PreRemove; import javax.persistence.Table; import javax.persistence.Transient; import org.joda.money.CurrencyUnit; @@ -71,16 +53,11 @@ import org.joda.money.Money; * This is fine though, because we only use the list with the highest revisionId. */ @ReportedOn -@Entity @javax.persistence.Entity @Table(indexes = {@Index(columnList = "name", name = "premiumlist_name_idx")}) -public final class PremiumList extends BaseDomainLabelList - implements NonReplicatedEntity { +public final class PremiumList extends BaseDomainLabelList + implements SqlOnlyEntity { - /** Stores the revision key for the set of currently used premium list entry entities. */ - @Transient Key revisionKey; - - @Ignore @Column(nullable = false) CurrencyUnit currency; @@ -91,80 +68,11 @@ public final class PremiumList extends BaseDomainLabelList labelsToPrices; + @ImmutableObject.Insignificant @Transient ImmutableMap labelsToPrices; - @Ignore @Column(nullable = false) BloomFilter bloomFilter; - /** Virtual parent entity for premium list entry entities associated with a single revision. */ - @ReportedOn - @Entity - @InCrossTld - public static class PremiumListRevision extends ImmutableObject implements DatastoreOnlyEntity { - - @Parent Key parent; - - @Id long revisionId; - - /** - * A Bloom filter that is used to determine efficiently and quickly whether a label might be - * premium. - * - *

If the label might be premium, then the premium list entry must be loaded by key and - * checked for existence. Otherwise, we know it's not premium, and no Datastore load is - * required. - */ - private BloomFilter probablePremiumLabels; - - /** - * Get the Bloom filter. - * - *

Note that this is not a copy, but the mutable object itself, because copying would be - * expensive. You probably should not modify the filter unless you know what you're doing. - */ - public BloomFilter getProbablePremiumLabels() { - return probablePremiumLabels; - } - - /** - * The maximum size of the Bloom filter. - * - *

Trying to set it any larger will throw an error, as we know it won't fit into a Datastore - * entity. We use 90% of the 1 MB Datastore limit to leave some wriggle room for the other - * fields and miscellaneous entity serialization overhead. - */ - private static final int MAX_BLOOM_FILTER_BYTES = 900000; - - /** Returns a new PremiumListRevision for the given key and premium list map. */ - @VisibleForTesting - public static PremiumListRevision create(PremiumList parent, Set premiumLabels) { - PremiumListRevision revision = new PremiumListRevision(); - revision.parent = Key.create(parent); - revision.revisionId = allocateId(); - // All premium list labels are already punycoded, so don't perform any further character - // encoding on them. - revision.probablePremiumLabels = - BloomFilter.create(unencodedCharsFunnel(), premiumLabels.size()); - premiumLabels.forEach(revision.probablePremiumLabels::put); - try { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - revision.probablePremiumLabels.writeTo(bos); - checkArgument( - bos.size() <= MAX_BLOOM_FILTER_BYTES, - "Too many premium labels were specified; Bloom filter exceeds max entity size"); - } catch (IOException e) { - throw new IllegalStateException("Could not serialize premium labels Bloom filter", e); - } - return revision; - } - } - - @VisibleForTesting - public Key getRevisionKey() { - return revisionKey; - } - /** Returns the {@link CurrencyUnit} used for this list. */ public CurrencyUnit getCurrency() { return currency; @@ -179,16 +87,14 @@ public final class PremiumList extends BaseDomainLabelList getLabelsToPrices() { if (labelsToPrices == null) { + Iterable entries = PremiumListDao.loadAllPremiumEntries(name); labelsToPrices = - jpaTm() - .createQueryComposer(PremiumEntry.class) - .where("revisionId", EQ, revisionId) - .stream() + Streams.stream(entries) .collect( toImmutableMap( PremiumEntry::getDomainLabel, // Set the correct amount of precision for the premium list's currency. - entry -> convertAmountToMoney(entry.getPrice()).getAmount())); + premiumEntry -> convertAmountToMoney(premiumEntry.getValue()).getAmount())); } return labelsToPrices; } @@ -212,29 +118,38 @@ public final class PremiumList extends BaseDomainLabelList - implements Buildable, DatastoreOnlyEntity { + @javax.persistence.Entity(name = "PremiumEntry") + public static class PremiumEntry extends DomainLabelEntry + implements Buildable, SqlOnlyEntity, Serializable { - @Parent - Key parent; + @ImmutableObject.Insignificant @javax.persistence.Id Long revisionId; - Money price; + @Column(nullable = false) + BigDecimal price; @Override - public Money getValue() { + public BigDecimal getValue() { return price; } + public static PremiumEntry create(Long revisionId, BigDecimal price, String label) { + return new PremiumEntry.Builder() + .setRevisionId(revisionId) + .setPrice(price) + .setLabel(label) + .build(); + } + @Override public String toString() { - // Don't include the comment so that we can use this when exporting the premium list - return String.format("%s,%s", label, price); + return String.format("%s, %s", domainLabel, price); + } + + public String toString(CurrencyUnit currencyUnit) { + return String.format("%s,%s %s", domainLabel, currencyUnit, price); } @Override @@ -242,22 +157,22 @@ public final class PremiumList extends BaseDomainLabelList { + /** A builder for constructing {@link PremiumEntry} objects, since they are immutable. */ + public static class Builder extends DomainLabelEntry.Builder { public Builder() {} - private Builder(PremiumListEntry instance) { + private Builder(PremiumEntry instance) { super(instance); } - public Builder setParent(Key parentKey) { - getInstance().parent = parentKey; + public Builder setPrice(BigDecimal price) { + getInstance().price = price; return this; } - public Builder setPrice(Money price) { - getInstance().price = price; + public Builder setRevisionId(Long revisionId) { + getInstance().revisionId = revisionId; return this; } } @@ -265,19 +180,29 @@ public final class PremiumList extends BaseDomainLabelList lineAndComment = splitOnComment(originalLine); if (lineAndComment.isEmpty()) { return null; } String line = lineAndComment.get(0); - String comment = lineAndComment.get(1); List parts = Splitter.on(',').trimResults().splitToList(line); checkArgument(parts.size() == 2, "Could not parse line in premium list: %s", originalLine); - return new PremiumListEntry.Builder() + List moneyParts = Splitter.on(' ').trimResults().splitToList(parts.get(1)); + if (moneyParts.size() == 2 && this.currency != null) { + if (!Money.parse(parts.get(1)).getCurrencyUnit().equals(this.currency)) { + throw new IllegalArgumentException( + String.format("The currency unit must be %s", this.currency.getCode())); + } + } + BigDecimal price = + moneyParts.size() == 2 + ? Money.parse(parts.get(1)).getAmount() + : new BigDecimal(parts.get(1)); + return new PremiumEntry.Builder() .setLabel(parts.get(0)) - .setPrice(Money.parse(parts.get(1))) - .setComment(comment) + .setPrice(price) + .setRevisionId(revisionId) .build(); } @@ -300,11 +225,6 @@ public final class PremiumList extends BaseDomainLabelList revision) { - getInstance().revisionKey = revision; - return this; - } - public Builder setCurrency(CurrencyUnit currency) { getInstance().currency = currency; return this; @@ -330,42 +250,4 @@ public final class PremiumList extends BaseDomainLabelListWe need to persist the list entries, but only on the initial insert (not on update) since - * the entries themselves never get changed, so we only annotate it with {@link PostPersist}, not - * {@link PostUpdate}. - */ - @PostPersist - void postPersist() { - // If the price map is loaded, persist it too. - if (labelsToPrices != null) { - labelsToPrices.entrySet().stream() - .forEach( - entry -> - jpaTm() - .insert(PremiumEntry.create(revisionId, entry.getValue(), entry.getKey()))); - } - } } diff --git a/core/src/main/java/google/registry/model/registry/label/ReservedList.java b/core/src/main/java/google/registry/model/registry/label/ReservedList.java index b930fb7df..9a2313484 100644 --- a/core/src/main/java/google/registry/model/registry/label/ReservedList.java +++ b/core/src/main/java/google/registry/model/registry/label/ReservedList.java @@ -131,15 +131,21 @@ public final class ReservedList @Column(nullable = false) ReservationType reservationType; + String comment; + /** Mapper for use with @Mapify */ static class LabelMapper implements Mapper { @Override public String getKey(ReservedListEntry entry) { - return entry.getLabel(); + return entry.getDomainLabel(); } } + public String getComment(String comment) { + return comment; + } + /** Creates a {@link ReservedListEntry} from a label, reservation type, and optional comment. */ public static ReservedListEntry create( String label, ReservationType reservationType, @Nullable String comment) { @@ -163,7 +169,7 @@ public final class ReservedList @Override public String toString() { return String.format( - "%s,%s%s", label, reservationType, isNullOrEmpty(comment) ? "" : " # " + comment); + "%s,%s%s", domainLabel, reservationType, isNullOrEmpty(comment) ? "" : " # " + comment); } /** A builder for constructing {@link ReservedListEntry} objects, since they are immutable. */ @@ -180,6 +186,11 @@ public final class ReservedList getInstance().reservationType = reservationType; return this; } + + ReservedListEntry.Builder setComment(String comment) { + getInstance().comment = comment; + return this; + } } } @@ -217,7 +228,7 @@ public final class ReservedList .createQueryComposer(ReservedListEntry.class) .where("revisionId", EQ, revisionId) .stream() - .collect(toImmutableMap(ReservedListEntry::getLabel, e -> e))); + .collect(toImmutableMap(ReservedListEntry::getDomainLabel, e -> e))); } return ImmutableMap.copyOf(nullToEmpty(reservedListMap)); } diff --git a/core/src/main/java/google/registry/persistence/converter/PremiumListKeyConverter.java b/core/src/main/java/google/registry/persistence/converter/PremiumListKeyConverter.java deleted file mode 100644 index 580694816..000000000 --- a/core/src/main/java/google/registry/persistence/converter/PremiumListKeyConverter.java +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright 2020 The Nomulus Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package google.registry.persistence.converter; - -import static google.registry.model.common.EntityGroupRoot.getCrossTldKey; - -import com.googlecode.objectify.Key; -import google.registry.model.registry.label.PremiumList; -import javax.persistence.AttributeConverter; -import javax.persistence.Converter; - -/** JPA converter for a {@link Key} containing a {@link PremiumList} */ -@Converter(autoApply = true) -public class PremiumListKeyConverter implements AttributeConverter, String> { - - @Override - public String convertToDatabaseColumn(Key attribute) { - return (attribute == null) ? null : attribute.getName(); - } - - @Override - public Key convertToEntityAttribute(String dbData) { - return (dbData == null) ? null : Key.create(getCrossTldKey(), PremiumList.class, dbData); - } -} diff --git a/core/src/main/java/google/registry/schema/tld/PremiumEntry.java b/core/src/main/java/google/registry/schema/tld/PremiumEntry.java deleted file mode 100644 index 41a307c5e..000000000 --- a/core/src/main/java/google/registry/schema/tld/PremiumEntry.java +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright 2019 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.schema.tld; - -import google.registry.model.ImmutableObject; -import google.registry.model.registry.label.PremiumList; -import google.registry.schema.replay.SqlOnlyEntity; -import java.io.Serializable; -import java.math.BigDecimal; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Id; - -/** - * Entity class for the premium price of an individual domain label. - * - *

These are not persisted directly, but rather, using {@link PremiumList#getLabelsToPrices()}. - */ -@Entity -public class PremiumEntry extends ImmutableObject implements Serializable, SqlOnlyEntity { - - @Id - @Column(nullable = false) - Long revisionId; - - @Column(nullable = false) - BigDecimal price; - - @Id - @Column(nullable = false) - String domainLabel; - - private PremiumEntry() {} - - public BigDecimal getPrice() { - return price; - } - - public String getDomainLabel() { - return domainLabel; - } - - public static PremiumEntry create(long revisionId, BigDecimal price, String domainLabel) { - PremiumEntry result = new PremiumEntry(); - result.revisionId = revisionId; - result.price = price; - result.domainLabel = domainLabel; - return result; - } -} diff --git a/core/src/main/java/google/registry/schema/tld/PremiumListDao.java b/core/src/main/java/google/registry/schema/tld/PremiumListDao.java index c98e0e990..052c4a251 100644 --- a/core/src/main/java/google/registry/schema/tld/PremiumListDao.java +++ b/core/src/main/java/google/registry/schema/tld/PremiumListDao.java @@ -26,15 +26,15 @@ 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.ImmutableSet; 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.PremiumList.PremiumEntry; import google.registry.util.NonFinalForTesting; 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; @@ -153,18 +153,48 @@ public class PremiumListDao { } } - public static PremiumList save(String name, List inputData) { - return save(PremiumListUtils.parseToPremiumList(name, inputData)); + public static PremiumList save(String name, CurrencyUnit currencyUnit, List inputData) { + return save(PremiumListUtils.parseToPremiumList(name, currencyUnit, inputData)); } public static PremiumList save(PremiumList premiumList) { jpaTm().transact(() -> jpaTm().insert(premiumList)); premiumListCache.invalidate(premiumList.getName()); + jpaTm() + .transact( + () -> { + if (premiumList.getLabelsToPrices() != null) { + Optional savedPremiumList = + PremiumListDao.getLatestRevision(premiumList.getName()); + ImmutableSet.Builder entries = new ImmutableSet.Builder<>(); + premiumList.getLabelsToPrices().entrySet().stream() + .forEach( + entry -> + entries.add( + PremiumEntry.create( + savedPremiumList.get().getRevisionId(), + entry.getValue(), + entry.getKey()))); + jpaTm().insertAll(entries.build()); + } + }); + premiumListCache.invalidate(premiumList.getName()); return premiumList; } public static void delete(PremiumList premiumList) { - jpaTm().transact(() -> getLatestRevision(premiumList.getName()).ifPresent(jpaTm()::delete)); + jpaTm() + .transact( + () -> { + Optional persistedList = getLatestRevision(premiumList.getName()); + if (persistedList.isPresent()) { + jpaTm() + .query("DELETE FROM PremiumEntry WHERE revisionId = :revisionId") + .setParameter("revisionId", persistedList.get().getRevisionId()) + .executeUpdate(); + jpaTm().delete(persistedList.get()); + } + }); premiumListCache.invalidate(premiumList.getName()); } @@ -183,11 +213,11 @@ public class PremiumListDao { } /** - * Returns all {@link PremiumListEntry PremiumListEntries} in the given {@code premiumList}. + * Returns all {@link PremiumEntry PremiumEntries} in the given {@code premiumList}. * *

This is an expensive operation and should only be used when the entire list is required. */ - public static Iterable loadPremiumListEntries(PremiumList premiumList) { + public static Iterable loadPremiumEntries(PremiumList premiumList) { return jpaTm() .transact( () -> @@ -220,24 +250,25 @@ public class PremiumListDao { } /** - * Returns all {@link PremiumListEntry PremiumListEntries} in the list with the given name. + * Returns all {@link PremiumEntry PremiumEntries} 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) { + public static Iterable loadAllPremiumEntries(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)) + Iterable entries = loadPremiumEntries(premiumList); + return Streams.stream(entries) .map( premiumEntry -> - new PremiumListEntry.Builder() - .setPrice(BigMoney.of(currencyUnit, premiumEntry.getPrice()).toMoney()) + new PremiumEntry.Builder() + .setPrice(premiumEntry.getValue()) .setLabel(premiumEntry.getDomainLabel()) + .setRevisionId(premiumList.getRevisionId()) .build()) .collect(toImmutableList()); } diff --git a/core/src/main/java/google/registry/schema/tld/PremiumListUtils.java b/core/src/main/java/google/registry/schema/tld/PremiumListUtils.java index c9b5275c6..41c22b01e 100644 --- a/core/src/main/java/google/registry/schema/tld/PremiumListUtils.java +++ b/core/src/main/java/google/registry/schema/tld/PremiumListUtils.java @@ -15,16 +15,12 @@ package google.registry.schema.tld; import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.collect.ImmutableSet.toImmutableSet; import static org.joda.time.DateTimeZone.UTC; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableSet; -import com.google.common.collect.ImmutableSortedSet; -import com.google.common.collect.Iterables; import com.google.common.collect.Maps; import google.registry.model.registry.label.PremiumList; -import google.registry.model.registry.label.PremiumList.PremiumListEntry; +import google.registry.model.registry.label.PremiumList.PremiumEntry; import java.math.BigDecimal; import java.util.List; import java.util.Map; @@ -34,28 +30,18 @@ import org.joda.time.DateTime; /** Static utility methods for {@link PremiumList}. */ public class PremiumListUtils { - public static PremiumList parseToPremiumList(String name, List inputData) { - ImmutableMap prices = - new PremiumList.Builder().setName(name).build().parse(inputData); - ImmutableSet currencies = - prices.values().stream() - .map(e -> e.getValue().getCurrencyUnit()) - .distinct() - .collect(toImmutableSet()); - checkArgument( - currencies.size() == 1, - "The Cloud SQL schema requires exactly one currency, but got: %s", - ImmutableSortedSet.copyOf(currencies)); - CurrencyUnit currency = Iterables.getOnlyElement(currencies); - - Map priceAmounts = - Maps.transformValues(prices, ple -> ple.getValue().getAmount()); - return new PremiumList.Builder() - .setName(name) - .setCurrency(currency) - .setLabelsToPrices(priceAmounts) - .setCreationTime(DateTime.now(UTC)) - .build(); + public static PremiumList parseToPremiumList( + String name, CurrencyUnit currencyUnit, List inputData) { + PremiumList partialPremiumList = + new PremiumList.Builder() + .setName(name) + .setCurrency(currencyUnit) + .setCreationTimestamp(DateTime.now(UTC)) + .build(); + ImmutableMap prices = partialPremiumList.parse(inputData); + checkArgument(inputData.size() > 0, "Input cannot be empty"); + Map priceAmounts = Maps.transformValues(prices, PremiumEntry::getValue); + return partialPremiumList.asBuilder().setLabelsToPrices(priceAmounts).build(); } private PremiumListUtils() {} diff --git a/core/src/main/java/google/registry/tools/CreateOrUpdatePremiumListCommand.java b/core/src/main/java/google/registry/tools/CreateOrUpdatePremiumListCommand.java index 8e827e99f..fd9ac3f48 100644 --- a/core/src/main/java/google/registry/tools/CreateOrUpdatePremiumListCommand.java +++ b/core/src/main/java/google/registry/tools/CreateOrUpdatePremiumListCommand.java @@ -21,15 +21,18 @@ import google.registry.tools.params.PathParameter; import java.nio.file.Path; import java.util.List; import javax.annotation.Nullable; +import org.joda.money.CurrencyUnit; /** * Base class for specification of command line parameters common to creating and updating premium * lists. */ -abstract class CreateOrUpdatePremiumListCommand extends MutatingCommand { +abstract class CreateOrUpdatePremiumListCommand extends ConfirmingCommand + implements CommandWithRemoteApi { private static final FluentLogger logger = FluentLogger.forEnclosingClass(); protected List inputData; + protected CurrencyUnit currency; @Nullable @Parameter( @@ -51,7 +54,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); - PremiumListDao.save(name, inputData); + PremiumListDao.save(name, currency, 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/CreatePremiumListCommand.java b/core/src/main/java/google/registry/tools/CreatePremiumListCommand.java index 693e709d8..e72cda163 100644 --- a/core/src/main/java/google/registry/tools/CreatePremiumListCommand.java +++ b/core/src/main/java/google/registry/tools/CreatePremiumListCommand.java @@ -22,12 +22,10 @@ import static java.nio.charset.StandardCharsets.UTF_8; import com.beust.jcommander.Parameter; import com.beust.jcommander.Parameters; 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.PremiumListDao; -import google.registry.schema.tld.PremiumListUtils; import java.nio.file.Files; +import org.joda.money.CurrencyUnit; /** Command to create a {@link PremiumList} on Database. */ @Parameters(separators = " =", commandDescription = "Create a PremiumList in Database.") @@ -38,9 +36,16 @@ public class CreatePremiumListCommand extends CreateOrUpdatePremiumListCommand { description = "Override restrictions on premium list naming") boolean override; + @Parameter( + names = {"-c", "--currency"}, + description = "CurrencyUnit for the list", + required = true) + String currencyUnit; + @Override // Using CreatePremiumListAction.java as reference; - protected void init() throws Exception { + protected String prompt() throws Exception { + currency = CurrencyUnit.of(currencyUnit); name = Strings.isNullOrEmpty(name) ? convertFilePathToName(inputFile) : name; checkArgument( !PremiumListDao.getLatestRevision(name).isPresent(), @@ -53,9 +58,6 @@ public class CreatePremiumListCommand extends CreateOrUpdatePremiumListCommand { + " (unless --override is specified), yet TLD %s does not exist"); } inputData = Files.readAllLines(inputFile, UTF_8); - // create a premium list with only input data and store as the first version of the entity - PremiumList newPremiumList = PremiumListUtils.parseToPremiumList(name, inputData); - stageEntityChange( - null, newPremiumList, VKey.createOfy(PremiumList.class, Key.create(newPremiumList))); + return String.format("Create new premium list for %s?", name); } } diff --git a/core/src/main/java/google/registry/tools/CreateReservedListCommand.java b/core/src/main/java/google/registry/tools/CreateReservedListCommand.java index b8c554130..33c4550b2 100644 --- a/core/src/main/java/google/registry/tools/CreateReservedListCommand.java +++ b/core/src/main/java/google/registry/tools/CreateReservedListCommand.java @@ -63,8 +63,7 @@ final class CreateReservedListCommand extends CreateOrUpdateReservedListCommand .setName(name) .setReservedListMapFromLines(allLines) .setShouldPublish(shouldPublish) - .setCreationTime(now) - .setLastUpdateTime(now) + .setCreationTimestamp(now) .build(); // calls the stageEntityChange method that takes old entity, new entity and a new vkey; diff --git a/core/src/main/java/google/registry/tools/GetPremiumListCommand.java b/core/src/main/java/google/registry/tools/GetPremiumListCommand.java index 3d1a5a87c..da5aae594 100644 --- a/core/src/main/java/google/registry/tools/GetPremiumListCommand.java +++ b/core/src/main/java/google/registry/tools/GetPremiumListCommand.java @@ -17,10 +17,12 @@ package google.registry.tools; 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.PremiumList; +import google.registry.model.registry.label.PremiumList.PremiumEntry; import google.registry.schema.tld.PremiumListDao; import java.util.Comparator; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; /** Retrieves and prints one or more premium lists. */ @@ -33,13 +35,14 @@ public class GetPremiumListCommand implements CommandWithRemoteApi { @Override public void run() { for (String premiumListName : mainParameters) { - if (PremiumListDao.getLatestRevision(premiumListName).isPresent()) { + Optional premiumList = PremiumListDao.getLatestRevision(premiumListName); + if (premiumList.isPresent()) { System.out.printf( "%s:\n%s\n", premiumListName, - Streams.stream(PremiumListDao.loadAllPremiumListEntries(premiumListName)) - .sorted(Comparator.comparing(PremiumListEntry::getLabel)) - .map(PremiumListEntry::toString) + Streams.stream(PremiumListDao.loadAllPremiumEntries(premiumListName)) + .sorted(Comparator.comparing(PremiumEntry::getDomainLabel)) + .map(premiumEntry -> premiumEntry.toString(premiumList.get().getCurrency())) .collect(Collectors.joining("\n"))); } else { System.out.printf("No list found with name %s.%n", premiumListName); diff --git a/core/src/main/java/google/registry/tools/GetReservedListCommand.java b/core/src/main/java/google/registry/tools/GetReservedListCommand.java index 3ac6f8aa7..3e94b3554 100644 --- a/core/src/main/java/google/registry/tools/GetReservedListCommand.java +++ b/core/src/main/java/google/registry/tools/GetReservedListCommand.java @@ -42,7 +42,7 @@ public class GetReservedListCommand implements CommandWithRemoteApi { .get() .getReservedListEntries() .values()) - .sorted(Comparator.comparing(ReservedListEntry::getLabel)) + .sorted(Comparator.comparing(ReservedListEntry::getDomainLabel)) .map(ReservedListEntry::toString) .collect(Collectors.joining("\n"))); } else { diff --git a/core/src/main/java/google/registry/tools/UpdatePremiumListCommand.java b/core/src/main/java/google/registry/tools/UpdatePremiumListCommand.java index 96cb83c2e..77372ca51 100644 --- a/core/src/main/java/google/registry/tools/UpdatePremiumListCommand.java +++ b/core/src/main/java/google/registry/tools/UpdatePremiumListCommand.java @@ -24,17 +24,13 @@ import com.beust.jcommander.Parameters; import com.google.common.base.Strings; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Streams; -import com.googlecode.objectify.Key; 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.model.registry.label.PremiumList.PremiumEntry; import google.registry.schema.tld.PremiumListDao; import google.registry.schema.tld.PremiumListUtils; import java.nio.file.Files; import java.util.List; import java.util.Optional; -import org.joda.money.BigMoney; /** Command to safely update {@link PremiumList} in Database for a given TLD. */ @Parameters(separators = " =", commandDescription = "Update a PremiumList in Database.") @@ -42,23 +38,23 @@ class UpdatePremiumListCommand extends CreateOrUpdatePremiumListCommand { @Override // Using UpdatePremiumListAction.java as reference; - protected void init() throws Exception { + protected String prompt() throws Exception { name = Strings.isNullOrEmpty(name) ? convertFilePathToName(inputFile) : name; - List existingEntry = getExistingPremiumListEntry(name).asList(); + Optional list = PremiumListDao.getLatestRevision(name); + checkArgument( + list.isPresent(), + String.format("Could not update premium list %s because it doesn't exist.", name)); + List existingEntry = getExistingPremiumEntry(list.get()).asList(); inputData = Files.readAllLines(inputFile, UTF_8); - + currency = list.get().getCurrency(); // reconstructing existing premium list to bypass Hibernate lazy initialization exception - PremiumList existingPremiumList = PremiumListUtils.parseToPremiumList(name, existingEntry); - PremiumList updatedPremiumList = PremiumListUtils.parseToPremiumList(name, inputData); + PremiumList existingPremiumList = + PremiumListUtils.parseToPremiumList(name, currency, existingEntry); + PremiumList updatedPremiumList = PremiumListUtils.parseToPremiumList(name, currency, inputData); - // use LabelsToPrices() for comparison between old and new premium lists since they have - // different creation date, updated date even if they have same content; - if (!existingPremiumList.getLabelsToPrices().equals(updatedPremiumList.getLabelsToPrices())) { - stageEntityChange( - existingPremiumList, - updatedPremiumList, - VKey.createOfy(PremiumList.class, Key.create(existingPremiumList))); - } + return String.format( + "Update premium list for %s?\n Old List: %s\n New List: %s", + name, existingPremiumList, updatedPremiumList); } /* @@ -78,22 +74,16 @@ class UpdatePremiumListCommand extends CreateOrUpdatePremiumListCommand { assertThat(persistedList.getLabelsToPrices()).containsEntry("foo", new BigDecimal("9000.00")); assertThat(persistedList.size()).isEqualTo(1); */ - protected ImmutableSet getExistingPremiumListEntry(String name) { - Optional list = PremiumListDao.getLatestRevision(name); - checkArgument( - list.isPresent(), - String.format("Could not update premium list %s because it doesn't exist.", name)); + protected ImmutableSet getExistingPremiumEntry(PremiumList list) { + Iterable sqlListEntries = - jpaTm().transact(() -> PremiumListDao.loadPremiumListEntries(list.get())); + jpaTm().transact(() -> PremiumListDao.loadPremiumEntries(list)); return Streams.stream(sqlListEntries) .map( premiumEntry -> - new PremiumListEntry.Builder() - .setPrice( - BigMoney.of(list.get().getCurrency(), premiumEntry.getPrice()).toMoney()) - .setLabel(premiumEntry.getDomainLabel()) - .build() - .toString()) + String.format( + "%s,%s %s", + premiumEntry.getDomainLabel(), list.getCurrency(), premiumEntry.getValue())) .collect(toImmutableSet()); } } 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 894156eb1..e334d331e 100644 --- a/core/src/main/java/google/registry/tools/server/CreatePremiumListAction.java +++ b/core/src/main/java/google/registry/tools/server/CreatePremiumListAction.java @@ -27,6 +27,7 @@ import google.registry.request.auth.Auth; import google.registry.schema.tld.PremiumListDao; import java.util.List; import javax.inject.Inject; +import org.joda.money.CurrencyUnit; /** * An action that creates a premium list, for use by the {@code nomulus create_premium_list} @@ -43,9 +44,14 @@ public class CreatePremiumListAction extends CreateOrUpdatePremiumListAction { public static final String OVERRIDE_PARAM = "override"; public static final String PATH = "/_dr/admin/createPremiumList"; + public static final String CURRENCY = "currency"; @Inject @Parameter(OVERRIDE_PARAM) boolean override; + @Inject + @Parameter("currency") + CurrencyUnit currency; + @Inject CreatePremiumListAction() {} @Override @@ -64,7 +70,7 @@ public class CreatePremiumListAction extends CreateOrUpdatePremiumListAction { logInputData(); List inputDataPreProcessed = Splitter.on('\n').omitEmptyStrings().splitToList(inputData); - PremiumListDao.save(name, inputDataPreProcessed); + PremiumListDao.save(name, currency, 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/ToolsServerModule.java b/core/src/main/java/google/registry/tools/server/ToolsServerModule.java index 778bea0fa..21985de54 100644 --- a/core/src/main/java/google/registry/tools/server/ToolsServerModule.java +++ b/core/src/main/java/google/registry/tools/server/ToolsServerModule.java @@ -28,6 +28,7 @@ import google.registry.request.Parameter; import google.registry.request.RequestParameters; import java.util.Optional; import javax.servlet.http.HttpServletRequest; +import org.joda.money.CurrencyUnit; /** * Dagger module for the tools package. @@ -66,6 +67,12 @@ public class ToolsServerModule { return extractRequiredParameter(req, CreatePremiumListAction.NAME_PARAM); } + @Provides + @Parameter("currency") + static CurrencyUnit provideCurrency(HttpServletRequest req) { + return CurrencyUnit.of(extractRequiredParameter(req, CreatePremiumListAction.CURRENCY)); + } + @Provides @Parameter("override") static boolean provideOverride(HttpServletRequest req) { 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 8c3a0e158..93ac07608 100644 --- a/core/src/main/java/google/registry/tools/server/UpdatePremiumListAction.java +++ b/core/src/main/java/google/registry/tools/server/UpdatePremiumListAction.java @@ -25,6 +25,7 @@ import google.registry.request.Action; import google.registry.request.auth.Auth; import google.registry.schema.tld.PremiumListDao; import java.util.List; +import java.util.Optional; import javax.inject.Inject; /** @@ -46,8 +47,9 @@ public class UpdatePremiumListAction extends CreateOrUpdatePremiumListAction { @Override protected void save() { + Optional existingList = PremiumListDao.getLatestRevision(name); checkArgument( - PremiumListDao.getLatestRevision(name).isPresent(), + existingList.isPresent(), "Could not update premium list %s because it doesn't exist.", name); @@ -55,7 +57,8 @@ public class UpdatePremiumListAction extends CreateOrUpdatePremiumListAction { logInputData(); List inputDataPreProcessed = Splitter.on('\n').omitEmptyStrings().splitToList(inputData); - PremiumList newPremiumList = PremiumListDao.save(name, inputDataPreProcessed); + PremiumList newPremiumList = + PremiumListDao.save(name, existingList.get().getCurrency(), inputDataPreProcessed); String message = String.format( diff --git a/core/src/main/resources/META-INF/persistence.xml b/core/src/main/resources/META-INF/persistence.xml index ff0fa1332..c897a0c51 100644 --- a/core/src/main/resources/META-INF/persistence.xml +++ b/core/src/main/resources/META-INF/persistence.xml @@ -60,6 +60,7 @@ google.registry.model.registrar.Registrar google.registry.model.registrar.RegistrarContact google.registry.model.registry.label.PremiumList + google.registry.model.registry.label.PremiumList$PremiumEntry google.registry.model.registry.label.ReservedList google.registry.model.registry.label.ReservedList$ReservedListEntry google.registry.model.registry.Registry @@ -74,7 +75,6 @@ google.registry.persistence.transaction.TransactionEntity google.registry.schema.domain.RegistryLock google.registry.schema.replay.SqlReplayCheckpoint - google.registry.schema.tld.PremiumEntry google.registry.persistence.converter.AllocationTokenStatusTransitionConverter @@ -90,7 +90,6 @@ google.registry.persistence.converter.InetAddressSetConverter google.registry.persistence.converter.LocalDateConverter google.registry.persistence.converter.PostalInfoChoiceListConverter - google.registry.persistence.converter.PremiumListKeyConverter google.registry.persistence.converter.RegistrarPocSetConverter google.registry.persistence.converter.ReservedListKeySetConverter google.registry.persistence.converter.Spec11ThreatMatchThreatTypeSetConverter diff --git a/core/src/test/java/google/registry/backup/ReplayCommitLogsToSqlActionTest.java b/core/src/test/java/google/registry/backup/ReplayCommitLogsToSqlActionTest.java index 553475b8e..b70991173 100644 --- a/core/src/test/java/google/registry/backup/ReplayCommitLogsToSqlActionTest.java +++ b/core/src/test/java/google/registry/backup/ReplayCommitLogsToSqlActionTest.java @@ -57,6 +57,7 @@ import google.registry.model.ofy.CommitLogManifest; import google.registry.model.ofy.CommitLogMutation; import google.registry.model.registrar.RegistrarContact; import google.registry.model.registry.label.PremiumList; +import google.registry.model.registry.label.PremiumList.PremiumEntry; import google.registry.model.registry.label.ReservedList; import google.registry.model.server.Lock; import google.registry.model.tmch.ClaimsList; @@ -65,7 +66,6 @@ import google.registry.persistence.VKey; import google.registry.persistence.transaction.JpaTransactionManager; import google.registry.persistence.transaction.TransactionManagerFactory; import google.registry.schema.replay.SqlReplayCheckpoint; -import google.registry.schema.tld.PremiumEntry; import google.registry.testing.AppEngineExtension; import google.registry.testing.DatabaseHelper; import google.registry.testing.FakeClock; diff --git a/core/src/test/java/google/registry/batch/ExpandRecurringBillingEventsActionTest.java b/core/src/test/java/google/registry/batch/ExpandRecurringBillingEventsActionTest.java index 9d240a1b1..6e8bb6739 100644 --- a/core/src/test/java/google/registry/batch/ExpandRecurringBillingEventsActionTest.java +++ b/core/src/test/java/google/registry/batch/ExpandRecurringBillingEventsActionTest.java @@ -691,7 +691,7 @@ public class ExpandRecurringBillingEventsActionTest persistResource( Registry.get("tld") .asBuilder() - .setPremiumList(persistPremiumList("tld2", "example,USD 100")) + .setPremiumList(persistPremiumList("tld2", USD, "example,USD 100")) .build()); persistResource(recurring); action.cursorTimeParam = Optional.of(START_OF_TIME); diff --git a/core/src/test/java/google/registry/export/ExportPremiumTermsActionTest.java b/core/src/test/java/google/registry/export/ExportPremiumTermsActionTest.java index eba59e47e..29f0e7775 100644 --- a/core/src/test/java/google/registry/export/ExportPremiumTermsActionTest.java +++ b/core/src/test/java/google/registry/export/ExportPremiumTermsActionTest.java @@ -23,6 +23,7 @@ import static google.registry.testing.DatabaseHelper.persistResource; import static java.nio.charset.StandardCharsets.UTF_8; import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR; import static javax.servlet.http.HttpServletResponse.SC_OK; +import static org.joda.money.CurrencyUnit.USD; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; @@ -54,7 +55,7 @@ public class ExportPremiumTermsActionTest { private static final ImmutableList PREMIUM_NAMES = ImmutableList.of("2048,USD 549", "0,USD 549"); private static final String EXPECTED_FILE_CONTENT = - DISCLAIMER_WITH_NEWLINE + "0,USD 549.00\n" + "2048,USD 549.00\n"; + DISCLAIMER_WITH_NEWLINE + "0, 549.00\n" + "2048, 549.00\n"; @RegisterExtension public final AppEngineExtension appEngine = @@ -75,7 +76,7 @@ public class ExportPremiumTermsActionTest { @BeforeEach void beforeEach() throws Exception { createTld("tld"); - PremiumList pl = PremiumListDao.save("pl-name", PREMIUM_NAMES); + PremiumList pl = PremiumListDao.save("pl-name", USD, PREMIUM_NAMES); persistResource( Registry.get("tld").asBuilder().setPremiumList(pl).setDriveFolderId("folder_id").build()); when(driveConnection.createOrUpdateFile( diff --git a/core/src/test/java/google/registry/flows/domain/DomainCheckFlowTest.java b/core/src/test/java/google/registry/flows/domain/DomainCheckFlowTest.java index 9f95b7dad..3b5e489b4 100644 --- a/core/src/test/java/google/registry/flows/domain/DomainCheckFlowTest.java +++ b/core/src/test/java/google/registry/flows/domain/DomainCheckFlowTest.java @@ -895,7 +895,7 @@ class DomainCheckFlowTest extends ResourceCheckFlowTestCase tm().put(registry)); @@ -145,7 +145,7 @@ public final class RegistryTest extends EntityTestCase { .setReservedListMapFromLines( ImmutableList.of("potato,FULLY_BLOCKED", "phone,FULLY_BLOCKED")) .setShouldPublish(true) - .setLastUpdateTime(fakeClock.nowUtc()) + .setCreationTimestamp(fakeClock.nowUtc()) .build()); ReservedList rl16 = persistReservedList( @@ -154,7 +154,7 @@ public final class RegistryTest extends EntityTestCase { .setReservedListMapFromLines( ImmutableList.of("port,FULLY_BLOCKED", "manteau,FULLY_BLOCKED")) .setShouldPublish(true) - .setLastUpdateTime(fakeClock.nowUtc()) + .setCreationTimestamp(fakeClock.nowUtc()) .build()); Registry registry1 = newRegistry("propter", "PROPTER") @@ -197,7 +197,7 @@ public final class RegistryTest extends EntityTestCase { .setReservedListMapFromLines( ImmutableList.of("potato,FULLY_BLOCKED", "phone,FULLY_BLOCKED")) .setShouldPublish(true) - .setLastUpdateTime(fakeClock.nowUtc()) + .setCreationTimestamp(fakeClock.nowUtc()) .build()); ReservedList rl6 = persistReservedList( @@ -206,7 +206,7 @@ public final class RegistryTest extends EntityTestCase { .setReservedListMapFromLines( ImmutableList.of("port,FULLY_BLOCKED", "manteau,FULLY_BLOCKED")) .setShouldPublish(true) - .setLastUpdateTime(fakeClock.nowUtc()) + .setCreationTimestamp(fakeClock.nowUtc()) .build()); Registry r = Registry.get("tld").asBuilder().setReservedLists(ImmutableSet.of(rl5, rl6)).build(); @@ -223,7 +223,7 @@ public final class RegistryTest extends EntityTestCase { .setReservedListMapFromLines( ImmutableList.of("potato,FULLY_BLOCKED", "phone,FULLY_BLOCKED")) .setShouldPublish(true) - .setLastUpdateTime(fakeClock.nowUtc()) + .setCreationTimestamp(fakeClock.nowUtc()) .build()); persistReservedList( new ReservedList.Builder() @@ -231,7 +231,7 @@ public final class RegistryTest extends EntityTestCase { .setReservedListMapFromLines( ImmutableList.of("port,FULLY_BLOCKED", "manteau,FULLY_BLOCKED")) .setShouldPublish(true) - .setLastUpdateTime(fakeClock.nowUtc()) + .setCreationTimestamp(fakeClock.nowUtc()) .build()); Registry r = Registry.get("tld") @@ -245,7 +245,7 @@ public final class RegistryTest extends EntityTestCase { @TestOfyAndSql void testSetPremiumList() { - PremiumList pl2 = persistPremiumList("tld2", "lol,USD 50", "cat,USD 700"); + PremiumList pl2 = persistPremiumList("tld2", USD, "lol,USD 50", "cat,USD 700"); Registry registry = Registry.get("tld").asBuilder().setPremiumList(pl2).build(); Optional pl = registry.getPremiumListName(); assertThat(pl).hasValue("tld2"); 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 985b919d6..ee5ea03a1 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 @@ -27,7 +27,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; 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.model.registry.label.PremiumList.PremiumEntry; import google.registry.schema.tld.PremiumListDao; import google.registry.testing.AppEngineExtension; import java.math.BigDecimal; @@ -48,11 +48,7 @@ public class PremiumListTest { createTld("tld"); PremiumList pl = persistPremiumList( - "tld", - "lol,USD 999 # yup", - "rich,USD 1999 #tada", - "icann,JPY 100", - "johnny-be-goode,USD 20.50"); + "tld", USD, "lol, 999", "rich, 1999", "icann, 100", "johnny-be-goode, 20.50"); persistResource(Registry.get("tld").asBuilder().setPremiumList(pl).build()); } @@ -60,7 +56,7 @@ public class PremiumListTest { void testSave_badSyntax() { assertThrows( IllegalArgumentException.class, - () -> persistPremiumList("gtld1", "lol,nonsense USD,e,e # yup")); + () -> persistPremiumList("gtld1", USD, "lol,nonsense USD,e,e # yup")); } @Test @@ -102,14 +98,21 @@ public class PremiumListTest { "List 'tld' cannot contain duplicate labels. Dupes (with counts) were: [lol x 2]"); } + @Test + void testParse_canIncludeOrNotIncludeCurrencyUnit() { + PremiumListDao.save("tld", USD, ImmutableList.of("rofl,USD 90", "paper, 80")); + assertThat(PremiumListDao.getPremiumPrice("tld", "rofl").get()).isEqualTo(Money.of(USD, 90)); + assertThat(PremiumListDao.getPremiumPrice("tld", "paper").get()).isEqualTo(Money.of(USD, 80)); + } + @Test void testValidation_labelMustBeLowercase() { Exception e = assertThrows( IllegalArgumentException.class, () -> - new PremiumListEntry.Builder() - .setPrice(Money.parse("USD 399")) + new PremiumEntry.Builder() + .setPrice(BigDecimal.valueOf(399)) .setLabel("UPPER.tld") .build()); assertThat(e).hasMessageThat().contains("must be in puny-coded, lower-case form"); @@ -121,8 +124,8 @@ public class PremiumListTest { assertThrows( IllegalArgumentException.class, () -> - new PremiumListEntry.Builder() - .setPrice(Money.parse("USD 399")) + new PremiumEntry.Builder() + .setPrice(BigDecimal.valueOf(399)) .setLabel("lower.みんな") .build()); assertThat(e).hasMessageThat().contains("must be in puny-coded, lower-case form"); diff --git a/core/src/test/java/google/registry/model/registry/label/ReservedListDaoTest.java b/core/src/test/java/google/registry/model/registry/label/ReservedListDaoTest.java index d882e1a3c..536a8ec0f 100644 --- a/core/src/test/java/google/registry/model/registry/label/ReservedListDaoTest.java +++ b/core/src/test/java/google/registry/model/registry/label/ReservedListDaoTest.java @@ -57,7 +57,7 @@ public class ReservedListDaoTest { testReservedList = new ReservedList.Builder() .setName("testlist") - .setLastUpdateTime(fakeClock.nowUtc()) + .setCreationTimestamp(fakeClock.nowUtc()) .setShouldPublish(false) .setReservedListMap(testReservations) .build(); @@ -76,7 +76,7 @@ public class ReservedListDaoTest { .getSingleResult(); assertThat(persistedList.getReservedListEntries()) .containsExactlyEntriesIn(testReservations); - assertThat(persistedList.getLastUpdateTime()).isEqualTo(fakeClock.nowUtc()); + assertThat(persistedList.getCreationTimestamp()).isEqualTo(fakeClock.nowUtc()); }); } @@ -108,7 +108,7 @@ public class ReservedListDaoTest { ReservedListDao.save(testReservedList); ReservedList persistedList = ReservedListDao.getLatestRevision("testlist").get(); assertThat(persistedList.getRevisionId()).isNotNull(); - assertThat(persistedList.getLastUpdateTime()).isEqualTo(fakeClock.nowUtc()); + assertThat(persistedList.getCreationTimestamp()).isEqualTo(fakeClock.nowUtc()); assertThat(persistedList.getName()).isEqualTo("testlist"); assertThat(persistedList.getShouldPublish()).isFalse(); assertThat(persistedList.getReservedListEntries()).containsExactlyEntriesIn(testReservations); @@ -119,7 +119,7 @@ public class ReservedListDaoTest { ReservedListDao.save( new ReservedList.Builder() .setName("testlist") - .setLastUpdateTime(fakeClock.nowUtc()) + .setCreationTimestamp(fakeClock.nowUtc()) .setShouldPublish(false) .setReservedListMap( ImmutableMap.of( @@ -130,7 +130,7 @@ public class ReservedListDaoTest { ReservedListDao.save(testReservedList); ReservedList persistedList = ReservedListDao.getLatestRevision("testlist").get(); assertThat(persistedList.getRevisionId()).isNotNull(); - assertThat(persistedList.getLastUpdateTime()).isEqualTo(fakeClock.nowUtc()); + assertThat(persistedList.getCreationTimestamp()).isEqualTo(fakeClock.nowUtc()); assertThat(persistedList.getName()).isEqualTo("testlist"); assertThat(persistedList.getShouldPublish()).isFalse(); assertThat(persistedList.getReservedListEntries()).containsExactlyEntriesIn(testReservations); diff --git a/core/src/test/java/google/registry/model/registry/label/ReservedListTest.java b/core/src/test/java/google/registry/model/registry/label/ReservedListTest.java index 68fc9dd3c..4e110133c 100644 --- a/core/src/test/java/google/registry/model/registry/label/ReservedListTest.java +++ b/core/src/test/java/google/registry/model/registry/label/ReservedListTest.java @@ -35,7 +35,7 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import google.registry.model.ofy.Ofy; import google.registry.model.registry.Registry; -import google.registry.schema.tld.PremiumEntry; +import google.registry.model.registry.label.PremiumList.PremiumEntry; import google.registry.testing.AppEngineExtension; import google.registry.testing.FakeClock; import google.registry.testing.InjectExtension; @@ -255,17 +255,17 @@ class ReservedListTest { assertThat(reservedList.getReservedListEntries()).hasSize(3); ReservedListEntry trombone = reservedList.getReservedListEntries().get("trombone"); - assertThat(trombone.label).isEqualTo("trombone"); + assertThat(trombone.domainLabel).isEqualTo("trombone"); assertThat(trombone.reservationType).isEqualTo(FULLY_BLOCKED); assertThat(trombone.comment).isEqualTo("yup"); ReservedListEntry oysters = reservedList.getReservedListEntries().get("oysters"); - assertThat(oysters.label).isEqualTo("oysters"); + assertThat(oysters.domainLabel).isEqualTo("oysters"); assertThat(oysters.reservationType).isEqualTo(FULLY_BLOCKED); assertThat(oysters.comment).isEqualTo("this is a loooong comment"); ReservedListEntry nullComment = reservedList.getReservedListEntries().get("nullcomment"); - assertThat(nullComment.label).isEqualTo("nullcomment"); + assertThat(nullComment.domainLabel).isEqualTo("nullcomment"); assertThat(nullComment.reservationType).isEqualTo(ALLOWED_IN_SUNRISE); assertThat(nullComment.comment).isEmpty(); } @@ -299,8 +299,7 @@ class ReservedListTest { ReservedList original = persistReservedList("tld-reserved-cloning", "trombone,FULLY_BLOCKED"); ReservedList clone = original.asBuilder().build(); assertThat(clone.getName()).isEqualTo("tld-reserved-cloning"); - assertThat(clone.creationTime).isEqualTo(original.creationTime); - assertThat(clone.lastUpdateTime).isEqualTo(original.lastUpdateTime); + assertThat(clone.creationTimestamp).isEqualTo(original.creationTimestamp); assertThat(clone.parent).isEqualTo(original.parent); assertThat(original.getReservedListEntries()).isEqualTo(clone.getReservedListEntries()); } diff --git a/core/src/test/java/google/registry/persistence/converter/PremiumListKeyConverterTest.java b/core/src/test/java/google/registry/persistence/converter/PremiumListKeyConverterTest.java deleted file mode 100644 index 6b379c13f..000000000 --- a/core/src/test/java/google/registry/persistence/converter/PremiumListKeyConverterTest.java +++ /dev/null @@ -1,90 +0,0 @@ -// Copyright 2020 The Nomulus Authors. All Rights Reserved. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package google.registry.persistence.converter; - -import static com.google.common.truth.Truth.assertThat; -import static google.registry.model.common.EntityGroupRoot.getCrossTldKey; -import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm; - -import com.googlecode.objectify.Key; -import google.registry.model.ImmutableObject; -import google.registry.model.registry.label.PremiumList; -import google.registry.testing.AppEngineExtension; -import javax.persistence.Entity; -import javax.persistence.Id; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.RegisterExtension; - -/** Unit tests for {@link PremiumListKeyConverter}. */ -class PremiumListKeyConverterTest { - - @RegisterExtension - final AppEngineExtension appEngine = - AppEngineExtension.builder() - .withDatastoreAndCloudSql() - .withJpaUnitTestEntities(PremiumListEntity.class) - .build(); - - private final PremiumListKeyConverter converter = new PremiumListKeyConverter(); - - @Test - void convertToDatabaseColumn_returnsNullIfInputIsNull() { - assertThat(converter.convertToDatabaseColumn(null)).isNull(); - } - - @Test - void convertToDatabaseColumn_convertsCorrectly() { - assertThat( - converter.convertToDatabaseColumn( - Key.create(getCrossTldKey(), PremiumList.class, "testList"))) - .isEqualTo("testList"); - } - - @Test - void convertToEntityAttribute_returnsNullIfInputIsNull() { - assertThat(converter.convertToEntityAttribute(null)).isNull(); - } - - @Test - void convertToEntityAttribute_convertsCorrectly() { - assertThat(converter.convertToEntityAttribute("testList")) - .isEqualTo(Key.create(getCrossTldKey(), PremiumList.class, "testList")); - } - - @Test - void testRoundTrip() { - Key key = Key.create(getCrossTldKey(), PremiumList.class, "test"); - PremiumListEntity testEntity = new PremiumListEntity(key); - jpaTm().transact(() -> jpaTm().insert(testEntity)); - PremiumListEntity persisted = - jpaTm().transact(() -> jpaTm().getEntityManager().find(PremiumListEntity.class, "test")); - assertThat(persisted.premiumList).isEqualTo(key); - } - - @Entity(name = "PremiumListEntity") - private static class PremiumListEntity extends ImmutableObject { - - @Id String name; - - Key premiumList; - - public PremiumListEntity() {} - - PremiumListEntity(Key premiumList) { - this.name = premiumList.getName(); - this.premiumList = premiumList; - } - } -} diff --git a/core/src/test/java/google/registry/pricing/PricingEngineProxyTest.java b/core/src/test/java/google/registry/pricing/PricingEngineProxyTest.java index 452a5f900..eca2bd4e8 100644 --- a/core/src/test/java/google/registry/pricing/PricingEngineProxyTest.java +++ b/core/src/test/java/google/registry/pricing/PricingEngineProxyTest.java @@ -49,7 +49,8 @@ public class PricingEngineProxyTest { @BeforeEach void beforeEach() { PremiumList premiumList = - persistPremiumList("rich,USD 100", "richer,USD 999", "fraction,USD 20.50"); + persistPremiumList( + "premium list", USD, "rich,USD 100", "richer,USD 999", "fraction,USD 20.50"); createTld("moka"); persistResource(Registry.get("moka").asBuilder().setPremiumList(premiumList).build()); clock = new FakeClock(DateTime.parse("2016-03-17T12:01:00Z")); diff --git a/core/src/test/java/google/registry/schema/tld/PremiumListDaoTest.java b/core/src/test/java/google/registry/schema/tld/PremiumListDaoTest.java index d49861b60..5c866f60d 100644 --- a/core/src/test/java/google/registry/schema/tld/PremiumListDaoTest.java +++ b/core/src/test/java/google/registry/schema/tld/PremiumListDaoTest.java @@ -76,7 +76,7 @@ public class PremiumListDaoTest { .setName("testname") .setCurrency(USD) .setLabelsToPrices(TEST_PRICES) - .setCreationTime(fakeClock.nowUtc()) + .setCreationTimestamp(fakeClock.nowUtc()) .build(); } @@ -90,7 +90,7 @@ public class PremiumListDaoTest { assertThat(persistedListOpt).isPresent(); PremiumList persistedList = persistedListOpt.get(); assertThat(persistedList.getLabelsToPrices()).containsExactlyEntriesIn(TEST_PRICES); - assertThat(persistedList.getCreationTime()).isEqualTo(fakeClock.nowUtc()); + assertThat(persistedList.getCreationTimestamp()).isEqualTo(fakeClock.nowUtc()); }); } @@ -112,7 +112,7 @@ public class PremiumListDaoTest { BigDecimal.valueOf(0.01), "silver", BigDecimal.valueOf(30.03))) - .setCreationTime(fakeClock.nowUtc()) + .setCreationTimestamp(fakeClock.nowUtc()) .build()); jpaTm() .transact( @@ -129,9 +129,8 @@ public class PremiumListDaoTest { BigDecimal.valueOf(0.01), "silver", BigDecimal.valueOf(30.03))); - assertThat(savedList.getCreationTime()).isEqualTo(fakeClock.nowUtc()); + assertThat(savedList.getCreationTimestamp()).isEqualTo(fakeClock.nowUtc()); assertThat(savedList.getRevisionId()).isGreaterThan(firstRevisionId); - assertThat(savedList.getCreationTime()).isEqualTo(fakeClock.nowUtc()); }); } @@ -154,14 +153,14 @@ public class PremiumListDaoTest { .setName("list1") .setCurrency(USD) .setLabelsToPrices(ImmutableMap.of("wrong", BigDecimal.valueOf(1000.50))) - .setCreationTime(fakeClock.nowUtc()) + .setCreationTimestamp(fakeClock.nowUtc()) .build()); PremiumListDao.save( new PremiumList.Builder() .setName("list1") .setCurrency(USD) .setLabelsToPrices(TEST_PRICES) - .setCreationTime(fakeClock.nowUtc()) + .setCreationTimestamp(fakeClock.nowUtc()) .build()); jpaTm() .transact( @@ -182,7 +181,7 @@ public class PremiumListDaoTest { .setName("list1") .setCurrency(JPY) .setLabelsToPrices(TEST_PRICES) - .setCreationTime(fakeClock.nowUtc()) + .setCreationTimestamp(fakeClock.nowUtc()) .build()); jpaTm() .transact( @@ -207,7 +206,7 @@ public class PremiumListDaoTest { .setName("premlist") .setCurrency(USD) .setLabelsToPrices(TEST_PRICES) - .setCreationTime(fakeClock.nowUtc()) + .setCreationTimestamp(fakeClock.nowUtc()) .build()); persistResource( newRegistry("foobar", "FOOBAR").asBuilder().setPremiumList(premiumList).build()); @@ -231,7 +230,7 @@ public class PremiumListDaoTest { BigDecimal.valueOf(1000.0), "palladium", BigDecimal.valueOf(15000))) - .setCreationTime(fakeClock.nowUtc()) + .setCreationTimestamp(fakeClock.nowUtc()) .build()); persistResource( newRegistry("foobar", "FOOBAR").asBuilder().setPremiumList(premiumList).build()); @@ -247,7 +246,7 @@ public class PremiumListDaoTest { 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"))); + transactIfJpaTm(() -> PremiumListDao.save("testname", USD, ImmutableList.of("test,USD 1"))); assertThat(PremiumListDao.premiumListCache.getIfPresent("testname")).isNull(); } diff --git a/core/src/test/java/google/registry/schema/tld/PremiumListUtilsTest.java b/core/src/test/java/google/registry/schema/tld/PremiumListUtilsTest.java index 0eb282de4..811a3df28 100644 --- a/core/src/test/java/google/registry/schema/tld/PremiumListUtilsTest.java +++ b/core/src/test/java/google/registry/schema/tld/PremiumListUtilsTest.java @@ -16,6 +16,7 @@ package google.registry.schema.tld; import static com.google.common.truth.Truth.assertThat; import static google.registry.schema.tld.PremiumListUtils.parseToPremiumList; +import static org.joda.money.CurrencyUnit.USD; import static org.junit.jupiter.api.Assertions.assertThrows; import com.google.common.collect.ImmutableList; @@ -36,7 +37,7 @@ class PremiumListUtilsTest { void parseInputToPremiumList_works() { PremiumList premiumList = parseToPremiumList( - "testlist", ImmutableList.of("foo,USD 99.50", "bar,USD 30", "baz,USD 10")); + "testlist", USD, ImmutableList.of("foo,USD 99.50", "bar,USD 30", "baz,USD 10")); assertThat(premiumList.getName()).isEqualTo("testlist"); assertThat(premiumList.getLabelsToPrices()) .containsExactly("foo", twoDigits(99.50), "bar", twoDigits(30), "baz", twoDigits(10)); @@ -49,10 +50,10 @@ class PremiumListUtilsTest { IllegalArgumentException.class, () -> parseToPremiumList( - "testlist", ImmutableList.of("foo,USD 99.50", "bar,USD 30", "baz,JPY 990"))); - assertThat(thrown) - .hasMessageThat() - .isEqualTo("The Cloud SQL schema requires exactly one currency, but got: [JPY, USD]"); + "testlist", + USD, + ImmutableList.of("foo,USD 99.50", "bar,USD 30", "baz,JPY 990"))); + assertThat(thrown).hasMessageThat().isEqualTo("The currency unit must be USD"); } private static BigDecimal twoDigits(double num) { diff --git a/core/src/test/java/google/registry/server/Fixture.java b/core/src/test/java/google/registry/server/Fixture.java index 3426288d0..bf0eeba8f 100644 --- a/core/src/test/java/google/registry/server/Fixture.java +++ b/core/src/test/java/google/registry/server/Fixture.java @@ -24,6 +24,7 @@ import static google.registry.testing.DatabaseHelper.newDomainBase; import static google.registry.testing.DatabaseHelper.persistActiveHost; import static google.registry.testing.DatabaseHelper.persistPremiumList; import static google.registry.testing.DatabaseHelper.persistResource; +import static org.joda.money.CurrencyUnit.USD; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; @@ -61,7 +62,7 @@ public enum Fixture { createTlds("xn--q9jyb4c", "example"); // Used for OT&E TLDs - persistPremiumList("default_sandbox_list", "sandbox,USD 1000"); + persistPremiumList("default_sandbox_list", USD, "sandbox,USD 1000"); try { OteStatsTestHelper.setupCompleteOte("otefinished"); diff --git a/core/src/test/java/google/registry/testing/DatabaseHelper.java b/core/src/test/java/google/registry/testing/DatabaseHelper.java index 8ad8151d8..1089403e3 100644 --- a/core/src/test/java/google/registry/testing/DatabaseHelper.java +++ b/core/src/test/java/google/registry/testing/DatabaseHelper.java @@ -101,7 +101,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.PremiumList.PremiumListEntry; +import google.registry.model.registry.label.PremiumList.PremiumEntry; import google.registry.model.registry.label.ReservedList; import google.registry.model.registry.label.ReservedListDao; import google.registry.model.reporting.HistoryEntry; @@ -264,7 +264,7 @@ public class DatabaseHelper { .setRestoreBillingCost(Money.of(USD, 17)) .setServerStatusChangeBillingCost(Money.of(USD, 19)) // Always set a default premium list. Tests that don't want it can delete it. - .setPremiumList(persistPremiumList(tld, DEFAULT_PREMIUM_LIST_CONTENTS.get())) + .setPremiumList(persistPremiumList(tld, USD, DEFAULT_PREMIUM_LIST_CONTENTS.get())) .setPremiumPricingEngine(StaticPremiumListPricingEngine.NAME) .setDnsWriters(ImmutableSet.of(VoidDnsWriter.NAME)) .build(); @@ -361,7 +361,7 @@ public class DatabaseHelper { .setName(listName) .setReservedListMapFromLines(ImmutableList.copyOf(lines)) .setShouldPublish(shouldPublish) - .setLastUpdateTime(DateTime.now(DateTimeZone.UTC)) + .setCreationTimestamp(DateTime.now(DateTimeZone.UTC)) .build(); return persistReservedList(reservedList); } @@ -374,29 +374,27 @@ public class DatabaseHelper { * incrementing FakeClock for all tests in order to persist the commit logs properly because of * the requirement to have monotonically increasing timestamps. */ - public static PremiumList persistPremiumList(String listName, String... lines) { + public static PremiumList persistPremiumList( + String listName, CurrencyUnit currencyUnit, String... lines) { checkState(lines.length != 0, "Must provide at least one premium entry"); PremiumList partialPremiumList = new PremiumList.Builder().setName(listName).build(); - ImmutableMap entries = partialPremiumList.parse(asList(lines)); - CurrencyUnit currencyUnit = - entries.entrySet().iterator().next().getValue().getValue().getCurrencyUnit(); + ImmutableMap entries = partialPremiumList.parse(asList(lines)); PremiumList premiumList = partialPremiumList .asBuilder() - .setCreationTime(DateTime.now(DateTimeZone.UTC)) + .setCreationTimestamp(DateTime.now(DateTimeZone.UTC)) .setCurrency(currencyUnit) .setLabelsToPrices( entries.entrySet().stream() .collect( - toImmutableMap( - Map.Entry::getKey, entry -> entry.getValue().getValue().getAmount()))) + toImmutableMap(Map.Entry::getKey, entry -> entry.getValue().getValue()))) .build(); // 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)); + PremiumListDao.save(premiumList); maybeAdvanceClock(); return premiumList; } @@ -1245,11 +1243,10 @@ public class DatabaseHelper { return result; } - /** Returns the entire map of {@link PremiumListEntry}s for the given {@link PremiumList}. */ - public static ImmutableMap loadPremiumListEntries( - PremiumList premiumList) { - return Streams.stream(PremiumListDao.loadAllPremiumListEntries(premiumList.getName())) - .collect(toImmutableMap(PremiumListEntry::getLabel, Function.identity())); + /** Returns the entire map of {@link PremiumEntry}s for the given {@link PremiumList}. */ + public static ImmutableMap loadPremiumEntries(PremiumList premiumList) { + return Streams.stream(PremiumListDao.loadAllPremiumEntries(premiumList.getName())) + .collect(toImmutableMap(PremiumEntry::getDomainLabel, Function.identity())); } /** Loads and returns the registrar with the given client ID, or throws IAE if not present. */ diff --git a/core/src/test/java/google/registry/tools/CreateAnchorTenantCommandTest.java b/core/src/test/java/google/registry/tools/CreateAnchorTenantCommandTest.java index e43654d9b..8e82f5123 100644 --- a/core/src/test/java/google/registry/tools/CreateAnchorTenantCommandTest.java +++ b/core/src/test/java/google/registry/tools/CreateAnchorTenantCommandTest.java @@ -17,6 +17,7 @@ package google.registry.tools; import static google.registry.testing.DatabaseHelper.createTld; import static google.registry.testing.DatabaseHelper.persistPremiumList; import static google.registry.testing.DatabaseHelper.persistResource; +import static org.joda.money.CurrencyUnit.JPY; import static org.junit.jupiter.api.Assertions.assertThrows; import com.beust.jcommander.ParameterException; @@ -76,7 +77,7 @@ class CreateAnchorTenantCommandTest extends EppToolCommandTestCase labelsToEntries) { return new ReservedList.Builder() .setName(name) - .setLastUpdateTime(creationTime) + .setCreationTimestamp(creationTime) .setShouldPublish(shouldPublish) .setReservedListMap(labelsToEntries) .build(); diff --git a/core/src/test/java/google/registry/tools/CreatePremiumListCommandTest.java b/core/src/test/java/google/registry/tools/CreatePremiumListCommandTest.java index 0927786e3..ee067fd27 100644 --- a/core/src/test/java/google/registry/tools/CreatePremiumListCommandTest.java +++ b/core/src/test/java/google/registry/tools/CreatePremiumListCommandTest.java @@ -33,7 +33,7 @@ class CreatePremiumListCommandTest @BeforeEach void beforeEach() { - registry = createRegistry(TLD_TEST, null); + registry = createRegistry(TLD_TEST, null, null); } @Test @@ -45,7 +45,7 @@ class CreatePremiumListCommandTest @Test void commandRun_successCreateList() throws Exception { - runCommandForced("--name=" + TLD_TEST, "--input=" + premiumTermsPath); + runCommandForced("--name=" + TLD_TEST, "--input=" + premiumTermsPath, "--currency=USD"); assertThat(registry.getTld().toString()).isEqualTo(TLD_TEST); assertThat(PremiumListDao.getLatestRevision(TLD_TEST).isPresent()).isTrue(); } @@ -53,50 +53,52 @@ class CreatePremiumListCommandTest @Test // since the old entity is always null and file cannot be empty, the prompt will NOT be "No entity // changes to apply." - void commandInit_successStageNewEntity() throws Exception { + void commandPrompt_successStageNewEntity() throws Exception { CreatePremiumListCommand command = new CreatePremiumListCommand(); command.inputFile = Paths.get(premiumTermsPath); - command.init(); - assertThat(command.prompt()).contains("Create PremiumList@"); - assertThat(command.prompt()).contains(String.format("name=%s", TLD_TEST)); + command.currencyUnit = "USD"; + command.prompt(); + assertThat(command.prompt()).isEqualTo("Create new premium list for prime?"); } @Test - void commandInit_successStageNewEntityWithOverride() throws Exception { + void commandPrompt_successStageNewEntityWithOverride() throws Exception { CreatePremiumListCommand command = new CreatePremiumListCommand(); String alterTld = "override"; command.inputFile = Paths.get(premiumTermsPath); command.override = true; command.name = alterTld; - command.init(); - assertThat(command.prompt()).contains("Create PremiumList@"); - assertThat(command.prompt()).contains(String.format("name=%s", alterTld)); + command.currencyUnit = "USD"; + command.prompt(); + assertThat(command.prompt()).isEqualTo("Create new premium list for override?"); } @Test - void commandInit_failureNoInputFile() { + void commandPrompt_failureNoInputFile() { CreatePremiumListCommand command = new CreatePremiumListCommand(); - assertThrows(NullPointerException.class, command::init); + assertThrows(NullPointerException.class, command::prompt); } @Test - void commandInit_failurePremiumListAlreadyExists() { + void commandPrompt_failurePremiumListAlreadyExists() { String randomStr = "random"; createTld(randomStr); CreatePremiumListCommand command = new CreatePremiumListCommand(); command.name = randomStr; - IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, command::init); + command.currencyUnit = "USD"; + IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, command::prompt); assertThat(thrown).hasMessageThat().isEqualTo("A premium list already exists by this name"); } @Test - void commandInit_failureMismatchedTldFileName_noOverride() throws Exception { + void commandPrompt_failureMismatchedTldFileName_noOverride() throws Exception { CreatePremiumListCommand command = new CreatePremiumListCommand(); String fileName = "random"; Path tmpPath = tmpDir.resolve(String.format("%s.txt", fileName)); Files.write(new byte[0], tmpPath.toFile()); command.inputFile = tmpPath; - IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, command::init); + command.currencyUnit = "USD"; + IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, command::prompt); assertThat(thrown) .hasMessageThat() .contains( @@ -108,11 +110,12 @@ class CreatePremiumListCommandTest } @Test - void commandInit_failureMismatchedTldName_noOverride() { + void commandPrompt_failureMismatchedTldName_noOverride() { CreatePremiumListCommand command = new CreatePremiumListCommand(); String fileName = "random"; command.name = fileName; - IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, command::init); + command.currencyUnit = "USD"; + IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, command::prompt); assertThat(thrown) .hasMessageThat() .contains( @@ -122,18 +125,4 @@ class CreatePremiumListCommandTest + "yet TLD %s does not exist", fileName)); } - - @Test - void commandInit_failureUseEmptyFile() throws Exception { - CreatePremiumListCommand command = new CreatePremiumListCommand(); - String fileName = "empty"; - Path tmpPath = tmpDir.resolve(String.format("%s.txt", fileName)); - Files.write(new byte[0], tmpPath.toFile()); - command.inputFile = tmpPath; - command.name = TLD_TEST; - IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, command::init); - assertThat(thrown) - .hasMessageThat() - .contains("The Cloud SQL schema requires exactly one currency"); - } } diff --git a/core/src/test/java/google/registry/tools/CreateTldCommandTest.java b/core/src/test/java/google/registry/tools/CreateTldCommandTest.java index a65e1d9a3..761a1096e 100644 --- a/core/src/test/java/google/registry/tools/CreateTldCommandTest.java +++ b/core/src/test/java/google/registry/tools/CreateTldCommandTest.java @@ -49,7 +49,7 @@ class CreateTldCommandTest extends CommandTestCase { persistReservedList("xn--q9jyb4c_abuse", "lamb,FULLY_BLOCKED"); persistReservedList("tld_banned", "kilo,FULLY_BLOCKED", "lima,FULLY_BLOCKED"); persistReservedList("soy_expurgated", "fireflies,FULLY_BLOCKED"); - persistPremiumList("xn--q9jyb4c", "minecraft,USD 1000"); + persistPremiumList("xn--q9jyb4c", USD, "minecraft,USD 1000"); command.validDnsWriterNames = ImmutableSet.of("VoidDnsWriter", "FooDnsWriter"); } diff --git a/core/src/test/java/google/registry/tools/DeletePremiumListCommandTest.java b/core/src/test/java/google/registry/tools/DeletePremiumListCommandTest.java index e9324d25d..79a1257b2 100644 --- a/core/src/test/java/google/registry/tools/DeletePremiumListCommandTest.java +++ b/core/src/test/java/google/registry/tools/DeletePremiumListCommandTest.java @@ -17,9 +17,10 @@ package google.registry.tools; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth8.assertThat; import static google.registry.testing.DatabaseHelper.createTld; -import static google.registry.testing.DatabaseHelper.loadPremiumListEntries; +import static google.registry.testing.DatabaseHelper.loadPremiumEntries; import static google.registry.testing.DatabaseHelper.persistPremiumList; import static google.registry.testing.DatabaseHelper.persistResource; +import static org.joda.money.CurrencyUnit.USD; import static org.junit.jupiter.api.Assertions.assertThrows; import google.registry.model.registry.Registry; @@ -32,8 +33,8 @@ class DeletePremiumListCommandTest extends CommandTestCase { void beforeEach() { command.passwordGenerator = passwordGenerator; command.clock = new FakeClock(DateTime.parse("2018-07-07TZ")); - persistPremiumList("default_sandbox_list", "sandbox,USD 1000"); + persistPremiumList("default_sandbox_list", USD, "sandbox,USD 1000"); } /** Verify TLD creation. */ @@ -79,17 +79,17 @@ class SetupOteCommandTest extends CommandTestCase { ImmutableSortedMap eapFeeSchedule = registry.getEapFeeScheduleAsMap(); if (!isEarlyAccess) { assertThat(eapFeeSchedule) - .isEqualTo(ImmutableSortedMap.of(new DateTime(0), Money.of(CurrencyUnit.USD, 0))); + .isEqualTo(ImmutableSortedMap.of(new DateTime(0), Money.of(USD, 0))); } else { assertThat(eapFeeSchedule) .isEqualTo( ImmutableSortedMap.of( new DateTime(0), - Money.of(CurrencyUnit.USD, 0), + Money.of(USD, 0), DateTime.parse("2018-03-01T00:00:00Z"), - Money.of(CurrencyUnit.USD, 100), + Money.of(USD, 100), DateTime.parse("2030-03-01T00:00:00Z"), - Money.of(CurrencyUnit.USD, 0))); + Money.of(USD, 0))); } } diff --git a/core/src/test/java/google/registry/tools/UpdatePremiumListCommandTest.java b/core/src/test/java/google/registry/tools/UpdatePremiumListCommandTest.java index 8f01fed80..6bde3f0cb 100644 --- a/core/src/test/java/google/registry/tools/UpdatePremiumListCommandTest.java +++ b/core/src/test/java/google/registry/tools/UpdatePremiumListCommandTest.java @@ -16,15 +16,18 @@ package google.registry.tools; import static com.google.common.truth.Truth.assertThat; import static java.nio.charset.StandardCharsets.UTF_8; +import static org.joda.money.CurrencyUnit.USD; 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.model.registry.label.PremiumList; import google.registry.schema.tld.PremiumListDao; import java.io.File; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.Optional; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -35,40 +38,32 @@ class UpdatePremiumListCommandTest @BeforeEach void beforeEach() { - registry = createRegistry(TLD_TEST, initialPremiumListData); + registry = createRegistry(TLD_TEST, USD, initialPremiumListData); } @Test void verify_registryIsSetUpCorrectly() { + Optional list = PremiumListDao.getLatestRevision(TLD_TEST); // ensure that no premium list is created before running the command - assertThat(PremiumListDao.getLatestRevision(TLD_TEST).isPresent()).isTrue(); + assertThat(list.isPresent()).isTrue(); // ensure that there's value in existing premium list; UpdatePremiumListCommand command = new UpdatePremiumListCommand(); - ImmutableSet entries = command.getExistingPremiumListEntry(TLD_TEST); + ImmutableSet entries = command.getExistingPremiumEntry(list.get()); assertThat(entries.size()).isEqualTo(1); // data from @beforeEach of CreateOrUpdatePremiumListCommandTestCase.java assertThat(entries.contains("doge,USD 9090.00")).isTrue(); } @Test - void commandInit_successStageNoEntityChange() throws Exception { - UpdatePremiumListCommand command = new UpdatePremiumListCommand(); - command.inputFile = Paths.get(premiumTermsPath); - command.name = TLD_TEST; - command.init(); - assertThat(command.prompt()).contains("No entity changes to apply."); - } - - @Test - void commandInit_successStageEntityChange() throws Exception { + void commandPrompt_successStageEntityChange() throws Exception { File tmpFile = tmpDir.resolve(String.format("%s.txt", TLD_TEST)).toFile(); - String newPremiumListData = "omg,JPY 1234"; + String newPremiumListData = "omg,USD 1234"; Files.asCharSink(tmpFile, UTF_8).write(newPremiumListData); UpdatePremiumListCommand command = new UpdatePremiumListCommand(); command.inputFile = Paths.get(tmpFile.getPath()); command.name = TLD_TEST; - command.init(); - assertThat(command.prompt()).contains("Update PremiumList@"); + command.prompt(); + assertThat(command.prompt()).contains("Update premium list for prime?"); } @Test @@ -82,7 +77,8 @@ class UpdatePremiumListCommandTest command.inputFile = Paths.get(tmpFile.getPath()); runCommandForced("--name=" + TLD_TEST, "--input=" + command.inputFile); - ImmutableSet entries = command.getExistingPremiumListEntry(TLD_TEST); + ImmutableSet entries = + command.getExistingPremiumEntry(PremiumListDao.getLatestRevision(TLD_TEST).get()); assertThat(entries.size()).isEqualTo(1); // verify that list is updated; cannot use only string since price is formatted; assertThat(entries.contains("eth,USD 9999.00")).isTrue(); @@ -99,7 +95,8 @@ class UpdatePremiumListCommandTest runCommandForced("--name=" + TLD_TEST, "--input=" + command.inputFile); // assert all three lines from premiumTerms are added - ImmutableSet entries = command.getExistingPremiumListEntry(TLD_TEST); + ImmutableSet entries = + command.getExistingPremiumEntry(PremiumListDao.getLatestRevision(TLD_TEST).get()); assertThat(entries.size()).isEqualTo(3); assertThat(entries.contains("foo,USD 9000.00")).isTrue(); assertThat(entries.contains("doge,USD 100.00")).isTrue(); @@ -107,26 +104,24 @@ class UpdatePremiumListCommandTest } @Test - void commandInit_failureUpdateEmptyList() throws Exception { + void commandPrompt_failureUpdateEmptyList() throws Exception { Path tmpPath = tmpDir.resolve(String.format("%s.txt", TLD_TEST)); Files.write(new byte[0], tmpPath.toFile()); UpdatePremiumListCommand command = new UpdatePremiumListCommand(); command.inputFile = tmpPath; command.name = TLD_TEST; - IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, command::init); - assertThat(thrown) - .hasMessageThat() - .contains("The Cloud SQL schema requires exactly one currency"); + IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, command::prompt); + assertThat(thrown).hasMessageThat().contains("Input cannot be empty"); } @Test - void commandInit_failureNoPreviousVersion() { + void commandPrompt_failureNoPreviousVersion() { String fileName = "random"; - registry = createRegistry(fileName, null); + registry = createRegistry(fileName, null, null); UpdatePremiumListCommand command = new UpdatePremiumListCommand(); command.name = fileName; - IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, command::init); + IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, command::prompt); assertThat(thrown) .hasMessageThat() .isEqualTo( @@ -134,17 +129,17 @@ class UpdatePremiumListCommandTest } @Test - void commandInit_failureNoInputFile() { + void commandPrompt_failureNoInputFile() { UpdatePremiumListCommand command = new UpdatePremiumListCommand(); - assertThrows(NullPointerException.class, command::init); + assertThrows(NullPointerException.class, command::prompt); } @Test - void commandInit_failureTldFromNameDoesNotExist() { + void commandPrompt_failureTldFromNameDoesNotExist() { String fileName = "random"; UpdatePremiumListCommand command = new UpdatePremiumListCommand(); command.name = fileName; - IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, command::init); + IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, command::prompt); assertThat(thrown) .hasMessageThat() .isEqualTo( @@ -152,13 +147,13 @@ class UpdatePremiumListCommandTest } @Test - void commandInit_failureTldFromInputFileDoesNotExist() { + void commandPrompt_failureTldFromInputFileDoesNotExist() { String fileName = "random"; UpdatePremiumListCommand command = new UpdatePremiumListCommand(); // using tld extracted from file name but this tld is not part of the registry command.inputFile = Paths.get(tmpDir.resolve(String.format("%s.txt", fileName)).toFile().getPath()); - IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, command::init); + IllegalArgumentException thrown = assertThrows(IllegalArgumentException.class, command::prompt); assertThat(thrown) .hasMessageThat() .isEqualTo( diff --git a/core/src/test/java/google/registry/tools/UpdateReservedListCommandTest.java b/core/src/test/java/google/registry/tools/UpdateReservedListCommandTest.java index 251bf37ed..ac33218cb 100644 --- a/core/src/test/java/google/registry/tools/UpdateReservedListCommandTest.java +++ b/core/src/test/java/google/registry/tools/UpdateReservedListCommandTest.java @@ -48,8 +48,7 @@ class UpdateReservedListCommandTest new ReservedList.Builder() .setName("xn--q9jyb4c_common-reserved") .setReservedListMapFromLines(ImmutableList.of("helicopter,FULLY_BLOCKED")) - .setCreationTime(START_OF_TIME) - .setLastUpdateTime(START_OF_TIME) + .setCreationTimestamp(START_OF_TIME) .setShouldPublish(shouldPublish) .build()); } diff --git a/core/src/test/java/google/registry/tools/UpdateTldCommandTest.java b/core/src/test/java/google/registry/tools/UpdateTldCommandTest.java index 50d695f80..c9d709882 100644 --- a/core/src/test/java/google/registry/tools/UpdateTldCommandTest.java +++ b/core/src/test/java/google/registry/tools/UpdateTldCommandTest.java @@ -54,7 +54,7 @@ class UpdateTldCommandTest extends CommandTestCase { persistReservedList("xn--q9jyb4c_abuse", "lamb,FULLY_BLOCKED"); persistReservedList("tld_banned", "kilo,FULLY_BLOCKED", "lima,FULLY_BLOCKED"); persistReservedList("soy_expurgated", "fireflies,FULLY_BLOCKED"); - persistPremiumList("xn--q9jyb4c", "minecraft,USD 1000"); + persistPremiumList("xn--q9jyb4c", USD, "minecraft,USD 1000"); persistReservedList("xn--q9jyb4c_r1", "foo,FULLY_BLOCKED"); persistReservedList("xn--q9jyb4c_r2", "moop,FULLY_BLOCKED"); createTld("xn--q9jyb4c"); 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 6971710a3..02de5a176 100644 --- a/core/src/test/java/google/registry/tools/server/CreatePremiumListActionTest.java +++ b/core/src/test/java/google/registry/tools/server/CreatePremiumListActionTest.java @@ -17,8 +17,9 @@ package google.registry.tools.server; import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth8.assertThat; import static google.registry.testing.DatabaseHelper.createTlds; -import static google.registry.testing.DatabaseHelper.loadPremiumListEntries; +import static google.registry.testing.DatabaseHelper.loadPremiumEntries; import static javax.servlet.http.HttpServletResponse.SC_OK; +import static org.joda.money.CurrencyUnit.USD; import google.registry.model.registry.label.PremiumList; import google.registry.schema.tld.PremiumListDao; @@ -86,20 +87,21 @@ public class CreatePremiumListActionTest { action.name = "zanzibar"; action.inputData = "zanzibar,USD 100"; action.override = true; + action.currency = USD; action.run(); assertThat(response.getStatus()).isEqualTo(SC_OK); - assertThat(loadPremiumListEntries(PremiumListDao.getLatestRevision("zanzibar").get())) - .hasSize(1); + assertThat(loadPremiumEntries(PremiumListDao.getLatestRevision("zanzibar").get())).hasSize(1); } @Test void test_success() { action.name = "foo"; action.inputData = "rich,USD 25\nricher,USD 1000\n"; + action.currency = USD; action.run(); assertThat(response.getStatus()).isEqualTo(SC_OK); PremiumList premiumList = PremiumListDao.getLatestRevision("foo").get(); - assertThat(loadPremiumListEntries(premiumList)).hasSize(2); + assertThat(loadPremiumEntries(premiumList)).hasSize(2); assertThat(PremiumListDao.getPremiumPrice(premiumList.getName(), "rich")) .hasValue(Money.parse("USD 25")); assertThat(PremiumListDao.getPremiumPrice(premiumList.getName(), "diamond")).isEmpty(); diff --git a/core/src/test/java/google/registry/tools/server/ListPremiumListsActionTest.java b/core/src/test/java/google/registry/tools/server/ListPremiumListsActionTest.java index a2191b0be..3302c13ef 100644 --- a/core/src/test/java/google/registry/tools/server/ListPremiumListsActionTest.java +++ b/core/src/test/java/google/registry/tools/server/ListPremiumListsActionTest.java @@ -15,6 +15,8 @@ package google.registry.tools.server; import static google.registry.testing.DatabaseHelper.persistPremiumList; +import static org.joda.money.CurrencyUnit.JPY; +import static org.joda.money.CurrencyUnit.USD; import java.util.Optional; import org.junit.jupiter.api.BeforeEach; @@ -27,8 +29,8 @@ class ListPremiumListsActionTest extends ListActionTestCase { @BeforeEach void beforeEach() { - persistPremiumList("xn--q9jyb4c", "rich,USD 100"); - persistPremiumList("how", "richer,JPY 5000"); + persistPremiumList("xn--q9jyb4c", USD, "rich,USD 100"); + persistPremiumList("how", JPY, "richer,JPY 5000"); action = new ListPremiumListsAction(); } 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 47972821d..00b3373bd 100644 --- a/core/src/test/java/google/registry/tools/server/UpdatePremiumListActionTest.java +++ b/core/src/test/java/google/registry/tools/server/UpdatePremiumListActionTest.java @@ -17,9 +17,10 @@ package google.registry.tools.server; import static com.google.common.truth.Truth.assertThat; import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm; import static google.registry.testing.DatabaseHelper.createTlds; -import static google.registry.testing.DatabaseHelper.loadPremiumListEntries; +import static google.registry.testing.DatabaseHelper.loadPremiumEntries; import static google.registry.util.ResourceUtils.readResourceUtf8; import static javax.servlet.http.HttpServletResponse.SC_OK; +import static org.joda.money.CurrencyUnit.USD; import com.google.common.base.Splitter; import com.google.common.truth.Truth8; @@ -79,12 +80,12 @@ class UpdatePremiumListActionTest { .omitEmptyStrings() .splitToList( readResourceUtf8(DatabaseHelper.class, "default_premium_list_testdata.csv")); - PremiumListDao.save("foo", inputLines); + PremiumListDao.save("foo", USD, inputLines); action.name = "foo"; action.inputData = "rich,USD 75\nricher,USD 5000\npoor, USD 0.99"; action.run(); assertThat(response.getStatus()).isEqualTo(SC_OK); - assertThat(loadPremiumListEntries(PremiumListDao.getLatestRevision("foo").get())).hasSize(3); + assertThat(loadPremiumEntries(PremiumListDao.getLatestRevision("foo").get())).hasSize(3); Truth8.assertThat(PremiumListDao.getPremiumPrice("foo", "rich")) .hasValue(Money.parse("USD 75")); Truth8.assertThat(PremiumListDao.getPremiumPrice("foo", "richer")) diff --git a/core/src/test/java/google/registry/ui/server/registrar/ConsoleOteSetupActionTest.java b/core/src/test/java/google/registry/ui/server/registrar/ConsoleOteSetupActionTest.java index fe6663286..c867f548e 100644 --- a/core/src/test/java/google/registry/ui/server/registrar/ConsoleOteSetupActionTest.java +++ b/core/src/test/java/google/registry/ui/server/registrar/ConsoleOteSetupActionTest.java @@ -20,6 +20,7 @@ import static com.google.common.truth.Truth8.assertThat; import static google.registry.model.registrar.Registrar.loadByClientId; import static google.registry.testing.DatabaseHelper.persistPremiumList; import static javax.servlet.http.HttpServletResponse.SC_MOVED_TEMPORARILY; +import static org.joda.money.CurrencyUnit.USD; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -78,7 +79,7 @@ public final class ConsoleOteSetupActionTest { @BeforeEach void beforeEach() throws Exception { - persistPremiumList("default_sandbox_list", "sandbox,USD 1000"); + persistPremiumList("default_sandbox_list", USD, "sandbox,USD 1000"); action.req = request; action.method = Method.GET; diff --git a/core/src/test/java/google/registry/ui/server/registrar/ConsoleRegistrarCreatorActionTest.java b/core/src/test/java/google/registry/ui/server/registrar/ConsoleRegistrarCreatorActionTest.java index d925b9aa9..3209cc3c1 100644 --- a/core/src/test/java/google/registry/ui/server/registrar/ConsoleRegistrarCreatorActionTest.java +++ b/core/src/test/java/google/registry/ui/server/registrar/ConsoleRegistrarCreatorActionTest.java @@ -20,6 +20,7 @@ import static google.registry.model.common.GaeUserIdConverter.convertEmailAddres import static google.registry.model.registrar.Registrar.loadByClientId; import static google.registry.testing.DatabaseHelper.persistPremiumList; import static javax.servlet.http.HttpServletResponse.SC_MOVED_TEMPORARILY; +import static org.joda.money.CurrencyUnit.USD; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -81,7 +82,7 @@ final class ConsoleRegistrarCreatorActionTest { @BeforeEach void beforeEach() throws Exception { - persistPremiumList("default_sandbox_list", "sandbox,USD 1000"); + persistPremiumList("default_sandbox_list", USD, "sandbox,USD 1000"); action.req = request; action.method = Method.GET; @@ -198,8 +199,7 @@ final class ConsoleRegistrarCreatorActionTest { Registrar registrar = loadByClientId("myclientid").orElse(null); assertThat(registrar).isNotNull(); assertThat(registrar.getClientId()).isEqualTo("myclientid"); - assertThat(registrar.getBillingAccountMap()) - .containsExactly(CurrencyUnit.USD, "billing-account"); + assertThat(registrar.getBillingAccountMap()).containsExactly(USD, "billing-account"); assertThat(registrar.getDriveFolderId()).isEqualTo("drive-id"); assertThat(registrar.getIanaIdentifier()).isEqualTo(12321L); @@ -296,9 +296,12 @@ final class ConsoleRegistrarCreatorActionTest { assertThat(registrar).isNotNull(); assertThat(registrar.getBillingAccountMap()) .containsExactly( - CurrencyUnit.JPY, "billing-account-yen", - CurrencyUnit.USD, "billing-account-usd", - CurrencyUnit.EUR, "billing-account-eur"); + CurrencyUnit.JPY, + "billing-account-yen", + USD, + "billing-account-usd", + CurrencyUnit.EUR, + "billing-account-eur"); } @TestOfyAndSql diff --git a/core/src/test/resources/google/registry/export/backup_kinds.txt b/core/src/test/resources/google/registry/export/backup_kinds.txt index c904af35a..1bb2b7568 100644 --- a/core/src/test/resources/google/registry/export/backup_kinds.txt +++ b/core/src/test/resources/google/registry/export/backup_kinds.txt @@ -15,9 +15,6 @@ LastSqlTransaction Modification OneTime PollMessage -PremiumList -PremiumListEntry -PremiumListRevision RdeRevision Recurring Registrar diff --git a/core/src/test/resources/google/registry/export/crosstld_kinds.txt b/core/src/test/resources/google/registry/export/crosstld_kinds.txt index 357bbc0cc..7cbfa8d9b 100644 --- a/core/src/test/resources/google/registry/export/crosstld_kinds.txt +++ b/core/src/test/resources/google/registry/export/crosstld_kinds.txt @@ -2,9 +2,6 @@ ClaimsList ClaimsListSingleton Cursor DatabaseMigrationStateSchedule -PremiumList -PremiumListEntry -PremiumListRevision Registrar RegistrarContact Registry diff --git a/core/src/test/resources/google/registry/export/reporting_kinds.txt b/core/src/test/resources/google/registry/export/reporting_kinds.txt index 89a606ad2..a7d062606 100644 --- a/core/src/test/resources/google/registry/export/reporting_kinds.txt +++ b/core/src/test/resources/google/registry/export/reporting_kinds.txt @@ -11,9 +11,6 @@ HostResource Modification OneTime PollMessage -PremiumList -PremiumListEntry -PremiumListRevision Recurring Registrar RegistrarContact diff --git a/core/src/test/resources/google/registry/model/schema.txt b/core/src/test/resources/google/registry/model/schema.txt index c3a8555c0..016987225 100644 --- a/core/src/test/resources/google/registry/model/schema.txt +++ b/core/src/test/resources/google/registry/model/schema.txt @@ -711,24 +711,6 @@ enum google.registry.model.registry.Registry$TldType { REAL; TEST; } -class google.registry.model.registry.label.PremiumList { - @Id java.lang.String name; - @Parent com.googlecode.objectify.Key parent; - com.googlecode.objectify.Key revisionKey; - org.joda.time.DateTime creationTime; - org.joda.time.DateTime lastUpdateTime; -} -class google.registry.model.registry.label.PremiumList$PremiumListEntry { - @Id java.lang.String label; - @Parent com.googlecode.objectify.Key parent; - java.lang.String comment; - org.joda.money.Money price; -} -class google.registry.model.registry.label.PremiumList$PremiumListRevision { - @Id long revisionId; - @Parent com.googlecode.objectify.Key parent; - com.google.common.hash.BloomFilter probablePremiumLabels; -} enum google.registry.model.registry.label.ReservationType { ALLOWED_IN_SUNRISE; FULLY_BLOCKED; @@ -741,11 +723,10 @@ class google.registry.model.registry.label.ReservedList { @Parent com.googlecode.objectify.Key parent; boolean shouldPublish; java.util.Map reservedListMap; - org.joda.time.DateTime creationTime; - org.joda.time.DateTime lastUpdateTime; + org.joda.time.DateTime creationTimestamp; } class google.registry.model.registry.label.ReservedList$ReservedListEntry { - @Id java.lang.String label; + @Id java.lang.String domainLabel; google.registry.model.registry.label.ReservationType reservationType; java.lang.Long revisionId; java.lang.String comment;