1/*
2 * Copyright (C) 2014 Square, Inc.
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 */
16package okio;
17
18import java.io.EOFException;
19import java.io.IOException;
20import java.io.InputStream;
21import java.util.Arrays;
22import org.junit.Test;
23
24import static okio.Util.UTF_8;
25import static org.junit.Assert.assertEquals;
26import static org.junit.Assert.fail;
27
28public final class RealBufferedSourceTest {
29  @Test public void inputStreamFromSource() throws Exception {
30    OkBuffer source = new OkBuffer();
31    source.writeUtf8("a");
32    source.writeUtf8(repeat('b', Segment.SIZE));
33    source.writeUtf8("c");
34
35    InputStream in = new RealBufferedSource(source).inputStream();
36    assertEquals(0, in.available());
37    assertEquals(Segment.SIZE + 2, source.size());
38
39    // Reading one byte buffers a full segment.
40    assertEquals('a', in.read());
41    assertEquals(Segment.SIZE - 1, in.available());
42    assertEquals(2, source.size());
43
44    // Reading as much as possible reads the rest of that buffered segment.
45    byte[] data = new byte[Segment.SIZE * 2];
46    assertEquals(Segment.SIZE - 1, in.read(data, 0, data.length));
47    assertEquals(repeat('b', Segment.SIZE - 1), new String(data, 0, Segment.SIZE - 1, UTF_8));
48    assertEquals(2, source.size());
49
50    // Continuing to read buffers the next segment.
51    assertEquals('b', in.read());
52    assertEquals(1, in.available());
53    assertEquals(0, source.size());
54
55    // Continuing to read reads from the buffer.
56    assertEquals('c', in.read());
57    assertEquals(0, in.available());
58    assertEquals(0, source.size());
59
60    // Once we've exhausted the source, we're done.
61    assertEquals(-1, in.read());
62    assertEquals(0, source.size());
63  }
64
65  @Test public void inputStreamFromSourceBounds() throws IOException {
66    OkBuffer source = new OkBuffer();
67    source.writeUtf8(repeat('a', 100));
68    InputStream in = new RealBufferedSource(source).inputStream();
69    try {
70      in.read(new byte[100], 50, 51);
71      fail();
72    } catch (ArrayIndexOutOfBoundsException expected) {
73    }
74  }
75
76  @Test public void requireTracksBufferFirst() throws Exception {
77    OkBuffer source = new OkBuffer();
78    source.writeUtf8("bb");
79
80    BufferedSource bufferedSource = new RealBufferedSource(source);
81    bufferedSource.buffer().writeUtf8("aa");
82
83    bufferedSource.require(2);
84    assertEquals(2, bufferedSource.buffer().size());
85    assertEquals(2, source.size());
86  }
87
88  @Test public void requireIncludesBufferBytes() throws Exception {
89    OkBuffer source = new OkBuffer();
90    source.writeUtf8("b");
91
92    BufferedSource bufferedSource = new RealBufferedSource(source);
93    bufferedSource.buffer().writeUtf8("a");
94
95    bufferedSource.require(2);
96    assertEquals("ab", bufferedSource.buffer().readUtf8(2));
97  }
98
99  @Test public void requireInsufficientData() throws Exception {
100    OkBuffer source = new OkBuffer();
101    source.writeUtf8("a");
102
103    BufferedSource bufferedSource = new RealBufferedSource(source);
104
105    try {
106      bufferedSource.require(2);
107      fail();
108    } catch (EOFException expected) {
109    }
110  }
111
112  @Test public void requireReadsOneSegmentAtATime() throws Exception {
113    OkBuffer source = new OkBuffer();
114    source.writeUtf8(repeat('a', Segment.SIZE));
115    source.writeUtf8(repeat('b', Segment.SIZE));
116
117    BufferedSource bufferedSource = new RealBufferedSource(source);
118
119    bufferedSource.require(2);
120    assertEquals(Segment.SIZE, source.size());
121    assertEquals(Segment.SIZE, bufferedSource.buffer().size());
122  }
123
124  @Test public void skipInsufficientData() throws Exception {
125    OkBuffer source = new OkBuffer();
126    source.writeUtf8("a");
127
128    BufferedSource bufferedSource = new RealBufferedSource(source);
129    try {
130      bufferedSource.skip(2);
131      fail();
132    } catch (EOFException expected) {
133    }
134  }
135
136  @Test public void skipReadsOneSegmentAtATime() throws Exception {
137    OkBuffer source = new OkBuffer();
138    source.writeUtf8(repeat('a', Segment.SIZE));
139    source.writeUtf8(repeat('b', Segment.SIZE));
140    BufferedSource bufferedSource = new RealBufferedSource(source);
141    bufferedSource.skip(2);
142    assertEquals(Segment.SIZE, source.size());
143    assertEquals(Segment.SIZE - 2, bufferedSource.buffer().size());
144  }
145
146  @Test public void skipTracksBufferFirst() throws Exception {
147    OkBuffer source = new OkBuffer();
148    source.writeUtf8("bb");
149
150    BufferedSource bufferedSource = new RealBufferedSource(source);
151    bufferedSource.buffer().writeUtf8("aa");
152
153    bufferedSource.skip(2);
154    assertEquals(0, bufferedSource.buffer().size());
155    assertEquals(2, source.size());
156  }
157
158  @Test public void operationsAfterClose() throws IOException {
159    OkBuffer source = new OkBuffer();
160    BufferedSource bufferedSource = new RealBufferedSource(source);
161    bufferedSource.close();
162
163    // Test a sample set of methods.
164    try {
165      bufferedSource.indexOf((byte) 1);
166      fail();
167    } catch (IllegalStateException expected) {
168    }
169
170    try {
171      bufferedSource.skip(1);
172      fail();
173    } catch (IllegalStateException expected) {
174    }
175
176    try {
177      bufferedSource.readByte();
178      fail();
179    } catch (IllegalStateException expected) {
180    }
181
182    try {
183      bufferedSource.readByteString(10);
184      fail();
185    } catch (IllegalStateException expected) {
186    }
187
188    // Test a sample set of methods on the InputStream.
189    InputStream is = bufferedSource.inputStream();
190    try {
191      is.read();
192      fail();
193    } catch (IOException expected) {
194    }
195
196    try {
197      is.read(new byte[10]);
198      fail();
199    } catch (IOException expected) {
200    }
201  }
202
203  private String repeat(char c, int count) {
204    char[] array = new char[count];
205    Arrays.fill(array, c);
206    return new String(array);
207  }
208}
209