• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
20 import com.google.common.annotations.GwtCompatible;
21 import com.google.common.annotations.GwtIncompatible;
22 import com.google.common.annotations.J2ktIncompatible;
23 import com.google.common.base.Ascii;
24 import com.google.common.base.Strings;
25 import com.google.common.collect.ImmutableSet;
26 import com.google.common.collect.Iterables;
27 import com.google.common.testing.EqualsTester;
28 import com.google.common.testing.NullPointerTester;
29 import junit.framework.TestCase;
30 
31 /**
32  * {@link TestCase} for {@link InternetDomainName}.
33  *
34  * @author Craig Berry
35  */
36 @GwtCompatible(emulated = true)
37 public final class InternetDomainNameTest extends TestCase {
38   private static final InternetDomainName UNICODE_EXAMPLE =
39       InternetDomainName.from("j\u00f8rpeland.no");
40   private static final InternetDomainName PUNYCODE_EXAMPLE =
41       InternetDomainName.from("xn--jrpeland-54a.no");
42 
43   /** The Greek letter delta, used in unicode testing. */
44   private static final String DELTA = "\u0394";
45 
46   /** A domain part which is valid under lenient validation, but invalid under strict validation. */
47   static final String LOTS_OF_DELTAS = Strings.repeat(DELTA, 62);
48 
49   private static final String ALMOST_TOO_MANY_LEVELS = Strings.repeat("a.", 127);
50 
51   private static final String ALMOST_TOO_LONG = Strings.repeat("aaaaa.", 40) + "1234567890.c";
52 
53   private static final ImmutableSet<String> VALID_NAME =
54       ImmutableSet.of(
55           "foo.com",
56           "f-_-o.cOM",
57           "f--1.com",
58           "f11-1.com",
59           "www",
60           "abc.a23",
61           "biz.com.ua",
62           "x",
63           "fOo",
64           "f--o",
65           "f_a",
66           "foo.net.us\uFF61ocm",
67           "woo.com.",
68           "8server.shop",
69           "123.cn",
70           "a" + DELTA + "b.com",
71           ALMOST_TOO_MANY_LEVELS,
72           ALMOST_TOO_LONG);
73 
74   private static final ImmutableSet<String> INVALID_NAME =
75       ImmutableSet.of(
76           "",
77           " ",
78           "127.0.0.1",
79           "::1",
80           "13",
81           "abc.12c",
82           "foo-.com",
83           "_bar.quux",
84           "foo+bar.com",
85           "foo!bar.com",
86           ".foo.com",
87           "..bar.com",
88           "baz..com",
89           "..quiffle.com",
90           "fleeb.com..",
91           ".",
92           "..",
93           "...",
94           "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.com",
95           "a" + DELTA + " .com",
96           ALMOST_TOO_MANY_LEVELS + "com",
97           ALMOST_TOO_LONG + ".c");
98 
99   private static final ImmutableSet<String> RS =
100       ImmutableSet.of(
101           "com",
102           "co.uk",
103           "foo.bd",
104           "xxxxxx.bd",
105           "org.mK",
106           "us",
107           "co.uk.", // Trailing dot
108           "co\uFF61uk", // Alternate dot character
109           "\u7f51\u7edc.Cn", // "网络.Cn"
110           "j\u00f8rpeland.no", // "jorpeland.no" (first o slashed)
111           "xn--jrpeland-54a.no"); // IDNA (punycode) encoding of above
112 
113   private static final ImmutableSet<String> PS_NOT_RS =
114       ImmutableSet.of("blogspot.com", "blogspot.co.uk", "uk.com");
115 
116   private static final ImmutableSet<String> PS =
117       ImmutableSet.<String>builder().addAll(RS).addAll(PS_NOT_RS).build();
118 
119   private static final ImmutableSet<String> NO_PS =
120       ImmutableSet.of("www", "foo.ihopethiswillneverbeapublicsuffix", "x.y.z");
121 
122   /**
123    * Having a public suffix is equivalent to having a registry suffix, because all registry suffixes
124    * are public suffixes, and all public suffixes have registry suffixes.
125    */
126   private static final ImmutableSet<String> NO_RS = NO_PS;
127 
128   private static final ImmutableSet<String> NON_PS =
129       ImmutableSet.of(
130           "foo.bar.com",
131           "foo.ca",
132           "foo.bar.ca",
133           "foo.blogspot.com",
134           "foo.blogspot.co.uk",
135           "foo.uk.com",
136           "foo.bar.co.il",
137           "state.CA.us",
138           "www.state.pa.us",
139           "pvt.k12.ca.us",
140           "www.google.com",
141           "www4.yahoo.co.uk",
142           "home.netscape.com",
143           "web.MIT.edu",
144           "foo.eDu.au",
145           "utenti.blah.IT",
146           "dominio.com.co");
147 
148   private static final ImmutableSet<String> NON_RS =
149       ImmutableSet.<String>builder().addAll(NON_PS).addAll(PS_NOT_RS).build();
150 
151   private static final ImmutableSet<String> TOP_UNDER_REGISTRY_SUFFIX =
152       ImmutableSet.of("google.com", "foo.Co.uk", "foo.ca.us.");
153 
154   private static final ImmutableSet<String> TOP_PRIVATE_DOMAIN =
155       ImmutableSet.of("google.com", "foo.Co.uk", "foo.ca.us.", "foo.blogspot.com");
156 
157   private static final ImmutableSet<String> UNDER_TOP_UNDER_REGISTRY_SUFFIX =
158       ImmutableSet.of("foo.bar.google.com", "a.b.co.uk", "x.y.ca.us");
159 
160   private static final ImmutableSet<String> UNDER_PRIVATE_DOMAIN =
161       ImmutableSet.of("foo.bar.google.com", "a.b.co.uk", "x.y.ca.us", "a.b.blogspot.com");
162 
163   private static final ImmutableSet<String> VALID_IP_ADDRS =
164       ImmutableSet.of("1.2.3.4", "127.0.0.1", "::1", "2001:db8::1");
165 
166   private static final ImmutableSet<String> INVALID_IP_ADDRS =
167       ImmutableSet.of(
168           "", "1", "1.2.3", "...", "1.2.3.4.5", "400.500.600.700", ":", ":::1", "2001:db8:");
169 
170   private static final ImmutableSet<String> SOMEWHERE_UNDER_PS =
171       ImmutableSet.of(
172           "foo.bar.google.com",
173           "a.b.c.1.2.3.ca.us",
174           "site.jp",
175           "uomi-online.kir.jp",
176           "jprs.co.jp",
177           "site.quick.jp",
178           "site.tenki.jp",
179           "site.or.jp",
180           "site.gr.jp",
181           "site.ne.jp",
182           "site.ac.jp",
183           "site.ad.jp",
184           "site.ed.jp",
185           "site.geo.jp",
186           "site.go.jp",
187           "site.lg.jp",
188           "1.fm",
189           "site.cc",
190           "site.ee",
191           "site.fi",
192           "site.fm",
193           "site.gr",
194           "www.leguide.ma",
195           "site.ma",
196           "some.org.mk",
197           "site.mk",
198           "site.tv",
199           "site.us",
200           "www.odev.us",
201           "www.GOOGLE.com",
202           "www.com",
203           "google.com",
204           "www7.google.co.uk",
205           "google.Co.uK",
206           "jobs.kt.com.",
207           "home.netscape.com",
208           "web.stanford.edu",
209           "stanford.edu",
210           "state.ca.us",
211           "www.state.ca.us",
212           "state.ca.us",
213           "pvt.k12.ca.us",
214           "www.rave.ca.",
215           "cnn.ca",
216           "ledger-enquirer.com",
217           "it-trace.ch",
218           "cool.dk",
219           "cool.co.uk",
220           "cool.de",
221           "cool.es",
222           "cool\uFF61fr", // Alternate dot character
223           "cool.nl",
224           "members.blah.nl.",
225           "cool.se",
226           "utenti.blah.it",
227           "kt.co",
228           "a\u7f51\u7edcA.\u7f51\u7edc.Cn" // "a网络A.网络.Cn"
229           );
230 
231   private static final ImmutableSet<String> SOMEWHERE_UNDER_RS =
232       ImmutableSet.<String>builder().addAll(SOMEWHERE_UNDER_PS).addAll(PS_NOT_RS).build();
233 
testValid()234   public void testValid() {
235     for (String name : VALID_NAME) {
236       InternetDomainName unused = InternetDomainName.from(name);
237     }
238   }
239 
testInvalid()240   public void testInvalid() {
241     for (String name : INVALID_NAME) {
242       try {
243         InternetDomainName.from(name);
244         fail("Should have been invalid: '" + name + "'");
245       } catch (IllegalArgumentException expected) {
246       }
247     }
248   }
249 
testPublicSuffix()250   public void testPublicSuffix() {
251     for (String name : PS) {
252       final InternetDomainName domain = InternetDomainName.from(name);
253       assertTrue(name, domain.isPublicSuffix());
254       assertTrue(name, domain.hasPublicSuffix());
255       assertFalse(name, domain.isUnderPublicSuffix());
256       assertFalse(name, domain.isTopPrivateDomain());
257       assertEquals(domain, domain.publicSuffix());
258     }
259 
260     for (String name : NO_PS) {
261       final InternetDomainName domain = InternetDomainName.from(name);
262       assertFalse(name, domain.isPublicSuffix());
263       assertFalse(name, domain.hasPublicSuffix());
264       assertFalse(name, domain.isUnderPublicSuffix());
265       assertFalse(name, domain.isTopPrivateDomain());
266       assertNull(domain.publicSuffix());
267     }
268 
269     for (String name : NON_PS) {
270       final InternetDomainName domain = InternetDomainName.from(name);
271       assertFalse(name, domain.isPublicSuffix());
272       assertTrue(name, domain.hasPublicSuffix());
273       assertTrue(name, domain.isUnderPublicSuffix());
274     }
275   }
276 
testUnderPublicSuffix()277   public void testUnderPublicSuffix() {
278     for (String name : SOMEWHERE_UNDER_PS) {
279       final InternetDomainName domain = InternetDomainName.from(name);
280       assertFalse(name, domain.isPublicSuffix());
281       assertTrue(name, domain.hasPublicSuffix());
282       assertTrue(name, domain.isUnderPublicSuffix());
283     }
284   }
285 
testTopPrivateDomain()286   public void testTopPrivateDomain() {
287     for (String name : TOP_PRIVATE_DOMAIN) {
288       final InternetDomainName domain = InternetDomainName.from(name);
289       assertFalse(name, domain.isPublicSuffix());
290       assertTrue(name, domain.hasPublicSuffix());
291       assertTrue(name, domain.isUnderPublicSuffix());
292       assertTrue(name, domain.isTopPrivateDomain());
293       assertEquals(domain.parent(), domain.publicSuffix());
294     }
295   }
296 
testUnderPrivateDomain()297   public void testUnderPrivateDomain() {
298     for (String name : UNDER_PRIVATE_DOMAIN) {
299       final InternetDomainName domain = InternetDomainName.from(name);
300       assertFalse(name, domain.isPublicSuffix());
301       assertTrue(name, domain.hasPublicSuffix());
302       assertTrue(name, domain.isUnderPublicSuffix());
303       assertFalse(name, domain.isTopPrivateDomain());
304     }
305   }
306 
testRegistrySuffix()307   public void testRegistrySuffix() {
308     for (String name : RS) {
309       final InternetDomainName domain = InternetDomainName.from(name);
310       assertTrue(name, domain.isRegistrySuffix());
311       assertTrue(name, domain.hasRegistrySuffix());
312       assertFalse(name, domain.isUnderRegistrySuffix());
313       assertFalse(name, domain.isTopDomainUnderRegistrySuffix());
314       assertEquals(domain, domain.registrySuffix());
315     }
316 
317     for (String name : NO_RS) {
318       final InternetDomainName domain = InternetDomainName.from(name);
319       assertFalse(name, domain.isRegistrySuffix());
320       assertFalse(name, domain.hasRegistrySuffix());
321       assertFalse(name, domain.isUnderRegistrySuffix());
322       assertFalse(name, domain.isTopDomainUnderRegistrySuffix());
323       assertNull(domain.registrySuffix());
324     }
325 
326     for (String name : NON_RS) {
327       final InternetDomainName domain = InternetDomainName.from(name);
328       assertFalse(name, domain.isRegistrySuffix());
329       assertTrue(name, domain.hasRegistrySuffix());
330       assertTrue(name, domain.isUnderRegistrySuffix());
331     }
332   }
333 
testUnderRegistrySuffix()334   public void testUnderRegistrySuffix() {
335     for (String name : SOMEWHERE_UNDER_RS) {
336       final InternetDomainName domain = InternetDomainName.from(name);
337       assertFalse(name, domain.isRegistrySuffix());
338       assertTrue(name, domain.hasRegistrySuffix());
339       assertTrue(name, domain.isUnderRegistrySuffix());
340     }
341   }
342 
testTopDomainUnderRegistrySuffix()343   public void testTopDomainUnderRegistrySuffix() {
344     for (String name : TOP_UNDER_REGISTRY_SUFFIX) {
345       final InternetDomainName domain = InternetDomainName.from(name);
346       assertFalse(name, domain.isRegistrySuffix());
347       assertTrue(name, domain.hasRegistrySuffix());
348       assertTrue(name, domain.isUnderRegistrySuffix());
349       assertTrue(name, domain.isTopDomainUnderRegistrySuffix());
350       assertEquals(domain.parent(), domain.registrySuffix());
351     }
352   }
353 
testUnderTopDomainUnderRegistrySuffix()354   public void testUnderTopDomainUnderRegistrySuffix() {
355     for (String name : UNDER_TOP_UNDER_REGISTRY_SUFFIX) {
356       final InternetDomainName domain = InternetDomainName.from(name);
357       assertFalse(name, domain.isRegistrySuffix());
358       assertTrue(name, domain.hasRegistrySuffix());
359       assertTrue(name, domain.isUnderRegistrySuffix());
360       assertFalse(name, domain.isTopDomainUnderRegistrySuffix());
361     }
362   }
363 
testParent()364   public void testParent() {
365     assertEquals("com", InternetDomainName.from("google.com").parent().toString());
366     assertEquals("uk", InternetDomainName.from("co.uk").parent().toString());
367     assertEquals("google.com", InternetDomainName.from("www.google.com").parent().toString());
368 
369     try {
370       InternetDomainName.from("com").parent();
371       fail("'com' should throw ISE on .parent() call");
372     } catch (IllegalStateException expected) {
373     }
374   }
375 
testChild()376   public void testChild() {
377     InternetDomainName domain = InternetDomainName.from("foo.com");
378 
379     assertEquals("www.foo.com", domain.child("www").toString());
380 
381     try {
382       domain.child("www.");
383       fail("www..google.com should have been invalid");
384     } catch (IllegalArgumentException expected) {
385     }
386   }
387 
testParentChild()388   public void testParentChild() {
389     InternetDomainName origin = InternetDomainName.from("foo.com");
390     InternetDomainName parent = origin.parent();
391     assertEquals("com", parent.toString());
392 
393     // These would throw an exception if leniency were not preserved during parent() and child()
394     // calls.
395     InternetDomainName child = parent.child(LOTS_OF_DELTAS);
396     InternetDomainName unused = child.child(LOTS_OF_DELTAS);
397   }
398 
testValidTopPrivateDomain()399   public void testValidTopPrivateDomain() {
400     InternetDomainName googleDomain = InternetDomainName.from("google.com");
401 
402     assertEquals(googleDomain, googleDomain.topPrivateDomain());
403     assertEquals(googleDomain, googleDomain.child("mail").topPrivateDomain());
404     assertEquals(googleDomain, googleDomain.child("foo.bar").topPrivateDomain());
405   }
406 
testInvalidTopPrivateDomain()407   public void testInvalidTopPrivateDomain() {
408     ImmutableSet<String> badCookieDomains = ImmutableSet.of("co.uk", "foo", "com");
409 
410     for (String domain : badCookieDomains) {
411       try {
412         InternetDomainName.from(domain).topPrivateDomain();
413         fail(domain);
414       } catch (IllegalStateException expected) {
415       }
416     }
417   }
418 
testIsValid()419   public void testIsValid() {
420     final Iterable<String> validCases = Iterables.concat(VALID_NAME, PS, NO_PS, NON_PS);
421     final Iterable<String> invalidCases =
422         Iterables.concat(INVALID_NAME, VALID_IP_ADDRS, INVALID_IP_ADDRS);
423 
424     for (String valid : validCases) {
425       assertTrue(valid, InternetDomainName.isValid(valid));
426     }
427 
428     for (String invalid : invalidCases) {
429       assertFalse(invalid, InternetDomainName.isValid(invalid));
430     }
431   }
432 
testToString()433   public void testToString() {
434     for (String inputName : SOMEWHERE_UNDER_PS) {
435       InternetDomainName domain = InternetDomainName.from(inputName);
436 
437       /*
438        * We would ordinarily use constants for the expected results, but
439        * doing it by derivation allows us to reuse the test case definitions
440        * used in other tests.
441        */
442 
443       String expectedName = Ascii.toLowerCase(inputName);
444       expectedName = expectedName.replaceAll("[\u3002\uFF0E\uFF61]", ".");
445 
446       if (expectedName.endsWith(".")) {
447         expectedName = expectedName.substring(0, expectedName.length() - 1);
448       }
449 
450       assertEquals(expectedName, domain.toString());
451     }
452   }
453 
testPublicSuffixExclusion()454   public void testPublicSuffixExclusion() {
455     InternetDomainName domain = InternetDomainName.from("foo.city.yokohama.jp");
456     assertTrue(domain.hasPublicSuffix());
457     assertEquals("yokohama.jp", domain.publicSuffix().toString());
458 
459     // Behold the weirdness!
460     assertFalse(domain.publicSuffix().isPublicSuffix());
461   }
462 
testPublicSuffixMultipleUnders()463   public void testPublicSuffixMultipleUnders() {
464     // PSL has both *.uk and *.sch.uk; the latter should win.
465     // See http://code.google.com/p/guava-libraries/issues/detail?id=1176
466 
467     InternetDomainName domain = InternetDomainName.from("www.essex.sch.uk");
468     assertTrue(domain.hasPublicSuffix());
469     assertEquals("essex.sch.uk", domain.publicSuffix().toString());
470     assertEquals("www.essex.sch.uk", domain.topPrivateDomain().toString());
471   }
472 
testRegistrySuffixExclusion()473   public void testRegistrySuffixExclusion() {
474     InternetDomainName domain = InternetDomainName.from("foo.city.yokohama.jp");
475     assertTrue(domain.hasRegistrySuffix());
476     assertEquals("yokohama.jp", domain.registrySuffix().toString());
477 
478     // Behold the weirdness!
479     assertFalse(domain.registrySuffix().isRegistrySuffix());
480   }
481 
testRegistrySuffixMultipleUnders()482   public void testRegistrySuffixMultipleUnders() {
483     // PSL has both *.uk and *.sch.uk; the latter should win.
484     // See http://code.google.com/p/guava-libraries/issues/detail?id=1176
485 
486     InternetDomainName domain = InternetDomainName.from("www.essex.sch.uk");
487     assertTrue(domain.hasRegistrySuffix());
488     assertEquals("essex.sch.uk", domain.registrySuffix().toString());
489     assertEquals("www.essex.sch.uk", domain.topDomainUnderRegistrySuffix().toString());
490   }
491 
testEquality()492   public void testEquality() {
493     new EqualsTester()
494         .addEqualityGroup(idn("google.com"), idn("google.com"), idn("GOOGLE.COM"))
495         .addEqualityGroup(idn("www.google.com"))
496         .addEqualityGroup(UNICODE_EXAMPLE)
497         .addEqualityGroup(PUNYCODE_EXAMPLE)
498         .testEquals();
499   }
500 
idn(String domain)501   private static InternetDomainName idn(String domain) {
502     return InternetDomainName.from(domain);
503   }
504 
505   @J2ktIncompatible
506   @GwtIncompatible // NullPointerTester
testNulls()507   public void testNulls() {
508     final NullPointerTester tester = new NullPointerTester();
509 
510     tester.testAllPublicStaticMethods(InternetDomainName.class);
511     tester.testAllPublicInstanceMethods(InternetDomainName.from("google.com"));
512   }
513 }
514