/**
* Copyright 2016, Xiaomi.
* All rights reserved.
* Author: xiajun@xiaomi.com
*/
package com.xiaomi.infra.galaxy.talos.consumer;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InOrder;
import org.mockito.Mockito;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.xiaomi.infra.galaxy.talos.client.TalosClientConfigKeys;
import com.xiaomi.infra.galaxy.talos.thrift.CheckPoint;
import com.xiaomi.infra.galaxy.talos.thrift.ConsumerService;
import com.xiaomi.infra.galaxy.talos.thrift.Message;
import com.xiaomi.infra.galaxy.talos.thrift.MessageAndOffset;
import com.xiaomi.infra.galaxy.talos.thrift.QueryOffsetRequest;
import com.xiaomi.infra.galaxy.talos.thrift.QueryOffsetResponse;
import com.xiaomi.infra.galaxy.talos.thrift.TopicAndPartition;
import com.xiaomi.infra.galaxy.talos.thrift.TopicTalosResourceName;
import com.xiaomi.infra.galaxy.talos.thrift.UpdateOffsetRequest;
import com.xiaomi.infra.galaxy.talos.thrift.UpdateOffsetResponse;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.inOrder;
public class TalosMessageReaderTest {
private static final Logger LOG = LoggerFactory.getLogger(TalosMessageReaderTest.class);
private static Properties properties = new Properties();
private TalosConsumerConfig consumerConfig;
private static final String topicName = "MyTopic";
private static final String resourceName = "12345#MyTopic#34595fkdiso456i390";
private static final int partitionId = 7;
private static final String consumerGroup = "MyConsumerGroup";
private static final String workerId = "workerId";
private static final TopicAndPartition topicAndPartition =
new TopicAndPartition(topicName, new TopicTalosResourceName(resourceName), partitionId);
private static final long startMessageOffset = 1;
private static List<MessageAndOffset> messageAndOffsetList;
private static List<MessageAndOffset> messageAndOffsetList2;
private static ConsumerService.Iface consumerClientMock;
private static SimpleConsumer simpleConsumerMock;
private class TestMessageProcessor implements MessageProcessor {
private TopicAndPartition topicAndPartition;
private long messageOffset;
@Override
public void init(TopicAndPartition topicAndPartition, long messageOffset) {
this.topicAndPartition = topicAndPartition;
this.messageOffset = messageOffset;
}
@Override
public void process(List<MessageAndOffset> messages, MessageCheckpointer messageCheckpointer) {
assertTrue(messageCheckpointer.checkpoint());
// checkpoint low messageOffset
assertFalse(messageCheckpointer.checkpoint(messageOffset));
// checkpoint high messageOffset
assertFalse(messageCheckpointer.checkpoint(messages.get(messages.size()-1).getMessageOffset()));
}
@Override
public void shutdown(MessageCheckpointer messageCheckpointer) {
assertFalse(messageCheckpointer.checkpoint());
}
public TopicAndPartition getTopicAndPartition() {
return topicAndPartition;
}
public long getMessageOffset() {
return messageOffset;
}
}
private TestMessageProcessor messageProcessor = new TestMessageProcessor();
private MessageProcessor messageProcessorMock;
private TalosMessageReader messageReader;
@Before
public void setUp() throws Exception {
messageAndOffsetList = new ArrayList<MessageAndOffset>();
messageAndOffsetList2 = new ArrayList<MessageAndOffset>();
MessageAndOffset messageAndOffset1 = new MessageAndOffset(new Message(
ByteBuffer.wrap("message1".getBytes())), startMessageOffset);
MessageAndOffset messageAndOffset2 = new MessageAndOffset(new Message(
ByteBuffer.wrap("message2".getBytes())), startMessageOffset + 1);
MessageAndOffset messageAndOffset3 = new MessageAndOffset(new Message(
ByteBuffer.wrap("message3".getBytes())), startMessageOffset + 2);
messageAndOffsetList.add(messageAndOffset1);
messageAndOffsetList.add(messageAndOffset2);
messageAndOffsetList.add(messageAndOffset3);
MessageAndOffset messageAndOffset4 = new MessageAndOffset(new Message(
ByteBuffer.wrap("message4".getBytes())), startMessageOffset + 3);
MessageAndOffset messageAndOffset5 = new MessageAndOffset(new Message(
ByteBuffer.wrap("message5".getBytes())), startMessageOffset + 4);
messageAndOffsetList2.add(messageAndOffset4);
messageAndOffsetList2.add(messageAndOffset5);
consumerClientMock = Mockito.mock(ConsumerService.Iface.class);
simpleConsumerMock = Mockito.mock(SimpleConsumer.class);
}
@Test
public void testDefaultCheckpointOffset() throws Exception {
properties.setProperty(TalosClientConfigKeys.GALAXY_TALOS_CONSUMER_CHECKPOINT_AUTO_COMMIT, "true");
properties.setProperty(TalosClientConfigKeys.GALAXY_TALOS_CONSUMER_FETCH_INTERVAL, "0");
properties.setProperty(TalosClientConfigKeys.GALAXY_TALOS_CONSUMER_COMMIT_OFFSET_INTERVAL, "0");
properties.setProperty(TalosClientConfigKeys.GALAXY_TALOS_CONSUMER_COMMIT_OFFSET_THRESHOLD, "0");
consumerConfig = new TalosConsumerConfig(properties, false);
messageProcessorMock = Mockito.mock(MessageProcessor.class);
messageReader = new TalosMessageReader(consumerConfig);
messageReader.setSimpleConsumer(simpleConsumerMock)
.setConsumerClient(consumerClientMock)
.setConsumerGroup(consumerGroup)
.setMessageProcessor(messageProcessorMock)
.setTopicAndPartition(topicAndPartition)
.setWorkerId(workerId);
InOrder inOrder = inOrder(simpleConsumerMock, consumerClientMock, messageProcessorMock);
QueryOffsetRequest queryOffsetRequest = new QueryOffsetRequest(consumerGroup, topicAndPartition);
QueryOffsetResponse queryOffsetResponse = new QueryOffsetResponse(startMessageOffset - 1);
doReturn(queryOffsetResponse).when(consumerClientMock).queryOffset(queryOffsetRequest);
doNothing().when(messageProcessorMock).init(topicAndPartition, startMessageOffset);
messageReader.initStartOffset();
inOrder.verify(consumerClientMock).queryOffset(queryOffsetRequest);
inOrder.verify(messageProcessorMock).init(topicAndPartition, startMessageOffset);
doReturn(messageAndOffsetList).when(simpleConsumerMock).fetchMessage(startMessageOffset);
doNothing().when(messageProcessorMock).process(messageAndOffsetList, messageReader);
CheckPoint checkpoint = new CheckPoint(consumerGroup, topicAndPartition, startMessageOffset+2, workerId);
UpdateOffsetRequest updateOffsetRequest = new UpdateOffsetRequest(checkpoint);
UpdateOffsetResponse updateOffsetResponse = new UpdateOffsetResponse(true);
doReturn(updateOffsetResponse).when(consumerClientMock).updateOffset(updateOffsetRequest);
messageReader.fetchData();
inOrder.verify(simpleConsumerMock).fetchMessage(startMessageOffset);
inOrder.verify(messageProcessorMock).process(messageAndOffsetList, messageReader);
inOrder.verify(consumerClientMock).updateOffset(updateOffsetRequest);
doReturn(messageAndOffsetList2).when(simpleConsumerMock).fetchMessage(startMessageOffset + 3);
doNothing().when(messageProcessorMock).process(messageAndOffsetList2, messageReader);
checkpoint = new CheckPoint(consumerGroup, topicAndPartition, startMessageOffset + 4, workerId);
updateOffsetRequest = new UpdateOffsetRequest(checkpoint);
updateOffsetResponse = new UpdateOffsetResponse(true);
doReturn(updateOffsetResponse).when(consumerClientMock).updateOffset(updateOffsetRequest);
messageReader.fetchData();
inOrder.verify(simpleConsumerMock).fetchMessage(startMessageOffset + 3);
inOrder.verify(messageProcessorMock).process(messageAndOffsetList2, messageReader);
inOrder.verify(consumerClientMock).updateOffset(updateOffsetRequest);
doNothing().when(messageProcessorMock).shutdown(messageReader);
messageReader.commitCheckPoint();
inOrder.verify(messageProcessorMock).shutdown(messageReader);
inOrder.verifyNoMoreInteractions();
}
@Test
public void testUserCheckpointOffset() throws Exception {
properties.setProperty(TalosClientConfigKeys.GALAXY_TALOS_CONSUMER_CHECKPOINT_AUTO_COMMIT, "false");
properties.setProperty(TalosClientConfigKeys.GALAXY_TALOS_CONSUMER_FETCH_INTERVAL, "0");
properties.setProperty(TalosClientConfigKeys.GALAXY_TALOS_SERVICE_ENDPOINT, "testURI");
consumerConfig = new TalosConsumerConfig(properties, false);
messageReader = new TalosMessageReader(consumerConfig);
messageReader.setSimpleConsumer(simpleConsumerMock)
.setConsumerClient(consumerClientMock)
.setConsumerGroup(consumerGroup)
.setMessageProcessor(messageProcessor)
.setTopicAndPartition(topicAndPartition)
.setWorkerId(workerId);
InOrder inOrder = inOrder(simpleConsumerMock, consumerClientMock);
QueryOffsetRequest queryOffsetRequest = new QueryOffsetRequest(consumerGroup, topicAndPartition);
QueryOffsetResponse queryOffsetResponse = new QueryOffsetResponse(startMessageOffset - 1);
doReturn(queryOffsetResponse).when(consumerClientMock).queryOffset(queryOffsetRequest);
messageReader.initStartOffset();
inOrder.verify(consumerClientMock).queryOffset(queryOffsetRequest);
assertEquals(messageProcessor.getMessageOffset(), startMessageOffset);
assertEquals(messageProcessor.getTopicAndPartition(), topicAndPartition);
doReturn(messageAndOffsetList).when(simpleConsumerMock).fetchMessage(startMessageOffset);
CheckPoint checkpoint = new CheckPoint(consumerGroup, topicAndPartition, startMessageOffset+2, workerId);
UpdateOffsetRequest updateOffsetRequest = new UpdateOffsetRequest(checkpoint);
UpdateOffsetResponse updateOffsetResponse = new UpdateOffsetResponse(true);
doReturn(updateOffsetResponse).when(consumerClientMock).updateOffset(updateOffsetRequest);
messageReader.fetchData();
inOrder.verify(simpleConsumerMock).fetchMessage(startMessageOffset);
inOrder.verify(consumerClientMock).updateOffset(updateOffsetRequest);
doReturn(messageAndOffsetList2).when(simpleConsumerMock).fetchMessage(startMessageOffset + 3);
checkpoint = new CheckPoint(consumerGroup, topicAndPartition, startMessageOffset + 4, workerId);
updateOffsetRequest = new UpdateOffsetRequest(checkpoint);
updateOffsetResponse = new UpdateOffsetResponse(true);
doReturn(updateOffsetResponse).when(consumerClientMock).updateOffset(updateOffsetRequest);
messageReader.fetchData();
inOrder.verify(simpleConsumerMock).fetchMessage(startMessageOffset + 3);
inOrder.verify(consumerClientMock).updateOffset(updateOffsetRequest);
messageReader.commitCheckPoint();
inOrder.verifyNoMoreInteractions();
}
}