diff --git a/core/src/main/java/google/registry/model/EppResourceUtils.java b/core/src/main/java/google/registry/model/EppResourceUtils.java index 4eeeb5553..fc58cd0e3 100644 --- a/core/src/main/java/google/registry/model/EppResourceUtils.java +++ b/core/src/main/java/google/registry/model/EppResourceUtils.java @@ -194,30 +194,6 @@ public final class EppResourceUtils { return ForeignKeyIndex.load(clazz, uniqueIds, now).keySet(); } - /** - * Loads resources that match some filter and that have {@link EppResource#deletionTime} that is - * not before "now". - * - *

This is an eventually consistent query. - * - * @param clazz the resource type to load - * @param now the logical time of the check - * @param filterDefinition the filter to apply when loading resources - * @param filterValue the acceptable value for the filter - */ - public static Iterable queryNotDeleted( - Class clazz, DateTime now, String filterDefinition, Object filterValue) { - return ofy() - .load() - .type(clazz) - .filter(filterDefinition, filterValue) - .filter("deletionTime >", now.toDate()) - .list() - .stream() - .map(EppResourceUtils.transformAtTime(now)) - .collect(toImmutableSet()); - } - /** * Returns a Function that transforms an EppResource to the given DateTime, suitable for use with * Iterables.transform() over a collection of EppResources. diff --git a/core/src/main/java/google/registry/model/index/ForeignKeyIndex.java b/core/src/main/java/google/registry/model/index/ForeignKeyIndex.java index 0629381e9..4d1d1200d 100644 --- a/core/src/main/java/google/registry/model/index/ForeignKeyIndex.java +++ b/core/src/main/java/google/registry/model/index/ForeignKeyIndex.java @@ -48,8 +48,10 @@ import google.registry.model.contact.ContactResource; import google.registry.model.domain.DomainBase; import google.registry.model.host.HostResource; import google.registry.persistence.VKey; +import google.registry.persistence.transaction.CriteriaQueryBuilder; import google.registry.schema.replay.DatastoreOnlyEntity; import google.registry.util.NonFinalForTesting; +import java.util.Collection; import java.util.Comparator; import java.util.Map; import java.util.Optional; @@ -193,7 +195,7 @@ public abstract class ForeignKeyIndex extends BackupGroup * has been soft deleted. */ public static ImmutableMap> load( - Class clazz, Iterable foreignKeys, final DateTime now) { + Class clazz, Collection foreignKeys, final DateTime now) { return loadIndexesFromStore(clazz, foreignKeys).entrySet().stream() .filter(e -> now.isBefore(e.getValue().getDeletionTime())) .collect(entriesToImmutableMap()); @@ -207,7 +209,7 @@ public abstract class ForeignKeyIndex extends BackupGroup */ private static ImmutableMap> loadIndexesFromStore( - Class clazz, Iterable foreignKeys) { + Class clazz, Collection foreignKeys) { if (tm().isOfy()) { return ImmutableMap.copyOf( tm().doTransactionless(() -> ofy().load().type(mapToFkiClass(clazz)).ids(foreignKeys))); @@ -215,19 +217,16 @@ public abstract class ForeignKeyIndex extends BackupGroup String property = RESOURCE_CLASS_TO_FKI_PROPERTY.get(clazz); ImmutableList> indexes = tm().transact( - () -> { - String entityName = - jpaTm().getEntityManager().getMetamodel().entity(clazz).getName(); - return jpaTm() - .query( - String.format( - "FROM %s WHERE %s IN :propertyValue", entityName, property), - clazz) - .setParameter("propertyValue", foreignKeys) - .getResultStream() - .map(e -> ForeignKeyIndex.create(e, e.getDeletionTime())) - .collect(toImmutableList()); - }); + () -> + jpaTm() + .getEntityManager() + .createQuery( + CriteriaQueryBuilder.create(clazz) + .whereFieldIsIn(property, foreignKeys) + .build()) + .getResultStream() + .map(e -> ForeignKeyIndex.create(e, e.getDeletionTime())) + .collect(toImmutableList())); // We need to find and return the entities with the maximum deletionTime for each foreign key. return Multimaps.index(indexes, ForeignKeyIndex::getForeignKey).asMap().entrySet().stream() .map( @@ -318,7 +317,7 @@ public abstract class ForeignKeyIndex extends BackupGroup * reasons, and are OK with the trade-offs in loss of transactional consistency. */ public static ImmutableMap> loadCached( - Class clazz, Iterable foreignKeys, final DateTime now) { + Class clazz, Collection foreignKeys, final DateTime now) { if (!RegistryConfig.isEppResourceCachingEnabled()) { return tm().doTransactionless(() -> load(clazz, foreignKeys, now)); } diff --git a/core/src/main/java/google/registry/whois/NameserverLookupByIpCommand.java b/core/src/main/java/google/registry/whois/NameserverLookupByIpCommand.java index b973e9bf2..163312409 100644 --- a/core/src/main/java/google/registry/whois/NameserverLookupByIpCommand.java +++ b/core/src/main/java/google/registry/whois/NameserverLookupByIpCommand.java @@ -16,12 +16,15 @@ package google.registry.whois; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.collect.ImmutableList.toImmutableList; -import static google.registry.model.EppResourceUtils.queryNotDeleted; +import static google.registry.model.ofy.ObjectifyService.ofy; +import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm; +import static google.registry.persistence.transaction.TransactionManagerFactory.tm; import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND; import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableList; import com.google.common.collect.Streams; +import com.google.common.net.InetAddresses; import com.google.common.net.InternetDomainName; import google.registry.model.host.HostResource; import google.registry.model.registry.Registries; @@ -46,9 +49,34 @@ final class NameserverLookupByIpCommand implements WhoisCommand { } @Override + @SuppressWarnings("unchecked") public WhoisResponse executeQuery(DateTime now) throws WhoisException { + Iterable hostsFromDb; + if (tm().isOfy()) { + hostsFromDb = + ofy() + .load() + .type(HostResource.class) + .filter("inetAddresses", ipAddress) + .filter("deletionTime >", now.toDate()); + } else { + hostsFromDb = + jpaTm() + .transact( + () -> + // We cannot query @Convert-ed fields in HQL so we must use native Postgres + jpaTm() + .getEntityManager() + .createNativeQuery( + "SELECT * From \"Host\" WHERE :address = ANY(inet_addresses) AND " + + "deletion_time > CAST(:now AS timestamptz)", + HostResource.class) + .setParameter("address", InetAddresses.toAddrString(ipAddress)) + .setParameter("now", now.toString()) + .getResultList()); + } ImmutableList hosts = - Streams.stream(queryNotDeleted(HostResource.class, now, "inetAddresses", ipAddress)) + Streams.stream(hostsFromDb) .filter( host -> Registries.findTldForName(InternetDomainName.from(host.getHostName())) diff --git a/core/src/test/java/google/registry/testing/FullFieldsTestEntityHelper.java b/core/src/test/java/google/registry/testing/FullFieldsTestEntityHelper.java index 6987f21a9..0588cd6e8 100644 --- a/core/src/test/java/google/registry/testing/FullFieldsTestEntityHelper.java +++ b/core/src/test/java/google/registry/testing/FullFieldsTestEntityHelper.java @@ -218,27 +218,20 @@ public final class FullFieldsTestEntityHelper { .setCountryCode("US") .build()); } - ContactResource.Builder builder = new ContactResource.Builder() - .setContactId(id) - .setRepoId(generateNewContactHostRoid()) - .setCreationTimeForTest(DateTime.parse("2000-10-08T00:45:00Z")) - .setInternationalizedPostalInfo(postalBuilder.build()) - .setVoiceNumber( - new ContactPhoneNumber.Builder() - .setPhoneNumber("+1.2126660420") - .build()) - .setFaxNumber( - new ContactPhoneNumber.Builder() - .setPhoneNumber("+1.2126660420") - .build()); + ContactResource.Builder builder = + new ContactResource.Builder() + .setContactId(id) + .setRepoId(generateNewContactHostRoid()) + .setCreationTimeForTest(DateTime.parse("2000-10-08T00:45:00Z")) + .setInternationalizedPostalInfo(postalBuilder.build()) + .setVoiceNumber( + new ContactPhoneNumber.Builder().setPhoneNumber("+1.2126660420").build()) + .setFaxNumber(new ContactPhoneNumber.Builder().setPhoneNumber("+1.2126660420").build()); if (email != null) { builder.setEmailAddress(email); } - if (registrar != null) { - builder - .setCreationClientId(registrar.getClientId()) - .setPersistedCurrentSponsorClientId(registrar.getClientId()); - } + String registrarId = registrar == null ? "TheRegistrar" : registrar.getClientId(); + builder.setCreationClientId(registrarId).setPersistedCurrentSponsorClientId(registrarId); if (deletionTime != null) { builder.setDeletionTime(deletionTime); } diff --git a/core/src/test/java/google/registry/whois/WhoisActionTest.java b/core/src/test/java/google/registry/whois/WhoisActionTest.java index ea57f6783..676a8e60e 100644 --- a/core/src/test/java/google/registry/whois/WhoisActionTest.java +++ b/core/src/test/java/google/registry/whois/WhoisActionTest.java @@ -54,11 +54,13 @@ import google.registry.model.registry.Registry; import google.registry.model.transfer.DomainTransferData; import google.registry.model.transfer.TransferStatus; import google.registry.testing.AppEngineExtension; +import google.registry.testing.DualDatabaseTest; import google.registry.testing.FakeClock; import google.registry.testing.FakeResponse; import google.registry.testing.FakeSleeper; import google.registry.testing.InjectExtension; import google.registry.testing.TestCacheExtension; +import google.registry.testing.TestOfyAndSql; import google.registry.util.Retrier; import google.registry.whois.WhoisMetrics.WhoisMetric; import java.io.IOException; @@ -68,15 +70,17 @@ import org.joda.time.DateTime; import org.joda.time.Duration; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; /** Unit tests for {@link WhoisAction}. */ +@DualDatabaseTest public class WhoisActionTest { + private final FakeClock clock = new FakeClock(DateTime.parse("2009-06-29T20:13:00Z")); + @RegisterExtension public final AppEngineExtension appEngine = - AppEngineExtension.builder().withDatastoreAndCloudSql().build(); + AppEngineExtension.builder().withDatastoreAndCloudSql().withClock(clock).build(); @RegisterExtension public final InjectExtension inject = new InjectExtension(); @@ -88,7 +92,6 @@ public class WhoisActionTest { .build(); private final FakeResponse response = new FakeResponse(); - private FakeClock clock; private WhoisAction newWhoisAction(String input) { WhoisAction whoisAction = new WhoisAction(); @@ -107,12 +110,11 @@ public class WhoisActionTest { @BeforeEach void setUp() { - clock = new FakeClock(DateTime.parse("2009-06-29T20:13:00Z")); createTlds("lol", "xn--q9jyb4c", "1.test"); inject.setStaticField(Ofy.class, "clock", clock); } - @Test + @TestOfyAndSql void testRun_badRequest_stillSends200() { newWhoisAction("\r\n").run(); assertThat(response.getStatus()).isEqualTo(200); @@ -130,7 +132,7 @@ public class WhoisActionTest { registrar); } - @Test + @TestOfyAndSql void testRun_domainQuery_works() { Registrar registrar = persistResource(makeRegistrar("evilregistrar", "Yes Virginia", ACTIVE)); @@ -141,7 +143,7 @@ public class WhoisActionTest { assertThat(response.getPayload()).isEqualTo(loadFile("whois_action_domain.txt")); } - @Test + @TestOfyAndSql void testRun_domainQuery_usesCache() { Registrar registrar = persistResource(makeRegistrar("evilregistrar", "Yes Virginia", ACTIVE)); @@ -169,7 +171,7 @@ public class WhoisActionTest { assertThat(response.getPayload()).isEqualTo(loadFile("whois_action_domain.txt")); } - @Test + @TestOfyAndSql void testRun_domainAfterTransfer_hasUpdatedEppTimeAndClientId() { Registrar registrar = persistResource(makeRegistrar("TheRegistrar", "Yes Virginia", ACTIVE)); persistResource( @@ -194,7 +196,7 @@ public class WhoisActionTest { assertThat(response.getPayload()).isEqualTo(loadFile("whois_action_transferred_domain.txt")); } - @Test + @TestOfyAndSql void testRun_idnDomain_works() { Registrar registrar = persistResource(makeRegistrar( "evilregistrar", "Yes Virginia", ACTIVE)); @@ -212,7 +214,7 @@ public class WhoisActionTest { assertThat(response.getPayload()).isEqualTo(loadFile("whois_action_idn_punycode.txt")); } - @Test + @TestOfyAndSql void testRun_punycodeDomain_works() { Registrar registrar = persistResource(makeRegistrar( "evilregistrar", "Yes Virginia", ACTIVE)); @@ -230,14 +232,14 @@ public class WhoisActionTest { assertThat(response.getPayload()).isEqualTo(loadFile("whois_action_idn_punycode.txt")); } - @Test + @TestOfyAndSql void testRun_domainNotFound_returns200OkAndPlainTextResponse() { newWhoisAction("domain cat.lol\r\n").run(); assertThat(response.getStatus()).isEqualTo(200); assertThat(response.getPayload()).isEqualTo(loadFile("whois_action_domain_not_found.txt")); } - @Test + @TestOfyAndSql void testRun_domainNotFound_usesCache() { // Populate the cache with the nonexistence of this domain. assertThat(loadByForeignKeyCached(DomainBase.class, "cat.lol", clock.nowUtc())).isEmpty(); @@ -250,7 +252,7 @@ public class WhoisActionTest { // todo (b/27378695): reenable or delete this test @Disabled - @Test + @TestOfyAndSql void testRun_domainInTestTld_isConsideredNotFound() { persistResource(Registry.get("lol").asBuilder().setTldType(Registry.TldType.TEST).build()); Registrar registrar = persistResource(makeRegistrar( @@ -269,7 +271,7 @@ public class WhoisActionTest { assertThat(response.getPayload()).isEqualTo(loadFile("whois_action_domain_not_found.txt")); } - @Test + @TestOfyAndSql void testRun_domainFlaggedAsDeletedInDatastore_isConsideredNotFound() { Registrar registrar; persistResource(makeDomainBase("cat.lol", @@ -294,7 +296,7 @@ public class WhoisActionTest { * Create a deleted domain and an active domain with the same label, and make sure only the active * one is returned. */ - @Test + @TestOfyAndSql void testRun_domainDeletedThenRecreated_isFound() { Registrar registrar; DomainBase domain1 = persistResource(makeDomainBase("cat.lol", @@ -330,7 +332,7 @@ public class WhoisActionTest { assertThat(response.getPayload()).contains("ns1.google.lol"); } - @Test + @TestOfyAndSql void testRun_nameserverQuery_works() { persistResource(loadRegistrar("TheRegistrar").asBuilder().setUrl("http://my.fake.url").build()); persistResource(makeHostResource("ns1.cat.lol", "1.2.3.4")); @@ -339,7 +341,7 @@ public class WhoisActionTest { assertThat(response.getPayload()).isEqualTo(loadFile("whois_action_nameserver.txt")); } - @Test + @TestOfyAndSql void testRun_ipv6_displaysInCollapsedReadableFormat() { persistResource(makeHostResource("ns1.cat.lol", "bad:f00d:cafe::15:beef")); newWhoisAction("nameserver ns1.cat.lol\r\n").run(); @@ -350,7 +352,7 @@ public class WhoisActionTest { assertThat(response.getPayload()).doesNotContain("bad:f00d:cafe:0:0:0:15:beef"); } - @Test + @TestOfyAndSql void testRun_idnNameserver_works() { persistResource(makeHostResource("ns1.cat.みんな", "1.2.3.4")); newWhoisAction("nameserver ns1.cat.みんな\r\n").run(); @@ -359,7 +361,7 @@ public class WhoisActionTest { assertThat(response.getPayload()).contains("1.2.3.4"); } - @Test + @TestOfyAndSql void testRun_nameserver_usesCache() { persistResource(makeHostResource("ns1.cat.xn--q9jyb4c", "1.2.3.4")); // Populate the cache. @@ -376,7 +378,7 @@ public class WhoisActionTest { assertThat(response.getPayload()).contains("1.2.3.4"); } - @Test + @TestOfyAndSql void testRun_punycodeNameserver_works() { persistResource(makeHostResource("ns1.cat.みんな", "1.2.3.4")); newWhoisAction("nameserver ns1.cat.xn--q9jyb4c\r\n").run(); @@ -385,7 +387,7 @@ public class WhoisActionTest { assertThat(response.getPayload()).contains("1.2.3.4"); } - @Test + @TestOfyAndSql void testRun_nameserverNotFound_returns200AndText() { persistResource(makeHostResource("ns1.cat.lol", "1.2.3.4")); newWhoisAction("nameserver ns1.cat.lulz\r\n").run(); @@ -393,7 +395,7 @@ public class WhoisActionTest { assertThat(response.getPayload()).isEqualTo(loadFile("whois_action_nameserver_not_found.txt")); } - @Test + @TestOfyAndSql void testRun_nameserverFlaggedAsDeletedInDatastore_doesntGetLeaked() { persistResource( makeHostResource("ns1.cat.lol", "1.2.3.4").asBuilder() @@ -403,7 +405,7 @@ public class WhoisActionTest { assertThat(response.getPayload()).isEqualTo(loadFile("whois_action_nameserver_not_found.txt")); } - @Test + @TestOfyAndSql void testRun_ipNameserverLookup_works() { persistResource(makeHostResource("ns1.cat.lol", "1.2.3.4")); newWhoisAction("nameserver 1.2.3.4").run(); @@ -411,7 +413,7 @@ public class WhoisActionTest { assertThat(response.getPayload()).contains("ns1.cat.lol"); } - @Test + @TestOfyAndSql void testRun_ipMapsToMultipleNameservers_theyAllGetReturned() { persistResource(makeHostResource("ns1.cat.lol", "1.2.3.4")); persistResource(makeHostResource("ns2.cat.lol", "1.2.3.4")); @@ -421,7 +423,7 @@ public class WhoisActionTest { assertThat(response.getPayload()).contains("ns2.cat.lol"); } - @Test + @TestOfyAndSql void testRun_ipMapsToMultipleNameserverInDifferentTlds_showsThemAll() { persistResource(makeHostResource("ns1.cat.lol", "1.2.3.4")); persistResource( @@ -432,14 +434,14 @@ public class WhoisActionTest { assertThat(response.getPayload()).contains("ns1.cat.xn--q9jyb4c"); } - @Test + @TestOfyAndSql void testRun_ipNameserverEntityDoesNotExist_returns200NotFound() { newWhoisAction("nameserver feed:a:bee::acab\r\n").run(); assertThat(response.getStatus()).isEqualTo(200); assertThat(response.getPayload()).isEqualTo(loadFile("whois_action_ip_not_found.txt")); } - @Test + @TestOfyAndSql void testRun_ipMapsToNameserverUnderNonAuthoritativeTld_notFound() { assertThat(getTlds()).doesNotContain("com"); persistResource(makeHostResource("ns1.google.com", "1.2.3.4")); @@ -448,7 +450,7 @@ public class WhoisActionTest { assertThat(response.getPayload()).isEqualTo(loadFile("whois_action_ip_not_found.txt")); } - @Test + @TestOfyAndSql void testRun_nameserverUnderNonAuthoritativeTld_notFound() { assertThat(getTlds()).doesNotContain("com"); persistResource(makeHostResource("ns1.google.com", "1.2.3.4")); @@ -459,7 +461,7 @@ public class WhoisActionTest { // todo (b/27378695): reenable or delete this test @Disabled - @Test + @TestOfyAndSql void testRun_nameserverInTestTld_notFound() { persistResource(Registry.get("lol").asBuilder().setTldType(Registry.TldType.TEST).build()); persistResource(makeHostResource("ns1.cat.lol", "1.2.3.4")); @@ -468,7 +470,7 @@ public class WhoisActionTest { assertThat(response.getPayload()).isEqualTo(loadFile("whois_action_nameserver_not_found.txt")); } - @Test + @TestOfyAndSql void testRun_registrarLookup_works() { Registrar registrar = persistResource( makeRegistrar("example", "Example Registrar, Inc.", ACTIVE)); @@ -479,7 +481,7 @@ public class WhoisActionTest { assertThat(response.getPayload()).isEqualTo(loadFile("whois_action_registrar.txt")); } - @Test + @TestOfyAndSql void testRun_pdtRegistrarLookup_works() { Registrar registrar = persistResource( @@ -495,7 +497,7 @@ public class WhoisActionTest { assertThat(response.getPayload()).isEqualTo(loadFile("whois_action_registrar.txt")); } - @Test + @TestOfyAndSql void testRun_registrarLookupInPendingState_returnsNotFound() { Registrar registrar = persistResource( makeRegistrar("example", "Example Registrar, Inc.", Registrar.State.PENDING)); @@ -505,7 +507,7 @@ public class WhoisActionTest { assertThat(response.getPayload()).isEqualTo(loadFile("whois_action_registrar_not_found.txt")); } - @Test + @TestOfyAndSql void testRun_registrarLookupWithTestType_returnsNotFound() { Registrar registrar = persistResource( makeRegistrar("example", "Example Registrar, Inc.", ACTIVE) @@ -519,7 +521,7 @@ public class WhoisActionTest { assertThat(response.getPayload()).isEqualTo(loadFile("whois_action_registrar_not_found.txt")); } - @Test + @TestOfyAndSql void testRun_multilevelDomain_isNotConsideredAHostname() { Registrar registrar = persistResource(makeRegistrar("example", "Example Registrar", ACTIVE)); @@ -537,7 +539,7 @@ public class WhoisActionTest { assertThat(response.getPayload()).contains("Domain Name: cat.1.test\r\n"); } - @Test + @TestOfyAndSql void testRun_hostnameWithMultilevelTld_isStillConsideredHostname() { persistResource(makeHostResource("ns1.cat.1.test", "1.2.3.4")); newWhoisAction("nameserver ns1.cat.1.test\r\n").run(); @@ -546,7 +548,7 @@ public class WhoisActionTest { assertThat(response.getPayload()).contains("1.2.3.4"); } - @Test + @TestOfyAndSql void testRun_metricsLoggedForSuccessfulCommand() { persistResource(makeHostResource("ns1.cat.lol", "1.2.3.4")); persistResource(makeHostResource("ns2.cat.lol", "1.2.3.4")); @@ -562,7 +564,7 @@ public class WhoisActionTest { verify(action.whoisMetrics).recordWhoisMetric(eq(expected)); } - @Test + @TestOfyAndSql void testRun_metricsLoggedForUnsuccessfulCommand() { WhoisAction action = newWhoisAction("domain cat.lol\r\n"); action.whoisMetrics = mock(WhoisMetrics.class); @@ -576,7 +578,7 @@ public class WhoisActionTest { verify(action.whoisMetrics).recordWhoisMetric(eq(expected)); } - @Test + @TestOfyAndSql void testRun_metricsLoggedForInternalServerError() throws Exception { persistResource(makeHostResource("ns1.cat.lol", "1.2.3.4")); WhoisAction action = newWhoisAction("ns1.cat.lol"); @@ -595,7 +597,7 @@ public class WhoisActionTest { assertThat(response.getPayload()).isEqualTo("Internal Server Error"); } - @Test + @TestOfyAndSql void testRun_retryOnTransientFailure() throws Exception { persistResource(loadRegistrar("TheRegistrar").asBuilder().setUrl("http://my.fake.url").build()); persistResource(makeHostResource("ns1.cat.lol", "1.2.3.4")); diff --git a/core/src/test/java/google/registry/whois/WhoisCommandFactoryTest.java b/core/src/test/java/google/registry/whois/WhoisCommandFactoryTest.java index 6405f0ca0..d67f30e7d 100644 --- a/core/src/test/java/google/registry/whois/WhoisCommandFactoryTest.java +++ b/core/src/test/java/google/registry/whois/WhoisCommandFactoryTest.java @@ -29,15 +29,17 @@ import google.registry.model.domain.DomainBase; import google.registry.model.host.HostResource; import google.registry.model.registrar.Registrar; import google.registry.testing.AppEngineExtension; +import google.registry.testing.DualDatabaseTest; import google.registry.testing.FakeClock; import google.registry.testing.TestCacheExtension; +import google.registry.testing.TestOfyAndSql; import java.net.InetAddress; import org.joda.time.Duration; 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; +@DualDatabaseTest class WhoisCommandFactoryTest { FakeClock clock = new FakeClock(); @@ -90,7 +92,7 @@ class WhoisCommandFactoryTest { RegistryConfig.CONFIG_SETTINGS.get().caching.singletonCacheRefreshSeconds = 0; } - @Test + @TestOfyAndSql void testNonCached_NameserverLookupByHostCommand() throws Exception { WhoisResponse response = noncachedFactory @@ -114,7 +116,7 @@ class WhoisCommandFactoryTest { .contains("Registrar: OtherRegistrar name"); } - @Test + @TestOfyAndSql void testCached_NameserverLookupByHostCommand() throws Exception { WhoisResponse response = cachedFactory @@ -137,7 +139,7 @@ class WhoisCommandFactoryTest { .contains("Registrar: The Registrar"); } - @Test + @TestOfyAndSql void testNonCached_DomainLookupCommand() throws Exception { WhoisResponse response = noncachedFactory @@ -161,7 +163,7 @@ class WhoisCommandFactoryTest { .contains("Registrar: OtherRegistrar name"); } - @Test + @TestOfyAndSql void testCached_DomainLookupCommand() throws Exception { WhoisResponse response = cachedFactory @@ -185,7 +187,7 @@ class WhoisCommandFactoryTest { .contains("Registrar: The Registrar"); } - @Test + @TestOfyAndSql void testNonCached_RegistrarLookupCommand() throws Exception { WhoisResponse response = noncachedFactory.registrarLookup("OtherRegistrar").executeQuery(clock.nowUtc()); @@ -199,7 +201,7 @@ class WhoisCommandFactoryTest { .contains("Phone Number: +1.2345677890"); } - @Test + @TestOfyAndSql void testCached_RegistrarLookupCommand() throws Exception { WhoisResponse response = cachedFactory.registrarLookup("OtherRegistrar").executeQuery(clock.nowUtc()); @@ -213,7 +215,7 @@ class WhoisCommandFactoryTest { .contains("Phone Number: +1.2223334444"); } - @Test + @TestOfyAndSql void testNonCached_NameserverLookupByIpCommand() throws Exception { // Note that this lookup currently doesn't cache the hosts, so there's no point in testing the // "cached" case. This test is here so that it will fail if anyone adds caching. diff --git a/core/src/test/java/google/registry/whois/WhoisHttpActionTest.java b/core/src/test/java/google/registry/whois/WhoisHttpActionTest.java index 3fd0c1dfd..c0e9c52f0 100644 --- a/core/src/test/java/google/registry/whois/WhoisHttpActionTest.java +++ b/core/src/test/java/google/registry/whois/WhoisHttpActionTest.java @@ -41,9 +41,11 @@ import google.registry.model.ofy.Ofy; import google.registry.model.registrar.Registrar; import google.registry.model.registry.Registry; import google.registry.testing.AppEngineExtension; +import google.registry.testing.DualDatabaseTest; import google.registry.testing.FakeClock; import google.registry.testing.FakeResponse; import google.registry.testing.InjectExtension; +import google.registry.testing.TestOfyAndSql; import google.registry.whois.WhoisMetrics.WhoisMetric; import java.io.IOException; import java.io.Reader; @@ -51,7 +53,6 @@ import org.joda.time.DateTime; import org.joda.time.Duration; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; /** @@ -60,6 +61,7 @@ import org.junit.jupiter.api.extension.RegisterExtension; *

This class should be limited to testing the HTTP interface, as the bulk of the WHOIS testing * can be found in {@link WhoisActionTest}. */ +@DualDatabaseTest class WhoisHttpActionTest { @RegisterExtension @@ -92,7 +94,7 @@ class WhoisHttpActionTest { inject.setStaticField(Ofy.class, "clock", clock); } - @Test + @TestOfyAndSql void testRun_emptyQuery_returns400BadRequestWithPlainTextOutput() { newWhoisHttpAction("").run(); assertThat(response.getStatus()).isEqualTo(400); @@ -100,7 +102,7 @@ class WhoisHttpActionTest { assertThat(response.getPayload()).isEqualTo(loadFile("whois_action_no_command.txt")); } - @Test + @TestOfyAndSql void testRun_badUrlEncoding_returns400BadRequestWithPlainTextOutput() { newWhoisHttpAction("nic.%u307F%u3093%u306A").run(); assertThat(response.getStatus()).isEqualTo(400); @@ -108,7 +110,7 @@ class WhoisHttpActionTest { assertThat(response.getPayload()).isEqualTo(loadFile("whois_action_malformed_path.txt")); } - @Test + @TestOfyAndSql void testRun_domainNotFound_returns404StatusAndPlainTextResponse() { newWhoisHttpAction("/domain/cat.lol").run(); assertThat(response.getStatus()).isEqualTo(404); @@ -118,7 +120,7 @@ class WhoisHttpActionTest { // todo (b/27378695): reenable or delete this test @Disabled - @Test + @TestOfyAndSql void testRun_domainInTestTld_isConsideredNotFound() { persistResource(Registry.get("lol").asBuilder().setTldType(Registry.TldType.TEST).build()); Registrar registrar = persistResource(makeRegistrar( @@ -138,7 +140,7 @@ class WhoisHttpActionTest { assertThat(response.getPayload()).isEqualTo(loadFile("whois_action_domain_not_found.txt")); } - @Test + @TestOfyAndSql void testRun_domainQueryIdn_works() { Registrar registrar = persistResource(makeRegistrar( "evilregistrar", "Yes Virginia", Registrar.State.ACTIVE)); @@ -156,7 +158,7 @@ class WhoisHttpActionTest { assertThat(response.getPayload()).isEqualTo(loadFile("whois_action_idn_utf8.txt")); } - @Test + @TestOfyAndSql void testRun_wickedLineFeedForgeryInDatastore_crlfSubstitutedWithSpace() { ContactResource trl = makeContactResource("5372808-TRL", "Eric Schmidt", "bog@cat.みんな"); trl = @@ -179,7 +181,7 @@ class WhoisHttpActionTest { assertThat(response.getPayload()).contains("Galactic Empire"); } - @Test + @TestOfyAndSql void testRun_domainOnly_works() { persistResource(makeDomainBase( "cat.みんな", @@ -194,14 +196,14 @@ class WhoisHttpActionTest { assertThat(response.getPayload()).contains("Domain Name: cat.みんな\r\n"); } - @Test + @TestOfyAndSql void testRun_hostnameOnly_works() { persistResource(makeHostResource("ns1.cat.みんな", "1.2.3.4")); newWhoisHttpAction("ns1.cat.みんな").run(); assertThat(response.getPayload()).contains("Server Name: ns1.cat.みんな\r\n"); } - @Test + @TestOfyAndSql void testRun_domainQueryPunycode_works() { Registrar registrar = persistResource(makeRegistrar( "evilregistrar", "Yes Virginia", Registrar.State.ACTIVE)); @@ -218,7 +220,7 @@ class WhoisHttpActionTest { assertThat(response.getPayload()).isEqualTo(loadFile("whois_action_idn_utf8.txt")); } - @Test + @TestOfyAndSql void testRun_nameserverQuery_works() { persistResource(loadRegistrar("TheRegistrar").asBuilder().setUrl("http://my.fake.url").build()); persistResource(makeHostResource("ns1.cat.lol", "1.2.3.4")); @@ -228,14 +230,14 @@ class WhoisHttpActionTest { // todo (b/27378695): reenable or delete this test @Disabled - @Test + @TestOfyAndSql void testRun_nameserverQueryInTestTld_notFound() { persistResource(makeHostResource("ns1.cat.lol", "1.2.3.4")); newWhoisHttpAction("/nameserver/ns1.cat.lol").run(); assertThat(response.getPayload()).isEqualTo(loadFile("whois_action_nameserver.txt")); } - @Test + @TestOfyAndSql void testRun_lastUpdateTimestamp_isPresentInResponse() { clock.setTo(DateTime.parse("2020-07-12T23:52:43Z")); persistResource(makeHostResource("ns1.cat.lol", "1.2.3.4")); @@ -244,7 +246,7 @@ class WhoisHttpActionTest { .contains(">>> Last update of WHOIS database: 2020-07-12T23:52:43Z <<<"); } - @Test + @TestOfyAndSql void testRun_nameserverQueryIdn_works() { persistResource(makeHostResource("ns1.cat.みんな", "1.2.3.4")); newWhoisHttpAction("/nameserver/ns1.cat.みんな").run(); @@ -252,7 +254,7 @@ class WhoisHttpActionTest { assertThat(response.getPayload()).contains("1.2.3.4"); } - @Test + @TestOfyAndSql void testRun_nameserverQueryPunycode_works() { persistResource(makeHostResource("ns1.cat.みんな", "1.2.3.4")); newWhoisHttpAction("/nameserver/ns1.cat.xn--q9jyb4c").run(); @@ -260,7 +262,7 @@ class WhoisHttpActionTest { assertThat(response.getPayload()).contains("1.2.3.4"); } - @Test + @TestOfyAndSql void testRun_trailingSlashInPath_getsIgnored() { persistResource(makeHostResource("ns1.cat.みんな", "1.2.3.4")); newWhoisHttpAction("/nameserver/ns1.cat.xn--q9jyb4c/").run(); @@ -268,7 +270,7 @@ class WhoisHttpActionTest { assertThat(response.getPayload()).contains("1.2.3.4"); } - @Test + @TestOfyAndSql void testRun_uppercaseDomain_ignoresCasing() { persistResource(makeDomainBase( "cat.lol", @@ -282,7 +284,7 @@ class WhoisHttpActionTest { assertThat(response.getPayload()).contains("Domain Name: cat.lol\r\n"); } - @Test + @TestOfyAndSql void testRun_hairyPath_getsDecoded() { persistResource(makeDomainBase( "cat.lol", @@ -297,7 +299,7 @@ class WhoisHttpActionTest { assertThat(response.getPayload()).contains("Domain Name: cat.lol\r\n"); } - @Test + @TestOfyAndSql void testRun_registrarLookup_works() { Registrar registrar = persistResource( makeRegistrar("example", "Example Registrar, Inc.", Registrar.State.ACTIVE)); @@ -308,7 +310,7 @@ class WhoisHttpActionTest { assertThat(response.getPayload()).isEqualTo(loadFile("whois_action_registrar.txt")); } - @Test + @TestOfyAndSql void testRun_registrarLookupInPendingState_returnsNotFound() { Registrar registrar = persistResource( makeRegistrar("example", "Example Registrar, Inc.", Registrar.State.PENDING)); @@ -318,7 +320,7 @@ class WhoisHttpActionTest { assertThat(response.getPayload()).isEqualTo(loadFile("whois_action_registrar_not_found.txt")); } - @Test + @TestOfyAndSql void testRun_registrarLookupWithTestType_returnsNotFound() { Registrar registrar = persistResource( makeRegistrar("example", "Example Registrar, Inc.", Registrar.State.ACTIVE) @@ -329,7 +331,7 @@ class WhoisHttpActionTest { assertThat(response.getPayload()).isEqualTo(loadFile("whois_action_registrar_not_found.txt")); } - @Test + @TestOfyAndSql void testRun_metricsLoggedForSuccessfulCommand() { persistResource(makeHostResource("ns1.cat.lol", "1.2.3.4")); WhoisHttpAction action = newWhoisHttpAction("/nameserver/ns1.cat.lol"); @@ -344,7 +346,7 @@ class WhoisHttpActionTest { verify(action.whoisMetrics).recordWhoisMetric(eq(expected)); } - @Test + @TestOfyAndSql void testRun_metricsLoggedForUnsuccessfulCommand() { WhoisHttpAction action = newWhoisHttpAction("nic.%u307F%u3093%u306A"); action.whoisMetrics = mock(WhoisMetrics.class); @@ -354,7 +356,7 @@ class WhoisHttpActionTest { verify(action.whoisMetrics).recordWhoisMetric(eq(expected)); } - @Test + @TestOfyAndSql void testRun_metricsLoggedForInternalServerError() throws Exception { persistResource(makeHostResource("ns1.cat.lol", "1.2.3.4")); WhoisHttpAction action = newWhoisHttpAction("ns1.cat.lol"); diff --git a/core/src/test/java/google/registry/whois/WhoisReaderTest.java b/core/src/test/java/google/registry/whois/WhoisReaderTest.java index cf212b7b9..a5c5b7296 100644 --- a/core/src/test/java/google/registry/whois/WhoisReaderTest.java +++ b/core/src/test/java/google/registry/whois/WhoisReaderTest.java @@ -22,14 +22,16 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import com.google.common.flogger.LoggerConfig; import com.google.common.testing.TestLogHandler; import google.registry.testing.AppEngineExtension; +import google.registry.testing.DualDatabaseTest; import google.registry.testing.FakeClock; +import google.registry.testing.TestOfyAndSql; import java.io.StringReader; import java.util.logging.Level; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; /** Unit tests for {@link WhoisReader}. */ +@DualDatabaseTest class WhoisReaderTest { @RegisterExtension @@ -83,245 +85,245 @@ class WhoisReaderTest { .isEqualTo("Example Registrar, Inc."); } - @Test + @TestOfyAndSql void testRegistrarLookupWithOneToken() throws Exception { assertThat(this.readCommand("Example").registrarName) .isEqualTo("Example"); } - @Test + @TestOfyAndSql void testDomainLookupWithoutCRLF() throws Exception { assertLoadsExampleTld("example.tld"); } - @Test + @TestOfyAndSql void testWhitespaceOnDomainLookupWithCommand() throws Exception { assertLoadsExampleTld(" \t domain \t \t example.tld \r\n"); } - @Test + @TestOfyAndSql void testDomainLookup() throws Exception { assertLoadsExampleTld("example.tld\r\n"); } - @Test + @TestOfyAndSql void testDomainLookupWithCommand() throws Exception { assertLoadsExampleTld("domain example.tld\r\n"); } - @Test + @TestOfyAndSql void testCaseInsensitiveDomainLookup() throws Exception { assertLoadsExampleTld("EXAMPLE.TLD\r\n"); } - @Test + @TestOfyAndSql void testCaseInsensitiveDomainLookupWithCommand() throws Exception { assertLoadsExampleTld("DOMAIN EXAMPLE.TLD\r\n"); } - @Test + @TestOfyAndSql void testIDNULabelDomainLookup() throws Exception { assertLoadsIDN("مثال.إختبار\r\n"); } - @Test + @TestOfyAndSql void testIDNULabelDomainLookupWithCommand() throws Exception { assertLoadsIDN("domain مثال.إختبار\r\n"); } - @Test + @TestOfyAndSql void testIDNALabelDomainLookupWithCommand() throws Exception { assertLoadsIDN("domain xn--mgbh0fb.xn--kgbechtv\r\n"); } - @Test + @TestOfyAndSql void testIDNALabelDomainLookup() throws Exception { assertLoadsIDN("xn--mgbh0fb.xn--kgbechtv\r\n"); } - @Test + @TestOfyAndSql void testTooManyArgsDomainLookup() { assertThrows(WhoisException.class, () -> readCommand("domain example.tld foo.bar")); } - @Test + @TestOfyAndSql void testTooFewArgsDomainLookup() { assertThrows(WhoisException.class, () -> readCommand("domain")); } - @Test + @TestOfyAndSql void testIllegalArgDomainLookup() { assertThrows(WhoisException.class, () -> readCommand("domain 1.1")); } - @Test + @TestOfyAndSql void testNameserverLookupWithoutCRLF() throws Exception { assertLoadsExampleNs("ns.example.tld"); } - @Test + @TestOfyAndSql void testWhitespaceOnNameserverLookupWithCommand() throws Exception { assertLoadsExampleNs(" \t nameserver \t \t ns.example.tld \r\n"); } - @Test + @TestOfyAndSql void testNameserverLookup() throws Exception { assertLoadsExampleNs("ns.example.tld\r\n"); } - @Test + @TestOfyAndSql void testDeepNameserverLookup() throws Exception { NameserverLookupByHostCommand command = readCommand("ns.foo.bar.baz.example.tld\r\n"); assertThat(command.domainOrHostName.toString()).isEqualTo("ns.foo.bar.baz.example.tld"); assertThat(command.domainOrHostName.toString()).isEqualTo("ns.foo.bar.baz.example.tld"); } - @Test + @TestOfyAndSql void testNameserverLookupWithCommand() throws Exception { assertLoadsExampleNs("nameserver ns.example.tld\r\n"); } - @Test + @TestOfyAndSql void testCaseInsensitiveNameserverLookup() throws Exception { assertLoadsExampleNs("NS.EXAMPLE.TLD\r\n"); } - @Test + @TestOfyAndSql void testCaseInsensitiveNameserverLookupWithCommand() throws Exception { assertLoadsExampleNs("NAMESERVER NS.EXAMPLE.TLD\r\n"); } - @Test + @TestOfyAndSql void testIDNULabelNameserverLookup() throws Exception { assertLoadsIDNNs("ns.مثال.إختبار\r\n"); } - @Test + @TestOfyAndSql void testIDNULabelNameserverLookupWithCommand() throws Exception { assertLoadsIDNNs("nameserver ns.مثال.إختبار\r\n"); } - @Test + @TestOfyAndSql void testIDNALabelNameserverLookupWithCommand() throws Exception { assertLoadsIDNNs("nameserver ns.xn--mgbh0fb.xn--kgbechtv\r\n"); } - @Test + @TestOfyAndSql void testIDNALabelNameserverLookup() throws Exception { assertLoadsIDNNs("ns.xn--mgbh0fb.xn--kgbechtv\r\n"); } - @Test + @TestOfyAndSql void testTooManyArgsNameserverLookup() { assertThrows(WhoisException.class, () -> readCommand("nameserver ns.example.tld foo.bar")); } - @Test + @TestOfyAndSql void testTooFewArgsNameserverLookup() { assertThrows(WhoisException.class, () -> readCommand("nameserver")); } - @Test + @TestOfyAndSql void testIllegalArgNameserverLookup() { assertThrows(WhoisException.class, () -> readCommand("nameserver 1.1")); } - @Test + @TestOfyAndSql void testRegistrarLookup() throws Exception { assertLoadsRegistrar("registrar Example Registrar, Inc."); } - @Test + @TestOfyAndSql void testRegistrarLookupCaseInsensitive() throws Exception { assertLoadsRegistrar("REGISTRAR Example Registrar, Inc."); } - @Test + @TestOfyAndSql void testRegistrarLookupWhitespace() throws Exception { assertLoadsRegistrar(" \t registrar \t \tExample Registrar, Inc. "); } - @Test + @TestOfyAndSql void testRegistrarLookupByDefault() throws Exception { assertLoadsRegistrar("Example Registrar, Inc."); } - @Test + @TestOfyAndSql void testRegistrarLookupOnTLD() throws Exception { assertThat(this.readCommand("com").registrarName).isEqualTo("com"); } - @Test + @TestOfyAndSql void testRegistrarLookupNoArgs() { assertThrows(WhoisException.class, () -> readCommand("registrar")); } - @Test + @TestOfyAndSql void testNameserverLookupByIp() throws Exception { assertNsLookup("43.34.12.213", "43.34.12.213"); } - @Test + @TestOfyAndSql void testNameserverLookupByIpv6() throws Exception { assertNsLookup("1080:0:0:0:8:800:200c:417a", "1080:0:0:0:8:800:200c:417a"); } - @Test + @TestOfyAndSql void testNameserverLookupByCompressedIpv6() throws Exception { assertNsLookup("1080::8:800:200c:417a", "1080:0:0:0:8:800:200c:417a"); } - @Test + @TestOfyAndSql void testNameserverLookupByNoncanonicalIpv6() throws Exception { assertNsLookup("1080:0:0:0:8:800:200C:417A", "1080:0:0:0:8:800:200c:417a"); } - @Test + @TestOfyAndSql void testNameserverLookupByBackwardsCompatibleIpv6() throws Exception { assertNsLookup("::FFFF:129.144.52.38", "129.144.52.38"); } - @Test + @TestOfyAndSql void testNameserverLookupByIpWithCommand() throws Exception { assertNsLookup("nameserver 43.34.12.213", "43.34.12.213"); } - @Test + @TestOfyAndSql void testNameserverLookupByIpv6WithCommand() throws Exception { assertNsLookup("nameserver 1080:0:0:0:8:800:200C:417a", "1080:0:0:0:8:800:200c:417a"); } - @Test + @TestOfyAndSql void testNameserverLookupByIpCaseInsenstive() throws Exception { assertNsLookup("NAMESERVER 43.34.12.213", "43.34.12.213"); } - @Test + @TestOfyAndSql void testNameserverLookupByIpWhitespace() throws Exception { assertNsLookup(" \t\t NAMESERVER \t 43.34.12.213 \r\n", "43.34.12.213"); } - @Test + @TestOfyAndSql void testNameserverLookupByIpTooManyArgs() { assertThrows(WhoisException.class, () -> readCommand("nameserver 43.34.12.213 43.34.12.213")); } - @Test + @TestOfyAndSql void testMultilevelDomainLookup() throws Exception { this.readCommand("example.1.test"); } - @Test + @TestOfyAndSql void testMultilevelNameserverLookup() throws Exception { this.readCommand("ns.example.1.test"); } - @Test + @TestOfyAndSql void testDeepMultilevelNameserverLookup() throws Exception { this.readCommand("ns.corp.example.1.test"); } - @Test + @TestOfyAndSql void testUnconfiguredTld() throws Exception { this.readCommand("example.test"); this.readCommand("1.example.test"); @@ -330,12 +332,12 @@ class WhoisReaderTest { this.readCommand("tld"); } - @Test + @TestOfyAndSql void testNoArgs() { assertThrows(WhoisException.class, () -> readCommand("")); } - @Test + @TestOfyAndSql void testLogsDomainLookupCommand() throws Exception { readCommand("domain example.tld"); assertAboutLogs() @@ -344,7 +346,7 @@ class WhoisReaderTest { Level.INFO, "Attempting domain lookup command using domain name example.tld"); } - @Test + @TestOfyAndSql void testLogsNameserverLookupCommandWithIpAddress() throws Exception { readCommand("nameserver 43.34.12.213"); assertAboutLogs() @@ -353,7 +355,7 @@ class WhoisReaderTest { Level.INFO, "Attempting nameserver lookup command using 43.34.12.213 as an IP address"); } - @Test + @TestOfyAndSql void testLogsNameserverLookupCommandWithHostname() throws Exception { readCommand("nameserver ns.example.tld"); assertAboutLogs() @@ -362,7 +364,7 @@ class WhoisReaderTest { Level.INFO, "Attempting nameserver lookup command using ns.example.tld as a hostname"); } - @Test + @TestOfyAndSql void testLogsRegistrarLookupCommand() throws Exception { readCommand("registrar Example Registrar, Inc."); assertAboutLogs() @@ -372,7 +374,7 @@ class WhoisReaderTest { "Attempting registrar lookup command using registrar Example Registrar, Inc."); } - @Test + @TestOfyAndSql void testLogsSingleArgumentNameserverLookupUsingIpAddress() throws Exception { readCommand("43.34.12.213"); assertAboutLogs() @@ -381,7 +383,7 @@ class WhoisReaderTest { Level.INFO, "Attempting nameserver lookup using 43.34.12.213 as an IP address"); } - @Test + @TestOfyAndSql void testLogsSingleArgumentRegistrarLookup() throws Exception { readCommand("test"); assertAboutLogs() @@ -390,7 +392,7 @@ class WhoisReaderTest { Level.INFO, "Attempting registrar lookup using test as a registrar"); } - @Test + @TestOfyAndSql void testLogsSingleArgumentDomainLookup() throws Exception { readCommand("example.tld"); assertAboutLogs() @@ -399,7 +401,7 @@ class WhoisReaderTest { Level.INFO, "Attempting domain lookup using example.tld as a domain name"); } - @Test + @TestOfyAndSql void testLogsSingleArgumentNameserverLookupUsingHostname() throws Exception { readCommand("ns.example.tld"); assertAboutLogs() @@ -408,7 +410,7 @@ class WhoisReaderTest { Level.INFO, "Attempting nameserver lookup using ns.example.tld as a hostname"); } - @Test + @TestOfyAndSql void testLogsMultipleArgumentsButNoParticularCommand() throws Exception { readCommand("Example Registrar, Inc."); assertAboutLogs()