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