Home | History | Annotate | Download | only in concurrent
      1 /*
      2  * Copyright (C) 2006 The Guava Authors
      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 
     17 package com.google.common.util.concurrent;
     18 
     19 import junit.framework.TestCase;
     20 
     21 import java.util.concurrent.Callable;
     22 import java.util.concurrent.ExecutorService;
     23 import java.util.concurrent.Executors;
     24 import java.util.concurrent.TimeUnit;
     25 
     26 /**
     27  * Unit test for {@link SimpleTimeLimiter}.
     28  *
     29  * @author kevinb
     30  */
     31 public class SimpleTimeLimiterTest extends TestCase {
     32 
     33   private static final int DELAY_MS = 50;
     34   private static final int ENOUGH_MS = 500;
     35   private static final int NOT_ENOUGH_MS = 5;
     36 
     37   private TimeLimiter service;
     38 
     39   private static final ExecutorService executor
     40       = Executors.newFixedThreadPool(1);
     41 
     42   private static String someGoodStaticMethod() throws InterruptedException {
     43     TimeUnit.MILLISECONDS.sleep(DELAY_MS);
     44     return "yes";
     45   }
     46 
     47   private static String someBadStaticMethod() throws InterruptedException,
     48       SampleException {
     49     TimeUnit.MILLISECONDS.sleep(DELAY_MS);
     50     throw new SampleException();
     51   }
     52 
     53   @Override protected void setUp() throws Exception {
     54     super.setUp();
     55     service = new SimpleTimeLimiter(executor);
     56   }
     57 
     58   public void testGoodCallableWithEnoughTime() throws Exception {
     59     long start = System.nanoTime();
     60     String result = service.callWithTimeout(
     61         new Callable<String>() {
     62           @Override
     63           public String call() throws InterruptedException {
     64             return someGoodStaticMethod();
     65           }
     66         }, ENOUGH_MS, TimeUnit.MILLISECONDS, true);
     67     assertEquals("yes", result);
     68     assertTheCallTookBetween(start, DELAY_MS, ENOUGH_MS);
     69   }
     70 
     71   public void testGoodCallableWithNotEnoughTime() throws Exception {
     72     long start = System.nanoTime();
     73     try {
     74       service.callWithTimeout(
     75           new Callable<String>() {
     76             @Override
     77             public String call() throws InterruptedException {
     78               return someGoodStaticMethod();
     79             }
     80           }, NOT_ENOUGH_MS, TimeUnit.MILLISECONDS, true);
     81       fail("no exception thrown");
     82     } catch (UncheckedTimeoutException expected) {
     83     }
     84     assertTheCallTookBetween(start, NOT_ENOUGH_MS, DELAY_MS);
     85   }
     86 
     87   public void testBadCallableWithEnoughTime() throws Exception {
     88     long start = System.nanoTime();
     89     try {
     90       service.callWithTimeout(
     91           new Callable<String>() {
     92             @Override
     93             public String call() throws SampleException, InterruptedException {
     94               return someBadStaticMethod();
     95             }
     96           }, ENOUGH_MS, TimeUnit.MILLISECONDS, true);
     97       fail("no exception thrown");
     98     } catch (SampleException expected) {
     99     }
    100     assertTheCallTookBetween(start, DELAY_MS, ENOUGH_MS);
    101   }
    102 
    103   public void testBadCallableWithNotEnoughTime() throws Exception {
    104     long start = System.nanoTime();
    105     try {
    106       service.callWithTimeout(
    107           new Callable<String>() {
    108             @Override
    109             public String call() throws SampleException, InterruptedException {
    110               return someBadStaticMethod();
    111             }
    112           }, NOT_ENOUGH_MS, TimeUnit.MILLISECONDS, true);
    113       fail("no exception thrown");
    114     } catch (UncheckedTimeoutException expected) {
    115     }
    116     assertTheCallTookBetween(start, NOT_ENOUGH_MS, DELAY_MS);
    117   }
    118 
    119   public void testGoodMethodWithEnoughTime() throws Exception {
    120     SampleImpl target = new SampleImpl();
    121     Sample proxy = service.newProxy(
    122         target, Sample.class, ENOUGH_MS, TimeUnit.MILLISECONDS);
    123     long start = System.nanoTime();
    124     assertEquals("x", proxy.sleepThenReturnInput("x"));
    125     assertTheCallTookBetween(start, DELAY_MS, ENOUGH_MS);
    126     assertTrue(target.finished);
    127   }
    128 
    129   public void testGoodMethodWithNotEnoughTime() throws Exception {
    130     SampleImpl target = new SampleImpl();
    131     Sample proxy = service.newProxy(
    132         target, Sample.class, NOT_ENOUGH_MS, TimeUnit.MILLISECONDS);
    133     long start = System.nanoTime();
    134     try {
    135       proxy.sleepThenReturnInput("x");
    136       fail("no exception thrown");
    137     } catch (UncheckedTimeoutException expected) {
    138     }
    139     assertTheCallTookBetween(start, NOT_ENOUGH_MS, DELAY_MS);
    140 
    141     // Is it still computing away anyway?
    142     assertFalse(target.finished);
    143     TimeUnit.MILLISECONDS.sleep(ENOUGH_MS);
    144     assertFalse(target.finished);
    145   }
    146 
    147   public void testBadMethodWithEnoughTime() throws Exception {
    148     SampleImpl target = new SampleImpl();
    149     Sample proxy = service.newProxy(
    150         target, Sample.class, ENOUGH_MS, TimeUnit.MILLISECONDS);
    151     long start = System.nanoTime();
    152     try {
    153       proxy.sleepThenThrowException();
    154       fail("no exception thrown");
    155     } catch (SampleException expected) {
    156     }
    157     assertTheCallTookBetween(start, DELAY_MS, ENOUGH_MS);
    158   }
    159 
    160   public void testBadMethodWithNotEnoughTime() throws Exception {
    161     SampleImpl target = new SampleImpl();
    162     Sample proxy = service.newProxy(
    163         target, Sample.class, NOT_ENOUGH_MS, TimeUnit.MILLISECONDS);
    164     long start = System.nanoTime();
    165     try {
    166       proxy.sleepThenThrowException();
    167       fail("no exception thrown");
    168     } catch (UncheckedTimeoutException expected) {
    169     }
    170     assertTheCallTookBetween(start, NOT_ENOUGH_MS, DELAY_MS);
    171   }
    172 
    173   private static void assertTheCallTookBetween(
    174       long startNanos, int atLeastMillis, int atMostMillis) {
    175     long nanos = System.nanoTime() - startNanos;
    176     assertTrue(nanos >= atLeastMillis * 1000000);
    177     assertTrue(nanos <= atMostMillis * 1000000);
    178   }
    179 
    180   public interface Sample {
    181     String sleepThenReturnInput(String input);
    182     void sleepThenThrowException() throws SampleException;
    183   }
    184 
    185   @SuppressWarnings("serial")
    186   public static class SampleException extends Exception {}
    187 
    188   public static class SampleImpl implements Sample {
    189     boolean finished;
    190 
    191     @Override
    192     public String sleepThenReturnInput(String input) {
    193       try {
    194         TimeUnit.MILLISECONDS.sleep(DELAY_MS);
    195         finished = true;
    196         return input;
    197       } catch (InterruptedException e) {
    198         return null;
    199       }
    200     }
    201     @Override
    202     public void sleepThenThrowException() throws SampleException {
    203       try {
    204         TimeUnit.MILLISECONDS.sleep(DELAY_MS);
    205       } catch (InterruptedException e) {
    206       }
    207       throw new SampleException();
    208     }
    209   }
    210 }
    211