blob: 45f2f69c6006de77b88d1c43d4414e82305adf0f [file] [log] [blame]
The Android Open Source Project9066cfe2009-03-03 19:31:44 -08001/*
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 */
Grace Kloba699c6462009-08-03 11:46:44 -0700500 public boolean handleSslErrorRequest(SslError error) {
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800501 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;
Grace Kloba699c6462009-08-03 11:46:44 -0700530
531 // return false so that we won't block the thread
532 return false;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800533 }
534
535 /**
536 * Use the low level net runner with no delayed response
537 * @param runner The LowLevelNetRunner object
538 */
539 public void setNetRunner(LowLevelNetRunner runner) {
540 setNetRunner(runner, false);
541 }
542
543 /**
544 * Use the low level net runner and specify if the response
545 * should be delayed
546 * @param runner The LowLevelNetRunner object
547 * @param delayedResponse Set to true is you will use the
548 * waitForRequestSent/waitForRequestResponse routines
549 */
550 public void setNetRunner(LowLevelNetRunner runner,
551 boolean delayedResponse) {
552 netRunner = runner;
553 useLowLevel = true;
554 delayResponse = delayedResponse;
555
556 if (!delayResponse)
557 netRunner.incrementRunCount();
558 }
559
560 /**
561 * Enable this listeners Request object to read server responses.
562 * This should only be used in conjunction with setDelayResponse(true)
563 */
564 public void waitForRequestResponse() {
565 if (!delayResponse || !useLowLevel) {
566 Log.d(LOGTAG, " Cant do this without delayReponse set ");
567 return;
568 }
569
570 //if (mRequest != null) {
571 // mRequest.startReadingResponse();
572 // }
573 /* Now wait for the response to be completed either through endData
574 * or an error
575 */
576 synchronized (syncObj) {
577 try {
578 syncObj.wait();
579 } catch (InterruptedException e) {
580 }
581 }
582 }
583
584 /**
585 * Enable this listeners Request object to read server responses.
586 * This should only be used in conjunction with setDelayResponse(true)
587 */
588 public void waitForRequestSent() {
589 if (!delayResponse || !useLowLevel) {
590 Log.d(LOGTAG, " Cant do this without delayReponse set ");
591 return;
592 }
593
594 /* Now wait for the response to be completed either through endData
595 * or an error
596 */
597 synchronized (syncObj) {
598 try {
599 syncObj.wait();
600 } catch (InterruptedException e) {
601 }
602 }
603 }
604
605 /* Test expected values - these routines set the tests expectations */
606
607 public void expectRequestSent() {
608 expects[TEST_REQUEST_SENT] = true;
609 }
610
611 public void expectNoRequestSent() {
612 notExpecting[TEST_REQUEST_SENT] = true;
613 }
614
615 public void expectStatus() {
616 expects[TEST_STATUS] = true;
617 }
618
619 public void expectNoStatus() {
620 notExpecting[TEST_STATUS] = true;
621 }
622
623 public void expectStatus(int major, int minor, int code) {
624 expects[TEST_STATUS] = true;
625 expectMajor = major;
626 expectMinor = minor;
627 expectCode = code;
628 }
629
630 public void expectStatus(int code) {
631 expects[TEST_STATUS] = true;
632 expectCode = code;
633 }
634
635 public void expectHeaders() {
636 expects[TEST_HEADERS] = true;
637 }
638
639 public void expectNoHeaders() {
640 notExpecting[TEST_HEADERS] = true;
641 }
642
643 public void expectHeaderAdd(String name) {
644 expects[TEST_HEADERS] = true;
645 TestHeader h = new TestHeader(name.toLowerCase(), null);
646 expectHeaders.add(h);
647 }
648
649 public void expectHeaderAdd(String name, String value) {
650 expects[TEST_HEADERS] = true;
651 TestHeader h = new TestHeader(name.toLowerCase(), value);
652 expectHeaders.add(h);
653 }
654
655 public void expectLocationChanged() {
656 expects[TEST_LOCATION_CHANGED] = true;
657 }
658
659 public void expectNoLocationChanged() {
660 notExpecting[TEST_LOCATION_CHANGED] = true;
661 }
662
663 public void expectLocationChanged(String newLocation) {
664 expects[TEST_LOCATION_CHANGED] = true;
665 expectLocation = newLocation;
666 }
667
668 public void expectLocationChanged(String newLocation, boolean permanent) {
669 expects[TEST_LOCATION_CHANGED] = true;
670 expectLocation = newLocation;
671 expectPermanent = permanent ? 1 : 0;
672 }
673
674 public void expectData() {
675 expects[TEST_DATA] = true;
676 }
677
678 public void expectNoData() {
679 notExpecting[TEST_DATA] = true;
680 }
681
682 public void expectData(int len) {
683 expects[TEST_DATA] = true;
684 expectDataLength = len;
685 }
686
687 public void expectData(byte[] data, int len) {
688 expects[TEST_DATA] = true;
689 expectData = new byte[len];
690 expectDataLength = len;
691
692 for (int i = 0; i < len; i++) {
693 expectData[i] = data[i];
694 }
695 }
696
697 public void expectEndData() {
698 expects[TEST_ENDDATA] = true;
699 }
700
701 public void expectNoEndData() {
702 notExpecting[TEST_ENDDATA] = true;
703 }
704
705 public void expectError() {
706 expects[TEST_ERROR] = true;
707 }
708
709 public void expectNoError() {
710 notExpecting[TEST_ERROR] = true;
711 }
712
713 public void expectError(int errorId) {
714 expects[TEST_ERROR] = true;
715 expectErrorId = errorId;
716 }
717
718 public void expectSSLCertificateError() {
719 expects[TEST_SSL_CERTIFICATE_ERROR] = true;
720 }
721
722 public void expectNoSSLCertificateError() {
723 notExpecting[TEST_SSL_CERTIFICATE_ERROR] = true;
724 }
725
726 public void expectSSLCertificateError(int errors) {
727 expects[TEST_SSL_CERTIFICATE_ERROR] = true;
728 expectSslErrors = errors;
729 }
730
731 public void expectSSLCertificateError(SslCertificate certificate) {
732 expects[TEST_SSL_CERTIFICATE_ERROR] = true;
733 expectCertificate = certificate;
734 }
735
736 /**
737 * Test to see if current expectations match recieved information
738 * @return True is all expected results have been matched
739 */
740 public boolean expectPassed() {
741 for (int i = 0; i < TEST_NUM_EXPECTS; i++) {
742 if (expects[i] == true) {
743 return false;
744 }
745 }
746
747 for (int i = 0; i < TEST_NUM_EXPECTS; i++) {
748 if (eventsReceived[i] && notExpecting[i]) {
749 return false;
750 }
751 }
752 return true;
753 }
754
755 /**
756 * Return message indicating expectation failures
757 */
758 public String getFailureMessage() {
759 return expectDetails.toString();
760 }
761
762 /**
763 * Reset all expectation values for re-use
764 */
765 public void resetExpects() {
766 expectMajor = -1;
767 expectMinor = -1;
768 expectCode = -1;
769 expectLocation = null;
770 expectPermanent = -1;
771 expectErrorId = -1;
772 expectSslErrors = -1;
773 expectCertificate = null;
774 expectDetails.setLength(0);
775 expectHeaders.clear();
776
777 for (int i = 0; i < TEST_NUM_EXPECTS; i++) {
778 expects[i] = false;
779 notExpecting[i] = false;
780 eventsReceived[i] = false;
781 }
782
783 for (int i = 0; i < expectDataLength; i++) {
784 expectData[i] = 0;
785 }
786
787 expectDataLength = -1;
788 }
789
790 /**
791 * Attach the RequestHandle to this handler
792 * @param requestHandle The RequestHandle
793 */
794 public void attachRequestHandle(RequestHandle requestHandle) {
795 if (Config.LOGV) {
796 Log.v(LOGTAG, "TestEventHandler.attachRequestHandle(): " +
797 "requestHandle: " + requestHandle);
798 }
799 mRequestHandle = requestHandle;
800 }
801
802 /**
803 * Detach the RequestHandle
804 */
805 public void detachRequestHandle() {
806 if (Config.LOGV) {
807 Log.v(LOGTAG, "TestEventHandler.detachRequestHandle(): " +
808 "requestHandle: " + mRequestHandle);
809 }
810 mRequestHandle = null;
811 }
812
813 protected final static String LOGTAG = "http";
814}