diff --git a/java/google/registry/flows/EppToolServlet.java b/java/google/registry/flows/EppToolServlet.java index 180484b47..9acbe1894 100644 --- a/java/google/registry/flows/EppToolServlet.java +++ b/java/google/registry/flows/EppToolServlet.java @@ -15,8 +15,7 @@ package google.registry.flows; import static google.registry.flows.EppServletUtils.handleEppCommandAndWriteResponse; - -import com.google.common.io.ByteStreams; +import static java.nio.charset.StandardCharsets.UTF_8; import google.registry.flows.SessionMetadata.SessionSource; import google.registry.model.eppcommon.ProtocolDefinition; @@ -42,9 +41,8 @@ public class EppToolServlet extends XsrfProtectedServlet { @Override protected void doPost(HttpServletRequest req, HttpServletResponse rsp) throws IOException { - byte[] xml = ByteStreams.toByteArray(req.getInputStream()); handleEppCommandAndWriteResponse( - xml, rsp, new StatelessRequestSessionMetadata( + req.getParameter("xml").getBytes(UTF_8), rsp, new StatelessRequestSessionMetadata( req.getParameter("clientIdentifier"), Boolean.parseBoolean(req.getParameter("superuser")), Boolean.parseBoolean(req.getParameter("dryRun")), diff --git a/java/google/registry/loadtest/BUILD b/java/google/registry/loadtest/BUILD index bf61090f7..848512f5d 100644 --- a/java/google/registry/loadtest/BUILD +++ b/java/google/registry/loadtest/BUILD @@ -17,6 +17,7 @@ java_library( deps = [ "//java/com/google/common/base", "//java/com/google/common/collect", + "//java/com/google/common/net", "//third_party/java/appengine:appengine-api", "//third_party/java/dagger", "//third_party/java/joda_time", @@ -24,8 +25,6 @@ java_library( "//third_party/java/objectify:objectify-v4_1", "//third_party/java/servlet/servlet_api", "//java/google/registry/config", - "//java/google/registry/flows", - "//java/google/registry/model", "//java/google/registry/request", "//java/google/registry/util", ], diff --git a/java/google/registry/loadtest/LoadTask.java b/java/google/registry/loadtest/LoadTask.java deleted file mode 100644 index 3b9ecd7ea..000000000 --- a/java/google/registry/loadtest/LoadTask.java +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 2016 The Domain Registry 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.loadtest; - -import static com.google.cloud.sql.jdbc.internal.Charsets.UTF_8; -import static google.registry.flows.EppController.handleEppCommand; - -import com.google.appengine.api.taskqueue.DeferredTask; - -import google.registry.flows.SessionMetadata.SessionSource; -import google.registry.flows.StatelessRequestSessionMetadata; -import google.registry.model.eppcommon.ProtocolDefinition; - -/** A task that executes a single EPP command. */ -public class LoadTask implements DeferredTask { - - private static final long serialVersionUID = -7541344556045675149L; - - private final String clientId; - private final String xml; - - LoadTask(String clientId, String xml) { - this.clientId = clientId; - this.xml = xml; - } - - @Override - public void run() { - handleEppCommand( - xml.getBytes(UTF_8), - new StatelessRequestSessionMetadata( - clientId, - false, - false, - ProtocolDefinition.getVisibleServiceExtensionUris(), - SessionSource.LOADTEST)); - } -} diff --git a/java/google/registry/loadtest/LoadTestAction.java b/java/google/registry/loadtest/LoadTestAction.java index a47b0670d..8ad58678e 100644 --- a/java/google/registry/loadtest/LoadTestAction.java +++ b/java/google/registry/loadtest/LoadTestAction.java @@ -16,19 +16,22 @@ package google.registry.loadtest; import static com.google.appengine.api.taskqueue.QueueConstants.maxTasksPerAdd; import static com.google.appengine.api.taskqueue.QueueFactory.getQueue; -import static com.google.appengine.api.taskqueue.TaskOptions.Builder.withPayload; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.collect.Lists.partition; import static com.google.common.collect.Lists.transform; import static google.registry.util.ResourceUtils.readResourceUtf8; +import static java.nio.charset.StandardCharsets.UTF_8; import static java.util.Arrays.asList; import static org.joda.time.DateTimeZone.UTC; import com.google.appengine.api.taskqueue.TaskOptions; import com.google.common.base.Function; +import com.google.common.base.Joiner; import com.google.common.collect.FluentIterable; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.Iterators; +import com.google.common.net.MediaType; import google.registry.config.RegistryEnvironment; import google.registry.request.Action; @@ -37,6 +40,8 @@ import google.registry.util.TaskEnqueuer; import org.joda.time.DateTime; +import java.io.UnsupportedEncodingException; +import java.net.URLEncoder; import java.util.Arrays; import java.util.Iterator; import java.util.List; @@ -278,12 +283,28 @@ public class LoadTestAction implements Runnable { for (int i = 0; i < xmls.size(); i++) { // Space tasks evenly within across a second. int offsetMillis = (int) (1000.0 / xmls.size() * i); - tasks.add(withPayload(new LoadTask(clientId, xmls.get(i))) - .etaMillis(start.plusMillis(offsetMillis).getMillis())); + tasks.add(TaskOptions.Builder.withUrl("/_dr/epptool") + .etaMillis(start.getMillis() + offsetMillis) + .payload( + Joiner.on('&').withKeyValueSeparator('=').join( + ImmutableMap.of( + "clientIdentifier", clientId, + "superuser", false, + "dryRun", false, + "xml", urlEncode(xmls.get(i)))), + MediaType.FORM_DATA.toString())); } return tasks.build(); } + private String urlEncode(String xml) { + try { + return URLEncoder.encode(xml, UTF_8.toString()); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + } + private void enqueue(List tasks) { List> chunks = partition(tasks, maxTasksPerAdd()); // Farm out tasks to multiple queues to work around queue qps quotas. diff --git a/java/google/registry/tools/EppToolCommand.java b/java/google/registry/tools/EppToolCommand.java index b10c1fe9f..981f2c604 100644 --- a/java/google/registry/tools/EppToolCommand.java +++ b/java/google/registry/tools/EppToolCommand.java @@ -20,7 +20,6 @@ import static com.google.common.base.Predicates.notNull; import static com.google.common.base.Strings.nullToEmpty; import static com.google.common.collect.Maps.filterValues; import static com.google.common.io.Resources.getResource; -import static google.registry.flows.EppServletUtils.APPLICATION_EPP_XML_UTF8; import static google.registry.model.registry.Registries.findTldForNameOrThrow; import static google.registry.tools.CommandUtilities.addHeader; import static google.registry.util.PreconditionsUtils.checkArgumentNotNull; @@ -29,9 +28,11 @@ import static java.nio.charset.StandardCharsets.UTF_8; import com.google.common.base.Joiner; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.Multimap; import com.google.common.net.InternetDomainName; +import com.google.common.net.MediaType; import com.google.template.soy.SoyFileSet; import com.google.template.soy.data.SoyRecord; import com.google.template.soy.parseinfo.SoyFileInfo; @@ -42,6 +43,7 @@ import com.beust.jcommander.Parameter; import google.registry.model.registrar.Registrar; import java.io.IOException; +import java.net.URLEncoder; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -144,11 +146,14 @@ abstract class EppToolCommand extends ConfirmingCommand implements ServerSideCom params.put("dryRun", dryRun); params.put("clientIdentifier", command.clientId); params.put("superuser", superuser); + params.put("xml", URLEncoder.encode(command.xml, UTF_8.toString())); + String requestBody = Joiner.on('&').withKeyValueSeparator('=') + .join(filterValues(params, notNull())); responses.add(nullToEmpty(connection.send( "/_dr/epptool", - filterValues(params, notNull()), - APPLICATION_EPP_XML_UTF8, - command.xml.getBytes(UTF_8)))); + ImmutableMap.of(), + MediaType.FORM_DATA, + requestBody.getBytes(UTF_8)))); } return responses.build(); } diff --git a/javatests/google/registry/tools/AllocateDomainCommandTest.java b/javatests/google/registry/tools/AllocateDomainCommandTest.java index d17f51662..49cf1b75b 100644 --- a/javatests/google/registry/tools/AllocateDomainCommandTest.java +++ b/javatests/google/registry/tools/AllocateDomainCommandTest.java @@ -18,7 +18,6 @@ import static com.google.common.io.BaseEncoding.base16; import static com.google.common.io.Resources.getResource; import static com.google.common.io.Resources.toByteArray; import static com.google.common.truth.Truth.assertThat; -import static google.registry.flows.EppServletUtils.APPLICATION_EPP_XML_UTF8; import static google.registry.flows.picker.FlowPicker.getFlowClass; import static google.registry.model.domain.DesignatedContact.Type.ADMIN; import static google.registry.model.domain.DesignatedContact.Type.BILLING; @@ -31,14 +30,8 @@ import static google.registry.testing.DatastoreHelper.persistActiveContact; import static google.registry.testing.DatastoreHelper.persistActiveHost; import static google.registry.testing.DatastoreHelper.persistResource; import static google.registry.util.DateTimeUtils.START_OF_TIME; -import static google.registry.util.ResourceUtils.readResourceUtf8; -import static google.registry.xml.XmlTestUtils.assertXmlEquals; -import static java.nio.charset.StandardCharsets.UTF_8; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; +import static google.registry.util.ResourceUtils.readResourceBytes; -import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.beust.jcommander.ParameterException; @@ -58,27 +51,16 @@ import google.registry.tools.ServerSideCommand.Connection; import org.joda.time.DateTime; import org.junit.Before; import org.junit.Test; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; import org.mockito.Mock; import java.io.IOException; -import java.util.List; /** Unit tests for {@link AllocateDomainCommand}. */ public class AllocateDomainCommandTest extends CommandTestCase { - private static final String EXPECTED_XML_ONE = - readResourceUtf8(AllocateDomainCommandTest.class, "testdata/allocate_domain.xml"); - private static final String EXPECTED_XML_TWO = - readResourceUtf8(AllocateDomainCommandTest.class, "testdata/allocate_domain2.xml"); - @Mock Connection connection; - @Captor - ArgumentCaptor xml; - @Before public void init() throws IOException { command.setConnection(connection); @@ -119,7 +101,6 @@ public class AllocateDomainCommandTest extends CommandTestCase params = ImmutableMap.of( - "dryRun", dryRun, - "clientIdentifier", clientId, - "superuser", true); - verify(connection, times(expectedXml.length)) - .send(eq("/_dr/epptool"), eq(params), eq(APPLICATION_EPP_XML_UTF8), xml.capture()); - - List allCapturedXml = xml.getAllValues(); - assertThat(allCapturedXml).hasSize(expectedXml.length); - int capturedXmlIndex = 0; - for (String expected : expectedXml) { - assertXmlEquals(expected, new String(allCapturedXml.get(capturedXmlIndex++), UTF_8)); - } + private EppToolVerifier eppVerifier() { + return new EppToolVerifier() + .withConnection(connection) + .withClientIdentifier("TheRegistrar") + .asSuperuser(); } @Test public void testSuccess() throws Exception { runCommand("--ids=1-TLD", "--force", "--superuser"); - // NB: These commands are all sent on behalf of the sponsoring registrar, in this case - // "TheRegistrar". - verifySent(false, "TheRegistrar", EXPECTED_XML_ONE); + // NB: These commands are sent as the sponsoring registrar, in this case "TheRegistrar". + eppVerifier().verifySent("allocate_domain.xml"); } @Test public void testSuccess_multiple() throws Exception { runCommand("--ids=1-TLD,2-TLD", "--force", "--superuser"); - verifySent(false, "TheRegistrar", EXPECTED_XML_ONE, EXPECTED_XML_TWO); + eppVerifier().verifySent("allocate_domain.xml", "allocate_domain2.xml"); } @Test public void testSuccess_dryRun() throws Exception { runCommand("--ids=1-TLD", "--dry_run", "--superuser"); - verifySent(true, "TheRegistrar", EXPECTED_XML_ONE); + eppVerifier().asDryRun().verifySent("allocate_domain.xml"); } @Test @@ -187,7 +158,8 @@ public class AllocateDomainCommandTest extends CommandTestCaseunmarshal(EXPECTED_XML_ONE.getBytes(UTF_8)))) - .isEqualTo(DomainAllocateFlow.class); + getFlowClass(EppXmlTransformer.unmarshal( + readResourceBytes(getClass(), "testdata/allocate_domain.xml").read()))) + .isEqualTo(DomainAllocateFlow.class); } } diff --git a/javatests/google/registry/tools/CreateAnchorTenantCommandTest.java b/javatests/google/registry/tools/CreateAnchorTenantCommandTest.java index 50a09da79..cdd465220 100644 --- a/javatests/google/registry/tools/CreateAnchorTenantCommandTest.java +++ b/javatests/google/registry/tools/CreateAnchorTenantCommandTest.java @@ -22,14 +22,15 @@ import com.beust.jcommander.ParameterException; import google.registry.model.registry.Registry; +import org.junit.Before; import org.junit.Test; /** Unit tests for {@link CreateAnchorTenantCommand}. */ public class CreateAnchorTenantCommandTest extends EppToolCommandTestCase { - @Override - void initEppToolCommandTestCase() { + @Before + public void initCommand() { command.passwordGenerator = new FakePasswordGenerator("abcdefghijklmnopqrstuvwxyz"); } @@ -37,35 +38,35 @@ public class CreateAnchorTenantCommandTest public void testSuccess() throws Exception { runCommandForced("--client=NewRegistrar", "--superuser", "--reason=anchor-tenant-test", "--contact=jd1234", "--domain_name=example.tld"); - eppVerifier().asSuperuser().verifySent("testdata/domain_create_anchor_tenant.xml"); + eppVerifier().asSuperuser().verifySent("domain_create_anchor_tenant.xml"); } @Test public void testSuccess_suppliedPassword() throws Exception { runCommandForced("--client=NewRegistrar", "--superuser", "--password=foo", "--reason=anchor-tenant-test", "--contact=jd1234", "--domain_name=example.tld"); - eppVerifier().asSuperuser().verifySent("testdata/domain_create_anchor_tenant_password.xml"); + eppVerifier().asSuperuser().verifySent("domain_create_anchor_tenant_password.xml"); } @Test public void testSuccess_multipleWordReason() throws Exception { runCommandForced("--client=NewRegistrar", "--superuser", "--reason=\"anchor tenant test\"", "--contact=jd1234", "--domain_name=example.tld"); - eppVerifier().asSuperuser().verifySent("testdata/domain_create_anchor_tenant_multiple_word_reason.xml"); + eppVerifier().asSuperuser().verifySent("domain_create_anchor_tenant_multiple_word_reason.xml"); } @Test public void testSuccess_noReason() throws Exception { runCommandForced("--client=NewRegistrar", "--superuser", "--contact=jd1234", "--domain_name=example.tld"); - eppVerifier().asSuperuser().verifySent("testdata/domain_create_anchor_tenant_no_reason.xml"); + eppVerifier().asSuperuser().verifySent("domain_create_anchor_tenant_no_reason.xml"); } @Test public void testSuccess_feeStandard() throws Exception { runCommandForced("--client=NewRegistrar", "--superuser", "--fee", "--reason=anchor-tenant-test", "--contact=jd1234", "--domain_name=example.tld"); - eppVerifier().asSuperuser().verifySent("testdata/domain_create_anchor_tenant_fee_standard.xml"); + eppVerifier().asSuperuser().verifySent("domain_create_anchor_tenant_fee_standard.xml"); } @Test @@ -78,7 +79,7 @@ public class CreateAnchorTenantCommandTest .build()); runCommandForced("--client=NewRegistrar", "--superuser", "--fee", "--reason=anchor-tenant-test", "--contact=jd1234", "--domain_name=premium.tld"); - eppVerifier().asSuperuser().verifySent("testdata/domain_create_anchor_tenant_fee_premium.xml"); + eppVerifier().asSuperuser().verifySent("domain_create_anchor_tenant_fee_premium.xml"); } @Test diff --git a/javatests/google/registry/tools/CreateContactCommandTest.java b/javatests/google/registry/tools/CreateContactCommandTest.java index bb629e232..4b7f4745b 100644 --- a/javatests/google/registry/tools/CreateContactCommandTest.java +++ b/javatests/google/registry/tools/CreateContactCommandTest.java @@ -16,14 +16,15 @@ package google.registry.tools; import com.beust.jcommander.ParameterException; +import org.junit.Before; import org.junit.Test; /** Unit tests for {@link CreateContactCommand}. */ public class CreateContactCommandTest extends EppToolCommandTestCase { - @Override - void initEppToolCommandTestCase() { + @Before + public void initCommand() { command.passwordGenerator = new FakePasswordGenerator("abcdefghijklmnopqrstuvwxyz"); } @@ -45,7 +46,7 @@ public class CreateContactCommandTest "--fax=+1.7035555556", "--email=jdoe@example.com", "--password=2fooBAR"); - eppVerifier().verifySent("testdata/contact_create_complete.xml"); + eppVerifier().verifySent("contact_create_complete.xml"); } @Test @@ -53,7 +54,7 @@ public class CreateContactCommandTest // Will never be the case, but tests that each field can be omitted. // Also tests the auto-gen password. runCommandForced("--client=NewRegistrar"); - eppVerifier().verifySent("testdata/contact_create_minimal.xml"); + eppVerifier().verifySent("contact_create_minimal.xml"); } @Test diff --git a/javatests/google/registry/tools/DeleteDomainCommandTest.java b/javatests/google/registry/tools/DeleteDomainCommandTest.java index ca5e13ecc..c3923bb56 100644 --- a/javatests/google/registry/tools/DeleteDomainCommandTest.java +++ b/javatests/google/registry/tools/DeleteDomainCommandTest.java @@ -25,28 +25,28 @@ public class DeleteDomainCommandTest extends EppToolCommandTestCase { @Test public void testSuccess_singleXmlCommand() throws Exception { - runCommandForced("--client=NewRegistrar", "xml"); - ImmutableMap params = ImmutableMap.of( - "clientIdentifier", "NewRegistrar", - "superuser", false, - "dryRun", false); - verify(connection) - .send(eq("/_dr/epptool"), eq(params), eq(APPLICATION_EPP_XML_UTF8), eq("xml".getBytes())); + // The choice of xml file is arbitrary. + runCommandForced( + "--client=NewRegistrar", + readResourceUtf8(getClass(), "testdata/contact_create.xml")); + eppVerifier().verifySent("contact_create.xml"); } @Test public void testSuccess_multipleXmlCommands() throws Exception { - runCommandForced("--client=NewRegistrar", "one", "two", "three"); - ImmutableMap params = ImmutableMap.of( - "clientIdentifier", "NewRegistrar", - "superuser", false, - "dryRun", false); - verify(connection) - .send(eq("/_dr/epptool"), eq(params), eq(APPLICATION_EPP_XML_UTF8), eq("one".getBytes())); - verify(connection) - .send(eq("/_dr/epptool"), eq(params), eq(APPLICATION_EPP_XML_UTF8), eq("two".getBytes())); - verify(connection) - .send(eq("/_dr/epptool"), eq(params), eq(APPLICATION_EPP_XML_UTF8), eq("three".getBytes())); + // The choice of xml files is arbitrary. + runCommandForced( + "--client=NewRegistrar", + readResourceUtf8(getClass(), "testdata/contact_create.xml"), + readResourceUtf8(getClass(), "testdata/domain_check.xml"), + readResourceUtf8(getClass(), "testdata/domain_check_fee.xml")); + eppVerifier().verifySent("contact_create.xml", "domain_check.xml", "domain_check_fee.xml"); } @Test diff --git a/javatests/google/registry/tools/EppToolCommandTestCase.java b/javatests/google/registry/tools/EppToolCommandTestCase.java index aca5f6aab..b7b6f9c7a 100644 --- a/javatests/google/registry/tools/EppToolCommandTestCase.java +++ b/javatests/google/registry/tools/EppToolCommandTestCase.java @@ -14,30 +14,13 @@ package google.registry.tools; -import static com.google.common.truth.Truth.assertThat; -import static google.registry.flows.EppServletUtils.APPLICATION_EPP_XML_UTF8; import static google.registry.testing.DatastoreHelper.createTlds; -import static google.registry.util.ResourceUtils.readResourceUtf8; -import static google.registry.xml.XmlTestUtils.assertXmlEquals; -import static java.nio.charset.StandardCharsets.UTF_8; -import static java.util.Arrays.binarySearch; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import com.google.common.collect.ImmutableMap; - -import google.registry.testing.InjectRule; import google.registry.tools.ServerSideCommand.Connection; import org.junit.Before; -import org.junit.Rule; -import org.mockito.ArgumentCaptor; -import org.mockito.Captor; import org.mockito.Mock; -import java.util.List; - /** * Abstract class for commands that construct + send EPP commands. * @@ -45,70 +28,18 @@ import java.util.List; */ public abstract class EppToolCommandTestCase extends CommandTestCase { - @Rule - public InjectRule inject = new InjectRule(); - @Mock Connection connection; - @Captor - ArgumentCaptor xml; - @Before public void init() throws Exception { // Create two TLDs for commands that allow multiple TLDs at once. createTlds("tld", "tld2"); command.setConnection(connection); - initEppToolCommandTestCase(); } - /** Subclasses can override this to perform additional initialization. */ - void initEppToolCommandTestCase() throws Exception {} - - /** Helper to get a new {@link EppVerifier} instance. */ - EppVerifier eppVerifier() { - return new EppVerifier("NewRegistrar", false, false); - } - - /** Class for verifying EPP commands sent to the server. */ - class EppVerifier { - - private final String clientIdentifier; - private final boolean superuser; - private final boolean dryRun; - - private EppVerifier(String clientIdentifier, boolean superuser, boolean dryRun) { - this.clientIdentifier = clientIdentifier; - this.superuser = superuser; - this.dryRun = dryRun; - } - - EppVerifier setClientIdentifier(String clientIdentifier) { - return new EppVerifier(clientIdentifier, superuser, dryRun); - } - - EppVerifier asSuperuser() { - return new EppVerifier(clientIdentifier, true, dryRun); - } - - EppVerifier asDryRun() { - return new EppVerifier(clientIdentifier, superuser, true); - } - - void verifySent(String... filesToMatch) throws Exception { - ImmutableMap params = ImmutableMap.of( - "clientIdentifier", clientIdentifier, - "superuser", superuser, - "dryRun", dryRun); - verify(connection, times(filesToMatch.length)) - .send(eq("/_dr/epptool"), eq(params), eq(APPLICATION_EPP_XML_UTF8), xml.capture()); - List capturedXml = xml.getAllValues(); - assertThat(filesToMatch).hasLength(capturedXml.size()); - for (String fileToMatch : filesToMatch) { - assertXmlEquals( - readResourceUtf8(getClass(), fileToMatch), - new String(capturedXml.get(binarySearch(filesToMatch, fileToMatch)), UTF_8)); - } - } + /** Helper to get a new {@link EppToolVerifier} instance. */ + EppToolVerifier eppVerifier() { + return new EppToolVerifier().withConnection(connection).withClientIdentifier("NewRegistrar"); } } diff --git a/javatests/google/registry/tools/EppToolVerifier.java b/javatests/google/registry/tools/EppToolVerifier.java new file mode 100644 index 000000000..5c37e1277 --- /dev/null +++ b/javatests/google/registry/tools/EppToolVerifier.java @@ -0,0 +1,97 @@ +// Copyright 2016 The Domain Registry 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.collect.Iterables.pairUp; +import static com.google.common.truth.Truth.assertThat; +import static google.registry.util.ResourceUtils.readResourceUtf8; +import static google.registry.xml.XmlTestUtils.assertXmlEquals; +import static java.nio.charset.StandardCharsets.UTF_8; +import static java.util.Arrays.asList; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import com.google.common.base.Pair; +import com.google.common.base.Splitter; +import com.google.common.collect.ImmutableMap; +import com.google.common.net.MediaType; + +import google.registry.tools.ServerSideCommand.Connection; + +import org.mockito.ArgumentCaptor; + +import java.net.URLDecoder; +import java.util.List; +import java.util.Map; + +/** Class for verifying EPP commands sent to the server via the tool endpoint. */ +public class EppToolVerifier { + + private final Connection connection; + private final String clientIdentifier; + private final boolean superuser; + private final boolean dryRun; + + public EppToolVerifier() { + this(null, null, false, false); + } + + private EppToolVerifier( + Connection connection, String clientIdentifier, boolean superuser, boolean dryRun) { + this.connection = connection; + this.clientIdentifier = clientIdentifier; + this.superuser = superuser; + this.dryRun = dryRun; + } + + EppToolVerifier withConnection(Connection connection) { + return new EppToolVerifier(connection, clientIdentifier, superuser, dryRun); + } + + EppToolVerifier withClientIdentifier(String clientIdentifier) { + return new EppToolVerifier(connection, clientIdentifier, superuser, dryRun); + } + + EppToolVerifier asSuperuser() { + return new EppToolVerifier(connection, clientIdentifier, true, dryRun); + } + + EppToolVerifier asDryRun() { + return new EppToolVerifier(connection, clientIdentifier, superuser, true); + } + + void verifySent(String... xmlToMatch) throws Exception { + ArgumentCaptor params = ArgumentCaptor.forClass(byte[].class); + verify(connection, times(xmlToMatch.length)).send( + eq("/_dr/epptool"), + eq(ImmutableMap.of()), + eq(MediaType.FORM_DATA), + params.capture()); + List capturedParams = params.getAllValues(); + assertThat(capturedParams).hasSize(xmlToMatch.length); + for (Pair xmlAndParams : pairUp(asList(xmlToMatch), capturedParams)) { + Map map = Splitter.on('&').withKeyValueSeparator('=') + .split(new String(xmlAndParams.getSecond(), UTF_8)); + assertThat(map).hasSize(4); + assertXmlEquals( + readResourceUtf8(getClass(), "testdata/" + xmlAndParams.getFirst()), + URLDecoder.decode(map.get("xml"), UTF_8.toString())); + assertThat(map).containsEntry("dryRun", Boolean.toString(dryRun)); + assertThat(map).containsEntry("clientIdentifier", clientIdentifier); + assertThat(map).containsEntry("superuser", Boolean.toString(superuser)); + } + } +} diff --git a/javatests/google/registry/tools/ExecuteEppCommandTest.java b/javatests/google/registry/tools/ExecuteEppCommandTest.java index 9ba490db0..d58c144e2 100644 --- a/javatests/google/registry/tools/ExecuteEppCommandTest.java +++ b/javatests/google/registry/tools/ExecuteEppCommandTest.java @@ -19,6 +19,10 @@ import static java.nio.charset.StandardCharsets.UTF_8; import com.beust.jcommander.ParameterException; +import google.registry.testing.InjectRule; + +import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import java.io.ByteArrayInputStream; @@ -26,11 +30,14 @@ import java.io.ByteArrayInputStream; /** Unit tests for {@link ExecuteEppCommand}. */ public class ExecuteEppCommandTest extends EppToolCommandTestCase { + @Rule + public InjectRule inject = new InjectRule(); + private String xmlInput; private String eppFile; - @Override - void initEppToolCommandTestCase() throws Exception { + @Before + public void initCommand() throws Exception { xmlInput = readResourceUtf8(ExecuteEppCommandTest.class, "testdata/contact_create.xml"); eppFile = writeToNamedTmpFile("eppFile", xmlInput); } @@ -38,19 +45,19 @@ public class ExecuteEppCommandTest extends EppToolCommandTestCase