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 java.io.ByteArrayInputStream;
56  import java.io.IOException;
57  import java.io.InputStream;
58  import java.io.PrintWriter;
59  import java.io.StringWriter;
60  import java.util.ArrayList;
61  import java.util.List;
62  
63  import org.junit.jupiter.api.Test;
64  
65  import static org.junit.jupiter.api.Assertions.assertEquals;
66  import static org.junit.jupiter.api.Assertions.assertNotNull;
67  import static org.junit.jupiter.api.Assertions.assertTrue;
68  
69  /**
70   * <p>StreamPumperTest class.</p>
71   *
72   * @author <a href="mailto:pj@thoughtworks.com">Paul Julius</a>
73   * @version $Id: $Id
74   * @since 3.4.0
75   */
76  public class StreamPumperTest {
77      private String lineSeparator = System.lineSeparator();
78  
79      /**
80       * <p>testPumping.</p>
81       */
82      @Test
83      public void testPumping() {
84          String line1 = "line1";
85          String line2 = "line2";
86          String lines = line1 + "\n" + line2;
87          ByteArrayInputStream inputStream = new ByteArrayInputStream(lines.getBytes());
88  
89          TestConsumer consumer = new TestConsumer();
90          StreamPumper pumper = new StreamPumper(inputStream, consumer);
91          new Thread(pumper).run();
92  
93          // Check the consumer to see if it got both lines.
94          assertTrue(consumer.wasLineConsumed(line1, 1000));
95          assertTrue(consumer.wasLineConsumed(line2, 1000));
96      }
97  
98      /**
99       * <p>testPumpingWithPrintWriter.</p>
100      */
101     @org.junit.jupiter.api.Test
102     public void testPumpingWithPrintWriter() {
103         String inputString = "This a test string";
104         ByteArrayInputStream bais = new ByteArrayInputStream(inputString.getBytes());
105         StringWriter sw = new StringWriter();
106         PrintWriter pw = new PrintWriter(sw);
107         StreamPumper pumper = new StreamPumper(bais, pw);
108         pumper.run();
109         pumper.flush();
110         System.out.println("aaa" + sw.toString());
111         assertEquals("This a test string" + lineSeparator, sw.toString());
112         pumper.close();
113     }
114 
115     /**
116      * <p>testPumperReadsInputStreamUntilEndEvenIfConsumerFails.</p>
117      */
118     @Test
119     public void testPumperReadsInputStreamUntilEndEvenIfConsumerFails() {
120         // the number of bytes generated should surely exceed the read buffer used by the pumper
121         GeneratorInputStream gis = new GeneratorInputStream(1024 * 1024 * 4);
122         StreamPumper pumper = new StreamPumper(gis, new FailingConsumer());
123         pumper.run();
124         assertEquals(gis.size, gis.read, "input stream was not fully consumed, producer deadlocks");
125         assertTrue(gis.closed);
126         assertNotNull(pumper.getException());
127     }
128 
129     static class GeneratorInputStream extends InputStream {
130 
131         final int size;
132 
133         int read = 0;
134 
135         boolean closed = false;
136 
137         public GeneratorInputStream(int size) {
138             this.size = size;
139         }
140 
141         public int read() throws IOException {
142             if (read < size) {
143                 read++;
144                 return '\n';
145             } else {
146                 return -1;
147             }
148         }
149 
150         public void close() throws IOException {
151             closed = true;
152         }
153     }
154 
155     static class FailingConsumer implements StreamConsumer {
156 
157         public void consumeLine(String line) {
158             throw new NullPointerException("too bad, the consumer is badly implemented...");
159         }
160     }
161 
162     /**
163      * Used by the test to track whether a line actually got consumed or not.
164      */
165     static class TestConsumer implements StreamConsumer {
166 
167         private List<String> lines = new ArrayList<String>();
168 
169         /**
170          * Checks to see if this consumer consumed a particular line. This method will wait up to timeout number of
171          * milliseconds for the line to get consumed.
172          *
173          * @param testLine Line to test for.
174          * @param timeout Number of milliseconds to wait for the line.
175          * @return true if the line gets consumed, else false.
176          */
177         public boolean wasLineConsumed(String testLine, long timeout) {
178 
179             long start = System.currentTimeMillis();
180             long trialTime = 0;
181 
182             do {
183                 if (lines.contains(testLine)) {
184                     return true;
185                 }
186 
187                 // Sleep a bit.
188                 try {
189                     Thread.sleep(10);
190                 } catch (InterruptedException e) {
191                     // ignoring...
192                 }
193 
194                 // How long have been waiting for the line?
195                 trialTime = System.currentTimeMillis() - start;
196 
197             } while (trialTime < timeout);
198 
199             // If we got here, then the line wasn't consumed within the timeout
200             return false;
201         }
202 
203         public void consumeLine(String line) {
204             lines.add(line);
205         }
206     }
207 
208     /**
209      * <p>testEnabled.</p>
210      */
211     @org.junit.jupiter.api.Test
212     public void testEnabled() {
213         ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream("AB\nCE\nEF".getBytes());
214         TestConsumer streamConsumer = new TestConsumer();
215         StreamPumper streamPumper = new StreamPumper(byteArrayInputStream, streamConsumer);
216         streamPumper.run();
217         assertEquals(3, streamConsumer.lines.size());
218     }
219 
220     /**
221      * <p>testDisabled.</p>
222      */
223     @Test
224     public void testDisabled() {
225         ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream("AB\nCE\nEF".getBytes());
226         TestConsumer streamConsumer = new TestConsumer();
227         StreamPumper streamPumper = new StreamPumper(byteArrayInputStream, streamConsumer);
228         streamPumper.disable();
229         streamPumper.run();
230         assertEquals(0, streamConsumer.lines.size());
231     }
232 }