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 com.google.common.base.Strings; 20 import com.google.common.collect.ImmutableList; 21 22 import java.io.EOFException; 23 import java.io.FilterReader; 24 import java.io.IOException; 25 import java.io.Reader; 26 import java.io.StringReader; 27 import java.io.StringWriter; 28 import java.io.Writer; 29 import java.util.List; 30 31 /** 32 * Unit test for {@link CharStreams}. 33 * 34 * @author Chris Nokleberg 35 */ 36 public class CharStreamsTest extends IoTestCase { 37 38 private static final String TEXT 39 = "The quick brown fox jumped over the lazy dog."; 40 testToString()41 public void testToString() throws IOException { 42 assertEquals(TEXT, CharStreams.toString(new StringReader(TEXT))); 43 } 44 testSkipFully_blockingRead()45 public void testSkipFully_blockingRead() throws IOException { 46 Reader reader = new NonSkippingReader("abcdef"); 47 CharStreams.skipFully(reader, 6); 48 assertEquals(-1, reader.read()); 49 } 50 51 private static class NonSkippingReader extends StringReader { NonSkippingReader(String s)52 NonSkippingReader(String s) { 53 super(s); 54 } 55 56 @Override skip(long n)57 public long skip(long n) { 58 return 0; 59 } 60 } 61 testReadLines()62 public void testReadLines() throws IOException { 63 List<String> lines = CharStreams.readLines( 64 new StringReader("a\nb\nc")); 65 assertEquals(ImmutableList.of("a", "b", "c"), lines); 66 } 67 testReadLines_withLineProcessor()68 public void testReadLines_withLineProcessor() throws IOException { 69 String text = "a\nb\nc"; 70 71 // Test a LineProcessor that always returns false. 72 Reader r = new StringReader(text); 73 LineProcessor<Integer> alwaysFalse = new LineProcessor<Integer>() { 74 int seen; 75 @Override 76 public boolean processLine(String line) { 77 seen++; 78 return false; 79 } 80 @Override 81 public Integer getResult() { 82 return seen; 83 } 84 }; 85 assertEquals("processLine was called more than once", 1, 86 CharStreams.readLines(r, alwaysFalse).intValue()); 87 88 // Test a LineProcessor that always returns true. 89 r = new StringReader(text); 90 LineProcessor<Integer> alwaysTrue = new LineProcessor<Integer>() { 91 int seen; 92 @Override 93 public boolean processLine(String line) { 94 seen++; 95 return true; 96 } 97 @Override 98 public Integer getResult() { 99 return seen; 100 } 101 }; 102 assertEquals("processLine was not called for all the lines", 3, 103 CharStreams.readLines(r, alwaysTrue).intValue()); 104 105 // Test a LineProcessor that is conditional. 106 r = new StringReader(text); 107 final StringBuilder sb = new StringBuilder(); 108 LineProcessor<Integer> conditional = new LineProcessor<Integer>() { 109 int seen; 110 @Override 111 public boolean processLine(String line) { 112 seen++; 113 sb.append(line); 114 return seen < 2; 115 } 116 @Override 117 public Integer getResult() { 118 return seen; 119 } 120 }; 121 assertEquals(2, CharStreams.readLines(r, conditional).intValue()); 122 assertEquals("ab", sb.toString()); 123 } 124 testSkipFully_EOF()125 public void testSkipFully_EOF() throws IOException { 126 Reader reader = new StringReader("abcde"); 127 try { 128 CharStreams.skipFully(reader, 6); 129 fail("expected EOFException"); 130 } catch (EOFException e) { 131 // expected 132 } 133 } 134 testSkipFully()135 public void testSkipFully() throws IOException { 136 String testString = "abcdef"; 137 Reader reader = new StringReader(testString); 138 139 assertEquals(testString.charAt(0), reader.read()); 140 CharStreams.skipFully(reader, 1); 141 assertEquals(testString.charAt(2), reader.read()); 142 CharStreams.skipFully(reader, 2); 143 assertEquals(testString.charAt(5), reader.read()); 144 145 assertEquals(-1, reader.read()); 146 } 147 testAsWriter()148 public void testAsWriter() { 149 // Should wrap Appendable in a new object 150 Appendable plainAppendable = new StringBuilder(); 151 Writer result = CharStreams.asWriter(plainAppendable); 152 assertNotSame(plainAppendable, result); 153 assertNotNull(result); 154 155 // A Writer should not be wrapped 156 Appendable secretlyAWriter = new StringWriter(); 157 result = CharStreams.asWriter(secretlyAWriter); 158 assertSame(secretlyAWriter, result); 159 } 160 testCopy()161 public void testCopy() throws IOException { 162 StringBuilder builder = new StringBuilder(); 163 long copied = CharStreams.copy(new StringReader(ASCII), builder); 164 assertEquals(ASCII, builder.toString()); 165 assertEquals(ASCII.length(), copied); 166 167 StringBuilder builder2 = new StringBuilder(); 168 copied = CharStreams.copy(new StringReader(I18N), builder2); 169 assertEquals(I18N, builder2.toString()); 170 assertEquals(I18N.length(), copied); 171 } 172 173 /** 174 * Test for Guava issue 1061: http://code.google.com/p/guava-libraries/issues/detail?id=1061 175 * 176 * <p>CharStreams.copy was failing to clear its CharBuffer after each read call, which effectively 177 * reduced the available size of the buffer each time a call to read didn't fill up the available 178 * space in the buffer completely. In general this is a performance problem since the buffer size 179 * is permanently reduced, but with certain Reader implementations it could also cause the buffer 180 * size to reach 0, causing an infinite loop. 181 */ testCopyWithReaderThatDoesNotFillBuffer()182 public void testCopyWithReaderThatDoesNotFillBuffer() throws IOException { 183 // need a long enough string for the buffer to hit 0 remaining before the copy completes 184 String string = Strings.repeat("0123456789", 100); 185 StringBuilder b = new StringBuilder(); 186 // the main assertion of this test is here... the copy will fail if the buffer size goes down 187 // each time it is not filled completely 188 long copied = CharStreams.copy(newNonBufferFillingReader(new StringReader(string)), b); 189 assertEquals(string, b.toString()); 190 assertEquals(string.length(), copied); 191 } 192 testNullWriter()193 public void testNullWriter() throws Exception { 194 // create a null writer 195 Writer nullWriter = CharStreams.nullWriter(); 196 // write to the writer 197 nullWriter.write('n'); 198 String test = "Test string for NullWriter"; 199 nullWriter.write(test); 200 nullWriter.write(test, 2, 10); 201 // nothing really to assert? 202 assertSame(CharStreams.nullWriter(), CharStreams.nullWriter()); 203 } 204 205 /** 206 * Returns a reader wrapping the given reader that only reads half of the maximum number of 207 * characters that it could read in read(char[], int, int). 208 */ newNonBufferFillingReader(Reader reader)209 private static Reader newNonBufferFillingReader(Reader reader) { 210 return new FilterReader(reader) { 211 @Override 212 public int read(char[] cbuf, int off, int len) throws IOException { 213 // if a buffer isn't being cleared correctly, this method will eventually start being called 214 // with a len of 0 forever 215 if (len <= 0) { 216 fail("read called with a len of " + len); 217 } 218 // read fewer than the max number of chars to read 219 // shouldn't be a problem unless the buffer is shrinking each call 220 return in.read(cbuf, off, Math.max(len - 1024, 0)); 221 } 222 }; 223 } 224 } 225