1/* 2 * Copyright (C) 2015 Square, Inc. 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 */ 16package com.squareup.okhttp; 17 18import com.squareup.okhttp.WebPlatformTestRun.SubtestResult; 19import com.squareup.okhttp.internal.Util; 20import java.io.IOException; 21import java.net.MalformedURLException; 22import java.net.URL; 23import java.util.ArrayList; 24import java.util.List; 25import okio.BufferedSource; 26import okio.Okio; 27import org.junit.Ignore; 28import org.junit.Test; 29import org.junit.runner.RunWith; 30import org.junit.runners.Parameterized; 31import org.junit.runners.Parameterized.Parameter; 32 33import static org.junit.Assert.assertEquals; 34import static org.junit.Assert.assertNotNull; 35import static org.junit.Assert.assertNull; 36 37/** Runs the web platform URL tests against Java URL models. */ 38@RunWith(Parameterized.class) 39public final class WebPlatformUrlTest { 40 @Parameterized.Parameters(name = "{0}") 41 public static List<Object[]> parameters() { 42 try { 43 List<WebPlatformUrlTestData> tests = loadTests(); 44 45 // The web platform tests are run in both HTML and XHTML variants. Major browsers pass more 46 // tests in HTML mode, so that's what we'll attempt to match. 47 String testName = "/url/a-element.html"; 48 WebPlatformTestRun firefoxTestRun 49 = loadTestRun("/web-platform-test-results-url-firefox-37.0.json"); 50 WebPlatformTestRun chromeTestRun 51 = loadTestRun("/web-platform-test-results-url-chrome-42.0.json"); 52 WebPlatformTestRun safariTestRun 53 = loadTestRun("/web-platform-test-results-url-safari-7.1.json"); 54 55 List<Object[]> result = new ArrayList<>(); 56 for (WebPlatformUrlTestData urlTestData : tests) { 57 String subtestName = urlTestData.toString(); 58 SubtestResult firefoxResult = firefoxTestRun.get(testName, subtestName); 59 SubtestResult chromeResult = chromeTestRun.get(testName, subtestName); 60 SubtestResult safariResult = safariTestRun.get(testName, subtestName); 61 result.add(new Object[] { urlTestData, firefoxResult, chromeResult, safariResult }); 62 } 63 return result; 64 } catch (IOException e) { 65 throw new AssertionError(); 66 } 67 } 68 69 @Parameter(0) 70 public WebPlatformUrlTestData testData; 71 72 @Parameter(1) 73 public SubtestResult firefoxResult; 74 75 @Parameter(2) 76 public SubtestResult chromeResultResult; 77 78 @Parameter(3) 79 public SubtestResult safariResult; 80 81 private static final List<String> JAVA_NET_URL_SCHEMES 82 = Util.immutableList("file", "ftp", "http", "https", "mailto"); 83 private static final List<String> HTTP_URL_SCHEMES 84 = Util.immutableList("http", "https"); 85 86 /** Test how {@link URL} does against the web platform test suite. */ 87 @Ignore // java.net.URL is broken. Not much we can do about that. 88 @Test public void javaNetUrl() throws Exception { 89 if (!testData.scheme.isEmpty() && !JAVA_NET_URL_SCHEMES.contains(testData.scheme)) { 90 System.out.println("Ignoring unsupported scheme " + testData.scheme); 91 return; 92 } 93 94 try { 95 testJavaNetUrl(); 96 } catch (AssertionError e) { 97 if (tolerateFailure()) { 98 System.out.println("Tolerable failure: " + e.getMessage()); 99 return; 100 } 101 throw e; 102 } 103 } 104 105 private void testJavaNetUrl() { 106 URL url = null; 107 String failureMessage = ""; 108 try { 109 if (testData.base.equals("about:blank")) { 110 url = new URL(testData.input); 111 } else { 112 URL baseUrl = new URL(testData.base); 113 url = new URL(baseUrl, testData.input); 114 } 115 } catch (MalformedURLException e) { 116 failureMessage = e.getMessage(); 117 } 118 119 if (testData.expectParseFailure()) { 120 assertNull("Expected URL to fail parsing", url); 121 } else { 122 assertNotNull("Expected URL to parse successfully, but was " + failureMessage, url); 123 String effectivePort = url.getPort() != -1 ? Integer.toString(url.getPort()) : ""; 124 String effectiveQuery = url.getQuery() != null ? "?" + url.getQuery() : ""; 125 String effectiveFragment = url.getRef() != null ? "#" + url.getRef() : ""; 126 assertEquals("scheme", testData.scheme, url.getProtocol()); 127 assertEquals("host", testData.host, url.getHost()); 128 assertEquals("port", testData.port, effectivePort); 129 assertEquals("path", testData.path, url.getPath()); 130 assertEquals("query", testData.query, effectiveQuery); 131 assertEquals("fragment", testData.fragment, effectiveFragment); 132 } 133 } 134 135 /** Test how {@link HttpUrl} does against the web platform test suite. */ 136 @Ignore // TODO(jwilson): implement character encoding. 137 @Test public void httpUrl() throws Exception { 138 if (!testData.scheme.isEmpty() && !HTTP_URL_SCHEMES.contains(testData.scheme)) { 139 System.out.println("Ignoring unsupported scheme " + testData.scheme); 140 return; 141 } 142 if (!testData.base.startsWith("https:") && !testData.base.startsWith("http:")) { 143 System.out.println("Ignoring unsupported base " + testData.base); 144 return; 145 } 146 147 try { 148 testHttpUrl(); 149 } catch (AssertionError e) { 150 if (tolerateFailure()) { 151 System.out.println("Tolerable failure: " + e.getMessage()); 152 return; 153 } 154 throw e; 155 } 156 } 157 158 private void testHttpUrl() { 159 HttpUrl url; 160 if (testData.base.equals("about:blank")) { 161 url = HttpUrl.parse(testData.input); 162 } else { 163 HttpUrl baseUrl = HttpUrl.parse(testData.base); 164 url = baseUrl.resolve(testData.input); 165 } 166 167 if (testData.expectParseFailure()) { 168 assertNull("Expected URL to fail parsing", url); 169 } else { 170 assertNotNull("Expected URL to parse successfully, but was null", url); 171 String effectivePort = url.port() != HttpUrl.defaultPort(url.scheme()) 172 ? Integer.toString(url.port()) 173 : ""; 174 String effectiveQuery = url.query() != null ? "?" + url.query() : ""; 175 String effectiveFragment = url.fragment() != null ? "#" + url.fragment() : ""; 176 assertEquals("scheme", testData.scheme, url.scheme()); 177 assertEquals("host", testData.host, url.host()); 178 assertEquals("port", testData.port, effectivePort); 179 assertEquals("path", testData.path, url.path()); 180 assertEquals("query", testData.query, effectiveQuery); 181 assertEquals("fragment", testData.fragment, effectiveFragment); 182 } 183 } 184 185 /** 186 * Returns true if several major browsers also fail this test, in which case the test itself is 187 * questionable. 188 */ 189 private boolean tolerateFailure() { 190 return !firefoxResult.isPass() 191 && !chromeResultResult.isPass() 192 && !safariResult.isPass(); 193 } 194 195 private static List<WebPlatformUrlTestData> loadTests() throws IOException { 196 BufferedSource source = Okio.buffer(Okio.source( 197 WebPlatformUrlTest.class.getResourceAsStream("/web-platform-test-urltestdata.txt"))); 198 return WebPlatformUrlTestData.load(source); 199 } 200 201 private static WebPlatformTestRun loadTestRun(String name) throws IOException { 202 return WebPlatformTestRun.load(WebPlatformUrlTest.class.getResourceAsStream(name)); 203 } 204} 205