/*
 * Copyright (C) 2008 The Guava Authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.google.common.testing;

import com.google.common.annotations.GwtCompatible;
import com.google.common.annotations.GwtIncompatible;
import java.util.EnumSet;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import junit.framework.TestCase;

/**
 * Unit test for {@link FakeTicker}.
 *
 * @author Jige Yu
 */
@GwtCompatible(emulated = true)
public class FakeTickerTest extends TestCase {

  @GwtIncompatible // NullPointerTester
  public void testNullPointerExceptions() {
    NullPointerTester tester = new NullPointerTester();
    tester.testAllPublicInstanceMethods(new FakeTicker());
  }

  public void testAdvance() {
    FakeTicker ticker = new FakeTicker();
    assertEquals(0, ticker.read());
    assertSame(ticker, ticker.advance(10));
    assertEquals(10, ticker.read());
    ticker.advance(1, TimeUnit.MILLISECONDS);
    assertEquals(1000010L, ticker.read());
  }

  public void testAutoIncrementStep_returnsSameInstance() {
    FakeTicker ticker = new FakeTicker();
    assertSame(ticker, ticker.setAutoIncrementStep(10, TimeUnit.NANOSECONDS));
  }

  public void testAutoIncrementStep_nanos() {
    FakeTicker ticker = new FakeTicker().setAutoIncrementStep(10, TimeUnit.NANOSECONDS);
    assertEquals(0, ticker.read());
    assertEquals(10, ticker.read());
    assertEquals(20, ticker.read());
  }

  public void testAutoIncrementStep_millis() {
    FakeTicker ticker = new FakeTicker().setAutoIncrementStep(1, TimeUnit.MILLISECONDS);
    assertEquals(0, ticker.read());
    assertEquals(1000000, ticker.read());
    assertEquals(2000000, ticker.read());
  }

  public void testAutoIncrementStep_seconds() {
    FakeTicker ticker = new FakeTicker().setAutoIncrementStep(3, TimeUnit.SECONDS);
    assertEquals(0, ticker.read());
    assertEquals(3000000000L, ticker.read());
    assertEquals(6000000000L, ticker.read());
  }

  public void testAutoIncrementStep_resetToZero() {
    FakeTicker ticker = new FakeTicker().setAutoIncrementStep(10, TimeUnit.NANOSECONDS);
    assertEquals(0, ticker.read());
    assertEquals(10, ticker.read());
    assertEquals(20, ticker.read());

    for (TimeUnit timeUnit : EnumSet.allOf(TimeUnit.class)) {
      ticker.setAutoIncrementStep(0, timeUnit);
      assertEquals(
          "Expected no auto-increment when setting autoIncrementStep to 0 " + timeUnit,
          30,
          ticker.read());
    }
  }

  public void testAutoIncrement_negative() {
    FakeTicker ticker = new FakeTicker();
    try {
      ticker.setAutoIncrementStep(-1, TimeUnit.NANOSECONDS);
      fail("Expected IllegalArgumentException");
    } catch (IllegalArgumentException expected) {
    }
  }

  @GwtIncompatible // concurrency

  public void testConcurrentAdvance() throws Exception {
    final FakeTicker ticker = new FakeTicker();

    int numberOfThreads = 64;
    runConcurrentTest(
        numberOfThreads,
        new Callable<Void>() {
          @Override
          public Void call() throws Exception {
            // adds two nanoseconds to the ticker
            ticker.advance(1L);
            Thread.sleep(10);
            ticker.advance(1L);
            return null;
          }
        });

    assertEquals(numberOfThreads * 2, ticker.read());
  }

  @GwtIncompatible // concurrency

  public void testConcurrentAutoIncrementStep() throws Exception {
    int incrementByNanos = 3;
    final FakeTicker ticker =
        new FakeTicker().setAutoIncrementStep(incrementByNanos, TimeUnit.NANOSECONDS);

    int numberOfThreads = 64;
    runConcurrentTest(
        numberOfThreads,
        new Callable<Void>() {
          @Override
          public Void call() throws Exception {
            ticker.read();
            return null;
          }
        });

    assertEquals(incrementByNanos * numberOfThreads, ticker.read());
  }

  /** Runs {@code callable} concurrently {@code numberOfThreads} times. */
  @GwtIncompatible // concurrency
  private void runConcurrentTest(int numberOfThreads, final Callable<Void> callable)
      throws Exception {
    ExecutorService executorService = Executors.newFixedThreadPool(numberOfThreads);
    final CountDownLatch startLatch = new CountDownLatch(numberOfThreads);
    final CountDownLatch doneLatch = new CountDownLatch(numberOfThreads);
    for (int i = numberOfThreads; i > 0; i--) {
      @SuppressWarnings("unused") // go/futurereturn-lsc
      Future<?> possiblyIgnoredError =
          executorService.submit(
              new Callable<Void>() {
                @Override
                public Void call() throws Exception {
                  startLatch.countDown();
                  startLatch.await();
                  callable.call();
                  doneLatch.countDown();
                  return null;
                }
              });
    }
    doneLatch.await();
  }
}
