mirror of
https://github.com/google/nomulus.git
synced 2025-05-14 00:17:20 +02:00
Add metadata parameters to CreateLrpTokensCommand
As part of this change, built out a KeyValueMapParameter from the existing TransitionListParameter in order to enable other Map types in commands (two of which are used in CreateLrpTokensCommand). ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=137476564
This commit is contained in:
parent
1dbc5f6bb0
commit
c89a902b72
6 changed files with 326 additions and 52 deletions
|
@ -27,6 +27,8 @@ import com.beust.jcommander.Parameters;
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Splitter;
|
import com.google.common.base.Splitter;
|
||||||
import com.google.common.collect.FluentIterable;
|
import com.google.common.collect.FluentIterable;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.io.Files;
|
import com.google.common.io.Files;
|
||||||
import com.google.common.io.LineReader;
|
import com.google.common.io.LineReader;
|
||||||
|
@ -34,6 +36,8 @@ import com.googlecode.objectify.Key;
|
||||||
import com.googlecode.objectify.Work;
|
import com.googlecode.objectify.Work;
|
||||||
import google.registry.model.domain.LrpTokenEntity;
|
import google.registry.model.domain.LrpTokenEntity;
|
||||||
import google.registry.tools.Command.RemoteApiCommand;
|
import google.registry.tools.Command.RemoteApiCommand;
|
||||||
|
import google.registry.tools.params.KeyValueMapParameter.StringToIntegerMap;
|
||||||
|
import google.registry.tools.params.KeyValueMapParameter.StringToStringMap;
|
||||||
import google.registry.tools.params.PathParameter;
|
import google.registry.tools.params.PathParameter;
|
||||||
import google.registry.util.StringGenerator;
|
import google.registry.util.StringGenerator;
|
||||||
import google.registry.util.TokenUtils;
|
import google.registry.util.TokenUtils;
|
||||||
|
@ -71,6 +75,24 @@ public final class CreateLrpTokensCommand implements RemoteApiCommand {
|
||||||
validateWith = PathParameter.InputFile.class)
|
validateWith = PathParameter.InputFile.class)
|
||||||
private Path assigneesFile;
|
private Path assigneesFile;
|
||||||
|
|
||||||
|
@Parameter(
|
||||||
|
names = {"-m", "--metadata"},
|
||||||
|
description = "Token metadata key-value pairs (formatted as key=value[,key=value...]). Used"
|
||||||
|
+ " only in conjunction with -a/--assignee when creating a single token.",
|
||||||
|
converter = StringToStringMap.class,
|
||||||
|
validateWith = StringToStringMap.class)
|
||||||
|
private ImmutableMap<String, String> metadata;
|
||||||
|
|
||||||
|
@Parameter(
|
||||||
|
names = {"-c", "--metadata_columns"},
|
||||||
|
description = "Token metadata columns (formatted as key=index[,key=index...], columns are"
|
||||||
|
+ " zero-indexed). Used only in conjunction with -i/--input to map additional fields in"
|
||||||
|
+ " the CSV file to metadata stored on the LRP token. The index corresponds to the column"
|
||||||
|
+ " number in the CSV file (where the assignee is assigned column 0).",
|
||||||
|
converter = StringToIntegerMap.class,
|
||||||
|
validateWith = StringToIntegerMap.class)
|
||||||
|
private ImmutableMap<String, Integer> metadataColumns;
|
||||||
|
|
||||||
@Inject StringGenerator stringGenerator;
|
@Inject StringGenerator stringGenerator;
|
||||||
|
|
||||||
private static final int BATCH_SIZE = 20;
|
private static final int BATCH_SIZE = 20;
|
||||||
|
@ -80,13 +102,19 @@ public final class CreateLrpTokensCommand implements RemoteApiCommand {
|
||||||
checkArgument(
|
checkArgument(
|
||||||
(assignee == null) == (assigneesFile != null),
|
(assignee == null) == (assigneesFile != null),
|
||||||
"Exactly one of either assignee or filename must be specified.");
|
"Exactly one of either assignee or filename must be specified.");
|
||||||
|
checkArgument(
|
||||||
|
(assigneesFile == null) || (metadata == null),
|
||||||
|
"Metadata cannot be specified along with a filename.");
|
||||||
|
checkArgument(
|
||||||
|
(assignee == null) || (metadataColumns == null),
|
||||||
|
"Metadata columns cannot be specified along with an assignee.");
|
||||||
final Set<String> validTlds = ImmutableSet.copyOf(Splitter.on(',').split(tlds));
|
final Set<String> validTlds = ImmutableSet.copyOf(Splitter.on(',').split(tlds));
|
||||||
for (String tld : validTlds) {
|
for (String tld : validTlds) {
|
||||||
assertTldExists(tld);
|
assertTldExists(tld);
|
||||||
}
|
}
|
||||||
|
|
||||||
LineReader reader = new LineReader(
|
LineReader reader = new LineReader(
|
||||||
(assignee == null)
|
(assigneesFile != null)
|
||||||
? Files.newReader(assigneesFile.toFile(), UTF_8)
|
? Files.newReader(assigneesFile.toFile(), UTF_8)
|
||||||
: new StringReader(assignee));
|
: new StringReader(assignee));
|
||||||
|
|
||||||
|
@ -96,11 +124,27 @@ public final class CreateLrpTokensCommand implements RemoteApiCommand {
|
||||||
for (String token : generateTokens(BATCH_SIZE)) {
|
for (String token : generateTokens(BATCH_SIZE)) {
|
||||||
line = reader.readLine();
|
line = reader.readLine();
|
||||||
if (!isNullOrEmpty(line)) {
|
if (!isNullOrEmpty(line)) {
|
||||||
tokensToSave.add(new LrpTokenEntity.Builder()
|
ImmutableList<String> values = ImmutableList.copyOf(Splitter.on(',').split(line));
|
||||||
.setAssignee(line)
|
LrpTokenEntity.Builder tokenBuilder = new LrpTokenEntity.Builder()
|
||||||
|
.setAssignee(values.get(0))
|
||||||
.setToken(token)
|
.setToken(token)
|
||||||
.setValidTlds(validTlds)
|
.setValidTlds(validTlds);
|
||||||
.build());
|
if (metadata != null) {
|
||||||
|
tokenBuilder.setMetadata(metadata);
|
||||||
|
} else if (metadataColumns != null) {
|
||||||
|
ImmutableMap.Builder<String, String> metadataBuilder = ImmutableMap.builder();
|
||||||
|
for (ImmutableMap.Entry<String, Integer> entry : metadataColumns.entrySet()) {
|
||||||
|
checkArgument(
|
||||||
|
values.size() > entry.getValue(),
|
||||||
|
"Entry for %s does not have a value for %s (index %s)",
|
||||||
|
values.get(0),
|
||||||
|
entry.getKey(),
|
||||||
|
entry.getValue());
|
||||||
|
metadataBuilder.put(entry.getKey(), values.get(entry.getValue()));
|
||||||
|
}
|
||||||
|
tokenBuilder.setMetadata(metadataBuilder.build());
|
||||||
|
}
|
||||||
|
tokensToSave.add(tokenBuilder.build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
saveTokens(tokensToSave.build());
|
saveTokens(tokensToSave.build());
|
||||||
|
|
96
java/google/registry/tools/params/KeyValueMapParameter.java
Normal file
96
java/google/registry/tools/params/KeyValueMapParameter.java
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
// Copyright 2016 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.params;
|
||||||
|
|
||||||
|
import com.google.common.base.Splitter;
|
||||||
|
import com.google.common.base.Strings;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Combined converter and validator class for key-value map JCommander argument strings.
|
||||||
|
*
|
||||||
|
* <p>These strings have the form {@code <K-str>=<V-str>,[<K-str>=<V-str>]*} where
|
||||||
|
* {@code <K-str>} and {@code <V-str>} are strings that can be parsed into instances of some key
|
||||||
|
* type {@code K} and value type {@code V}, respectively. This class converts a string into an
|
||||||
|
* ImmutableMap mapping {@code K} to {@code V}. Validation and conversion share the same logic;
|
||||||
|
* validation is just done by attempting conversion and throwing exceptions if need be.
|
||||||
|
*
|
||||||
|
* <p>Subclasses must implement parseKey() and parseValue() to define how to parse {@code <K-str>}
|
||||||
|
* and {@code <V-str>} into {@code K} and {@code V}, respectively.
|
||||||
|
*
|
||||||
|
* @param <K> instance key type
|
||||||
|
* @param <V> instance value type
|
||||||
|
*/
|
||||||
|
public abstract class KeyValueMapParameter<K, V>
|
||||||
|
extends ParameterConverterValidator<ImmutableMap<K, V>> {
|
||||||
|
|
||||||
|
public KeyValueMapParameter(String messageForInvalid) {
|
||||||
|
super(messageForInvalid);
|
||||||
|
}
|
||||||
|
|
||||||
|
public KeyValueMapParameter() {
|
||||||
|
super("Not formatted correctly.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Override to define how to parse rawKey into an object of type K. */
|
||||||
|
protected abstract K parseKey(String rawKey);
|
||||||
|
|
||||||
|
/** Override to define how to parse rawValue into an object of type V. */
|
||||||
|
protected abstract V parseValue(String rawValue);
|
||||||
|
|
||||||
|
/** Override to perform any post-processing on the map. */
|
||||||
|
protected ImmutableMap<K, V> processMap(ImmutableMap<K, V> map) {
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final ImmutableMap<K, V> convert(String keyValueMapString) {
|
||||||
|
ImmutableMap.Builder<K, V> builder = new ImmutableMap.Builder<>();
|
||||||
|
if (!Strings.isNullOrEmpty(keyValueMapString)) {
|
||||||
|
for (Map.Entry<String, String> entry :
|
||||||
|
Splitter.on(',').withKeyValueSeparator('=').split(keyValueMapString).entrySet()) {
|
||||||
|
builder.put(parseKey(entry.getKey()), parseValue(entry.getValue()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return processMap(builder.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Combined converter and validator class for string-to-string Map argument strings. */
|
||||||
|
public static class StringToStringMap extends KeyValueMapParameter<String, String> {
|
||||||
|
@Override
|
||||||
|
protected String parseKey(String rawKey) {
|
||||||
|
return rawKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String parseValue(String value) {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Combined converter and validator class for string-to-integer Map argument strings. */
|
||||||
|
public static class StringToIntegerMap extends KeyValueMapParameter<String, Integer> {
|
||||||
|
@Override
|
||||||
|
protected String parseKey(String rawKey) {
|
||||||
|
return rawKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Integer parseValue(String value) {
|
||||||
|
return Integer.parseInt(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,33 +16,16 @@ package google.registry.tools.params;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
|
|
||||||
import com.google.common.base.Splitter;
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableSortedMap;
|
import com.google.common.collect.ImmutableSortedMap;
|
||||||
import com.google.common.collect.Ordering;
|
import com.google.common.collect.Ordering;
|
||||||
import google.registry.model.registry.Registry.TldState;
|
import google.registry.model.registry.Registry.TldState;
|
||||||
import java.util.Map;
|
|
||||||
import org.joda.money.Money;
|
import org.joda.money.Money;
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
|
|
||||||
/**
|
/** Combined converter and validator class for transition list JCommander argument strings. */
|
||||||
* Combined converter and validator class for transition list JCommander argument strings.
|
|
||||||
*
|
|
||||||
* <p>These strings have the form {@code <DateTime>=<T-str>,[<DateTime>=<T-str>]*} where
|
|
||||||
* {@code <T-str>} is a string that can be parsed into an instance of some value type {@code T}, and
|
|
||||||
* the entire argument represents a series of timed transitions of some property taking on those
|
|
||||||
* values. This class converts such a string into an ImmutableSortedMap mapping DateTime to
|
|
||||||
* {@code T}. Validation and conversion share the same logic; validation is just done by attempting
|
|
||||||
* conversion and throwing exceptions if need be.
|
|
||||||
*
|
|
||||||
* <p>Subclasses must implement parseValue() to define how to parse {@code <T-str>} into a
|
|
||||||
* {@code T}.
|
|
||||||
*
|
|
||||||
* @param <T> instance value type
|
|
||||||
*/
|
|
||||||
// TODO(b/19031334): Investigate making this complex generic type work with the factory.
|
// TODO(b/19031334): Investigate making this complex generic type work with the factory.
|
||||||
public abstract class TransitionListParameter<T>
|
public abstract class TransitionListParameter<V> extends KeyValueMapParameter<DateTime, V> {
|
||||||
extends ParameterConverterValidator<ImmutableSortedMap<DateTime, T>> {
|
|
||||||
|
|
||||||
private static final DateTimeParameter DATE_TIME_CONVERTER = new DateTimeParameter();
|
private static final DateTimeParameter DATE_TIME_CONVERTER = new DateTimeParameter();
|
||||||
|
|
||||||
|
@ -50,22 +33,15 @@ public abstract class TransitionListParameter<T>
|
||||||
super("Not formatted correctly or has transition times out of order.");
|
super("Not formatted correctly or has transition times out of order.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Override to define how to parse rawValue into an object of type T. */
|
@Override
|
||||||
protected abstract T parseValue(String rawValue);
|
protected final DateTime parseKey(String rawKey) {
|
||||||
|
return DATE_TIME_CONVERTER.convert(rawKey);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ImmutableSortedMap<DateTime, T> convert(String transitionListString) {
|
protected final ImmutableSortedMap<DateTime, V> processMap(ImmutableMap<DateTime, V> map) {
|
||||||
ImmutableMap.Builder<DateTime, T> builder = new ImmutableMap.Builder<>();
|
checkArgument(Ordering.natural().isOrdered(map.keySet()), "Transition times out of order.");
|
||||||
for (Map.Entry<String, String> entry :
|
return ImmutableSortedMap.copyOf(map);
|
||||||
Splitter.on(',').withKeyValueSeparator('=').split(transitionListString).entrySet()) {
|
|
||||||
builder.put(
|
|
||||||
DATE_TIME_CONVERTER.convert(entry.getKey()),
|
|
||||||
parseValue(entry.getValue()));
|
|
||||||
}
|
|
||||||
ImmutableMap<DateTime, T> transitionMap = builder.build();
|
|
||||||
checkArgument(Ordering.natural().isOrdered(transitionMap.keySet()),
|
|
||||||
"Transition times out of order.");
|
|
||||||
return ImmutableSortedMap.copyOf(transitionMap);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Converter-validator for TLD state transitions. */
|
/** Converter-validator for TLD state transitions. */
|
||||||
|
|
|
@ -55,7 +55,20 @@ public class CreateLrpTokensCommandTest extends CommandTestCase<CreateLrpTokensC
|
||||||
public void testSuccess_oneAssignee() throws Exception {
|
public void testSuccess_oneAssignee() throws Exception {
|
||||||
runCommand("--assignee=domain.tld", "--tlds=tld");
|
runCommand("--assignee=domain.tld", "--tlds=tld");
|
||||||
assertLrpTokens(
|
assertLrpTokens(
|
||||||
createToken("LRP_abcdefghijklmnop", "domain.tld", ImmutableSet.of("tld"), null));
|
createToken("LRP_abcdefghijklmnop", "domain.tld", ImmutableSet.of("tld"), null, null));
|
||||||
|
assertInStdout("domain.tld,LRP_abcdefghijklmnop");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSuccess_oneAssignee_withMetadata() throws Exception {
|
||||||
|
runCommand("--assignee=domain.tld", "--tlds=tld", "--metadata=key=foo,key2=bar");
|
||||||
|
assertLrpTokens(
|
||||||
|
createToken(
|
||||||
|
"LRP_abcdefghijklmnop",
|
||||||
|
"domain.tld",
|
||||||
|
ImmutableSet.of("tld"),
|
||||||
|
null,
|
||||||
|
ImmutableMap.of("key", "foo", "key2", "bar")));
|
||||||
assertInStdout("domain.tld,LRP_abcdefghijklmnop");
|
assertInStdout("domain.tld,LRP_abcdefghijklmnop");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,7 +82,7 @@ public class CreateLrpTokensCommandTest extends CommandTestCase<CreateLrpTokensC
|
||||||
runCommand("--assignee=domain.tld", "--tlds=tld");
|
runCommand("--assignee=domain.tld", "--tlds=tld");
|
||||||
assertLrpTokens(
|
assertLrpTokens(
|
||||||
existingToken,
|
existingToken,
|
||||||
createToken("LRP_qrstuvwxyzabcdef", "domain.tld", ImmutableSet.of("tld"), null));
|
createToken("LRP_qrstuvwxyzabcdef", "domain.tld", ImmutableSet.of("tld"), null, null));
|
||||||
assertInStdout("domain.tld,LRP_qrstuvwxyzabcdef");
|
assertInStdout("domain.tld,LRP_qrstuvwxyzabcdef");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +91,21 @@ public class CreateLrpTokensCommandTest extends CommandTestCase<CreateLrpTokensC
|
||||||
Files.write("domain.tld", assigneeFile, UTF_8);
|
Files.write("domain.tld", assigneeFile, UTF_8);
|
||||||
runCommand("--input=" + assigneeFilePath, "--tlds=tld");
|
runCommand("--input=" + assigneeFilePath, "--tlds=tld");
|
||||||
assertLrpTokens(
|
assertLrpTokens(
|
||||||
createToken("LRP_abcdefghijklmnop", "domain.tld", ImmutableSet.of("tld"), null));
|
createToken("LRP_abcdefghijklmnop", "domain.tld", ImmutableSet.of("tld"), null, null));
|
||||||
|
assertInStdout("domain.tld,LRP_abcdefghijklmnop");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSuccess_oneAssignee_byFile_withMetadata() throws Exception {
|
||||||
|
Files.write("domain.tld,foo,bar", assigneeFile, UTF_8);
|
||||||
|
runCommand("--input=" + assigneeFilePath, "--tlds=tld", "--metadata_columns=key=1,key2=2");
|
||||||
|
assertLrpTokens(
|
||||||
|
createToken(
|
||||||
|
"LRP_abcdefghijklmnop",
|
||||||
|
"domain.tld",
|
||||||
|
ImmutableSet.of("tld"),
|
||||||
|
null,
|
||||||
|
ImmutableMap.of("key", "foo", "key2", "bar")));
|
||||||
assertInStdout("domain.tld,LRP_abcdefghijklmnop");
|
assertInStdout("domain.tld,LRP_abcdefghijklmnop");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,9 +123,9 @@ public class CreateLrpTokensCommandTest extends CommandTestCase<CreateLrpTokensC
|
||||||
runCommand("--input=" + assigneeFilePath, "--tlds=tld");
|
runCommand("--input=" + assigneeFilePath, "--tlds=tld");
|
||||||
|
|
||||||
assertLrpTokens(
|
assertLrpTokens(
|
||||||
createToken("LRP_abcdefghijklmnop", "domain1.tld", ImmutableSet.of("tld"), null),
|
createToken("LRP_abcdefghijklmnop", "domain1.tld", ImmutableSet.of("tld"), null, null),
|
||||||
createToken("LRP_qrstuvwxyzabcdef", "domain2.tld", ImmutableSet.of("tld"), null),
|
createToken("LRP_qrstuvwxyzabcdef", "domain2.tld", ImmutableSet.of("tld"), null, null),
|
||||||
createToken("LRP_ghijklmnopqrstuv", "domain3.tld", ImmutableSet.of("tld"), null));
|
createToken("LRP_ghijklmnopqrstuv", "domain3.tld", ImmutableSet.of("tld"), null, null));
|
||||||
|
|
||||||
assertInStdout("domain1.tld,LRP_abcdefghijklmnop");
|
assertInStdout("domain1.tld,LRP_abcdefghijklmnop");
|
||||||
assertInStdout("domain2.tld,LRP_qrstuvwxyzabcdef");
|
assertInStdout("domain2.tld,LRP_qrstuvwxyzabcdef");
|
||||||
|
@ -110,15 +137,15 @@ public class CreateLrpTokensCommandTest extends CommandTestCase<CreateLrpTokensC
|
||||||
Files.write("domain1.tld\n\ndomain2.tld", assigneeFile, UTF_8);
|
Files.write("domain1.tld\n\ndomain2.tld", assigneeFile, UTF_8);
|
||||||
runCommand("--input=" + assigneeFilePath, "--tlds=tld");
|
runCommand("--input=" + assigneeFilePath, "--tlds=tld");
|
||||||
assertLrpTokens(
|
assertLrpTokens(
|
||||||
createToken("LRP_abcdefghijklmnop", "domain1.tld", ImmutableSet.of("tld"), null),
|
createToken("LRP_abcdefghijklmnop", "domain1.tld", ImmutableSet.of("tld"), null, null),
|
||||||
// Second deterministic token (LRP_qrstuvwxyzabcdef) still consumed but not assigned
|
// Second deterministic token (LRP_qrstuvwxyzabcdef) still consumed but not assigned
|
||||||
createToken("LRP_ghijklmnopqrstuv", "domain2.tld", ImmutableSet.of("tld"), null));
|
createToken("LRP_ghijklmnopqrstuv", "domain2.tld", ImmutableSet.of("tld"), null, null));
|
||||||
assertInStdout("domain1.tld,LRP_abcdefghijklmnop");
|
assertInStdout("domain1.tld,LRP_abcdefghijklmnop");
|
||||||
assertInStdout("domain2.tld,LRP_ghijklmnopqrstuv");
|
assertInStdout("domain2.tld,LRP_ghijklmnopqrstuv");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSuccess_largeFile() throws Exception {
|
public void testSuccess_largeFile_withMetadata() throws Exception {
|
||||||
int numberOfTokens = 67;
|
int numberOfTokens = 67;
|
||||||
LrpTokenEntity[] expectedTokens = new LrpTokenEntity[numberOfTokens];
|
LrpTokenEntity[] expectedTokens = new LrpTokenEntity[numberOfTokens];
|
||||||
// Prepend a counter to avoid collisions, 16-char alphabet will always generate the same string.
|
// Prepend a counter to avoid collisions, 16-char alphabet will always generate the same string.
|
||||||
|
@ -127,16 +154,17 @@ public class CreateLrpTokensCommandTest extends CommandTestCase<CreateLrpTokensC
|
||||||
command.stringGenerator = stringGenerator;
|
command.stringGenerator = stringGenerator;
|
||||||
StringBuilder assigneeFileBuilder = new StringBuilder();
|
StringBuilder assigneeFileBuilder = new StringBuilder();
|
||||||
for (int i = 0; i < numberOfTokens; i++) {
|
for (int i = 0; i < numberOfTokens; i++) {
|
||||||
assigneeFileBuilder.append(String.format("domain%d.tld\n", i));
|
assigneeFileBuilder.append(String.format("domain%d.tld,%d,%d\n", i, i * 2, i * 3));
|
||||||
expectedTokens[i] =
|
expectedTokens[i] =
|
||||||
createToken(
|
createToken(
|
||||||
String.format("LRP_%04d_abcdefghijklmnop", i),
|
String.format("LRP_%04d_abcdefghijklmnop", i),
|
||||||
String.format("domain%d.tld", i),
|
String.format("domain%d.tld", i),
|
||||||
ImmutableSet.of("tld"),
|
ImmutableSet.of("tld"),
|
||||||
null);
|
null,
|
||||||
|
ImmutableMap.of("key", Integer.toString(i * 2), "key2", Integer.toString(i * 3)));
|
||||||
}
|
}
|
||||||
Files.write(assigneeFileBuilder, assigneeFile, UTF_8);
|
Files.write(assigneeFileBuilder, assigneeFile, UTF_8);
|
||||||
runCommand("--input=" + assigneeFilePath, "--tlds=tld");
|
runCommand("--input=" + assigneeFilePath, "--tlds=tld", "--metadata_columns=key=1,key2=2");
|
||||||
assertLrpTokens(expectedTokens);
|
assertLrpTokens(expectedTokens);
|
||||||
for (int i = 0; i < numberOfTokens; i++) {
|
for (int i = 0; i < numberOfTokens; i++) {
|
||||||
assertInStdout(String.format("domain%d.tld,LRP_%04d_abcdefghijklmnop", i, i));
|
assertInStdout(String.format("domain%d.tld,LRP_%04d_abcdefghijklmnop", i, i));
|
||||||
|
@ -159,12 +187,36 @@ public class CreateLrpTokensCommandTest extends CommandTestCase<CreateLrpTokensC
|
||||||
runCommand("--assignee=domain.tld", "--tlds=tld", "--input=" + assigneeFilePath);
|
runCommand("--assignee=domain.tld", "--tlds=tld", "--input=" + assigneeFilePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFailure_bothMetadataAndFile() throws Exception {
|
||||||
|
thrown.expect(
|
||||||
|
IllegalArgumentException.class,
|
||||||
|
"Metadata cannot be specified along with a filename.");
|
||||||
|
runCommand("--tlds=tld", "--input=" + assigneeFilePath, "--metadata=key=foo");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFailure_bothAssigneeAndMetadataColumns() throws Exception {
|
||||||
|
thrown.expect(
|
||||||
|
IllegalArgumentException.class,
|
||||||
|
"Metadata columns cannot be specified along with an assignee.");
|
||||||
|
runCommand("--assignee=domain.tld", "--tlds=tld", "--metadata_columns=foo=1");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testFailure_badTld() throws Exception {
|
public void testFailure_badTld() throws Exception {
|
||||||
thrown.expect(IllegalArgumentException.class, "TLD foo does not exist");
|
thrown.expect(IllegalArgumentException.class, "TLD foo does not exist");
|
||||||
runCommand("--assignee=domain.tld", "--tlds=foo");
|
runCommand("--assignee=domain.tld", "--tlds=foo");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFailure_oneAssignee_byFile_insufficientMetadata() throws Exception {
|
||||||
|
Files.write("domain.tld,foo", assigneeFile, UTF_8);
|
||||||
|
thrown.expect(IllegalArgumentException.class,
|
||||||
|
"Entry for domain.tld does not have a value for key2 (index 2)");
|
||||||
|
runCommand("--input=" + assigneeFilePath, "--tlds=tld", "--metadata_columns=key=1,key2=2");
|
||||||
|
}
|
||||||
|
|
||||||
private void assertLrpTokens(LrpTokenEntity... expected) throws Exception {
|
private void assertLrpTokens(LrpTokenEntity... expected) throws Exception {
|
||||||
// Using ImmutableObject comparison here is tricky because updateTimestamp is not set on the
|
// Using ImmutableObject comparison here is tricky because updateTimestamp is not set on the
|
||||||
// expected LrpToken objects and will cause the assert to fail.
|
// expected LrpToken objects and will cause the assert to fail.
|
||||||
|
@ -190,7 +242,8 @@ public class CreateLrpTokensCommandTest extends CommandTestCase<CreateLrpTokensC
|
||||||
String token,
|
String token,
|
||||||
String assignee,
|
String assignee,
|
||||||
Set<String> validTlds,
|
Set<String> validTlds,
|
||||||
@Nullable Key<HistoryEntry> redemptionHistoryEntry) {
|
@Nullable Key<HistoryEntry> redemptionHistoryEntry,
|
||||||
|
@Nullable ImmutableMap<String, String> metadata) {
|
||||||
LrpTokenEntity.Builder tokenBuilder = new LrpTokenEntity.Builder()
|
LrpTokenEntity.Builder tokenBuilder = new LrpTokenEntity.Builder()
|
||||||
.setAssignee(assignee)
|
.setAssignee(assignee)
|
||||||
.setValidTlds(validTlds)
|
.setValidTlds(validTlds)
|
||||||
|
@ -198,6 +251,9 @@ public class CreateLrpTokensCommandTest extends CommandTestCase<CreateLrpTokensC
|
||||||
if (redemptionHistoryEntry != null) {
|
if (redemptionHistoryEntry != null) {
|
||||||
tokenBuilder.setRedemptionHistoryEntry(redemptionHistoryEntry);
|
tokenBuilder.setRedemptionHistoryEntry(redemptionHistoryEntry);
|
||||||
}
|
}
|
||||||
|
if (metadata != null) {
|
||||||
|
tokenBuilder.setMetadata(metadata);
|
||||||
|
}
|
||||||
return tokenBuilder.build();
|
return tokenBuilder.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ java_library(
|
||||||
srcs = glob(["*.java"]),
|
srcs = glob(["*.java"]),
|
||||||
deps = [
|
deps = [
|
||||||
"//java/com/google/common/base",
|
"//java/com/google/common/base",
|
||||||
|
"//java/com/google/common/collect",
|
||||||
"//third_party/java/hamcrest",
|
"//third_party/java/hamcrest",
|
||||||
"//third_party/java/jcommander",
|
"//third_party/java/jcommander",
|
||||||
"//third_party/java/joda_money",
|
"//third_party/java/joda_money",
|
||||||
|
|
|
@ -0,0 +1,101 @@
|
||||||
|
// Copyright 2016 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.params;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import google.registry.testing.ExceptionRule;
|
||||||
|
import google.registry.tools.params.KeyValueMapParameter.StringToIntegerMap;
|
||||||
|
import google.registry.tools.params.KeyValueMapParameter.StringToStringMap;
|
||||||
|
import org.junit.Rule;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.junit.runners.JUnit4;
|
||||||
|
|
||||||
|
/** Unit tests for {@link KeyValueMapParameter}. */
|
||||||
|
@RunWith(JUnit4.class)
|
||||||
|
public class KeyValueMapParameterTest {
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public final ExceptionRule thrown = new ExceptionRule();
|
||||||
|
|
||||||
|
private final StringToStringMap stringToStringInstance = new StringToStringMap();
|
||||||
|
private final StringToIntegerMap stringToIntegerInstance = new StringToIntegerMap();
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSuccess_convertStringToString_singleEntry() throws Exception {
|
||||||
|
assertThat(stringToStringInstance.convert("key=foo"))
|
||||||
|
.isEqualTo(ImmutableMap.of("key", "foo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSuccess_convertStringToInteger_singleEntry() throws Exception {
|
||||||
|
assertThat(stringToIntegerInstance.convert("key=1"))
|
||||||
|
.isEqualTo(ImmutableMap.of("key", 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSuccess_convertStringToString() throws Exception {
|
||||||
|
assertThat(stringToStringInstance.convert("key=foo,key2=bar"))
|
||||||
|
.isEqualTo(ImmutableMap.of("key", "foo", "key2", "bar"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSuccess_convertStringToInteger() throws Exception {
|
||||||
|
assertThat(stringToIntegerInstance.convert("key=1,key2=2"))
|
||||||
|
.isEqualTo(ImmutableMap.of("key", 1, "key2", 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSuccess_convertStringToString_empty() throws Exception {
|
||||||
|
assertThat(stringToStringInstance.convert("")).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSuccess_convertStringToInteger_empty() throws Exception {
|
||||||
|
assertThat(stringToIntegerInstance.convert("")).isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFailure_convertStringToInteger_badType() throws Exception {
|
||||||
|
thrown.expect(NumberFormatException.class);
|
||||||
|
stringToIntegerInstance.convert("key=1,key2=foo");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFailure_convertStringToString_badSeparator() throws Exception {
|
||||||
|
thrown.expect(IllegalArgumentException.class);
|
||||||
|
stringToStringInstance.convert("key=foo&key2=bar");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFailure_convertStringToInteger_badSeparator() throws Exception {
|
||||||
|
thrown.expect(IllegalArgumentException.class);
|
||||||
|
stringToIntegerInstance.convert("key=1&key2=2");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFailure_convertStringToString_badFormat() throws Exception {
|
||||||
|
thrown.expect(IllegalArgumentException.class);
|
||||||
|
stringToStringInstance.convert("foo");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFailure_convertStringToInteger_badFormat() throws Exception {
|
||||||
|
thrown.expect(IllegalArgumentException.class);
|
||||||
|
stringToIntegerInstance.convert("foo");
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue