com.nextdoor.bender.ipc.http.HttpTransportTest.java Source code

Java tutorial

Introduction

Here is the source code for com.nextdoor.bender.ipc.http.HttpTransportTest.java

Source

/*
 * 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.
 *
 * Copyright 2017 Nextdoor.com, Inc
 *
 */

package com.nextdoor.bender.ipc.http;

import static org.junit.Assert.assertEquals;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.zip.GZIPOutputStream;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.EntityBuilder;
import org.apache.http.client.entity.GzipDecompressingEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
import org.junit.Test;
import org.mockito.ArgumentCaptor;

import com.nextdoor.bender.config.BenderConfig;
import com.nextdoor.bender.ipc.TransportException;

public class HttpTransportTest {

    private HttpClient getMockClientWithResponse(byte[] respPayload, ContentType contentType, int status,
            boolean compressed) throws IOException {
        HttpClient mockClient = mock(HttpClient.class);
        HttpResponse mockResponse = mock(HttpResponse.class);

        StatusLine mockStatusLine = mock(StatusLine.class);
        doReturn("expected failure").when(mockStatusLine).getReasonPhrase();
        doReturn(status).when(mockStatusLine).getStatusCode();
        doReturn(mockStatusLine).when(mockResponse).getStatusLine();
        EntityBuilder eb = EntityBuilder.create().setBinary(respPayload).setContentType(contentType);

        HttpEntity he;
        if (compressed) {
            eb.setContentEncoding("gzip");
            he = new GzipDecompressingEntity(eb.build());
        } else {
            he = eb.build();
        }

        doReturn(he).when(mockResponse).getEntity();

        doReturn(mockResponse).when(mockClient).execute(any(HttpPost.class));
        return mockClient;
    }

    @Test
    public void testOkResponse() throws TransportException, IOException {
        byte[] respPayload = "{}".getBytes(StandardCharsets.UTF_8);
        byte[] payload = "foo".getBytes();

        HttpClient client = getMockClientWithResponse(respPayload, ContentType.APPLICATION_JSON, HttpStatus.SC_OK,
                false);
        HttpTransport transport = new HttpTransport(client, "", false, 1, 1);
        transport.sendBatch(payload);
    }

    @Test(expected = TransportException.class)
    public void testNotOkResponse() throws TransportException, IOException {
        byte[] respPayload = "{\"foo\": \"bar\"}".getBytes(StandardCharsets.UTF_8);

        HttpClient client = getMockClientWithResponse(respPayload, ContentType.APPLICATION_JSON,
                HttpStatus.SC_INTERNAL_SERVER_ERROR, false);
        HttpTransport transport = new HttpTransport(client, "", false, 1, 1);

        transport.sendBatch("foo".getBytes());
    }

    @Test
    public void testNoErrorsResponse() throws TransportException, IOException {
        byte[] respPayload = "{}".getBytes(StandardCharsets.UTF_8);

        HttpClient client = getMockClientWithResponse(respPayload, ContentType.APPLICATION_JSON, HttpStatus.SC_OK,
                false);
        HttpTransport transport = new HttpTransport(client, "", false, 1, 1);

        transport.sendBatch("foo".getBytes());
    }

    @Test(expected = TransportException.class)
    public void testErrorsResponse() throws TransportException, IOException {
        byte[] respPayload = "resp".getBytes(StandardCharsets.UTF_8);

        HttpClient client = getMockClientWithResponse(respPayload, ContentType.APPLICATION_JSON,
                HttpStatus.SC_INTERNAL_SERVER_ERROR, false);
        HttpTransport transport = new HttpTransport(client, "", false, 1, 1);

        try {
            transport.sendBatch("foo".getBytes());
        } catch (Exception e) {
            assertEquals("http transport call failed because \"expected failure\" payload response \"resp\"",
                    e.getCause().getMessage());
            throw e;
        }
    }

    @Test(expected = TransportException.class)
    public void testGzipErrorsResponse() throws TransportException, IOException {
        byte[] respPayload = "gzip resp".getBytes(StandardCharsets.UTF_8);

        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        GZIPOutputStream os = new GZIPOutputStream(baos);
        os.write(respPayload);
        os.close();
        byte[] compressedResponse = baos.toByteArray();

        HttpClient client = getMockClientWithResponse(compressedResponse, ContentType.DEFAULT_BINARY,
                HttpStatus.SC_INTERNAL_SERVER_ERROR, true);
        HttpTransport transport = new HttpTransport(client, "", true, 1, 1);

        try {
            transport.sendBatch("foo".getBytes());
        } catch (Exception e) {
            assertEquals("http transport call failed because \"expected failure\" payload response \"gzip resp\"",
                    e.getCause().getMessage());
            throw e;
        }
    }

    @Test(expected = TransportException.class)
    public void testRetries() throws Exception {
        byte[] respPayload = "resp".getBytes(StandardCharsets.UTF_8);

        HttpClient client = getMockClientWithResponse(respPayload, ContentType.APPLICATION_JSON,
                HttpStatus.SC_INTERNAL_SERVER_ERROR, false);
        HttpTransport transport = new HttpTransport(client, "", false, 3, 10);

        try {
            transport.sendBatch("foo".getBytes());
        } catch (Exception e) {
            assertEquals("http transport call failed because \"expected failure\" payload response \"resp\"",
                    e.getCause().getMessage());
            throw e;
        }
    }

    @Test(expected = IOException.class)
    public void testIOException() throws Throwable {
        byte[] arr = "{".getBytes();
        HttpClient client = getMockClientWithResponse(arr, ContentType.DEFAULT_BINARY,
                HttpStatus.SC_INTERNAL_SERVER_ERROR, false);

        doThrow(new IOException()).when(client).execute(any(HttpPost.class));

        HttpTransport transport = new HttpTransport(client, "", true, 3, 1);

        try {
            transport.sendBatch("foo".getBytes());
        } catch (Exception e) {
            throw e.getCause().getCause();
        }
    }

    @Test
    public void testHttpPostUrl() throws TransportException, IOException {
        byte[] respPayload = "{}".getBytes(StandardCharsets.UTF_8);
        byte[] payload = "foo".getBytes();
        String url = "https://localhost:443/foo";

        HttpClient client = getMockClientWithResponse(respPayload, ContentType.APPLICATION_JSON, HttpStatus.SC_OK,
                false);
        HttpTransport transport = spy(new HttpTransport(client, url, false, 1, 1));
        transport.sendBatch(payload);

        ArgumentCaptor<HttpPost> captor = ArgumentCaptor.forClass(HttpPost.class);
        verify(client, times(1)).execute(captor.capture());

        assertEquals(url, captor.getValue().getURI().toString());
    }

    @Test
    public void testHttpPostGzipHeader() throws TransportException, IOException {
        byte[] respPayload = "{}".getBytes(StandardCharsets.UTF_8);
        byte[] payload = "foo".getBytes();
        String url = "https://localhost:443/foo";

        HttpClient client = getMockClientWithResponse(respPayload, ContentType.APPLICATION_JSON, HttpStatus.SC_OK,
                false);
        HttpTransport transport = spy(new HttpTransport(client, url, true, 1, 1));
        transport.sendBatch(payload);

        ArgumentCaptor<HttpPost> captor = ArgumentCaptor.forClass(HttpPost.class);
        verify(client, times(1)).execute(captor.capture());

        assertEquals("gzip", captor.getValue().getFirstHeader("Accept-Encoding").getValue());
    }
}