// Copyright (C) 2003-2009 by Object Mentor, Inc. All rights reserved. // Released under the terms of the CPL Common Public License version 1.0. package util; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import static util.RegexTestCase.assertHasRegexp; import java.io.ByteArrayOutputStream; import java.io.PipedInputStream; import java.io.PipedOutputStream; import org.junit.After; import org.junit.Before; import org.junit.Test; public class StreamReaderTest { private PipedOutputStream output; private StreamReader reader; private String readResult; private byte[] byteResult; private Thread thread; @SuppressWarnings("unused") private Exception exception; @Before public void setUp() throws Exception { output = new PipedOutputStream(); reader = new StreamReader(new PipedInputStream(output)); } @After public void tearDown() throws Exception { output.close(); reader.close(); } private void writeToPipe(String value) throws Exception { byte[] bytes = value.getBytes(); output.write(bytes); } @Test public void testReadLine() throws Exception { startReading(new ReadLine()); writeToPipe("a line\r\n"); finishReading(); assertEquals("a line", readResult); } @Test public void testReadLineBytes() throws Exception { startReading(new ReadLineBytes()); writeToPipe("a line\r\n"); finishReading(); assertEquals("a line", new String(byteResult)); } @Test public void testBufferCanGrow() throws Exception { startReading(new ReadLine()); for (int i = 0; i < 1001; i++) writeToPipe(i + ","); writeToPipe("\r\n"); finishReading(); assertHasRegexp("1000", readResult); } @Test public void testReadNumberOfBytesAsString() throws Exception { startReading(new ReadCount(100)); StringBuilder buffer = new StringBuilder(); for (int i = 0; i < 100; i++) { buffer.append("*"); writeToPipe("*"); } finishReading(); assertEquals(buffer.toString(), readResult); } @Test public void testReadNumberOfBytes() throws Exception { startReading(new ReadCountBytes(100)); StringBuilder buffer = new StringBuilder(); for (int i = 0; i < 100; i++) { buffer.append("*"); writeToPipe("*"); } finishReading(); assertEquals(buffer.toString(), new String(byteResult)); } @Test public void testReadNumberOfBytesWithClosedInput() throws Exception { startReading(new ReadCountBytes(100)); for (int i = 0; i < 50; i++) writeToPipe("*"); output.close(); finishReading(); assertEquals("bytes consumed", 50, reader.numberOfBytesConsumed()); assertEquals("bytes returned", 50, byteResult.length); } @Test public void testReadingZeroBytes() throws Exception { startReading(new ReadCount(0)); finishReading(); assertEquals("", readResult); } @Test public void testReadUpTo() throws Exception { checkReadUoTo("--boundary", "some bytes--boundary", "some bytes"); } @Test public void testReadUpToNonEnd() throws Exception { checkReadUoTo("--bound", "some bytes--boundary", "some bytes"); } @Test public void testReadBytesUpTo() throws Exception { startReading(new ReadUpToBytes("--boundary")); writeToPipe("some bytes--boundary"); finishReading(); assertEquals("some bytes", new String(byteResult)); } @Test public void testReadUpTo2() throws Exception { checkReadUoTo("--bob", "----bob\r\n", "--"); } @Test public void testReadUpTo3() throws Exception { checkReadUoTo("12345", "112123123412345", "1121231234"); } private void checkReadUoTo(String boundary, String input, String expected) throws Exception { startReading(new ReadUpTo(boundary)); writeToPipe(input); finishReading(); assertEquals(expected, readResult); } @Test public void testCopyBytesUpTo() throws Exception { ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); writeToPipe("some bytes--boundary"); reader.copyBytesUpTo("--boundary", outputStream); assertEquals("some bytes", outputStream.toString()); } @Test public void testEofReadCount() throws Exception { writeToPipe("abcdefghijklmnopqrstuvwxyz"); output.close(); assertFalse(reader.isEof()); reader.read(10); assertFalse(reader.isEof()); reader.read(16); assertFalse(reader.isEof()); reader.read(1); assertTrue(reader.isEof()); } @Test public void testEofReadLine() throws Exception { writeToPipe("one line\ntwo lines\nthree lines"); output.close(); assertFalse(reader.isEof()); reader.readLine(); assertFalse(reader.isEof()); reader.readLine(); assertFalse(reader.isEof()); reader.readLine(); assertTrue(reader.isEof()); } @Test public void testEofReadUpTo() throws Exception { writeToPipe("mark one, mark two, the end"); output.close(); assertFalse(reader.isEof()); reader.readUpTo("one"); assertFalse(reader.isEof()); reader.readUpTo("two"); assertFalse(reader.isEof()); reader.readUpTo("three"); assertTrue(reader.isEof()); } @Test public void testBytesConsumed() throws Exception { writeToPipe("One line\r\n12345abc-boundary"); assertEquals(0, reader.numberOfBytesConsumed()); reader.readLine(); assertEquals(10, reader.numberOfBytesConsumed()); reader.read(5); assertEquals(15, reader.numberOfBytesConsumed()); reader.readUpTo("-boundary"); assertEquals(27, reader.numberOfBytesConsumed()); } @Test public void testEarlyClosingStream() throws Exception { startReading(new ReadCount(10)); output.close(); finishReading(); assertEquals("", readResult); } private void startReading(ReadThread thread) { this.thread = thread; this.thread.start(); } private void finishReading() throws Exception { thread.join(); } abstract class ReadThread extends Thread { @Override public void run() { try { doRead(); } catch (Exception e) { exception = e; } } public abstract void doRead() throws Exception; } class ReadLine extends ReadThread { @Override public void doRead() throws Exception { readResult = reader.readLine(); } } class ReadCount extends ReadThread { private int amount; public ReadCount(int amount) { this.amount = amount; } @Override public void doRead() throws Exception { readResult = reader.read(amount); } } class ReadUpTo extends ReadThread { private String boundary; public ReadUpTo(String b) { boundary = b; } @Override public void doRead() throws Exception { readResult = reader.readUpTo(boundary); } } class ReadLineBytes extends ReadThread { @Override public void doRead() throws Exception { byteResult = reader.readLineBytes(); } } class ReadCountBytes extends ReadThread { private int amount; public ReadCountBytes(int amount) { this.amount = amount; } @Override public void doRead() throws Exception { byteResult = reader.readBytes(amount); } } class ReadUpToBytes extends ReadThread { private String boundary; public ReadUpToBytes(String b) { boundary = b; } @Override public void doRead() throws Exception { byteResult = reader.readBytesUpTo(boundary); } } }