/**
* Copyright 2016 StreamSets Inc.
*
* Licensed under the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.streamsets.lib.security.http;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@SuppressWarnings("unchecked")
public class TestRestClient {
@Test
public void testBuilderAndClientCreation() throws Exception {
RestClient.Builder builder = RestClient.builder("http://foo/bar");
Assert.assertEquals("RestClient", builder.name);
builder.name("name");
Assert.assertEquals("name", builder.name);
Assert.assertEquals("http://foo/bar/", builder.baseUrl);
Assert.assertNull(builder.path);
builder.path("path");
Assert.assertEquals("path", builder.path);
Assert.assertTrue(builder.csrf);
builder.csrf(false);
Assert.assertFalse(builder.csrf);
Assert.assertTrue(builder.json);
builder.json(false);
Assert.assertFalse(builder.json);
Assert.assertNull(builder.componentId);
builder.componentId("componentId");
Assert.assertEquals("componentId", builder.componentId);
Assert.assertNull(builder.appAuthToken);
builder.appAuthToken("appAuthToken");
Assert.assertEquals("appAuthToken", builder.appAuthToken);
Assert.assertTrue(builder.headers.isEmpty());
builder.header("a", "A");
Assert.assertEquals(1, builder.headers.size());
Assert.assertTrue(builder.headers.containsKey("a"));
Assert.assertEquals(ImmutableList.of("A"), builder.headers.get("a"));
Assert.assertTrue(builder.queryParams.isEmpty());
builder.queryParam("b", "B");
Assert.assertEquals(1, builder.queryParams.size());
Assert.assertTrue(builder.queryParams.containsKey("b"));
Assert.assertEquals(ImmutableList.of("B"), builder.queryParams.get("b"));
Assert.assertEquals(30 * 1000, builder.timeoutMillis);
builder.timeout(10);
Assert.assertEquals(10, builder.timeoutMillis);
Assert.assertSame(RestClient.OBJECT_MAPPER, builder.jsonMapper);
ObjectMapper mapper = new ObjectMapper();
builder.jsonMapper(mapper);
Assert.assertSame(mapper, builder.jsonMapper);
RestClient client = builder.build();
Assert.assertNotNull(client);
Assert.assertEquals("http://foo/bar/", client.baseUrl);
Assert.assertEquals("path", client.path);
Map expectedHeaders = ImmutableMap.of(
"a", ImmutableList.of("A"),
SSOConstants.X_APP_COMPONENT_ID.toLowerCase(), ImmutableList.of("componentId"),
SSOConstants.X_APP_AUTH_TOKEN.toLowerCase(), ImmutableList.of("appAuthToken")
);
Assert.assertEquals(3, client.headers.size());
Assert.assertTrue(client.headers.containsKey("a"));
Assert.assertEquals(expectedHeaders, client.headers);
Assert.assertNotSame(builder.headers, client.headers);
Assert.assertFalse(client.json);
Assert.assertEquals(1, client.queryParams.size());
Assert.assertTrue(client.queryParams.containsKey("b"));
Assert.assertEquals(ImmutableList.of("B"), client.queryParams.get("b"));
Assert.assertNotSame(builder.queryParams, client.queryParams);
Assert.assertEquals(10, client.timeoutMillis);
Assert.assertSame(mapper, client.jsonMapper);
Assert.assertNotNull(client.conn);
Assert.assertEquals(new URL("http://foo/bar/path?b=B"), client.conn.getURL());
Assert.assertEquals(expectedHeaders, client.conn.getRequestProperties());
Assert.assertEquals(10, client.conn.getConnectTimeout());
Assert.assertEquals(10, client.conn.getReadTimeout());
Assert.assertFalse(client.conn.getDefaultUseCaches());
builder.path(null).queryParam("b", null).json(true).csrf(true);
expectedHeaders =
ImmutableMap.builder()
.putAll(expectedHeaders)
.put(SSOConstants.X_REST_CALL.toLowerCase(), ImmutableList.of("name"))
.put(RestClient.CONTENT_TYPE, ImmutableList.of(RestClient.APPLICATION_JSON))
.put(RestClient.ACCEPT, ImmutableList.of(RestClient.APPLICATION_JSON))
.build();
client = builder.build();
Assert.assertEquals(new URL("http://foo/bar/"), client.conn.getURL());
Assert.assertEquals(expectedHeaders, client.conn.getRequestProperties());
}
@Test
public void testClientGet() throws Exception {
RestClient client = Mockito.spy(RestClient.builder("http://foo").build());
RestClient.Response response = Mockito.mock(RestClient.Response.class);
HttpURLConnection conn = Mockito.mock(HttpURLConnection.class);
Mockito.doReturn(conn).when(client).getConnection();
Mockito
.doReturn(response)
.when(client).doHttp(Mockito.eq(conn), Mockito.eq("GET"), Mockito.any());
Assert.assertEquals(response, client.get());
Mockito.verify(conn, Mockito.times(1)).setDoOutput(Mockito.eq(true));
}
@Test
public void testClientPost() throws Exception {
RestClient client = Mockito.spy(RestClient.builder("http://foo").build());
RestClient.Response response = Mockito.mock(RestClient.Response.class);
HttpURLConnection conn = Mockito.mock(HttpURLConnection.class);
Mockito.doReturn(conn).when(client).getConnection();
Object data = new Object();
Mockito
.doReturn(response)
.when(client).doHttp(Mockito.eq(conn), Mockito.eq("POST"), Mockito.eq(data));
Assert.assertEquals(response, client.post(data));
Mockito.verify(conn, Mockito.times(1)).setDoOutput(Mockito.eq(true));
Mockito.verify(conn, Mockito.times(1)).setDoInput(Mockito.eq(true));
}
@Test
public void testClientPut() throws Exception {
RestClient client = Mockito.spy(RestClient.builder("http://foo").build());
RestClient.Response response = Mockito.mock(RestClient.Response.class);
HttpURLConnection conn = Mockito.mock(HttpURLConnection.class);
Mockito.doReturn(conn).when(client).getConnection();
Object data = new Object();
Mockito
.doReturn(response)
.when(client).doHttp(Mockito.eq(conn), Mockito.eq("PUT"), Mockito.eq(data));
Assert.assertEquals(response, client.put(data));
Mockito.verify(conn, Mockito.times(1)).setDoOutput(Mockito.eq(true));
Mockito.verify(conn, Mockito.times(1)).setDoInput(Mockito.eq(true));
}
@Test
public void testClientDelete() throws Exception {
RestClient client = Mockito.spy(RestClient.builder("http://foo").build());
RestClient.Response response = Mockito.mock(RestClient.Response.class);
HttpURLConnection conn = Mockito.mock(HttpURLConnection.class);
Mockito.doReturn(conn).when(client).getConnection();
Mockito
.doReturn(response)
.when(client).doHttp(Mockito.eq(conn), Mockito.eq("DELETE"), Mockito.any());
Assert.assertEquals(response, client.delete());
Mockito.verify(conn, Mockito.times(1)).setDoOutput(Mockito.eq(true));
}
@Test
public void testDoHttp() throws Exception {
RestClient client = Mockito.spy(RestClient.builder("http://foo").build());
HttpURLConnection conn = Mockito.mock(HttpURLConnection.class);
RestClient.Response response = client.doHttp(conn, "METHOD", null);
Assert.assertEquals(client.jsonMapper, response.jsonMapper);
Assert.assertEquals(conn, response.conn);
Mockito.verify(conn, Mockito.times(1)).setRequestMethod(Mockito.eq("METHOD"));
ByteArrayOutputStream baos = new ByteArrayOutputStream();
Mockito.when(conn.getOutputStream()).thenReturn(baos);
client.doHttp(conn, "METHOD", new HashMap());
Assert.assertEquals("{}", new String(baos.toByteArray()));
}
@Test(expected = IllegalStateException.class)
public void testDoHttpNotJson() throws Exception {
RestClient client = Mockito.spy(RestClient.builder("http://foo").json(false).build());
HttpURLConnection conn = Mockito.mock(HttpURLConnection.class);
Mockito.doReturn(conn).when(client).getConnection();
Object data = new Object();
client.post(data);
}
@Test
public void testResponse() throws Exception {
HttpURLConnection conn = Mockito.mock(HttpURLConnection.class);
Mockito.when(conn.getResponseCode()).thenReturn(100);
Mockito.when(conn.getContentType()).thenReturn("application/json");
Mockito.when(conn.getHeaderField(Mockito.eq("a"))).thenReturn("A");
Map<String, List<String>> headers = new HashMap<>();
Mockito.when(conn.getHeaderFields()).thenReturn(headers);
InputStream inputStream = Mockito.mock(InputStream.class);
Mockito.when(conn.getInputStream()).thenReturn(inputStream);
RestClient.Response response = new RestClient.Response(new ObjectMapper(), conn);
Assert.assertEquals(conn, response.getConnection());
Assert.assertEquals(100, response.getStatus());
Assert.assertEquals("application/json", response.getContentType());
Assert.assertTrue(response.isJson());
Assert.assertEquals("A", response.getHeader("a"));
Assert.assertEquals(headers, response.getHeaders());
Assert.assertEquals(inputStream, response.getInputStream());
inputStream = new ByteArrayInputStream("[\"a\"]".getBytes());
Mockito.when(conn.getInputStream()).thenReturn(inputStream);
response = new RestClient.Response(new ObjectMapper(), conn);
TypeReference<List<String>> typeReference = new TypeReference<List<String>>() {
};
List<String> list = response.getData(typeReference);
Assert.assertNotNull(list);
Assert.assertEquals("a", list.get(0));
inputStream = new ByteArrayInputStream("{\"message\" : \"hello\"}".getBytes());
Mockito.when(conn.getErrorStream()).thenReturn(inputStream);
response = new RestClient.Response(new ObjectMapper(), conn);
Assert.assertEquals(ImmutableMap.of("message", "hello"), response.getError());
}
@Test(expected = IllegalStateException.class)
public void testResponseNoJson() throws Exception {
HttpURLConnection conn = Mockito.mock(HttpURLConnection.class);
Mockito.when(conn.getResponseCode()).thenReturn(100);
Mockito.when(conn.getContentType()).thenReturn("foo");
RestClient.Response response = new RestClient.Response(new ObjectMapper(), conn);
response.getData(Object.class);
}
}