1   /*
2       This file is part of quExec.
3   
4       quExec is free software; you can redistribute it and/or modify
5       it under the terms of the GNU Lesser General Public License as published by
6       the Free Software Foundation; either version 2 of the License, or
7       (at your option) any later version.
8   
9       quExec is distributed in the hope that it will be useful,
10      but WITHOUT ANY WARRANTY; without even the implied warranty of
11      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12      GNU Lesser General Public License for more details.
13  
14      You should have received a copy of the GNU Lesser General Public License
15      along with quExec; if not, write to the Free Software
16      Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  */
18  
19  package net.sourceforge.quexec.packet.chars.producer;
20  
21  import static org.junit.Assert.assertEquals;
22  import static org.junit.Assert.fail;
23  
24  import java.io.CharArrayReader;
25  import java.io.IOException;
26  import java.io.PipedReader;
27  import java.io.PipedWriter;
28  import java.io.Reader;
29  import java.util.concurrent.Executors;
30  
31  import net.sourceforge.quexec.packet.chars.consumer.StoreCharPacketConsumer;
32  
33  import org.apache.commons.lang.RandomStringUtils;
34  import org.apache.commons.logging.Log;
35  import org.apache.commons.logging.LogFactory;
36  import org.junit.Before;
37  import org.junit.Test;
38  
39  public abstract class AbstractReaderCharPacketProducerTest {
40  	
41  	private static final Log log = LogFactory.getLog(AbstractReaderCharPacketProducerTest.class);
42  
43  	protected static final int bufSize = 10;
44  	
45  	private static final int dataWaitTime = 10;
46  	
47  	private StoreCharPacketConsumer consumer;
48  	
49  	private AbstractReaderCharPacketProducer producer;
50  
51  	@Before
52  	public void runBeforeEveryTest() throws Exception {
53  		this.consumer = new StoreCharPacketConsumer();
54  		this.producer = getReaderCharPipeProducer();
55  		this.producer.setDataWaitTime(dataWaitTime);
56  		this.producer.setConsumer(this.consumer);
57  		this.producer.setExecutor(Executors.newCachedThreadPool());
58  	}
59  	
60  	protected abstract AbstractReaderCharPacketProducer getReaderCharPipeProducer();
61  
62  	@Test
63  	public void readMuchMoreDataThanBufferSize() {
64  		executeTestWithRandomData(bufSize*10);
65  	}
66  
67  	@Test
68  	public void readSingleChar() {
69  		executeTestWithRandomData(1);
70  	}
71  
72  	@Test
73  	public void readEmptyStream() {
74  		executeTestWithRandomData(0);
75  	}
76  	
77  	@Test
78  	public void readStutteringStream() throws IOException {
79  		final String testData = "ab\ncd";
80  		
81  		final PipedReader reader = new PipedReader();
82  		final PipedWriter writer = new PipedWriter(reader);
83  
84  		Thread t = new Thread() {
85  			public void run() {
86  				try {
87  					for (int i = 0; i < testData.length(); i++) {
88  						Thread.sleep(10);
89  						log.debug("sending data: " + testData.charAt(i));
90  						writer.append(testData.charAt(i));
91  					}
92  					writer.flush();
93  				}
94  				catch (Exception e) {
95  					throw new RuntimeException("exception in test data driver thread", e);
96  				}
97  			}
98  		};
99  		t.start();
100 		
101 		sendAndCheckTestData(testData, reader);
102 	}
103 
104 	private void executeTestWithRandomData(int dataSize) {
105 		String randStr = RandomStringUtils.random(dataSize, 'a', 'z', true, false);
106 		Reader testDataReader = new CharArrayReader(randStr.toCharArray());
107 		
108 		sendAndCheckTestData(randStr, testDataReader);
109 	}
110 
111 	private void sendAndCheckTestData(String testData, Reader testDataReader) {
112 		this.producer.setReader(testDataReader);
113 		
114 		this.producer.start();
115 		try {
116 			Thread.sleep(100);
117 			this.producer.shutdown();
118 		}
119 		catch (InterruptedException e) {
120 			fail("unexpected interrupt");
121 		}
122 
123 		String consumedChars = this.consumer.retrieveData();
124 		log.debug("consumer data retrieved: '" + consumedChars + "'");
125 		
126 		assertEquals(testData, consumedChars);
127 	}
128 }