mirror of
https://github.com/google/nomulus.git
synced 2025-07-09 20:53:26 +02:00
Don't NPE when nomulus tool is run without a subcommand (#564)
* Don't NPE when nomulus tool is run without a subcommand This occurred when an environment was specified but without a subcommand. Now, the list of valid subcommands is outputted instead of seeing a generic NPE. This also makes some formatting changes in other files that were causing the incremental format check to fail. * Try AppEngineRule
This commit is contained in:
parent
5d58be6f0a
commit
210de9340e
8 changed files with 135 additions and 50 deletions
|
@ -18,9 +18,7 @@ import google.registry.persistence.VKey;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.persistence.AttributeConverter;
|
import javax.persistence.AttributeConverter;
|
||||||
|
|
||||||
/**
|
/** Converts VKey to a string column. */
|
||||||
* Converts VKey to a string column.
|
|
||||||
*/
|
|
||||||
public abstract class VKeyConverter<T> implements AttributeConverter<VKey<T>, String> {
|
public abstract class VKeyConverter<T> implements AttributeConverter<VKey<T>, String> {
|
||||||
@Override
|
@Override
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@ -34,8 +32,6 @@ public abstract class VKeyConverter<T> implements AttributeConverter<VKey<T>, St
|
||||||
return dbData == null ? null : VKey.createSql(getAttributeClass(), dbData);
|
return dbData == null ? null : VKey.createSql(getAttributeClass(), dbData);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Returns the class of the attribute. */
|
||||||
* Returns the class of the attribute.
|
|
||||||
*/
|
|
||||||
protected abstract Class<T> getAttributeClass();
|
protected abstract Class<T> getAttributeClass();
|
||||||
}
|
}
|
||||||
|
|
|
@ -153,8 +153,8 @@ public final class DomainLockUtils {
|
||||||
/**
|
/**
|
||||||
* Creates and applies a lock in one step.
|
* Creates and applies a lock in one step.
|
||||||
*
|
*
|
||||||
* <p>This should only be used for admin actions, e.g. Nomulus tool commands or relocks.
|
* <p>This should only be used for admin actions, e.g. Nomulus tool commands or relocks. Note: in
|
||||||
* Note: in the case of relocks, isAdmin is determined by the previous lock.
|
* the case of relocks, isAdmin is determined by the previous lock.
|
||||||
*/
|
*/
|
||||||
public RegistryLock administrativelyApplyLock(
|
public RegistryLock administrativelyApplyLock(
|
||||||
String domainName, String registrarId, @Nullable String registrarPocId, boolean isAdmin) {
|
String domainName, String registrarId, @Nullable String registrarPocId, boolean isAdmin) {
|
||||||
|
@ -175,7 +175,7 @@ public final class DomainLockUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates and applies an unlock in one step.
|
* Creates and applies an unlock in one step.
|
||||||
*
|
*
|
||||||
* <p>This should only be used for admin actions, e.g. Nomulus tool commands.
|
* <p>This should only be used for admin actions, e.g. Nomulus tool commands.
|
||||||
*/
|
*/
|
||||||
public RegistryLock administrativelyApplyUnlock(
|
public RegistryLock administrativelyApplyUnlock(
|
||||||
|
|
|
@ -132,10 +132,8 @@ final class RegistryCli implements AutoCloseable, CommandRunner {
|
||||||
jcommander.parse(args);
|
jcommander.parse(args);
|
||||||
} catch (ParameterException e) {
|
} catch (ParameterException e) {
|
||||||
// If we failed to fully parse the command but at least found a valid command name, show only
|
// If we failed to fully parse the command but at least found a valid command name, show only
|
||||||
// the usage for that command. Otherwise, show full usage. Either way, rethrow the error.
|
// the usage for that command.
|
||||||
if (jcommander.getParsedCommand() == null) {
|
if (jcommander.getParsedCommand() != null) {
|
||||||
jcommander.usage();
|
|
||||||
} else {
|
|
||||||
jcommander.usage(jcommander.getParsedCommand());
|
jcommander.usage(jcommander.getParsedCommand());
|
||||||
}
|
}
|
||||||
// Don't rethrow if we said: nomulus command --help
|
// Don't rethrow if we said: nomulus command --help
|
||||||
|
@ -144,8 +142,13 @@ final class RegistryCli implements AutoCloseable, CommandRunner {
|
||||||
}
|
}
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
String parsedCommand = jcommander.getParsedCommand();
|
||||||
if (showAllCommands) {
|
// Show the list of all commands either if requested or if no subcommand name was specified
|
||||||
|
// (which does not throw a ParameterException parse error above).
|
||||||
|
if (showAllCommands || parsedCommand == null) {
|
||||||
|
if (parsedCommand == null) {
|
||||||
|
System.out.println("The list of available subcommands is:");
|
||||||
|
}
|
||||||
commands.keySet().forEach(System.out::println);
|
commands.keySet().forEach(System.out::println);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -161,8 +164,7 @@ final class RegistryCli implements AutoCloseable, CommandRunner {
|
||||||
// retrieving the first (and, by virtue of our usage, only) object from it.
|
// retrieving the first (and, by virtue of our usage, only) object from it.
|
||||||
Command command =
|
Command command =
|
||||||
(Command)
|
(Command)
|
||||||
Iterables.getOnlyElement(
|
Iterables.getOnlyElement(jcommander.getCommands().get(parsedCommand).getObjects());
|
||||||
jcommander.getCommands().get(jcommander.getParsedCommand()).getObjects());
|
|
||||||
loggingParams.configureLogging(); // Must be called after parameters are parsed.
|
loggingParams.configureLogging(); // Must be called after parameters are parsed.
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -186,9 +186,7 @@ public final class RegistrarFormFields {
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
public static final FormField<String, String> REGISTRY_LOCK_EMAIL_ADDRESS_FIELD =
|
public static final FormField<String, String> REGISTRY_LOCK_EMAIL_ADDRESS_FIELD =
|
||||||
FormFields.EMAIL
|
FormFields.EMAIL.asBuilderNamed("registryLockEmailAddress").build();
|
||||||
.asBuilderNamed("registryLockEmailAddress")
|
|
||||||
.build();
|
|
||||||
|
|
||||||
public static final FormField<Boolean, Boolean> CONTACT_VISIBLE_IN_WHOIS_AS_ADMIN_FIELD =
|
public static final FormField<Boolean, Boolean> CONTACT_VISIBLE_IN_WHOIS_AS_ADMIN_FIELD =
|
||||||
FormField.named("visibleInWhoisAsAdmin", Boolean.class)
|
FormField.named("visibleInWhoisAsAdmin", Boolean.class)
|
||||||
|
|
|
@ -64,8 +64,8 @@ public class DumpGoldenSchemaCommand extends PostgresqlCommand {
|
||||||
if (result.getExitCode() != 0) {
|
if (result.getExitCode() != 0) {
|
||||||
throw new RuntimeException(result.toString());
|
throw new RuntimeException(result.toString());
|
||||||
}
|
}
|
||||||
result = postgresContainer.execInContainer(
|
result =
|
||||||
"cp", CONTAINER_MOUNT_POINT_TMP, CONTAINER_MOUNT_POINT);
|
postgresContainer.execInContainer("cp", CONTAINER_MOUNT_POINT_TMP, CONTAINER_MOUNT_POINT);
|
||||||
if (result.getExitCode() != 0) {
|
if (result.getExitCode() != 0) {
|
||||||
throw new RuntimeException(result.toString());
|
throw new RuntimeException(result.toString());
|
||||||
}
|
}
|
||||||
|
|
|
@ -45,8 +45,8 @@ public class VKeyConverterTest {
|
||||||
jpaTm().transact(() -> jpaTm().getEntityManager().persist(original));
|
jpaTm().transact(() -> jpaTm().getEntityManager().persist(original));
|
||||||
|
|
||||||
TestEntity retrieved =
|
TestEntity retrieved =
|
||||||
jpaTm().transact(
|
jpaTm()
|
||||||
() -> jpaTm().getEntityManager().find(TestEntity.class, "TheRealSpartacus"));
|
.transact(() -> jpaTm().getEntityManager().find(TestEntity.class, "TheRealSpartacus"));
|
||||||
assertThat(retrieved.other.getSqlKey()).isEqualTo("ImSpartacus!");
|
assertThat(retrieved.other.getSqlKey()).isEqualTo("ImSpartacus!");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -60,8 +60,7 @@ public class VKeyConverterTest {
|
||||||
|
|
||||||
@Entity(name = "TestEntity")
|
@Entity(name = "TestEntity")
|
||||||
static class TestEntity {
|
static class TestEntity {
|
||||||
@Id
|
@Id String id;
|
||||||
String id;
|
|
||||||
|
|
||||||
// Specifying "@Converter(autoApply = true) on TestEntityVKeyConverter this doesn't seem to
|
// Specifying "@Converter(autoApply = true) on TestEntityVKeyConverter this doesn't seem to
|
||||||
// work.
|
// work.
|
||||||
|
|
|
@ -98,19 +98,20 @@ public class RegistrarContactCommandTest extends CommandTestCase<RegistrarContac
|
||||||
"--visible_in_domain_whois_as_abuse=false",
|
"--visible_in_domain_whois_as_abuse=false",
|
||||||
"NewRegistrar");
|
"NewRegistrar");
|
||||||
RegistrarContact registrarContact = loadRegistrar("NewRegistrar").getContacts().asList().get(1);
|
RegistrarContact registrarContact = loadRegistrar("NewRegistrar").getContacts().asList().get(1);
|
||||||
assertThat(registrarContact).isEqualTo(
|
assertThat(registrarContact)
|
||||||
new RegistrarContact.Builder()
|
.isEqualTo(
|
||||||
.setParent(registrar)
|
new RegistrarContact.Builder()
|
||||||
.setName("Judith Registrar")
|
.setParent(registrar)
|
||||||
.setEmailAddress("judith.doe@example.com")
|
.setName("Judith Registrar")
|
||||||
.setRegistryLockEmailAddress("judith.doe@external.com")
|
.setEmailAddress("judith.doe@example.com")
|
||||||
.setPhoneNumber("+1.2125650000")
|
.setRegistryLockEmailAddress("judith.doe@external.com")
|
||||||
.setFaxNumber("+1.2125650001")
|
.setPhoneNumber("+1.2125650000")
|
||||||
.setTypes(ImmutableSet.of(WHOIS))
|
.setFaxNumber("+1.2125650001")
|
||||||
.setVisibleInWhoisAsAdmin(true)
|
.setTypes(ImmutableSet.of(WHOIS))
|
||||||
.setVisibleInWhoisAsTech(false)
|
.setVisibleInWhoisAsAdmin(true)
|
||||||
.setVisibleInDomainWhoisAsAbuse(false)
|
.setVisibleInWhoisAsTech(false)
|
||||||
.build());
|
.setVisibleInDomainWhoisAsAbuse(false)
|
||||||
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -305,17 +306,18 @@ public class RegistrarContactCommandTest extends CommandTestCase<RegistrarContac
|
||||||
"--visible_in_domain_whois_as_abuse=true",
|
"--visible_in_domain_whois_as_abuse=true",
|
||||||
"NewRegistrar");
|
"NewRegistrar");
|
||||||
RegistrarContact registrarContact = loadRegistrar("NewRegistrar").getContacts().asList().get(1);
|
RegistrarContact registrarContact = loadRegistrar("NewRegistrar").getContacts().asList().get(1);
|
||||||
assertThat(registrarContact).isEqualTo(
|
assertThat(registrarContact)
|
||||||
new RegistrarContact.Builder()
|
.isEqualTo(
|
||||||
.setParent(registrar)
|
new RegistrarContact.Builder()
|
||||||
.setName("Jim Doe")
|
.setParent(registrar)
|
||||||
.setEmailAddress("jim.doe@example.com")
|
.setName("Jim Doe")
|
||||||
.setRegistryLockEmailAddress("jim.doe@external.com")
|
.setEmailAddress("jim.doe@example.com")
|
||||||
.setTypes(ImmutableSet.of(ADMIN, ABUSE))
|
.setRegistryLockEmailAddress("jim.doe@external.com")
|
||||||
.setVisibleInWhoisAsAdmin(true)
|
.setTypes(ImmutableSet.of(ADMIN, ABUSE))
|
||||||
.setVisibleInWhoisAsTech(false)
|
.setVisibleInWhoisAsAdmin(true)
|
||||||
.setVisibleInDomainWhoisAsAbuse(true)
|
.setVisibleInWhoisAsTech(false)
|
||||||
.build());
|
.setVisibleInDomainWhoisAsAbuse(true)
|
||||||
|
.build());
|
||||||
assertThat(registrarContact.getGaeUserId()).isNull();
|
assertThat(registrarContact.getGaeUserId()).isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
// Copyright 2020 The Nomulus Authors. All Rights Reserved.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
package google.registry.tools;
|
||||||
|
|
||||||
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||||
|
import static org.junit.Assert.assertThrows;
|
||||||
|
|
||||||
|
import google.registry.testing.AppEngineRule;
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.extension.RegisterExtension;
|
||||||
|
|
||||||
|
/** Unit tests for {@link google.registry.tools.RegistryTool}. */
|
||||||
|
public class RegistryToolTest {
|
||||||
|
|
||||||
|
@RegisterExtension
|
||||||
|
public final AppEngineRule appEngine = AppEngineRule.builder().withDatastoreAndCloudSql().build();
|
||||||
|
|
||||||
|
// Lock for stdout/stderr. Note that this is static: since we're dealing with globals, we need
|
||||||
|
// to lock for the entire JVM.
|
||||||
|
private static final ReentrantLock stdoutLock = new ReentrantLock();
|
||||||
|
|
||||||
|
private PrintStream oldStdout;
|
||||||
|
private final ByteArrayOutputStream stdout = new ByteArrayOutputStream();
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
void beforeEach() {
|
||||||
|
// Capture standard output/error. This is problematic because gradle tests run in parallel in
|
||||||
|
// the same JVM. So first lock out any other tests in this JVM that are trying to do this
|
||||||
|
// trick.
|
||||||
|
// TODO(mcilwain): Turn this into a JUnit 5 extension.
|
||||||
|
stdoutLock.lock();
|
||||||
|
oldStdout = System.out;
|
||||||
|
System.setOut(new PrintStream(stdout));
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
final void afterEach() {
|
||||||
|
System.setOut(oldStdout);
|
||||||
|
stdoutLock.unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void test_displayAvailableCommands() throws Exception {
|
||||||
|
RegistryTool.main(new String[] {"-e", "unittest", "--commands"});
|
||||||
|
// Check for the existence of a few common commands.
|
||||||
|
assertThat(getStdout()).contains("login");
|
||||||
|
assertThat(getStdout()).contains("check_domain");
|
||||||
|
assertThat(getStdout()).contains("get_tld");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void test_noSubcommandSpecified_displaysAvailableCommands() throws Exception {
|
||||||
|
RegistryTool.main(new String[] {"-e", "unittest"});
|
||||||
|
assertThat(getStdout()).contains("The list of available subcommands is:");
|
||||||
|
assertThat(getStdout()).contains("login");
|
||||||
|
assertThat(getStdout()).contains("check_domain");
|
||||||
|
assertThat(getStdout()).contains("get_tld");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void test_noEnvironmentSpecified_throwsCorrectError() {
|
||||||
|
IllegalArgumentException thrown =
|
||||||
|
assertThrows(IllegalArgumentException.class, () -> RegistryTool.main(new String[] {}));
|
||||||
|
assertThat(thrown).hasMessageThat().contains("Please specify the environment flag");
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getStdout() {
|
||||||
|
return new String(stdout.toByteArray(), UTF_8);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue