1e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller/*
2e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * Copyright (C) 2014 Square, Inc.
3e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller *
4e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * Licensed under the Apache License, Version 2.0 (the "License");
5e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * you may not use this file except in compliance with the License.
6e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * You may obtain a copy of the License at
7e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller *
8e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller *      http://www.apache.org/licenses/LICENSE-2.0
9e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller *
10e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * Unless required by applicable law or agreed to in writing, software
11e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * distributed under the License is distributed on an "AS IS" BASIS,
12e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * See the License for the specific language governing permissions and
14e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * limitations under the License.
15e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller */
16e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerpackage okio;
17e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
18e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.io.IOException;
19e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.io.InterruptedIOException;
20e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.util.Arrays;
21e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.util.List;
22e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.util.concurrent.CopyOnWriteArrayList;
23e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport java.util.concurrent.TimeUnit;
24e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport org.junit.Before;
25e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport org.junit.Test;
26e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
27e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport static org.junit.Assert.assertEquals;
28e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport static org.junit.Assert.assertFalse;
29e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport static org.junit.Assert.assertTrue;
30e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerimport static org.junit.Assert.fail;
31e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
32e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller/**
33e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * This test uses four timeouts of varying durations: 250ms, 500ms, 750ms and
34e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller * 1000ms, named 'a', 'b', 'c' and 'd'.
35e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller */
36e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fullerpublic class AsyncTimeoutTest {
37e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  private final List<Timeout> timedOut = new CopyOnWriteArrayList<Timeout>();
38e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  private final AsyncTimeout a = new RecordingAsyncTimeout();
39e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  private final AsyncTimeout b = new RecordingAsyncTimeout();
40e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  private final AsyncTimeout c = new RecordingAsyncTimeout();
41e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  private final AsyncTimeout d = new RecordingAsyncTimeout();
42e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
43e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Before public void setUp() throws Exception {
44e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    a.timeout( 250, TimeUnit.MILLISECONDS);
45e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    b.timeout( 500, TimeUnit.MILLISECONDS);
46e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    c.timeout( 750, TimeUnit.MILLISECONDS);
47e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    d.timeout(1000, TimeUnit.MILLISECONDS);
48e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
49e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
50e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Test public void zeroTimeoutIsNoTimeout() throws Exception {
51e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    AsyncTimeout timeout = new RecordingAsyncTimeout();
52e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    timeout.timeout(0, TimeUnit.MILLISECONDS);
53e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    timeout.enter();
54e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    Thread.sleep(250);
55e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertFalse(timeout.exit());
56e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertTimedOut();
57e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
58e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
59e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Test public void singleInstanceTimedOut() throws Exception {
60e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    a.enter();
61e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    Thread.sleep(500);
62e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertTrue(a.exit());
63e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertTimedOut(a);
64e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
65e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
66e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Test public void singleInstanceNotTimedOut() throws Exception {
67e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    b.enter();
68e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    Thread.sleep(250);
69e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    b.exit();
70e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertFalse(b.exit());
71e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertTimedOut();
72e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
73e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
74e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Test public void instancesAddedAtEnd() throws Exception {
75e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    a.enter();
76e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    b.enter();
77e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    c.enter();
78e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    d.enter();
79e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    Thread.sleep(1250);
80e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertTrue(a.exit());
81e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertTrue(b.exit());
82e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertTrue(c.exit());
83e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertTrue(d.exit());
84e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertTimedOut(a, b, c, d);
85e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
86e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
87e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Test public void instancesAddedAtFront() throws Exception {
88e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    d.enter();
89e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    c.enter();
90e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    b.enter();
91e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    a.enter();
92e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    Thread.sleep(1250);
93e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertTrue(d.exit());
94e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertTrue(c.exit());
95e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertTrue(b.exit());
96e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertTrue(a.exit());
97e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertTimedOut(a, b, c, d);
98e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
99e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
100e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Test public void instancesRemovedAtFront() throws Exception {
101e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    a.enter();
102e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    b.enter();
103e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    c.enter();
104e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    d.enter();
105e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertFalse(a.exit());
106e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertFalse(b.exit());
107e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertFalse(c.exit());
108e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertFalse(d.exit());
109e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertTimedOut();
110e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
111e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
112e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Test public void instancesRemovedAtEnd() throws Exception {
113e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    a.enter();
114e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    b.enter();
115e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    c.enter();
116e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    d.enter();
117e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertFalse(d.exit());
118e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertFalse(c.exit());
119e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertFalse(b.exit());
120e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertFalse(a.exit());
121e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertTimedOut();
122e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
123e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
124e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  /** Detecting double-enters is not guaranteed. */
125e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Test public void doubleEnter() throws Exception {
126e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    a.enter();
127e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    try {
128e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      a.enter();
129e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      fail();
130e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    } catch (IllegalStateException expected) {
131e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    }
132e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
133e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
134e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Test public void deadlineOnly() throws Exception {
135e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    RecordingAsyncTimeout timeout = new RecordingAsyncTimeout();
136e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    timeout.deadline(250, TimeUnit.MILLISECONDS);
137e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    timeout.enter();
138e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    Thread.sleep(500);
139e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertTrue(timeout.exit());
140e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertTimedOut(timeout);
141e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
142e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
143e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Test public void deadlineBeforeTimeout() throws Exception {
144e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    RecordingAsyncTimeout timeout = new RecordingAsyncTimeout();
145e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    timeout.deadline(250, TimeUnit.MILLISECONDS);
146e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    timeout.timeout(750, TimeUnit.MILLISECONDS);
147e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    timeout.enter();
148e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    Thread.sleep(500);
149e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertTrue(timeout.exit());
150e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertTimedOut(timeout);
151e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
152e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
153e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Test public void deadlineAfterTimeout() throws Exception {
154e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    RecordingAsyncTimeout timeout = new RecordingAsyncTimeout();
155e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    timeout.timeout(250, TimeUnit.MILLISECONDS);
156e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    timeout.deadline(750, TimeUnit.MILLISECONDS);
157e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    timeout.enter();
158e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    Thread.sleep(500);
159e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertTrue(timeout.exit());
160e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertTimedOut(timeout);
161e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
162e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
163e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Test public void deadlineStartsBeforeEnter() throws Exception {
164e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    RecordingAsyncTimeout timeout = new RecordingAsyncTimeout();
165e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    timeout.deadline(500, TimeUnit.MILLISECONDS);
166e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    Thread.sleep(500);
167e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    timeout.enter();
168e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    Thread.sleep(250);
169e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertTrue(timeout.exit());
170e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertTimedOut(timeout);
171e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
172e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
173e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Test public void deadlineInThePast() throws Exception {
174e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    RecordingAsyncTimeout timeout = new RecordingAsyncTimeout();
175e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    timeout.deadlineNanoTime(System.nanoTime() - 1);
176e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    timeout.enter();
177e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    Thread.sleep(250);
178e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertTrue(timeout.exit());
179e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertTimedOut(timeout);
180e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
181e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
182e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Test public void wrappedSinkTimesOut() throws Exception {
183e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    Sink sink = new ForwardingSink(new Buffer()) {
184e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      @Override public void write(Buffer source, long byteCount) throws IOException {
185e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        try {
186e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller          Thread.sleep(500);
187e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        } catch (InterruptedException e) {
188e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller          throw new AssertionError();
189e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        }
190e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      }
191e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    };
192e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    AsyncTimeout timeout = new AsyncTimeout();
193e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    timeout.timeout(250, TimeUnit.MILLISECONDS);
194e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    Sink timeoutSink = timeout.sink(sink);
195e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    try {
196e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      timeoutSink.write(null, 0);
197e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      fail();
198e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    } catch (InterruptedIOException expected) {
199e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    }
200e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
201e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
202e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Test public void wrappedSourceTimesOut() throws Exception {
203e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    Source source = new ForwardingSource(new Buffer()) {
204e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      @Override public long read(Buffer sink, long byteCount) throws IOException {
205e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        try {
206e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller          Thread.sleep(500);
207e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller          return -1;
208e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        } catch (InterruptedException e) {
209e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller          throw new AssertionError();
210e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        }
211e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      }
212e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    };
213e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    AsyncTimeout timeout = new AsyncTimeout();
214e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    timeout.timeout(250, TimeUnit.MILLISECONDS);
215e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    Source timeoutSource = timeout.source(source);
216e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    try {
217e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      timeoutSource.read(null, 0);
218e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      fail();
219e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    } catch (InterruptedIOException expected) {
220e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    }
221e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
222e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
223e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Test public void wrappedThrowsWithTimeout() throws Exception {
224e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    Sink sink = new ForwardingSink(new Buffer()) {
225e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      @Override public void write(Buffer source, long byteCount) throws IOException {
226e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        try {
227e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller          Thread.sleep(500);
228e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller          throw new IOException("exception and timeout");
229e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        } catch (InterruptedException e) {
230e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller          throw new AssertionError();
231e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        }
232e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      }
233e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    };
234e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    AsyncTimeout timeout = new AsyncTimeout();
235e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    timeout.timeout(250, TimeUnit.MILLISECONDS);
236e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    Sink timeoutSink = timeout.sink(sink);
237e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    try {
238e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      timeoutSink.write(null, 0);
239e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      fail();
240e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    } catch (InterruptedIOException expected) {
241e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      assertEquals("timeout", expected.getMessage());
242e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      assertEquals("exception and timeout", expected.getCause().getMessage());
243e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    }
244e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
245e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
246e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  @Test public void wrappedThrowsWithoutTimeout() throws Exception {
247e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    Sink sink = new ForwardingSink(new Buffer()) {
248e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      @Override public void write(Buffer source, long byteCount) throws IOException {
249e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller        throw new IOException("no timeout occurred");
250e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      }
251e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    };
252e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    AsyncTimeout timeout = new AsyncTimeout();
253e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    timeout.timeout(250, TimeUnit.MILLISECONDS);
254e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    Sink timeoutSink = timeout.sink(sink);
255e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    try {
256e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      timeoutSink.write(null, 0);
257e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      fail();
258e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    } catch (IOException expected) {
259e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      assertEquals("no timeout occurred", expected.getMessage());
260e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    }
261e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
262e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
263e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  /** Asserts which timeouts fired, and in which order. */
264e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  private void assertTimedOut(Timeout... expected) {
265e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    assertEquals(Arrays.asList(expected), timedOut);
266e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
267e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller
268e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  class RecordingAsyncTimeout extends AsyncTimeout {
269e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    @Override protected void timedOut() {
270e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller      timedOut.add(this);
271e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller    }
272e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller  }
273e78f117bcbd6b57d783737107f445ef75ecb474aNeil Fuller}
274