android.core.TestEventHandler.java Source code

Java tutorial

Introduction

Here is the source code for android.core.TestEventHandler.java

Source

/*
 * Copyright (C) 2007 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package android.core;

import java.util.ArrayList;
import java.util.Map;

import org.apache.http.protocol.HTTP;
import android.util.Log;
import android.net.http.*;

/**
 * Implements EventHandler and provides test functionality to validate
 * responses to requests from the test server
 */
public class TestEventHandler implements EventHandler {

    /**
     * Status variables
     */
    private int majorVersion = -1;
    private int minorVersion = -1;
    private int responseCode = -1;
    private String reasonPhrase;

    /* List of headers received */
    private Map<String, String> headerMap;

    /* Used to sync low level delayed requests */
    public static final Object syncObj = new Object();

    /* Indicates whether the low level request testing is in operation */
    private boolean useLowLevel = false;

    /* Indicates whether responses should be automatically generated or
     * delayed
     */
    private boolean delayResponse = false;

    /* Test method expectation identifiers */
    public final static int TEST_REQUEST_SENT = 0;
    public final static int TEST_STATUS = 1;
    public final static int TEST_HEADERS = 2;
    public final static int TEST_LOCATION_CHANGED = 3;
    public final static int TEST_DATA = 4;
    public final static int TEST_ENDDATA = 5;
    public final static int TEST_ERROR = 6;
    public final static int TEST_SSL_CERTIFICATE_ERROR = 7;

    public final static int TEST_NUM_EXPECTS = 8;

    /* Expected status codes */
    private int expectMajor = -1;
    private int expectMinor = -1;
    private int expectCode = -1;

    /* Array indicating which event types are expected */
    private boolean[] expects = new boolean[TEST_NUM_EXPECTS];

    /* Array indicating which event types are not expected */
    private boolean[] notExpecting = new boolean[TEST_NUM_EXPECTS];

    /* Indicates which events have been received */
    private boolean[] eventsReceived = new boolean[TEST_NUM_EXPECTS];

    /* Redirection variables */
    private String expectLocation;
    private int expectPermanent = -1;

    /* Content data expected to be received */
    private byte[] expectData;
    private int expectDataLength = -1;

    private int expectErrorId = -1;

    private int expectSslErrors = -1;
    private SslCertificate expectCertificate;

    public class TestHeader {
        public TestHeader(String n, String v) {
            name = n;
            value = v;
        }

        public String name;
        public String value;
    }

    private ArrayList<TestHeader> expectHeaders = new ArrayList<TestHeader>();

    /* Holds failure details */
    private StringBuffer expectDetails = new StringBuffer();

    /* If we use a request handle, we retain a reference here for redirects
     * using setupRedirect
     */
    private RequestHandle mRequestHandle;

    /* The low level API uses this reference also for non-delayed requests */
    private LowLevelNetRunner netRunner;

    public TestEventHandler() {
        for (int i = 0; i < TEST_NUM_EXPECTS; i++) {
            expects[i] = false;
            notExpecting[i] = false;
            eventsReceived[i] = false;
        }
    }

    /**
     * Implementation of EventHandler method called when a request has been
     * sent. If the test is waiting for this call, it will be signalled,
     * otherwise this method will trigger the response to be read
     * automatically.
     */
    public void requestSent() {
        Log.v(LOGTAG, "TestEventHandler:requestSent()");
        expects[TEST_REQUEST_SENT] = false;
        eventsReceived[TEST_REQUEST_SENT] = true;
        if (notExpecting[TEST_REQUEST_SENT]) {
            expectDetails.append("Request sent event received but not expected");
            expectDetails.append("\r\n");
        }

        if (useLowLevel) {
            if (delayResponse) {
                synchronized (syncObj) {
                    syncObj.notifyAll();
                }
            } else {
                // mRequest.startReadingResponse();
            }
        }
    }

    /**
     * Implements the EventHandler status method called when a server status
     * response is received.
     * @param major_version The HTTP major version
     * @param minor_version The HTTP minor version
     * @param code The status code
     * @param reason_phrase A reason phrase passed to us by the server
     */
    public void status(int major_version, int minor_version, int code, String reason_phrase) {
        if (false) {
            Log.v(LOGTAG, "TestEventHandler:status() major: " + major_version + " minor: " + minor_version
                    + " code: " + code + " reason: " + reason_phrase);
        }

        eventsReceived[TEST_STATUS] = true;
        if (notExpecting[TEST_STATUS]) {
            expectDetails.append("Status event received but not expected");
            expectDetails.append("\r\n");
        }

        majorVersion = major_version;
        minorVersion = minor_version;
        responseCode = code;
        reasonPhrase = reason_phrase;

        if (expectMajor != -1) {
            if (expectMajor == major_version) {
                expectMajor = -1;
            } else {
                expectDetails.append("Major version expected:" + expectMajor + " got:" + major_version);
                expectDetails.append("\r\n");
            }
        }

        if (expectMinor != -1) {
            if (expectMinor == minor_version) {
                expectMinor = -1;
            } else {
                expectDetails.append("Minor version expected:" + expectMinor + " got:" + minor_version);
                expectDetails.append("\r\n");
            }
        }

        if (expectCode != -1) {
            if (expectCode == code) {
                expectCode = -1;
            } else {
                expectDetails.append("Status code expected:" + expectCode + " got:" + code);
                expectDetails.append("\r\n");
            }
        }

        if ((expectMajor == -1) && (expectMinor == -1) && (expectCode == -1)) {
            expects[TEST_STATUS] = false;
        } else {
            System.out.println("MAJOR = " + expectMajor + " MINOR = " + expectMinor + " CODE = " + expectCode);
        }
    }

    /**
     * Implements the EventHandler headers method called when a server
     * sends header fields
     */
    public void headers(Headers headers) {
        if (false) {
            Log.v(LOGTAG, "TestEventHandler:headers()");
        }
        expects[TEST_HEADERS] = false;

        if (notExpecting[TEST_HEADERS]) {
            expectDetails.append("Header event received but not expected");
            expectDetails.append("\r\n");
        }

        /* Check through headers received for matches with expected
         * headers */
        if (expectHeaders.isEmpty()) {
            return;
        }

        for (int i = expectHeaders.size() - 1; i >= 0; i--) {
            TestHeader h = expectHeaders.get(i);
            System.out.println("Expected header name: " + h.name);
            String s = null;
            switch (h.name.hashCode()) {
            case -1132779846:
                s = Long.toString(headers.getContentLength());
                break;
            case 785670158:
                s = headers.getContentType();
                break;
            case 2095084583:
                s = headers.getContentEncoding();
                break;
            case 1901043637:
                s = headers.getLocation();
                break;
            case -243037365:
                s = headers.getWwwAuthenticate();
                break;
            case -301767724:
                s = headers.getProxyAuthenticate();
                break;
            case -1267267485:
                s = headers.getContentDisposition();
                break;
            case 1397189435:
                s = headers.getAcceptRanges();
                break;
            case -1309235404:
                s = headers.getExpires();
                break;
            case -208775662:
                s = headers.getCacheControl();
                break;
            case 150043680:
                s = headers.getLastModified();
                break;
            case 3123477:
                s = headers.getEtag();
                break;
            case -775651618:
                int ct = headers.getConnectionType();
                if (ct == Headers.CONN_CLOSE) {
                    s = HTTP.CONN_CLOSE;
                } else if (ct == Headers.CONN_KEEP_ALIVE) {
                    s = HTTP.CONN_KEEP_ALIVE;
                }
                break;
            default:
                s = null;

            }
            if (evaluateHeader(h, s)) {
                expectHeaders.remove(i);
            }
        }

    }

    public boolean evaluateHeader(TestHeader h, String value) {
        if (value == null) {
            expects[TEST_HEADERS] = true;
            System.out.print(" Missing!  ");
            expectDetails.append(" missing header " + h.name);
            return false;
        }
        if (h.value == null) {
            System.out.println("Expect value = null");
            return true;
        }
        System.out.println("Expect value = " + (h.value.toLowerCase()) + " got " + value.toLowerCase());

        if (!h.value.equalsIgnoreCase(value)) {
            expectDetails.append("expect header value " + h.value + " got " + value);
            expects[TEST_HEADERS] = true;
            return false;
        }
        return true;
    }

    /**
     * Implements the EventHandler locationChanged method called when a server
     * sends a redirect message
     * @param newLocation The URL to the new server
     * @param permanent Indicator of whether this is a permanent change
     */
    public void locationChanged(String newLocation, boolean permanent) {
        if (false) {
            Log.v(LOGTAG, "TestEventHandler: locationChanged() " + newLocation + " permanent " + permanent);
        }

        eventsReceived[TEST_LOCATION_CHANGED] = true;
        if (notExpecting[TEST_LOCATION_CHANGED]) {
            expectDetails.append("Location changed event received but " + "not expected");
            expectDetails.append("\r\n");
        }

        if (expectLocation != null) {
            if (expectLocation.equals(newLocation)) {
                expectLocation = null;
            } else {
                expectDetails.append("Location expected:" + expectLocation + " got:" + newLocation);
                expectDetails.append("\r\n");
            }
        }

        if (expectPermanent != -1) {
            if (((expectPermanent == 0) && !permanent) || ((expectPermanent == 1) && permanent)) {
                expectPermanent = -1;
            } else {
                expectDetails.append("Location permanent expected:" + expectPermanent + " got" + permanent);
                expectDetails.append("\r\n");
            }
        }

        if ((expectLocation == null) && (expectPermanent == -1))
            expects[TEST_LOCATION_CHANGED] = false;
    }

    /**
     * Implements the EventHandler data method called when a server
     * sends content data
     * @param data The byte array content
     * @param len The length of the data
     */
    public void data(byte[] data, int len) {
        boolean mismatch = false;

        if (false) {
            Log.v(LOGTAG, "TestEventHandler: data() " + len + " bytes");
        }

        eventsReceived[TEST_DATA] = true;
        if (notExpecting[TEST_DATA]) {
            expectDetails.append("Data event received but not expected");
            expectDetails.append("\r\n");
        }

        Log.v(LOGTAG, new String(data, 0, len));

        if (expectDataLength != -1) {
            if (expectDataLength == len) {
                expectDataLength = -1;
            } else {
                expectDetails.append("expect data length mismatch expected:" + expectDataLength + " got:" + len);
                expectDetails.append("\r\n");
            }

            /* Check data only if length is the same */
            if ((expectDataLength == -1) && expectData != null) {
                for (int i = 0; i < len; i++) {
                    if (expectData[i] != data[i]) {
                        mismatch = true;
                        expectDetails.append("Expect data mismatch at byte " + i + " expected:" + expectData[i]
                                + " got:" + data[i]);
                        expectDetails.append("\r\n");
                        break;
                    }
                }
            }
        }

        if ((expectDataLength == -1) || !mismatch)
            expects[TEST_DATA] = false;
    }

    /**
     * Implements the EventHandler endData method called to
     * indicate completion or a request
     */
    public void endData() {
        if (false) {
            Log.v(LOGTAG, "TestEventHandler: endData() called");
        }

        eventsReceived[TEST_ENDDATA] = true;
        if (notExpecting[TEST_ENDDATA]) {
            expectDetails.append("End data event received but not expected");
            expectDetails.append("\r\n");
        }

        expects[TEST_ENDDATA] = false;

        if (useLowLevel) {
            if (delayResponse) {
                synchronized (syncObj) {
                    syncObj.notifyAll();
                }
            } else {
                if (netRunner != null) {
                    System.out.println("TestEventHandler: endData() stopping " + netRunner);
                    netRunner.decrementRunCount();
                }
            }
        }
    }

    /**
     * Implements the EventHandler certificate method called every
     * time a resource is loaded via a secure connection
     */
    public void certificate(SslCertificate certificate) {
    }

    /**
     * Implements the EventHandler error method called when a server
     * sends header fields
     * @param id Status code of the error
     * @param description Brief description of the error
     */
    public void error(int id, String description) {
        if (false) {
            Log.v(LOGTAG, "TestEventHandler: error() called Id:" + id + " description " + description);
        }

        eventsReceived[TEST_ERROR] = true;
        if (notExpecting[TEST_ERROR]) {
            expectDetails.append("Error event received but not expected");
            expectDetails.append("\r\n");
        }
        if (expectErrorId != -1) {
            if (expectErrorId == id) {
                expectErrorId = -1;
            } else {
                expectDetails.append("Error Id expected:" + expectErrorId + " got:" + id);
                expectDetails.append("\r\n");
            }
        }

        if (expectErrorId == -1)
            expects[TEST_ERROR] = false;

        if (useLowLevel) {
            if (delayResponse) {
                synchronized (syncObj) {
                    syncObj.notifyAll();
                }
            } else {
                if (netRunner != null) {
                    System.out.println("TestEventHandler: endData() stopping " + netRunner);
                    netRunner.decrementRunCount();
                }
            }
        }
    }

    /**
     * SSL certificate error callback. Handles SSL error(s) on the way
     * up to the user.
     */
    public boolean handleSslErrorRequest(SslError error) {
        int primaryError = error.getPrimaryError();

        if (false) {
            Log.v(LOGTAG, "TestEventHandler: handleSslErrorRequest(): " + " primary error:" + primaryError
                    + " certificate: " + error.getCertificate());
        }

        eventsReceived[TEST_SSL_CERTIFICATE_ERROR] = true;
        if (notExpecting[TEST_SSL_CERTIFICATE_ERROR]) {
            expectDetails.append("SSL Certificate error event received " + "but not expected");
            expectDetails.append("\r\n");
        }

        if (expectSslErrors != -1) {
            if (expectSslErrors == primaryError) {
                expectSslErrors = -1;
            } else {
                expectDetails
                        .append("SslCertificateError id expected:" + expectSslErrors + " got: " + primaryError);
                expectDetails.append("\r\n");
            }
        }

        // SslCertificate match here?

        if (expectSslErrors == -1) // && expectSslCertificate == certificate?
            expects[TEST_SSL_CERTIFICATE_ERROR] = false;

        // return false so that we won't block the thread
        return false;
    }

    /**
     * Use the low level net runner with no delayed response
     * @param runner The LowLevelNetRunner object
     */
    public void setNetRunner(LowLevelNetRunner runner) {
        setNetRunner(runner, false);
    }

    /**
     * Use the low level net runner and specify if the response
     * should be delayed
     * @param runner The LowLevelNetRunner object
     * @param delayedResponse Set to true is you will use the
     * waitForRequestSent/waitForRequestResponse routines
     */
    public void setNetRunner(LowLevelNetRunner runner, boolean delayedResponse) {
        netRunner = runner;
        useLowLevel = true;
        delayResponse = delayedResponse;

        if (!delayResponse)
            netRunner.incrementRunCount();
    }

    /**
     * Enable this listeners Request object to read server responses.
     * This should only be used in conjunction with setDelayResponse(true)
     */
    public void waitForRequestResponse() {
        if (!delayResponse || !useLowLevel) {
            Log.d(LOGTAG, " Cant do this without delayReponse set ");
            return;
        }

        //if (mRequest != null) {
        // mRequest.startReadingResponse();
        // }
        /* Now wait for the response to be completed either through endData
         * or an error
         */
        synchronized (syncObj) {
            try {
                syncObj.wait();
            } catch (InterruptedException e) {
            }
        }
    }

    /**
     * Enable this listeners Request object to read server responses.
     * This should only be used in conjunction with setDelayResponse(true)
     */
    public void waitForRequestSent() {
        if (!delayResponse || !useLowLevel) {
            Log.d(LOGTAG, " Cant do this without delayReponse set ");
            return;
        }

        /* Now wait for the response to be completed either through endData
         * or an error
         */
        synchronized (syncObj) {
            try {
                syncObj.wait();
            } catch (InterruptedException e) {
            }
        }
    }

    /* Test expected values - these routines set the tests expectations */

    public void expectRequestSent() {
        expects[TEST_REQUEST_SENT] = true;
    }

    public void expectNoRequestSent() {
        notExpecting[TEST_REQUEST_SENT] = true;
    }

    public void expectStatus() {
        expects[TEST_STATUS] = true;
    }

    public void expectNoStatus() {
        notExpecting[TEST_STATUS] = true;
    }

    public void expectStatus(int major, int minor, int code) {
        expects[TEST_STATUS] = true;
        expectMajor = major;
        expectMinor = minor;
        expectCode = code;
    }

    public void expectStatus(int code) {
        expects[TEST_STATUS] = true;
        expectCode = code;
    }

    public void expectHeaders() {
        expects[TEST_HEADERS] = true;
    }

    public void expectNoHeaders() {
        notExpecting[TEST_HEADERS] = true;
    }

    public void expectHeaderAdd(String name) {
        expects[TEST_HEADERS] = true;
        TestHeader h = new TestHeader(name.toLowerCase(), null);
        expectHeaders.add(h);
    }

    public void expectHeaderAdd(String name, String value) {
        expects[TEST_HEADERS] = true;
        TestHeader h = new TestHeader(name.toLowerCase(), value);
        expectHeaders.add(h);
    }

    public void expectLocationChanged() {
        expects[TEST_LOCATION_CHANGED] = true;
    }

    public void expectNoLocationChanged() {
        notExpecting[TEST_LOCATION_CHANGED] = true;
    }

    public void expectLocationChanged(String newLocation) {
        expects[TEST_LOCATION_CHANGED] = true;
        expectLocation = newLocation;
    }

    public void expectLocationChanged(String newLocation, boolean permanent) {
        expects[TEST_LOCATION_CHANGED] = true;
        expectLocation = newLocation;
        expectPermanent = permanent ? 1 : 0;
    }

    public void expectData() {
        expects[TEST_DATA] = true;
    }

    public void expectNoData() {
        notExpecting[TEST_DATA] = true;
    }

    public void expectData(int len) {
        expects[TEST_DATA] = true;
        expectDataLength = len;
    }

    public void expectData(byte[] data, int len) {
        expects[TEST_DATA] = true;
        expectData = new byte[len];
        expectDataLength = len;

        for (int i = 0; i < len; i++) {
            expectData[i] = data[i];
        }
    }

    public void expectEndData() {
        expects[TEST_ENDDATA] = true;
    }

    public void expectNoEndData() {
        notExpecting[TEST_ENDDATA] = true;
    }

    public void expectError() {
        expects[TEST_ERROR] = true;
    }

    public void expectNoError() {
        notExpecting[TEST_ERROR] = true;
    }

    public void expectError(int errorId) {
        expects[TEST_ERROR] = true;
        expectErrorId = errorId;
    }

    public void expectSSLCertificateError() {
        expects[TEST_SSL_CERTIFICATE_ERROR] = true;
    }

    public void expectNoSSLCertificateError() {
        notExpecting[TEST_SSL_CERTIFICATE_ERROR] = true;
    }

    public void expectSSLCertificateError(int errors) {
        expects[TEST_SSL_CERTIFICATE_ERROR] = true;
        expectSslErrors = errors;
    }

    public void expectSSLCertificateError(SslCertificate certificate) {
        expects[TEST_SSL_CERTIFICATE_ERROR] = true;
        expectCertificate = certificate;
    }

    /**
     * Test to see if current expectations match recieved information
     * @return True is all expected results have been matched
     */
    public boolean expectPassed() {
        for (int i = 0; i < TEST_NUM_EXPECTS; i++) {
            if (expects[i] == true) {
                return false;
            }
        }

        for (int i = 0; i < TEST_NUM_EXPECTS; i++) {
            if (eventsReceived[i] && notExpecting[i]) {
                return false;
            }
        }
        return true;
    }

    /**
     * Return message indicating expectation failures
     */
    public String getFailureMessage() {
        return expectDetails.toString();
    }

    /**
     * Reset all expectation values for re-use
     */
    public void resetExpects() {
        expectMajor = -1;
        expectMinor = -1;
        expectCode = -1;
        expectLocation = null;
        expectPermanent = -1;
        expectErrorId = -1;
        expectSslErrors = -1;
        expectCertificate = null;
        expectDetails.setLength(0);
        expectHeaders.clear();

        for (int i = 0; i < TEST_NUM_EXPECTS; i++) {
            expects[i] = false;
            notExpecting[i] = false;
            eventsReceived[i] = false;
        }

        for (int i = 0; i < expectDataLength; i++) {
            expectData[i] = 0;
        }

        expectDataLength = -1;
    }

    /**
     * Attach the RequestHandle to this handler
     * @param requestHandle The RequestHandle
     */
    public void attachRequestHandle(RequestHandle requestHandle) {
        if (false) {
            Log.v(LOGTAG, "TestEventHandler.attachRequestHandle(): " + "requestHandle: " + requestHandle);
        }
        mRequestHandle = requestHandle;
    }

    /**
     * Detach the RequestHandle
     */
    public void detachRequestHandle() {
        if (false) {
            Log.v(LOGTAG, "TestEventHandler.detachRequestHandle(): " + "requestHandle: " + mRequestHandle);
        }
        mRequestHandle = null;
    }

    protected final static String LOGTAG = "http";
}