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