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 tests.support; 19 20import java.io.ByteArrayOutputStream; 21import java.io.IOException; 22import java.io.InputStream; 23import java.io.OutputStream; 24import junit.framework.Assert; 25 26/** 27 * Performs some basic testing of either HttpConnection or HttpURLConnection 28 * depending on the Support_ServerSocket and Support_HttpConnector passed to the 29 * constructor. 30 * 31 */ 32public class Support_HttpTests { 33 34 private Support_ServerSocket serversocket; 35 36 private Support_HttpConnector connector; 37 38 public Support_HttpTests(Support_ServerSocket serversocket, 39 Support_HttpConnector client) { 40 this.serversocket = serversocket; 41 this.connector = client; 42 } 43 44 public void runTests(junit.framework.TestCase test) { 45 46 // get a port to use for the test 47 int portNumber = Support_PortManager.getNextPort(); 48 49 // url's for the various tests 50 final String chunkedTestUrl = "http://localhost:" + portNumber 51 + Support_HttpServer.CHUNKEDTEST; 52 final String contentTestUrl = "http://localhost:" + portNumber 53 + Support_HttpServer.CONTENTTEST; 54 final String redirectTestUrl = "http://localhost:" + portNumber 55 + Support_HttpServer.REDIRECTTEST; 56 final String postTestUrl = "http://localhost:" + portNumber 57 + Support_HttpServer.POSTTEST; 58 final String headersTestUrl = "http://localhost:" + portNumber 59 + Support_HttpServer.HEADERSTEST; 60 61 // start the test server. It will timeout and shut down after 62 // 5 seconds of inactivity 63 Support_HttpServer server = new Support_HttpServer(serversocket, test); 64 server.startServer(portNumber); 65 66 ByteArrayOutputStream bout = new ByteArrayOutputStream(); 67 InputStream is; 68 int c; 69 70 // Chunked HTTP Transfer Coding Test 71 try { 72 // access the url and open a stream 73 connector.open(chunkedTestUrl); 74 is = connector.getInputStream(); 75 76 // receive the data, and then read again after EOF 77 c = is.read(); 78 while (c > 0) { 79 c = is.read(); 80 } 81 c = is.read(); 82 is.close(); 83 connector.close(); 84 Assert.assertEquals("Error receiving chunked transfer coded data", 85 -1, c); 86 } catch (Exception e) { 87 e.printStackTrace(); 88 Assert.fail("Exception during test a: " + e); 89 } 90 91 // Content-Length Test 92 try { 93 connector.open(contentTestUrl); 94 is = connector.getInputStream(); 95 bout.reset(); 96 do { 97 c = is.read(); 98 if (c != -1) { 99 bout.write(c); 100 } 101 } while (c != -1); 102 is.close(); 103 connector.close(); 104 String result = new String(bout.toByteArray(), "ISO8859_1"); 105 Assert.assertTrue("Error receiving content coded data: " + result, 106 "ABCDE".equals(result)); 107 } catch (Exception e) { 108 e.printStackTrace(); 109 Assert.fail("Exception during test b: " + e); 110 } 111 112 // Headers Test 113 try { 114 connector.open(headersTestUrl); 115 connector.setRequestProperty("header1", "value1"); 116 connector.setRequestProperty("header1", "value2"); 117 int i = 0, found = 0; 118 String[] expected = new String[] { "no-cache=\"set-cookie\"", 119 "private", "no-transform" }; 120 while (true) { 121 String key = connector.getHeaderFieldKey(i); 122 if (key == null && i > 0) { 123 break; 124 } 125 if ("Cache-Control".equals(key)) { 126 Assert.assertTrue("Too many headers at: " + i, found <= 2); 127 String value = connector.getHeaderField(i); 128 Assert.assertTrue("Invalid header value: " + found + ": " 129 + value, expected[found].equals(value)); 130 found++; 131 } 132 i++; 133 } 134 Assert.assertTrue("Invalid headers: " + found, found == 3); 135 connector.close(); 136 } catch (Exception e) { 137 e.printStackTrace(); 138 Assert.fail("Exception during test c: " + e); 139 } 140 141 // Post Test 142 // Same as "Basic post" test below, but uses read() instead 143 // of read(buf, offset, length) to read the results 144 try { 145 String toWrite = "abcdef"; 146 connector.open(postTestUrl); 147 OutputStream out = connector.getOutputStream(); 148 out.write(toWrite.getBytes("ISO8859_1")); 149 out.close(); 150 is = connector.getInputStream(); 151 bout.reset(); 152 do { 153 c = is.read(); 154 if (c != -1) { 155 bout.write(c); 156 } 157 } while (c != -1); 158 is.close(); 159 connector.close(); 160 String result = new String(bout.toByteArray(), "ISO8859_1"); 161 Assert.assertTrue("Error sending data 1: " + result, toWrite 162 .equals(result)); 163 } catch (Exception e) { 164 e.printStackTrace(); 165 Assert.fail("Exception during test d: " + e); 166 } 167 168 // Post Test chunked 169 try { 170 String toWrite = "zyxwvuts"; 171 connector.open(postTestUrl); 172 connector.setRequestProperty("Transfer-encoding", "chunked"); 173 OutputStream out = connector.getOutputStream(); 174 out.write(toWrite.getBytes("ISO8859_1")); 175 out.close(); 176 is = connector.getInputStream(); 177 bout.reset(); 178 do { 179 c = is.read(); 180 if (c != -1) { 181 bout.write(c); 182 } 183 } while (c != -1); 184 is.close(); 185 connector.close(); 186 String result = new String(bout.toByteArray(), "ISO8859_1"); 187 Assert.assertEquals(toWrite, result); 188 } catch (Exception e) { 189 e.printStackTrace(); 190 Assert.fail("Exception during test e: " + e); 191 } 192 193 OutputStream os = null; 194 195 byte[] data = new byte[1024]; 196 int len = 0; 197 198 // Basic post 199 try { 200 String message = "test"; 201 connector.open(postTestUrl); 202 os = connector.getOutputStream(); 203 os.write(message.getBytes("ISO8859_1")); 204 os.close(); 205 is = connector.getInputStream(); 206 len = 0; 207 do { 208 int r = is.read(data, len, data.length - len); 209 if (r == -1) { 210 break; 211 } 212 len += r; 213 } while (true); 214 is.close(); 215 connector.close(); 216 String result = new String(data, 0, len, "ISO8859_1"); 217 Assert.assertTrue("Basic port error: " + result, message 218 .equals(result)); 219 } catch (IOException e) { 220 e.printStackTrace(); 221 Assert.fail("Exception during basic post test: " + e); 222 } 223 224 String chunkChar = connector.isChunkedOnFlush() ? "C" : ""; 225 226 // Flushing with post 227 try { 228 String message1 = "test2", message2 = "test3"; 229 connector.open(postTestUrl); 230 os = connector.getOutputStream(); 231 os.write(message1.getBytes("ISO8859_1")); 232 os.flush(); 233 os.write(message2.getBytes("ISO8859_1")); 234 os.close(); 235 is = connector.getInputStream(); 236 len = 0; 237 do { 238 int r = is.read(data, len, data.length - len); 239 if (r == -1) { 240 break; 241 } 242 len += r; 243 } while (true); 244 is.close(); 245 connector.close(); 246 String result = new String(data, 0, len, "ISO8859_1"); 247 Assert.assertTrue("Flushing with post: " + result, (chunkChar 248 + message1 + chunkChar + message2).equals(result)); 249 } catch (IOException e) { 250 e.printStackTrace(); 251 Assert.fail("Exception during flushing post test: " + e); 252 } 253 254 // Flushing with post and setting content-length 255 try { 256 String message1 = "test4", message2 = "test5"; 257 connector.open(postTestUrl); 258 connector.setRequestProperty("Content-Length", "10"); 259 os = connector.getOutputStream(); 260 os.write(message1.getBytes("ISO8859_1")); 261 os.flush(); 262 os.write(message2.getBytes("ISO8859_1")); 263 os.close(); 264 is = connector.getInputStream(); 265 len = 0; 266 do { 267 int r = is.read(data, len, data.length - len); 268 if (r == -1) { 269 break; 270 } 271 len += r; 272 } while (true); 273 is.close(); 274 connector.close(); 275 String result = new String(data, 0, len, "ISO8859_1"); 276 Assert.assertTrue("Flushing with post and setting content-length: " 277 + result, (chunkChar + message1 + chunkChar + message2) 278 .equals(result)); 279 } catch (IOException e) { 280 e.printStackTrace(); 281 Assert.fail("Exception during flushing with content-length post test: " 282 + e); 283 } 284 285 // Flushing followed immediately by a close() 286 try { 287 String message = "test6"; 288 connector.open(postTestUrl); 289 os = connector.getOutputStream(); 290 os.write(message.getBytes("ISO8859_1")); 291 os.flush(); 292 os.close(); 293 is = connector.getInputStream(); 294 len = 0; 295 do { 296 int r = is.read(data, len, data.length - len); 297 if (r == -1) { 298 break; 299 } 300 len += r; 301 } while (true); 302 is.close(); 303 connector.close(); 304 String result = new String(data, 0, len, "ISO8859_1"); 305 Assert.assertTrue("Flushing followed immediately by a close(): " 306 + result, (chunkChar + message).equals(result)); 307 } catch (IOException e) { 308 e.printStackTrace(); 309 Assert.fail("Exception during flush followed by close post test: " 310 + e); 311 } 312 313 // Redirection Tests 314 final int[] testCodes = { Support_HttpServer.MULT_CHOICE, 315 Support_HttpServer.MOVED_PERM, Support_HttpServer.FOUND, 316 Support_HttpServer.SEE_OTHER, Support_HttpServer.NOT_MODIFIED, 317 Support_HttpServer.UNUSED, Support_HttpServer.TEMP_REDIRECT, }; 318 319 final int[] results = { 'A', 'A', 'A', 'A', 'P', 'P', 'P' }; 320 // see Support_HTTPServer for the source of this data 321 322 final String fullLocalLocation = contentTestUrl; 323 final String partLocalLocation = Support_HttpServer.CONTENTTEST; 324 325 for (int i = 0; i < testCodes.length; i++) { 326 327 // test each of the redirection response codes 328 try { 329 // append the response code for the server to return 330 // and the location to redirect to 331 connector.open(redirectTestUrl + "/" + testCodes[i] + "-" 332 + fullLocalLocation); 333 is = connector.getInputStream(); 334 connector.close(); 335 336 c = is.read(); 337 338 if (testCodes[i] == Support_HttpServer.NOT_MODIFIED) { 339 // accept either the message-body or nothing, since the spec 340 // says there MUST NOT be a message body on 304 responses. 341 // But Java returns the message-body 342 if (!(c == results[i] || c == -1)) { 343 Assert.fail("Incorrect data returned on test of HTTP response " 344 + testCodes[i]); 345 } 346 } else if (c != results[i]) { 347 Assert.fail("Incorrect data returned on test of HTTP response " 348 + testCodes[i]); 349 } 350 while (c > 0) { 351 c = is.read(); 352 } 353 c = is.read(); 354 is.close(); 355 } catch (Exception e) { 356 e.printStackTrace(); 357 Assert.fail("Error during redirection test " + i + ": " + e); 358 } 359 } 360 361 // Test redirecting to a location on a different port 362 Class<?> serversocketclass = serversocket.getClass(); 363 try { 364 Support_ServerSocket serversocket2 = (Support_ServerSocket) serversocketclass 365 .newInstance(); 366 367 Support_HttpServer server2 = new Support_HttpServer(serversocket2, 368 test); 369 int newport = Support_PortManager.getNextPort(); 370 server2.startServer(newport); 371 server2.setPortRedirectTestEnable(true); 372 373 // Test if redirection to a different port works 374 final String otherPortLocation = "http://localhost:" + newport 375 + Support_HttpServer.PORTREDIRTEST; 376 377 try { 378 // append the response code for the server to return 379 // and the location to redirect to 380 381 connector.open(redirectTestUrl + "/" 382 + Support_HttpServer.MOVED_PERM + "-" 383 + otherPortLocation); 384 is = connector.getInputStream(); 385 connector.close(); 386 387 c = is.read(); 388 Assert.assertEquals("Incorrect data returned on redirection to a different port.", 389 'A', c); 390 while (c > 0) { 391 c = is.read(); 392 } 393 c = is.read(); 394 is.close(); 395 } catch (Exception e) { 396 e.printStackTrace(); 397 Assert.fail("Exception during test f: " + e); 398 } 399 server2.stopServer(); 400 } catch (IllegalAccessException e) { 401 Assert.fail("Exception during redirection to a different port:" + e); 402 } catch (InstantiationException e) { 403 Assert.fail("Exception during redirection to a different port:" + e); 404 } 405 406 // test redirecting to a relative URL on the same host 407 try { 408 // append the response code for the server to return 409 connector.open(redirectTestUrl + "/" 410 + Support_HttpServer.MOVED_PERM + "-" + partLocalLocation); 411 is = connector.getInputStream(); 412 connector.close(); 413 414 c = is.read(); 415 Assert.assertEquals("Incorrect data returned on redirect to relative URI.", 416 'A', c); 417 while (c > 0) { 418 c = is.read(); 419 } 420 c = is.read(); 421 is.close(); 422 } catch (Exception e) { 423 e.printStackTrace(); 424 Assert.fail("Exception during redirection test to a relative URL: " + e); 425 } 426 server.stopServer(); 427 } 428 429} 430