Home | History | Annotate | Download | only in net
      1 /*
      2  * Copyright (C) 2009 The Guava Authors
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  * http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.google.common.net;
     18 
     19 import com.google.common.annotations.GwtCompatible;
     20 import com.google.common.annotations.GwtIncompatible;
     21 import com.google.common.base.Strings;
     22 import com.google.common.collect.ImmutableList;
     23 import com.google.common.collect.Iterables;
     24 import com.google.common.testing.EqualsTester;
     25 import com.google.common.testing.NullPointerTester;
     26 
     27 import junit.framework.TestCase;
     28 
     29 import java.util.List;
     30 import java.util.Locale;
     31 
     32 /**
     33  * {@link TestCase} for {@link InternetDomainName}.
     34  *
     35  * @author Craig Berry
     36  */
     37 @GwtCompatible(emulated = true)
     38 public final class InternetDomainNameTest extends TestCase {
     39   private static final InternetDomainName UNICODE_EXAMPLE =
     40       InternetDomainName.from("j\u00f8rpeland.no");
     41   private static final InternetDomainName PUNYCODE_EXAMPLE =
     42       InternetDomainName.from("xn--jrpeland-54a.no");
     43 
     44   /**
     45    * The Greek letter delta, used in unicode testing.
     46    */
     47   private static final String DELTA = "\u0394";
     48 
     49   /**
     50    * A domain part which is valid under lenient validation, but invalid under
     51    * strict validation.
     52    */
     53   static final String LOTS_OF_DELTAS = Strings.repeat(DELTA, 62);
     54 
     55   private static final String ALMOST_TOO_MANY_LEVELS =
     56       Strings.repeat("a.", 127);
     57 
     58   private static final String ALMOST_TOO_LONG =
     59       Strings.repeat("aaaaa.", 40) + "1234567890.c";
     60 
     61   private static final List<String> VALID_NAME = ImmutableList.of(
     62       "foo.com",
     63       "f-_-o.cOM",
     64       "f--1.com",
     65       "f11-1.com",
     66       "www",
     67       "abc.a23",
     68       "biz.com.ua",
     69       "x",
     70       "fOo",
     71       "f--o",
     72       "f_a",
     73       "foo.net.us\uFF61ocm",
     74       "woo.com.",
     75       "a" + DELTA + "b.com",
     76       ALMOST_TOO_MANY_LEVELS,
     77       ALMOST_TOO_LONG);
     78 
     79   private static final List<String> INVALID_NAME = ImmutableList.of(
     80       "",
     81       " ",
     82       "127.0.0.1",
     83       "::1", "13",
     84       "abc.12c",
     85       "foo-.com",
     86       "_bar.quux",
     87       "foo+bar.com",
     88       "foo!bar.com",
     89       ".foo.com",
     90       "..bar.com",
     91       "baz..com",
     92       "..quiffle.com",
     93       "fleeb.com..",
     94       ".",
     95       "..",
     96       "...",
     97       "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com",
     98       "a" + DELTA + " .com",
     99       ALMOST_TOO_MANY_LEVELS + "com",
    100       ALMOST_TOO_LONG + ".c");
    101 
    102   private static final List<String> PS = ImmutableList.of(
    103       "com",
    104       "co.uk",
    105       "foo.ar",
    106       "xxxxxx.ar",
    107       "org.mK",
    108       "us",
    109       "uk\uFF61com.",  // Alternate dot character
    110       "\u7f51\u7edc.Cn",  // ".Cn"
    111       "j\u00f8rpeland.no",  // "jorpeland.no" (first o slashed)
    112       "xn--jrpeland-54a.no"  // IDNA (punycode) encoding of above
    113   );
    114 
    115   private static final List<String> NO_PS = ImmutableList.of(
    116       "www", "foo.google", "x.y.z");
    117 
    118   private static final List<String> NON_PS = ImmutableList.of(
    119       "foo.bar.com", "foo.ca", "foo.bar.ca",
    120       "foo.bar.co.il", "state.CA.us", "www.state.pa.us", "pvt.k12.ca.us",
    121       "www.google.com", "www4.yahoo.co.uk", "home.netscape.com",
    122       "web.MIT.edu", "foo.eDu.au", "utenti.blah.IT", "dominio.com.co");
    123 
    124   private static final List<String> TOP_PRIVATE_DOMAIN = ImmutableList.of(
    125       "google.com", "foo.Co.uk", "foo.ca.us.");
    126 
    127   private static final List<String> UNDER_PRIVATE_DOMAIN = ImmutableList.of(
    128       "foo.bar.google.com", "a.b.co.uk", "x.y.ca.us");
    129 
    130   private static final List<String> VALID_IP_ADDRS = ImmutableList.of(
    131       "1.2.3.4", "127.0.0.1", "::1", "2001:db8::1");
    132 
    133   private static final List<String> INVALID_IP_ADDRS = ImmutableList.of(
    134       "", "1", "1.2.3", "...", "1.2.3.4.5", "400.500.600.700",
    135       ":", ":::1", "2001:db8:");
    136 
    137   private static final List<String> SOMEWHERE_UNDER_PS = ImmutableList.of(
    138       "foo.bar.google.com",
    139       "a.b.c.1.2.3.ca.us",
    140       "site.jp",
    141       "uomi-online.kir.jp",
    142       "jprs.co.jp",
    143       "site.quick.jp",
    144       "site.tenki.jp",
    145       "site.or.jp",
    146       "site.gr.jp",
    147       "site.ne.jp",
    148       "site.ac.jp",
    149       "site.ad.jp",
    150       "site.ed.jp",
    151       "site.geo.jp",
    152       "site.go.jp",
    153       "site.lg.jp",
    154       "1.fm",
    155       "site.cc",
    156       "site.ee",
    157       "site.fi",
    158       "site.fm",
    159       "site.gr",
    160       "www.leguide.ma",
    161       "site.ma",
    162       "some.org.mk",
    163       "site.mk",
    164       "site.tv",
    165       "site.us",
    166       "www.odev.us",
    167       "www.GOOGLE.com",
    168       "www.com",
    169       "google.com",
    170       "www7.google.co.uk",
    171       "google.Co.uK",
    172       "jobs.kt.com.",
    173       "home.netscape.com",
    174       "web.stanford.edu",
    175       "stanford.edu",
    176       "state.ca.us",
    177       "www.state.ca.us",
    178       "state.ca.us",
    179       "pvt.k12.ca.us",
    180       "www.rave.ca.",
    181       "cnn.ca",
    182       "ledger-enquirer.com",
    183       "it-trace.ch",
    184       "cool.dk",
    185       "cool.co.uk",
    186       "cool.de",
    187       "cool.es",
    188       "cool\uFF61fr", // Alternate dot character
    189       "cool.nl",
    190       "members.blah.nl.",
    191       "cool.se",
    192       "utenti.blah.it",
    193       "kt.co",
    194       "a\u7f51\u7edcA.\u7f51\u7edc.Cn"  // "aA..Cn"
    195   );
    196 
    197   public void testValid() {
    198     for (String name : VALID_NAME) {
    199       InternetDomainName.from(name);
    200     }
    201   }
    202 
    203   public void testInvalid() {
    204     for (String name : INVALID_NAME) {
    205       try {
    206         InternetDomainName.from(name);
    207         fail("Should have been invalid: '" + name + "'");
    208       } catch (IllegalArgumentException expected) {
    209         // Expected case
    210       }
    211     }
    212   }
    213 
    214   public void testPublicSuffix() {
    215     for (String name : PS) {
    216       final InternetDomainName domain = InternetDomainName.from(name);
    217       assertTrue(name, domain.isPublicSuffix());
    218       assertTrue(name, domain.hasPublicSuffix());
    219       assertFalse(name, domain.isUnderPublicSuffix());
    220       assertFalse(name, domain.isTopPrivateDomain());
    221       assertEquals(domain, domain.publicSuffix());
    222     }
    223 
    224     for (String name : NO_PS) {
    225       final InternetDomainName domain = InternetDomainName.from(name);
    226       assertFalse(name, domain.isPublicSuffix());
    227       assertFalse(name, domain.hasPublicSuffix());
    228       assertFalse(name, domain.isUnderPublicSuffix());
    229       assertFalse(name, domain.isTopPrivateDomain());
    230       assertNull(domain.publicSuffix());
    231     }
    232 
    233     for (String name : NON_PS) {
    234       final InternetDomainName domain = InternetDomainName.from(name);
    235       assertFalse(name, domain.isPublicSuffix());
    236       assertTrue(name, domain.hasPublicSuffix());
    237       assertTrue(name, domain.isUnderPublicSuffix());
    238     }
    239   }
    240 
    241   public void testUnderPublicSuffix() {
    242     for (String name : SOMEWHERE_UNDER_PS) {
    243       final InternetDomainName domain = InternetDomainName.from(name);
    244       assertFalse(name, domain.isPublicSuffix());
    245       assertTrue(name, domain.hasPublicSuffix());
    246       assertTrue(name, domain.isUnderPublicSuffix());
    247     }
    248   }
    249 
    250   public void testTopPrivateDomain() {
    251     for (String name : TOP_PRIVATE_DOMAIN) {
    252       final InternetDomainName domain = InternetDomainName.from(name);
    253       assertFalse(name, domain.isPublicSuffix());
    254       assertTrue(name, domain.hasPublicSuffix());
    255       assertTrue(name, domain.isUnderPublicSuffix());
    256       assertTrue(name, domain.isTopPrivateDomain());
    257       assertEquals(domain.parent(), domain.publicSuffix());
    258     }
    259   }
    260 
    261   public void testUnderPrivateDomain() {
    262     for (String name : UNDER_PRIVATE_DOMAIN) {
    263       final InternetDomainName domain = InternetDomainName.from(name);
    264       assertFalse(name, domain.isPublicSuffix());
    265       assertTrue(name, domain.hasPublicSuffix());
    266       assertTrue(name, domain.isUnderPublicSuffix());
    267       assertFalse(name, domain.isTopPrivateDomain());
    268     }
    269   }
    270 
    271   public void testParent() {
    272     assertEquals(
    273         "com",
    274         InternetDomainName.from("google.com").parent().name());
    275     assertEquals(
    276         "uk",
    277         InternetDomainName.from("co.uk").parent().name());
    278     assertEquals(
    279         "google.com",
    280         InternetDomainName.from("www.google.com").parent().name());
    281 
    282     try {
    283       InternetDomainName.from("com").parent();
    284       fail("'com' should throw ISE on .parent() call");
    285     } catch (IllegalStateException expected) {
    286     }
    287   }
    288 
    289   public void testChild() {
    290     InternetDomainName domain = InternetDomainName.from("foo.com");
    291 
    292     assertEquals("www.foo.com", domain.child("www").name());
    293 
    294     try {
    295       domain.child("www.");
    296       fail("www..google.com should have been invalid");
    297     } catch (IllegalArgumentException expected) {
    298       // Expected outcome
    299     }
    300   }
    301 
    302   public void testParentChild() {
    303     InternetDomainName origin = InternetDomainName.from("foo.com");
    304     InternetDomainName parent = origin.parent();
    305     assertEquals("com", parent.name());
    306 
    307     // These would throw an exception if leniency were not preserved during parent() and child()
    308     // calls.
    309     InternetDomainName child = parent.child(LOTS_OF_DELTAS);
    310     child.child(LOTS_OF_DELTAS);
    311   }
    312 
    313   public void testValidTopPrivateDomain() {
    314     InternetDomainName googleDomain = InternetDomainName.from("google.com");
    315 
    316     assertEquals(googleDomain, googleDomain.topPrivateDomain());
    317     assertEquals(googleDomain, googleDomain.child("mail").topPrivateDomain());
    318     assertEquals(googleDomain, googleDomain.child("foo.bar").topPrivateDomain());
    319   }
    320 
    321   public void testInvalidTopPrivateDomain() {
    322     List<String> badCookieDomains = ImmutableList.of("co.uk", "foo", "com");
    323 
    324     for (String domain : badCookieDomains) {
    325       try {
    326         InternetDomainName.from(domain).topPrivateDomain();
    327         fail(domain);
    328       } catch (IllegalStateException expected) {
    329       }
    330     }
    331   }
    332 
    333   public void testIsValid() {
    334     final Iterable<String> validCases = Iterables.concat(
    335         VALID_NAME, PS, NO_PS, NON_PS);
    336     final Iterable<String> invalidCases = Iterables.concat(
    337         INVALID_NAME, VALID_IP_ADDRS, INVALID_IP_ADDRS);
    338 
    339     for (String valid : validCases) {
    340       assertTrue(valid, InternetDomainName.isValid(valid));
    341     }
    342 
    343     for (String invalid : invalidCases) {
    344       assertFalse(invalid, InternetDomainName.isValid(invalid));
    345     }
    346   }
    347 
    348   // TODO(hhchan): Resurrect this test after removing the reference to
    349   // String.toLowerCase(Locale)
    350   @GwtIncompatible("String.toLowerCase(Locale)")
    351   public void testName() {
    352     for (String inputName : SOMEWHERE_UNDER_PS) {
    353       InternetDomainName domain = InternetDomainName.from(inputName);
    354 
    355       /*
    356        * We would ordinarily use constants for the expected results, but
    357        * doing it by derivation allows us to reuse the test case definitions
    358        * used in other tests.
    359        */
    360 
    361       String expectedName = inputName.toLowerCase(Locale.ENGLISH);
    362       expectedName = expectedName.replaceAll("[\u3002\uFF0E\uFF61]", ".");
    363 
    364       if (expectedName.endsWith(".")) {
    365         expectedName = expectedName.substring(0, expectedName.length() - 1);
    366       }
    367 
    368       assertEquals(expectedName, domain.name());
    369     }
    370   }
    371 
    372   public void testExclusion() {
    373     InternetDomainName domain = InternetDomainName.from("foo.nhs.uk");
    374     assertTrue(domain.hasPublicSuffix());
    375     assertEquals("uk", domain.publicSuffix().name());
    376 
    377     // Behold the weirdness!
    378     assertFalse(domain.publicSuffix().isPublicSuffix());
    379   }
    380 
    381   public void testEquality() {
    382     new EqualsTester()
    383         .addEqualityGroup(
    384             idn("google.com"), idn("google.com"), idn("GOOGLE.COM"))
    385         .addEqualityGroup(idn("www.google.com"))
    386         .addEqualityGroup(UNICODE_EXAMPLE)
    387         .addEqualityGroup(PUNYCODE_EXAMPLE)
    388         .testEquals();
    389   }
    390 
    391   private static InternetDomainName idn(String domain) {
    392     return InternetDomainName.from(domain);
    393   }
    394 
    395   @GwtIncompatible("NullPointerTester")
    396   public void testNulls() throws Exception {
    397     final NullPointerTester tester = new NullPointerTester();
    398 
    399     tester.testAllPublicStaticMethods(InternetDomainName.class);
    400     tester.testAllPublicInstanceMethods(InternetDomainName.from("google.com"));
    401   }
    402 
    403 }
    404