View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.io.output;
18  
19  import static org.junit.jupiter.api.Assertions.assertEquals;
20  import static org.junit.jupiter.api.Assertions.assertThrows;
21  import static org.junit.jupiter.api.Assertions.assertTrue;
22  import static org.mockito.Mockito.mock;
23  import static org.mockito.Mockito.verify;
24  
25  import java.io.IOException;
26  import java.io.StringWriter;
27  import java.io.Writer;
28  import java.util.Arrays;
29  import java.util.Collection;
30  
31  import org.apache.commons.io.IOExceptionList;
32  import org.apache.commons.io.IOIndexedException;
33  import org.junit.jupiter.api.Test;
34  
35  /**
36   * Tests {@link TeeWriter}.
37   */
38  @SuppressWarnings("resource") // not necessary to close these resources
39  public class TeeWriterTest {
40  
41      @Test
42      public void testArrayIOExceptionOnAppendChar1() {
43          final Writer badW = BrokenWriter.INSTANCE;
44          final StringWriter goodW = mock(StringWriter.class);
45          final ProxyCollectionWriter tw = new ProxyCollectionWriter(badW, goodW, null);
46          final char data = 'A';
47  
48          final IOExceptionList e = assertThrows(IOExceptionList.class, () -> tw.append(data));
49          verify(goodW).append(data);
50          assertEquals(1, e.getCauseList().size());
51          assertEquals(0, e.getCause(0, IOIndexedException.class).getIndex());
52      }
53  
54      @Test
55      public void testArrayIOExceptionOnAppendChar2() {
56          final Writer badW = BrokenWriter.INSTANCE;
57          final StringWriter goodW = mock(StringWriter.class);
58          final ProxyCollectionWriter tw = new ProxyCollectionWriter(goodW, badW, null);
59          final char data = 'A';
60  
61          final IOExceptionList e = assertThrows(IOExceptionList.class, () -> tw.append(data));
62          verify(goodW).append(data);
63          assertEquals(1, e.getCauseList().size());
64          assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex());
65      }
66  
67      @Test
68      public void testArrayIOExceptionOnAppendCharSequence1() {
69          final Writer badW = BrokenWriter.INSTANCE;
70          final StringWriter goodW = mock(StringWriter.class);
71          final TeeWriter tw = new TeeWriter(badW, goodW, null);
72          final String data = "A";
73  
74          final IOExceptionList e = assertThrows(IOExceptionList.class, () -> tw.append(data));
75          verify(goodW).append(data);
76          assertEquals(1, e.getCauseList().size());
77          assertEquals(0, e.getCause(0, IOIndexedException.class).getIndex());
78      }
79  
80      @Test
81      public void testArrayIOExceptionOnAppendCharSequence2() {
82          final Writer badW = BrokenWriter.INSTANCE;
83          final StringWriter goodW = mock(StringWriter.class);
84          final TeeWriter tw = new TeeWriter(goodW, badW, null);
85          final String data = "A";
86  
87          final IOExceptionList e = assertThrows(IOExceptionList.class, () -> tw.append(data));
88          verify(goodW).append(data);
89          assertEquals(1, e.getCauseList().size());
90          assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex());
91      }
92  
93      @Test
94      public void testArrayIOExceptionOnAppendCharSequenceIntInt1() {
95          final Writer badW = BrokenWriter.INSTANCE;
96          final StringWriter goodW = mock(StringWriter.class);
97          final TeeWriter tw = new TeeWriter(badW, goodW, null);
98          final String data = "A";
99  
100         final IOExceptionList e = assertThrows(IOExceptionList.class, () -> tw.append(data, 0, 0));
101         verify(goodW).append(data, 0, 0);
102         assertEquals(1, e.getCauseList().size());
103         assertEquals(0, e.getCause(0, IOIndexedException.class).getIndex());
104     }
105 
106     @Test
107     public void testArrayIOExceptionOnAppendCharSequenceIntInt2() {
108         final Writer badW = BrokenWriter.INSTANCE;
109         final StringWriter goodW = mock(StringWriter.class);
110         final TeeWriter tw = new TeeWriter(goodW, badW, null);
111         final String data = "A";
112 
113         final IOExceptionList e = assertThrows(IOExceptionList.class, () -> tw.append(data, 0, 0));
114         verify(goodW).append(data, 0, 0);
115         assertEquals(1, e.getCauseList().size());
116         assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex());
117     }
118 
119     @Test
120     public void testArrayIOExceptionOnClose1() throws IOException {
121         final Writer badW = BrokenWriter.INSTANCE;
122         final StringWriter goodW = mock(StringWriter.class);
123         final TeeWriter tw = new TeeWriter(badW, goodW, null);
124 
125         final IOExceptionList e = assertThrows(IOExceptionList.class, tw::close);
126         verify(goodW).close();
127         assertEquals(1, e.getCauseList().size());
128         assertEquals(0, e.getCause(0, IOIndexedException.class).getIndex());
129     }
130 
131     @Test
132     public void testArrayIOExceptionOnClose2() throws IOException {
133         final Writer badW = BrokenWriter.INSTANCE;
134         final StringWriter goodW = mock(StringWriter.class);
135         final TeeWriter tw = new TeeWriter(goodW, badW, null);
136 
137         final IOExceptionList e = assertThrows(IOExceptionList.class, tw::close);
138         verify(goodW).close();
139         assertEquals(1, e.getCauseList().size());
140         assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex());
141     }
142 
143     @Test
144     public void testArrayIOExceptionOnFlush1() {
145         final Writer badW = BrokenWriter.INSTANCE;
146         final StringWriter goodW = mock(StringWriter.class);
147         final TeeWriter tw = new TeeWriter(badW, goodW, null);
148 
149         final IOExceptionList e = assertThrows(IOExceptionList.class, tw::flush);
150         verify(goodW).flush();
151         assertEquals(1, e.getCauseList().size());
152         assertEquals(0, e.getCause(0, IOIndexedException.class).getIndex());
153     }
154 
155     @Test
156     public void testArrayIOExceptionOnFlush2() {
157         final Writer badW = BrokenWriter.INSTANCE;
158         final StringWriter goodW = mock(StringWriter.class);
159         final TeeWriter tw = new TeeWriter(goodW, badW, null);
160 
161         final IOExceptionList e = assertThrows(IOExceptionList.class, tw::flush);
162         verify(goodW).flush();
163         assertEquals(1, e.getCauseList().size());
164         assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex());
165     }
166 
167     @Test
168     public void testArrayIOExceptionOnWriteCharArray1() throws IOException {
169         final Writer badW = BrokenWriter.INSTANCE;
170         final StringWriter goodW = mock(StringWriter.class);
171         final TeeWriter tw = new TeeWriter(badW, goodW, null);
172         final char[] data = { 'a' };
173 
174         final IOExceptionList e = assertThrows(IOExceptionList.class, () -> tw.write(data));
175         verify(goodW).write(data);
176         assertEquals(1, e.getCauseList().size());
177         assertEquals(0, e.getCause(0, IOIndexedException.class).getIndex());
178     }
179 
180     @Test
181     public void testArrayIOExceptionOnWriteCharArray2() throws IOException {
182         final Writer badW = BrokenWriter.INSTANCE;
183         final StringWriter goodW = mock(StringWriter.class);
184         final TeeWriter tw = new TeeWriter(goodW, badW, null);
185         final char[] data = { 'a' };
186 
187         final IOExceptionList e = assertThrows(IOExceptionList.class, () -> tw.write(data));
188         verify(goodW).write(data);
189         assertEquals(1, e.getCauseList().size());
190         assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex());
191     }
192 
193     @Test
194     public void testArrayIOExceptionOnWriteCharArrayIntInt1() {
195         final Writer badW = BrokenWriter.INSTANCE;
196         final StringWriter goodW = mock(StringWriter.class);
197         final TeeWriter tw = new TeeWriter(badW, goodW, null);
198         final char[] data = { 'a' };
199 
200         final IOExceptionList e = assertThrows(IOExceptionList.class, () -> tw.write(data, 0, 0));
201         verify(goodW).write(data, 0, 0);
202         assertEquals(1, e.getCauseList().size());
203         assertEquals(0, e.getCause(0, IOIndexedException.class).getIndex());
204     }
205 
206     @Test
207     public void testArrayIOExceptionOnWriteCharArrayIntInt2() {
208         final Writer badW = BrokenWriter.INSTANCE;
209         final StringWriter goodW = mock(StringWriter.class);
210         final TeeWriter tw = new TeeWriter(goodW, badW, null);
211         final char[] data = { 'a' };
212 
213         final IOExceptionList e = assertThrows(IOExceptionList.class, () -> tw.write(data, 0, 0));
214         verify(goodW).write(data, 0, 0);
215         assertEquals(1, e.getCauseList().size());
216         assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex());
217     }
218 
219     @Test
220     public void testArrayIOExceptionOnWriteInt1() {
221         final Writer badW = BrokenWriter.INSTANCE;
222         final StringWriter goodW = mock(StringWriter.class);
223         final TeeWriter tw = new TeeWriter(badW, goodW, null);
224         final int data = 32;
225 
226         final IOExceptionList e = assertThrows(IOExceptionList.class, () -> tw.write(data));
227         verify(goodW).write(data);
228         assertEquals(1, e.getCauseList().size());
229         assertEquals(0, e.getCause(0, IOIndexedException.class).getIndex());
230     }
231 
232     @Test
233     public void testArrayIOExceptionOnWriteInt2() {
234         final Writer badW = BrokenWriter.INSTANCE;
235         final StringWriter goodW = mock(StringWriter.class);
236         final TeeWriter tw = new TeeWriter(goodW, badW, null);
237 
238         final IOExceptionList e = assertThrows(IOExceptionList.class, () -> tw.write(32));
239         verify(goodW).write(32);
240         assertEquals(1, e.getCauseList().size());
241         assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex());
242     }
243 
244     @Test
245     public void testArrayIOExceptionOnWriteString1() {
246         final Writer badW = BrokenWriter.INSTANCE;
247         final StringWriter goodW = mock(StringWriter.class);
248         final TeeWriter tw = new TeeWriter(badW, goodW, null);
249         final String data = "A";
250 
251         final IOExceptionList e = assertThrows(IOExceptionList.class, () -> tw.write(data));
252         verify(goodW).write(data);
253         assertEquals(1, e.getCauseList().size());
254         assertEquals(0, e.getCause(0, IOIndexedException.class).getIndex());
255     }
256 
257     @Test
258     public void testArrayIOExceptionOnWriteString2() {
259         final Writer badW = BrokenWriter.INSTANCE;
260         final StringWriter goodW = mock(StringWriter.class);
261         final TeeWriter tw = new TeeWriter(goodW, badW, null);
262         final String data = "A";
263 
264         final IOExceptionList e = assertThrows(IOExceptionList.class, () -> tw.write(data));
265         verify(goodW).write(data);
266         assertEquals(1, e.getCauseList().size());
267         assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex());
268     }
269 
270     @Test
271     public void testArrayIOExceptionOnWriteStringIntInt1() {
272         final Writer badW = BrokenWriter.INSTANCE;
273         final StringWriter goodW = mock(StringWriter.class);
274         final TeeWriter tw = new TeeWriter(badW, goodW, null);
275         final String data = "A";
276 
277         final IOExceptionList e = assertThrows(IOExceptionList.class, () -> tw.write(data, 0, 0));
278         verify(goodW).write(data, 0, 0);
279         assertEquals(1, e.getCauseList().size());
280         assertEquals(0, e.getCause(0, IOIndexedException.class).getIndex());
281     }
282 
283     @Test
284     public void testArrayIOExceptionOnWriteStringIntInt2() {
285         final Writer badW = BrokenWriter.INSTANCE;
286         final StringWriter goodW = mock(StringWriter.class);
287         final TeeWriter tw = new TeeWriter(goodW, badW, null);
288         final String data = "A";
289 
290         final IOExceptionList e = assertThrows(IOExceptionList.class, () -> tw.write(data, 0, 0));
291         verify(goodW).write(data, 0, 0);
292         assertEquals(1, e.getCauseList().size());
293         assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex());
294     }
295 
296     @Test
297     public void testCollectionCloseBranchIOException() throws IOException {
298         final Writer badW = BrokenWriter.INSTANCE;
299         final StringWriter goodW = mock(StringWriter.class);
300         final TeeWriter tw = new TeeWriter(Arrays.asList(goodW, badW, null));
301 
302         final IOExceptionList e = assertThrows(IOExceptionList.class, tw::close);
303         verify(goodW).close();
304         assertEquals(1, e.getCauseList().size());
305         assertEquals(1, e.getCause(0, IOIndexedException.class).getIndex());
306     }
307 
308     @Test
309     public void testConstructorsNull() throws IOException {
310         try (TeeWriter teeWriter = new TeeWriter((Writer[]) null)) {
311             // Call any method, should not throw
312             teeWriter.append('a');
313             teeWriter.flush();
314         }
315         try (TeeWriter teeWriter = new TeeWriter((Collection<Writer>) null)) {
316             // Call any method, should not throw
317             teeWriter.append('a');
318             teeWriter.flush();
319         }
320         assertTrue(true, "Dummy to show test completed OK");
321     }
322 
323     @Test
324     public void testTee() throws IOException {
325         final StringBuilderWriter sbw1 = new StringBuilderWriter();
326         final StringBuilderWriter sbw2 = new StringBuilderWriter();
327         final StringBuilderWriter expected = new StringBuilderWriter();
328 
329         try (TeeWriter tw = new TeeWriter(sbw1, sbw2, null)) {
330             for (int i = 0; i < 20; i++) {
331                 tw.write(i);
332                 expected.write(i);
333             }
334             assertEquals(expected.toString(), sbw1.toString(), "TeeWriter.write(int)");
335             assertEquals(expected.toString(), sbw2.toString(), "TeeWriter.write(int)");
336 
337             final char[] array = new char[10];
338             for (int i = 20; i < 30; i++) {
339                 array[i - 20] = (char) i;
340             }
341             tw.write(array);
342             expected.write(array);
343             assertEquals(expected.toString(), sbw1.toString(), "TeeWriter.write(char[])");
344             assertEquals(expected.toString(), sbw2.toString(), "TeeWriter.write(char[])");
345 
346             for (int i = 25; i < 35; i++) {
347                 array[i - 25] = (char) i;
348             }
349             tw.write(array, 5, 5);
350             expected.write(array, 5, 5);
351             assertEquals(expected.toString(), sbw1.toString(), "TeeOutputStream.write(byte[], int, int)");
352             assertEquals(expected.toString(), sbw2.toString(), "TeeOutputStream.write(byte[], int, int)");
353 
354             for (int i = 0; i < 20; i++) {
355                 tw.append((char) i);
356                 expected.append((char) i);
357             }
358             assertEquals(expected.toString(), sbw1.toString(), "TeeWriter.append(char)");
359             assertEquals(expected.toString(), sbw2.toString(), "TeeWriter.append(char)");
360 
361             for (int i = 20; i < 30; i++) {
362                 array[i - 20] = (char) i;
363             }
364             tw.append(new String(array));
365             expected.append(new String(array));
366             assertEquals(expected.toString(), sbw1.toString(), "TeeWriter.append(CharSequence)");
367             assertEquals(expected.toString(), sbw2.toString(), "TeeWriter.append(CharSequence)");
368 
369             for (int i = 25; i < 35; i++) {
370                 array[i - 25] = (char) i;
371             }
372             tw.append(new String(array), 5, 5);
373             expected.append(new String(array), 5, 5);
374             assertEquals(expected.toString(), sbw1.toString(), "TeeWriter.append(CharSequence, int, int)");
375             assertEquals(expected.toString(), sbw2.toString(), "TeeWriter.append(CharSequence, int, int)");
376 
377             expected.flush();
378             expected.close();
379 
380             tw.flush();
381         }
382     }
383 
384 }