/* * Copyright (C) 2017 Square, Inc. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package okhttp3.internal.publicsuffix; import java.io.IOException; import java.io.InputStream; import okhttp3.internal.Util; import okio.Buffer; import okio.BufferedSource; import okio.GzipSource; import okio.Okio; import org.junit.Test; import static okhttp3.internal.publicsuffix.PublicSuffixDatabase.PUBLIC_SUFFIX_RESOURCE; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.fail; public final class PublicSuffixDatabaseTest { private final PublicSuffixDatabase publicSuffixDatabase = new PublicSuffixDatabase(); @Test public void longestMatchWins() { Buffer buffer = new Buffer() .writeUtf8("com\n") .writeUtf8("my.square.com\n") .writeUtf8("square.com\n"); publicSuffixDatabase.setListBytes(buffer.readByteArray(), new byte[]{}); assertEquals("example.com", publicSuffixDatabase.getEffectiveTldPlusOne("example.com")); assertEquals("example.com", publicSuffixDatabase.getEffectiveTldPlusOne("foo.example.com")); assertEquals("bar.square.com", publicSuffixDatabase.getEffectiveTldPlusOne("foo.bar.square.com")); assertEquals("foo.my.square.com", publicSuffixDatabase.getEffectiveTldPlusOne("foo.my.square.com")); } @Test public void wildcardMatch() { Buffer buffer = new Buffer() .writeUtf8("*.square.com\n") .writeUtf8("com\n") .writeUtf8("example.com\n"); publicSuffixDatabase.setListBytes(buffer.readByteArray(), new byte[]{}); assertNull(publicSuffixDatabase.getEffectiveTldPlusOne("my.square.com")); assertEquals("foo.my.square.com", publicSuffixDatabase.getEffectiveTldPlusOne("foo.my.square.com")); assertEquals("foo.my.square.com", publicSuffixDatabase.getEffectiveTldPlusOne("bar.foo.my.square.com")); } @Test public void boundarySearches() { Buffer buffer = new Buffer() .writeUtf8("bbb\n") .writeUtf8("ddd\n") .writeUtf8("fff\n"); publicSuffixDatabase.setListBytes(buffer.readByteArray(), new byte[]{}); assertNull(publicSuffixDatabase.getEffectiveTldPlusOne("aaa")); assertNull(publicSuffixDatabase.getEffectiveTldPlusOne("ggg")); assertNull(publicSuffixDatabase.getEffectiveTldPlusOne("ccc")); assertNull(publicSuffixDatabase.getEffectiveTldPlusOne("eee")); } @Test public void exceptionRule() { Buffer exception = new Buffer() .writeUtf8("my.square.jp\n"); Buffer buffer = new Buffer() .writeUtf8("*.jp\n") .writeUtf8("*.square.jp\n") .writeUtf8("example.com\n") .writeUtf8("square.com\n"); publicSuffixDatabase.setListBytes(buffer.readByteArray(), exception.readByteArray()); assertEquals("my.square.jp", publicSuffixDatabase.getEffectiveTldPlusOne("my.square.jp")); assertEquals("my.square.jp", publicSuffixDatabase.getEffectiveTldPlusOne("foo.my.square.jp")); assertNull(publicSuffixDatabase.getEffectiveTldPlusOne("my1.square.jp")); } @Test public void noEffectiveTldPlusOne() { Buffer exception = new Buffer() .writeUtf8("my.square.jp\n"); Buffer buffer = new Buffer() .writeUtf8("*.jp\n") .writeUtf8("*.square.jp\n") .writeUtf8("example.com\n") .writeUtf8("square.com\n"); publicSuffixDatabase.setListBytes(buffer.readByteArray(), exception.readByteArray()); assertNull(publicSuffixDatabase.getEffectiveTldPlusOne("example.com")); assertNull(publicSuffixDatabase.getEffectiveTldPlusOne("foo.square.jp")); } @Test public void allPublicSuffixes() throws IOException { InputStream resource = PublicSuffixDatabaseTest.class.getClassLoader() .getResourceAsStream(PUBLIC_SUFFIX_RESOURCE); BufferedSource source = Okio.buffer(new GzipSource(Okio.source(resource))); int length = source.readInt(); Buffer buffer = new Buffer(); buffer.write(source, length); resource.close(); while (!buffer.exhausted()) { String publicSuffix = buffer.readUtf8LineStrict(); if (publicSuffix.contains("*")) { // A wildcard rule, let's replace the wildcard with a value. publicSuffix = publicSuffix.replaceAll("\\*", "square"); } assertNull(publicSuffixDatabase.getEffectiveTldPlusOne(publicSuffix)); String test = "foobar." + publicSuffix; assertEquals(test, publicSuffixDatabase.getEffectiveTldPlusOne(test)); } } @Test public void publicSuffixExceptions() throws IOException { InputStream resource = PublicSuffixDatabaseTest.class.getClassLoader() .getResourceAsStream(PUBLIC_SUFFIX_RESOURCE); BufferedSource source = Okio.buffer(new GzipSource(Okio.source(resource))); int length = source.readInt(); source.skip(length); length = source.readInt(); Buffer buffer = new Buffer(); buffer.write(source, length); resource.close(); while (!buffer.exhausted()) { String exception = buffer.readUtf8LineStrict(); assertEquals(exception, publicSuffixDatabase.getEffectiveTldPlusOne(exception)); String test = "foobar." + exception; assertEquals(exception, publicSuffixDatabase.getEffectiveTldPlusOne(test)); } } /** * These tests are provided by <a href="https://publicsuffix.org/list/">publicsuffix.org</a>. */ @Test public void publicSuffixDotOrgTestCases() { // Any copyright is dedicated to the Public Domain. // https://creativecommons.org/publicdomain/zero/1.0/ // null input. checkPublicSuffix(null, null); // Mixed case. checkPublicSuffix("COM", null); checkPublicSuffix("example.COM", "example.com"); checkPublicSuffix("WwW.example.COM", "example.com"); // Leading dot. checkPublicSuffix(".com", null); checkPublicSuffix(".example", null); checkPublicSuffix(".example.com", null); checkPublicSuffix(".example.example", null); // Unlisted TLD. checkPublicSuffix("example", null); checkPublicSuffix("example.example", "example.example"); checkPublicSuffix("b.example.example", "example.example"); checkPublicSuffix("a.b.example.example", "example.example"); // Listed, but non-Internet, TLD. //checkPublicSuffix("local", null); //checkPublicSuffix("example.local", null); //checkPublicSuffix("b.example.local", null); //checkPublicSuffix("a.b.example.local", null); // TLD with only 1 rule. checkPublicSuffix("biz", null); checkPublicSuffix("domain.biz", "domain.biz"); checkPublicSuffix("b.domain.biz", "domain.biz"); checkPublicSuffix("a.b.domain.biz", "domain.biz"); // TLD with some 2-level rules. checkPublicSuffix("com", null); checkPublicSuffix("example.com", "example.com"); checkPublicSuffix("b.example.com", "example.com"); checkPublicSuffix("a.b.example.com", "example.com"); checkPublicSuffix("uk.com", null); checkPublicSuffix("example.uk.com", "example.uk.com"); checkPublicSuffix("b.example.uk.com", "example.uk.com"); checkPublicSuffix("a.b.example.uk.com", "example.uk.com"); checkPublicSuffix("test.ac", "test.ac"); // TLD with only 1 (wildcard) rule. checkPublicSuffix("mm", null); checkPublicSuffix("c.mm", null); checkPublicSuffix("b.c.mm", "b.c.mm"); checkPublicSuffix("a.b.c.mm", "b.c.mm"); // More complex TLD. checkPublicSuffix("jp", null); checkPublicSuffix("test.jp", "test.jp"); checkPublicSuffix("www.test.jp", "test.jp"); checkPublicSuffix("ac.jp", null); checkPublicSuffix("test.ac.jp", "test.ac.jp"); checkPublicSuffix("www.test.ac.jp", "test.ac.jp"); checkPublicSuffix("kyoto.jp", null); checkPublicSuffix("test.kyoto.jp", "test.kyoto.jp"); checkPublicSuffix("ide.kyoto.jp", null); checkPublicSuffix("b.ide.kyoto.jp", "b.ide.kyoto.jp"); checkPublicSuffix("a.b.ide.kyoto.jp", "b.ide.kyoto.jp"); checkPublicSuffix("c.kobe.jp", null); checkPublicSuffix("b.c.kobe.jp", "b.c.kobe.jp"); checkPublicSuffix("a.b.c.kobe.jp", "b.c.kobe.jp"); checkPublicSuffix("city.kobe.jp", "city.kobe.jp"); checkPublicSuffix("www.city.kobe.jp", "city.kobe.jp"); // TLD with a wildcard rule and exceptions. checkPublicSuffix("ck", null); checkPublicSuffix("test.ck", null); checkPublicSuffix("b.test.ck", "b.test.ck"); checkPublicSuffix("a.b.test.ck", "b.test.ck"); checkPublicSuffix("www.ck", "www.ck"); checkPublicSuffix("www.www.ck", "www.ck"); // US K12. checkPublicSuffix("us", null); checkPublicSuffix("test.us", "test.us"); checkPublicSuffix("www.test.us", "test.us"); checkPublicSuffix("ak.us", null); checkPublicSuffix("test.ak.us", "test.ak.us"); checkPublicSuffix("www.test.ak.us", "test.ak.us"); checkPublicSuffix("k12.ak.us", null); checkPublicSuffix("test.k12.ak.us", "test.k12.ak.us"); checkPublicSuffix("www.test.k12.ak.us", "test.k12.ak.us"); // IDN labels. checkPublicSuffix("食狮.com.cn", "食狮.com.cn"); checkPublicSuffix("食狮.公司.cn", "食狮.公司.cn"); checkPublicSuffix("www.食狮.公司.cn", "食狮.公司.cn"); checkPublicSuffix("shishi.公司.cn", "shishi.公司.cn"); checkPublicSuffix("公司.cn", null); checkPublicSuffix("食狮.中国", "食狮.中国"); checkPublicSuffix("www.食狮.中国", "食狮.中国"); checkPublicSuffix("shishi.中国", "shishi.中国"); checkPublicSuffix("中国", null); // Same as above, but punycoded. checkPublicSuffix("xn--85x722f.com.cn", "xn--85x722f.com.cn"); checkPublicSuffix("xn--85x722f.xn--55qx5d.cn", "xn--85x722f.xn--55qx5d.cn"); checkPublicSuffix("www.xn--85x722f.xn--55qx5d.cn", "xn--85x722f.xn--55qx5d.cn"); checkPublicSuffix("shishi.xn--55qx5d.cn", "shishi.xn--55qx5d.cn"); checkPublicSuffix("xn--55qx5d.cn", null); checkPublicSuffix("xn--85x722f.xn--fiqs8s", "xn--85x722f.xn--fiqs8s"); checkPublicSuffix("www.xn--85x722f.xn--fiqs8s", "xn--85x722f.xn--fiqs8s"); checkPublicSuffix("shishi.xn--fiqs8s", "shishi.xn--fiqs8s"); checkPublicSuffix("xn--fiqs8s", null); } private void checkPublicSuffix(String domain, String registrablePart) { if (domain == null) { try { publicSuffixDatabase.getEffectiveTldPlusOne(null); fail(); } catch (NullPointerException expected) { } return; } String canonicalDomain = Util.domainToAscii(domain); if (canonicalDomain == null) return; String result = publicSuffixDatabase.getEffectiveTldPlusOne(canonicalDomain); if (registrablePart == null) { assertNull(result); } else { assertEquals(Util.domainToAscii(registrablePart), result); } } }