/**
* Licensed to 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.pinterest.terrapin.thrift;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.pinterest.terrapin.client.TerrapinClient;
import com.pinterest.terrapin.thrift.generated.*;
import com.twitter.util.Duration;
import com.twitter.util.Future;
import com.twitter.util.Throw;
import com.twitter.util.Try;
import org.junit.Before;
import org.junit.Test;
import org.mockito.MockitoAnnotations;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Map;
import java.util.Set;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.when;
/**
* Unit test for TerrapinServiceImpl.
*/
public class TerrapinServiceImplTest {
private static final String CLUSTER1 = "cluster1";
private static final String CLUSTER2 = "cluster2";
private static final String FILESET = "fileset";
private static final byte[] KEY = "key".getBytes();
@MockitoAnnotations.Mock
TerrapinClient mockClient1;
@MockitoAnnotations.Mock
TerrapinClient mockClient2;
private TerrapinService.ServiceIface serviceIface;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
serviceIface = new TerrapinServiceImpl(ImmutableMap.of(CLUSTER1, mockClient1, CLUSTER2, mockClient2));
}
private TerrapinGetRequest prepareGetRequest() {
TerrapinGetRequest request = new TerrapinGetRequest();
request.setFileSet(FILESET);
request.setClusterList(ImmutableList.of(CLUSTER1));
ByteBuffer key = ByteBuffer.wrap(KEY);
request.setKey(key);
return request;
}
private TerrapinMultiGetRequest prepareMultiGetRequest() {
TerrapinMultiGetRequest request = new TerrapinMultiGetRequest();
request.setFileSet(FILESET);
request.setClusterList(ImmutableList.of(CLUSTER1));
request.addToKeyList(ByteBuffer.wrap("key1".getBytes()));
request.addToKeyList(ByteBuffer.wrap("key2".getBytes()));
request.addToKeyList(ByteBuffer.wrap("key3".getBytes()));
return request;
}
@Test
public void testGetSuccess() {
ByteBuffer key = ByteBuffer.wrap(KEY);
TerrapinGetRequest request = prepareGetRequest();
TerrapinResponse response = new TerrapinResponse().setResponseMap(ImmutableMap.of(
key, new TerrapinSingleResponse().setValue(ByteBuffer.wrap("value".getBytes()))));
when(mockClient1.getMany(eq(FILESET), eq(Sets.newHashSet(key)))).thenReturn(
Future.value(response));
TerrapinSingleResponse singleResponse = serviceIface.get(request).get();
assertFalse(singleResponse.isSetErrorCode());
assertEquals("value", new String(singleResponse.getValue()));
}
@Test
public void testGetMultiClusters() {
ByteBuffer key = ByteBuffer.wrap(KEY);
TerrapinGetRequest request = prepareGetRequest();
RequestOptions options = new RequestOptions();
options.setSelectionPolicy(SelectionPolicy.PRIMARY_FIRST);
request.setOptions(options);
request.setClusterList(ImmutableList.of(CLUSTER1, CLUSTER2));
TerrapinResponse response = new TerrapinResponse().setResponseMap(ImmutableMap.of(
key, new TerrapinSingleResponse().setValue(ByteBuffer.wrap("value".getBytes()))));
when(mockClient1.getMany(eq(FILESET), eq(Sets.newHashSet(key)))).thenReturn(
Future.<TerrapinResponse>exception(new IOException()));
when(mockClient2.getManyNoRetries(eq(FILESET), eq(Sets.newHashSet(key)))).thenReturn(
Future.value(response));
TerrapinSingleResponse singleResponse = serviceIface.get(request).get();
assertFalse(singleResponse.isSetErrorCode());
assertEquals("value", new String(singleResponse.getValue()));
}
@Test
public void testGetEmptyClusters() {
ByteBuffer key = ByteBuffer.wrap(KEY);
TerrapinGetRequest request = prepareGetRequest();
RequestOptions options = new RequestOptions();
options.setSelectionPolicy(SelectionPolicy.PRIMARY_FIRST);
request.setOptions(options);
request.setClusterList(ImmutableList.copyOf(new String[]{}));
TerrapinResponse response = new TerrapinResponse().setResponseMap(ImmutableMap.of(
key, new TerrapinSingleResponse().setValue(ByteBuffer.wrap("value".getBytes()))));
when(mockClient1.getMany(eq(FILESET), eq(Sets.newHashSet(key)))).thenReturn(
Future.value(response));
when(mockClient2.getManyNoRetries(eq(FILESET), eq(Sets.newHashSet(key)))).thenReturn(
Future.value(response));
Try<TerrapinSingleResponse> singleResponseTry = serviceIface.get(request).get(Duration.forever());
assertTrue(singleResponseTry.isThrow());
assertEquals(TerrapinGetErrorCode.INVALID_REQUEST,
((TerrapinGetException)((Throw)singleResponseTry).e()).getErrorCode());
}
@Test
public void testGetNotFound() {
ByteBuffer key = ByteBuffer.wrap(KEY);
TerrapinGetRequest request = prepareGetRequest();
TerrapinResponse response = new TerrapinResponse().setResponseMap((Map)Maps.newHashMap());
when(mockClient1.getMany(eq(FILESET), eq(Sets.newHashSet(key)))).thenReturn(
Future.value(response));
TerrapinSingleResponse singleResponse = serviceIface.get(request).get();
assertFalse(singleResponse.isSetErrorCode());
assertFalse(singleResponse.isSetValue());
}
@Test
public void testGetClusterNotFound() {
TerrapinGetRequest request = prepareGetRequest().setClusterList(ImmutableList.of(
"random-cluster"));
Try<TerrapinSingleResponse> singleResponseTry =
serviceIface.get(request).get(Duration.forever());
assertTrue(singleResponseTry.isThrow());
assertEquals(TerrapinGetErrorCode.CLUSTER_NOT_FOUND,
((TerrapinGetException)((Throw)singleResponseTry).e()).getErrorCode());
}
@Test
public void testGetError() {
// Test the case where We get back an error set through an error code set in
// TerrapinSingleResponse.
ByteBuffer key = ByteBuffer.wrap(KEY);
TerrapinGetRequest request = prepareGetRequest();
TerrapinResponse response = new TerrapinResponse().setResponseMap(ImmutableMap.of(
key, new TerrapinSingleResponse().setErrorCode(TerrapinGetErrorCode.OTHER)));
when(mockClient1.getMany(eq(FILESET), eq(Sets.newHashSet(key)))).thenReturn(
Future.value(response));
Try<TerrapinSingleResponse> singleResponseTry = serviceIface.get(request).get(
Duration.forever());
assertTrue(singleResponseTry.isThrow());
assertEquals(TerrapinGetErrorCode.OTHER,
((TerrapinGetException)((Throw)singleResponseTry).e()).getErrorCode());
// Test the case where the call to the client library itself bails out due to a
// legit error.
when(mockClient1.getMany(eq(FILESET), eq(Sets.newHashSet(key)))).thenReturn(
Future.<TerrapinResponse>exception(new TerrapinGetException("Failed.",
TerrapinGetErrorCode.FILE_SET_NOT_FOUND)));
singleResponseTry = serviceIface.get(request).get(Duration.forever());
assertTrue(singleResponseTry.isThrow());
assertEquals(TerrapinGetErrorCode.FILE_SET_NOT_FOUND,
((TerrapinGetException)((Throw)singleResponseTry).e()).getErrorCode());
// Test the case where the call to the client library bails out due to a runtime
// exception.
when(mockClient1.getMany(eq(FILESET), eq(Sets.newHashSet(key)))).thenThrow(
new RuntimeException(new NullPointerException()));
singleResponseTry = serviceIface.get(request).get(Duration.forever());
assertTrue(singleResponseTry.isThrow());
assertEquals(TerrapinGetErrorCode.OTHER,
((TerrapinGetException)((Throw)singleResponseTry).e()).getErrorCode());
}
@Test
public void testMultiGetSuccess() {
TerrapinMultiGetRequest request = prepareMultiGetRequest();
TerrapinResponse response = new TerrapinResponse().setResponseMap(ImmutableMap.of(
ByteBuffer.wrap("key1".getBytes()),
new TerrapinSingleResponse().setValue("value1".getBytes()),
ByteBuffer.wrap("key2".getBytes()),
new TerrapinSingleResponse().setErrorCode(TerrapinGetErrorCode.READ_ERROR)));
Set<ByteBuffer> keys = Sets.newHashSet(ByteBuffer.wrap("key1".getBytes()),
ByteBuffer.wrap("key2".getBytes()),
ByteBuffer.wrap("key3".getBytes()));
when(mockClient1.getMany(eq(FILESET), eq(keys))).thenReturn(Future.value(response));
TerrapinResponse returnResponse = serviceIface.multiGet(request).get();
assertEquals(response, returnResponse);
}
@Test
public void testMultiGetMultiClusters() {
TerrapinMultiGetRequest request = prepareMultiGetRequest();
RequestOptions options = new RequestOptions();
options.setSelectionPolicy(SelectionPolicy.PRIMARY_FIRST);
request.setOptions(options);
request.setClusterList(ImmutableList.of(CLUSTER1, CLUSTER2));
TerrapinResponse response = new TerrapinResponse().setResponseMap(ImmutableMap.of(
ByteBuffer.wrap("key1".getBytes()),
new TerrapinSingleResponse().setValue("value1".getBytes()),
ByteBuffer.wrap("key2".getBytes()),
new TerrapinSingleResponse().setErrorCode(TerrapinGetErrorCode.READ_ERROR)));
Set<ByteBuffer> keys = Sets.newHashSet(ByteBuffer.wrap("key1".getBytes()),
ByteBuffer.wrap("key2".getBytes()),
ByteBuffer.wrap("key3".getBytes()));
when(mockClient1.getMany(eq(FILESET), eq(keys))).thenReturn(
Future.<TerrapinResponse>exception(new IOException()));
when(mockClient2.getManyNoRetries(eq(FILESET), eq(keys))).thenReturn(Future.value(response));
TerrapinResponse returnResponse = serviceIface.multiGet(request).get();
assertEquals(response, returnResponse);
}
@Test
public void testMultiGetEmptyClusters() {
TerrapinMultiGetRequest request = prepareMultiGetRequest();
RequestOptions options = new RequestOptions();
options.setSelectionPolicy(SelectionPolicy.PRIMARY_FIRST);
request.setOptions(options);
request.setClusterList(ImmutableList.copyOf(new String[]{}));
TerrapinResponse response = new TerrapinResponse().setResponseMap(ImmutableMap.of(
ByteBuffer.wrap("key1".getBytes()),
new TerrapinSingleResponse().setValue("value1".getBytes()),
ByteBuffer.wrap("key2".getBytes()),
new TerrapinSingleResponse().setErrorCode(TerrapinGetErrorCode.READ_ERROR)));
Set<ByteBuffer> keys = Sets.newHashSet(ByteBuffer.wrap("key1".getBytes()),
ByteBuffer.wrap("key2".getBytes()),
ByteBuffer.wrap("key3".getBytes()));
when(mockClient1.getMany(eq(FILESET), eq(keys))).thenReturn(Future.value(response));
when(mockClient2.getManyNoRetries(eq(FILESET), eq(keys))).thenReturn(Future.value(response));
Try<TerrapinResponse> returnResponseTry = serviceIface.multiGet(request).get(Duration.forever());
assertTrue(returnResponseTry.isThrow());
assertEquals(TerrapinGetErrorCode.INVALID_REQUEST,
((TerrapinGetException)((Throw)returnResponseTry).e()).getErrorCode());
}
@Test
public void testMultiGetError() {
TerrapinMultiGetRequest request = prepareMultiGetRequest();
Set<ByteBuffer> keys = Sets.newHashSet(ByteBuffer.wrap("key1".getBytes()),
ByteBuffer.wrap("key2".getBytes()),
ByteBuffer.wrap("key3".getBytes()));
when (mockClient1.getMany(eq(FILESET), eq(keys))).thenReturn(
Future.<TerrapinResponse>exception(new TerrapinGetException("Failed",
TerrapinGetErrorCode.FILE_SET_NOT_FOUND)));
Try<TerrapinResponse> responseTry = serviceIface.multiGet(request).get(Duration.forever());
assertTrue(responseTry.isThrow());
assertEquals(TerrapinGetErrorCode.FILE_SET_NOT_FOUND,
((TerrapinGetException)((Throw)responseTry).e()).getErrorCode());
when(mockClient1.getMany(eq(FILESET), eq(keys))).thenThrow(
new RuntimeException(new NullPointerException()));
responseTry = serviceIface.multiGet(request).get(Duration.forever());
assertTrue(responseTry.isThrow());
assertEquals(TerrapinGetErrorCode.OTHER,
((TerrapinGetException)((Throw)responseTry).e()).getErrorCode());
}
@Test
public void testMultiGetClusterNotFound() {
TerrapinMultiGetRequest request = prepareMultiGetRequest().setClusterList(ImmutableList.of(
"random-cluster"));
Try<TerrapinResponse> responseTry =
serviceIface.multiGet(request).get(Duration.forever());
assertTrue(responseTry.isThrow());
assertEquals(TerrapinGetErrorCode.CLUSTER_NOT_FOUND,
((TerrapinGetException)((Throw)responseTry).e()).getErrorCode());
}
}