Home | History | Annotate | Download | only in io
      1 /*
      2  * Copyright (C) 2007 The Guava Authors
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  * http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package com.google.common.io;
     18 
     19 import static com.google.common.base.Charsets.UTF_8;
     20 import static com.google.common.io.CharStreams.copy;
     21 import static com.google.common.io.CharStreams.newReaderSupplier;
     22 
     23 import com.google.common.base.Charsets;
     24 import com.google.common.collect.ImmutableList;
     25 import com.google.common.collect.ImmutableSet;
     26 import com.google.common.testing.TestLogHandler;
     27 
     28 import java.io.ByteArrayInputStream;
     29 import java.io.EOFException;
     30 import java.io.FilterReader;
     31 import java.io.FilterWriter;
     32 import java.io.IOException;
     33 import java.io.InputStreamReader;
     34 import java.io.Reader;
     35 import java.io.StringReader;
     36 import java.io.StringWriter;
     37 import java.io.Writer;
     38 import java.util.List;
     39 
     40 /**
     41  * Unit test for {@link CharStreams}.
     42  *
     43  * @author Chris Nokleberg
     44  */
     45 public class CharStreamsTest extends IoTestCase {
     46   private static final String TEXT
     47       = "The quick brown fox jumped over the lazy dog.";
     48 
     49   static final InputSupplier<? extends Reader> BROKEN_READ
     50       = CharStreams.newReaderSupplier(ByteStreamsTest.BROKEN_READ, UTF_8);
     51 
     52   static final OutputSupplier<? extends Writer> BROKEN_WRITE
     53       = CharStreams.newWriterSupplier(ByteStreamsTest.BROKEN_WRITE, UTF_8);
     54 
     55   static final InputSupplier<? extends Reader> BROKEN_CLOSE_INPUT
     56       = CharStreams.newReaderSupplier(ByteStreamsTest.BROKEN_CLOSE_INPUT, UTF_8);
     57 
     58   static final OutputSupplier<? extends Writer> BROKEN_CLOSE_OUTPUT
     59       = CharStreams.newWriterSupplier(ByteStreamsTest.BROKEN_CLOSE_OUTPUT, UTF_8);
     60 
     61   static final InputSupplier<? extends Reader> BROKEN_GET_INPUT
     62       = CharStreams.newReaderSupplier(ByteStreamsTest.BROKEN_GET_INPUT, UTF_8);
     63 
     64   static final OutputSupplier<? extends Writer> BROKEN_GET_OUTPUT
     65       = CharStreams.newWriterSupplier(ByteStreamsTest.BROKEN_GET_OUTPUT, UTF_8);
     66 
     67   private static final ImmutableSet<InputSupplier<? extends Reader>> BROKEN_INPUTS =
     68       ImmutableSet.of(BROKEN_CLOSE_INPUT, BROKEN_GET_INPUT, BROKEN_READ);
     69   private static final ImmutableSet<OutputSupplier<? extends Writer>> BROKEN_OUTPUTS
     70       = ImmutableSet.of(BROKEN_CLOSE_OUTPUT, BROKEN_GET_OUTPUT, BROKEN_WRITE);
     71 
     72   public void testToString() throws IOException {
     73     assertEquals(TEXT, CharStreams.toString(new StringReader(TEXT)));
     74     assertEquals(TEXT,
     75         CharStreams.toString(CharStreams.newReaderSupplier(TEXT)));
     76   }
     77 
     78   public void testSkipFully_blockingRead() throws IOException {
     79     Reader reader = new NonSkippingReader("abcdef");
     80     CharStreams.skipFully(reader, 6);
     81     assertEquals(-1, reader.read());
     82   }
     83 
     84   private static class NonSkippingReader extends StringReader {
     85     NonSkippingReader(String s) {
     86       super(s);
     87     }
     88 
     89     @Override
     90     public long skip(long n) {
     91       return 0;
     92     }
     93   }
     94 
     95   public void testReadLines_fromReadable() throws IOException {
     96     byte[] bytes = "a\nb\nc".getBytes(Charsets.UTF_8.name());
     97     List<String> lines = CharStreams.readLines(
     98         new InputStreamReader(new ByteArrayInputStream(bytes), Charsets.UTF_8));
     99     assertEquals(ImmutableList.of("a", "b", "c"), lines);
    100   }
    101 
    102   public void testReadLines_withLineProcessor() throws IOException {
    103     InputSupplier<StringReader> r = CharStreams.newReaderSupplier("a\nb\nc");
    104 
    105     // Test a LineProcessor that always returns false.
    106     LineProcessor<Integer> alwaysFalse = new LineProcessor<Integer>() {
    107       int seen;
    108       @Override
    109       public boolean processLine(String line) {
    110         seen++;
    111         return false;
    112       }
    113       @Override
    114       public Integer getResult() {
    115         return seen;
    116       }
    117     };
    118     assertEquals("processLine was called more than once", 1,
    119         CharStreams.readLines(r, alwaysFalse).intValue());
    120 
    121     // Test a LineProcessor that always returns true.
    122     LineProcessor<Integer> alwaysTrue = new LineProcessor<Integer>() {
    123       int seen;
    124       @Override
    125       public boolean processLine(String line) {
    126         seen++;
    127         return true;
    128       }
    129       @Override
    130       public Integer getResult() {
    131         return seen;
    132       }
    133     };
    134     assertEquals("processLine was not called for all the lines", 3,
    135         CharStreams.readLines(r, alwaysTrue).intValue());
    136 
    137     // Test a LineProcessor that is conditional.
    138     final StringBuilder sb = new StringBuilder();
    139     LineProcessor<Integer> conditional = new LineProcessor<Integer>() {
    140       int seen;
    141       @Override
    142       public boolean processLine(String line) {
    143         seen++;
    144         sb.append(line);
    145         return seen < 2;
    146       }
    147       @Override
    148       public Integer getResult() {
    149         return seen;
    150       }
    151     };
    152     assertEquals(2, CharStreams.readLines(r, conditional).intValue());
    153     assertEquals("ab", sb.toString());
    154   }
    155 
    156   public void testAlwaysCloses() throws IOException {
    157     CheckCloseSupplier.Input<Reader> okRead
    158         = newCheckReader(CharStreams.newReaderSupplier(TEXT));
    159     CheckCloseSupplier.Output<Writer> okWrite
    160         = newCheckWriter(new OutputSupplier<Writer>() {
    161           @Override
    162           public Writer getOutput() {
    163             return new StringWriter();
    164           }
    165         });
    166     CheckCloseSupplier.Input<Reader> brokenRead = newCheckReader(BROKEN_READ);
    167     CheckCloseSupplier.Output<Writer> brokenWrite
    168         = newCheckWriter(BROKEN_WRITE);
    169 
    170     CharStreams.copy(okRead, okWrite);
    171     assertTrue(okRead.areClosed());
    172     assertTrue(okWrite.areClosed());
    173 
    174     try {
    175       CharStreams.copy(okRead, brokenWrite);
    176       fail("expected exception");
    177     } catch (Exception e) {
    178       assertEquals("broken write", e.getMessage());
    179     }
    180     assertTrue(okRead.areClosed());
    181     assertTrue(brokenWrite.areClosed());
    182 
    183     try {
    184       CharStreams.copy(brokenRead, okWrite);
    185       fail("expected exception");
    186     } catch (Exception e) {
    187       assertEquals("broken read", e.getMessage());
    188     }
    189     assertTrue(brokenRead.areClosed());
    190     assertTrue(okWrite.areClosed());
    191 
    192     try {
    193       CharStreams.copy(brokenRead, brokenWrite);
    194       fail("expected exception");
    195     } catch (Exception e) {
    196       assertEquals("broken read", e.getMessage());
    197     }
    198     assertTrue(brokenRead.areClosed());
    199     assertTrue(brokenWrite.areClosed());
    200 
    201     assertEquals(TEXT, CharStreams.toString(okRead));
    202     assertTrue(okRead.areClosed());
    203 
    204     try {
    205       CharStreams.toString(brokenRead);
    206       fail("expected exception");
    207     } catch (Exception e) {
    208       assertEquals("broken read", e.getMessage());
    209     }
    210     assertTrue(brokenRead.areClosed());
    211 
    212     try {
    213       CharStreams.write("hello world", brokenWrite);
    214       fail("expected exception");
    215     } catch (Exception e) {
    216       assertEquals("broken write", e.getMessage());
    217     }
    218     assertTrue(brokenWrite.areClosed());
    219   }
    220 
    221   private static int getAndResetRecords(TestLogHandler logHandler) {
    222     int records = logHandler.getStoredLogRecords().size();
    223     logHandler.clear();
    224     return records;
    225   }
    226 
    227   private static void runFailureTest(
    228       InputSupplier<? extends Reader> in, OutputSupplier<? extends Writer> out) {
    229     try {
    230       copy(in, out);
    231       fail();
    232     } catch (IOException expected) {
    233     }
    234   }
    235 
    236   private static OutputSupplier<Writer> newStringWriterSupplier() {
    237     return new OutputSupplier<Writer>() {
    238       @Override public Writer getOutput() {
    239         return new StringWriter();
    240       }
    241     };
    242   }
    243 
    244   public void testSkipFully_EOF() throws IOException {
    245     Reader reader = new StringReader("abcde");
    246     try {
    247       CharStreams.skipFully(reader, 6);
    248       fail("expected EOFException");
    249     } catch (EOFException e) {
    250       // expected
    251     }
    252   }
    253 
    254   public void testSkipFully() throws IOException {
    255     String testString = "abcdef";
    256     Reader reader = new StringReader(testString);
    257 
    258     assertEquals(testString.charAt(0), reader.read());
    259     CharStreams.skipFully(reader, 1);
    260     assertEquals(testString.charAt(2), reader.read());
    261     CharStreams.skipFully(reader, 2);
    262     assertEquals(testString.charAt(5), reader.read());
    263 
    264     assertEquals(-1, reader.read());
    265   }
    266 
    267   public void testAsWriter() {
    268     // Should wrap Appendable in a new object
    269     Appendable plainAppendable = new StringBuilder();
    270     Writer result = CharStreams.asWriter(plainAppendable);
    271     assertNotSame(plainAppendable, result);
    272     assertNotNull(result);
    273 
    274     // A Writer should not be wrapped
    275     Appendable secretlyAWriter = new StringWriter();
    276     result = CharStreams.asWriter(secretlyAWriter);
    277     assertSame(secretlyAWriter, result);
    278   }
    279 
    280   public void testWriteString() throws IOException {
    281     final StringWriter sw = new StringWriter();
    282     String expected = "foo";
    283     CharStreams.write(expected, new OutputSupplier<Writer>() {
    284       @Override public Writer getOutput() {
    285         return sw;
    286       }
    287     });
    288     assertEquals(expected, sw.toString());
    289   }
    290 
    291   private static CheckCloseSupplier.Input<Reader> newCheckReader(
    292       InputSupplier<? extends Reader> delegate) {
    293     return new CheckCloseSupplier.Input<Reader>(delegate) {
    294       @Override protected Reader wrap(Reader object, final Callback callback) {
    295         return new FilterReader(object) {
    296           @Override public void close() throws IOException {
    297             callback.delegateClosed();
    298             super.close();
    299           }
    300         };
    301       }
    302     };
    303   }
    304 
    305   private static CheckCloseSupplier.Output<Writer> newCheckWriter(
    306       OutputSupplier<? extends Writer> delegate) {
    307     return new CheckCloseSupplier.Output<Writer>(delegate) {
    308       @Override protected Writer wrap(Writer object, final Callback callback) {
    309         return new FilterWriter(object) {
    310           @Override public void close() throws IOException {
    311             callback.delegateClosed();
    312             super.close();
    313           }
    314         };
    315       }
    316     };
    317   }
    318 }
    319