1a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller/*
2a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller * Copyright (C) 2014 Square, Inc.
3a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller *
4a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller * Licensed under the Apache License, Version 2.0 (the "License");
5a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller * you may not use this file except in compliance with the License.
6a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller * You may obtain a copy of the License at
7a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller *
8a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller *      http://www.apache.org/licenses/LICENSE-2.0
9a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller *
10a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller * Unless required by applicable law or agreed to in writing, software
11a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller * distributed under the License is distributed on an "AS IS" BASIS,
12a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller * See the License for the specific language governing permissions and
14a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller * limitations under the License.
15a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller */
16e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerpackage okio;
17e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
18a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fullerimport java.io.EOFException;
19e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.io.IOException;
20e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.io.OutputStream;
21a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fullerimport java.math.BigInteger;
22e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.nio.charset.Charset;
23e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.util.Arrays;
24e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.util.List;
25e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport org.junit.Before;
26e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport org.junit.Test;
27e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport org.junit.runner.RunWith;
28e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport org.junit.runners.Parameterized;
29e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
30e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport static java.util.Arrays.asList;
31e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport static okio.TestUtil.repeat;
32e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport static okio.Util.UTF_8;
33e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport static org.junit.Assert.assertEquals;
34e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport static org.junit.Assert.fail;
35e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
36e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller@RunWith(Parameterized.class)
37e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerpublic class BufferedSinkTest {
38e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  private interface Factory {
39e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    BufferedSink create(Buffer data);
40e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
41e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
42e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  // ANDROID-BEGIN
43e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  //  @Parameterized.Parameters(name = "{0}")
44e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  // ANDROID-END
45e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  public static List<Object[]> parameters() {
46e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    return Arrays.asList(new Object[] {
47e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        new Factory() {
48e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller          @Override public BufferedSink create(Buffer data) {
49e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller            return data;
50e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller          }
51e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
52e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller          @Override public String toString() {
53e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller            return "Buffer";
54e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller          }
55e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        }
56e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    }, new Object[] {
57e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        new Factory() {
58e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller          @Override public BufferedSink create(Buffer data) {
59e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller            return new RealBufferedSink(data);
60e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller          }
61e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
62e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller          @Override public String toString() {
63e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller            return "RealBufferedSink";
64e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller          }
65e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        }
66e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    });
67e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
68e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
69e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  // ANDROID-BEGIN
70e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  //  @Parameterized.Parameter
71e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  public Factory factory = (Factory) (parameters().get(0))[0];
72e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  // ANDROID-END
73e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
74e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  private Buffer data;
75e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  private BufferedSink sink;
76e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
77e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Before public void setUp() {
78e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    data = new Buffer();
79e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink = factory.create(data);
80e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
81e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
82e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Test public void writeNothing() throws IOException {
83e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.writeUtf8("");
84e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.flush();
85e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertEquals(0, data.size());
86e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
87e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
88e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Test public void writeBytes() throws Exception {
89e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.writeByte(0xab);
90e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.writeByte(0xcd);
91e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.flush();
92e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertEquals("Buffer[size=2 data=abcd]", data.toString());
93e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
94e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
95e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Test public void writeLastByteInSegment() throws Exception {
96e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.writeUtf8(repeat('a', Segment.SIZE - 1));
97e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.writeByte(0x20);
98e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.writeByte(0x21);
99e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.flush();
100e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertEquals(asList(Segment.SIZE, 1), data.segmentSizes());
101e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertEquals(repeat('a', Segment.SIZE - 1), data.readUtf8(Segment.SIZE - 1));
102e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertEquals("Buffer[size=2 data=2021]", data.toString());
103e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
104e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
105e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Test public void writeShort() throws Exception {
106e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.writeShort(0xabcd);
107e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.writeShort(0x4321);
108e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.flush();
109e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertEquals("Buffer[size=4 data=abcd4321]", data.toString());
110e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
111e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
112e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Test public void writeShortLe() throws Exception {
113e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.writeShortLe(0xabcd);
114e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.writeShortLe(0x4321);
115e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.flush();
116e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertEquals("Buffer[size=4 data=cdab2143]", data.toString());
117e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
118e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
119e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Test public void writeInt() throws Exception {
120e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.writeInt(0xabcdef01);
121e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.writeInt(0x87654321);
122e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.flush();
123e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertEquals("Buffer[size=8 data=abcdef0187654321]", data.toString());
124e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
125e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
126e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Test public void writeLastIntegerInSegment() throws Exception {
127e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.writeUtf8(repeat('a', Segment.SIZE - 4));
128e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.writeInt(0xabcdef01);
129e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.writeInt(0x87654321);
130e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.flush();
131e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertEquals(asList(Segment.SIZE, 4), data.segmentSizes());
132e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertEquals(repeat('a', Segment.SIZE - 4), data.readUtf8(Segment.SIZE - 4));
133e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertEquals("Buffer[size=8 data=abcdef0187654321]", data.toString());
134e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
135e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
136e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Test public void writeIntegerDoesNotQuiteFitInSegment() throws Exception {
137e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.writeUtf8(repeat('a', Segment.SIZE - 3));
138e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.writeInt(0xabcdef01);
139e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.writeInt(0x87654321);
140e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.flush();
141e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertEquals(asList(Segment.SIZE - 3, 8), data.segmentSizes());
142e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertEquals(repeat('a', Segment.SIZE - 3), data.readUtf8(Segment.SIZE - 3));
143e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertEquals("Buffer[size=8 data=abcdef0187654321]", data.toString());
144e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
145e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
146e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Test public void writeIntLe() throws Exception {
147e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.writeIntLe(0xabcdef01);
148e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.writeIntLe(0x87654321);
149e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.flush();
150e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertEquals("Buffer[size=8 data=01efcdab21436587]", data.toString());
151e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
152e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
153e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Test public void writeLong() throws Exception {
154e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.writeLong(0xabcdef0187654321L);
155e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.writeLong(0xcafebabeb0b15c00L);
156e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.flush();
157e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertEquals("Buffer[size=16 data=abcdef0187654321cafebabeb0b15c00]", data.toString());
158e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
159e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
160e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Test public void writeLongLe() throws Exception {
161e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.writeLongLe(0xabcdef0187654321L);
162e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.writeLongLe(0xcafebabeb0b15c00L);
163e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.flush();
164e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertEquals("Buffer[size=16 data=2143658701efcdab005cb1b0bebafeca]", data.toString());
165e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
166e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
167a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller  @Test public void writeStringUtf8() throws IOException {
168a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    sink.writeUtf8("təˈranəˌsôr");
169a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    sink.flush();
170a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    assertEquals(ByteString.decodeHex("74c999cb8872616ec999cb8c73c3b472"), data.readByteString());
171a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller  }
172a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller
173a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller  @Test public void writeSubstringUtf8() throws IOException {
174a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    sink.writeUtf8("təˈranəˌsôr", 3, 7);
175a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    sink.flush();
176a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    assertEquals(ByteString.decodeHex("72616ec999"), data.readByteString());
177a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller  }
178a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller
179a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller  @Test public void writeStringWithCharset() throws IOException {
180e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.writeString("təˈranəˌsôr", Charset.forName("utf-32be"));
181e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.flush();
182e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertEquals(ByteString.decodeHex("0000007400000259000002c800000072000000610000006e00000259"
183e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        + "000002cc00000073000000f400000072"), data.readByteString());
184e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
185e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
186a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller  @Test public void writeSubstringWithCharset() throws IOException {
187a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    sink.writeString("təˈranəˌsôr", 3, 7, Charset.forName("utf-32be"));
188a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    sink.flush();
189a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    assertEquals(ByteString.decodeHex("00000072000000610000006e00000259"), data.readByteString());
190a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller  }
191a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller
192e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Test public void writeAll() throws Exception {
193e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    Buffer source = new Buffer().writeUtf8("abcdef");
194e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
195e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertEquals(6, sink.writeAll(source));
196e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertEquals(0, source.size());
197e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.flush();
198e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertEquals("abcdef", data.readUtf8());
199e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
200e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
201e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Test public void writeSource() throws Exception {
202e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    Buffer source = new Buffer().writeUtf8("abcdef");
203e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
204e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    // Force resolution of the Source method overload.
205e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.write((Source) source, 4);
206e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.flush();
207e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertEquals("abcd", data.readUtf8());
208e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertEquals("ef", source.readUtf8());
209e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
210e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
211a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller  @Test public void writeSourceReadsFully() throws Exception {
212a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    Source source = new ForwardingSource(new Buffer()) {
213a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller      @Override public long read(Buffer sink, long byteCount) throws IOException {
214a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller        sink.writeUtf8("abcd");
215a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller        return 4;
216a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller      }
217a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    };
218a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller
219a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    sink.write(source, 8);
220a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    sink.flush();
221a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    assertEquals("abcdabcd", data.readUtf8());
222a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller  }
223a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller
224a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller  @Test public void writeSourcePropagatesEof() throws IOException {
225a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    Source source = new Buffer().writeUtf8("abcd");
226a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller
227a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    try {
228a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller      sink.write(source, 8);
229a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller      fail();
230a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    } catch (EOFException expected) {
231a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    }
232a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller
233a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    // Ensure that whatever was available was correctly written.
234a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    sink.flush();
235a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    assertEquals("abcd", data.readUtf8());
236a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller  }
237a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller
238e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Test public void writeSourceWithZeroIsNoOp() throws IOException {
239e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    // This test ensures that a zero byte count never calls through to read the source. It may be
240e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    // tied to something like a socket which will potentially block trying to read a segment when
241e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    // ultimately we don't want any data.
242e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    Source source = new ForwardingSource(new Buffer()) {
243e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      @Override public long read(Buffer sink, long byteCount) throws IOException {
244e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        throw new AssertionError();
245e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      }
246e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    };
247e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.write(source, 0);
248e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertEquals(0, data.size());
249e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
250e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
251e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Test public void writeAllExhausted() throws Exception {
252e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    Buffer source = new Buffer();
253e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertEquals(0, sink.writeAll(source));
254e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertEquals(0, source.size());
255e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
256e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
257e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Test public void closeEmitsBufferedBytes() throws IOException {
258e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.writeByte('a');
259e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    sink.close();
260e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertEquals('a', data.readByte());
261e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
262e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
263e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Test public void outputStream() throws Exception {
264e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    OutputStream out = sink.outputStream();
265e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    out.write('a');
266e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    out.write(repeat('b', 9998).getBytes(UTF_8));
267e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    out.write('c');
268e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    out.flush();
269e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertEquals("a" + repeat('b', 9998) + "c", data.readUtf8());
270e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
271e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
272e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Test public void outputStreamBounds() throws Exception {
273e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    OutputStream out = sink.outputStream();
274e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    try {
275e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      out.write(new byte[100], 50, 51);
276e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      fail();
277e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    } catch (ArrayIndexOutOfBoundsException expected) {
278e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    }
279e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
280a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller
281a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller  @Test public void longDecimalString() throws IOException {
282a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    assertLongDecimalString(0);
283a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    assertLongDecimalString(Long.MIN_VALUE);
284a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    assertLongDecimalString(Long.MAX_VALUE);
285a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller
286a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    for (int i = 1; i < 20; i++) {
287a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller      long value = BigInteger.valueOf(10L).pow(i).longValue();
288a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller      assertLongDecimalString(value - 1);
289a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller      assertLongDecimalString(value);
290a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    }
291a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller  }
292a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller
293a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller  private void assertLongDecimalString(long value) throws IOException {
294a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    sink.writeDecimalLong(value).writeUtf8("zzz").flush();
295a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    String expected = Long.toString(value) + "zzz";
296a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    String actual = data.readUtf8();
297a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    assertEquals(value + " expected " + expected + " but was " + actual, actual, expected);
298a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller  }
299a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller
300a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller  @Test public void longHexString() throws IOException {
301a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    assertLongHexString(0);
302a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    assertLongHexString(Long.MIN_VALUE);
303a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    assertLongHexString(Long.MAX_VALUE);
304a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller
305a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    for (int i = 0; i < 16; i++) {
306a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller      assertLongHexString((1 << i) - 1);
307a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller      assertLongHexString(1 << i);
308a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    }
309a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller  }
310a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller
311a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller  private void assertLongHexString(long value) throws IOException {
312a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    sink.writeHexadecimalUnsignedLong(value).writeUtf8("zzz").flush();
313a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    String expected = String.format("%x", value) + "zzz";
314a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    String actual = data.readUtf8();
315a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller    assertEquals(value + " expected " + expected + " but was " + actual, actual, expected);
316a2cab72aa5ff730ba2ae987b45398faafffeb505Neil Fuller  }
317e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller}
318