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