TestEventHandler.java revision f013e1afd1e68af5e3b868c26a653bbfb39538f8
1/* 2 * Copyright (C) 2007 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 17package android.core; 18 19import java.util.ArrayList; 20import java.util.Map; 21 22import org.apache.http.protocol.HTTP; 23import android.util.Log; 24import android.util.Config; 25import android.net.http.*; 26 27/** 28 * Implements EventHandler and provides test functionality to validate 29 * responses to requests from the test server 30 */ 31public class TestEventHandler implements EventHandler { 32 33 /** 34 * Status variables 35 */ 36 private int majorVersion = -1; 37 private int minorVersion = -1; 38 private int responseCode = -1; 39 private String reasonPhrase; 40 41 /* List of headers received */ 42 private Map<String, String> headerMap; 43 44 /* Used to sync low level delayed requests */ 45 public static final Object syncObj = new Object(); 46 47 /* Indicates whether the low level request testing is in operation */ 48 private boolean useLowLevel = false; 49 50 /* Indicates whether responses should be automatically generated or 51 * delayed 52 */ 53 private boolean delayResponse = false; 54 55 /* Test method expectation identifiers */ 56 public final static int TEST_REQUEST_SENT = 0; 57 public final static int TEST_STATUS = 1; 58 public final static int TEST_HEADERS = 2; 59 public final static int TEST_LOCATION_CHANGED = 3; 60 public final static int TEST_DATA = 4; 61 public final static int TEST_ENDDATA = 5; 62 public final static int TEST_ERROR = 6; 63 public final static int TEST_SSL_CERTIFICATE_ERROR = 7; 64 65 public final static int TEST_NUM_EXPECTS = 8; 66 67 /* Expected status codes */ 68 private int expectMajor = -1; 69 private int expectMinor = -1; 70 private int expectCode = -1; 71 72 /* Array indicating which event types are expected */ 73 private boolean[] expects = new boolean[TEST_NUM_EXPECTS]; 74 75 /* Array indicating which event types are not expected */ 76 private boolean[] notExpecting = new boolean[TEST_NUM_EXPECTS]; 77 78 /* Indicates which events have been received */ 79 private boolean[] eventsReceived = new boolean[TEST_NUM_EXPECTS]; 80 81 /* Redirection variables */ 82 private String expectLocation; 83 private int expectPermanent = -1; 84 85 /* Content data expected to be received */ 86 private byte[] expectData; 87 private int expectDataLength = -1; 88 89 private int expectErrorId = -1; 90 91 private int expectSslErrors = -1; 92 private SslCertificate expectCertificate; 93 94 public class TestHeader { 95 public TestHeader(String n, String v) { 96 name = n; 97 value = v; 98 } 99 public String name; 100 public String value; 101 } 102 103 private ArrayList<TestHeader> expectHeaders = new ArrayList<TestHeader>(); 104 105 /* Holds failure details */ 106 private StringBuffer expectDetails = new StringBuffer(); 107 108 /* If we use a request handle, we retain a reference here for redirects 109 * using setupRedirect 110 */ 111 private RequestHandle mRequestHandle; 112 113 /* The low level API uses this reference also for non-delayed requests */ 114 private LowLevelNetRunner netRunner; 115 116 public TestEventHandler() { 117 for (int i = 0; i < TEST_NUM_EXPECTS; i++) { 118 expects[i] = false; 119 notExpecting[i] = false; 120 eventsReceived[i] = false; 121 } 122 } 123 124 /** 125 * Implementation of EventHandler method called when a request has been 126 * sent. If the test is waiting for this call, it will be signalled, 127 * otherwise this method will trigger the response to be read 128 * automatically. 129 */ 130 public void requestSent() { 131 Log.v(LOGTAG, "TestEventHandler:requestSent()"); 132 expects[TEST_REQUEST_SENT] = false; 133 eventsReceived[TEST_REQUEST_SENT] = true; 134 if (notExpecting[TEST_REQUEST_SENT]) { 135 expectDetails.append("Request sent event received but not expected"); 136 expectDetails.append("\r\n"); 137 } 138 139 if (useLowLevel) { 140 if (delayResponse) { 141 synchronized (syncObj) { 142 syncObj.notifyAll(); 143 } 144 } else { 145 // mRequest.startReadingResponse(); 146 } 147 } 148 } 149 150 /** 151 * Implements the EventHandler status method called when a server status 152 * response is received. 153 * @param major_version The HTTP major version 154 * @param minor_version The HTTP minor version 155 * @param code The status code 156 * @param reason_phrase A reason phrase passed to us by the server 157 */ 158 public void status(int major_version, int minor_version, 159 int code, String reason_phrase) { 160 if (Config.LOGV) { 161 Log.v(LOGTAG, "TestEventHandler:status() major: " + major_version + 162 " minor: " + minor_version + 163 " code: " + code + 164 " reason: " + reason_phrase); 165 } 166 167 eventsReceived[TEST_STATUS] = true; 168 if (notExpecting[TEST_STATUS]) { 169 expectDetails.append("Status event received but not expected"); 170 expectDetails.append("\r\n"); 171 } 172 173 majorVersion = major_version; 174 minorVersion = minor_version; 175 responseCode = code; 176 reasonPhrase = reason_phrase; 177 178 if (expectMajor != -1) { 179 if (expectMajor == major_version) { 180 expectMajor = -1; 181 } else { 182 expectDetails.append("Major version expected:"+expectMajor+ 183 " got:"+major_version); 184 expectDetails.append("\r\n"); 185 } 186 } 187 188 if (expectMinor != -1) { 189 if (expectMinor == minor_version) { 190 expectMinor = -1; 191 } else { 192 expectDetails.append("Minor version expected:"+expectMinor+ 193 " got:"+minor_version); 194 expectDetails.append("\r\n"); 195 } 196 } 197 198 if (expectCode != -1) { 199 if (expectCode == code) { 200 expectCode = -1; 201 } else { 202 expectDetails.append("Status code expected:"+expectCode+ 203 " got:"+code); 204 expectDetails.append("\r\n"); 205 } 206 } 207 208 209 if ((expectMajor == -1) && (expectMinor == -1) && (expectCode == -1)) { 210 expects[TEST_STATUS] = false; 211 } else { 212 System.out.println("MAJOR = "+expectMajor+" MINOR = "+expectMinor+ 213 " CODE = "+expectCode); 214 } 215 } 216 217 /** 218 * Implements the EventHandler headers method called when a server 219 * sends header fields 220 */ 221 public void headers(Headers headers) { 222 if (Config.LOGV) { 223 Log.v(LOGTAG, "TestEventHandler:headers()"); 224 } 225 expects[TEST_HEADERS] = false; 226 227 if (notExpecting[TEST_HEADERS]) { 228 expectDetails.append("Header event received but not expected"); 229 expectDetails.append("\r\n"); 230 } 231 232 /* Check through headers received for matches with expected 233 * headers */ 234 if (expectHeaders.isEmpty()) { 235 return; 236 } 237 238 for (int i = expectHeaders.size() - 1; i >= 0; i--) { 239 TestHeader h = expectHeaders.get(i); 240 System.out.println("Expected header name: " + h.name); 241 String s = null; 242 switch (h.name.hashCode()) { 243 case -1132779846: 244 s = Long.toString(headers.getContentLength()); 245 break; 246 case 785670158: 247 s = headers.getContentType(); 248 break; 249 case 2095084583: 250 s = headers.getContentEncoding(); 251 break; 252 case 1901043637: 253 s = headers.getLocation(); 254 break; 255 case -243037365: 256 s = headers.getWwwAuthenticate(); 257 break; 258 case -301767724: 259 s = headers.getProxyAuthenticate(); 260 break; 261 case -1267267485: 262 s = headers.getContentDisposition(); 263 break; 264 case 1397189435: 265 s = headers.getAcceptRanges(); 266 break; 267 case -1309235404: 268 s = headers.getExpires(); 269 break; 270 case -208775662: 271 s = headers.getCacheControl(); 272 break; 273 case 150043680: 274 s = headers.getLastModified(); 275 break; 276 case 3123477: 277 s = headers.getEtag(); 278 break; 279 case -775651618: 280 int ct = headers.getConnectionType(); 281 if (ct == Headers.CONN_CLOSE) { 282 s = HTTP.CONN_CLOSE; 283 } else if (ct == Headers.CONN_KEEP_ALIVE) { 284 s = HTTP.CONN_KEEP_ALIVE; 285 } 286 break; 287 default: 288 s = null; 289 290 } 291 if (evaluateHeader(h, s)) { 292 expectHeaders.remove(i); 293 } 294 } 295 296 } 297 298 public boolean evaluateHeader(TestHeader h, String value) { 299 if (value == null) { 300 expects[TEST_HEADERS] = true; 301 System.out.print(" Missing! "); 302 expectDetails.append(" missing header " + h.name); 303 return false; 304 } 305 if (h.value == null) { 306 System.out.println("Expect value = null"); 307 return true; 308 } 309 System.out.println("Expect value = " + 310 (h.value.toLowerCase()) + " got " + 311 value.toLowerCase()); 312 313 if (!h.value.equalsIgnoreCase(value)) { 314 expectDetails.append("expect header value " + h.value + 315 " got " + value); 316 expects[TEST_HEADERS] = true; 317 return false; 318 } 319 return true; 320 } 321 /** 322 * Implements the EventHandler locationChanged method called when a server 323 * sends a redirect message 324 * @param newLocation The URL to the new server 325 * @param permanent Indicator of whether this is a permanent change 326 */ 327 public void locationChanged(String newLocation, boolean permanent) { 328 if (Config.LOGV) { 329 Log.v(LOGTAG, "TestEventHandler: locationChanged() " + 330 newLocation + " permanent " + permanent); 331 } 332 333 eventsReceived[TEST_LOCATION_CHANGED] = true; 334 if (notExpecting[TEST_LOCATION_CHANGED]) { 335 expectDetails.append("Location changed event received but "+ 336 "not expected"); 337 expectDetails.append("\r\n"); 338 } 339 340 if (expectLocation != null) { 341 if (expectLocation.equals(newLocation)) { 342 expectLocation = null; 343 } else { 344 expectDetails.append("Location expected:"+expectLocation+ 345 " got:"+newLocation); 346 expectDetails.append("\r\n"); 347 } 348 } 349 350 if (expectPermanent != -1) { 351 if (((expectPermanent == 0) && !permanent) || 352 ((expectPermanent == 1) && permanent)){ 353 expectPermanent = -1; 354 } else { 355 expectDetails.append("Location permanent expected:"+ 356 expectPermanent+" got"+permanent); 357 expectDetails.append("\r\n"); 358 } 359 } 360 361 if ((expectLocation == null) && (expectPermanent == -1)) 362 expects[TEST_LOCATION_CHANGED] = false; 363 } 364 365 /** 366 * Implements the EventHandler data method called when a server 367 * sends content data 368 * @param data The byte array content 369 * @param len The length of the data 370 */ 371 public void data(byte[] data, int len) { 372 boolean mismatch = false; 373 374 if (Config.LOGV) { 375 Log.v(LOGTAG, "TestEventHandler: data() " + len + " bytes"); 376 } 377 378 eventsReceived[TEST_DATA] = true; 379 if (notExpecting[TEST_DATA]) { 380 expectDetails.append("Data event received but not expected"); 381 expectDetails.append("\r\n"); 382 } 383 384 Log.v(LOGTAG, new String(data, 0, len)); 385 386 if (expectDataLength != -1) { 387 if (expectDataLength == len) { 388 expectDataLength = -1; 389 } else { 390 expectDetails.append("expect data length mismatch expected:"+ 391 expectDataLength+" got:"+len); 392 expectDetails.append("\r\n"); 393 } 394 395 /* Check data only if length is the same */ 396 if ((expectDataLength == -1) && expectData != null) { 397 for (int i = 0; i < len; i++) { 398 if (expectData[i] != data[i]) { 399 mismatch = true; 400 expectDetails.append("Expect data mismatch at byte "+ 401 i+" expected:"+expectData[i]+" got:"+data[i]); 402 expectDetails.append("\r\n"); 403 break; 404 } 405 } 406 } 407 } 408 409 if ((expectDataLength == -1) || !mismatch) 410 expects[TEST_DATA] = false; 411 } 412 413 /** 414 * Implements the EventHandler endData method called to 415 * indicate completion or a request 416 */ 417 public void endData() { 418 if (Config.LOGV) { 419 Log.v(LOGTAG, "TestEventHandler: endData() called"); 420 } 421 422 eventsReceived[TEST_ENDDATA] = true; 423 if (notExpecting[TEST_ENDDATA]) { 424 expectDetails.append("End data event received but not expected"); 425 expectDetails.append("\r\n"); 426 } 427 428 expects[TEST_ENDDATA] = false; 429 430 if (useLowLevel) { 431 if (delayResponse) { 432 synchronized (syncObj) { 433 syncObj.notifyAll(); 434 } 435 } else { 436 if (netRunner != null) { 437 System.out.println("TestEventHandler: endData() stopping "+ 438 netRunner); 439 netRunner.decrementRunCount(); 440 } 441 } 442 } 443 } 444 445 /** 446 * Implements the EventHandler certificate method called every 447 * time a resource is loaded via a secure connection 448 */ 449 public void certificate(SslCertificate certificate) {} 450 451 /** 452 * Implements the EventHandler error method called when a server 453 * sends header fields 454 * @param id Status code of the error 455 * @param description Brief description of the error 456 */ 457 public void error(int id, String description) { 458 if (Config.LOGV) { 459 Log.v(LOGTAG, "TestEventHandler: error() called Id:" + id + 460 " description " + description); 461 } 462 463 eventsReceived[TEST_ERROR] = true; 464 if (notExpecting[TEST_ERROR]) { 465 expectDetails.append("Error event received but not expected"); 466 expectDetails.append("\r\n"); 467 } 468 if (expectErrorId != -1) { 469 if (expectErrorId == id) { 470 expectErrorId = -1; 471 } else { 472 expectDetails.append("Error Id expected:"+expectErrorId+ 473 " got:"+id); 474 expectDetails.append("\r\n"); 475 } 476 } 477 478 if (expectErrorId == -1) 479 expects[TEST_ERROR] = false; 480 481 if (useLowLevel) { 482 if (delayResponse) { 483 synchronized (syncObj) { 484 syncObj.notifyAll(); 485 } 486 } else { 487 if (netRunner != null) { 488 System.out.println("TestEventHandler: endData() stopping "+ 489 netRunner); 490 netRunner.decrementRunCount(); 491 } 492 } 493 } 494 } 495 496 /** 497 * SSL certificate error callback. Handles SSL error(s) on the way 498 * up to the user. 499 */ 500 public void handleSslErrorRequest(SslError error) { 501 int primaryError = error.getPrimaryError(); 502 503 if (Config.LOGV) { 504 Log.v(LOGTAG, "TestEventHandler: handleSslErrorRequest(): "+ 505 " primary error:" + primaryError + 506 " certificate: " + error.getCertificate()); 507 } 508 509 eventsReceived[TEST_SSL_CERTIFICATE_ERROR] = true; 510 if (notExpecting[TEST_SSL_CERTIFICATE_ERROR]) { 511 expectDetails.append("SSL Certificate error event received "+ 512 "but not expected"); 513 expectDetails.append("\r\n"); 514 } 515 516 if (expectSslErrors != -1) { 517 if (expectSslErrors == primaryError) { 518 expectSslErrors = -1; 519 } else { 520 expectDetails.append("SslCertificateError id expected:"+ 521 expectSslErrors+" got: " + primaryError); 522 expectDetails.append("\r\n"); 523 } 524 } 525 526 // SslCertificate match here? 527 528 if (expectSslErrors == -1) // && expectSslCertificate == certificate? 529 expects[TEST_SSL_CERTIFICATE_ERROR] = false; 530 } 531 532 /** 533 * Use the low level net runner with no delayed response 534 * @param runner The LowLevelNetRunner object 535 */ 536 public void setNetRunner(LowLevelNetRunner runner) { 537 setNetRunner(runner, false); 538 } 539 540 /** 541 * Use the low level net runner and specify if the response 542 * should be delayed 543 * @param runner The LowLevelNetRunner object 544 * @param delayedResponse Set to true is you will use the 545 * waitForRequestSent/waitForRequestResponse routines 546 */ 547 public void setNetRunner(LowLevelNetRunner runner, 548 boolean delayedResponse) { 549 netRunner = runner; 550 useLowLevel = true; 551 delayResponse = delayedResponse; 552 553 if (!delayResponse) 554 netRunner.incrementRunCount(); 555 } 556 557 /** 558 * Enable this listeners Request object to read server responses. 559 * This should only be used in conjunction with setDelayResponse(true) 560 */ 561 public void waitForRequestResponse() { 562 if (!delayResponse || !useLowLevel) { 563 Log.d(LOGTAG, " Cant do this without delayReponse set "); 564 return; 565 } 566 567 //if (mRequest != null) { 568 // mRequest.startReadingResponse(); 569 // } 570 /* Now wait for the response to be completed either through endData 571 * or an error 572 */ 573 synchronized (syncObj) { 574 try { 575 syncObj.wait(); 576 } catch (InterruptedException e) { 577 } 578 } 579 } 580 581 /** 582 * Enable this listeners Request object to read server responses. 583 * This should only be used in conjunction with setDelayResponse(true) 584 */ 585 public void waitForRequestSent() { 586 if (!delayResponse || !useLowLevel) { 587 Log.d(LOGTAG, " Cant do this without delayReponse set "); 588 return; 589 } 590 591 /* Now wait for the response to be completed either through endData 592 * or an error 593 */ 594 synchronized (syncObj) { 595 try { 596 syncObj.wait(); 597 } catch (InterruptedException e) { 598 } 599 } 600 } 601 602 /* Test expected values - these routines set the tests expectations */ 603 604 public void expectRequestSent() { 605 expects[TEST_REQUEST_SENT] = true; 606 } 607 608 public void expectNoRequestSent() { 609 notExpecting[TEST_REQUEST_SENT] = true; 610 } 611 612 public void expectStatus() { 613 expects[TEST_STATUS] = true; 614 } 615 616 public void expectNoStatus() { 617 notExpecting[TEST_STATUS] = true; 618 } 619 620 public void expectStatus(int major, int minor, int code) { 621 expects[TEST_STATUS] = true; 622 expectMajor = major; 623 expectMinor = minor; 624 expectCode = code; 625 } 626 627 public void expectStatus(int code) { 628 expects[TEST_STATUS] = true; 629 expectCode = code; 630 } 631 632 public void expectHeaders() { 633 expects[TEST_HEADERS] = true; 634 } 635 636 public void expectNoHeaders() { 637 notExpecting[TEST_HEADERS] = true; 638 } 639 640 public void expectHeaderAdd(String name) { 641 expects[TEST_HEADERS] = true; 642 TestHeader h = new TestHeader(name.toLowerCase(), null); 643 expectHeaders.add(h); 644 } 645 646 public void expectHeaderAdd(String name, String value) { 647 expects[TEST_HEADERS] = true; 648 TestHeader h = new TestHeader(name.toLowerCase(), value); 649 expectHeaders.add(h); 650 } 651 652 public void expectLocationChanged() { 653 expects[TEST_LOCATION_CHANGED] = true; 654 } 655 656 public void expectNoLocationChanged() { 657 notExpecting[TEST_LOCATION_CHANGED] = true; 658 } 659 660 public void expectLocationChanged(String newLocation) { 661 expects[TEST_LOCATION_CHANGED] = true; 662 expectLocation = newLocation; 663 } 664 665 public void expectLocationChanged(String newLocation, boolean permanent) { 666 expects[TEST_LOCATION_CHANGED] = true; 667 expectLocation = newLocation; 668 expectPermanent = permanent ? 1 : 0; 669 } 670 671 public void expectData() { 672 expects[TEST_DATA] = true; 673 } 674 675 public void expectNoData() { 676 notExpecting[TEST_DATA] = true; 677 } 678 679 public void expectData(int len) { 680 expects[TEST_DATA] = true; 681 expectDataLength = len; 682 } 683 684 public void expectData(byte[] data, int len) { 685 expects[TEST_DATA] = true; 686 expectData = new byte[len]; 687 expectDataLength = len; 688 689 for (int i = 0; i < len; i++) { 690 expectData[i] = data[i]; 691 } 692 } 693 694 public void expectEndData() { 695 expects[TEST_ENDDATA] = true; 696 } 697 698 public void expectNoEndData() { 699 notExpecting[TEST_ENDDATA] = true; 700 } 701 702 public void expectError() { 703 expects[TEST_ERROR] = true; 704 } 705 706 public void expectNoError() { 707 notExpecting[TEST_ERROR] = true; 708 } 709 710 public void expectError(int errorId) { 711 expects[TEST_ERROR] = true; 712 expectErrorId = errorId; 713 } 714 715 public void expectSSLCertificateError() { 716 expects[TEST_SSL_CERTIFICATE_ERROR] = true; 717 } 718 719 public void expectNoSSLCertificateError() { 720 notExpecting[TEST_SSL_CERTIFICATE_ERROR] = true; 721 } 722 723 public void expectSSLCertificateError(int errors) { 724 expects[TEST_SSL_CERTIFICATE_ERROR] = true; 725 expectSslErrors = errors; 726 } 727 728 public void expectSSLCertificateError(SslCertificate certificate) { 729 expects[TEST_SSL_CERTIFICATE_ERROR] = true; 730 expectCertificate = certificate; 731 } 732 733 /** 734 * Test to see if current expectations match recieved information 735 * @return True is all expected results have been matched 736 */ 737 public boolean expectPassed() { 738 for (int i = 0; i < TEST_NUM_EXPECTS; i++) { 739 if (expects[i] == true) { 740 return false; 741 } 742 } 743 744 for (int i = 0; i < TEST_NUM_EXPECTS; i++) { 745 if (eventsReceived[i] && notExpecting[i]) { 746 return false; 747 } 748 } 749 return true; 750 } 751 752 /** 753 * Return message indicating expectation failures 754 */ 755 public String getFailureMessage() { 756 return expectDetails.toString(); 757 } 758 759 /** 760 * Reset all expectation values for re-use 761 */ 762 public void resetExpects() { 763 expectMajor = -1; 764 expectMinor = -1; 765 expectCode = -1; 766 expectLocation = null; 767 expectPermanent = -1; 768 expectErrorId = -1; 769 expectSslErrors = -1; 770 expectCertificate = null; 771 expectDetails.setLength(0); 772 expectHeaders.clear(); 773 774 for (int i = 0; i < TEST_NUM_EXPECTS; i++) { 775 expects[i] = false; 776 notExpecting[i] = false; 777 eventsReceived[i] = false; 778 } 779 780 for (int i = 0; i < expectDataLength; i++) { 781 expectData[i] = 0; 782 } 783 784 expectDataLength = -1; 785 } 786 787 /** 788 * Attach the RequestHandle to this handler 789 * @param requestHandle The RequestHandle 790 */ 791 public void attachRequestHandle(RequestHandle requestHandle) { 792 if (Config.LOGV) { 793 Log.v(LOGTAG, "TestEventHandler.attachRequestHandle(): " + 794 "requestHandle: " + requestHandle); 795 } 796 mRequestHandle = requestHandle; 797 } 798 799 /** 800 * Detach the RequestHandle 801 */ 802 public void detachRequestHandle() { 803 if (Config.LOGV) { 804 Log.v(LOGTAG, "TestEventHandler.detachRequestHandle(): " + 805 "requestHandle: " + mRequestHandle); 806 } 807 mRequestHandle = null; 808 } 809 810 protected final static String LOGTAG = "http"; 811} 812