1/*
2 * Copyright (C) 2013 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
17package com.google.common.io;
18
19import junit.framework.TestCase;
20
21import java.io.IOException;
22import java.nio.CharBuffer;
23
24/**
25 * Tests for {@link CharSequenceReader}.
26 *
27 * @author Colin Decker
28 */
29public class CharSequenceReaderTest extends TestCase {
30
31  public void testReadEmptyString() throws IOException {
32    assertReadsCorrectly("");
33  }
34
35  public void testReadsStringsCorrectly() throws IOException {
36    assertReadsCorrectly("abc");
37    assertReadsCorrectly("abcde");
38    assertReadsCorrectly("abcdefghijkl");
39    assertReadsCorrectly(""
40        + "abcdefghijklmnopqrstuvwxyz\n"
41        + "ABCDEFGHIJKLMNOPQRSTUVWXYZ\r"
42        + "0123456789\r\n"
43        + "!@#$%^&*()-=_+\t[]{};':\",./<>?\\| ");
44  }
45
46  public void testMarkAndReset() throws IOException {
47    String string = "abcdefghijklmnopqrstuvwxyz";
48    CharSequenceReader reader = new CharSequenceReader(string);
49    assertTrue(reader.markSupported());
50
51    assertEquals(string, readFully(reader));
52    assertFullyRead(reader);
53
54    // reset and read again
55    reader.reset();
56    assertEquals(string, readFully(reader));
57    assertFullyRead(reader);
58
59    // reset, skip, mark, then read the rest
60    reader.reset();
61    assertEquals(5, reader.skip(5));
62    reader.mark(Integer.MAX_VALUE);
63    assertEquals(string.substring(5), readFully(reader));
64    assertFullyRead(reader);
65
66    // reset to the mark and then read the rest
67    reader.reset();
68    assertEquals(string.substring(5), readFully(reader));
69    assertFullyRead(reader);
70  }
71
72  public void testIllegalArguments() throws IOException {
73    CharSequenceReader reader = new CharSequenceReader("12345");
74
75    char[] buf = new char[10];
76    try {
77      reader.read(buf, 0, 11);
78      fail();
79    } catch (IndexOutOfBoundsException expected) {
80    }
81
82    try {
83      reader.read(buf, 10, 1);
84      fail();
85    } catch (IndexOutOfBoundsException expected) {
86    }
87
88    try {
89      reader.read(buf, 11, 0);
90      fail();
91    } catch (IndexOutOfBoundsException expected) {
92    }
93
94    try {
95      reader.read(buf, -1, 5);
96      fail();
97    } catch (IndexOutOfBoundsException expected) {
98    }
99
100    try {
101      reader.read(buf, 5, -1);
102      fail();
103    } catch (IndexOutOfBoundsException expected) {
104    }
105
106    try {
107      reader.read(buf, 0, 11);
108      fail();
109    } catch (IndexOutOfBoundsException expected) {
110    }
111
112    try {
113      reader.skip(-1);
114      fail();
115    } catch (IllegalArgumentException expected) {
116    }
117
118    try {
119      reader.mark(-1);
120      fail();
121    } catch (IllegalArgumentException expected) {
122    }
123  }
124
125  public void testMethodsThrowWhenClosed() throws IOException {
126    CharSequenceReader reader = new CharSequenceReader("");
127    reader.close();
128
129    try {
130      reader.read();
131      fail();
132    } catch (IOException expected) {
133    }
134
135    try {
136      reader.read(new char[10]);
137      fail();
138    } catch (IOException expected) {
139    }
140
141    try {
142      reader.read(new char[10], 0, 10);
143      fail();
144    } catch (IOException expected) {
145    }
146
147    try {
148      reader.read(CharBuffer.allocate(10));
149      fail();
150    } catch (IOException expected) {
151    }
152
153    try {
154      reader.skip(10);
155      fail();
156    } catch (IOException expected) {
157    }
158
159    try {
160      reader.ready();
161      fail();
162    } catch (IOException expected) {
163    }
164
165    try {
166      reader.mark(10);
167      fail();
168    } catch (IOException expected) {
169    }
170
171    try {
172      reader.reset();
173      fail();
174    } catch (IOException expected) {
175    }
176  }
177
178  /**
179   * Creates a CharSequenceReader wrapping the given CharSequence and tests that the reader produces
180   * the same sequence when read using each type of read method it provides.
181   */
182  private static void assertReadsCorrectly(CharSequence charSequence) throws IOException {
183    String expected = charSequence.toString();
184
185    // read char by char
186    CharSequenceReader reader = new CharSequenceReader(charSequence);
187    for (int i = 0; i < expected.length(); i++) {
188      assertEquals(expected.charAt(i), reader.read());
189    }
190    assertFullyRead(reader);
191
192    // read all to one array
193    reader = new CharSequenceReader(charSequence);
194    char[] buf = new char[expected.length()];
195    assertEquals(expected.length() == 0 ? -1 : expected.length(), reader.read(buf));
196    assertEquals(expected, new String(buf));
197    assertFullyRead(reader);
198
199    // read in chunks to fixed array
200    reader = new CharSequenceReader(charSequence);
201    buf = new char[5];
202    StringBuilder builder = new StringBuilder();
203    int read;
204    while ((read = reader.read(buf, 0, buf.length)) != -1) {
205      builder.append(buf, 0, read);
206    }
207    assertEquals(expected, builder.toString());
208    assertFullyRead(reader);
209
210    // read all to one CharBuffer
211    reader = new CharSequenceReader(charSequence);
212    CharBuffer buf2 = CharBuffer.allocate(expected.length());
213    assertEquals(expected.length() == 0 ? -1 : expected.length(), reader.read(buf2));
214    buf2.flip();
215    assertEquals(expected, buf2.toString());
216    assertFullyRead(reader);
217
218    // read in chunks to fixed CharBuffer
219    reader = new CharSequenceReader(charSequence);
220    buf2 = CharBuffer.allocate(5);
221    builder = new StringBuilder();
222    while (reader.read(buf2) != -1) {
223      buf2.flip();
224      builder.append(buf2);
225      buf2.clear();
226    }
227    assertEquals(expected, builder.toString());
228    assertFullyRead(reader);
229
230    // skip fully
231    reader = new CharSequenceReader(charSequence);
232    assertEquals(expected.length(), reader.skip(Long.MAX_VALUE));
233    assertFullyRead(reader);
234
235    // skip 5 and read the rest
236    if (expected.length() > 5) {
237      reader = new CharSequenceReader(charSequence);
238      assertEquals(5, reader.skip(5));
239
240      buf = new char[expected.length() - 5];
241      assertEquals(buf.length, reader.read(buf, 0, buf.length));
242      assertEquals(expected.substring(5), new String(buf));
243      assertFullyRead(reader);
244    }
245  }
246
247  private static void assertFullyRead(CharSequenceReader reader) throws IOException {
248    assertEquals(-1, reader.read());
249    assertEquals(-1, reader.read(new char[10], 0, 10));
250    assertEquals(-1, reader.read(CharBuffer.allocate(10)));
251    assertEquals(0, reader.skip(10));
252  }
253
254  private static String readFully(CharSequenceReader reader) throws IOException {
255    StringBuilder builder = new StringBuilder();
256    int read;
257    while ((read = reader.read()) != -1) {
258      builder.append((char) read);
259    }
260    return builder.toString();
261  }
262}
263