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" // "a网络A.网络.Cn" 195 ); 196 testValid()197 public void testValid() { 198 for (String name : VALID_NAME) { 199 InternetDomainName.from(name); 200 } 201 } 202 testInvalid()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 testPublicSuffix()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 testUnderPublicSuffix()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 testTopPrivateDomain()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 testUnderPrivateDomain()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 testParent()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 testChild()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 testParentChild()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 testValidTopPrivateDomain()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 testInvalidTopPrivateDomain()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 testIsValid()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)") testName()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 testExclusion()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 testEquality()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 idn(String domain)391 private static InternetDomainName idn(String domain) { 392 return InternetDomainName.from(domain); 393 } 394 395 @GwtIncompatible("NullPointerTester") testNulls()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