mirror of
https://github.com/google/nomulus.git
synced 2025-05-01 20:47:52 +02:00
Overriding getter methods to change values is a bit overkill when these values are static (don't change based on internal state). Just setting them in the base class' constructor is simpler. Also, we can read the PATH of an Action based on the Annotation instead returning it manually for each Action. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=246135754
919 lines
32 KiB
Java
919 lines
32 KiB
Java
// Copyright 2017 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.rdap;
|
|
|
|
import static com.google.common.truth.Truth.assertThat;
|
|
import static google.registry.request.Action.Method.GET;
|
|
import static google.registry.testing.DatastoreHelper.createTld;
|
|
import static google.registry.testing.DatastoreHelper.persistResource;
|
|
import static google.registry.testing.DatastoreHelper.persistResources;
|
|
import static google.registry.testing.DatastoreHelper.persistSimpleResources;
|
|
import static google.registry.testing.FullFieldsTestEntityHelper.makeAndPersistHostResource;
|
|
import static google.registry.testing.FullFieldsTestEntityHelper.makeContactResource;
|
|
import static google.registry.testing.FullFieldsTestEntityHelper.makeDomainBase;
|
|
import static google.registry.testing.FullFieldsTestEntityHelper.makeHostResource;
|
|
import static google.registry.testing.FullFieldsTestEntityHelper.makeRegistrar;
|
|
import static google.registry.testing.FullFieldsTestEntityHelper.makeRegistrarContacts;
|
|
import static google.registry.testing.TestDataHelper.loadFile;
|
|
|
|
import com.google.common.collect.ImmutableList;
|
|
import com.google.common.collect.ImmutableListMultimap;
|
|
import com.google.common.collect.ImmutableMap;
|
|
import com.google.common.collect.ImmutableSet;
|
|
import com.googlecode.objectify.Key;
|
|
import google.registry.model.domain.DomainBase;
|
|
import google.registry.model.host.HostResource;
|
|
import google.registry.model.registrar.Registrar;
|
|
import google.registry.rdap.RdapMetrics.EndpointType;
|
|
import google.registry.rdap.RdapMetrics.SearchType;
|
|
import google.registry.rdap.RdapMetrics.WildcardType;
|
|
import google.registry.rdap.RdapSearchResults.IncompletenessWarningType;
|
|
import google.registry.testing.FakeResponse;
|
|
import java.net.URLDecoder;
|
|
import java.util.Optional;
|
|
import javax.annotation.Nullable;
|
|
import org.json.simple.JSONArray;
|
|
import org.json.simple.JSONObject;
|
|
import org.json.simple.JSONValue;
|
|
import org.junit.Before;
|
|
import org.junit.Test;
|
|
import org.junit.runner.RunWith;
|
|
import org.junit.runners.JUnit4;
|
|
|
|
/** Unit tests for {@link RdapNameserverSearchAction}. */
|
|
@RunWith(JUnit4.class)
|
|
public class RdapNameserverSearchActionTest
|
|
extends RdapSearchActionTestCase<RdapNameserverSearchAction> {
|
|
|
|
public RdapNameserverSearchActionTest() {
|
|
super(RdapNameserverSearchAction.class);
|
|
}
|
|
|
|
private DomainBase domainCatLol;
|
|
private HostResource hostNs1CatLol;
|
|
private HostResource hostNs2CatLol;
|
|
|
|
private Object generateActualJsonWithName(String name) {
|
|
return generateActualJsonWithName(name, null);
|
|
}
|
|
|
|
private Object generateActualJsonWithName(String name, String cursor) {
|
|
metricSearchType = SearchType.BY_NAMESERVER_NAME;
|
|
rememberWildcardType(name);
|
|
action.nameParam = Optional.of(name);
|
|
if (cursor == null) {
|
|
action.parameterMap = ImmutableListMultimap.of("name", name);
|
|
action.cursorTokenParam = Optional.empty();
|
|
} else {
|
|
action.parameterMap = ImmutableListMultimap.of("name", name, "cursor", cursor);
|
|
action.cursorTokenParam = Optional.of(cursor);
|
|
}
|
|
action.run();
|
|
return JSONValue.parse(response.getPayload());
|
|
}
|
|
|
|
private Object generateActualJsonWithIp(String ipString) {
|
|
return generateActualJsonWithIp(ipString, null);
|
|
}
|
|
|
|
private Object generateActualJsonWithIp(String ipString, String cursor) {
|
|
metricSearchType = SearchType.BY_NAMESERVER_ADDRESS;
|
|
action.parameterMap = ImmutableListMultimap.of("ip", ipString);
|
|
action.ipParam = Optional.of(ipString);
|
|
if (cursor == null) {
|
|
action.parameterMap = ImmutableListMultimap.of("ip", ipString);
|
|
action.cursorTokenParam = Optional.empty();
|
|
} else {
|
|
action.parameterMap = ImmutableListMultimap.of("ip", ipString, "cursor", cursor);
|
|
action.cursorTokenParam = Optional.of(cursor);
|
|
}
|
|
action.run();
|
|
return JSONValue.parse(response.getPayload());
|
|
}
|
|
|
|
@Before
|
|
public void setUp() {
|
|
// cat.lol and cat2.lol
|
|
createTld("lol");
|
|
Registrar registrar =
|
|
persistResource(
|
|
makeRegistrar("evilregistrar", "Yes Virginia <script>", Registrar.State.ACTIVE));
|
|
persistSimpleResources(makeRegistrarContacts(registrar));
|
|
hostNs1CatLol = makeAndPersistHostResource(
|
|
"ns1.cat.lol", "1.2.3.4", clock.nowUtc().minusYears(1));
|
|
hostNs2CatLol = makeAndPersistHostResource(
|
|
"ns2.cat.lol", "bad:f00d:cafe::15:beef", clock.nowUtc().minusYears(1));
|
|
makeAndPersistHostResource(
|
|
"ns1.cat2.lol", "1.2.3.3", "bad:f00d:cafe::15:beef", clock.nowUtc().minusYears(1));
|
|
makeAndPersistHostResource("ns1.cat.external", null, null, clock.nowUtc().minusYears(1));
|
|
|
|
// cat.みんな
|
|
createTld("xn--q9jyb4c");
|
|
registrar = persistResource(makeRegistrar("unicoderegistrar", "みんな", Registrar.State.ACTIVE));
|
|
persistSimpleResources(makeRegistrarContacts(registrar));
|
|
makeAndPersistHostResource("ns1.cat.みんな", "1.2.3.5", clock.nowUtc().minusYears(1));
|
|
|
|
// cat.1.test
|
|
createTld("1.test");
|
|
registrar = persistResource(makeRegistrar("multiregistrar", "1.test", Registrar.State.ACTIVE));
|
|
persistSimpleResources(makeRegistrarContacts(registrar));
|
|
makeAndPersistHostResource("ns1.cat.1.test", "1.2.3.6", clock.nowUtc().minusYears(1));
|
|
|
|
// create a domain so that we can use it as a test nameserver search string suffix
|
|
domainCatLol = persistResource(
|
|
makeDomainBase(
|
|
"cat.lol",
|
|
persistResource(
|
|
makeContactResource("5372808-ERL", "Goblin Market", "lol@cat.lol", registrar)),
|
|
persistResource(
|
|
makeContactResource("5372808-IRL", "Santa Claus", "BOFH@cat.lol", registrar)),
|
|
persistResource(
|
|
makeContactResource("5372808-TRL", "The Raven", "bog@cat.lol", registrar)),
|
|
hostNs1CatLol,
|
|
hostNs2CatLol,
|
|
registrar)
|
|
.asBuilder()
|
|
.setSubordinateHosts(ImmutableSet.of("ns1.cat.lol", "ns2.cat.lol"))
|
|
.build());
|
|
persistResource(
|
|
hostNs1CatLol.asBuilder().setSuperordinateDomain(Key.create(domainCatLol)).build());
|
|
persistResource(
|
|
hostNs2CatLol.asBuilder().setSuperordinateDomain(Key.create(domainCatLol)).build());
|
|
|
|
action.ipParam = Optional.empty();
|
|
action.nameParam = Optional.empty();
|
|
}
|
|
|
|
private Object generateExpectedJson(String expectedOutputFile) {
|
|
return generateExpectedJson(null, null, null, null, null, expectedOutputFile);
|
|
}
|
|
|
|
private Object generateExpectedJson(String name, String expectedOutputFile) {
|
|
return generateExpectedJson(name, null, null, null, null, expectedOutputFile);
|
|
}
|
|
|
|
private Object generateExpectedJson(
|
|
@Nullable String name,
|
|
@Nullable String punycodeName,
|
|
@Nullable String handle,
|
|
@Nullable String ipAddressType,
|
|
@Nullable String ipAddress,
|
|
String expectedOutputFile) {
|
|
ImmutableMap.Builder<String, String> builder = new ImmutableMap.Builder<>();
|
|
if (name != null) {
|
|
builder.put("NAME", name);
|
|
}
|
|
if ((name != null) || (punycodeName != null)) {
|
|
builder.put("PUNYCODENAME", (punycodeName == null) ? name : punycodeName);
|
|
}
|
|
if (handle != null) {
|
|
builder.put("HANDLE", handle);
|
|
}
|
|
if (ipAddressType != null) {
|
|
builder.put("ADDRESSTYPE", ipAddressType);
|
|
}
|
|
if (ipAddress != null) {
|
|
builder.put("ADDRESS", ipAddress);
|
|
}
|
|
builder.put("STATUS", "active");
|
|
builder.put("TYPE", "nameserver");
|
|
return JSONValue.parse(
|
|
loadFile(this.getClass(), expectedOutputFile, builder.build()));
|
|
}
|
|
|
|
private Object generateExpectedJsonForNameserver(
|
|
String name,
|
|
String punycodeName,
|
|
String handle,
|
|
String ipAddressType,
|
|
String ipAddress,
|
|
String expectedOutputFile) {
|
|
Object obj =
|
|
generateExpectedJson(
|
|
name, punycodeName, handle, ipAddressType, ipAddress, expectedOutputFile);
|
|
ImmutableMap.Builder<String, Object> builder = new ImmutableMap.Builder<>();
|
|
builder.put("nameserverSearchResults", ImmutableList.of(obj));
|
|
builder.put("rdapConformance", ImmutableList.of("icann_rdap_response_profile_0"));
|
|
RdapTestHelper.addNonDomainBoilerplateNotices(
|
|
builder, RdapTestHelper.createNotices("https://example.tld/rdap/"));
|
|
return builder.build();
|
|
}
|
|
|
|
private void createManyHosts(int numHosts) {
|
|
ImmutableList.Builder<HostResource> hostsBuilder = new ImmutableList.Builder<>();
|
|
ImmutableSet.Builder<String> subordinateHostsBuilder = new ImmutableSet.Builder<>();
|
|
for (int i = 1; i <= numHosts; i++) {
|
|
String hostName = String.format("nsx%d.cat.lol", i);
|
|
subordinateHostsBuilder.add(hostName);
|
|
hostsBuilder.add(makeHostResource(hostName, "5.5.5.1", "5.5.5.2"));
|
|
}
|
|
persistResources(hostsBuilder.build());
|
|
domainCatLol = persistResource(
|
|
domainCatLol.asBuilder()
|
|
.setSubordinateHosts(subordinateHostsBuilder.build())
|
|
.build());
|
|
}
|
|
|
|
private void createDeletedHost() {
|
|
persistResource(
|
|
makeAndPersistHostResource("nsdeleted.cat.lol", "4.3.2.1", clock.nowUtc().minusYears(1))
|
|
.asBuilder()
|
|
.setDeletionTime(clock.nowUtc().minusMonths(1))
|
|
.build());
|
|
}
|
|
|
|
private void verifyMetrics(long numHostsRetrieved) {
|
|
verifyMetrics(Optional.of(numHostsRetrieved), IncompletenessWarningType.COMPLETE);
|
|
}
|
|
|
|
private void verifyMetrics(
|
|
Optional<Long> numHostsRetrieved, IncompletenessWarningType incompletenessWarningType) {
|
|
verifyMetrics(
|
|
EndpointType.NAMESERVERS,
|
|
GET,
|
|
action.includeDeletedParam.orElse(false),
|
|
action.registrarParam.isPresent(),
|
|
Optional.empty(),
|
|
numHostsRetrieved,
|
|
Optional.empty(),
|
|
incompletenessWarningType);
|
|
}
|
|
|
|
private void verifyErrorMetrics() {
|
|
metricStatusCode = 404;
|
|
verifyMetrics(0);
|
|
}
|
|
|
|
private void verifyErrorMetrics(Optional<Long> numHostsRetrieved, int statusCode) {
|
|
metricStatusCode = statusCode;
|
|
verifyMetrics(numHostsRetrieved, IncompletenessWarningType.COMPLETE);
|
|
}
|
|
|
|
@Test
|
|
public void testInvalidPath_rejected() {
|
|
action.requestPath = actionPath + "/path";
|
|
action.run();
|
|
assertThat(response.getStatus()).isEqualTo(400);
|
|
verifyErrorMetrics(Optional.empty(), 400);
|
|
}
|
|
|
|
@Test
|
|
public void testInvalidRequest_rejected() {
|
|
action.run();
|
|
assertThat(JSONValue.parse(response.getPayload()))
|
|
.isEqualTo(
|
|
generateExpectedJson(
|
|
"You must specify either name=XXXX or ip=YYYY", "rdap_error_400.json"));
|
|
assertThat(response.getStatus()).isEqualTo(400);
|
|
verifyErrorMetrics(Optional.empty(), 400);
|
|
}
|
|
|
|
@Test
|
|
public void testInvalidSuffix_rejected() {
|
|
assertThat(generateActualJsonWithName("exam*ple"))
|
|
.isEqualTo(
|
|
generateExpectedJson(
|
|
"Suffix after wildcard must be one or more domain"
|
|
+ " name labels, e.g. exam*.tld, ns*.example.tld",
|
|
"rdap_error_422.json"));
|
|
assertThat(response.getStatus()).isEqualTo(422);
|
|
verifyErrorMetrics(Optional.empty(), 422);
|
|
}
|
|
|
|
@Test
|
|
public void testNonexistentDomainSuffix_unprocessable() {
|
|
assertThat(generateActualJsonWithName("exam*.foo.bar"))
|
|
.isEqualTo(
|
|
generateExpectedJson(
|
|
"A suffix after a wildcard in a nameserver lookup must be an in-bailiwick domain",
|
|
"rdap_error_422.json"));
|
|
assertThat(response.getStatus()).isEqualTo(422);
|
|
verifyErrorMetrics(Optional.empty(), 422);
|
|
}
|
|
|
|
@Test
|
|
public void testMultipleWildcards_rejected() {
|
|
assertThat(generateActualJsonWithName("*.*"))
|
|
.isEqualTo(generateExpectedJson("Only one wildcard allowed", "rdap_error_422.json"));
|
|
assertThat(response.getStatus()).isEqualTo(422);
|
|
verifyErrorMetrics(Optional.empty(), 422);
|
|
}
|
|
|
|
@Test
|
|
public void testNoCharactersToMatch_rejected() {
|
|
assertThat(generateActualJsonWithName("*"))
|
|
.isEqualTo(
|
|
generateExpectedJson(
|
|
"Initial search string must be at least 2 characters", "rdap_error_422.json"));
|
|
assertThat(response.getStatus()).isEqualTo(422);
|
|
verifyErrorMetrics(Optional.empty(), 422);
|
|
}
|
|
|
|
@Test
|
|
public void testFewerThanTwoCharactersToMatch_rejected() {
|
|
assertThat(generateActualJsonWithName("a*"))
|
|
.isEqualTo(
|
|
generateExpectedJson(
|
|
"Initial search string must be at least 2 characters", "rdap_error_422.json"));
|
|
assertThat(response.getStatus()).isEqualTo(422);
|
|
verifyErrorMetrics(Optional.empty(), 422);
|
|
}
|
|
|
|
@Test
|
|
public void testNameMatch_ns1_cat_lol_found() {
|
|
assertThat(generateActualJsonWithName("ns1.cat.lol"))
|
|
.isEqualTo(
|
|
generateExpectedJsonForNameserver(
|
|
"ns1.cat.lol", null, "2-ROID", "v4", "1.2.3.4", "rdap_host_linked.json"));
|
|
assertThat(response.getStatus()).isEqualTo(200);
|
|
verifyMetrics(1);
|
|
}
|
|
|
|
@Test
|
|
public void testNameMatch_ns1_cat_lol_foundWithUpperCase() {
|
|
assertThat(generateActualJsonWithName("Ns1.CaT.lOl"))
|
|
.isEqualTo(
|
|
generateExpectedJsonForNameserver(
|
|
"ns1.cat.lol", null, "2-ROID", "v4", "1.2.3.4", "rdap_host_linked.json"));
|
|
assertThat(response.getStatus()).isEqualTo(200);
|
|
verifyMetrics(1);
|
|
}
|
|
|
|
@Test
|
|
public void testNameMatch_ns1_cat_lol_found_sameRegistrarRequested() {
|
|
action.registrarParam = Optional.of("TheRegistrar");
|
|
generateActualJsonWithName("ns1.cat.lol");
|
|
assertThat(response.getStatus()).isEqualTo(200);
|
|
verifyMetrics(1);
|
|
}
|
|
|
|
@Test
|
|
public void testNameMatch_ns1_cat_lol_notFound_differentRegistrarRequested() {
|
|
action.registrarParam = Optional.of("unicoderegistrar");
|
|
generateActualJsonWithName("ns1.cat.lol");
|
|
assertThat(response.getStatus()).isEqualTo(404);
|
|
verifyErrorMetrics(Optional.of(0L), 404);
|
|
}
|
|
|
|
@Test
|
|
public void testNameMatch_ns2_cat_lol_found() {
|
|
assertThat(generateActualJsonWithName("ns2.cat.lol"))
|
|
.isEqualTo(generateExpectedJsonForNameserver(
|
|
"ns2.cat.lol",
|
|
null,
|
|
"4-ROID",
|
|
"v6",
|
|
"bad:f00d:cafe::15:beef",
|
|
"rdap_host_linked.json"));
|
|
assertThat(response.getStatus()).isEqualTo(200);
|
|
verifyMetrics(1);
|
|
}
|
|
|
|
@Test
|
|
public void testNameMatch_ns1_cat2_lol_found() {
|
|
// ns1.cat2.lol has two IP addresses; just test that we are able to find it
|
|
generateActualJsonWithName("ns1.cat2.lol");
|
|
assertThat(response.getStatus()).isEqualTo(200);
|
|
verifyMetrics(1);
|
|
}
|
|
|
|
@Test
|
|
public void testNameMatch_ns1_cat_external_found() {
|
|
assertThat(generateActualJsonWithName("ns1.cat.external"))
|
|
.isEqualTo(
|
|
generateExpectedJsonForNameserver(
|
|
"ns1.cat.external", null, "8-ROID", null, null, "rdap_host_external.json"));
|
|
assertThat(response.getStatus()).isEqualTo(200);
|
|
verifyMetrics(1);
|
|
}
|
|
|
|
@Test
|
|
public void testNameMatch_ns1_cat_idn_unicode_badRequest() {
|
|
// name must use punycode.
|
|
generateActualJsonWithName("ns1.cat.みんな");
|
|
metricWildcardType = WildcardType.INVALID;
|
|
metricPrefixLength = 0;
|
|
assertThat(response.getStatus()).isEqualTo(400);
|
|
verifyErrorMetrics(Optional.empty(), 400);
|
|
}
|
|
|
|
@Test
|
|
public void testNameMatch_ns1_cat_idn_punycode_found() {
|
|
assertThat(generateActualJsonWithName("ns1.cat.xn--q9jyb4c"))
|
|
.isEqualTo(
|
|
generateExpectedJsonForNameserver(
|
|
"ns1.cat.みんな",
|
|
"ns1.cat.xn--q9jyb4c",
|
|
"B-ROID",
|
|
"v4",
|
|
"1.2.3.5",
|
|
"rdap_host_unicode.json"));
|
|
assertThat(response.getStatus()).isEqualTo(200);
|
|
verifyMetrics(1);
|
|
}
|
|
|
|
@Test
|
|
public void testNameMatch_ns1_cat_1_test_found() {
|
|
assertThat(generateActualJsonWithName("ns1.cat.1.test"))
|
|
.isEqualTo(
|
|
generateExpectedJsonForNameserver(
|
|
"ns1.cat.1.test", null, "E-ROID", "v4", "1.2.3.6", "rdap_host.json"));
|
|
assertThat(response.getStatus()).isEqualTo(200);
|
|
verifyMetrics(1);
|
|
}
|
|
|
|
@Test
|
|
public void testNameMatch_nsstar_cat_lol_found() {
|
|
generateActualJsonWithName("ns*.cat.lol");
|
|
assertThat(response.getStatus()).isEqualTo(200);
|
|
verifyMetrics(2);
|
|
}
|
|
|
|
@Test
|
|
public void testNameMatch_nsstar_cat_lol_found_sameRegistrarRequested() {
|
|
action.registrarParam = Optional.of("TheRegistrar");
|
|
generateActualJsonWithName("ns*.cat.lol");
|
|
assertThat(response.getStatus()).isEqualTo(200);
|
|
verifyMetrics(2);
|
|
}
|
|
|
|
@Test
|
|
public void testNameMatch_nsstar_cat_lol_notFound_differentRegistrarRequested() {
|
|
action.registrarParam = Optional.of("unicoderegistrar");
|
|
generateActualJsonWithName("ns*.cat.lol");
|
|
assertThat(response.getStatus()).isEqualTo(404);
|
|
verifyErrorMetrics(Optional.of(2L), 404);
|
|
}
|
|
|
|
@Test
|
|
public void testNameMatch_nstar_cat_lol_found() {
|
|
generateActualJsonWithName("n*.cat.lol");
|
|
assertThat(response.getStatus()).isEqualTo(200);
|
|
verifyMetrics(2);
|
|
}
|
|
|
|
@Test
|
|
public void testNameMatch_star_cat_lol_found() {
|
|
generateActualJsonWithName("*.cat.lol");
|
|
assertThat(response.getStatus()).isEqualTo(200);
|
|
verifyMetrics(2);
|
|
}
|
|
|
|
@Test
|
|
public void testNameMatch_star_cat_lol_found_sameRegistrarRequested() {
|
|
action.registrarParam = Optional.of("TheRegistrar");
|
|
generateActualJsonWithName("*.cat.lol");
|
|
assertThat(response.getStatus()).isEqualTo(200);
|
|
verifyMetrics(2);
|
|
}
|
|
|
|
@Test
|
|
public void testNameMatch_star_cat_lol_notFound_differentRegistrarRequested() {
|
|
action.registrarParam = Optional.of("unicoderegistrar");
|
|
generateActualJsonWithName("*.cat.lol");
|
|
assertThat(response.getStatus()).isEqualTo(404);
|
|
verifyErrorMetrics(Optional.of(2L), 404);
|
|
}
|
|
|
|
@Test
|
|
public void testNameMatch_nsstar_found() {
|
|
generateActualJsonWithName("ns*");
|
|
assertThat(response.getStatus()).isEqualTo(200);
|
|
verifyMetrics(5);
|
|
}
|
|
|
|
@Test
|
|
public void testNameMatch_ns1_cat_lstar_found() {
|
|
generateActualJsonWithName("ns1.cat.l*");
|
|
assertThat(response.getStatus()).isEqualTo(200);
|
|
verifyMetrics(1);
|
|
}
|
|
|
|
@Test
|
|
public void testNameMatch_ns1_castar_found() {
|
|
generateActualJsonWithName("ns1.ca*");
|
|
assertThat(response.getStatus()).isEqualTo(200);
|
|
verifyMetrics(5);
|
|
}
|
|
|
|
@Test
|
|
public void testNameMatch_dogstar_notFound() {
|
|
generateActualJsonWithName("dog*");
|
|
assertThat(response.getStatus()).isEqualTo(404);
|
|
verifyErrorMetrics();
|
|
}
|
|
|
|
@Test
|
|
public void testNameMatch_nontruncatedResultSet() {
|
|
createManyHosts(4);
|
|
assertThat(generateActualJsonWithName("nsx*.cat.lol"))
|
|
.isEqualTo(generateExpectedJson("rdap_nontruncated_hosts.json"));
|
|
assertThat(response.getStatus()).isEqualTo(200);
|
|
verifyMetrics(4);
|
|
}
|
|
|
|
@Test
|
|
public void testNameMatch_truncatedResultSet() {
|
|
createManyHosts(5);
|
|
assertThat(generateActualJsonWithName("nsx*.cat.lol"))
|
|
.isEqualTo(
|
|
generateExpectedJson(
|
|
"name=nsx*.cat.lol&cursor=bnN4NC5jYXQubG9s", "rdap_truncated_hosts.json"));
|
|
assertThat(response.getStatus()).isEqualTo(200);
|
|
verifyMetrics(5);
|
|
}
|
|
|
|
@Test
|
|
public void testNameMatch_reallyTruncatedResultSet() {
|
|
createManyHosts(9);
|
|
assertThat(generateActualJsonWithName("nsx*.cat.lol"))
|
|
.isEqualTo(
|
|
generateExpectedJson(
|
|
"name=nsx*.cat.lol&cursor=bnN4NC5jYXQubG9s", "rdap_truncated_hosts.json"));
|
|
assertThat(response.getStatus()).isEqualTo(200);
|
|
// When searching names, we look for additional matches, in case some are not visible.
|
|
verifyMetrics(9);
|
|
}
|
|
|
|
@Test
|
|
public void testNameMatchDeletedHost_foundTheOtherHost() {
|
|
persistResource(
|
|
hostNs1CatLol.asBuilder().setDeletionTime(clock.nowUtc().minusDays(1)).build());
|
|
assertThat(generateActualJsonWithName("ns*.cat.lol"))
|
|
.isEqualTo(
|
|
generateExpectedJsonForNameserver(
|
|
"ns2.cat.lol",
|
|
null,
|
|
"4-ROID",
|
|
"v6",
|
|
"bad:f00d:cafe::15:beef",
|
|
"rdap_host_linked.json"));
|
|
assertThat(response.getStatus()).isEqualTo(200);
|
|
verifyMetrics(2);
|
|
}
|
|
|
|
@Test
|
|
public void testNameMatchDeletedHost_notFound() {
|
|
persistResource(hostNs1CatLol.asBuilder().setDeletionTime(clock.nowUtc().minusDays(1)).build());
|
|
assertThat(generateActualJsonWithName("ns1.cat.lol"))
|
|
.isEqualTo(generateExpectedJson("No nameservers found", "rdap_error_404.json"));
|
|
assertThat(response.getStatus()).isEqualTo(404);
|
|
verifyErrorMetrics();
|
|
}
|
|
|
|
@Test
|
|
public void testNameMatchDeletedHostWithWildcard_notFound() {
|
|
persistResource(hostNs1CatLol.asBuilder().setDeletionTime(clock.nowUtc().minusDays(1)).build());
|
|
assertThat(generateActualJsonWithName("cat.lo*"))
|
|
.isEqualTo(generateExpectedJson("No nameservers found", "rdap_error_404.json"));
|
|
assertThat(response.getStatus()).isEqualTo(404);
|
|
verifyErrorMetrics();
|
|
}
|
|
|
|
@Test
|
|
public void testNameMatchDeleted_notFound_includeDeletedNotSpecified() {
|
|
createDeletedHost();
|
|
generateActualJsonWithName("nsdeleted.cat.lol");
|
|
assertThat(response.getStatus()).isEqualTo(404);
|
|
verifyErrorMetrics();
|
|
}
|
|
|
|
@Test
|
|
public void testNameMatchDeleted_notFound_notLoggedIn() {
|
|
createDeletedHost();
|
|
action.includeDeletedParam = Optional.of(true);
|
|
generateActualJsonWithName("nsdeleted.cat.lol");
|
|
assertThat(response.getStatus()).isEqualTo(404);
|
|
verifyErrorMetrics();
|
|
}
|
|
|
|
@Test
|
|
public void testNameMatchDeleted_notFound_loggedInAsDifferentRegistrar() {
|
|
createDeletedHost();
|
|
action.includeDeletedParam = Optional.of(true);
|
|
login("unicoderegistrar");
|
|
generateActualJsonWithName("nsdeleted.cat.lol");
|
|
assertThat(response.getStatus()).isEqualTo(404);
|
|
verifyErrorMetrics(Optional.of(1L), 404);
|
|
}
|
|
|
|
@Test
|
|
public void testNameMatchDeleted_found_loggedInAsCorrectRegistrar() {
|
|
createDeletedHost();
|
|
action.includeDeletedParam = Optional.of(true);
|
|
login("TheRegistrar");
|
|
generateActualJsonWithName("nsdeleted.cat.lol");
|
|
assertThat(response.getStatus()).isEqualTo(200);
|
|
verifyMetrics(1);
|
|
}
|
|
|
|
@Test
|
|
public void testNameMatchDeleted_found_loggedInAsAdmin() {
|
|
createDeletedHost();
|
|
action.includeDeletedParam = Optional.of(true);
|
|
loginAsAdmin();
|
|
generateActualJsonWithName("nsdeleted.cat.lol");
|
|
assertThat(response.getStatus()).isEqualTo(200);
|
|
verifyMetrics(1);
|
|
}
|
|
|
|
@Test
|
|
public void testNameMatchDeleted_found_loggedInAndRequestingSameRegistrar() {
|
|
createDeletedHost();
|
|
action.registrarParam = Optional.of("TheRegistrar");
|
|
action.includeDeletedParam = Optional.of(true);
|
|
login("TheRegistrar");
|
|
generateActualJsonWithName("nsdeleted.cat.lol");
|
|
assertThat(response.getStatus()).isEqualTo(200);
|
|
verifyMetrics(1);
|
|
}
|
|
|
|
@Test
|
|
public void testNameMatchDeleted_notFound_loggedInButRequestingDifferentRegistrar() {
|
|
createDeletedHost();
|
|
action.registrarParam = Optional.of("unicoderegistrar");
|
|
action.includeDeletedParam = Optional.of(true);
|
|
login("TheRegistrar");
|
|
generateActualJsonWithName("nsdeleted.cat.lol");
|
|
assertThat(response.getStatus()).isEqualTo(404);
|
|
verifyErrorMetrics();
|
|
}
|
|
|
|
/**
|
|
* Checks multi-page result set navigation using the cursor.
|
|
*
|
|
* <p>If there are more results than the max result set size, the RDAP code returns a cursor token
|
|
* which can be used in a subsequent call to get the next chunk of results.
|
|
*
|
|
* @param byName true if we are searching by name; false if we are searching by address
|
|
* @param paramValue the query string
|
|
* @param expectedNames an immutable list of the host names we expect to retrieve
|
|
*/
|
|
private void checkCursorNavigation(
|
|
boolean byName, String paramValue, ImmutableList<String> expectedNames)
|
|
throws Exception {
|
|
String cursor = null;
|
|
int expectedNameOffset = 0;
|
|
int expectedPageCount =
|
|
(expectedNames.size() + action.rdapResultSetMaxSize - 1) / action.rdapResultSetMaxSize;
|
|
for (int pageNum = 0; pageNum < expectedPageCount; pageNum++) {
|
|
Object results =
|
|
byName
|
|
? generateActualJsonWithName(paramValue, cursor)
|
|
: generateActualJsonWithIp(paramValue, cursor);
|
|
assertThat(response.getStatus()).isEqualTo(200);
|
|
String linkToNext = RdapTestHelper.getLinkToNext(results);
|
|
if (pageNum == expectedPageCount - 1) {
|
|
assertThat(linkToNext).isNull();
|
|
} else {
|
|
assertThat(linkToNext).isNotNull();
|
|
int pos = linkToNext.indexOf("cursor=");
|
|
assertThat(pos).isAtLeast(0);
|
|
cursor = URLDecoder.decode(linkToNext.substring(pos + 7), "UTF-8");
|
|
Object searchResults = ((JSONObject) results).get("nameserverSearchResults");
|
|
assertThat(searchResults).isInstanceOf(JSONArray.class);
|
|
assertThat(((JSONArray) searchResults)).hasSize(action.rdapResultSetMaxSize);
|
|
for (Object item : ((JSONArray) searchResults)) {
|
|
assertThat(item).isInstanceOf(JSONObject.class);
|
|
Object name = ((JSONObject) item).get("ldhName");
|
|
assertThat(name).isNotNull();
|
|
assertThat(name).isInstanceOf(String.class);
|
|
assertThat(name).isEqualTo(expectedNames.get(expectedNameOffset++));
|
|
}
|
|
response = new FakeResponse();
|
|
action.response = response;
|
|
}
|
|
}
|
|
}
|
|
|
|
@Test
|
|
public void testNameMatch_cursorNavigationWithSuperordinateDomain() throws Exception {
|
|
createManyHosts(9);
|
|
checkCursorNavigation(
|
|
true,
|
|
"ns*.cat.lol",
|
|
ImmutableList.of(
|
|
"nsx1.cat.lol",
|
|
"nsx2.cat.lol",
|
|
"nsx3.cat.lol",
|
|
"nsx4.cat.lol",
|
|
"nsx5.cat.lol",
|
|
"nsx6.cat.lol",
|
|
"nsx7.cat.lol",
|
|
"nsx8.cat.lol",
|
|
"nsx9.cat.lol"));
|
|
}
|
|
|
|
@Test
|
|
public void testNameMatch_cursorNavigationWithPrefix() throws Exception {
|
|
createManyHosts(9);
|
|
checkCursorNavigation(
|
|
true,
|
|
"ns*",
|
|
ImmutableList.of(
|
|
"ns1.cat.1.test",
|
|
"ns1.cat.external",
|
|
"ns1.cat.lol",
|
|
"ns1.cat.xn--q9jyb4c",
|
|
"ns1.cat2.lol",
|
|
"ns2.cat.lol",
|
|
"nsx1.cat.lol",
|
|
"nsx2.cat.lol",
|
|
"nsx3.cat.lol",
|
|
"nsx4.cat.lol",
|
|
"nsx5.cat.lol",
|
|
"nsx6.cat.lol",
|
|
"nsx7.cat.lol",
|
|
"nsx8.cat.lol",
|
|
"nsx9.cat.lol"));
|
|
}
|
|
|
|
@Test
|
|
public void testAddressMatch_invalidAddress() {
|
|
generateActualJsonWithIp("It is to laugh");
|
|
assertThat(response.getStatus()).isEqualTo(400);
|
|
verifyErrorMetrics(Optional.empty(), 400);
|
|
}
|
|
|
|
@Test
|
|
public void testAddressMatchV4Address_found() {
|
|
assertThat(generateActualJsonWithIp("1.2.3.4"))
|
|
.isEqualTo(
|
|
generateExpectedJsonForNameserver(
|
|
"ns1.cat.lol", null, "2-ROID", "v4", "1.2.3.4", "rdap_host_linked.json"));
|
|
assertThat(response.getStatus()).isEqualTo(200);
|
|
verifyMetrics(1);
|
|
}
|
|
|
|
@Test
|
|
public void testAddressMatchV4Address_found_sameRegistrarRequested() {
|
|
action.registrarParam = Optional.of("TheRegistrar");
|
|
generateActualJsonWithIp("1.2.3.4");
|
|
assertThat(response.getStatus()).isEqualTo(200);
|
|
verifyMetrics(1);
|
|
}
|
|
|
|
@Test
|
|
public void testAddressMatchV4Address_notFound_differentRegistrarRequested() {
|
|
action.registrarParam = Optional.of("unicoderegistrar");
|
|
generateActualJsonWithIp("1.2.3.4");
|
|
assertThat(response.getStatus()).isEqualTo(404);
|
|
verifyErrorMetrics();
|
|
}
|
|
|
|
@Test
|
|
public void testAddressMatchV6Address_foundMultiple() {
|
|
assertThat(generateActualJsonWithIp("bad:f00d:cafe::15:beef"))
|
|
.isEqualTo(generateExpectedJson("rdap_multiple_hosts.json"));
|
|
assertThat(response.getStatus()).isEqualTo(200);
|
|
verifyMetrics(2);
|
|
}
|
|
|
|
@Test
|
|
public void testAddressMatchLocalhost_notFound() {
|
|
generateActualJsonWithIp("127.0.0.1");
|
|
assertThat(response.getStatus()).isEqualTo(404);
|
|
verifyErrorMetrics();
|
|
}
|
|
|
|
@Test
|
|
public void testAddressMatchDeletedHost_notFound() {
|
|
persistResource(hostNs1CatLol.asBuilder().setDeletionTime(clock.nowUtc().minusDays(1)).build());
|
|
assertThat(generateActualJsonWithIp("1.2.3.4"))
|
|
.isEqualTo(generateExpectedJson("No nameservers found", "rdap_error_404.json"));
|
|
assertThat(response.getStatus()).isEqualTo(404);
|
|
verifyErrorMetrics();
|
|
}
|
|
|
|
@Test
|
|
public void testAddressMatch_nontruncatedResultSet() {
|
|
createManyHosts(4);
|
|
assertThat(generateActualJsonWithIp("5.5.5.1"))
|
|
.isEqualTo(generateExpectedJson("rdap_nontruncated_hosts.json"));
|
|
assertThat(response.getStatus()).isEqualTo(200);
|
|
verifyMetrics(4);
|
|
}
|
|
|
|
@Test
|
|
public void testAddressMatch_truncatedResultSet() {
|
|
createManyHosts(5);
|
|
assertThat(generateActualJsonWithIp("5.5.5.1"))
|
|
.isEqualTo(
|
|
generateExpectedJson(
|
|
"ip=5.5.5.1&cursor=MTctUk9JRA%3D%3D", "rdap_truncated_hosts.json"));
|
|
assertThat(response.getStatus()).isEqualTo(200);
|
|
verifyMetrics(5);
|
|
}
|
|
|
|
@Test
|
|
public void testAddressMatch_reallyTruncatedResultSet() {
|
|
createManyHosts(9);
|
|
assertThat(generateActualJsonWithIp("5.5.5.1"))
|
|
.isEqualTo(
|
|
generateExpectedJson(
|
|
"ip=5.5.5.1&cursor=MTctUk9JRA%3D%3D", "rdap_truncated_hosts.json"));
|
|
assertThat(response.getStatus()).isEqualTo(200);
|
|
// When searching by address and not including deleted, we don't need to search for extra
|
|
// matches.
|
|
verifyMetrics(5);
|
|
}
|
|
|
|
@Test
|
|
public void testAddressMatchDeleted_notFound_includeDeletedNotSpecified() {
|
|
createDeletedHost();
|
|
generateActualJsonWithIp("4.3.2.1");
|
|
assertThat(response.getStatus()).isEqualTo(404);
|
|
verifyErrorMetrics();
|
|
}
|
|
|
|
@Test
|
|
public void testAddressMatchDeleted_notFound_notLoggedIn() {
|
|
createDeletedHost();
|
|
action.includeDeletedParam = Optional.of(true);
|
|
generateActualJsonWithIp("4.3.2.1");
|
|
assertThat(response.getStatus()).isEqualTo(404);
|
|
verifyErrorMetrics();
|
|
}
|
|
|
|
@Test
|
|
public void testAddressMatchDeleted_notFound_loggedInAsDifferentRegistrar() {
|
|
createDeletedHost();
|
|
action.includeDeletedParam = Optional.of(true);
|
|
login("unicoderegistrar");
|
|
generateActualJsonWithIp("4.3.2.1");
|
|
assertThat(response.getStatus()).isEqualTo(404);
|
|
verifyErrorMetrics(Optional.of(1L), 404);
|
|
}
|
|
|
|
@Test
|
|
public void testAddressMatchDeleted_found_loggedInAsCorrectRegistrar() {
|
|
createDeletedHost();
|
|
action.includeDeletedParam = Optional.of(true);
|
|
login("TheRegistrar");
|
|
generateActualJsonWithIp("4.3.2.1");
|
|
assertThat(response.getStatus()).isEqualTo(200);
|
|
verifyMetrics(1);
|
|
}
|
|
|
|
@Test
|
|
public void testAddressMatchDeleted_found_loggedInAsAdmin() {
|
|
createDeletedHost();
|
|
action.includeDeletedParam = Optional.of(true);
|
|
loginAsAdmin();
|
|
generateActualJsonWithIp("4.3.2.1");
|
|
assertThat(response.getStatus()).isEqualTo(200);
|
|
verifyMetrics(1);
|
|
}
|
|
|
|
@Test
|
|
public void testAddressMatchDeleted_found_loggedInAndRequestingSameRegisrar() {
|
|
createDeletedHost();
|
|
action.registrarParam = Optional.of("TheRegistrar");
|
|
action.includeDeletedParam = Optional.of(true);
|
|
login("TheRegistrar");
|
|
generateActualJsonWithIp("4.3.2.1");
|
|
assertThat(response.getStatus()).isEqualTo(200);
|
|
verifyMetrics(1);
|
|
}
|
|
|
|
@Test
|
|
public void testAddressMatchDeleted_notFound_loggedButRequestingDiffentRegistrar() {
|
|
createDeletedHost();
|
|
action.registrarParam = Optional.of("unicoderegistrar");
|
|
action.includeDeletedParam = Optional.of(true);
|
|
login("TheRegistrar");
|
|
generateActualJsonWithIp("4.3.2.1");
|
|
assertThat(response.getStatus()).isEqualTo(404);
|
|
verifyErrorMetrics();
|
|
}
|
|
|
|
@Test
|
|
public void testAddressMatch_cursorNavigation() throws Exception {
|
|
createManyHosts(9);
|
|
checkCursorNavigation(
|
|
false,
|
|
"5.5.5.1",
|
|
ImmutableList.of(
|
|
"nsx1.cat.lol",
|
|
"nsx2.cat.lol",
|
|
"nsx3.cat.lol",
|
|
"nsx4.cat.lol",
|
|
"nsx5.cat.lol",
|
|
"nsx6.cat.lol",
|
|
"nsx7.cat.lol",
|
|
"nsx8.cat.lol",
|
|
"nsx9.cat.lol"));
|
|
}
|
|
}
|