com.scvngr.levelup.core.net.LevelUpResponseTest.java Source code

Java tutorial

Introduction

Here is the source code for com.scvngr.levelup.core.net.LevelUpResponseTest.java

Source

/*
 * Copyright (C) 2014 SCVNGR, Inc. d/b/a LevelUp
 *
 * 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 com.scvngr.levelup.core.net;

import android.support.annotation.NonNull;
import android.test.MoreAsserts;
import android.test.suitebuilder.annotation.SmallTest;

import com.scvngr.levelup.core.model.Error;
import com.scvngr.levelup.core.model.ErrorFixture;
import com.scvngr.levelup.core.net.AbstractRequest.BadRequestException;
import com.scvngr.levelup.core.net.BufferedResponse.ResponseTooLargeException;
import com.scvngr.levelup.core.net.error.ErrorCode;
import com.scvngr.levelup.core.net.error.ErrorObject;
import com.scvngr.levelup.core.test.ParcelTestUtils;
import com.scvngr.levelup.core.test.SupportAndroidTestCase;

import org.json.JSONArray;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.LinkedList;
import java.util.List;

import static com.scvngr.levelup.core.util.NullUtils.nonNullContract;

/**
 * Tests {@link com.scvngr.levelup.core.net.LevelUpResponse}.
 */
public final class LevelUpResponseTest extends SupportAndroidTestCase {
    @NonNull
    private static final String SERVER_LEVELUP_PLATFORM = "LevelUp";

    @NonNull
    private static final String SERVER_NOT_LEVELUP_PLATFORM = "LevelUp/Failover";

    @NonNull
    private static final String EMPTY = "";

    @NonNull
    private static final Error mError1 = new Error("debit_card_only", "message1", "credit_card", "property1");

    @NonNull
    private static final Error mError2 = new Error("delinquent_bundle", "message2", "payment_token", "property2");

    /**
     * Tests {@link com.scvngr.levelup.core.net.LevelUpResponse} parceling.
     */
    @SmallTest
    public void testParcelable() {
        final JSONArray errorArray = new JSONArray();
        errorArray.put(ErrorFixture.getJsonObjectFromModel(mError1));
        final LevelUpResponse response = new LevelUpResponse(errorArray.toString(), LevelUpStatus.ERROR_SERVER);
        final LevelUpResponse parceledResponse = ParcelTestUtils.feedThroughParceling(response);
        assertEquals("resulting Parcelable differs. ", response, parceledResponse);

        final LevelUpResponse exceptionResponse = new LevelUpResponse("test", LevelUpStatus.ERROR_SERVER);
        final LevelUpResponse parceledExceptionResponse = ParcelTestUtils.feedThroughParceling(exceptionResponse);
        assertEquals("resulting Parcelable differs. ", exceptionResponse, parceledExceptionResponse);
        assertEquals(exceptionResponse.getError().getMessage(), parceledExceptionResponse.getError().getMessage());

        final LevelUpResponse okResponse = new LevelUpResponse("test", LevelUpStatus.OK);
        final LevelUpResponse parceledOkResponse = ParcelTestUtils.feedThroughParceling(okResponse);
        assertEquals("resulting Parcelable differs. ", okResponse, parceledOkResponse);
    }

    /**
     * Tests {@link com.scvngr.levelup.core.net.LevelUpResponse#mapStatus(int, String)}.
     */
    @SmallTest
    public void testMapStatusHttp_okCode() {
        assertEquals(LevelUpStatus.OK,
                LevelUpResponse.mapStatus(HttpURLConnection.HTTP_OK, SERVER_LEVELUP_PLATFORM));
    }

    /**
     * Tests {@link LevelUpResponse#mapStatus(int, String)} with a sub-200 response code.
     */
    @SmallTest
    public void testMapStatusHttp_okCode_notFromPlatform() {
        assertEquals(LevelUpStatus.OK,
                LevelUpResponse.mapStatus(HttpURLConnection.HTTP_OK, SERVER_NOT_LEVELUP_PLATFORM));
    }

    /**
     * Tests {@link com.scvngr.levelup.core.net.LevelUpResponse#mapStatus(int, String)} with a
     * sub-200 response code.
     */
    @SmallTest
    public void testMapStatusHttp_errorCodeLow() {
        assertEquals(LevelUpStatus.ERROR_SERVER, LevelUpResponse.mapStatus(100, SERVER_LEVELUP_PLATFORM));
    }

    /**
     * Tests {@link com.scvngr.levelup.core.net.LevelUpResponse#mapStatus(int, String)}.
     */
    @SmallTest
    public void testMapStatusHttp_errorCodeLow_notFromPlatform() {
        assertEquals(LevelUpStatus.ERROR_SERVER, LevelUpResponse.mapStatus(100, SERVER_NOT_LEVELUP_PLATFORM));
    }

    /**
     * Tests {@link com.scvngr.levelup.core.net.LevelUpResponse#mapStatus(int, String)} with an
     * unknown code above the 2xx range.
     *
     */
    @SmallTest
    public void testMapStatusHttp_errorCodeUnknown() {
        assertEquals(LevelUpStatus.ERROR_SERVER, LevelUpResponse.mapStatus(300, SERVER_LEVELUP_PLATFORM));
    }

    /**
     * Tests {@link com.scvngr.levelup.core.net.LevelUpResponse#mapStatus(int, String)} with an
     * unknown code above the 2xx range.
     */
    @SmallTest
    public void testMapStatusHttp_errorCodeUnknown_notFromPlatform() {
        assertEquals(LevelUpStatus.ERROR_SERVER, LevelUpResponse.mapStatus(300, SERVER_NOT_LEVELUP_PLATFORM));
    }

    /**
     * Tests {@link com.scvngr.levelup.core.net.LevelUpResponse#mapStatus(int, String)}.
     */
    @SmallTest
    public void testMapStatusHttp_errorCodeNotFound() {
        assertEquals(LevelUpStatus.ERROR_NOT_FOUND,
                LevelUpResponse.mapStatus(HttpURLConnection.HTTP_NOT_FOUND, SERVER_LEVELUP_PLATFORM));
    }

    /**
     * Tests {@link com.scvngr.levelup.core.net.LevelUpResponse#mapStatus(int, String)}. 404s should
     * be treated as generic server failures if the response is coming from a server other than
     * LevelUp Platform.
     */
    @SmallTest
    public void testMapStatusHttp_errorCodeNotFound_notFromPlatform() {
        assertEquals(LevelUpStatus.ERROR_SERVER,
                LevelUpResponse.mapStatus(HttpURLConnection.HTTP_NOT_FOUND, SERVER_NOT_LEVELUP_PLATFORM));
    }

    /**
     * Tests {@link com.scvngr.levelup.core.net.LevelUpResponse#mapStatus(int, String)}.
     */
    @SmallTest
    public void testMapStatusHttp_errorCodeRedirection() {
        assertEquals(LevelUpStatus.ERROR_SERVER,
                LevelUpResponse.mapStatus(HttpURLConnection.HTTP_MULT_CHOICE, SERVER_LEVELUP_PLATFORM));
    }

    /**
     * Tests {@link com.scvngr.levelup.core.net.LevelUpResponse#mapStatus(int, String)}.
     */
    @SmallTest
    public void testMapStatusHttp_errorCodeClientError() {
        assertEquals(LevelUpStatus.ERROR_SERVER,
                LevelUpResponse.mapStatus(HttpURLConnection.HTTP_BAD_REQUEST, SERVER_LEVELUP_PLATFORM));
    }

    /**
     * Tests {@link com.scvngr.levelup.core.net.LevelUpResponse#mapStatus(int, String)}.
     */
    @SmallTest
    public void testMapStatusHttp_errorCodeMaintenenace() {
        assertEquals(LevelUpStatus.ERROR_MAINTENANCE,
                LevelUpResponse.mapStatus(HttpURLConnection.HTTP_UNAVAILABLE, SERVER_LEVELUP_PLATFORM));
    }

    /**
     * Tests {@link com.scvngr.levelup.core.net.LevelUpResponse#mapStatus(int, String)}. Maintenance
     * mode applies even for responses not coming directly from LevelUp Platform.
     */
    @SmallTest
    public void testMapStatusHttp_errorCodeMaintenenace_notFromPlatform() {
        assertEquals(LevelUpStatus.ERROR_MAINTENANCE,
                LevelUpResponse.mapStatus(HttpURLConnection.HTTP_UNAVAILABLE, SERVER_NOT_LEVELUP_PLATFORM));
    }

    /**
     * Tests {@link com.scvngr.levelup.core.net.LevelUpResponse#mapStatus(int, String)}.
     */
    @SmallTest
    public void testMapStatusHttp_errorCodeUpgrade() {
        assertEquals(LevelUpStatus.UPGRADE,
                LevelUpResponse.mapStatus(HttpURLConnection.HTTP_NOT_IMPLEMENTED, SERVER_LEVELUP_PLATFORM));
    }

    /**
     * Tests {@link LevelUpResponse#mapStatus(int, String)}. Responses not coming from LevelUp
     * Platform should be treated as generic errors rather than upgrade-required messages.
     */
    @SmallTest
    public void testMapStatusHttp_errorCodeUpgrade_notFromLevelUp() {
        assertEquals(LevelUpStatus.ERROR_SERVER,
                LevelUpResponse.mapStatus(HttpURLConnection.HTTP_NOT_IMPLEMENTED, SERVER_NOT_LEVELUP_PLATFORM));
    }

    /**
     * Tests {@link com.scvngr.levelup.core.net.LevelUpResponse#mapStatus(Exception)}.
     */
    @SmallTest
    public void testMapStatusException_tooLarge() {
        assertEquals(LevelUpStatus.ERROR_RESPONSE_TOO_LARGE,
                LevelUpResponse.mapStatus(new ResponseTooLargeException()));
    }

    /**
     * Tests {@link com.scvngr.levelup.core.net.LevelUpResponse#mapStatus(Exception)}.
     */
    @SmallTest
    public void testMapStatusException_badRequest() {
        assertEquals(LevelUpStatus.ERROR_BAD_REQUEST, LevelUpResponse.mapStatus(new BadRequestException("")));
    }

    /**
     * Tests {@link com.scvngr.levelup.core.net.LevelUpResponse#mapStatus(Exception)}.
     */
    @SmallTest
    public void testMapStatusException_ioException() {
        assertEquals(LevelUpStatus.ERROR_NETWORK, LevelUpResponse.mapStatus(new IOException()));
    }

    /**
     * Tests {@link com.scvngr.levelup.core.net.LevelUpResponse#mapStatus(com.scvngr.levelup.core.net.StreamingResponse)}.
     *
     * @throws Exception if the URL in the mock object is malformed (i.e. it won't throw this)
     */
    @SmallTest
    public void testMapStatusResponse_responseWithoutError() throws Exception {
        final StreamingResponse response = new StreamingResponse(new MockHttpUrlConnection());

        assertEquals(LevelUpStatus.OK, LevelUpResponse.mapStatus(response));
    }

    /**
     * Tests {@link LevelUpResponse#mapStatus(com.scvngr.levelup.core.net.StreamingResponse)}.
     * Tests that a response with an error doesn't use the status code to determine the status, but
     * uses the exception in the response object.
     */
    @SmallTest
    public void testMapStatusResponse_responseWithError() {
        final StreamingResponse response = new StreamingResponse(new ResponseTooLargeException());

        assertEquals(LevelUpStatus.ERROR_RESPONSE_TOO_LARGE, LevelUpResponse.mapStatus(response));
    }

    /**
     * Tests {@link com.scvngr.levelup.core.net.LevelUpResponse#mapStatus(com.scvngr.levelup.core.net.StreamingResponse, Exception)}.
     *
     * @throws Exception if the URL in the mock object is malformed (i.e. it won't throw this)
     */
    @SmallTest
    public void testMapStatusResponseException_noError() throws Exception {
        final StreamingResponse response = new StreamingResponse(new MockHttpUrlConnection());

        assertEquals(LevelUpStatus.OK, LevelUpResponse.mapStatus(response, null));
    }

    /**
     * Tests {@link com.scvngr.levelup.core.net.LevelUpResponse#mapStatus(com.scvngr.levelup.core.net.StreamingResponse, Exception)}. Tests that passing an
     * error with the response doesn't use the status code to determine the status, but uses the
     * exception passed.
     *
     * @throws Exception if the URL in the mock object is malformed (i.e. it won't throw this)
     */
    @SmallTest
    public void testMapStatusResponseException_withError() throws Exception {
        final StreamingResponse response = new StreamingResponse(new MockHttpUrlConnection());

        assertEquals(LevelUpStatus.ERROR_RESPONSE_TOO_LARGE,
                LevelUpResponse.mapStatus(response, new ResponseTooLargeException()));
    }

    /**
     * Tests {@link com.scvngr.levelup.core.net.LevelUpResponse#mapStatus(com.scvngr.levelup.core.net.StreamingResponse, Exception)}. Tests that passing an
     * error with the response doesn't use the status code or response error to determine the
     * status, but uses the exception passed.
     */
    @SmallTest
    public void testMapStatusResponseException_withErrorAndResponseError() {
        final StreamingResponse response = new StreamingResponse(new ResponseTooLargeException());

        assertEquals(LevelUpStatus.ERROR_NETWORK, LevelUpResponse.mapStatus(response, new IOException()));
    }

    /**
     * Tests the {@link com.scvngr.levelup.core.net.LevelUpResponse#equals(Object)} and
     * {@link com.scvngr.levelup.core.net.LevelUpResponse#hashCode()} methods.
     *
     * @throws Exception if {@link com.scvngr.levelup.core.net.LevelUpResponseTest.MockHttpUrlConnection}
     * throws
     */
    @SmallTest
    public void testEqualsAndHashCode() throws Exception {
        final StreamingResponse baseResponse = new StreamingResponse();
        LevelUpResponse response1 = new LevelUpResponse(baseResponse);
        LevelUpResponse response2 = new LevelUpResponse(baseResponse);

        // Same base response should be the same
        MoreAsserts.checkEqualsAndHashCodeMethods(response1, response2, true);

        // New object should be the same.
        response2 = new LevelUpResponse(new StreamingResponse());
        MoreAsserts.checkEqualsAndHashCodeMethods(response1, response2, true);

        // Null shouldn't be the same
        MoreAsserts.checkEqualsAndHashCodeMethods(response1, null, false);

        // Differing data
        response2 = new LevelUpResponse(new StreamingResponse(new MockHttpUrlConnection()));
        MoreAsserts.checkEqualsAndHashCodeMethods(response1, response2, false);

        // Now have the same response data.
        response1 = new LevelUpResponse(new StreamingResponse(new MockHttpUrlConnection()));
        MoreAsserts.checkEqualsAndHashCodeMethods(response1, response2, true);

        // Reset to initial
        response1 = new LevelUpResponse(baseResponse);

        // Build response 2 from error
        response2 = new LevelUpResponse(new StreamingResponse(new ResponseTooLargeException()));
        MoreAsserts.checkEqualsAndHashCodeMethods(response1, response2, false);

        // Match it with response 1
        response1 = new LevelUpResponse(new StreamingResponse(new ResponseTooLargeException()));
        MoreAsserts.checkEqualsAndHashCodeMethods(response1, response2, true);

        // Build response 2 from error
        response2 = new LevelUpResponse(new StreamingResponse(new IOException()));
        MoreAsserts.checkEqualsAndHashCodeMethods(response1, response2, false);

        // Match it with response 1
        response1 = new LevelUpResponse(new StreamingResponse(new IOException()));
        MoreAsserts.checkEqualsAndHashCodeMethods(response1, response2, true);

        response2 = null;
        MoreAsserts.checkEqualsAndHashCodeMethods(response1, response2, false);

        // With original response
        final LevelUpResponse originalResponse = new LevelUpResponse("data", LevelUpStatus.OK);

        response2 = new LevelUpResponse(LevelUpStatus.ERROR_PARSING, originalResponse);

        MoreAsserts.checkEqualsAndHashCodeMethods(response1, response2, false);

        response1 = new LevelUpResponse(LevelUpStatus.ERROR_PARSING, originalResponse);

        MoreAsserts.checkEqualsAndHashCodeMethods(response1, response2, true);

    }

    @SmallTest
    public void testGetError() {

        final JSONArray errorList = new JSONArray();

        errorList.put(ErrorFixture.getJsonObjectFromModel(mError1));
        errorList.put(ErrorFixture.getJsonObjectFromModel(mError2));

        final LevelUpResponse response = new LevelUpResponse(nonNullContract(errorList.toString()),
                LevelUpStatus.ERROR_NETWORK);

        assertEquals(mError1, response.getServerError(nonNullContract(ErrorObject.fromString(mError1.getObject())),
                nonNullContract(ErrorCode.fromString(mError1.getCode()))));
        assertEquals(mError2, response.getServerError(nonNullContract(ErrorObject.fromString(mError2.getObject())),
                nonNullContract(ErrorCode.fromString(mError2.getCode()))));

        assertNull(response.getServerError(nonNullContract(ErrorObject.fromString(mError1.getObject())),
                nonNullContract(ErrorCode.fromString(mError2.getCode()))));
        assertNull(response.getServerError(nonNullContract(ErrorObject.fromString(mError2.getObject())),
                nonNullContract(ErrorCode.fromString(mError1.getCode()))));
    }

    @SmallTest
    public void testGetErrorList() {
        final List<Error> expectedErrorList = new LinkedList<Error>();

        expectedErrorList.add(mError1);
        expectedErrorList.add(mError2);

        final JSONArray errorList = new JSONArray();

        errorList.put(ErrorFixture.getJsonObjectFromModel(mError1));
        errorList.put(ErrorFixture.getJsonObjectFromModel(mError2));

        final LevelUpResponse response = new LevelUpResponse(nonNullContract(errorList.toString()),
                LevelUpStatus.ERROR_NETWORK);

        assertEquals(expectedErrorList, response.getServerErrors());

        // Invalid errors should not throw exceptions.
        final LevelUpResponse responseNoErrors = new LevelUpResponse(EMPTY, LevelUpStatus.ERROR_SERVER);
        final List<Error> emptyList = responseNoErrors.getServerErrors();

        assertTrue(emptyList.isEmpty());
    }

    @SmallTest
    public void testParsingInvalidError_containsErrorException() {
        final LevelUpResponse response = new LevelUpResponse(nonNullContract("<html />"),
                LevelUpStatus.ERROR_NETWORK);

        assertTrue(response.getError() instanceof IOException);
    }

    @SmallTest
    public void testNonErrorNetwork_hasNoErrorOrServerError() {
        final LevelUpResponse expectedOriginalResponse = new LevelUpResponse("data", LevelUpStatus.OK);
        final LevelUpResponse response = new LevelUpResponse(LevelUpStatus.ERROR_PARSING, expectedOriginalResponse);

        assertNull(response.getError());
        assertNull(response.getData());
        assertEquals(response.getOriginalResponse(), expectedOriginalResponse);
        assertEquals(0, response.getServerErrors().size());
    }

    /**
     * Wrapped {@link java.net.HttpURLConnection} to return
     * {@link java.net.HttpURLConnection#HTTP_OK} for
     * {@link java.net.HttpURLConnection#getResponseCode()}.
     */
    private static class MockHttpUrlConnection extends HttpURLConnection {

        /**
         * Constructor.
         *
         * @throws java.net.MalformedURLException if the URL is malformed
         */
        public MockHttpUrlConnection() throws MalformedURLException {
            super(new URL("http://www.example.com"));
        }

        @Override
        public int getResponseCode() throws IOException {
            return HttpURLConnection.HTTP_OK;
        }

        @Override
        public InputStream getInputStream() throws IOException {
            return null;
        }

        @Override
        public void disconnect() {
            // do nothing
        }

        @Override
        public boolean usingProxy() {
            return false;
        }

        @Override
        public void connect() throws IOException {
            // do nothing
        }
    }
}