diff --git a/core/src/main/java/google/registry/model/tld/Tld.java b/core/src/main/java/google/registry/model/tld/Tld.java index 1af964a52..ca616b925 100644 --- a/core/src/main/java/google/registry/model/tld/Tld.java +++ b/core/src/main/java/google/registry/model/tld/Tld.java @@ -980,7 +980,7 @@ public class Tld extends ImmutableObject implements Buildable, UnsafeSerializabl return this; } - private static final Pattern ROID_SUFFIX_PATTERN = Pattern.compile("^[A-Z\\d_]{1,8}$"); + public static final Pattern ROID_SUFFIX_PATTERN = Pattern.compile("^[A-Z\\d_]{1,8}$"); public Builder setRoidSuffix(String roidSuffix) { checkArgument( diff --git a/core/src/main/java/google/registry/tools/ConfigureTldCommand.java b/core/src/main/java/google/registry/tools/ConfigureTldCommand.java new file mode 100644 index 000000000..0ac2eb38f --- /dev/null +++ b/core/src/main/java/google/registry/tools/ConfigureTldCommand.java @@ -0,0 +1,172 @@ +// Copyright 2023 The Nomulus Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package google.registry.tools; + +import static com.google.common.base.Preconditions.checkArgument; +import static google.registry.model.tld.Tld.Builder.ROID_SUFFIX_PATTERN; +import static google.registry.model.tld.Tlds.getTlds; +import static google.registry.util.ListNamingUtils.convertFilePathToName; + +import com.beust.jcommander.Parameter; +import com.beust.jcommander.Parameters; +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.base.CharMatcher; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSortedMap; +import com.google.common.collect.Sets; +import com.google.common.collect.Sets.SetView; +import google.registry.model.tld.Tld; +import google.registry.model.tld.label.PremiumList; +import google.registry.model.tld.label.PremiumListDao; +import google.registry.tools.params.PathParameter; +import google.registry.util.Idn; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Map; +import java.util.Optional; +import java.util.Set; +import java.util.stream.Collectors; +import javax.inject.Inject; +import javax.inject.Named; +import org.joda.money.CurrencyUnit; +import org.joda.money.Money; +import org.joda.time.DateTime; +import org.yaml.snakeyaml.Yaml; + +/** Command to create or update a {@link Tld} using a YAML file. */ +@Parameters(separators = " =", commandDescription = "Create or update TLD using YAML") +public class ConfigureTldCommand extends MutatingCommand { + + @Parameter( + names = {"-i", "--input"}, + description = "Filename of TLD YAML file.", + validateWith = PathParameter.InputFile.class, + required = true) + Path inputFile; + + @Inject ObjectMapper mapper; + + @Inject + @Named("dnsWriterNames") + Set validDnsWriterNames; + + // TODO(sarahbot@): Add a breakglass setting to this tool to indicate when a TLD has been modified + // outside of source control + + // TODO(sarahbot@): Add a check for diffs between passed in file and current TLD and exit if there + // is no diff. Treat nulls and empty sets as the same value. + + @Override + protected void init() throws Exception { + String name = convertFilePathToName(inputFile); + Map tldData = new Yaml().load(Files.newBufferedReader(inputFile)); + checkName(name, tldData); + checkForMissingFields(tldData); + Tld oldTld = getTlds().contains(name) ? Tld.get(name) : null; + Tld newTld = mapper.readValue(inputFile.toFile(), Tld.class); + checkPremiumList(newTld); + checkDnsWriters(newTld); + checkCurrency(newTld); + stageEntityChange(oldTld, newTld); + } + + private void checkName(String name, Map tldData) { + checkArgument(CharMatcher.ascii().matchesAllOf(name), "A TLD name must be in plain ASCII"); + checkArgument(!Character.isDigit(name.charAt(0)), "TLDs cannot begin with a number"); + checkArgument( + tldData.get("tldStr").equals(name), + "The input file name must match the name of the TLD it represents"); + checkArgument( + tldData.get("tldUnicode").equals(Idn.toUnicode(name)), + "The value for tldUnicode must equal the unicode representation of the TLD name"); + checkArgument( + ROID_SUFFIX_PATTERN.matcher((CharSequence) tldData.get("roidSuffix")).matches(), + "ROID suffix must be in format %s", + ROID_SUFFIX_PATTERN.pattern()); + } + + private void checkForMissingFields(Map tldData) { + Set tldFields = + Arrays.stream(Tld.class.getDeclaredFields()) + .filter(field -> !Modifier.isStatic(field.getModifiers())) + .filter(field -> field.getAnnotation(JsonIgnore.class) == null) + .map(Field::getName) + .collect(Collectors.toSet()); + Set missingFields = new HashSet<>(); + for (String field : tldFields) { + if (!tldData.containsKey(field)) { + missingFields.add(field); + } + } + checkArgument( + missingFields.isEmpty(), + "The input file is missing data for the following fields: %s", + missingFields); + } + + private void checkPremiumList(Tld newTld) { + Optional premiumListName = newTld.getPremiumListName(); + if (!premiumListName.isPresent()) return; + Optional premiumList = PremiumListDao.getLatestRevision(premiumListName.get()); + checkArgument( + premiumList.isPresent(), + "The premium list with the name %s does not exist", + premiumListName.get()); + checkArgument( + premiumList.get().getCurrency().equals(newTld.getCurrency()), + "The premium list must use the TLD's currency"); + } + + private void checkDnsWriters(Tld newTld) { + ImmutableSet dnsWriters = newTld.getDnsWriters(); + SetView invalidDnsWriters = Sets.difference(dnsWriters, validDnsWriterNames); + checkArgument( + invalidDnsWriters.isEmpty(), "Invalid DNS writer name(s) specified: %s", invalidDnsWriters); + } + + private void checkCurrency(Tld newTld) { + CurrencyUnit currencyUnit = newTld.getCurrency(); + checkArgument( + currencyUnit.equals(newTld.getCreateBillingCost().getCurrencyUnit()), + "createBillingCost must use the same currency as the TLD"); + checkArgument( + currencyUnit.equals(newTld.getRestoreBillingCost().getCurrencyUnit()), + "restoreBillingCost must use the same currency as the TLD"); + checkArgument( + currencyUnit.equals(newTld.getServerStatusChangeBillingCost().getCurrencyUnit()), + "serverStatusChangeBillingCost must use the same currency as the TLD"); + checkArgument( + currencyUnit.equals(newTld.getRegistryLockOrUnlockBillingCost().getCurrencyUnit()), + "registryLockOrUnlockBillingCost must use the same currency as the TLD"); + ImmutableSortedMap renewBillingCostTransitions = + newTld.getRenewBillingCostTransitions(); + for (Money renewBillingCost : renewBillingCostTransitions.values()) { + checkArgument( + renewBillingCost.getCurrencyUnit().equals(currencyUnit), + "All Money values in the renewBillingCostTransitions map must use the TLD's currency" + + " unit"); + } + ImmutableSortedMap eapFeeSchedule = newTld.getEapFeeScheduleAsMap(); + for (Money eapFee : eapFeeSchedule.values()) { + checkArgument( + eapFee.getCurrencyUnit().equals(currencyUnit), + "All Money values in the eapFeeSchedule map must use the TLD's currency unit"); + } + } +} diff --git a/core/src/main/java/google/registry/tools/CreateOrUpdateTldCommand.java b/core/src/main/java/google/registry/tools/CreateOrUpdateTldCommand.java index ecce2e6cc..9f6caeb89 100644 --- a/core/src/main/java/google/registry/tools/CreateOrUpdateTldCommand.java +++ b/core/src/main/java/google/registry/tools/CreateOrUpdateTldCommand.java @@ -25,8 +25,8 @@ import com.google.common.base.Joiner; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSortedMap; -import com.google.common.collect.ImmutableSortedSet; import com.google.common.collect.Sets; +import com.google.common.collect.Sets.SetView; import google.registry.model.pricing.StaticPremiumListPricingEngine; import google.registry.model.tld.Tld; import google.registry.model.tld.Tld.TldState; @@ -409,8 +409,7 @@ abstract class CreateOrUpdateTldCommand extends MutatingCommand { if (dnsWriters != null) { ImmutableSet dnsWritersSet = ImmutableSet.copyOf(dnsWriters); - ImmutableSortedSet invalidDnsWriters = - ImmutableSortedSet.copyOf(Sets.difference(dnsWritersSet, validDnsWriterNames)); + SetView invalidDnsWriters = Sets.difference(dnsWritersSet, validDnsWriterNames); checkArgument( invalidDnsWriters.isEmpty(), "Invalid DNS writer name(s) specified: %s", diff --git a/core/src/main/java/google/registry/tools/RegistryTool.java b/core/src/main/java/google/registry/tools/RegistryTool.java index 2971f2b48..1970e0132 100644 --- a/core/src/main/java/google/registry/tools/RegistryTool.java +++ b/core/src/main/java/google/registry/tools/RegistryTool.java @@ -33,6 +33,7 @@ public final class RegistryTool { .put("canonicalize_labels", CanonicalizeLabelsCommand.class) .put("check_domain", CheckDomainCommand.class) .put("check_domain_claims", CheckDomainClaimsCommand.class) + .put("configure_tld", ConfigureTldCommand.class) .put("convert_idn", ConvertIdnCommand.class) .put("count_domains", CountDomainsCommand.class) .put("create_anchor_tenant", CreateAnchorTenantCommand.class) diff --git a/core/src/main/java/google/registry/tools/RegistryToolComponent.java b/core/src/main/java/google/registry/tools/RegistryToolComponent.java index 3a9bb51a5..e9862a8d2 100644 --- a/core/src/main/java/google/registry/tools/RegistryToolComponent.java +++ b/core/src/main/java/google/registry/tools/RegistryToolComponent.java @@ -90,6 +90,8 @@ interface RegistryToolComponent { void inject(CheckDomainCommand command); + void inject(ConfigureTldCommand command); + void inject(CountDomainsCommand command); void inject(CreateAnchorTenantCommand command); diff --git a/core/src/test/java/google/registry/tools/ConfigureTldCommandTest.java b/core/src/test/java/google/registry/tools/ConfigureTldCommandTest.java new file mode 100644 index 000000000..96950e679 --- /dev/null +++ b/core/src/test/java/google/registry/tools/ConfigureTldCommandTest.java @@ -0,0 +1,448 @@ +// Copyright 2023 The Nomulus Authors. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +package google.registry.tools; + +import static com.google.common.truth.Truth.assertThat; +import static google.registry.model.domain.token.AllocationToken.TokenType.DEFAULT_PROMO; +import static google.registry.testing.DatabaseHelper.createTld; +import static google.registry.testing.DatabaseHelper.persistPremiumList; +import static google.registry.testing.DatabaseHelper.persistResource; +import static google.registry.testing.TestDataHelper.loadFile; +import static google.registry.tldconfig.idn.IdnTableEnum.EXTENDED_LATIN; +import static google.registry.tldconfig.idn.IdnTableEnum.JA; +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.joda.money.CurrencyUnit.JPY; +import static org.joda.money.CurrencyUnit.USD; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.exc.InvalidFormatException; +import com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException; +import com.google.common.base.Ascii; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSet; +import com.google.common.io.Files; +import google.registry.model.EntityYamlUtils; +import google.registry.model.domain.token.AllocationToken; +import google.registry.model.tld.Tld; +import google.registry.model.tld.label.PremiumList; +import google.registry.model.tld.label.PremiumListDao; +import java.io.File; +import org.joda.money.Money; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.testcontainers.shaded.com.google.common.collect.ImmutableMap; + +/** Unit tests for {@link ConfigureTldCommand} */ +public class ConfigureTldCommandTest extends CommandTestCase { + + PremiumList premiumList; + ObjectMapper objectMapper = EntityYamlUtils.createObjectMapper(); + + @BeforeEach + void beforeEach() { + command.mapper = objectMapper; + premiumList = persistPremiumList("test", USD, "silver,USD 50", "gold,USD 80"); + command.validDnsWriterNames = ImmutableSet.of("VoidDnsWriter", "FooDnsWriter"); + } + + private void testTldConfiguredSuccessfully(Tld tld, String filename) + throws JsonProcessingException { + String yaml = objectMapper.writeValueAsString(tld); + assertThat(yaml).isEqualTo(loadFile(getClass(), filename)); + } + + @Test + void testSuccess_createNewTld() throws Exception { + File tldFile = tmpDir.resolve("tld.yaml").toFile(); + Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "tld.yaml")); + runCommandForced("--input=" + tldFile); + Tld tld = Tld.get("tld"); + assertThat(tld).isNotNull(); + assertThat(tld.getDriveFolderId()).isEqualTo("driveFolder"); + assertThat(tld.getCreateBillingCost()).isEqualTo(Money.of(USD, 25)); + testTldConfiguredSuccessfully(tld, "tld.yaml"); + } + + @Test + void testSuccess_updateTld() throws Exception { + Tld tld = createTld("tld"); + assertThat(tld.getCreateBillingCost()).isEqualTo(Money.of(USD, 13)); + File tldFile = tmpDir.resolve("tld.yaml").toFile(); + Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "tld.yaml")); + runCommandForced("--input=" + tldFile); + Tld updatedTld = Tld.get("tld"); + assertThat(updatedTld.getCreateBillingCost()).isEqualTo(Money.of(USD, 25)); + testTldConfiguredSuccessfully(updatedTld, "tld.yaml"); + } + + @Test + void testSuccess_outOfOrderFieldsOnCreate() throws Exception { + File tldFile = tmpDir.resolve("outoforderfields.yaml").toFile(); + Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "outoforderfields.yaml")); + runCommandForced("--input=" + tldFile); + Tld tld = Tld.get("outoforderfields"); + // Cannot test that created TLD converted to YAML is equal to original YAML since the created + // TLD's YAML will contain the fields in the correct order + assertThat(tld).isNotNull(); + assertThat(tld.getDriveFolderId()).isEqualTo("driveFolder"); + assertThat(tld.getCreateBillingCost()).isEqualTo(Money.of(USD, 25)); + assertThat(tld.getPremiumListName().get()).isEqualTo("test"); + } + + @Test + void testSuccess_outOfOrderFieldsOnUpdate() throws Exception { + Tld tld = createTld("outoforderfields"); + assertThat(tld.getCreateBillingCost()).isEqualTo(Money.of(USD, 13)); + File tldFile = tmpDir.resolve("outoforderfields.yaml").toFile(); + Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "outoforderfields.yaml")); + runCommandForced("--input=" + tldFile); + Tld updatedTld = Tld.get("outoforderfields"); + // Cannot test that created TLD converted to YAML is equal to original YAML since the created + // TLD's YAML will contain the fields in the correct order + assertThat(updatedTld.getCreateBillingCost()).isEqualTo(Money.of(USD, 25)); + } + + @Test + void testFailure_fileMissingNullableFieldsOnCreate() throws Exception { + File tldFile = tmpDir.resolve("missingnullablefields.yaml").toFile(); + Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "missingnullablefields.yaml")); + IllegalArgumentException thrown = + assertThrows(IllegalArgumentException.class, () -> runCommandForced("--input=" + tldFile)); + assertThat(thrown.getMessage()) + .isEqualTo( + "The input file is missing data for the following fields: [tldStateTransitions," + + " premiumListName, currency, numDnsPublishLocks]"); + } + + @Test + void testFailure_fileMissingNullableFieldOnUpdate() throws Exception { + Tld tld = createTld("missingnullablefields"); + persistResource( + tld.asBuilder().setNumDnsPublishLocks(5).build()); // numDnsPublishLocks is nullable + File tldFile = tmpDir.resolve("missingnullablefields.yaml").toFile(); + Files.asCharSink(tldFile, UTF_8) + .write( + loadFile( + getClass(), "missingnullablefields.yaml")); // file is missing numDnsPublishLocks + IllegalArgumentException thrown = + assertThrows(IllegalArgumentException.class, () -> runCommandForced("--input=" + tldFile)); + assertThat(thrown.getMessage()) + .isEqualTo( + "The input file is missing data for the following fields: [tldStateTransitions," + + " premiumListName, currency, numDnsPublishLocks]"); + } + + @Test + void testSuccess_nullableFieldsAllNullOnCreate() throws Exception { + File tldFile = tmpDir.resolve("nullablefieldsallnull.yaml").toFile(); + Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "nullablefieldsallnull.yaml")); + runCommandForced("--input=" + tldFile); + Tld tld = Tld.get("nullablefieldsallnull"); + assertThat(tld).isNotNull(); + assertThat(tld.getDriveFolderId()).isEqualTo(null); + assertThat(tld.getCreateBillingCost()).isEqualTo(Money.of(USD, 25)); + // cannot test that created TLD converted to YAML is equal to original YAML since the created + // TLD's YAML will contain empty sets for some of the null fields + assertThat(tld.getIdnTables()).isEmpty(); + assertThat(tld.getDefaultPromoTokens()).isEmpty(); + } + + @Test + void testSuccess_nullableFieldsAllNullOnUpdate() throws Exception { + Tld tld = createTld("nullablefieldsallnull"); + persistResource( + tld.asBuilder().setIdnTables(ImmutableSet.of(JA)).setDriveFolderId("drive").build()); + File tldFile = tmpDir.resolve("nullablefieldsallnull.yaml").toFile(); + Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "nullablefieldsallnull.yaml")); + runCommandForced("--input=" + tldFile); + Tld updatedTld = Tld.get("nullablefieldsallnull"); + assertThat(updatedTld).isNotNull(); + assertThat(updatedTld.getDriveFolderId()).isEqualTo(null); + assertThat(updatedTld.getCreateBillingCost()).isEqualTo(Money.of(USD, 25)); + // cannot test that created TLD converted to YAML is equal to original YAML since the created + // TLD's YAML will contain empty sets for some of the null fields + assertThat(updatedTld.getIdnTables()).isEmpty(); + assertThat(updatedTld.getDefaultPromoTokens()).isEmpty(); + } + + @Test + void testFailure_fileContainsExtraFields() throws Exception { + File tldFile = tmpDir.resolve("extrafield.yaml").toFile(); + Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "extrafield.yaml")); + assertThrows(UnrecognizedPropertyException.class, () -> runCommandForced("--input=" + tldFile)); + } + + @Test + void testFailure_fileNameDoesNotMatchTldName() throws Exception { + File tldFile = tmpDir.resolve("othertld.yaml").toFile(); + Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "tld.yaml")); + IllegalArgumentException thrown = + assertThrows(IllegalArgumentException.class, () -> runCommandForced("--input=" + tldFile)); + assertThat(thrown.getMessage()) + .isEqualTo("The input file name must match the name of the TLD it represents"); + } + + @Test + void testFailure_tldUnicodeDoesNotMatch() throws Exception { + File tldFile = tmpDir.resolve("badunicode.yaml").toFile(); + Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "badunicode.yaml")); + IllegalArgumentException thrown = + assertThrows(IllegalArgumentException.class, () -> runCommandForced("--input=" + tldFile)); + assertThat(thrown.getMessage()) + .isEqualTo( + "The value for tldUnicode must equal the unicode representation of the TLD name"); + } + + @Test + void testFailure_tldUpperCase() throws Exception { + String name = "TLD"; + File tldFile = tmpDir.resolve("TLD.yaml").toFile(); + Files.asCharSink(tldFile, UTF_8) + .write( + loadFile( + getClass(), + "wildcard.yaml", + ImmutableMap.of( + "TLDSTR", name, "TLDUNICODE", name, "ROIDSUFFIX", Ascii.toUpperCase(name)))); + IllegalArgumentException thrown = + assertThrows(IllegalArgumentException.class, () -> runCommandForced("--input=" + tldFile)); + assertThat(thrown.getMessage()) + .isEqualTo( + "The value for tldUnicode must equal the unicode representation of the TLD name"); + } + + @Test + void testSuccess_asciiNameWithOptionalPunycode() throws Exception { + String name = "xn--q9jyb4c"; + File tldFile = tmpDir.resolve(name + ".yaml").toFile(); + String fileContents = + loadFile( + getClass(), + "wildcard.yaml", + ImmutableMap.of( + "TLDSTR", + "\"" + name + "\"", + "TLDUNICODE", + "\"みんな\"", + "ROIDSUFFIX", + "\"Q9JYB4C\"")); + Files.asCharSink(tldFile, UTF_8).write(fileContents); + runCommandForced("--input=" + tldFile); + Tld tld = Tld.get(name); + assertThat(tld).isNotNull(); + assertThat(tld.getDriveFolderId()).isEqualTo("driveFolder"); + assertThat(tld.getCreateBillingCost()).isEqualTo(Money.of(USD, 25)); + String yaml = objectMapper.writeValueAsString(tld); + assertThat(yaml).isEqualTo(fileContents); + } + + @Test + void testFailure_punycodeDoesNotMatch() throws Exception { + String name = "xn--q9jyb4c"; + File tldFile = tmpDir.resolve(name + ".yaml").toFile(); + String fileContents = + loadFile( + getClass(), + "wildcard.yaml", + ImmutableMap.of( + "TLDSTR", + "\"" + name + "\"", + "TLDUNICODE", + "\"yoyo\"", + "ROIDSUFFIX", + "\"Q9JYB4C\"")); + Files.asCharSink(tldFile, UTF_8).write(fileContents); + IllegalArgumentException thrown = + assertThrows(IllegalArgumentException.class, () -> runCommandForced("--input=" + tldFile)); + assertThat(thrown.getMessage()) + .isEqualTo( + "The value for tldUnicode must equal the unicode representation of the TLD name"); + } + + @Test + void testFailure_punycodeName() throws Exception { + String name = "みんな"; + File tldFile = tmpDir.resolve(name + ".yaml").toFile(); + String fileContents = + loadFile( + getClass(), + "wildcard.yaml", + ImmutableMap.of( + "TLDSTR", + "\"" + name + "\"", + "TLDUNICODE", + "\"みんな\"", + "ROIDSUFFIX", + "\"Q9JYB4C\"")); + Files.asCharSink(tldFile, UTF_8).write(fileContents); + IllegalArgumentException thrown = + assertThrows(IllegalArgumentException.class, () -> runCommandForced("--input=" + tldFile)); + assertThat(thrown.getMessage()).isEqualTo("A TLD name must be in plain ASCII"); + } + + @Test + void testFailure_invalidRoidSuffix() throws Exception { + String name = "tld"; + File tldFile = tmpDir.resolve("tld.yaml").toFile(); + Files.asCharSink(tldFile, UTF_8) + .write( + loadFile( + getClass(), + "wildcard.yaml", + ImmutableMap.of( + "TLDSTR", name, "TLDUNICODE", name, "ROIDSUFFIX", "TLLLLLLLLLLLLLLLLLLLLLLD"))); + IllegalArgumentException thrown = + assertThrows(IllegalArgumentException.class, () -> runCommandForced("--input=" + tldFile)); + assertThat(thrown.getMessage()).isEqualTo("ROID suffix must be in format ^[A-Z\\d_]{1,8}$"); + } + + @Test + void testFailure_invalidIdnTable() throws Exception { + File tldFile = tmpDir.resolve("badidn.yaml").toFile(); + Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "badidn.yaml")); + assertThrows(InvalidFormatException.class, () -> runCommandForced("--input=" + tldFile)); + } + + @Test + void testFailure_tldNameStartsWithNumber() throws Exception { + File tldFile = tmpDir.resolve("1tld.yaml").toFile(); + Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "1tld.yaml")); + IllegalArgumentException thrown = + assertThrows(IllegalArgumentException.class, () -> runCommandForced("--input=" + tldFile)); + assertThat(thrown.getMessage()).isEqualTo("TLDs cannot begin with a number"); + } + + @Test + void testFailure_invalidDnsWriter() throws Exception { + command.validDnsWriterNames = ImmutableSet.of("foo"); + File tldFile = tmpDir.resolve("tld.yaml").toFile(); + Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "tld.yaml")); + IllegalArgumentException thrown = + assertThrows(IllegalArgumentException.class, () -> runCommandForced("--input=" + tldFile)); + assertThat(thrown.getMessage()) + .isEqualTo("Invalid DNS writer name(s) specified: [VoidDnsWriter]"); + } + + @Test + void testFailure_mismatchedCurrencyUnitsOnCreate() throws Exception { + File tldFile = tmpDir.resolve("wrongcurrency.yaml").toFile(); + Files.asCharSink(tldFile, UTF_8) + .write( + loadFile( + getClass(), + "wrongcurrency.yaml", + ImmutableMap.of("RESTORECURRENCY", "EUR", "RENEWCURRENCY", "USD"))); + IllegalArgumentException thrown = + assertThrows(IllegalArgumentException.class, () -> runCommandForced("--input=" + tldFile)); + assertThat(thrown.getMessage()) + .isEqualTo("restoreBillingCost must use the same currency as the TLD"); + File tldFile2 = tmpDir.resolve("wrongcurrency.yaml").toFile(); + Files.asCharSink(tldFile2, UTF_8) + .write( + loadFile( + getClass(), + "wrongcurrency.yaml", + ImmutableMap.of("RESTORECURRENCY", "USD", "RENEWCURRENCY", "EUR"))); + thrown = + assertThrows(IllegalArgumentException.class, () -> runCommandForced("--input=" + tldFile2)); + assertThat(thrown.getMessage()) + .isEqualTo( + "All Money values in the renewBillingCostTransitions map must use the TLD's currency" + + " unit"); + } + + @Test + void testFailure_mismatchedCurrencyUnitsOnUpdate() throws Exception { + createTld("wrongcurreency"); + File tldFile = tmpDir.resolve("wrongcurrency.yaml").toFile(); + Files.asCharSink(tldFile, UTF_8) + .write( + loadFile( + getClass(), + "wrongcurrency.yaml", + ImmutableMap.of("RESTORECURRENCY", "EUR", "RENEWCURRENCY", "USD"))); + IllegalArgumentException thrown = + assertThrows(IllegalArgumentException.class, () -> runCommandForced("--input=" + tldFile)); + assertThat(thrown.getMessage()) + .isEqualTo("restoreBillingCost must use the same currency as the TLD"); + File tldFile2 = tmpDir.resolve("wrongcurrency.yaml").toFile(); + Files.asCharSink(tldFile2, UTF_8) + .write( + loadFile( + getClass(), + "wrongcurrency.yaml", + ImmutableMap.of("RESTORECURRENCY", "USD", "RENEWCURRENCY", "EUR"))); + thrown = + assertThrows(IllegalArgumentException.class, () -> runCommandForced("--input=" + tldFile2)); + assertThat(thrown.getMessage()) + .isEqualTo( + "All Money values in the renewBillingCostTransitions map must use the TLD's currency" + + " unit"); + } + + @Test + void testSuccess_emptyStringClearsDefaultPromoTokens() throws Exception { + Tld tld = createTld("tld"); + AllocationToken defaultToken = + persistResource( + new AllocationToken.Builder() + .setToken("bbbbb") + .setTokenType(DEFAULT_PROMO) + .setAllowedTlds(ImmutableSet.of("tld")) + .build()); + persistResource( + tld.asBuilder().setDefaultPromoTokens(ImmutableList.of(defaultToken.createVKey())).build()); + File tldFile = tmpDir.resolve("tld.yaml").toFile(); + Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "tld.yaml")); + runCommandForced("--input=" + tldFile); + Tld updatedTld = Tld.get("tld"); + assertThat(updatedTld.getDefaultPromoTokens()).isEmpty(); + testTldConfiguredSuccessfully(updatedTld, "tld.yaml"); + } + + @Test + void testSuccess_emptyStringClearsIdnTables() throws Exception { + Tld tld = createTld("tld"); + persistResource(tld.asBuilder().setIdnTables(ImmutableSet.of(EXTENDED_LATIN, JA)).build()); + File tldFile = tmpDir.resolve("tld.yaml").toFile(); + Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "tld.yaml")); + runCommandForced("--input=" + tldFile); + Tld updatedTld = Tld.get("tld"); + assertThat(updatedTld.getIdnTables()).isEmpty(); + testTldConfiguredSuccessfully(updatedTld, "tld.yaml"); + } + + @Test + void testFailure_premiumListDoesNotExist() throws Exception { + PremiumListDao.delete(premiumList); + File tldFile = tmpDir.resolve("tld.yaml").toFile(); + Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "tld.yaml")); + IllegalArgumentException thrown = + assertThrows(IllegalArgumentException.class, () -> runCommandForced("--input=" + tldFile)); + assertThat(thrown.getMessage()).isEqualTo("The premium list with the name test does not exist"); + } + + @Test + void testFailure_premiumListWrongCurrency() throws Exception { + PremiumListDao.delete(premiumList); + persistPremiumList("test", JPY, "bronze,JPY 80"); + File tldFile = tmpDir.resolve("tld.yaml").toFile(); + Files.asCharSink(tldFile, UTF_8).write(loadFile(getClass(), "tld.yaml")); + IllegalArgumentException thrown = + assertThrows(IllegalArgumentException.class, () -> runCommandForced("--input=" + tldFile)); + assertThat(thrown.getMessage()).isEqualTo("The premium list must use the TLD's currency"); + } +} diff --git a/core/src/test/java/google/registry/tools/CreateTldCommandTest.java b/core/src/test/java/google/registry/tools/CreateTldCommandTest.java index ccfc1af19..2fd0eb0c7 100644 --- a/core/src/test/java/google/registry/tools/CreateTldCommandTest.java +++ b/core/src/test/java/google/registry/tools/CreateTldCommandTest.java @@ -632,7 +632,7 @@ class CreateTldCommandTest extends CommandTestCase { "xn--q9jyb4c", "--roid_suffix=Q9JYB4C", "--dns_writers=Invalid,Deadbeef")); assertThat(thrown) .hasMessageThat() - .contains("Invalid DNS writer name(s) specified: [Deadbeef, Invalid]"); + .contains("Invalid DNS writer name(s) specified: [Invalid, Deadbeef]"); } @Test diff --git a/core/src/test/java/google/registry/tools/GetTldCommandTest.java b/core/src/test/java/google/registry/tools/GetTldCommandTest.java index bd5b1aadb..2d41d9123 100644 --- a/core/src/test/java/google/registry/tools/GetTldCommandTest.java +++ b/core/src/test/java/google/registry/tools/GetTldCommandTest.java @@ -16,11 +16,18 @@ package google.registry.tools; import static google.registry.testing.DatabaseHelper.createTld; import static google.registry.testing.DatabaseHelper.createTlds; +import static google.registry.testing.DatabaseHelper.persistPremiumList; +import static google.registry.testing.DatabaseHelper.persistResource; import static google.registry.testing.TestDataHelper.loadFile; +import static org.joda.money.CurrencyUnit.USD; import static org.junit.jupiter.api.Assertions.assertThrows; import com.beust.jcommander.ParameterException; import google.registry.model.EntityYamlUtils; +import google.registry.model.tld.Tld; +import google.registry.model.tld.label.PremiumList; +import org.joda.money.Money; +import org.joda.time.Duration; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -34,8 +41,16 @@ class GetTldCommandTest extends CommandTestCase { @Test void testSuccess() throws Exception { - createTld("xn--q9jyb4c"); - runCommand("xn--q9jyb4c"); + Tld tld = createTld("tld"); + PremiumList premiumList = persistPremiumList("test", USD, "silver,USD 50", "gold,USD 80"); + persistResource( + tld.asBuilder() + .setDnsAPlusAaaaTtl(Duration.millis(900)) + .setDriveFolderId("driveFolder") + .setCreateBillingCost(Money.of(USD, 25)) + .setPremiumList(premiumList) + .build()); + runCommand("tld"); assertInStdout(loadFile(getClass(), "tld.yaml")); } diff --git a/core/src/test/resources/google/registry/tools/1tld.yaml b/core/src/test/resources/google/registry/tools/1tld.yaml new file mode 100644 index 000000000..25c45be38 --- /dev/null +++ b/core/src/test/resources/google/registry/tools/1tld.yaml @@ -0,0 +1,55 @@ +addGracePeriodLength: 432000000 +allowedFullyQualifiedHostNames: [] +allowedRegistrantContactIds: [] +anchorTenantAddGracePeriodLength: 2592000000 +autoRenewGracePeriodLength: 3888000000 +automaticTransferLength: 432000000 +claimsPeriodEnd: "294247-01-10T04:00:54.775Z" +createBillingCost: + currency: "USD" + amount: 25.00 +creationTime: "2022-09-01T00:00:00.000Z" +currency: "USD" +defaultPromoTokens: [] +dnsAPlusAaaaTtl: 900 +dnsDsTtl: null +dnsNsTtl: null +dnsPaused: false +dnsWriters: +- "VoidDnsWriter" +driveFolderId: "driveFolder" +eapFeeSchedule: + "1970-01-01T00:00:00.000Z": + currency: "USD" + amount: 0.00 +escrowEnabled: false +idnTables: [] +invoicingEnabled: false +lordnUsername: null +numDnsPublishLocks: 1 +pendingDeleteLength: 432000000 +premiumListName: "test" +pricingEngineClassName: "google.registry.model.pricing.StaticPremiumListPricingEngine" +redemptionGracePeriodLength: 2592000000 +registryLockOrUnlockBillingCost: + currency: "USD" + amount: 0.00 +renewBillingCostTransitions: + "1970-01-01T00:00:00.000Z": + currency: "USD" + amount: 11.00 +renewGracePeriodLength: 432000000 +reservedListNames: [] +restoreBillingCost: + currency: "USD" + amount: 17.00 +roidSuffix: "1TLD" +serverStatusChangeBillingCost: + currency: "USD" + amount: 19.00 +tldStateTransitions: + "1970-01-01T00:00:00.000Z": "GENERAL_AVAILABILITY" +tldStr: "1tld" +tldType: "REAL" +tldUnicode: "1tld" +transferGracePeriodLength: 432000000 diff --git a/core/src/test/resources/google/registry/tools/badidn.yaml b/core/src/test/resources/google/registry/tools/badidn.yaml new file mode 100644 index 000000000..30bac2e33 --- /dev/null +++ b/core/src/test/resources/google/registry/tools/badidn.yaml @@ -0,0 +1,56 @@ +addGracePeriodLength: 432000000 +allowedFullyQualifiedHostNames: [] +allowedRegistrantContactIds: [] +anchorTenantAddGracePeriodLength: 2592000000 +autoRenewGracePeriodLength: 3888000000 +automaticTransferLength: 432000000 +claimsPeriodEnd: "294247-01-10T04:00:54.775Z" +createBillingCost: + currency: "USD" + amount: 25.00 +creationTime: "2022-09-01T00:00:00.000Z" +currency: "USD" +defaultPromoTokens: [] +dnsAPlusAaaaTtl: 900 +dnsDsTtl: null +dnsNsTtl: null +dnsPaused: false +dnsWriters: +- "VoidDnsWriter" +driveFolderId: "driveFolder" +eapFeeSchedule: + "1970-01-01T00:00:00.000Z": + currency: "USD" + amount: 0.00 +escrowEnabled: false +idnTables: +- "foo" +invoicingEnabled: false +lordnUsername: null +numDnsPublishLocks: 1 +pendingDeleteLength: 432000000 +premiumListName: "test" +pricingEngineClassName: "google.registry.model.pricing.StaticPremiumListPricingEngine" +redemptionGracePeriodLength: 2592000000 +registryLockOrUnlockBillingCost: + currency: "USD" + amount: 0.00 +renewBillingCostTransitions: + "1970-01-01T00:00:00.000Z": + currency: "USD" + amount: 11.00 +renewGracePeriodLength: 432000000 +reservedListNames: [] +restoreBillingCost: + currency: "USD" + amount: 17.00 +roidSuffix: "BADIDN" +serverStatusChangeBillingCost: + currency: "USD" + amount: 19.00 +tldStateTransitions: + "1970-01-01T00:00:00.000Z": "GENERAL_AVAILABILITY" +tldStr: "badidn" +tldType: "REAL" +tldUnicode: "badidn" +transferGracePeriodLength: 432000000 diff --git a/core/src/test/resources/google/registry/tools/badunicode.yaml b/core/src/test/resources/google/registry/tools/badunicode.yaml new file mode 100644 index 000000000..686b9b011 --- /dev/null +++ b/core/src/test/resources/google/registry/tools/badunicode.yaml @@ -0,0 +1,55 @@ +addGracePeriodLength: 432000000 +allowedFullyQualifiedHostNames: [] +allowedRegistrantContactIds: [] +anchorTenantAddGracePeriodLength: 2592000000 +autoRenewGracePeriodLength: 3888000000 +automaticTransferLength: 432000000 +claimsPeriodEnd: "294247-01-10T04:00:54.775Z" +createBillingCost: + currency: "USD" + amount: 25.00 +creationTime: "2022-09-01T00:00:00.000Z" +currency: "USD" +defaultPromoTokens: [] +dnsAPlusAaaaTtl: 900 +dnsDsTtl: null +dnsNsTtl: null +dnsPaused: false +dnsWriters: +- "VoidDnsWriter" +driveFolderId: "driveFolder" +eapFeeSchedule: + "1970-01-01T00:00:00.000Z": + currency: "USD" + amount: 0.00 +escrowEnabled: false +idnTables: [] +invoicingEnabled: false +lordnUsername: null +numDnsPublishLocks: 1 +pendingDeleteLength: 432000000 +premiumListName: "test" +pricingEngineClassName: "google.registry.model.pricing.StaticPremiumListPricingEngine" +redemptionGracePeriodLength: 2592000000 +registryLockOrUnlockBillingCost: + currency: "USD" + amount: 0.00 +renewBillingCostTransitions: + "1970-01-01T00:00:00.000Z": + currency: "USD" + amount: 11.00 +renewGracePeriodLength: 432000000 +reservedListNames: [] +restoreBillingCost: + currency: "USD" + amount: 17.00 +roidSuffix: "TLD" +serverStatusChangeBillingCost: + currency: "USD" + amount: 19.00 +tldStateTransitions: + "1970-01-01T00:00:00.000Z": "GENERAL_AVAILABILITY" +tldStr: "badunicode" +tldType: "REAL" +tldUnicode: "tld" +transferGracePeriodLength: 432000000 diff --git a/core/src/test/resources/google/registry/tools/extrafield.yaml b/core/src/test/resources/google/registry/tools/extrafield.yaml new file mode 100644 index 000000000..af3c54b0a --- /dev/null +++ b/core/src/test/resources/google/registry/tools/extrafield.yaml @@ -0,0 +1,56 @@ +addGracePeriodLength: 432000000 +allowedFullyQualifiedHostNames: [] +allowedRegistrantContactIds: [] +anchorTenantAddGracePeriodLength: 2592000000 +autoRenewGracePeriodLength: 3888000000 +automaticTransferLength: 432000000 +claimsPeriodEnd: "294247-01-10T04:00:54.775Z" +createBillingCost: + currency: "USD" + amount: 25.00 +creationTime: "2022-09-01T00:00:00.000Z" +currency: "USD" +defaultPromoTokens: [] +dnsAPlusAaaaTtl: 900 +dnsDsTtl: null +dnsNsTtl: null +dnsPaused: false +dnsWriters: +- "VoidDnsWriter" +driveFolderId: "driveFolder" +eapFeeSchedule: + "1970-01-01T00:00:00.000Z": + currency: "USD" + amount: 0.00 +escrowEnabled: false +idnTables: [] +invoicingEnabled: false +lordnUsername: null +numDnsPublishLocks: 1 +pendingDeleteLength: 432000000 +premiumListName: "test" +pricingEngineClassName: "google.registry.model.pricing.StaticPremiumListPricingEngine" +redemptionGracePeriodLength: 2592000000 +registryLockOrUnlockBillingCost: + currency: "USD" + amount: 0.00 +renewBillingCostTransitions: + "1970-01-01T00:00:00.000Z": + currency: "USD" + amount: 11.00 +renewGracePeriodLength: 432000000 +reservedListNames: [] +restoreBillingCost: + currency: "USD" + amount: 17.00 +roidSuffix: "EXTRA" +serverStatusChangeBillingCost: + currency: "USD" + amount: 19.00 +tldStateTransitions: + "1970-01-01T00:00:00.000Z": "GENERAL_AVAILABILITY" +tldStr: "extrafield" +tldType: "REAL" +tldUnicode: "extrafield" +transferGracePeriodLength: 432000000 +extraField: "hello" diff --git a/core/src/test/resources/google/registry/tools/missingnullablefields.yaml b/core/src/test/resources/google/registry/tools/missingnullablefields.yaml new file mode 100644 index 000000000..7425c6c72 --- /dev/null +++ b/core/src/test/resources/google/registry/tools/missingnullablefields.yaml @@ -0,0 +1,50 @@ +addGracePeriodLength: 432000000 +allowedFullyQualifiedHostNames: [] +allowedRegistrantContactIds: [] +anchorTenantAddGracePeriodLength: 2592000000 +automaticTransferLength: 432000000 +autoRenewGracePeriodLength: 3888000000 +claimsPeriodEnd: "294247-01-10T04:00:54.775Z" +createBillingCost: + currency: "USD" + amount: 25.00 +creationTime: "2022-09-01T00:00:00.000Z" +defaultPromoTokens: [] +dnsAPlusAaaaTtl: null +dnsDsTtl: null +dnsNsTtl: null +dnsPaused: false +dnsWriters: +- "VoidDnsWriter" +driveFolderId: "driveFolder" +eapFeeSchedule: + "1970-01-01T00:00:00.000Z": + currency: "USD" + amount: 0.00 +escrowEnabled: false +idnTables: [] +invoicingEnabled: false +lordnUsername: null +pendingDeleteLength: 432000000 +pricingEngineClassName: "google.registry.model.pricing.StaticPremiumListPricingEngine" +redemptionGracePeriodLength: 2592000000 +registryLockOrUnlockBillingCost: + currency: "USD" + amount: 0.00 +renewBillingCostTransitions: + "1970-01-01T00:00:00.000Z": + currency: "USD" + amount: 11.00 +renewGracePeriodLength: 432000000 +reservedListNames: [] +restoreBillingCost: + currency: "USD" + amount: 17.00 +roidSuffix: "NONULLS" +serverStatusChangeBillingCost: + currency: "USD" + amount: 19.00 +tldStr: "missingnullablefields" +tldType: "REAL" +tldUnicode: "missingnullablefields" +transferGracePeriodLength: 432000000 diff --git a/core/src/test/resources/google/registry/tools/nullablefieldsallnull.yaml b/core/src/test/resources/google/registry/tools/nullablefieldsallnull.yaml new file mode 100644 index 000000000..3bb75a8d1 --- /dev/null +++ b/core/src/test/resources/google/registry/tools/nullablefieldsallnull.yaml @@ -0,0 +1,55 @@ +tldStr: "nullablefieldsallnull" +roidSuffix: "NULLS" +pricingEngineClassName: null +dnsWriters: +- "VoidDnsWriter" +numDnsPublishLocks: 1 +dnsAPlusAaaaTtl: null +dnsNsTtl: null +dnsDsTtl: null +tldUnicode: "nullablefieldsallnull" +driveFolderId: null +tldType: "REAL" +invoicingEnabled: false +tldStateTransitions: + "1970-01-01T00:00:00.000Z": "GENERAL_AVAILABILITY" +creationTime: "2022-09-01T00:00:00.000Z" +reservedListNames: null +premiumListName: null +escrowEnabled: false +dnsPaused: false +addGracePeriodLength: 432000000 +anchorTenantAddGracePeriodLength: 2592000000 +autoRenewGracePeriodLength: 3888000000 +redemptionGracePeriodLength: 2592000000 +renewGracePeriodLength: 432000000 +transferGracePeriodLength: 432000000 +automaticTransferLength: 432000000 +pendingDeleteLength: 432000000 +currency: "USD" +createBillingCost: + currency: "USD" + amount: 25.00 +restoreBillingCost: + currency: "USD" + amount: 17.00 +serverStatusChangeBillingCost: + currency: "USD" + amount: 19.00 +registryLockOrUnlockBillingCost: + currency: "USD" + amount: 0.00 +renewBillingCostTransitions: + "1970-01-01T00:00:00.000Z": + currency: "USD" + amount: 11.00 +lordnUsername: null +claimsPeriodEnd: "294247-01-10T04:00:54.775Z" +allowedRegistrantContactIds: null +allowedFullyQualifiedHostNames: null +defaultPromoTokens: null +idnTables: null +eapFeeSchedule: + "1970-01-01T00:00:00.000Z": + currency: "USD" + amount: 0.00 diff --git a/core/src/test/resources/google/registry/tools/outoforderfields.yaml b/core/src/test/resources/google/registry/tools/outoforderfields.yaml new file mode 100644 index 000000000..c110d0500 --- /dev/null +++ b/core/src/test/resources/google/registry/tools/outoforderfields.yaml @@ -0,0 +1,55 @@ +pricingEngineClassName: "google.registry.model.pricing.StaticPremiumListPricingEngine" +numDnsPublishLocks: 1 +creationTime: "2022-09-01T00:00:00.000Z" +reservedListNames: [] +dnsPaused: false +tldType: "REAL" +escrowEnabled: false +anchorTenantAddGracePeriodLength: 2592000000 +dnsNsTtl: null +tldStr: "outoforderfields" +roidSuffix: "TLD" +dnsWriters: +- "VoidDnsWriter" +dnsAPlusAaaaTtl: 900 +dnsDsTtl: null +tldUnicode: "outoforderfields" +driveFolderId: "driveFolder" +invoicingEnabled: false +tldStateTransitions: + "1970-01-01T00:00:00.000Z": "GENERAL_AVAILABILITY" +premiumListName: "test" +addGracePeriodLength: 432000000 +autoRenewGracePeriodLength: 3888000000 +redemptionGracePeriodLength: 2592000000 +renewGracePeriodLength: 432000000 +transferGracePeriodLength: 432000000 +automaticTransferLength: 432000000 +pendingDeleteLength: 432000000 +currency: "USD" +createBillingCost: + currency: "USD" + amount: 25.00 +restoreBillingCost: + currency: "USD" + amount: 17.00 +serverStatusChangeBillingCost: + currency: "USD" + amount: 19.00 +registryLockOrUnlockBillingCost: + currency: "USD" + amount: 0.00 +renewBillingCostTransitions: + "1970-01-01T00:00:00.000Z": + currency: "USD" + amount: 11.00 +lordnUsername: null +claimsPeriodEnd: "294247-01-10T04:00:54.775Z" +allowedRegistrantContactIds: [] +allowedFullyQualifiedHostNames: [] +defaultPromoTokens: [] +idnTables: [] +eapFeeSchedule: + "1970-01-01T00:00:00.000Z": + currency: "USD" + amount: 0.00 diff --git a/core/src/test/resources/google/registry/tools/tld.yaml b/core/src/test/resources/google/registry/tools/tld.yaml index 1dd5a2ad5..62363325b 100644 --- a/core/src/test/resources/google/registry/tools/tld.yaml +++ b/core/src/test/resources/google/registry/tools/tld.yaml @@ -7,17 +7,17 @@ automaticTransferLength: 432000000 claimsPeriodEnd: "294247-01-10T04:00:54.775Z" createBillingCost: currency: "USD" - amount: 13.00 + amount: 25.00 creationTime: "2022-09-01T00:00:00.000Z" currency: "USD" defaultPromoTokens: [] -dnsAPlusAaaaTtl: null +dnsAPlusAaaaTtl: 900 dnsDsTtl: null dnsNsTtl: null dnsPaused: false dnsWriters: - "VoidDnsWriter" -driveFolderId: null +driveFolderId: "driveFolder" eapFeeSchedule: "1970-01-01T00:00:00.000Z": currency: "USD" @@ -28,7 +28,7 @@ invoicingEnabled: false lordnUsername: null numDnsPublishLocks: 1 pendingDeleteLength: 432000000 -premiumListName: "xn--q9jyb4c" +premiumListName: "test" pricingEngineClassName: "google.registry.model.pricing.StaticPremiumListPricingEngine" redemptionGracePeriodLength: 2592000000 registryLockOrUnlockBillingCost: @@ -43,13 +43,13 @@ reservedListNames: [] restoreBillingCost: currency: "USD" amount: 17.00 -roidSuffix: "Q9JYB4C" +roidSuffix: "TLD" serverStatusChangeBillingCost: currency: "USD" amount: 19.00 tldStateTransitions: "1970-01-01T00:00:00.000Z": "GENERAL_AVAILABILITY" -tldStr: "xn--q9jyb4c" +tldStr: "tld" tldType: "REAL" -tldUnicode: "みんな" -transferGracePeriodLength: 432000000 \ No newline at end of file +tldUnicode: "tld" +transferGracePeriodLength: 432000000 diff --git a/core/src/test/resources/google/registry/tools/wildcard.yaml b/core/src/test/resources/google/registry/tools/wildcard.yaml new file mode 100644 index 000000000..854ad0800 --- /dev/null +++ b/core/src/test/resources/google/registry/tools/wildcard.yaml @@ -0,0 +1,55 @@ +addGracePeriodLength: 432000000 +allowedFullyQualifiedHostNames: [] +allowedRegistrantContactIds: [] +anchorTenantAddGracePeriodLength: 2592000000 +autoRenewGracePeriodLength: 3888000000 +automaticTransferLength: 432000000 +claimsPeriodEnd: "294247-01-10T04:00:54.775Z" +createBillingCost: + currency: "USD" + amount: 25.00 +creationTime: "2022-09-01T00:00:00.000Z" +currency: "USD" +defaultPromoTokens: [] +dnsAPlusAaaaTtl: 900 +dnsDsTtl: null +dnsNsTtl: null +dnsPaused: false +dnsWriters: +- "VoidDnsWriter" +driveFolderId: "driveFolder" +eapFeeSchedule: + "1970-01-01T00:00:00.000Z": + currency: "USD" + amount: 0.00 +escrowEnabled: false +idnTables: [] +invoicingEnabled: false +lordnUsername: null +numDnsPublishLocks: 1 +pendingDeleteLength: 432000000 +premiumListName: "test" +pricingEngineClassName: "google.registry.model.pricing.StaticPremiumListPricingEngine" +redemptionGracePeriodLength: 2592000000 +registryLockOrUnlockBillingCost: + currency: "USD" + amount: 0.00 +renewBillingCostTransitions: + "1970-01-01T00:00:00.000Z": + currency: "USD" + amount: 11.00 +renewGracePeriodLength: 432000000 +reservedListNames: [] +restoreBillingCost: + currency: "USD" + amount: 17.00 +roidSuffix: %ROIDSUFFIX% +serverStatusChangeBillingCost: + currency: "USD" + amount: 19.00 +tldStateTransitions: + "1970-01-01T00:00:00.000Z": "GENERAL_AVAILABILITY" +tldStr: %TLDSTR% +tldType: "REAL" +tldUnicode: %TLDUNICODE% +transferGracePeriodLength: 432000000 diff --git a/core/src/test/resources/google/registry/tools/wrongcurrency.yaml b/core/src/test/resources/google/registry/tools/wrongcurrency.yaml new file mode 100644 index 000000000..02c1a1fc1 --- /dev/null +++ b/core/src/test/resources/google/registry/tools/wrongcurrency.yaml @@ -0,0 +1,55 @@ +tldStr: "wrongcurrency" +roidSuffix: "WRONGCUR" +pricingEngineClassName: "google.registry.model.pricing.StaticPremiumListPricingEngine" +dnsWriters: +- "VoidDnsWriter" +numDnsPublishLocks: 1 +dnsAPlusAaaaTtl: 900 +dnsNsTtl: null +dnsDsTtl: null +tldUnicode: "wrongcurrency" +driveFolderId: "driveFolder" +tldType: "REAL" +invoicingEnabled: false +tldStateTransitions: + "1970-01-01T00:00:00.000Z": "GENERAL_AVAILABILITY" +creationTime: "2022-09-01T00:00:00.000Z" +reservedListNames: [] +premiumListName: "test" +escrowEnabled: false +dnsPaused: false +addGracePeriodLength: 432000000 +anchorTenantAddGracePeriodLength: 2592000000 +autoRenewGracePeriodLength: 3888000000 +redemptionGracePeriodLength: 2592000000 +renewGracePeriodLength: 432000000 +transferGracePeriodLength: 432000000 +automaticTransferLength: 432000000 +pendingDeleteLength: 432000000 +currency: "USD" +createBillingCost: + currency: "USD" + amount: 25.00 +restoreBillingCost: + currency: %RESTORECURRENCY% + amount: 70.00 +serverStatusChangeBillingCost: + currency: "USD" + amount: 19.00 +registryLockOrUnlockBillingCost: + currency: "USD" + amount: 0.00 +renewBillingCostTransitions: + "1970-01-01T00:00:00.000Z": + currency: %RENEWCURRENCY% + amount: 11.00 +lordnUsername: null +claimsPeriodEnd: "294247-01-10T04:00:54.775Z" +allowedRegistrantContactIds: [] +allowedFullyQualifiedHostNames: [] +defaultPromoTokens: [] +idnTables: [] +eapFeeSchedule: + "1970-01-01T00:00:00.000Z": + currency: "USD" + amount: 0.00