1 /* 2 * Copyright (C) 2008 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.testing; 18 19 import com.google.common.annotations.GwtCompatible; 20 import com.google.common.annotations.GwtIncompatible; 21 import java.util.EnumSet; 22 import java.util.concurrent.Callable; 23 import java.util.concurrent.CountDownLatch; 24 import java.util.concurrent.ExecutorService; 25 import java.util.concurrent.Executors; 26 import java.util.concurrent.Future; 27 import java.util.concurrent.TimeUnit; 28 import junit.framework.TestCase; 29 30 /** 31 * Unit test for {@link FakeTicker}. 32 * 33 * @author Jige Yu 34 */ 35 @GwtCompatible(emulated = true) 36 public class FakeTickerTest extends TestCase { 37 38 @GwtIncompatible // NullPointerTester testNullPointerExceptions()39 public void testNullPointerExceptions() { 40 NullPointerTester tester = new NullPointerTester(); 41 tester.testAllPublicInstanceMethods(new FakeTicker()); 42 } 43 testAdvance()44 public void testAdvance() { 45 FakeTicker ticker = new FakeTicker(); 46 assertEquals(0, ticker.read()); 47 assertSame(ticker, ticker.advance(10)); 48 assertEquals(10, ticker.read()); 49 ticker.advance(1, TimeUnit.MILLISECONDS); 50 assertEquals(1000010L, ticker.read()); 51 } 52 testAutoIncrementStep_returnsSameInstance()53 public void testAutoIncrementStep_returnsSameInstance() { 54 FakeTicker ticker = new FakeTicker(); 55 assertSame(ticker, ticker.setAutoIncrementStep(10, TimeUnit.NANOSECONDS)); 56 } 57 testAutoIncrementStep_nanos()58 public void testAutoIncrementStep_nanos() { 59 FakeTicker ticker = new FakeTicker().setAutoIncrementStep(10, TimeUnit.NANOSECONDS); 60 assertEquals(0, ticker.read()); 61 assertEquals(10, ticker.read()); 62 assertEquals(20, ticker.read()); 63 } 64 testAutoIncrementStep_millis()65 public void testAutoIncrementStep_millis() { 66 FakeTicker ticker = new FakeTicker().setAutoIncrementStep(1, TimeUnit.MILLISECONDS); 67 assertEquals(0, ticker.read()); 68 assertEquals(1000000, ticker.read()); 69 assertEquals(2000000, ticker.read()); 70 } 71 testAutoIncrementStep_seconds()72 public void testAutoIncrementStep_seconds() { 73 FakeTicker ticker = new FakeTicker().setAutoIncrementStep(3, TimeUnit.SECONDS); 74 assertEquals(0, ticker.read()); 75 assertEquals(3000000000L, ticker.read()); 76 assertEquals(6000000000L, ticker.read()); 77 } 78 testAutoIncrementStep_resetToZero()79 public void testAutoIncrementStep_resetToZero() { 80 FakeTicker ticker = new FakeTicker().setAutoIncrementStep(10, TimeUnit.NANOSECONDS); 81 assertEquals(0, ticker.read()); 82 assertEquals(10, ticker.read()); 83 assertEquals(20, ticker.read()); 84 85 for (TimeUnit timeUnit : EnumSet.allOf(TimeUnit.class)) { 86 ticker.setAutoIncrementStep(0, timeUnit); 87 assertEquals( 88 "Expected no auto-increment when setting autoIncrementStep to 0 " + timeUnit, 89 30, 90 ticker.read()); 91 } 92 } 93 testAutoIncrement_negative()94 public void testAutoIncrement_negative() { 95 FakeTicker ticker = new FakeTicker(); 96 try { 97 ticker.setAutoIncrementStep(-1, TimeUnit.NANOSECONDS); 98 fail("Expected IllegalArgumentException"); 99 } catch (IllegalArgumentException expected) { 100 } 101 } 102 103 @GwtIncompatible // concurrency 104 testConcurrentAdvance()105 public void testConcurrentAdvance() throws Exception { 106 final FakeTicker ticker = new FakeTicker(); 107 108 int numberOfThreads = 64; 109 runConcurrentTest( 110 numberOfThreads, 111 new Callable<Void>() { 112 @Override 113 public Void call() throws Exception { 114 // adds two nanoseconds to the ticker 115 ticker.advance(1L); 116 Thread.sleep(10); 117 ticker.advance(1L); 118 return null; 119 } 120 }); 121 122 assertEquals(numberOfThreads * 2, ticker.read()); 123 } 124 125 @GwtIncompatible // concurrency 126 testConcurrentAutoIncrementStep()127 public void testConcurrentAutoIncrementStep() throws Exception { 128 int incrementByNanos = 3; 129 final FakeTicker ticker = 130 new FakeTicker().setAutoIncrementStep(incrementByNanos, TimeUnit.NANOSECONDS); 131 132 int numberOfThreads = 64; 133 runConcurrentTest( 134 numberOfThreads, 135 new Callable<Void>() { 136 @Override 137 public Void call() throws Exception { 138 ticker.read(); 139 return null; 140 } 141 }); 142 143 assertEquals(incrementByNanos * numberOfThreads, ticker.read()); 144 } 145 146 /** Runs {@code callable} concurrently {@code numberOfThreads} times. */ 147 @GwtIncompatible // concurrency runConcurrentTest(int numberOfThreads, final Callable<Void> callable)148 private void runConcurrentTest(int numberOfThreads, final Callable<Void> callable) 149 throws Exception { 150 ExecutorService executorService = Executors.newFixedThreadPool(numberOfThreads); 151 final CountDownLatch startLatch = new CountDownLatch(numberOfThreads); 152 final CountDownLatch doneLatch = new CountDownLatch(numberOfThreads); 153 for (int i = numberOfThreads; i > 0; i--) { 154 @SuppressWarnings("unused") // https://errorprone.info/bugpattern/FutureReturnValueIgnored 155 Future<?> possiblyIgnoredError = 156 executorService.submit( 157 new Callable<Void>() { 158 @Override 159 public Void call() throws Exception { 160 startLatch.countDown(); 161 startLatch.await(); 162 callable.call(); 163 doneLatch.countDown(); 164 return null; 165 } 166 }); 167 } 168 doneLatch.await(); 169 } 170 } 171