/*
* Copyright (C) 2009 The Guava Authors
*
* 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 com.google.common.net;
import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import com.google.common.testing.EqualsTester;
import com.google.common.testing.NullPointerTester;
import junit.framework.TestCase;
import java.util.List;
import java.util.Locale;
/**
* {@link TestCase} for {@link InternetDomainName}.
*
* @author Craig Berry
*/
@GwtCompatible(emulated = true)
public final class InternetDomainNameTest extends TestCase {
private static final InternetDomainName UNICODE_EXAMPLE =
InternetDomainName.from("j\u00f8rpeland.no");
private static final InternetDomainName PUNYCODE_EXAMPLE =
InternetDomainName.from("xn--jrpeland-54a.no");
/**
* The Greek letter delta, used in unicode testing.
*/
private static final String DELTA = "\u0394";
/**
* A domain part which is valid under lenient validation, but invalid under
* strict validation.
*/
static final String LOTS_OF_DELTAS = Strings.repeat(DELTA, 62);
private static final String ALMOST_TOO_MANY_LEVELS =
Strings.repeat("a.", 127);
private static final String ALMOST_TOO_LONG =
Strings.repeat("aaaaa.", 40) + "1234567890.c";
private static final List<String> VALID_NAME = ImmutableList.of(
"foo.com",
"f-_-o.cOM",
"f--1.com",
"f11-1.com",
"www",
"abc.a23",
"biz.com.ua",
"x",
"fOo",
"f--o",
"f_a",
"foo.net.us\uFF61ocm",
"woo.com.",
"a" + DELTA + "b.com",
ALMOST_TOO_MANY_LEVELS,
ALMOST_TOO_LONG);
private static final List<String> INVALID_NAME = ImmutableList.of(
"",
" ",
"127.0.0.1",
"::1", "13",
"abc.12c",
"foo-.com",
"_bar.quux",
"foo+bar.com",
"foo!bar.com",
".foo.com",
"..bar.com",
"baz..com",
"..quiffle.com",
"fleeb.com..",
".",
"..",
"...",
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com",
"a" + DELTA + " .com",
ALMOST_TOO_MANY_LEVELS + "com",
ALMOST_TOO_LONG + ".c");
private static final List<String> PS = ImmutableList.of(
"com",
"co.uk",
"foo.ar",
"xxxxxx.ar",
"org.mK",
"us",
"uk\uFF61com.", // Alternate dot character
"\u7f51\u7edc.Cn", // "网络.Cn"
"j\u00f8rpeland.no", // "jorpeland.no" (first o slashed)
"xn--jrpeland-54a.no" // IDNA (punycode) encoding of above
);
private static final List<String> NO_PS = ImmutableList.of(
"www", "foo.google", "x.y.z");
private static final List<String> NON_PS = ImmutableList.of(
"foo.bar.com", "foo.ca", "foo.bar.ca",
"foo.bar.co.il", "state.CA.us", "www.state.pa.us", "pvt.k12.ca.us",
"www.google.com", "www4.yahoo.co.uk", "home.netscape.com",
"web.MIT.edu", "foo.eDu.au", "utenti.blah.IT", "dominio.com.co");
private static final List<String> TOP_PRIVATE_DOMAIN = ImmutableList.of(
"google.com", "foo.Co.uk", "foo.ca.us.");
private static final List<String> UNDER_PRIVATE_DOMAIN = ImmutableList.of(
"foo.bar.google.com", "a.b.co.uk", "x.y.ca.us");
private static final List<String> VALID_IP_ADDRS = ImmutableList.of(
"1.2.3.4", "127.0.0.1", "::1", "2001:db8::1");
private static final List<String> INVALID_IP_ADDRS = ImmutableList.of(
"", "1", "1.2.3", "...", "1.2.3.4.5", "400.500.600.700",
":", ":::1", "2001:db8:");
private static final List<String> SOMEWHERE_UNDER_PS = ImmutableList.of(
"foo.bar.google.com",
"a.b.c.1.2.3.ca.us",
"site.jp",
"uomi-online.kir.jp",
"jprs.co.jp",
"site.quick.jp",
"site.tenki.jp",
"site.or.jp",
"site.gr.jp",
"site.ne.jp",
"site.ac.jp",
"site.ad.jp",
"site.ed.jp",
"site.geo.jp",
"site.go.jp",
"site.lg.jp",
"1.fm",
"site.cc",
"site.ee",
"site.fi",
"site.fm",
"site.gr",
"www.leguide.ma",
"site.ma",
"some.org.mk",
"site.mk",
"site.tv",
"site.us",
"www.odev.us",
"www.GOOGLE.com",
"www.com",
"google.com",
"www7.google.co.uk",
"google.Co.uK",
"jobs.kt.com.",
"home.netscape.com",
"web.stanford.edu",
"stanford.edu",
"state.ca.us",
"www.state.ca.us",
"state.ca.us",
"pvt.k12.ca.us",
"www.rave.ca.",
"cnn.ca",
"ledger-enquirer.com",
"it-trace.ch",
"cool.dk",
"cool.co.uk",
"cool.de",
"cool.es",
"cool\uFF61fr", // Alternate dot character
"cool.nl",
"members.blah.nl.",
"cool.se",
"utenti.blah.it",
"kt.co",
"a\u7f51\u7edcA.\u7f51\u7edc.Cn" // "a网络A.网络.Cn"
);
public void testValid() {
for (String name : VALID_NAME) {
InternetDomainName.from(name);
}
}
public void testInvalid() {
for (String name : INVALID_NAME) {
try {
InternetDomainName.from(name);
fail("Should have been invalid: '" + name + "'");
} catch (IllegalArgumentException expected) {
// Expected case
}
}
}
public void testPublicSuffix() {
for (String name : PS) {
final InternetDomainName domain = InternetDomainName.from(name);
assertTrue(name, domain.isPublicSuffix());
assertTrue(name, domain.hasPublicSuffix());
assertFalse(name, domain.isUnderPublicSuffix());
assertFalse(name, domain.isTopPrivateDomain());
assertEquals(domain, domain.publicSuffix());
}
for (String name : NO_PS) {
final InternetDomainName domain = InternetDomainName.from(name);
assertFalse(name, domain.isPublicSuffix());
assertFalse(name, domain.hasPublicSuffix());
assertFalse(name, domain.isUnderPublicSuffix());
assertFalse(name, domain.isTopPrivateDomain());
assertNull(domain.publicSuffix());
}
for (String name : NON_PS) {
final InternetDomainName domain = InternetDomainName.from(name);
assertFalse(name, domain.isPublicSuffix());
assertTrue(name, domain.hasPublicSuffix());
assertTrue(name, domain.isUnderPublicSuffix());
}
}
public void testUnderPublicSuffix() {
for (String name : SOMEWHERE_UNDER_PS) {
final InternetDomainName domain = InternetDomainName.from(name);
assertFalse(name, domain.isPublicSuffix());
assertTrue(name, domain.hasPublicSuffix());
assertTrue(name, domain.isUnderPublicSuffix());
}
}
public void testTopPrivateDomain() {
for (String name : TOP_PRIVATE_DOMAIN) {
final InternetDomainName domain = InternetDomainName.from(name);
assertFalse(name, domain.isPublicSuffix());
assertTrue(name, domain.hasPublicSuffix());
assertTrue(name, domain.isUnderPublicSuffix());
assertTrue(name, domain.isTopPrivateDomain());
assertEquals(domain.parent(), domain.publicSuffix());
}
}
public void testUnderPrivateDomain() {
for (String name : UNDER_PRIVATE_DOMAIN) {
final InternetDomainName domain = InternetDomainName.from(name);
assertFalse(name, domain.isPublicSuffix());
assertTrue(name, domain.hasPublicSuffix());
assertTrue(name, domain.isUnderPublicSuffix());
assertFalse(name, domain.isTopPrivateDomain());
}
}
public void testParent() {
assertEquals(
"com",
InternetDomainName.from("google.com").parent().name());
assertEquals(
"uk",
InternetDomainName.from("co.uk").parent().name());
assertEquals(
"google.com",
InternetDomainName.from("www.google.com").parent().name());
try {
InternetDomainName.from("com").parent();
fail("'com' should throw ISE on .parent() call");
} catch (IllegalStateException expected) {
}
}
public void testChild() {
InternetDomainName domain = InternetDomainName.from("foo.com");
assertEquals("www.foo.com", domain.child("www").name());
try {
domain.child("www.");
fail("www..google.com should have been invalid");
} catch (IllegalArgumentException expected) {
// Expected outcome
}
}
public void testParentChild() {
InternetDomainName origin = InternetDomainName.from("foo.com");
InternetDomainName parent = origin.parent();
assertEquals("com", parent.name());
// These would throw an exception if leniency were not preserved during parent() and child()
// calls.
InternetDomainName child = parent.child(LOTS_OF_DELTAS);
child.child(LOTS_OF_DELTAS);
}
public void testValidTopPrivateDomain() {
InternetDomainName googleDomain = InternetDomainName.from("google.com");
assertEquals(googleDomain, googleDomain.topPrivateDomain());
assertEquals(googleDomain, googleDomain.child("mail").topPrivateDomain());
assertEquals(googleDomain, googleDomain.child("foo.bar").topPrivateDomain());
}
public void testInvalidTopPrivateDomain() {
List<String> badCookieDomains = ImmutableList.of("co.uk", "foo", "com");
for (String domain : badCookieDomains) {
try {
InternetDomainName.from(domain).topPrivateDomain();
fail(domain);
} catch (IllegalStateException expected) {
}
}
}
public void testIsValid() {
final Iterable<String> validCases = Iterables.concat(
VALID_NAME, PS, NO_PS, NON_PS);
final Iterable<String> invalidCases = Iterables.concat(
INVALID_NAME, VALID_IP_ADDRS, INVALID_IP_ADDRS);
for (String valid : validCases) {
assertTrue(valid, InternetDomainName.isValid(valid));
}
for (String invalid : invalidCases) {
assertFalse(invalid, InternetDomainName.isValid(invalid));
}
}
// TODO(hhchan): Resurrect this test after removing the reference to
// String.toLowerCase(Locale)
@GwtIncompatible("String.toLowerCase(Locale)")
public void testName() {
for (String inputName : SOMEWHERE_UNDER_PS) {
InternetDomainName domain = InternetDomainName.from(inputName);
/*
* We would ordinarily use constants for the expected results, but
* doing it by derivation allows us to reuse the test case definitions
* used in other tests.
*/
String expectedName = inputName.toLowerCase(Locale.ENGLISH);
expectedName = expectedName.replaceAll("[\u3002\uFF0E\uFF61]", ".");
if (expectedName.endsWith(".")) {
expectedName = expectedName.substring(0, expectedName.length() - 1);
}
assertEquals(expectedName, domain.name());
}
}
public void testExclusion() {
InternetDomainName domain = InternetDomainName.from("foo.nhs.uk");
assertTrue(domain.hasPublicSuffix());
assertEquals("uk", domain.publicSuffix().name());
// Behold the weirdness!
assertFalse(domain.publicSuffix().isPublicSuffix());
}
public void testEquality() {
new EqualsTester()
.addEqualityGroup(
idn("google.com"), idn("google.com"), idn("GOOGLE.COM"))
.addEqualityGroup(idn("www.google.com"))
.addEqualityGroup(UNICODE_EXAMPLE)
.addEqualityGroup(PUNYCODE_EXAMPLE)
.testEquals();
}
private static InternetDomainName idn(String domain) {
return InternetDomainName.from(domain);
}
@GwtIncompatible("NullPointerTester")
public void testNulls() throws Exception {
final NullPointerTester tester = new NullPointerTester();
tester.testAllPublicStaticMethods(InternetDomainName.class);
tester.testAllPublicInstanceMethods(InternetDomainName.from("google.com"));
}
}