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 */ 16 package okio; 17 18 import java.io.IOException; 19 import java.io.OutputStream; 20 import org.junit.Test; 21 22 import static okio.TestUtil.repeat; 23 import static org.junit.Assert.assertEquals; 24 import static org.junit.Assert.fail; 25 26 /** 27 * Tests solely for the behavior of RealBufferedSink's implementation. For generic 28 * BufferedSink behavior use BufferedSinkTest. 29 */ 30 public final class RealBufferedSinkTest { 31 @Test public void inputStreamCloses() throws Exception { 32 RealBufferedSink sink = new RealBufferedSink(new Buffer()); 33 OutputStream out = sink.outputStream(); 34 out.close(); 35 try { 36 sink.writeUtf8("Hi!"); 37 fail(); 38 } catch (IllegalStateException e) { 39 assertEquals("closed", e.getMessage()); 40 } 41 } 42 43 @Test public void bufferedSinkEmitsTailWhenItIsComplete() throws IOException { 44 Buffer sink = new Buffer(); 45 BufferedSink bufferedSink = new RealBufferedSink(sink); 46 bufferedSink.writeUtf8(repeat('a', Segment.SIZE - 1)); 47 assertEquals(0, sink.size()); 48 bufferedSink.writeByte(0); 49 assertEquals(Segment.SIZE, sink.size()); 50 assertEquals(0, bufferedSink.buffer().size()); 51 } 52 53 @Test public void bufferedSinkEmitMultipleSegments() throws IOException { 54 Buffer sink = new Buffer(); 55 BufferedSink bufferedSink = new RealBufferedSink(sink); 56 bufferedSink.writeUtf8(repeat('a', Segment.SIZE * 4 - 1)); 57 assertEquals(Segment.SIZE * 3, sink.size()); 58 assertEquals(Segment.SIZE - 1, bufferedSink.buffer().size()); 59 } 60 61 @Test public void bufferedSinkFlush() throws IOException { 62 Buffer sink = new Buffer(); 63 BufferedSink bufferedSink = new RealBufferedSink(sink); 64 bufferedSink.writeByte('a'); 65 assertEquals(0, sink.size()); 66 bufferedSink.flush(); 67 assertEquals(0, bufferedSink.buffer().size()); 68 assertEquals(1, sink.size()); 69 } 70 71 @Test public void bytesEmittedToSinkWithFlush() throws Exception { 72 Buffer sink = new Buffer(); 73 BufferedSink bufferedSink = new RealBufferedSink(sink); 74 bufferedSink.writeUtf8("abc"); 75 bufferedSink.flush(); 76 assertEquals(3, sink.size()); 77 } 78 79 @Test public void bytesNotEmittedToSinkWithoutFlush() throws Exception { 80 Buffer sink = new Buffer(); 81 BufferedSink bufferedSink = new RealBufferedSink(sink); 82 bufferedSink.writeUtf8("abc"); 83 assertEquals(0, sink.size()); 84 } 85 86 @Test public void bytesEmittedToSinkWithEmit() throws Exception { 87 Buffer sink = new Buffer(); 88 BufferedSink bufferedSink = new RealBufferedSink(sink); 89 bufferedSink.writeUtf8("abc"); 90 bufferedSink.emit(); 91 assertEquals(3, sink.size()); 92 } 93 94 @Test public void completeSegmentsEmitted() throws Exception { 95 Buffer sink = new Buffer(); 96 BufferedSink bufferedSink = new RealBufferedSink(sink); 97 bufferedSink.writeUtf8(repeat('a', Segment.SIZE * 3)); 98 assertEquals(Segment.SIZE * 3, sink.size()); 99 } 100 101 @Test public void incompleteSegmentsNotEmitted() throws Exception { 102 Buffer sink = new Buffer(); 103 BufferedSink bufferedSink = new RealBufferedSink(sink); 104 bufferedSink.writeUtf8(repeat('a', Segment.SIZE * 3 - 1)); 105 assertEquals(Segment.SIZE * 2, sink.size()); 106 } 107 108 @Test public void closeWithExceptionWhenWriting() throws IOException { 109 MockSink mockSink = new MockSink(); 110 mockSink.scheduleThrow(0, new IOException()); 111 BufferedSink bufferedSink = new RealBufferedSink(mockSink); 112 bufferedSink.writeByte('a'); 113 try { 114 bufferedSink.close(); 115 fail(); 116 } catch (IOException expected) { 117 } 118 mockSink.assertLog("write(Buffer[size=1 data=61], 1)", "close()"); 119 } 120 121 @Test public void closeWithExceptionWhenClosing() throws IOException { 122 MockSink mockSink = new MockSink(); 123 mockSink.scheduleThrow(1, new IOException()); 124 BufferedSink bufferedSink = new RealBufferedSink(mockSink); 125 bufferedSink.writeByte('a'); 126 try { 127 bufferedSink.close(); 128 fail(); 129 } catch (IOException expected) { 130 } 131 mockSink.assertLog("write(Buffer[size=1 data=61], 1)", "close()"); 132 } 133 134 @Test public void closeWithExceptionWhenWritingAndClosing() throws IOException { 135 MockSink mockSink = new MockSink(); 136 mockSink.scheduleThrow(0, new IOException("first")); 137 mockSink.scheduleThrow(1, new IOException("second")); 138 BufferedSink bufferedSink = new RealBufferedSink(mockSink); 139 bufferedSink.writeByte('a'); 140 try { 141 bufferedSink.close(); 142 fail(); 143 } catch (IOException expected) { 144 assertEquals("first", expected.getMessage()); 145 } 146 mockSink.assertLog("write(Buffer[size=1 data=61], 1)", "close()"); 147 } 148 149 @Test public void operationsAfterClose() throws IOException { 150 MockSink mockSink = new MockSink(); 151 BufferedSink bufferedSink = new RealBufferedSink(mockSink); 152 bufferedSink.writeByte('a'); 153 bufferedSink.close(); 154 155 // Test a sample set of methods. 156 try { 157 bufferedSink.writeByte('a'); 158 fail(); 159 } catch (IllegalStateException expected) { 160 } 161 162 try { 163 bufferedSink.write(new byte[10]); 164 fail(); 165 } catch (IllegalStateException expected) { 166 } 167 168 try { 169 bufferedSink.emitCompleteSegments(); 170 fail(); 171 } catch (IllegalStateException expected) { 172 } 173 174 try { 175 bufferedSink.emit(); 176 fail(); 177 } catch (IllegalStateException expected) { 178 } 179 180 try { 181 bufferedSink.flush(); 182 fail(); 183 } catch (IllegalStateException expected) { 184 } 185 186 // Test a sample set of methods on the OutputStream. 187 OutputStream os = bufferedSink.outputStream(); 188 try { 189 os.write('a'); 190 fail(); 191 } catch (IOException expected) { 192 } 193 194 try { 195 os.write(new byte[10]); 196 fail(); 197 } catch (IOException expected) { 198 } 199 200 // Permitted 201 os.flush(); 202 } 203 204 @Test public void writeAll() throws IOException { 205 MockSink mockSink = new MockSink(); 206 BufferedSink bufferedSink = Okio.buffer(mockSink); 207 208 bufferedSink.buffer().writeUtf8("abc"); 209 assertEquals(3, bufferedSink.writeAll(new Buffer().writeUtf8("def"))); 210 211 assertEquals(6, bufferedSink.buffer().size()); 212 assertEquals("abcdef", bufferedSink.buffer().readUtf8(6)); 213 mockSink.assertLog(); // No writes. 214 } 215 216 @Test public void writeAllExhausted() throws IOException { 217 MockSink mockSink = new MockSink(); 218 BufferedSink bufferedSink = Okio.buffer(mockSink); 219 220 assertEquals(0, bufferedSink.writeAll(new Buffer())); 221 assertEquals(0, bufferedSink.buffer().size()); 222 mockSink.assertLog(); // No writes. 223 } 224 225 @Test public void writeAllWritesOneSegmentAtATime() throws IOException { 226 Buffer write1 = new Buffer().writeUtf8(TestUtil.repeat('a', Segment.SIZE)); 227 Buffer write2 = new Buffer().writeUtf8(TestUtil.repeat('b', Segment.SIZE)); 228 Buffer write3 = new Buffer().writeUtf8(TestUtil.repeat('c', Segment.SIZE)); 229 230 Buffer source = new Buffer().writeUtf8("" 231 + TestUtil.repeat('a', Segment.SIZE) 232 + TestUtil.repeat('b', Segment.SIZE) 233 + TestUtil.repeat('c', Segment.SIZE)); 234 235 MockSink mockSink = new MockSink(); 236 BufferedSink bufferedSink = Okio.buffer(mockSink); 237 assertEquals(Segment.SIZE * 3, bufferedSink.writeAll(source)); 238 239 mockSink.assertLog( 240 "write(" + write1 + ", " + write1.size() + ")", 241 "write(" + write2 + ", " + write2.size() + ")", 242 "write(" + write3 + ", " + write3.size() + ")"); 243 } 244 } 245