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