HttpURLConnectionTest.java revision cc05ad238516f1303687aba4a978e24e57c0c07a
1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package org.apache.harmony.luni.tests.internal.net.www.protocol.http; 19 20import dalvik.annotation.TestTargetClass; 21import dalvik.annotation.TestTargets; 22import dalvik.annotation.TestLevel; 23import dalvik.annotation.TestTargetNew; 24 25import java.io.IOException; 26import java.net.Authenticator; 27import java.net.HttpURLConnection; 28import java.net.InetSocketAddress; 29import java.net.PasswordAuthentication; 30import java.net.Proxy; 31import java.net.ProxySelector; 32import java.net.ServerSocket; 33import java.net.Socket; 34import java.net.SocketAddress; 35import java.net.SocketTimeoutException; 36import java.net.URI; 37import java.net.URL; 38import java.util.ArrayList; 39 40import junit.framework.TestCase; 41 42 43/** 44 * Tests for <code>HTTPURLConnection</code> class constructors and methods. 45 * 46 */ 47@TestTargetClass(HttpURLConnection.class) 48public class HttpURLConnectionTest extends TestCase { 49 50 private final static Object bound = new Object(); 51 52 static class MockServer extends Thread { 53 ServerSocket serverSocket; 54 boolean accepted = false; 55 boolean started = false; 56 57 public MockServer(String name) throws IOException { 58 super(name); 59 serverSocket = new ServerSocket(0); 60 serverSocket.setSoTimeout(1000); 61 } 62 63 public int port() { 64 return serverSocket.getLocalPort(); 65 } 66 67 @Override 68 public void run() { 69 try { 70 synchronized (bound) { 71 started = true; 72 bound.notify(); 73 } 74 try { 75 serverSocket.accept().close(); 76 accepted = true; 77 } catch (SocketTimeoutException ignore) { 78 } 79 serverSocket.close(); 80 } catch (IOException e) { 81 throw new RuntimeException(e); 82 } 83 } 84 } 85 86 static class MockProxyServer extends MockServer { 87 88 boolean acceptedAuthorizedRequest; 89 90 public MockProxyServer(String name) throws Exception { 91 super(name); 92 } 93 94 @Override 95 public void run() { 96 try { 97 Socket socket = serverSocket.accept(); 98 socket.setSoTimeout(1000); 99 byte[] buff = new byte[1024]; 100 int num = socket.getInputStream().read(buff); 101 socket.getOutputStream().write(( 102 "HTTP/1.0 407 Proxy authentication required\n" 103 + "Proxy-authenticate: Basic realm=\"remotehost\"\n\n") 104 .getBytes()); 105 num = socket.getInputStream().read(buff); 106 if (num == -1) { 107 // this connection was closed, create new one: 108 socket = serverSocket.accept(); 109 socket.setSoTimeout(1000); 110 num = socket.getInputStream().read(buff); 111 } 112 String request = new String(buff, 0, num); 113 acceptedAuthorizedRequest = 114 request.toLowerCase().indexOf("proxy-authorization:") > 0; 115 if (acceptedAuthorizedRequest) { 116 socket.getOutputStream().write(( 117 "HTTP/1.1 200 OK\n\n").getBytes()); 118 } 119 } catch (IOException e) { 120 } 121 } 122 } 123 124 /** 125 * ProxySelector implementation used in the test. 126 */ 127 static class TestProxySelector extends ProxySelector { 128 // proxy port 129 private int proxy_port; 130 // server port 131 private int server_port; 132 133 /** 134 * Creates proxy selector instance. 135 * Selector will return the proxy, only if the connection 136 * is made to localhost:server_port. Otherwise it will 137 * return NO_PROXY. 138 * Address of the returned proxy will be localhost:proxy_port. 139 */ 140 public TestProxySelector(int server_port, int proxy_port) { 141 this.server_port = server_port; 142 this.proxy_port = proxy_port; 143 } 144 145 @Override 146 public java.util.List<Proxy> select(URI uri) { 147 Proxy proxy = Proxy.NO_PROXY; 148 if (("localhost".equals(uri.getHost())) 149 && (server_port == uri.getPort())) { 150 proxy = new Proxy(Proxy.Type.HTTP, 151 new InetSocketAddress("localhost", proxy_port)); 152 } 153 ArrayList<Proxy> result = new ArrayList<Proxy>(); 154 result.add(proxy); 155 return result; 156 } 157 158 @Override 159 public void connectFailed(URI uri, SocketAddress sa, IOException ioe) { 160 // do nothing 161 } 162 } 163 164 /** 165 * @tests org.apache.harmony.luni.internal.net.www.http.getOutputStream() 166 */ 167 @TestTargetNew( 168 level = TestLevel.PARTIAL, 169 notes = "Regression test.", 170 method = "getOutputStream", 171 args = {} 172 ) 173 public void testGetOutputStream() throws Exception { 174 // Regression for HARMONY-482 175 MockServer httpServer = 176 new MockServer("ServerSocket for HttpURLConnectionTest"); 177 httpServer.start(); 178 synchronized(bound) { 179 if (!httpServer.started) { 180 bound.wait(5000); 181 } 182 } 183 HttpURLConnection c = (HttpURLConnection) 184 new URL("http://127.0.0.1:" + httpServer.port()).openConnection(); 185 c.setDoOutput(true); 186 //use new String("POST") instead of simple "POST" to obtain other 187 //object instances then those that are in HttpURLConnection classes 188 c.setRequestMethod(new String("POST")); 189 c.getOutputStream(); 190 httpServer.join(); 191 } 192 193 194 /** 195 * Test checks if the proxy specified in openConnection 196 * method will be used for connection to the server 197 */ 198 @TestTargetNew( 199 level = TestLevel.PARTIAL, 200 notes = "Verifies if the proxy specified in openConnection method will be used for connection to the server.", 201 method = "usingProxy", 202 args = {} 203 ) 204 public void testUsingProxy() throws Exception { 205 // Regression for HARMONY-570 206 MockServer server = new MockServer("server"); 207 MockServer proxy = new MockServer("proxy"); 208 209 URL url = new URL("http://localhost:" + server.port()); 210 211 HttpURLConnection connection = (HttpURLConnection) url 212 .openConnection(new Proxy(Proxy.Type.HTTP, 213 new InetSocketAddress("localhost", 214 proxy.port()))); 215 connection.setConnectTimeout(2000); 216 connection.setReadTimeout(2000); 217 218 server.start(); 219 synchronized(bound) { 220 if (!server.started) bound.wait(5000); 221 } 222 proxy.start(); 223 synchronized(bound) { 224 if (!proxy.started) bound.wait(5000); 225 } 226 227 connection.connect(); 228 229 // wait while server and proxy run 230 server.join(); 231 proxy.join(); 232 233 assertTrue("Connection does not use proxy", connection.usingProxy()); 234 assertTrue("Proxy server was not used", proxy.accepted); 235 236 HttpURLConnection huc = (HttpURLConnection)url.openConnection(Proxy.NO_PROXY); 237 assertFalse(huc.usingProxy()); 238 } 239 240 /** 241 * Test checks if the proxy provided by proxy selector 242 * will be used for connection to the server 243 */ 244 @TestTargetNew( 245 level = TestLevel.PARTIAL, 246 notes = "Verifies if the proxy provided by proxy selector will be used for connection to the server.", 247 method = "usingProxy", 248 args = {} 249 ) 250 public void testUsingProxySelector() throws Exception { 251 // Regression for HARMONY-570 252 MockServer server = new MockServer("server"); 253 MockServer proxy = new MockServer("proxy"); 254 255 URL url = new URL("http://localhost:" + server.port()); 256 257 // keep default proxy selector 258 ProxySelector defPS = ProxySelector.getDefault(); 259 // replace selector 260 ProxySelector.setDefault( 261 new TestProxySelector(server.port(), proxy.port())); 262 263 try { 264 HttpURLConnection connection = 265 (HttpURLConnection) url.openConnection(); 266 connection.setConnectTimeout(2000); 267 connection.setReadTimeout(2000); 268 269 server.start(); 270 synchronized(bound) { 271 if (!server.started) bound.wait(5000); 272 } 273 proxy.start(); 274 synchronized(bound) { 275 if (!proxy.started) bound.wait(5000); 276 } 277 connection.connect(); 278 279 // wait while server and proxy run 280 server.join(); 281 proxy.join(); 282 283 assertTrue("Connection does not use proxy", 284 connection.usingProxy()); 285 assertTrue("Proxy server was not used", proxy.accepted); 286 } finally { 287 // restore default proxy selector 288 ProxySelector.setDefault(defPS); 289 } 290 } 291 @TestTargets({ 292 @TestTargetNew( 293 level = TestLevel.PARTIAL, 294 notes = "Regression test.", 295 method = "getResponseCode", 296 args = {} 297 ), 298 @TestTargetNew( 299 level = TestLevel.PARTIAL, 300 notes = "Regression test.", 301 method = "connect", 302 args = {} 303 ) 304 }) 305 public void testProxyAuthorization() throws Exception { 306 // Set up test Authenticator 307 Authenticator.setDefault(new Authenticator() { 308 @Override 309 protected PasswordAuthentication getPasswordAuthentication() { 310 return new PasswordAuthentication( 311 "user", "password".toCharArray()); 312 } 313 }); 314 315 try { 316 MockProxyServer proxy = new MockProxyServer("ProxyServer"); 317 318 URL url = new URL("http://remotehost:55555/requested.data"); 319 HttpURLConnection connection = 320 (HttpURLConnection) url.openConnection( 321 new Proxy(Proxy.Type.HTTP, 322 new InetSocketAddress("localhost", proxy.port()))); 323 connection.setConnectTimeout(1000); 324 connection.setReadTimeout(1000); 325 326 proxy.start(); 327 328 connection.connect(); 329 assertEquals("unexpected response code", 330 200, connection.getResponseCode()); 331 proxy.join(); 332 assertTrue("Connection did not send proxy authorization request", 333 proxy.acceptedAuthorizedRequest); 334 } finally { 335 // remove previously set authenticator 336 Authenticator.setDefault(null); 337 } 338 } 339 340} 341