1 /* 2 * Copyright (C) 2008 The Android Open Source Project 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 android.core; 18 19 import android.test.suitebuilder.annotation.Suppress; 20 import junit.framework.TestCase; 21 22 import java.io.BufferedReader; 23 import java.io.IOException; 24 import java.io.InputStream; 25 import java.io.InputStreamReader; 26 import java.io.OutputStream; 27 import java.io.PrintWriter; 28 import java.net.HttpURLConnection; 29 import java.net.ServerSocket; 30 import java.net.Socket; 31 import java.net.URL; 32 import java.net.URLConnection; 33 import java.util.HashMap; 34 import java.util.Map; 35 36 public class URLTest extends TestCase { 37 38 private static void get(String u) throws IOException { 39 URL url = new URL(u); 40 URLConnection cn = url.openConnection(); 41 cn.connect(); 42 // System.out.println("Content-Type: " + cn.getContentType()); 43 // System.out.println("Content-Length: " + cn.getContentLength()); 44 45 InputStream stream = cn.getInputStream(); 46 if (stream == null) { 47 throw new RuntimeException("stream is null"); 48 } 49 byte[] data = new byte[1024]; 50 stream.read(data); 51 52 // if (true) { 53 // System.out.print("data="); 54 // System.out.write(data); 55 // System.out.println(); 56 // } 57 58 // System.out.println("Content-Type: " + cn.getContentType()); 59 // System.out.print("data:"); 60 // System.out.write(data); 61 // System.out.println(); 62 63 assertTrue(new String(data).indexOf("<html>") >= 0); 64 } 65 66 @Suppress 67 public void testGetHTTP() throws Exception { 68 get("http://www.google.com"); 69 } 70 71 @Suppress 72 public void testGetHTTPS() throws Exception { 73 get("https://www.fortify.net/cgi/ssl_2.pl"); 74 } 75 76 /** 77 * Dummy HTTP server class for testing keep-alive behavior. Listens a 78 * single time and responds to a given number of requests on the same 79 * socket. Then closes the socket. 80 */ 81 private static class DummyServer implements Runnable { 82 83 private int keepAliveCount; 84 private Map<String, String> headers = new HashMap<String, String>(); 85 86 public DummyServer(int keepAliveCount) { 87 this.keepAliveCount = keepAliveCount; 88 } 89 90 public void run() { 91 try { 92 ServerSocket server = new ServerSocket(8182); 93 Socket socket = server.accept(); 94 95 InputStream input = socket.getInputStream(); 96 BufferedReader reader = new BufferedReader(new InputStreamReader(input)); 97 try { 98 for (int i = 0; i < keepAliveCount; i++) { 99 reader.readLine(); 100 headers.clear(); 101 while (true) { 102 String header = reader.readLine(); 103 if (header.length() == 0) { 104 break; 105 } 106 int colon = header.indexOf(":"); 107 String key = header.substring(0, colon); 108 String value = header.substring(colon + 1).trim(); 109 headers.put(key, value); 110 } 111 112 OutputStream output = socket.getOutputStream(); 113 PrintWriter writer = new PrintWriter(output); 114 115 try { 116 writer.println("HTTP/1.1 200 OK"); 117 String body = "Hello, Android world #" + i + "!"; 118 writer.println("Content-Length: " + body.length()); 119 writer.println(""); 120 writer.print(body); 121 writer.flush(); 122 } finally { 123 writer.close(); 124 } 125 } 126 } finally { 127 reader.close(); 128 } 129 socket.close(); 130 server.close(); 131 } catch (Exception ex) { 132 throw new RuntimeException(ex); 133 } 134 } 135 } 136 137 /** 138 * Does a request to the given URL, reads and returns the result. 139 */ 140 private String request(URL url) throws Exception { 141 URLConnection connection = url.openConnection(); 142 connection.connect(); 143 144 InputStream input = connection.getInputStream(); 145 BufferedReader reader = new BufferedReader(new InputStreamReader(input)); 146 try { 147 return reader.readLine(); 148 } finally { 149 reader.close(); 150 } 151 } 152 153 /** 154 * Test case for HTTP keep-alive behavior. 155 */ 156 @Suppress 157 public void testGetKeepAlive() throws Exception { 158 new Thread(new DummyServer(3)).start(); 159 Thread.sleep(100); 160 161 // We expect the request to work three times, then it fails. 162 URL url = new URL("http://localhost:8182"); 163 assertEquals("Hello, Android world #0!", request(url)); 164 assertEquals("Hello, Android world #1!", request(url)); 165 assertEquals("Hello, Android world #2!", request(url)); 166 167 try { 168 request(url); 169 fail("ConnectException expected."); 170 } catch (Exception ex) { 171 // Ok. 172 } 173 } 174 175 @Suppress 176 public void testUserAgentHeader() throws Exception { 177 DummyServer server = new DummyServer(1); 178 new Thread(server).start(); 179 Thread.sleep(100); 180 181 // We expect the request to work three times, then it fails. 182 request(new URL("http://localhost:8182")); 183 184 String userAgent = server.headers.get("User-Agent"); 185 assertTrue("Unexpected User-Agent: " + userAgent, userAgent.matches( 186 "Dalvik/[\\d.]+ \\(Linux; U; Android \\w+(;.*)?( Build/\\w+)?\\)")); 187 } 188 189 /** 190 * Regression for issue 1001814. 191 */ 192 @Suppress 193 public void testHttpConnectionTimeout() throws Exception { 194 int timeout = 5000; 195 HttpURLConnection cn = null; 196 long start = 0; 197 try { 198 start = System.currentTimeMillis(); 199 URL url = new URL("http://123.123.123.123"); 200 cn = (HttpURLConnection) url.openConnection(); 201 cn.setConnectTimeout(5000); 202 cn.connect(); 203 fail("should have thrown an exception"); 204 } catch (IOException ioe) { 205 long delay = System.currentTimeMillis() - start; 206 if (Math.abs(timeout - delay) > 1000) { 207 fail("Timeout was not accurate. it needed " + delay + 208 " instead of " + timeout + "miliseconds"); 209 } 210 } finally { 211 if (cn != null) { 212 cn.disconnect(); 213 } 214 } 215 } 216 217 /** 218 * Regression test for issue 1158780 where using '{' and '}' in an URL threw 219 * an NPE. The RI accepts this URL and returns the status 404. 220 */ 221 @Suppress 222 public void testMalformedUrl() throws Exception { 223 URL url = new URL("http://www.google.com/cgi-bin/myscript?g={United+States}+Borders+Mexico+{Climate+change}+Marketing+{Automotive+industry}+News+Health+Internet"); 224 HttpURLConnection conn = (HttpURLConnection)url.openConnection(); 225 int status = conn.getResponseCode(); 226 android.util.Log.d("URLTest", "status: " + status); 227 } 228 } 229