View Javadoc
1   /********************************************************************************
2    * CruiseControl, a Continuous Integration Toolkit
3    * Copyright (c) 2003, ThoughtWorks, Inc.
4    * 651 W Washington Ave. Suite 500
5    * Chicago, IL 60661 USA
6    * All rights reserved.
7    *
8    * Redistribution and use in source and binary forms, with or without
9    * modification, are permitted provided that the following conditions
10   * are met:
11   *
12   *     + Redistributions of source code must retain the above copyright
13   *       notice, this list of conditions and the following disclaimer.
14   *
15   *     + Redistributions in binary form must reproduce the above
16   *       copyright notice, this list of conditions and the following
17   *       disclaimer in the documentation and/or other materials provided
18   *       with the distribution.
19   *
20   *     + Neither the name of ThoughtWorks, Inc., CruiseControl, nor the
21   *       names of its contributors may be used to endorse or promote
22   *       products derived from this software without specific prior
23   *       written permission.
24   *
25   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26   * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27   * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28   * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
29   * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30   * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31   * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32   * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33   * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34   * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36   ********************************************************************************/
37  package org.codehaus.plexus.util.cli;
38  
39  /*
40   * Copyright The Codehaus Foundation.
41   *
42   * Licensed under the Apache License, Version 2.0 (the "License");
43   * you may not use this file except in compliance with the License.
44   * You may obtain a copy of the License at
45   *
46   *     http://www.apache.org/licenses/LICENSE-2.0
47   *
48   * Unless required by applicable law or agreed to in writing, software
49   * distributed under the License is distributed on an "AS IS" BASIS,
50   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
51   * See the License for the specific language governing permissions and
52   * limitations under the License.
53   */
54  
55  import junit.framework.TestCase;
56  
57  import java.io.ByteArrayInputStream;
58  import java.io.IOException;
59  import java.io.InputStream;
60  import java.io.PrintWriter;
61  import java.io.StringWriter;
62  import java.util.ArrayList;
63  import java.util.List;
64  
65  /**
66   * @author <a href="mailto:pj@thoughtworks.com">Paul Julius</a>
67   */
68  public class StreamPumperTest
69      extends TestCase
70  {
71      private String lineSeparator;
72  
73      /**
74       * @param testName
75       */
76      public StreamPumperTest( String testName )
77      {
78          super( testName );
79      }
80  
81      /*
82       * @see TestCase#setUp()
83       */
84      public void setUp()
85          throws Exception
86      {
87          super.setUp();
88          lineSeparator = System.getProperty( "line.separator" );
89      }
90  
91      public void testPumping()
92      {
93          String line1 = "line1";
94          String line2 = "line2";
95          String lines = line1 + "\n" + line2;
96          ByteArrayInputStream inputStream = new ByteArrayInputStream( lines.getBytes() );
97  
98          TestConsumer consumer = new TestConsumer();
99          StreamPumper pumper = new StreamPumper( inputStream, consumer );
100         new Thread( pumper ).run();
101 
102         // Check the consumer to see if it got both lines.
103         assertTrue( consumer.wasLineConsumed( line1, 1000 ) );
104         assertTrue( consumer.wasLineConsumed( line2, 1000 ) );
105     }
106 
107     public void testPumpingWithPrintWriter()
108     {
109         String inputString = "This a test string";
110         ByteArrayInputStream bais = new ByteArrayInputStream( inputString.getBytes() );
111         StringWriter sw = new StringWriter();
112         PrintWriter pw = new PrintWriter( sw );
113         StreamPumper pumper = new StreamPumper( bais, pw );
114         pumper.run();
115         pumper.flush();
116         System.out.println( "aaa" + sw.toString() );
117         assertEquals( "This a test string" + lineSeparator, sw.toString() );
118         pumper.close();
119     }
120 
121     public void testPumperReadsInputStreamUntilEndEvenIfConsumerFails()
122     {
123         // the number of bytes generated should surely exceed the read buffer used by the pumper
124         GeneratorInputStream gis = new GeneratorInputStream( 1024 * 1024 * 4 );
125         StreamPumper pumper = new StreamPumper( gis, new FailingConsumer() );
126         pumper.run();
127         assertEquals( "input stream was not fully consumed, producer deadlocks", gis.size, gis.read );
128         assertTrue( gis.closed );
129         assertNotNull( pumper.getException() );
130     }
131 
132     static class GeneratorInputStream
133         extends InputStream
134     {
135 
136         final int size;
137 
138         int read = 0;
139 
140         boolean closed = false;
141 
142         public GeneratorInputStream( int size )
143         {
144             this.size = size;
145         }
146 
147         public int read()
148             throws IOException
149         {
150             if ( read < size )
151             {
152                 read++;
153                 return '\n';
154             }
155             else
156             {
157                 return -1;
158             }
159         }
160 
161         public void close()
162             throws IOException
163         {
164             closed = true;
165         }
166 
167     }
168 
169     static class FailingConsumer
170         implements StreamConsumer
171     {
172 
173         public void consumeLine( String line )
174         {
175             throw new NullPointerException( "too bad, the consumer is badly implemented..." );
176         }
177 
178     }
179 
180     /**
181      * Used by the test to track whether a line actually got consumed or not.
182      */
183     static class TestConsumer
184         implements StreamConsumer
185     {
186 
187         private List<String> lines = new ArrayList<String>();
188 
189         /**
190          * Checks to see if this consumer consumed a particular line. This method will wait up to timeout number of
191          * milliseconds for the line to get consumed.
192          *
193          * @param testLine Line to test for.
194          * @param timeout Number of milliseconds to wait for the line.
195          * @return true if the line gets consumed, else false.
196          */
197         public boolean wasLineConsumed( String testLine, long timeout )
198         {
199 
200             long start = System.currentTimeMillis();
201             long trialTime = 0;
202 
203             do
204             {
205                 if ( lines.contains( testLine ) )
206                 {
207                     return true;
208                 }
209 
210                 // Sleep a bit.
211                 try
212                 {
213                     Thread.sleep( 10 );
214                 }
215                 catch ( InterruptedException e )
216                 {
217                     // ignoring...
218                 }
219 
220                 // How long have been waiting for the line?
221                 trialTime = System.currentTimeMillis() - start;
222 
223             }
224             while ( trialTime < timeout );
225 
226             // If we got here, then the line wasn't consumed within the timeout
227             return false;
228         }
229 
230         public void consumeLine( String line )
231         {
232             lines.add( line );
233         }
234     }
235 
236     public void testEnabled()
237     {
238         ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream( "AB\nCE\nEF".getBytes() );
239         TestConsumer streamConsumer = new TestConsumer();
240         StreamPumper streamPumper = new StreamPumper( byteArrayInputStream, streamConsumer );
241         streamPumper.run();
242         assertEquals( 3, streamConsumer.lines.size() );
243     }
244 
245     public void testDisabled()
246     {
247         ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream( "AB\nCE\nEF".getBytes() );
248         TestConsumer streamConsumer = new TestConsumer();
249         StreamPumper streamPumper = new StreamPumper( byteArrayInputStream, streamConsumer );
250         streamPumper.disable();
251         streamPumper.run();
252         assertEquals( 0, streamConsumer.lines.size() );
253     }
254 }