mirror of
https://github.com/google/nomulus.git
synced 2025-07-09 20:53:26 +02:00
Add initial support to write/update reserved lists to Cloud SQL (#388)
* Add initial support to write reserved list to Cloud SQL * Add support to update reserved list in Cloud SQL * Fix wrong check when override is enabled in create command * Add sql dependent tests to the suite * Address comment * Make invocation of super.execute more readable * Add test to check upper case and non-puny code label * Move ReservedListDao related classes to schema package * Simplify a function name
This commit is contained in:
parent
f301314d97
commit
f76030f7f0
13 changed files with 573 additions and 12 deletions
|
@ -121,7 +121,7 @@ public abstract class BaseDomainLabelList<T extends Comparable<?>, R extends Dom
|
||||||
* (sans comment) and the comment (in that order). If the line was blank or empty, then this
|
* (sans comment) and the comment (in that order). If the line was blank or empty, then this
|
||||||
* method returns an empty list.
|
* method returns an empty list.
|
||||||
*/
|
*/
|
||||||
protected static List<String> splitOnComment(String line) {
|
public static List<String> splitOnComment(String line) {
|
||||||
String comment = "";
|
String comment = "";
|
||||||
int index = line.indexOf('#');
|
int index = line.indexOf('#');
|
||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
|
|
|
@ -14,13 +14,20 @@
|
||||||
|
|
||||||
package google.registry.schema.tld;
|
package google.registry.schema.tld;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
import static com.google.common.base.Preconditions.checkState;
|
import static com.google.common.base.Preconditions.checkState;
|
||||||
|
import static com.google.common.collect.ImmutableList.sortedCopyOf;
|
||||||
|
import static com.google.common.collect.ImmutableList.toImmutableList;
|
||||||
|
import static google.registry.util.DomainNameUtils.canonicalizeDomainName;
|
||||||
|
|
||||||
|
import com.google.common.base.Joiner;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import google.registry.model.CreateAutoTimestamp;
|
import google.registry.model.CreateAutoTimestamp;
|
||||||
import google.registry.model.ImmutableObject;
|
import google.registry.model.ImmutableObject;
|
||||||
import google.registry.model.registry.label.ReservationType;
|
import google.registry.model.registry.label.ReservationType;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.stream.Stream;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.persistence.CollectionTable;
|
import javax.persistence.CollectionTable;
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
|
@ -114,6 +121,22 @@ public class ReservedList extends ImmutableObject {
|
||||||
/** Constructs a {@link ReservedList} object. */
|
/** Constructs a {@link ReservedList} object. */
|
||||||
public static ReservedList create(
|
public static ReservedList create(
|
||||||
String name, Boolean shouldPublish, Map<String, ReservedEntry> labelsToReservations) {
|
String name, Boolean shouldPublish, Map<String, ReservedEntry> labelsToReservations) {
|
||||||
|
ImmutableList<String> invalidLabels =
|
||||||
|
labelsToReservations.entrySet().parallelStream()
|
||||||
|
.flatMap(
|
||||||
|
entry -> {
|
||||||
|
String label = entry.getKey();
|
||||||
|
if (label.equals(canonicalizeDomainName(label))) {
|
||||||
|
return Stream.empty();
|
||||||
|
} else {
|
||||||
|
return Stream.of(label);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect(toImmutableList());
|
||||||
|
checkArgument(
|
||||||
|
invalidLabels.isEmpty(),
|
||||||
|
"Label(s) [%s] must be in puny-coded, lower-case form",
|
||||||
|
Joiner.on(",").join(sortedCopyOf(invalidLabels)));
|
||||||
return new ReservedList(name, shouldPublish, labelsToReservations);
|
return new ReservedList(name, shouldPublish, labelsToReservations);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
// 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 static google.registry.model.transaction.TransactionManagerFactory.jpaTm;
|
||||||
|
|
||||||
|
/** Data access object class for {@link ReservedList} */
|
||||||
|
public class ReservedListDao {
|
||||||
|
|
||||||
|
/** Persist a new reserved list to Cloud SQL. */
|
||||||
|
public static void save(ReservedList reservedList) {
|
||||||
|
jpaTm().transact(() -> jpaTm().getEntityManager().persist(reservedList));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the reserved list of the given name exists.
|
||||||
|
*
|
||||||
|
* <p>This means that at least one reserved list revision must exist for the given name.
|
||||||
|
*/
|
||||||
|
public static boolean checkExists(String reservedListName) {
|
||||||
|
return jpaTm()
|
||||||
|
.transact(
|
||||||
|
() ->
|
||||||
|
jpaTm()
|
||||||
|
.getEntityManager()
|
||||||
|
.createQuery("SELECT 1 FROM ReservedList WHERE name = :name", Integer.class)
|
||||||
|
.setParameter("name", reservedListName)
|
||||||
|
.setMaxResults(1)
|
||||||
|
.getResultList()
|
||||||
|
.size()
|
||||||
|
> 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ReservedListDao() {}
|
||||||
|
}
|
|
@ -14,9 +14,23 @@
|
||||||
|
|
||||||
package google.registry.tools;
|
package google.registry.tools;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
|
import static google.registry.model.registry.label.BaseDomainLabelList.splitOnComment;
|
||||||
|
import static google.registry.util.DomainNameUtils.canonicalizeDomainName;
|
||||||
|
|
||||||
import com.beust.jcommander.Parameter;
|
import com.beust.jcommander.Parameter;
|
||||||
|
import com.google.common.base.Splitter;
|
||||||
|
import com.google.common.collect.HashMultiset;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
import com.google.common.collect.Multiset;
|
||||||
|
import com.google.common.flogger.FluentLogger;
|
||||||
|
import google.registry.model.registry.label.ReservationType;
|
||||||
|
import google.registry.schema.tld.ReservedList.ReservedEntry;
|
||||||
import google.registry.tools.params.PathParameter;
|
import google.registry.tools.params.PathParameter;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25,6 +39,8 @@ import javax.annotation.Nullable;
|
||||||
*/
|
*/
|
||||||
public abstract class CreateOrUpdateReservedListCommand extends MutatingCommand {
|
public abstract class CreateOrUpdateReservedListCommand extends MutatingCommand {
|
||||||
|
|
||||||
|
static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
@Parameter(
|
@Parameter(
|
||||||
names = {"-n", "--name"},
|
names = {"-n", "--name"},
|
||||||
|
@ -45,4 +61,81 @@ public abstract class CreateOrUpdateReservedListCommand extends MutatingCommand
|
||||||
"Whether the list is published to the concatenated list on Drive (defaults to true).",
|
"Whether the list is published to the concatenated list on Drive (defaults to true).",
|
||||||
arity = 1)
|
arity = 1)
|
||||||
Boolean shouldPublish;
|
Boolean shouldPublish;
|
||||||
|
|
||||||
|
@Parameter(
|
||||||
|
names = {"--also_cloud_sql"},
|
||||||
|
description =
|
||||||
|
"Persist reserved list to Cloud SQL in addition to Datastore; defaults to false.")
|
||||||
|
boolean alsoCloudSql;
|
||||||
|
|
||||||
|
google.registry.schema.tld.ReservedList cloudSqlReservedList;
|
||||||
|
|
||||||
|
abstract void saveToCloudSql();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String execute() throws Exception {
|
||||||
|
// Save the list to Datastore and output its response.
|
||||||
|
String output = super.execute();
|
||||||
|
logger.atInfo().log(output);
|
||||||
|
|
||||||
|
String cloudSqlMessage;
|
||||||
|
if (alsoCloudSql) {
|
||||||
|
cloudSqlMessage =
|
||||||
|
String.format(
|
||||||
|
"Saved reserved list %s with %d entries",
|
||||||
|
name, cloudSqlReservedList.getLabelsToReservations().size());
|
||||||
|
try {
|
||||||
|
logger.atInfo().log("Saving reserved list to Cloud SQL for TLD %s", name);
|
||||||
|
saveToCloudSql();
|
||||||
|
logger.atInfo().log(cloudSqlMessage);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
cloudSqlMessage =
|
||||||
|
"Unexpected error saving reserved list to Cloud SQL from nomulus tool command";
|
||||||
|
logger.atSevere().withCause(e).log(cloudSqlMessage);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cloudSqlMessage = "Persisting reserved list to Cloud SQL is not enabled";
|
||||||
|
}
|
||||||
|
return cloudSqlMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Turns the list CSV data into a map of labels to {@link ReservedEntry}. */
|
||||||
|
static ImmutableMap<String, ReservedEntry> parseToReservationsByLabels(Iterable<String> lines) {
|
||||||
|
Map<String, ReservedEntry> labelsToEntries = Maps.newHashMap();
|
||||||
|
Multiset<String> duplicateLabels = HashMultiset.create();
|
||||||
|
for (String originalLine : lines) {
|
||||||
|
List<String> lineAndComment = splitOnComment(originalLine);
|
||||||
|
if (lineAndComment.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
String line = lineAndComment.get(0);
|
||||||
|
String comment = lineAndComment.get(1);
|
||||||
|
List<String> parts = Splitter.on(',').trimResults().splitToList(line);
|
||||||
|
checkArgument(
|
||||||
|
parts.size() == 2 || parts.size() == 3,
|
||||||
|
"Could not parse line in reserved list: %s",
|
||||||
|
originalLine);
|
||||||
|
String label = parts.get(0);
|
||||||
|
checkArgument(
|
||||||
|
label.equals(canonicalizeDomainName(label)),
|
||||||
|
"Label '%s' must be in puny-coded, lower-case form",
|
||||||
|
label);
|
||||||
|
ReservationType reservationType = ReservationType.valueOf(parts.get(1));
|
||||||
|
ReservedEntry reservedEntry = ReservedEntry.create(reservationType, comment);
|
||||||
|
// 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)) {
|
||||||
|
duplicateLabels.add(label, duplicateLabels.contains(label) ? 1 : 2);
|
||||||
|
} else {
|
||||||
|
labelsToEntries.put(label, reservedEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!duplicateLabels.isEmpty()) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
String.format(
|
||||||
|
"Reserved list cannot contain duplicate labels. Dupes (with counts) were: %s",
|
||||||
|
duplicateLabels));
|
||||||
|
}
|
||||||
|
return ImmutableMap.copyOf(labelsToEntries);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ package google.registry.tools;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
import static google.registry.model.registry.Registries.assertTldExists;
|
import static google.registry.model.registry.Registries.assertTldExists;
|
||||||
|
import static google.registry.model.transaction.TransactionManagerFactory.jpaTm;
|
||||||
import static google.registry.util.ListNamingUtils.convertFilePathToName;
|
import static google.registry.util.ListNamingUtils.convertFilePathToName;
|
||||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
import static org.joda.time.DateTimeZone.UTC;
|
import static org.joda.time.DateTimeZone.UTC;
|
||||||
|
@ -26,6 +27,7 @@ import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.base.Splitter;
|
import com.google.common.base.Splitter;
|
||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
import google.registry.model.registry.label.ReservedList;
|
import google.registry.model.registry.label.ReservedList;
|
||||||
|
import google.registry.schema.tld.ReservedListDao;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
|
@ -54,15 +56,35 @@ final class CreateReservedListCommand extends CreateOrUpdateReservedListCommand
|
||||||
validateListName(name);
|
validateListName(name);
|
||||||
}
|
}
|
||||||
DateTime now = DateTime.now(UTC);
|
DateTime now = DateTime.now(UTC);
|
||||||
|
List<String> allLines = Files.readAllLines(input, UTF_8);
|
||||||
|
boolean shouldPublish = this.shouldPublish == null || this.shouldPublish;
|
||||||
ReservedList reservedList =
|
ReservedList reservedList =
|
||||||
new ReservedList.Builder()
|
new ReservedList.Builder()
|
||||||
.setName(name)
|
.setName(name)
|
||||||
.setReservedListMapFromLines(Files.readAllLines(input, UTF_8))
|
.setReservedListMapFromLines(allLines)
|
||||||
.setShouldPublish(shouldPublish == null || shouldPublish)
|
.setShouldPublish(shouldPublish)
|
||||||
.setCreationTime(now)
|
.setCreationTime(now)
|
||||||
.setLastUpdateTime(now)
|
.setLastUpdateTime(now)
|
||||||
.build();
|
.build();
|
||||||
stageEntityChange(null, reservedList);
|
stageEntityChange(null, reservedList);
|
||||||
|
if (alsoCloudSql) {
|
||||||
|
cloudSqlReservedList =
|
||||||
|
google.registry.schema.tld.ReservedList.create(
|
||||||
|
name, shouldPublish, parseToReservationsByLabels(allLines));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void saveToCloudSql() {
|
||||||
|
jpaTm()
|
||||||
|
.transact(
|
||||||
|
() -> {
|
||||||
|
checkArgument(
|
||||||
|
!ReservedListDao.checkExists(cloudSqlReservedList.getName()),
|
||||||
|
"A reserved list of this name already exists: %s.",
|
||||||
|
cloudSqlReservedList.getName());
|
||||||
|
ReservedListDao.save(cloudSqlReservedList);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void validateListName(String name) {
|
private static void validateListName(String name) {
|
||||||
|
|
|
@ -15,14 +15,17 @@
|
||||||
package google.registry.tools;
|
package google.registry.tools;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
|
import static google.registry.model.transaction.TransactionManagerFactory.jpaTm;
|
||||||
import static google.registry.util.ListNamingUtils.convertFilePathToName;
|
import static google.registry.util.ListNamingUtils.convertFilePathToName;
|
||||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
|
||||||
import com.beust.jcommander.Parameters;
|
import com.beust.jcommander.Parameters;
|
||||||
import com.google.common.base.Strings;
|
import com.google.common.base.Strings;
|
||||||
import google.registry.model.registry.label.ReservedList;
|
import google.registry.model.registry.label.ReservedList;
|
||||||
|
import google.registry.schema.tld.ReservedListDao;
|
||||||
import google.registry.util.SystemClock;
|
import google.registry.util.SystemClock;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
/** Command to safely update {@link ReservedList} on Datastore. */
|
/** Command to safely update {@link ReservedList} on Datastore. */
|
||||||
|
@ -32,18 +35,38 @@ final class UpdateReservedListCommand extends CreateOrUpdateReservedListCommand
|
||||||
@Override
|
@Override
|
||||||
protected void init() throws Exception {
|
protected void init() throws Exception {
|
||||||
name = Strings.isNullOrEmpty(name) ? convertFilePathToName(input) : name;
|
name = Strings.isNullOrEmpty(name) ? convertFilePathToName(input) : name;
|
||||||
|
// TODO(shicong): Read existing entry from Cloud SQL
|
||||||
Optional<ReservedList> existing = ReservedList.get(name);
|
Optional<ReservedList> existing = ReservedList.get(name);
|
||||||
checkArgument(
|
checkArgument(
|
||||||
existing.isPresent(), "Could not update reserved list %s because it doesn't exist.", name);
|
existing.isPresent(), "Could not update reserved list %s because it doesn't exist.", name);
|
||||||
|
boolean shouldPublish =
|
||||||
|
this.shouldPublish == null ? existing.get().getShouldPublish() : this.shouldPublish;
|
||||||
|
List<String> allLines = Files.readAllLines(input, UTF_8);
|
||||||
ReservedList.Builder updated =
|
ReservedList.Builder updated =
|
||||||
existing
|
existing
|
||||||
.get()
|
.get()
|
||||||
.asBuilder()
|
.asBuilder()
|
||||||
.setReservedListMapFromLines(Files.readAllLines(input, UTF_8))
|
.setReservedListMapFromLines(allLines)
|
||||||
.setLastUpdateTime(new SystemClock().nowUtc());
|
.setLastUpdateTime(new SystemClock().nowUtc())
|
||||||
if (shouldPublish != null) {
|
.setShouldPublish(shouldPublish);
|
||||||
updated.setShouldPublish(shouldPublish);
|
|
||||||
}
|
|
||||||
stageEntityChange(existing.get(), updated.build());
|
stageEntityChange(existing.get(), updated.build());
|
||||||
|
if (alsoCloudSql) {
|
||||||
|
cloudSqlReservedList =
|
||||||
|
google.registry.schema.tld.ReservedList.create(
|
||||||
|
name, shouldPublish, parseToReservationsByLabels(allLines));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
void saveToCloudSql() {
|
||||||
|
jpaTm()
|
||||||
|
.transact(
|
||||||
|
() -> {
|
||||||
|
checkArgument(
|
||||||
|
ReservedListDao.checkExists(cloudSqlReservedList.getName()),
|
||||||
|
"A reserved list of this name doesn't exist: %s.",
|
||||||
|
cloudSqlReservedList.getName());
|
||||||
|
ReservedListDao.save(cloudSqlReservedList);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,10 @@ import google.registry.persistence.UpdateAutoTimestampConverterTest;
|
||||||
import google.registry.persistence.ZonedDateTimeConverterTest;
|
import google.registry.persistence.ZonedDateTimeConverterTest;
|
||||||
import google.registry.schema.cursor.CursorDaoTest;
|
import google.registry.schema.cursor.CursorDaoTest;
|
||||||
import google.registry.schema.tld.PremiumListDaoTest;
|
import google.registry.schema.tld.PremiumListDaoTest;
|
||||||
|
import google.registry.schema.tld.ReservedListDaoTest;
|
||||||
import google.registry.schema.tmch.ClaimsListDaoTest;
|
import google.registry.schema.tmch.ClaimsListDaoTest;
|
||||||
|
import google.registry.tools.CreateReservedListCommandTest;
|
||||||
|
import google.registry.tools.UpdateReservedListCommandTest;
|
||||||
import google.registry.ui.server.registrar.RegistryLockGetActionTest;
|
import google.registry.ui.server.registrar.RegistryLockGetActionTest;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.junit.runners.Suite;
|
import org.junit.runners.Suite;
|
||||||
|
@ -47,6 +50,7 @@ import org.junit.runners.Suite.SuiteClasses;
|
||||||
BloomFilterConverterTest.class,
|
BloomFilterConverterTest.class,
|
||||||
ClaimsListDaoTest.class,
|
ClaimsListDaoTest.class,
|
||||||
CreateAutoTimestampConverterTest.class,
|
CreateAutoTimestampConverterTest.class,
|
||||||
|
CreateReservedListCommandTest.class,
|
||||||
CurrencyUnitConverterTest.class,
|
CurrencyUnitConverterTest.class,
|
||||||
CursorDaoTest.class,
|
CursorDaoTest.class,
|
||||||
DateTimeConverterTest.class,
|
DateTimeConverterTest.class,
|
||||||
|
@ -56,7 +60,9 @@ import org.junit.runners.Suite.SuiteClasses;
|
||||||
PremiumListDaoTest.class,
|
PremiumListDaoTest.class,
|
||||||
RegistryLockDaoTest.class,
|
RegistryLockDaoTest.class,
|
||||||
RegistryLockGetActionTest.class,
|
RegistryLockGetActionTest.class,
|
||||||
|
ReservedListDaoTest.class,
|
||||||
UpdateAutoTimestampConverterTest.class,
|
UpdateAutoTimestampConverterTest.class,
|
||||||
|
UpdateReservedListCommandTest.class,
|
||||||
ZonedDateTimeConverterTest.class
|
ZonedDateTimeConverterTest.class
|
||||||
})
|
})
|
||||||
public class SqlIntegrationTestSuite {}
|
public class SqlIntegrationTestSuite {}
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
// 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 static com.google.common.truth.Truth.assertThat;
|
||||||
|
import static google.registry.model.transaction.TransactionManagerFactory.jpaTm;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import google.registry.model.registry.label.ReservationType;
|
||||||
|
import google.registry.model.transaction.JpaTransactionManagerRule;
|
||||||
|
import google.registry.schema.tld.ReservedList.ReservedEntry;
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.junit.runners.JUnit4;
|
||||||
|
|
||||||
|
/** Unit tests for {@link ReservedListDao}. */
|
||||||
|
@RunWith(JUnit4.class)
|
||||||
|
public class ReservedListDaoTest {
|
||||||
|
@Rule
|
||||||
|
public final JpaTransactionManagerRule jpaTmRule =
|
||||||
|
new JpaTransactionManagerRule.Builder().build();
|
||||||
|
|
||||||
|
private static final ImmutableMap<String, ReservedEntry> TEST_RESERVATIONS =
|
||||||
|
ImmutableMap.of(
|
||||||
|
"food",
|
||||||
|
ReservedEntry.create(ReservationType.RESERVED_FOR_SPECIFIC_USE, null),
|
||||||
|
"music",
|
||||||
|
ReservedEntry.create(ReservationType.FULLY_BLOCKED, "fully blocked"));
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void save_worksSuccessfully() {
|
||||||
|
ReservedList reservedList = ReservedList.create("testname", false, TEST_RESERVATIONS);
|
||||||
|
ReservedListDao.save(reservedList);
|
||||||
|
jpaTm()
|
||||||
|
.transact(
|
||||||
|
() -> {
|
||||||
|
ReservedList persistedList =
|
||||||
|
jpaTm()
|
||||||
|
.getEntityManager()
|
||||||
|
.createQuery("FROM ReservedList WHERE name = :name", ReservedList.class)
|
||||||
|
.setParameter("name", "testname")
|
||||||
|
.getSingleResult();
|
||||||
|
assertThat(persistedList.getLabelsToReservations())
|
||||||
|
.containsExactlyEntriesIn(TEST_RESERVATIONS);
|
||||||
|
assertThat(persistedList.getCreationTimestamp())
|
||||||
|
.isEqualTo(jpaTmRule.getTxnClock().nowUtc());
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void checkExists_worksSuccessfully() {
|
||||||
|
assertThat(ReservedListDao.checkExists("testlist")).isFalse();
|
||||||
|
ReservedListDao.save(ReservedList.create("testlist", false, TEST_RESERVATIONS));
|
||||||
|
assertThat(ReservedListDao.checkExists("testlist")).isTrue();
|
||||||
|
}
|
||||||
|
}
|
|
@ -15,6 +15,8 @@
|
||||||
package google.registry.schema.tld;
|
package google.registry.schema.tld;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
import static google.registry.model.registry.label.ReservationType.FULLY_BLOCKED;
|
||||||
|
import static google.registry.testing.JUnitBackports.assertThrows;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import google.registry.model.registry.label.ReservationType;
|
import google.registry.model.registry.label.ReservationType;
|
||||||
|
@ -50,4 +52,34 @@ public class ReservedListTest {
|
||||||
ReservedEntry.create(
|
ReservedEntry.create(
|
||||||
ReservationType.RESERVED_FOR_ANCHOR_TENANT, "reserved for anchor tenant"));
|
ReservationType.RESERVED_FOR_ANCHOR_TENANT, "reserved for anchor tenant"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void create_throwsExceptionWhenLabelIsNotLowercase() {
|
||||||
|
Exception e =
|
||||||
|
assertThrows(
|
||||||
|
IllegalArgumentException.class,
|
||||||
|
() ->
|
||||||
|
ReservedList.create(
|
||||||
|
"UPPER.tld",
|
||||||
|
true,
|
||||||
|
ImmutableMap.of("UPPER", ReservedEntry.create(FULLY_BLOCKED, ""))));
|
||||||
|
assertThat(e)
|
||||||
|
.hasMessageThat()
|
||||||
|
.contains("Label(s) [UPPER] must be in puny-coded, lower-case form");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void create_labelMustBePunyCoded() {
|
||||||
|
Exception e =
|
||||||
|
assertThrows(
|
||||||
|
IllegalArgumentException.class,
|
||||||
|
() ->
|
||||||
|
ReservedList.create(
|
||||||
|
"lower.みんな",
|
||||||
|
true,
|
||||||
|
ImmutableMap.of("みんな", ReservedEntry.create(FULLY_BLOCKED, ""))));
|
||||||
|
assertThat(e)
|
||||||
|
.hasMessageThat()
|
||||||
|
.contains("Label(s) [みんな] must be in puny-coded, lower-case form");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,126 @@
|
||||||
|
// 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.tools;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
import static google.registry.model.registry.label.ReservationType.ALLOWED_IN_SUNRISE;
|
||||||
|
import static google.registry.model.registry.label.ReservationType.FULLY_BLOCKED;
|
||||||
|
import static google.registry.testing.JUnitBackports.assertThrows;
|
||||||
|
import static google.registry.tools.CreateOrUpdateReservedListCommand.parseToReservationsByLabels;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import google.registry.model.registry.label.ReservationType;
|
||||||
|
import google.registry.schema.tld.ReservedList.ReservedEntry;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.junit.runners.JUnit4;
|
||||||
|
|
||||||
|
/** Unit tests for {@link CreateOrUpdateReservedListCommand}. */
|
||||||
|
@RunWith(JUnit4.class)
|
||||||
|
public class CreateOrUpdateReservedListCommandTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseToReservationsByLabels_worksCorrectly() {
|
||||||
|
assertThat(
|
||||||
|
parseToReservationsByLabels(
|
||||||
|
ImmutableList.of(
|
||||||
|
"reserveddomain,FULLY_BLOCKED",
|
||||||
|
"availableinga,ALLOWED_IN_SUNRISE#allowed_in_sunrise",
|
||||||
|
"fourletterword,FULLY_BLOCKED")))
|
||||||
|
.containsExactly(
|
||||||
|
"reserveddomain",
|
||||||
|
ReservedEntry.create(ReservationType.FULLY_BLOCKED, ""),
|
||||||
|
"availableinga",
|
||||||
|
ReservedEntry.create(ALLOWED_IN_SUNRISE, "allowed_in_sunrise"),
|
||||||
|
"fourletterword",
|
||||||
|
ReservedEntry.create(FULLY_BLOCKED, ""));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseToReservationsByLabels_throwsExceptionForInvalidLabel() {
|
||||||
|
Throwable thrown =
|
||||||
|
assertThrows(
|
||||||
|
IllegalArgumentException.class,
|
||||||
|
() ->
|
||||||
|
parseToReservationsByLabels(
|
||||||
|
ImmutableList.of("reserveddomain,FULLY_BLOCKED", "UPPER,FULLY_BLOCKED")));
|
||||||
|
assertThat(thrown)
|
||||||
|
.hasMessageThat()
|
||||||
|
.isEqualTo("Label 'UPPER' must be in puny-coded, lower-case form");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseToReservationsByLabels_throwsExceptionForNonPunyCodedLabel() {
|
||||||
|
Throwable thrown =
|
||||||
|
assertThrows(
|
||||||
|
IllegalArgumentException.class,
|
||||||
|
() ->
|
||||||
|
parseToReservationsByLabels(
|
||||||
|
ImmutableList.of("reserveddomain,FULLY_BLOCKED", "みんな,FULLY_BLOCKED")));
|
||||||
|
assertThat(thrown)
|
||||||
|
.hasMessageThat()
|
||||||
|
.isEqualTo("Label 'みんな' must be in puny-coded, lower-case form");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseToReservationsByLabels_throwsExceptionForInvalidReservationType() {
|
||||||
|
Throwable thrown =
|
||||||
|
assertThrows(
|
||||||
|
IllegalArgumentException.class,
|
||||||
|
() ->
|
||||||
|
parseToReservationsByLabels(
|
||||||
|
ImmutableList.of(
|
||||||
|
"reserveddomain,FULLY_BLOCKED", "invalidtype,INVALID_RESERVATION_TYPE")));
|
||||||
|
assertThat(thrown)
|
||||||
|
.hasMessageThat()
|
||||||
|
.isEqualTo(
|
||||||
|
"No enum constant"
|
||||||
|
+ " google.registry.model.registry.label.ReservationType.INVALID_RESERVATION_TYPE");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseToReservationsByLabels_throwsExceptionForInvalidLines() {
|
||||||
|
Throwable thrown =
|
||||||
|
assertThrows(
|
||||||
|
IllegalArgumentException.class,
|
||||||
|
() ->
|
||||||
|
parseToReservationsByLabels(
|
||||||
|
ImmutableList.of(
|
||||||
|
"reserveddomain,FULLY_BLOCKED,too,many,parts",
|
||||||
|
"fourletterword,FULLY_BLOCKED")));
|
||||||
|
assertThat(thrown)
|
||||||
|
.hasMessageThat()
|
||||||
|
.isEqualTo(
|
||||||
|
"Could not parse line in reserved list: reserveddomain,FULLY_BLOCKED,too,many,parts");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void parseToReservationsByLabels_throwsExceptionForDuplicateEntries() {
|
||||||
|
Throwable thrown =
|
||||||
|
assertThrows(
|
||||||
|
IllegalStateException.class,
|
||||||
|
() ->
|
||||||
|
parseToReservationsByLabels(
|
||||||
|
ImmutableList.of(
|
||||||
|
"reserveddomain,FULLY_BLOCKED",
|
||||||
|
"fourletterword,FULLY_BLOCKED",
|
||||||
|
"fourletterword,FULLY_BLOCKED")));
|
||||||
|
assertThat(thrown)
|
||||||
|
.hasMessageThat()
|
||||||
|
.isEqualTo(
|
||||||
|
"Reserved list cannot contain duplicate labels. Dupes (with counts) were:"
|
||||||
|
+ " [fourletterword x 2]");
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,15 +14,26 @@
|
||||||
|
|
||||||
package google.registry.tools;
|
package google.registry.tools;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
import static google.registry.model.registry.label.ReservationType.FULLY_BLOCKED;
|
||||||
|
import static google.registry.model.transaction.TransactionManagerFactory.jpaTm;
|
||||||
import static google.registry.testing.JUnitBackports.assertThrows;
|
import static google.registry.testing.JUnitBackports.assertThrows;
|
||||||
import static google.registry.testing.TestDataHelper.loadFile;
|
import static google.registry.testing.TestDataHelper.loadFile;
|
||||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
|
||||||
import com.beust.jcommander.ParameterException;
|
import com.beust.jcommander.ParameterException;
|
||||||
import com.google.common.io.Files;
|
import com.google.common.io.Files;
|
||||||
|
import com.google.common.truth.Truth8;
|
||||||
|
import google.registry.model.registry.label.ReservedList;
|
||||||
|
import google.registry.model.transaction.JpaTransactionManagerRule;
|
||||||
|
import google.registry.schema.tld.ReservedList.ReservedEntry;
|
||||||
|
import google.registry.schema.tld.ReservedListDao;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -33,6 +44,10 @@ import org.junit.Test;
|
||||||
public abstract class CreateOrUpdateReservedListCommandTestCase
|
public abstract class CreateOrUpdateReservedListCommandTestCase
|
||||||
<T extends CreateOrUpdateReservedListCommand> extends CommandTestCase<T> {
|
<T extends CreateOrUpdateReservedListCommand> extends CommandTestCase<T> {
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public final JpaTransactionManagerRule jpaTmRule =
|
||||||
|
new JpaTransactionManagerRule.Builder().build();
|
||||||
|
|
||||||
String reservedTermsPath;
|
String reservedTermsPath;
|
||||||
String invalidReservedTermsPath;
|
String invalidReservedTermsPath;
|
||||||
|
|
||||||
|
@ -64,4 +79,52 @@ public abstract class CreateOrUpdateReservedListCommandTestCase
|
||||||
IllegalArgumentException.class,
|
IllegalArgumentException.class,
|
||||||
() -> runCommandForced("--name=xn--q9jyb4c-blork", "--input=" + invalidReservedTermsPath));
|
() -> runCommandForced("--name=xn--q9jyb4c-blork", "--input=" + invalidReservedTermsPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
google.registry.schema.tld.ReservedList createCloudSqlReservedList(
|
||||||
|
String name, boolean shouldPublish, Map<String, ReservedEntry> labelsToEntries) {
|
||||||
|
return google.registry.schema.tld.ReservedList.create(name, shouldPublish, labelsToEntries);
|
||||||
|
}
|
||||||
|
|
||||||
|
google.registry.schema.tld.ReservedList getCloudSqlReservedList(String name) {
|
||||||
|
return jpaTm()
|
||||||
|
.transact(
|
||||||
|
() -> {
|
||||||
|
EntityManager em = jpaTm().getEntityManager();
|
||||||
|
long revisionId =
|
||||||
|
em.createQuery(
|
||||||
|
"SELECT MAX(rl.revisionId) FROM ReservedList rl WHERE name = :name",
|
||||||
|
Long.class)
|
||||||
|
.setParameter("name", name)
|
||||||
|
.getSingleResult();
|
||||||
|
return em.createQuery(
|
||||||
|
"FROM ReservedList rl LEFT JOIN FETCH rl.labelsToReservations WHERE"
|
||||||
|
+ " rl.revisionId = :revisionId",
|
||||||
|
google.registry.schema.tld.ReservedList.class)
|
||||||
|
.setParameter("revisionId", revisionId)
|
||||||
|
.getSingleResult();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void verifyXnq9jyb4cInCloudSql() {
|
||||||
|
assertThat(ReservedListDao.checkExists("xn--q9jyb4c_common-reserved")).isTrue();
|
||||||
|
google.registry.schema.tld.ReservedList persistedList =
|
||||||
|
getCloudSqlReservedList("xn--q9jyb4c_common-reserved");
|
||||||
|
assertThat(persistedList.getName()).isEqualTo("xn--q9jyb4c_common-reserved");
|
||||||
|
assertThat(persistedList.getShouldPublish()).isTrue();
|
||||||
|
assertThat(persistedList.getCreationTimestamp()).isEqualTo(jpaTmRule.getTxnClock().nowUtc());
|
||||||
|
assertThat(persistedList.getLabelsToReservations())
|
||||||
|
.containsExactly(
|
||||||
|
"baddies",
|
||||||
|
ReservedEntry.create(FULLY_BLOCKED, ""),
|
||||||
|
"ford",
|
||||||
|
ReservedEntry.create(FULLY_BLOCKED, "random comment"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void verifyXnq9jyb4cInDatastore() {
|
||||||
|
Truth8.assertThat(ReservedList.get("xn--q9jyb4c_common-reserved")).isPresent();
|
||||||
|
ReservedList reservedList = ReservedList.get("xn--q9jyb4c_common-reserved").get();
|
||||||
|
assertThat(reservedList.getReservedListEntries()).hasSize(2);
|
||||||
|
Truth8.assertThat(reservedList.getReservationInList("baddies")).hasValue(FULLY_BLOCKED);
|
||||||
|
Truth8.assertThat(reservedList.getReservationInList("ford")).hasValue(FULLY_BLOCKED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,8 +24,11 @@ import static google.registry.testing.JUnitBackports.assertThrows;
|
||||||
import static google.registry.tools.CreateReservedListCommand.INVALID_FORMAT_ERROR_MESSAGE;
|
import static google.registry.tools.CreateReservedListCommand.INVALID_FORMAT_ERROR_MESSAGE;
|
||||||
import static org.joda.time.DateTimeZone.UTC;
|
import static org.joda.time.DateTimeZone.UTC;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
import google.registry.model.registry.Registry;
|
import google.registry.model.registry.Registry;
|
||||||
import google.registry.model.registry.label.ReservedList;
|
import google.registry.model.registry.label.ReservedList;
|
||||||
|
import google.registry.schema.tld.ReservedList.ReservedEntry;
|
||||||
|
import google.registry.schema.tld.ReservedListDao;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -173,6 +176,28 @@ public class CreateReservedListCommandTest extends
|
||||||
runNameTestExpectedFailure("soy_$oy", INVALID_FORMAT_ERROR_MESSAGE);
|
runNameTestExpectedFailure("soy_$oy", INVALID_FORMAT_ERROR_MESSAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSaveToCloudSql_succeeds() throws Exception {
|
||||||
|
runCommandForced(
|
||||||
|
"--name=xn--q9jyb4c_common-reserved", "--input=" + reservedTermsPath, "--also_cloud_sql");
|
||||||
|
verifyXnq9jyb4cInDatastore();
|
||||||
|
verifyXnq9jyb4cInCloudSql();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSaveToCloudSql_noExceptionThrownWhenSaveFail() throws Exception {
|
||||||
|
// Note that, during the dual-write phase, we want to make sure that no exception will be
|
||||||
|
// thrown if saving reserved list to Cloud SQL fails.
|
||||||
|
ReservedListDao.save(
|
||||||
|
createCloudSqlReservedList(
|
||||||
|
"xn--q9jyb4c_common-reserved",
|
||||||
|
true,
|
||||||
|
ImmutableMap.of("testdomain", ReservedEntry.create(FULLY_BLOCKED, ""))));
|
||||||
|
runCommandForced(
|
||||||
|
"--name=xn--q9jyb4c_common-reserved", "--input=" + reservedTermsPath, "--also_cloud_sql");
|
||||||
|
verifyXnq9jyb4cInDatastore();
|
||||||
|
}
|
||||||
|
|
||||||
private void runNameTestExpectedFailure(String name, String expectedErrorMsg) {
|
private void runNameTestExpectedFailure(String name, String expectedErrorMsg) {
|
||||||
IllegalArgumentException thrown =
|
IllegalArgumentException thrown =
|
||||||
assertThrows(
|
assertThrows(
|
||||||
|
|
|
@ -22,14 +22,17 @@ import static google.registry.testing.JUnitBackports.assertThrows;
|
||||||
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
import static google.registry.util.DateTimeUtils.START_OF_TIME;
|
||||||
|
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
import google.registry.model.registry.label.ReservedList;
|
import google.registry.model.registry.label.ReservedList;
|
||||||
|
import google.registry.schema.tld.ReservedList.ReservedEntry;
|
||||||
|
import google.registry.schema.tld.ReservedListDao;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
/** Unit tests for {@link UpdateReservedListCommand}. */
|
/** Unit tests for {@link UpdateReservedListCommand}. */
|
||||||
public class UpdateReservedListCommandTest extends
|
public class UpdateReservedListCommandTest extends
|
||||||
CreateOrUpdateReservedListCommandTestCase<UpdateReservedListCommand> {
|
CreateOrUpdateReservedListCommandTestCase<UpdateReservedListCommand> {
|
||||||
|
|
||||||
private void populateInitialReservedList(boolean shouldPublish) {
|
private void populateInitialReservedListInDatastore(boolean shouldPublish) {
|
||||||
persistResource(
|
persistResource(
|
||||||
new ReservedList.Builder()
|
new ReservedList.Builder()
|
||||||
.setName("xn--q9jyb4c_common-reserved")
|
.setName("xn--q9jyb4c_common-reserved")
|
||||||
|
@ -40,6 +43,14 @@ public class UpdateReservedListCommandTest extends
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void populateInitialReservedListInCloudSql(boolean shouldPublish) {
|
||||||
|
ReservedListDao.save(
|
||||||
|
createCloudSqlReservedList(
|
||||||
|
"xn--q9jyb4c_common-reserved",
|
||||||
|
shouldPublish,
|
||||||
|
ImmutableMap.of("helicopter", ReservedEntry.create(FULLY_BLOCKED, ""))));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSuccess() throws Exception {
|
public void testSuccess() throws Exception {
|
||||||
runSuccessfulUpdateTest("--name=xn--q9jyb4c_common-reserved", "--input=" + reservedTermsPath);
|
runSuccessfulUpdateTest("--name=xn--q9jyb4c_common-reserved", "--input=" + reservedTermsPath);
|
||||||
|
@ -52,7 +63,7 @@ public class UpdateReservedListCommandTest extends
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSuccess_lastUpdateTime_updatedCorrectly() throws Exception {
|
public void testSuccess_lastUpdateTime_updatedCorrectly() throws Exception {
|
||||||
populateInitialReservedList(true);
|
populateInitialReservedListInDatastore(true);
|
||||||
ReservedList original = ReservedList.get("xn--q9jyb4c_common-reserved").get();
|
ReservedList original = ReservedList.get("xn--q9jyb4c_common-reserved").get();
|
||||||
runCommandForced("--input=" + reservedTermsPath);
|
runCommandForced("--input=" + reservedTermsPath);
|
||||||
ReservedList updated = ReservedList.get("xn--q9jyb4c_common-reserved").get();
|
ReservedList updated = ReservedList.get("xn--q9jyb4c_common-reserved").get();
|
||||||
|
@ -71,7 +82,7 @@ public class UpdateReservedListCommandTest extends
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSuccess_shouldPublish_doesntOverrideFalseIfNotSpecified() throws Exception {
|
public void testSuccess_shouldPublish_doesntOverrideFalseIfNotSpecified() throws Exception {
|
||||||
populateInitialReservedList(false);
|
populateInitialReservedListInDatastore(false);
|
||||||
runCommandForced("--input=" + reservedTermsPath);
|
runCommandForced("--input=" + reservedTermsPath);
|
||||||
assertThat(ReservedList.get("xn--q9jyb4c_common-reserved")).isPresent();
|
assertThat(ReservedList.get("xn--q9jyb4c_common-reserved")).isPresent();
|
||||||
ReservedList reservedList = ReservedList.get("xn--q9jyb4c_common-reserved").get();
|
ReservedList reservedList = ReservedList.get("xn--q9jyb4c_common-reserved").get();
|
||||||
|
@ -79,7 +90,7 @@ public class UpdateReservedListCommandTest extends
|
||||||
}
|
}
|
||||||
|
|
||||||
private void runSuccessfulUpdateTest(String... args) throws Exception {
|
private void runSuccessfulUpdateTest(String... args) throws Exception {
|
||||||
populateInitialReservedList(true);
|
populateInitialReservedListInDatastore(true);
|
||||||
runCommandForced(args);
|
runCommandForced(args);
|
||||||
assertThat(ReservedList.get("xn--q9jyb4c_common-reserved")).isPresent();
|
assertThat(ReservedList.get("xn--q9jyb4c_common-reserved")).isPresent();
|
||||||
ReservedList reservedList = ReservedList.get("xn--q9jyb4c_common-reserved").get();
|
ReservedList reservedList = ReservedList.get("xn--q9jyb4c_common-reserved").get();
|
||||||
|
@ -100,4 +111,25 @@ public class UpdateReservedListCommandTest extends
|
||||||
runCommand("--force", "--name=xn--q9jyb4c_poobah", "--input=" + reservedTermsPath));
|
runCommand("--force", "--name=xn--q9jyb4c_poobah", "--input=" + reservedTermsPath));
|
||||||
assertThat(thrown).hasMessageThat().contains(errorMessage);
|
assertThat(thrown).hasMessageThat().contains(errorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSaveToCloudSql_succeeds() throws Exception {
|
||||||
|
populateInitialReservedListInDatastore(true);
|
||||||
|
populateInitialReservedListInCloudSql(true);
|
||||||
|
runCommandForced(
|
||||||
|
"--name=xn--q9jyb4c_common-reserved", "--input=" + reservedTermsPath, "--also_cloud_sql");
|
||||||
|
verifyXnq9jyb4cInDatastore();
|
||||||
|
verifyXnq9jyb4cInCloudSql();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSaveToCloudSql_noExceptionThrownWhenSaveFail() throws Exception {
|
||||||
|
// Note that, during the dual-write phase, we want to make sure that no exception will be
|
||||||
|
// thrown if saving reserved list to Cloud SQL fails.
|
||||||
|
populateInitialReservedListInDatastore(true);
|
||||||
|
runCommandForced(
|
||||||
|
"--name=xn--q9jyb4c_common-reserved", "--input=" + reservedTermsPath, "--also_cloud_sql");
|
||||||
|
verifyXnq9jyb4cInDatastore();
|
||||||
|
assertThat(ReservedListDao.checkExists("xn--q9jyb4c_common-reserved")).isFalse();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue