/**
* 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 org.apache.camel.component.couchbase;
import java.util.HashMap;
import java.util.Map;
import com.couchbase.client.CouchbaseClient;
import net.spy.memcached.PersistTo;
import net.spy.memcached.ReplicateTo;
import net.spy.memcached.internal.OperationFuture;
import org.apache.camel.Exchange;
import org.apache.camel.InvalidPayloadException;
import org.apache.camel.Message;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import static org.apache.camel.component.couchbase.CouchbaseConstants.HEADER_TTL;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.MockitoAnnotations.initMocks;
public class CouchbaseProducerTest {
@Mock
private CouchbaseClient client;
@Mock
private CouchbaseEndpoint endpoint;
@Mock
private Exchange exchange;
@Mock
private Message msg;
@Mock
private OperationFuture response;
private CouchbaseProducer producer;
@Before
public void before() throws Exception {
initMocks(this);
when(endpoint.getProducerRetryAttempts()).thenReturn(CouchbaseConstants.DEFAULT_PRODUCER_RETRIES);
producer = new CouchbaseProducer(endpoint, client, 0, 0);
when(exchange.getIn()).thenReturn(msg);
}
@SuppressWarnings("unchecked")
@Test(expected = CouchbaseException.class)
public void testBodyMandatory() throws Exception {
when(msg.getMandatoryBody()).thenThrow(InvalidPayloadException.class);
producer.process(exchange);
}
@Test(expected = IllegalArgumentException.class)
public void testPersistToLowerThanSupported() throws Exception {
producer = new CouchbaseProducer(endpoint, client, -1, 0);
}
@Test(expected = IllegalArgumentException.class)
public void testPersistToHigherThanSupported() throws Exception {
producer = new CouchbaseProducer(endpoint, client, 5, 0);
}
@Test(expected = IllegalArgumentException.class)
public void testReplicateToLowerThanSupported() throws Exception {
producer = new CouchbaseProducer(endpoint, client, 0, -1);
}
@Test(expected = IllegalArgumentException.class)
public void testReplicateToHigherThanSupported() throws Exception {
producer = new CouchbaseProducer(endpoint, client, 0, 4);
}
@Test
public void testMaximumValuesForPersistToAndRepicateTo() throws Exception {
try {
producer = new CouchbaseProducer(endpoint, client, 4, 3);
} catch (IllegalArgumentException e) {
Assert.fail("Exception was thrown while testing maximum values for persistTo and replicateTo parameters " + e.getMessage());
}
}
@Test
public void testExpiryTimeIsSet() throws Exception {
OperationFuture of = mock(OperationFuture.class);
when(of.get()).thenAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Exception {
return true;
}
});
when(client.set(org.mockito.Matchers.anyString(), org.mockito.Matchers.anyInt(), org.mockito.Matchers.anyObject(), org.mockito.Matchers.any(PersistTo.class),
org.mockito.Matchers.any(ReplicateTo.class))).thenReturn(of);
// Mock out some headers so we can set an expiry
int expiry = 5000;
Map<String, Object> testHeaders = new HashMap<String, Object>();
testHeaders.put("CCB_TTL", Integer.toString(expiry));
when(msg.getHeaders()).thenReturn(testHeaders);
when(msg.getHeader(HEADER_TTL, String.class)).thenReturn(Integer.toString(expiry));
when(endpoint.getId()).thenReturn("123");
when(endpoint.getOperation()).thenReturn("CCB_PUT");
Message outmsg = mock(Message.class);
when(exchange.getOut()).thenReturn(msg);
producer.process(exchange);
verify(client).set(org.mockito.Matchers.anyString(), Mockito.eq(expiry), org.mockito.Matchers.anyObject(), org.mockito.Matchers.any(PersistTo.class),
org.mockito.Matchers.any(ReplicateTo.class));
}
@Test
public void testTimeOutRetryToException() throws Exception {
OperationFuture of = mock(OperationFuture.class);
when(of.get()).thenAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Exception {
throw new RuntimeException("Timed out waiting for operation");
}
});
when(client.set(org.mockito.Matchers.anyString(), org.mockito.Matchers.anyInt(), org.mockito.Matchers.anyObject(), org.mockito.Matchers.any(PersistTo.class),
org.mockito.Matchers.any(ReplicateTo.class))).thenReturn(of);
when(endpoint.getId()).thenReturn("123");
when(endpoint.getOperation()).thenReturn("CCB_PUT");
try {
producer.process(exchange);
} catch (Exception e) {
// do nothing
verify(of, times(3)).get();
}
}
@Test
public void testTimeOutRetryThenSuccess() throws Exception {
OperationFuture of = mock(OperationFuture.class);
when(of.get()).thenAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Exception {
throw new RuntimeException("Timed out waiting for operation");
}
}).thenAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Exception {
return true;
}
});
when(client.set(org.mockito.Matchers.anyString(), org.mockito.Matchers.anyInt(), org.mockito.Matchers.anyObject(), org.mockito.Matchers.any(PersistTo.class),
org.mockito.Matchers.any(ReplicateTo.class))).thenReturn(of);
when(endpoint.getId()).thenReturn("123");
when(endpoint.getOperation()).thenReturn("CCB_PUT");
when(exchange.getOut()).thenReturn(msg);
producer.process(exchange);
verify(of, times(2)).get();
verify(msg).setBody(true);
}
@Test
public void testTimeOutRetryTwiceThenSuccess() throws Exception {
OperationFuture of = mock(OperationFuture.class);
when(of.get()).thenAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Exception {
throw new RuntimeException("Timed out waiting for operation");
}
}).thenAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Exception {
throw new RuntimeException("Timed out waiting for operation");
}
}).thenAnswer(new Answer<Object>() {
@Override
public Object answer(InvocationOnMock invocation) throws Exception {
return true;
}
});
when(client.set(org.mockito.Matchers.anyString(), org.mockito.Matchers.anyInt(), org.mockito.Matchers.anyObject(), org.mockito.Matchers.any(PersistTo.class),
org.mockito.Matchers.any(ReplicateTo.class))).thenReturn(of);
when(endpoint.getId()).thenReturn("123");
when(endpoint.getOperation()).thenReturn("CCB_PUT");
when(exchange.getOut()).thenReturn(msg);
producer.process(exchange);
verify(of, times(3)).get();
verify(msg).setBody(true);
}
}