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