package com.leansoft.luxun.consumer;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.junit.Test;
import com.leansoft.luxun.LuxunServerTestHarness;
import com.leansoft.luxun.common.exception.ConsumerTimeoutException;
import com.leansoft.luxun.consumer.ConsumerConfig;
import com.leansoft.luxun.consumer.IStreamFactory;
import com.leansoft.luxun.consumer.MessageStream;
import com.leansoft.luxun.message.Message;
import com.leansoft.luxun.message.MessageList;
import com.leansoft.luxun.message.generated.CompressionCodec;
import com.leansoft.luxun.producer.SyncProducer;
import com.leansoft.luxun.serializer.StringDecoder;
import com.leansoft.luxun.server.ServerConfig;
import com.leansoft.luxun.utils.ImmutableMap;
import com.leansoft.luxun.utils.TestUtils;
import com.leansoft.luxun.utils.Utils;
public class ConsumerTest extends LuxunServerTestHarness {
static final Logger logger = LoggerFactory.getLogger(ConsumerTest.class);
int numNodes = 2;
String topic = "topic1";
String group = "group1";
String consumer0 = "consumer0";
String consumer1 = "consumer1";
String consumer2 = "consumer2";
String consumer3 = "consumer3";
int nMessages = 2;
String brokerList;
@Override
public void setUp() throws Exception {
configs = new ArrayList<ServerConfig>();
List<Properties> propsList = TestUtils.createBrokerConfigs(numNodes);
for(Properties props : propsList) {
configs.add(new ServerConfig(props));
if (brokerList == null) {
brokerList = "";
} else {
brokerList += ",";
}
brokerList += props.getProperty("brokerid") + ":127.0.0.1:" + props.getProperty("port");
}
super.setUp();
}
@Test
public void testBasic() throws Exception {
Properties props = TestUtils.createConsumerProperties(brokerList, group, consumer0, 200);
ConsumerConfig consumerConfig0 = new ConsumerConfig(props);
// test consumer timeout logic
@SuppressWarnings("resource")
IStreamFactory streamFactory0 = new StreamFactory(consumerConfig0);
Map<String, List<MessageStream<Message>>> topicMessageStreams0 =
streamFactory0.createMessageStreams(ImmutableMap.of(topic, numNodes));
// no messages to consume, we should hit timeout;
// also the iterator should support re-entrant, so loop it twice
for(int i = 0; i < 2; i++) {
try {
this.getMessages(nMessages, topicMessageStreams0);
fail("should get an exception");
} catch (ConsumerTimeoutException e) {
// this is ok
} catch (Exception e) {
throw e;
}
}
streamFactory0.close();
// send some messages to each broker
List<Message> sentMessages1 = sendMessages(nMessages, "batch1");
// create a consumer
ConsumerConfig consumerConfig1 = new ConsumerConfig(TestUtils.createConsumerProperties(brokerList, group, consumer1));
IStreamFactory streamFactory1 = new StreamFactory(consumerConfig1);
Map<String, List<MessageStream<Message>>> topicMessageStreams1 =
streamFactory1.createMessageStreams(ImmutableMap.of(topic, numNodes));
List<Message> receivedMessages1 = getMessages(nMessages, topicMessageStreams1);
assertTrue(isMessageListEqual(sentMessages1, receivedMessages1));
streamFactory1.close();
}
@Test
public void testCompression() throws Exception {
// send some messages to each broker
List<Message> sentMessages1 = sendMessages(nMessages, "batch1", CompressionCodec.GZIP);
// create a consumer
ConsumerConfig consumerConfig1 = new ConsumerConfig(TestUtils.createConsumerProperties(brokerList, group, consumer1));
IStreamFactory streamFactory1 = new StreamFactory(consumerConfig1);
Map<String, List<MessageStream<Message>>> topicMessageStreams1 =
streamFactory1.createMessageStreams(ImmutableMap.of(topic, numNodes));
List<Message> receivedMessages1 = getMessages(nMessages, topicMessageStreams1);
assertTrue(isMessageListEqual(sentMessages1, receivedMessages1));
streamFactory1.close();
}
@Test
public void testConsumerDecoder() throws IOException {
List<Message> sentMessages = sendMessages(nMessages, "batch1");
Properties props = TestUtils.createConsumerProperties(brokerList, group, consumer1);
ConsumerConfig consumerConfig = new ConsumerConfig(props);
// create a consumer
IStreamFactory streamFactory = new StreamFactory(consumerConfig);
Map<String, List<MessageStream<String>>> topicMessageStreams =
streamFactory.createMessageStreams(ImmutableMap.of(topic, numNodes), new StringDecoder());
List<Message> receivedMessages = new ArrayList<Message>();
for(String topic : topicMessageStreams.keySet()) {
List<MessageStream<String>> messageStreams = topicMessageStreams.get(topic);
for(MessageStream<String> messageStream : messageStreams) {
Iterator<String> iterator = messageStream.iterator();
for(int i = 0; i < nMessages; i++) {
assertTrue(iterator.hasNext());
String message = iterator.next();
receivedMessages.add(new Message(message.getBytes()));
logger.debug("received message : " + message);
}
}
}
assertTrue(isMessageListEqual(sentMessages, receivedMessages));
streamFactory.close();
}
private List<Message> sendMessages(ServerConfig conf, int messagesPerNode, String header, CompressionCodec compression) {
List<Message> messages = new ArrayList<Message>();
SyncProducer producer = TestUtils.createProducer("127.0.0.1", conf.getPort());
MessageList messageList = new MessageList();
for(int i = 0; i < messagesPerNode; i++) {
Message message = new Message((header + conf.getBrokerId() + "-" + i).getBytes());
messageList.add(message);
messages.add(message);
}
producer.send(topic, messageList);
producer.close();
return messages;
}
private boolean isMessageListEqual(List<Message> sourceMessageList, List<Message> targetMessageList) {
if (sourceMessageList.size() != targetMessageList.size()) {
return false;
}
Set<Message> messageSet = new HashSet<Message>();
for(Message msg : sourceMessageList) {
messageSet.add(msg);
}
for(Message msg : targetMessageList) {
messageSet.remove(msg);
}
return messageSet.size() == 0;
}
private List<Message> sendMessages(int messagesPerNode, String header) {
return this.sendMessages(messagesPerNode, header, CompressionCodec.NO_COMPRESSION);
}
private List<Message> sendMessages(int messagesPerNode, String header, CompressionCodec compression) {
List<Message> messages = new ArrayList<Message>();
for(ServerConfig conf : configs) {
messages.addAll(this.sendMessages(conf, messagesPerNode, header, compression));
}
return messages;
}
private List<Message> getMessages(int nMessagesPerThread, Map<String, List<MessageStream<Message>>> topicMessageStreams) {
List<Message> messages = new ArrayList<Message>();
for(String topic : topicMessageStreams.keySet()) {
List<MessageStream<Message>> messageStreams = topicMessageStreams.get(topic);
for(MessageStream<Message> messageStream : messageStreams) {
Iterator<Message> iterator = messageStream.iterator();
for(int i = 0; i < nMessagesPerThread; i++) {
assertTrue(iterator.hasNext());
Message message = iterator.next();
messages.add(message);
logger.debug("received message : " + Utils.toString(message.getBufferDuplicate(), "UTF-8"));
}
}
}
return messages;
}
}