1781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller/* 2781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller * Copyright (C) 2015 Square, Inc. 3781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller * 4781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller * Licensed under the Apache License, Version 2.0 (the "License"); 5781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller * you may not use this file except in compliance with the License. 6781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller * You may obtain a copy of the License at 7781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller * 8781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller * http://www.apache.org/licenses/LICENSE-2.0 9781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller * 10781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller * Unless required by applicable law or agreed to in writing, software 11781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller * distributed under the License is distributed on an "AS IS" BASIS, 12781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller * See the License for the specific language governing permissions and 14781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller * limitations under the License. 15781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller */ 16781c9c216deed11c44044d23841a4ba6a012106eNeil Fullerpackage com.squareup.okhttp; 17781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller 18781c9c216deed11c44044d23841a4ba6a012106eNeil Fullerimport com.squareup.okhttp.WebPlatformTestRun.SubtestResult; 19781c9c216deed11c44044d23841a4ba6a012106eNeil Fullerimport com.squareup.okhttp.internal.Util; 20781c9c216deed11c44044d23841a4ba6a012106eNeil Fullerimport java.io.IOException; 21781c9c216deed11c44044d23841a4ba6a012106eNeil Fullerimport java.net.MalformedURLException; 22781c9c216deed11c44044d23841a4ba6a012106eNeil Fullerimport java.net.URL; 23781c9c216deed11c44044d23841a4ba6a012106eNeil Fullerimport java.util.ArrayList; 24781c9c216deed11c44044d23841a4ba6a012106eNeil Fullerimport java.util.List; 25781c9c216deed11c44044d23841a4ba6a012106eNeil Fullerimport okio.BufferedSource; 26781c9c216deed11c44044d23841a4ba6a012106eNeil Fullerimport okio.Okio; 27781c9c216deed11c44044d23841a4ba6a012106eNeil Fullerimport org.junit.Ignore; 28781c9c216deed11c44044d23841a4ba6a012106eNeil Fullerimport org.junit.Test; 29781c9c216deed11c44044d23841a4ba6a012106eNeil Fullerimport org.junit.runner.RunWith; 30781c9c216deed11c44044d23841a4ba6a012106eNeil Fullerimport org.junit.runners.Parameterized; 31781c9c216deed11c44044d23841a4ba6a012106eNeil Fullerimport org.junit.runners.Parameterized.Parameter; 32781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller 33781c9c216deed11c44044d23841a4ba6a012106eNeil Fullerimport static org.junit.Assert.assertEquals; 34781c9c216deed11c44044d23841a4ba6a012106eNeil Fullerimport static org.junit.Assert.assertNotNull; 35781c9c216deed11c44044d23841a4ba6a012106eNeil Fullerimport static org.junit.Assert.assertNull; 36781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller 37781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller/** Runs the web platform URL tests against Java URL models. */ 38781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller@RunWith(Parameterized.class) 39781c9c216deed11c44044d23841a4ba6a012106eNeil Fullerpublic final class WebPlatformUrlTest { 40781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller @Parameterized.Parameters(name = "{0}") 41781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller public static List<Object[]> parameters() { 42781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller try { 43781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller List<WebPlatformUrlTestData> tests = loadTests(); 44781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller 45781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller // The web platform tests are run in both HTML and XHTML variants. Major browsers pass more 46781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller // tests in HTML mode, so that's what we'll attempt to match. 47781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller String testName = "/url/a-element.html"; 48781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller WebPlatformTestRun firefoxTestRun 49781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller = loadTestRun("/web-platform-test-results-url-firefox-37.0.json"); 50781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller WebPlatformTestRun chromeTestRun 51781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller = loadTestRun("/web-platform-test-results-url-chrome-42.0.json"); 52781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller WebPlatformTestRun safariTestRun 53781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller = loadTestRun("/web-platform-test-results-url-safari-7.1.json"); 54781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller 55781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller List<Object[]> result = new ArrayList<>(); 56781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller for (WebPlatformUrlTestData urlTestData : tests) { 57781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller String subtestName = urlTestData.toString(); 58781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller SubtestResult firefoxResult = firefoxTestRun.get(testName, subtestName); 59781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller SubtestResult chromeResult = chromeTestRun.get(testName, subtestName); 60781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller SubtestResult safariResult = safariTestRun.get(testName, subtestName); 61781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller result.add(new Object[] { urlTestData, firefoxResult, chromeResult, safariResult }); 62781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller } 63781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller return result; 64781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller } catch (IOException e) { 65781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller throw new AssertionError(); 66781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller } 67781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller } 68781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller 69781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller @Parameter(0) 70781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller public WebPlatformUrlTestData testData; 71781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller 72781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller @Parameter(1) 73781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller public SubtestResult firefoxResult; 74781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller 75781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller @Parameter(2) 76781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller public SubtestResult chromeResultResult; 77781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller 78781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller @Parameter(3) 79781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller public SubtestResult safariResult; 80781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller 81781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller private static final List<String> JAVA_NET_URL_SCHEMES 82781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller = Util.immutableList("file", "ftp", "http", "https", "mailto"); 83781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller private static final List<String> HTTP_URL_SCHEMES 84781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller = Util.immutableList("http", "https"); 85781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller 86781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller /** Test how {@link URL} does against the web platform test suite. */ 87781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller @Ignore // java.net.URL is broken. Not much we can do about that. 88781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller @Test public void javaNetUrl() throws Exception { 89781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller if (!testData.scheme.isEmpty() && !JAVA_NET_URL_SCHEMES.contains(testData.scheme)) { 90781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller System.out.println("Ignoring unsupported scheme " + testData.scheme); 91781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller return; 92781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller } 93781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller 94781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller try { 95781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller testJavaNetUrl(); 96781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller } catch (AssertionError e) { 97781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller if (tolerateFailure()) { 98781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller System.out.println("Tolerable failure: " + e.getMessage()); 99781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller return; 100781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller } 101781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller throw e; 102781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller } 103781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller } 104781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller 105781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller private void testJavaNetUrl() { 106781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller URL url = null; 107781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller String failureMessage = ""; 108781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller try { 109781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller if (testData.base.equals("about:blank")) { 110781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller url = new URL(testData.input); 111781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller } else { 112781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller URL baseUrl = new URL(testData.base); 113781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller url = new URL(baseUrl, testData.input); 114781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller } 115781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller } catch (MalformedURLException e) { 116781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller failureMessage = e.getMessage(); 117781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller } 118781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller 119781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller if (testData.expectParseFailure()) { 120781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller assertNull("Expected URL to fail parsing", url); 121781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller } else { 122781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller assertNotNull("Expected URL to parse successfully, but was " + failureMessage, url); 123781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller String effectivePort = url.getPort() != -1 ? Integer.toString(url.getPort()) : ""; 124781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller String effectiveQuery = url.getQuery() != null ? "?" + url.getQuery() : ""; 125781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller String effectiveFragment = url.getRef() != null ? "#" + url.getRef() : ""; 126781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller assertEquals("scheme", testData.scheme, url.getProtocol()); 127781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller assertEquals("host", testData.host, url.getHost()); 128781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller assertEquals("port", testData.port, effectivePort); 129781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller assertEquals("path", testData.path, url.getPath()); 130781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller assertEquals("query", testData.query, effectiveQuery); 131781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller assertEquals("fragment", testData.fragment, effectiveFragment); 132781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller } 133781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller } 134781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller 135781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller /** Test how {@link HttpUrl} does against the web platform test suite. */ 136781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller @Ignore // TODO(jwilson): implement character encoding. 137781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller @Test public void httpUrl() throws Exception { 138781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller if (!testData.scheme.isEmpty() && !HTTP_URL_SCHEMES.contains(testData.scheme)) { 139781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller System.out.println("Ignoring unsupported scheme " + testData.scheme); 140781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller return; 141781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller } 142781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller if (!testData.base.startsWith("https:") && !testData.base.startsWith("http:")) { 143781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller System.out.println("Ignoring unsupported base " + testData.base); 144781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller return; 145781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller } 146781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller 147781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller try { 148781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller testHttpUrl(); 149781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller } catch (AssertionError e) { 150781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller if (tolerateFailure()) { 151781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller System.out.println("Tolerable failure: " + e.getMessage()); 152781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller return; 153781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller } 154781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller throw e; 155781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller } 156781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller } 157781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller 158781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller private void testHttpUrl() { 159781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller HttpUrl url; 160781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller if (testData.base.equals("about:blank")) { 161781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller url = HttpUrl.parse(testData.input); 162781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller } else { 163781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller HttpUrl baseUrl = HttpUrl.parse(testData.base); 164781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller url = baseUrl.resolve(testData.input); 165781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller } 166781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller 167781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller if (testData.expectParseFailure()) { 168781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller assertNull("Expected URL to fail parsing", url); 169781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller } else { 170781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller assertNotNull("Expected URL to parse successfully, but was null", url); 171781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller String effectivePort = url.port() != HttpUrl.defaultPort(url.scheme()) 172781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller ? Integer.toString(url.port()) 173781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller : ""; 174781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller String effectiveQuery = url.query() != null ? "?" + url.query() : ""; 175781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller String effectiveFragment = url.fragment() != null ? "#" + url.fragment() : ""; 176781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller assertEquals("scheme", testData.scheme, url.scheme()); 177781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller assertEquals("host", testData.host, url.host()); 178781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller assertEquals("port", testData.port, effectivePort); 179781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller assertEquals("path", testData.path, url.path()); 180781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller assertEquals("query", testData.query, effectiveQuery); 181781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller assertEquals("fragment", testData.fragment, effectiveFragment); 182781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller } 183781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller } 184781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller 185781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller /** 186781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller * Returns true if several major browsers also fail this test, in which case the test itself is 187781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller * questionable. 188781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller */ 189781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller private boolean tolerateFailure() { 190781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller return !firefoxResult.isPass() 191781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller && !chromeResultResult.isPass() 192781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller && !safariResult.isPass(); 193781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller } 194781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller 195781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller private static List<WebPlatformUrlTestData> loadTests() throws IOException { 196781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller BufferedSource source = Okio.buffer(Okio.source( 197781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller WebPlatformUrlTest.class.getResourceAsStream("/web-platform-test-urltestdata.txt"))); 198781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller return WebPlatformUrlTestData.load(source); 199781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller } 200781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller 201781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller private static WebPlatformTestRun loadTestRun(String name) throws IOException { 202781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller return WebPlatformTestRun.load(WebPlatformUrlTest.class.getResourceAsStream(name)); 203781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller } 204781c9c216deed11c44044d23841a4ba6a012106eNeil Fuller} 205