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