1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342
|
/*
* Copyright (C) 2007 The Guava Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.common.io;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import java.io.EOFException;
import java.io.FilterReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import java.io.StringWriter;
import java.io.Writer;
import java.nio.CharBuffer;
import java.util.List;
/**
* Unit test for {@link CharStreams}.
*
* @author Chris Nokleberg
*/
public class CharStreamsTest extends IoTestCase {
private static final String TEXT = "The quick brown fox jumped over the lazy dog.";
public void testToString() throws IOException {
assertEquals(TEXT, CharStreams.toString(new StringReader(TEXT)));
}
public void testReadLines() throws IOException {
List<String> lines = CharStreams.readLines(new StringReader("a\nb\nc"));
assertEquals(ImmutableList.of("a", "b", "c"), lines);
}
public void testReadLines_withLineProcessor() throws IOException {
String text = "a\nb\nc";
// Test a LineProcessor that always returns false.
Reader r = new StringReader(text);
LineProcessor<Integer> alwaysFalse =
new LineProcessor<Integer>() {
int seen;
@Override
public boolean processLine(String line) {
seen++;
return false;
}
@Override
public Integer getResult() {
return seen;
}
};
assertEquals(
"processLine was called more than once",
1,
CharStreams.readLines(r, alwaysFalse).intValue());
// Test a LineProcessor that always returns true.
r = new StringReader(text);
LineProcessor<Integer> alwaysTrue =
new LineProcessor<Integer>() {
int seen;
@Override
public boolean processLine(String line) {
seen++;
return true;
}
@Override
public Integer getResult() {
return seen;
}
};
assertEquals(
"processLine was not called for all the lines",
3,
CharStreams.readLines(r, alwaysTrue).intValue());
// Test a LineProcessor that is conditional.
r = new StringReader(text);
final StringBuilder sb = new StringBuilder();
LineProcessor<Integer> conditional =
new LineProcessor<Integer>() {
int seen;
@Override
public boolean processLine(String line) {
seen++;
sb.append(line);
return seen < 2;
}
@Override
public Integer getResult() {
return seen;
}
};
assertEquals(2, CharStreams.readLines(r, conditional).intValue());
assertEquals("ab", sb.toString());
}
public void testSkipFully_EOF() throws IOException {
Reader reader = new StringReader("abcde");
try {
CharStreams.skipFully(reader, 6);
fail("expected EOFException");
} catch (EOFException expected) {
}
}
public void testSkipFully() throws IOException {
String testString = "abcdef";
Reader reader = new StringReader(testString);
assertEquals(testString.charAt(0), reader.read());
CharStreams.skipFully(reader, 1);
assertEquals(testString.charAt(2), reader.read());
CharStreams.skipFully(reader, 2);
assertEquals(testString.charAt(5), reader.read());
assertEquals(-1, reader.read());
}
public void testAsWriter() {
// Should wrap Appendable in a new object
Appendable plainAppendable = new StringBuilder();
Writer result = CharStreams.asWriter(plainAppendable);
assertNotSame(plainAppendable, result);
assertNotNull(result);
// A Writer should not be wrapped
Appendable secretlyAWriter = new StringWriter();
result = CharStreams.asWriter(secretlyAWriter);
assertSame(secretlyAWriter, result);
}
// CharStreams.copy has type specific optimizations for Readers,StringBuilders and Writers
public void testCopy() throws IOException {
StringBuilder builder = new StringBuilder();
long copied =
CharStreams.copy(
wrapAsGenericReadable(new StringReader(ASCII)), wrapAsGenericAppendable(builder));
assertEquals(ASCII, builder.toString());
assertEquals(ASCII.length(), copied);
StringBuilder builder2 = new StringBuilder();
copied =
CharStreams.copy(
wrapAsGenericReadable(new StringReader(I18N)), wrapAsGenericAppendable(builder2));
assertEquals(I18N, builder2.toString());
assertEquals(I18N.length(), copied);
}
public void testCopy_toStringBuilder_fromReader() throws IOException {
StringBuilder builder = new StringBuilder();
long copied = CharStreams.copy(new StringReader(ASCII), builder);
assertEquals(ASCII, builder.toString());
assertEquals(ASCII.length(), copied);
StringBuilder builder2 = new StringBuilder();
copied = CharStreams.copy(new StringReader(I18N), builder2);
assertEquals(I18N, builder2.toString());
assertEquals(I18N.length(), copied);
}
public void testCopy_toStringBuilder_fromReadable() throws IOException {
StringBuilder builder = new StringBuilder();
long copied = CharStreams.copy(wrapAsGenericReadable(new StringReader(ASCII)), builder);
assertEquals(ASCII, builder.toString());
assertEquals(ASCII.length(), copied);
StringBuilder builder2 = new StringBuilder();
copied = CharStreams.copy(wrapAsGenericReadable(new StringReader(I18N)), builder2);
assertEquals(I18N, builder2.toString());
assertEquals(I18N.length(), copied);
}
public void testCopy_toWriter_fromReader() throws IOException {
StringWriter writer = new StringWriter();
long copied = CharStreams.copy(new StringReader(ASCII), writer);
assertEquals(ASCII, writer.toString());
assertEquals(ASCII.length(), copied);
StringWriter writer2 = new StringWriter();
copied = CharStreams.copy(new StringReader(I18N), writer2);
assertEquals(I18N, writer2.toString());
assertEquals(I18N.length(), copied);
}
public void testCopy_toWriter_fromReadable() throws IOException {
StringWriter writer = new StringWriter();
long copied = CharStreams.copy(wrapAsGenericReadable(new StringReader(ASCII)), writer);
assertEquals(ASCII, writer.toString());
assertEquals(ASCII.length(), copied);
StringWriter writer2 = new StringWriter();
copied = CharStreams.copy(wrapAsGenericReadable(new StringReader(I18N)), writer2);
assertEquals(I18N, writer2.toString());
assertEquals(I18N.length(), copied);
}
/**
* Test for Guava issue 1061: http://code.google.com/p/guava-libraries/issues/detail?id=1061
*
* <p>CharStreams.copy was failing to clear its CharBuffer after each read call, which effectively
* reduced the available size of the buffer each time a call to read didn't fill up the available
* space in the buffer completely. In general this is a performance problem since the buffer size
* is permanently reduced, but with certain Reader implementations it could also cause the buffer
* size to reach 0, causing an infinite loop.
*/
public void testCopyWithReaderThatDoesNotFillBuffer() throws IOException {
// need a long enough string for the buffer to hit 0 remaining before the copy completes
String string = Strings.repeat("0123456789", 100);
StringBuilder b = new StringBuilder();
// the main assertion of this test is here... the copy will fail if the buffer size goes down
// each time it is not filled completely
long copied = CharStreams.copy(newNonBufferFillingReader(new StringReader(string)), b);
assertEquals(string, b.toString());
assertEquals(string.length(), copied);
}
public void testExhaust_reader() throws IOException {
Reader reader = new StringReader(ASCII);
assertEquals(ASCII.length(), CharStreams.exhaust(reader));
assertEquals(-1, reader.read());
assertEquals(0, CharStreams.exhaust(reader));
Reader empty = new StringReader("");
assertEquals(0, CharStreams.exhaust(empty));
assertEquals(-1, empty.read());
}
public void testExhaust_readable() throws IOException {
CharBuffer buf = CharBuffer.wrap(ASCII);
assertEquals(ASCII.length(), CharStreams.exhaust(buf));
assertEquals(0, buf.remaining());
assertEquals(0, CharStreams.exhaust(buf));
CharBuffer empty = CharBuffer.wrap("");
assertEquals(0, CharStreams.exhaust(empty));
assertEquals(0, empty.remaining());
}
public void testNullWriter() throws Exception {
// create a null writer
Writer nullWriter = CharStreams.nullWriter();
// write to the writer
nullWriter.write('n');
String test = "Test string for NullWriter";
nullWriter.write(test);
nullWriter.write(test, 2, 10);
nullWriter.append(null);
nullWriter.append(null, 0, 4);
try {
nullWriter.append(null, -1, 4);
fail();
} catch (IndexOutOfBoundsException expected) {
}
try {
nullWriter.append(null, 0, 5);
fail();
} catch (IndexOutOfBoundsException expected) {
}
// nothing really to assert?
assertSame(CharStreams.nullWriter(), CharStreams.nullWriter());
}
/**
* Returns a reader wrapping the given reader that only reads half of the maximum number of
* characters that it could read in read(char[], int, int).
*/
private static Reader newNonBufferFillingReader(Reader reader) {
return new FilterReader(reader) {
@Override
public int read(char[] cbuf, int off, int len) throws IOException {
// if a buffer isn't being cleared correctly, this method will eventually start being called
// with a len of 0 forever
if (len <= 0) {
fail("read called with a len of " + len);
}
// read fewer than the max number of chars to read
// shouldn't be a problem unless the buffer is shrinking each call
return in.read(cbuf, off, Math.max(len - 1024, 0));
}
};
}
/** Wrap an appendable in an appendable to defeat any type specific optimizations. */
private static Appendable wrapAsGenericAppendable(final Appendable a) {
return new Appendable() {
@Override
public Appendable append(CharSequence csq) throws IOException {
a.append(csq);
return this;
}
@Override
public Appendable append(CharSequence csq, int start, int end) throws IOException {
a.append(csq, start, end);
return this;
}
@Override
public Appendable append(char c) throws IOException {
a.append(c);
return this;
}
};
}
/** Wrap a readable in a readable to defeat any type specific optimizations. */
private static Readable wrapAsGenericReadable(final Readable a) {
return new Readable() {
@Override
public int read(CharBuffer cb) throws IOException {
return a.read(cb);
}
};
}
}
|