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 org.junit.Test; 22 23import static okio.TestUtil.repeat; 24import static okio.Util.UTF_8; 25import static org.junit.Assert.assertEquals; 26import static org.junit.Assert.fail; 27 28/** 29 * Tests solely for the behavior of RealBufferedSource's implementation. For generic 30 * BufferedSource behavior use BufferedSourceTest. 31 */ 32public final class RealBufferedSourceTest { 33 @Test public void inputStreamTracksSegments() throws Exception { 34 Buffer source = new Buffer(); 35 source.writeUtf8("a"); 36 source.writeUtf8(repeat('b', Segment.SIZE)); 37 source.writeUtf8("c"); 38 39 InputStream in = new RealBufferedSource(source).inputStream(); 40 assertEquals(0, in.available()); 41 assertEquals(Segment.SIZE + 2, source.size()); 42 43 // Reading one byte buffers a full segment. 44 assertEquals('a', in.read()); 45 assertEquals(Segment.SIZE - 1, in.available()); 46 assertEquals(2, source.size()); 47 48 // Reading as much as possible reads the rest of that buffered segment. 49 byte[] data = new byte[Segment.SIZE * 2]; 50 assertEquals(Segment.SIZE - 1, in.read(data, 0, data.length)); 51 assertEquals(repeat('b', Segment.SIZE - 1), new String(data, 0, Segment.SIZE - 1, UTF_8)); 52 assertEquals(2, source.size()); 53 54 // Continuing to read buffers the next segment. 55 assertEquals('b', in.read()); 56 assertEquals(1, in.available()); 57 assertEquals(0, source.size()); 58 59 // Continuing to read reads from the buffer. 60 assertEquals('c', in.read()); 61 assertEquals(0, in.available()); 62 assertEquals(0, source.size()); 63 64 // Once we've exhausted the source, we're done. 65 assertEquals(-1, in.read()); 66 assertEquals(0, source.size()); 67 } 68 69 @Test public void inputStreamCloses() throws Exception { 70 RealBufferedSource source = new RealBufferedSource(new Buffer()); 71 InputStream in = source.inputStream(); 72 in.close(); 73 try { 74 source.require(1); 75 fail(); 76 } catch (IllegalStateException e) { 77 assertEquals("closed", e.getMessage()); 78 } 79 } 80 81 @Test public void requireTracksBufferFirst() throws Exception { 82 Buffer source = new Buffer(); 83 source.writeUtf8("bb"); 84 85 BufferedSource bufferedSource = new RealBufferedSource(source); 86 bufferedSource.buffer().writeUtf8("aa"); 87 88 bufferedSource.require(2); 89 assertEquals(2, bufferedSource.buffer().size()); 90 assertEquals(2, source.size()); 91 } 92 93 @Test public void requireIncludesBufferBytes() throws Exception { 94 Buffer source = new Buffer(); 95 source.writeUtf8("b"); 96 97 BufferedSource bufferedSource = new RealBufferedSource(source); 98 bufferedSource.buffer().writeUtf8("a"); 99 100 bufferedSource.require(2); 101 assertEquals("ab", bufferedSource.buffer().readUtf8(2)); 102 } 103 104 @Test public void requireInsufficientData() throws Exception { 105 Buffer source = new Buffer(); 106 source.writeUtf8("a"); 107 108 BufferedSource bufferedSource = new RealBufferedSource(source); 109 110 try { 111 bufferedSource.require(2); 112 fail(); 113 } catch (EOFException expected) { 114 } 115 } 116 117 @Test public void requireReadsOneSegmentAtATime() throws Exception { 118 Buffer source = new Buffer(); 119 source.writeUtf8(repeat('a', Segment.SIZE)); 120 source.writeUtf8(repeat('b', Segment.SIZE)); 121 122 BufferedSource bufferedSource = new RealBufferedSource(source); 123 124 bufferedSource.require(2); 125 assertEquals(Segment.SIZE, source.size()); 126 assertEquals(Segment.SIZE, bufferedSource.buffer().size()); 127 } 128 129 @Test public void skipReadsOneSegmentAtATime() throws Exception { 130 Buffer source = new Buffer(); 131 source.writeUtf8(repeat('a', Segment.SIZE)); 132 source.writeUtf8(repeat('b', Segment.SIZE)); 133 BufferedSource bufferedSource = new RealBufferedSource(source); 134 bufferedSource.skip(2); 135 assertEquals(Segment.SIZE, source.size()); 136 assertEquals(Segment.SIZE - 2, bufferedSource.buffer().size()); 137 } 138 139 @Test public void skipTracksBufferFirst() throws Exception { 140 Buffer source = new Buffer(); 141 source.writeUtf8("bb"); 142 143 BufferedSource bufferedSource = new RealBufferedSource(source); 144 bufferedSource.buffer().writeUtf8("aa"); 145 146 bufferedSource.skip(2); 147 assertEquals(0, bufferedSource.buffer().size()); 148 assertEquals(2, source.size()); 149 } 150 151 @Test public void operationsAfterClose() throws IOException { 152 Buffer source = new Buffer(); 153 BufferedSource bufferedSource = new RealBufferedSource(source); 154 bufferedSource.close(); 155 156 // Test a sample set of methods. 157 try { 158 bufferedSource.indexOf((byte) 1); 159 fail(); 160 } catch (IllegalStateException expected) { 161 } 162 163 try { 164 bufferedSource.skip(1); 165 fail(); 166 } catch (IllegalStateException expected) { 167 } 168 169 try { 170 bufferedSource.readByte(); 171 fail(); 172 } catch (IllegalStateException expected) { 173 } 174 175 try { 176 bufferedSource.readByteString(10); 177 fail(); 178 } catch (IllegalStateException expected) { 179 } 180 181 // Test a sample set of methods on the InputStream. 182 InputStream is = bufferedSource.inputStream(); 183 try { 184 is.read(); 185 fail(); 186 } catch (IOException expected) { 187 } 188 189 try { 190 is.read(new byte[10]); 191 fail(); 192 } catch (IOException expected) { 193 } 194 } 195 196 /** 197 * We don't want readAll to buffer an unbounded amount of data. Instead it 198 * should buffer a segment, write it, and repeat. 199 */ 200 @Test public void readAllReadsOneSegmentAtATime() throws IOException { 201 Buffer write1 = new Buffer().writeUtf8(TestUtil.repeat('a', Segment.SIZE)); 202 Buffer write2 = new Buffer().writeUtf8(TestUtil.repeat('b', Segment.SIZE)); 203 Buffer write3 = new Buffer().writeUtf8(TestUtil.repeat('c', Segment.SIZE)); 204 205 Buffer source = new Buffer().writeUtf8("" 206 + TestUtil.repeat('a', Segment.SIZE) 207 + TestUtil.repeat('b', Segment.SIZE) 208 + TestUtil.repeat('c', Segment.SIZE)); 209 210 MockSink mockSink = new MockSink(); 211 BufferedSource bufferedSource = Okio.buffer((Source) source); 212 assertEquals(Segment.SIZE * 3, bufferedSource.readAll(mockSink)); 213 mockSink.assertLog( 214 "write(" + write1 + ", " + write1.size() + ")", 215 "write(" + write2 + ", " + write2.size() + ")", 216 "write(" + write3 + ", " + write3.size() + ")"); 217 } 218} 219