/* * 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 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 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 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 NO_PS = ImmutableList.of( "www", "foo.google", "x.y.z"); private static final List 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 TOP_PRIVATE_DOMAIN = ImmutableList.of( "google.com", "foo.Co.uk", "foo.ca.us."); private static final List UNDER_PRIVATE_DOMAIN = ImmutableList.of( "foo.bar.google.com", "a.b.co.uk", "x.y.ca.us"); private static final List VALID_IP_ADDRS = ImmutableList.of( "1.2.3.4", "127.0.0.1", "::1", "2001:db8::1"); private static final List 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 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 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 validCases = Iterables.concat( VALID_NAME, PS, NO_PS, NON_PS); final Iterable 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")); } }