/*
 * Copyright (C) 2011 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 com.android.volley.toolbox;

import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.MockitoAnnotations.initMocks;

import com.android.volley.AuthFailureError;
import com.android.volley.Cache.Entry;
import com.android.volley.Header;
import com.android.volley.NetworkResponse;
import com.android.volley.NoConnectionError;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.RetryPolicy;
import com.android.volley.ServerError;
import com.android.volley.TimeoutError;
import com.android.volley.VolleyError;
import com.android.volley.mock.MockHttpStack;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.SocketTimeoutException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.robolectric.RobolectricTestRunner;

@RunWith(RobolectricTestRunner.class)
public class BasicNetworkTest {

    @Mock private Request<String> mMockRequest;
    @Mock private RetryPolicy mMockRetryPolicy;

    @Before
    public void setUp() throws Exception {
        initMocks(this);
    }

    @Test
    public void headersAndPostParams() throws Exception {
        MockHttpStack mockHttpStack = new MockHttpStack();
        InputStream responseStream =
                new ByteArrayInputStream("foobar".getBytes(StandardCharsets.UTF_8));
        HttpResponse fakeResponse =
                new HttpResponse(200, Collections.<Header>emptyList(), 6, responseStream);
        mockHttpStack.setResponseToReturn(fakeResponse);
        BasicNetwork httpNetwork = new BasicNetwork(mockHttpStack);
        Request<String> request = buildRequest();
        Entry entry = new Entry();
        entry.etag = "foobar";
        entry.lastModified = 1503102002000L;
        request.setCacheEntry(entry);
        httpNetwork.performRequest(request);
        assertEquals("foo", mockHttpStack.getLastHeaders().get("requestheader"));
        assertEquals("foobar", mockHttpStack.getLastHeaders().get("If-None-Match"));
        assertEquals(
                "Sat, 19 Aug 2017 00:20:02 GMT",
                mockHttpStack.getLastHeaders().get("If-Modified-Since"));
        assertEquals(
                "requestpost=foo&",
                new String(mockHttpStack.getLastPostBody(), StandardCharsets.UTF_8));
    }

    @Test
    public void notModified() throws Exception {
        MockHttpStack mockHttpStack = new MockHttpStack();
        List<Header> headers = new ArrayList<>();
        headers.add(new Header("ServerKeyA", "ServerValueA"));
        headers.add(new Header("ServerKeyB", "ServerValueB"));
        headers.add(new Header("SharedKey", "ServerValueShared"));
        headers.add(new Header("sharedcaseinsensitivekey", "ServerValueShared1"));
        headers.add(new Header("SharedCaseInsensitiveKey", "ServerValueShared2"));
        HttpResponse fakeResponse = new HttpResponse(HttpURLConnection.HTTP_NOT_MODIFIED, headers);
        mockHttpStack.setResponseToReturn(fakeResponse);
        BasicNetwork httpNetwork = new BasicNetwork(mockHttpStack);
        Request<String> request = buildRequest();
        Entry entry = new Entry();
        entry.allResponseHeaders = new ArrayList<>();
        entry.allResponseHeaders.add(new Header("CachedKeyA", "CachedValueA"));
        entry.allResponseHeaders.add(new Header("CachedKeyB", "CachedValueB"));
        entry.allResponseHeaders.add(new Header("SharedKey", "CachedValueShared"));
        entry.allResponseHeaders.add(new Header("SHAREDCASEINSENSITIVEKEY", "CachedValueShared1"));
        entry.allResponseHeaders.add(new Header("shAREDcaSEinSENSITIVEkeY", "CachedValueShared2"));
        request.setCacheEntry(entry);
        NetworkResponse response = httpNetwork.performRequest(request);
        List<Header> expectedHeaders = new ArrayList<>();
        // Should have all server headers + cache headers that didn't show up in server response.
        expectedHeaders.add(new Header("ServerKeyA", "ServerValueA"));
        expectedHeaders.add(new Header("ServerKeyB", "ServerValueB"));
        expectedHeaders.add(new Header("SharedKey", "ServerValueShared"));
        expectedHeaders.add(new Header("sharedcaseinsensitivekey", "ServerValueShared1"));
        expectedHeaders.add(new Header("SharedCaseInsensitiveKey", "ServerValueShared2"));
        expectedHeaders.add(new Header("CachedKeyA", "CachedValueA"));
        expectedHeaders.add(new Header("CachedKeyB", "CachedValueB"));
        assertThat(expectedHeaders, containsInAnyOrder(response.allHeaders.toArray(new Header[0])));
    }

    @Test
    public void notModified_legacyCache() throws Exception {
        MockHttpStack mockHttpStack = new MockHttpStack();
        List<Header> headers = new ArrayList<>();
        headers.add(new Header("ServerKeyA", "ServerValueA"));
        headers.add(new Header("ServerKeyB", "ServerValueB"));
        headers.add(new Header("SharedKey", "ServerValueShared"));
        headers.add(new Header("sharedcaseinsensitivekey", "ServerValueShared1"));
        headers.add(new Header("SharedCaseInsensitiveKey", "ServerValueShared2"));
        HttpResponse fakeResponse = new HttpResponse(HttpURLConnection.HTTP_NOT_MODIFIED, headers);
        mockHttpStack.setResponseToReturn(fakeResponse);
        BasicNetwork httpNetwork = new BasicNetwork(mockHttpStack);
        Request<String> request = buildRequest();
        Entry entry = new Entry();
        entry.responseHeaders = new HashMap<>();
        entry.responseHeaders.put("CachedKeyA", "CachedValueA");
        entry.responseHeaders.put("CachedKeyB", "CachedValueB");
        entry.responseHeaders.put("SharedKey", "CachedValueShared");
        entry.responseHeaders.put("SHAREDCASEINSENSITIVEKEY", "CachedValueShared1");
        entry.responseHeaders.put("shAREDcaSEinSENSITIVEkeY", "CachedValueShared2");
        request.setCacheEntry(entry);
        NetworkResponse response = httpNetwork.performRequest(request);
        List<Header> expectedHeaders = new ArrayList<>();
        // Should have all server headers + cache headers that didn't show up in server response.
        expectedHeaders.add(new Header("ServerKeyA", "ServerValueA"));
        expectedHeaders.add(new Header("ServerKeyB", "ServerValueB"));
        expectedHeaders.add(new Header("SharedKey", "ServerValueShared"));
        expectedHeaders.add(new Header("sharedcaseinsensitivekey", "ServerValueShared1"));
        expectedHeaders.add(new Header("SharedCaseInsensitiveKey", "ServerValueShared2"));
        expectedHeaders.add(new Header("CachedKeyA", "CachedValueA"));
        expectedHeaders.add(new Header("CachedKeyB", "CachedValueB"));
        assertThat(expectedHeaders, containsInAnyOrder(response.allHeaders.toArray(new Header[0])));
    }

    @Test
    public void socketTimeout() throws Exception {
        MockHttpStack mockHttpStack = new MockHttpStack();
        mockHttpStack.setExceptionToThrow(new SocketTimeoutException());
        BasicNetwork httpNetwork = new BasicNetwork(mockHttpStack);
        Request<String> request = buildRequest();
        request.setRetryPolicy(mMockRetryPolicy);
        doThrow(new VolleyError()).when(mMockRetryPolicy).retry(any(VolleyError.class));
        try {
            httpNetwork.performRequest(request);
        } catch (VolleyError e) {
            // expected
        }
        // should retry socket timeouts
        verify(mMockRetryPolicy).retry(any(TimeoutError.class));
    }

    @Test
    public void noConnectionDefault() throws Exception {
        MockHttpStack mockHttpStack = new MockHttpStack();
        mockHttpStack.setExceptionToThrow(new IOException());
        BasicNetwork httpNetwork = new BasicNetwork(mockHttpStack);
        Request<String> request = buildRequest();
        request.setRetryPolicy(mMockRetryPolicy);
        doThrow(new VolleyError()).when(mMockRetryPolicy).retry(any(VolleyError.class));
        try {
            httpNetwork.performRequest(request);
        } catch (VolleyError e) {
            // expected
        }
        // should not retry when there is no connection
        verify(mMockRetryPolicy, never()).retry(any(VolleyError.class));
    }

    @Test
    public void noConnectionRetry() throws Exception {
        MockHttpStack mockHttpStack = new MockHttpStack();
        mockHttpStack.setExceptionToThrow(new IOException());
        BasicNetwork httpNetwork = new BasicNetwork(mockHttpStack);
        Request<String> request = buildRequest();
        request.setRetryPolicy(mMockRetryPolicy);
        request.setShouldRetryConnectionErrors(true);
        doThrow(new VolleyError()).when(mMockRetryPolicy).retry(any(VolleyError.class));
        try {
            httpNetwork.performRequest(request);
        } catch (VolleyError e) {
            // expected
        }
        // should retry when there is no connection
        verify(mMockRetryPolicy).retry(any(NoConnectionError.class));
        reset(mMockRetryPolicy);
    }

    @Test
    public void noConnectionNoRetry() throws Exception {
        MockHttpStack mockHttpStack = new MockHttpStack();
        mockHttpStack.setExceptionToThrow(new IOException());
        BasicNetwork httpNetwork = new BasicNetwork(mockHttpStack);
        Request<String> request = buildRequest();
        request.setRetryPolicy(mMockRetryPolicy);
        request.setShouldRetryConnectionErrors(false);
        doThrow(new VolleyError()).when(mMockRetryPolicy).retry(any(VolleyError.class));
        try {
            httpNetwork.performRequest(request);
        } catch (VolleyError e) {
            // expected
        }
        // should not retry when there is no connection
        verify(mMockRetryPolicy, never()).retry(any(VolleyError.class));
    }

    @Test
    public void unauthorized() throws Exception {
        MockHttpStack mockHttpStack = new MockHttpStack();
        HttpResponse fakeResponse = new HttpResponse(401, Collections.<Header>emptyList());
        mockHttpStack.setResponseToReturn(fakeResponse);
        BasicNetwork httpNetwork = new BasicNetwork(mockHttpStack);
        Request<String> request = buildRequest();
        request.setRetryPolicy(mMockRetryPolicy);
        doThrow(new VolleyError()).when(mMockRetryPolicy).retry(any(VolleyError.class));
        try {
            httpNetwork.performRequest(request);
        } catch (VolleyError e) {
            // expected
        }
        // should retry in case it's an auth failure.
        verify(mMockRetryPolicy).retry(any(AuthFailureError.class));
    }

    @Test
    public void forbidden() throws Exception {
        MockHttpStack mockHttpStack = new MockHttpStack();
        HttpResponse fakeResponse = new HttpResponse(403, Collections.<Header>emptyList());
        mockHttpStack.setResponseToReturn(fakeResponse);
        BasicNetwork httpNetwork = new BasicNetwork(mockHttpStack);
        Request<String> request = buildRequest();
        request.setRetryPolicy(mMockRetryPolicy);
        doThrow(new VolleyError()).when(mMockRetryPolicy).retry(any(VolleyError.class));
        try {
            httpNetwork.performRequest(request);
        } catch (VolleyError e) {
            // expected
        }
        // should retry in case it's an auth failure.
        verify(mMockRetryPolicy).retry(any(AuthFailureError.class));
    }

    @Test
    public void redirect() throws Exception {
        for (int i = 300; i <= 399; i++) {
            MockHttpStack mockHttpStack = new MockHttpStack();
            HttpResponse fakeResponse = new HttpResponse(i, Collections.<Header>emptyList());
            mockHttpStack.setResponseToReturn(fakeResponse);
            BasicNetwork httpNetwork = new BasicNetwork(mockHttpStack);
            Request<String> request = buildRequest();
            request.setRetryPolicy(mMockRetryPolicy);
            doThrow(new VolleyError()).when(mMockRetryPolicy).retry(any(VolleyError.class));
            try {
                httpNetwork.performRequest(request);
            } catch (VolleyError e) {
                // expected
            }
            // should not retry 300 responses.
            verify(mMockRetryPolicy, never()).retry(any(VolleyError.class));
            reset(mMockRetryPolicy);
        }
    }

    @Test
    public void otherClientError() throws Exception {
        for (int i = 400; i <= 499; i++) {
            if (i == 401 || i == 403) {
                // covered above.
                continue;
            }
            MockHttpStack mockHttpStack = new MockHttpStack();
            HttpResponse fakeResponse = new HttpResponse(i, Collections.<Header>emptyList());
            mockHttpStack.setResponseToReturn(fakeResponse);
            BasicNetwork httpNetwork = new BasicNetwork(mockHttpStack);
            Request<String> request = buildRequest();
            request.setRetryPolicy(mMockRetryPolicy);
            doThrow(new VolleyError()).when(mMockRetryPolicy).retry(any(VolleyError.class));
            try {
                httpNetwork.performRequest(request);
            } catch (VolleyError e) {
                // expected
            }
            // should not retry other 400 errors.
            verify(mMockRetryPolicy, never()).retry(any(VolleyError.class));
            reset(mMockRetryPolicy);
        }
    }

    @Test
    public void serverError_enableRetries() throws Exception {
        for (int i = 500; i <= 599; i++) {
            MockHttpStack mockHttpStack = new MockHttpStack();
            HttpResponse fakeResponse = new HttpResponse(i, Collections.<Header>emptyList());
            mockHttpStack.setResponseToReturn(fakeResponse);
            BasicNetwork httpNetwork = new BasicNetwork(mockHttpStack, new ByteArrayPool(4096));
            Request<String> request = buildRequest();
            request.setRetryPolicy(mMockRetryPolicy);
            request.setShouldRetryServerErrors(true);
            doThrow(new VolleyError()).when(mMockRetryPolicy).retry(any(VolleyError.class));
            try {
                httpNetwork.performRequest(request);
            } catch (VolleyError e) {
                // expected
            }
            // should retry all 500 errors
            verify(mMockRetryPolicy).retry(any(ServerError.class));
            reset(mMockRetryPolicy);
        }
    }

    @Test
    public void serverError_disableRetries() throws Exception {
        for (int i = 500; i <= 599; i++) {
            MockHttpStack mockHttpStack = new MockHttpStack();
            HttpResponse fakeResponse = new HttpResponse(i, Collections.<Header>emptyList());
            mockHttpStack.setResponseToReturn(fakeResponse);
            BasicNetwork httpNetwork = new BasicNetwork(mockHttpStack);
            Request<String> request = buildRequest();
            request.setRetryPolicy(mMockRetryPolicy);
            doThrow(new VolleyError()).when(mMockRetryPolicy).retry(any(VolleyError.class));
            try {
                httpNetwork.performRequest(request);
            } catch (VolleyError e) {
                // expected
            }
            // should not retry any 500 error w/ HTTP 500 retries turned off (the default).
            verify(mMockRetryPolicy, never()).retry(any(VolleyError.class));
            reset(mMockRetryPolicy);
        }
    }

    private static Request<String> buildRequest() {
        return new Request<String>(Request.Method.GET, "http://foo", null) {

            @Override
            protected Response<String> parseNetworkResponse(NetworkResponse response) {
                return null;
            }

            @Override
            protected void deliverResponse(String response) {}

            @Override
            public Map<String, String> getHeaders() {
                Map<String, String> result = new HashMap<String, String>();
                result.put("requestheader", "foo");
                return result;
            }

            @Override
            public Map<String, String> getParams() {
                Map<String, String> result = new HashMap<String, String>();
                result.put("requestpost", "foo");
                return result;
            }
        };
    }
}
