/**
* Copyright 2013 Twitter, Inc.
* Licensed 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.twitter.hbc.common;
import com.google.common.base.Charsets;
import com.google.common.collect.Lists;
import org.junit.Test;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;
public class DelimitedStreamReaderTest {
@Test
public void testReadlineWithSmallBuffer() throws Exception {
String myMessage = "{this is my message}\r\n";
byte[] bytes = myMessage.getBytes(Charsets.UTF_8);
InputStream stream = new ByteArrayInputStream(bytes);
DelimitedStreamReader r = new DelimitedStreamReader(stream, Charsets.UTF_8, myMessage.length() / 3);
String msg = r.readLine();
assertEquals(msg, myMessage.trim());
}
@Test
public void testReadlineWithBigBuffer() throws Exception {
String myMessage = "{this is my message}\r\n";
byte[] bytes = myMessage.getBytes(Charsets.UTF_8);
InputStream stream = new ByteArrayInputStream(bytes);
DelimitedStreamReader r = new DelimitedStreamReader(stream, Charsets.UTF_8, myMessage.length() * 3);
String msg = r.readLine();
assertEquals(msg, myMessage.trim());
}
@Test
public void testReadlineMultipleSmallBuffer() throws Exception {
String myMessage = "{msg1}\r\n";
String myMessage2 = "{this is my message}\n";
String myMessage3 = "{this is my message2}\r\n";
byte[] bytes = (myMessage + myMessage2 + myMessage3).getBytes(Charsets.UTF_8);
InputStream stream = new ByteArrayInputStream(bytes);
DelimitedStreamReader r = new DelimitedStreamReader(stream, Charsets.UTF_8, myMessage.length());
String msg1 = r.readLine();
String msg2 = r.readLine();
String msg3 = r.readLine();
assertEquals(msg1, myMessage.trim());
assertEquals(msg2, myMessage2.trim());
assertEquals(msg3, myMessage3.trim());
}
@Test
public void testReadlineMultipleHugeBuffer() throws Exception {
String myMessage = "{msg1}\r\n";
String myMessage2 = "{this is my message}\r\n";
byte[] bytes = (myMessage + myMessage2).getBytes(Charsets.UTF_8);
InputStream stream = new ByteArrayInputStream(bytes);
DelimitedStreamReader r = new DelimitedStreamReader(stream, Charsets.UTF_8, myMessage.length() * 10 );
String msg1 = r.readLine();
String msg2 = r.readLine();
assertEquals(msg1, myMessage.trim());
assertEquals(msg2, myMessage2.trim());
}
@Test
public void testEmptyReadline() throws Exception {
InputStream stream = mock(InputStream.class);
when(stream.read(any(byte[].class), anyInt(), anyInt()))
.thenReturn(-1);
DelimitedStreamReader r = new DelimitedStreamReader(stream, Charsets.UTF_8, 10);
try {
r.readLine();
fail();
} catch (IOException e) {
// expected
}
}
@Test
public void testIncompleteReadline() {
String myMessage = "{this is my message}";
byte[] bytes = myMessage.getBytes(Charsets.UTF_8);
InputStream stream = new ByteArrayInputStream(bytes);
DelimitedStreamReader r = new DelimitedStreamReader(stream, Charsets.UTF_8, myMessage.length());
try {
r.readLine();
fail();
} catch (IOException e) {
// expected
}
}
@Test
public void testReadWithSmallBuffer() throws Exception {
String myMessage = "{this is my message}\r\n";
byte[] bytes = myMessage.getBytes(Charsets.UTF_8);
InputStream stream = new ByteArrayInputStream(bytes);
DelimitedStreamReader r = new DelimitedStreamReader(stream, Charsets.UTF_8, myMessage.length() / 3);
String msg = r.read(myMessage.length());
assertEquals(msg, myMessage);
}
@Test
public void testReadWithBigBuffer() throws Exception {
String myMessage = "{this is my message}\r\n";
byte[] bytes = myMessage.getBytes(Charsets.UTF_8);
InputStream stream = new ByteArrayInputStream(bytes);
DelimitedStreamReader r = new DelimitedStreamReader(stream, Charsets.UTF_8, myMessage.length() * 3);
String msg = r.read(myMessage.length());
assertEquals(msg, myMessage);
}
@Test
public void testReadMultipleSmallBuffer() throws Exception {
String myMessage = "{msg1}\r\n";
String myMessage2 = "{this is my message}\r\n";
byte[] bytes = (myMessage + myMessage2).getBytes(Charsets.UTF_8);
InputStream stream = new ByteArrayInputStream(bytes);
DelimitedStreamReader r = new DelimitedStreamReader(stream, Charsets.UTF_8, myMessage.length() - 1);
String msg1 = r.read(myMessage.length());
String msg2 = r.read(myMessage2.length());
assertEquals(msg1, myMessage);
assertEquals(msg2, myMessage2);
}
@Test
public void testReadMultipleHugeBuffer() throws Exception {
String myMessage = "{msg1}\r\n";
String myMessage2 = "{this is my message}\r\n";
byte[] bytes = (myMessage + myMessage2).getBytes(Charsets.UTF_8);
InputStream stream = new ByteArrayInputStream(bytes);
DelimitedStreamReader r = new DelimitedStreamReader(stream, Charsets.UTF_8, myMessage.length() * 10);
String msg1 = r.read(myMessage.length());
String msg2 = r.read(myMessage2.length());
assertEquals(msg1, myMessage);
assertEquals(msg2, myMessage2);
}
@Test
public void testEmptyRead() throws Exception {
InputStream stream = mock(InputStream.class);
when(stream.read(any(byte[].class), anyInt(), anyInt()))
.thenReturn(-1);
DelimitedStreamReader r = new DelimitedStreamReader(stream, Charsets.UTF_8, 10);
try {
r.read(10);
fail();
} catch (IOException e) {
// expected
}
}
@Test
public void testReadRemainder() throws Exception {
String myMessage = "{this is my message}\n";
byte[] bytes = myMessage.getBytes(Charsets.UTF_8);
InputStream stream = new ByteArrayInputStream(bytes);
DelimitedStreamReader r = new DelimitedStreamReader(stream, Charsets.UTF_8, myMessage.length() / 3);
assertTrue(stream.read(new byte[myMessage.length()/2], 0, myMessage.length()/2) > 0);
String remainder = r.read(myMessage.length() - myMessage.length()/2);
assertEquals(remainder, myMessage.substring(myMessage.length()/2, myMessage.length()));
}
@Test
public void testIncompleteRead() {
String myMessage = "{this is my message}";
byte[] bytes = myMessage.getBytes(Charsets.UTF_8);
InputStream stream = new ByteArrayInputStream(bytes);
DelimitedStreamReader r = new DelimitedStreamReader(stream, Charsets.UTF_8, myMessage.length());
try {
r.read(myMessage.length() * 2);
fail();
} catch (IOException e) {
// expected
}
}
@Test
public void testLenientRead() throws Exception {
String myMessage = "{this is my message}\n";
byte[] bytes = myMessage.getBytes(Charsets.UTF_8);
InputStream stream = new ByteArrayInputStream(bytes);
DelimitedStreamReader r = new DelimitedStreamReader(stream, Charsets.UTF_8, myMessage.length() / 3);
// read less bytes than the actual message, but we're lenient so we'll read up to the newline
String msg = r.read(myMessage.length()/2);
assertEquals(msg, myMessage);
}
@Test
public void testCombo() throws Exception {
String myMessage = "{this is my message}\n";
int length = myMessage.length();
byte[] bytes = (length + "\n" + myMessage).getBytes(Charsets.UTF_8);
InputStream stream = new ByteArrayInputStream(bytes);
DelimitedStreamReader r = new DelimitedStreamReader(stream, Charsets.UTF_8, myMessage.length() / 3);
// read less bytes than the actual message, but we're lenient so we'll read up to the newline
String line = r.readLine();
String msg = r.read(Integer.parseInt(line));
assertEquals(msg, myMessage);
}
@Test
public void testMultibyteCharacters() throws Exception {
String myMessage = "{this is my message: héÿ}\n";
byte[] bytes = myMessage.getBytes(Charsets.UTF_8);
InputStream stream = new ByteArrayInputStream(bytes);
DelimitedStreamReader r = new DelimitedStreamReader(stream, Charsets.UTF_8, myMessage.length() / 3);
// read less bytes than the actual message, but we're lenient so we'll read up to the newline
String msg = r.read(myMessage.length());
assertEquals(msg, myMessage);
}
/**
* This tests the case where we have to call multiple Inputstream.read()s to consume the entire message, as we might
* have to in real life
*/
@Test
public void testMultipleStreamReads() throws Exception {
String myMessage = "{this is my message: héÿ}\n";
byte[] bytes = myMessage.substring(0, myMessage.length()/2).getBytes(Charsets.UTF_8);
byte[] bytes2 = myMessage.substring(myMessage.length()/2, myMessage.length()).getBytes(Charsets.UTF_8);
InputStream miniStream = new ByteArrayInputStream(bytes);
InputStream miniStream2 = new ByteArrayInputStream(bytes2);
InputStream stream = new SplitInputStream(Lists.newArrayList(miniStream, miniStream2));
DelimitedStreamReader r = new DelimitedStreamReader(stream, Charsets.UTF_8, myMessage.length() / 3);
// read less bytes than the actual message, but we're lenient so we'll read up to the newline
String msg = r.read(myMessage.length());
assertEquals(msg, myMessage);
}
}