/*
 * Copyright (C) 2012 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.util.concurrent;

import static com.google.common.truth.Truth.assertThat;
import static java.util.Arrays.asList;
import static java.util.concurrent.TimeUnit.SECONDS;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.common.testing.NullPointerTester;
import com.google.common.testing.TestLogHandler;
import com.google.common.util.concurrent.Service.State;
import com.google.common.util.concurrent.ServiceManager.Listener;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.logging.Formatter;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import junit.framework.TestCase;

/**
 * Tests for {@link ServiceManager}.
 *
 * @author Luke Sandberg
 * @author Chris Nokleberg
 */
public class ServiceManagerTest extends TestCase {

  private static class NoOpService extends AbstractService {
    @Override
    protected void doStart() {
      notifyStarted();
    }

    @Override
    protected void doStop() {
      notifyStopped();
    }
  }

  /*
   * A NoOp service that will delay the startup and shutdown notification for a configurable amount
   * of time.
   */
  private static class NoOpDelayedService extends NoOpService {
    private long delay;

    public NoOpDelayedService(long delay) {
      this.delay = delay;
    }

    @Override
    protected void doStart() {
      new Thread() {
        @Override
        public void run() {
          Uninterruptibles.sleepUninterruptibly(delay, TimeUnit.MILLISECONDS);
          notifyStarted();
        }
      }.start();
    }

    @Override
    protected void doStop() {
      new Thread() {
        @Override
        public void run() {
          Uninterruptibles.sleepUninterruptibly(delay, TimeUnit.MILLISECONDS);
          notifyStopped();
        }
      }.start();
    }
  }

  private static class FailStartService extends NoOpService {
    @Override
    protected void doStart() {
      notifyFailed(new IllegalStateException("start failure"));
    }
  }

  private static class FailRunService extends NoOpService {
    @Override
    protected void doStart() {
      super.doStart();
      notifyFailed(new IllegalStateException("run failure"));
    }
  }

  private static class FailStopService extends NoOpService {
    @Override
    protected void doStop() {
      notifyFailed(new IllegalStateException("stop failure"));
    }
  }

  public void testServiceStartupTimes() {
    Service a = new NoOpDelayedService(150);
    Service b = new NoOpDelayedService(353);
    ServiceManager serviceManager = new ServiceManager(asList(a, b));
    serviceManager.startAsync().awaitHealthy();
    ImmutableMap<Service, Long> startupTimes = serviceManager.startupTimes();
    assertEquals(2, startupTimes.size());
    // TODO(kak): Use assertThat(startupTimes.get(a)).isAtLeast(150);
    assertTrue(startupTimes.get(a) >= 150);
    // TODO(kak): Use assertThat(startupTimes.get(b)).isAtLeast(353);
    assertTrue(startupTimes.get(b) >= 353);
  }

  public void testServiceStartupTimes_selfStartingServices() {
    // This tests to ensure that:
    // 1. service times are accurate when the service is started by the manager
    // 2. service times are recorded when the service is not started by the manager (but they may
    // not be accurate).
    final Service b =
        new NoOpDelayedService(353) {
          @Override
          protected void doStart() {
            super.doStart();
            // This will delay service listener execution at least 150 milliseconds
            Uninterruptibles.sleepUninterruptibly(150, TimeUnit.MILLISECONDS);
          }
        };
    Service a =
        new NoOpDelayedService(150) {
          @Override
          protected void doStart() {
            b.startAsync();
            super.doStart();
          }
        };
    ServiceManager serviceManager = new ServiceManager(asList(a, b));
    serviceManager.startAsync().awaitHealthy();
    ImmutableMap<Service, Long> startupTimes = serviceManager.startupTimes();
    assertEquals(2, startupTimes.size());
    // TODO(kak): Use assertThat(startupTimes.get(a)).isAtLeast(150);
    assertTrue(startupTimes.get(a) >= 150);
    // Service b startup takes at least 353 millis, but starting the timer is delayed by at least
    // 150 milliseconds. so in a perfect world the timing would be 353-150=203ms, but since either
    // of our sleep calls can be arbitrarily delayed we should just assert that there is a time
    // recorded.
    assertThat(startupTimes.get(b)).isNotNull();
  }

  public void testServiceStartStop() {
    Service a = new NoOpService();
    Service b = new NoOpService();
    ServiceManager manager = new ServiceManager(asList(a, b));
    RecordingListener listener = new RecordingListener();
    manager.addListener(listener);
    assertState(manager, Service.State.NEW, a, b);
    assertFalse(manager.isHealthy());
    manager.startAsync().awaitHealthy();
    assertState(manager, Service.State.RUNNING, a, b);
    assertTrue(manager.isHealthy());
    assertTrue(listener.healthyCalled);
    assertFalse(listener.stoppedCalled);
    assertTrue(listener.failedServices.isEmpty());
    manager.stopAsync().awaitStopped();
    assertState(manager, Service.State.TERMINATED, a, b);
    assertFalse(manager.isHealthy());
    assertTrue(listener.stoppedCalled);
    assertTrue(listener.failedServices.isEmpty());
  }

  public void testFailStart() throws Exception {
    Service a = new NoOpService();
    Service b = new FailStartService();
    Service c = new NoOpService();
    Service d = new FailStartService();
    Service e = new NoOpService();
    ServiceManager manager = new ServiceManager(asList(a, b, c, d, e));
    RecordingListener listener = new RecordingListener();
    manager.addListener(listener);
    assertState(manager, Service.State.NEW, a, b, c, d, e);
    try {
      manager.startAsync().awaitHealthy();
      fail();
    } catch (IllegalStateException expected) {
    }
    assertFalse(listener.healthyCalled);
    assertState(manager, Service.State.RUNNING, a, c, e);
    assertEquals(ImmutableSet.of(b, d), listener.failedServices);
    assertState(manager, Service.State.FAILED, b, d);
    assertFalse(manager.isHealthy());

    manager.stopAsync().awaitStopped();
    assertFalse(manager.isHealthy());
    assertFalse(listener.healthyCalled);
    assertTrue(listener.stoppedCalled);
  }

  public void testFailRun() throws Exception {
    Service a = new NoOpService();
    Service b = new FailRunService();
    ServiceManager manager = new ServiceManager(asList(a, b));
    RecordingListener listener = new RecordingListener();
    manager.addListener(listener);
    assertState(manager, Service.State.NEW, a, b);
    try {
      manager.startAsync().awaitHealthy();
      fail();
    } catch (IllegalStateException expected) {
    }
    assertTrue(listener.healthyCalled);
    assertEquals(ImmutableSet.of(b), listener.failedServices);

    manager.stopAsync().awaitStopped();
    assertState(manager, Service.State.FAILED, b);
    assertState(manager, Service.State.TERMINATED, a);

    assertTrue(listener.stoppedCalled);
  }

  public void testFailStop() throws Exception {
    Service a = new NoOpService();
    Service b = new FailStopService();
    Service c = new NoOpService();
    ServiceManager manager = new ServiceManager(asList(a, b, c));
    RecordingListener listener = new RecordingListener();
    manager.addListener(listener);

    manager.startAsync().awaitHealthy();
    assertTrue(listener.healthyCalled);
    assertFalse(listener.stoppedCalled);
    manager.stopAsync().awaitStopped();

    assertTrue(listener.stoppedCalled);
    assertEquals(ImmutableSet.of(b), listener.failedServices);
    assertState(manager, Service.State.FAILED, b);
    assertState(manager, Service.State.TERMINATED, a, c);
  }

  public void testToString() throws Exception {
    Service a = new NoOpService();
    Service b = new FailStartService();
    ServiceManager manager = new ServiceManager(asList(a, b));
    String toString = manager.toString();
    assertThat(toString).contains("NoOpService");
    assertThat(toString).contains("FailStartService");
  }

  public void testTimeouts() throws Exception {
    Service a = new NoOpDelayedService(50);
    ServiceManager manager = new ServiceManager(asList(a));
    manager.startAsync();
    try {
      manager.awaitHealthy(1, TimeUnit.MILLISECONDS);
      fail();
    } catch (TimeoutException expected) {
    }
    manager.awaitHealthy(5, SECONDS); // no exception thrown

    manager.stopAsync();
    try {
      manager.awaitStopped(1, TimeUnit.MILLISECONDS);
      fail();
    } catch (TimeoutException expected) {
    }
    manager.awaitStopped(5, SECONDS); // no exception thrown
  }

  /**
   * This covers a case where if the last service to stop failed then the stopped callback would
   * never be called.
   */
  public void testSingleFailedServiceCallsStopped() {
    Service a = new FailStartService();
    ServiceManager manager = new ServiceManager(asList(a));
    RecordingListener listener = new RecordingListener();
    manager.addListener(listener);
    try {
      manager.startAsync().awaitHealthy();
      fail();
    } catch (IllegalStateException expected) {
    }
    assertTrue(listener.stoppedCalled);
  }

  /**
   * This covers a bug where listener.healthy would get called when a single service failed during
   * startup (it occurred in more complicated cases also).
   */
  public void testFailStart_singleServiceCallsHealthy() {
    Service a = new FailStartService();
    ServiceManager manager = new ServiceManager(asList(a));
    RecordingListener listener = new RecordingListener();
    manager.addListener(listener);
    try {
      manager.startAsync().awaitHealthy();
      fail();
    } catch (IllegalStateException expected) {
    }
    assertFalse(listener.healthyCalled);
  }

  /**
   * This covers a bug where if a listener was installed that would stop the manager if any service
   * fails and something failed during startup before service.start was called on all the services,
   * then awaitStopped would deadlock due to an IllegalStateException that was thrown when trying to
   * stop the timer(!).
   */
  public void testFailStart_stopOthers() throws TimeoutException {
    Service a = new FailStartService();
    Service b = new NoOpService();
    final ServiceManager manager = new ServiceManager(asList(a, b));
    manager.addListener(
        new Listener() {
          @Override
          public void failure(Service service) {
            manager.stopAsync();
          }
        });
    manager.startAsync();
    manager.awaitStopped(10, TimeUnit.MILLISECONDS);
  }

  public void testDoCancelStart() throws TimeoutException {
    Service a =
        new AbstractService() {
          @Override
          protected void doStart() {
            // Never starts!
          }

          @Override
          protected void doCancelStart() {
            assertThat(state()).isEqualTo(Service.State.STOPPING);
            notifyStopped();
          }

          @Override
          protected void doStop() {
            throw new AssertionError(); // Should not be called.
          }
        };

    final ServiceManager manager = new ServiceManager(asList(a));
    manager.startAsync();
    manager.stopAsync();
    manager.awaitStopped(10, TimeUnit.MILLISECONDS);
    assertThat(manager.servicesByState().keySet()).containsExactly(Service.State.TERMINATED);
  }

  public void testNotifyStoppedAfterFailure() throws TimeoutException {
    Service a =
        new AbstractService() {
          @Override
          protected void doStart() {
            notifyFailed(new IllegalStateException("start failure"));
            notifyStopped(); // This will be a no-op.
          }

          @Override
          protected void doStop() {
            notifyStopped();
          }
        };
    final ServiceManager manager = new ServiceManager(asList(a));
    manager.startAsync();
    manager.awaitStopped(10, TimeUnit.MILLISECONDS);
    assertThat(manager.servicesByState().keySet()).containsExactly(Service.State.FAILED);
  }

  private static void assertState(
      ServiceManager manager, Service.State state, Service... services) {
    Collection<Service> managerServices = manager.servicesByState().get(state);
    for (Service service : services) {
      assertEquals(service.toString(), state, service.state());
      assertEquals(service.toString(), service.isRunning(), state == Service.State.RUNNING);
      assertTrue(managerServices + " should contain " + service, managerServices.contains(service));
    }
  }

  /**
   * This is for covering a case where the ServiceManager would behave strangely if constructed with
   * no service under management. Listeners would never fire because the ServiceManager was healthy
   * and stopped at the same time. This test ensures that listeners fire and isHealthy makes sense.
   */
  public void testEmptyServiceManager() {
    Logger logger = Logger.getLogger(ServiceManager.class.getName());
    logger.setLevel(Level.FINEST);
    TestLogHandler logHandler = new TestLogHandler();
    logger.addHandler(logHandler);
    ServiceManager manager = new ServiceManager(Arrays.<Service>asList());
    RecordingListener listener = new RecordingListener();
    manager.addListener(listener);
    manager.startAsync().awaitHealthy();
    assertTrue(manager.isHealthy());
    assertTrue(listener.healthyCalled);
    assertFalse(listener.stoppedCalled);
    assertTrue(listener.failedServices.isEmpty());
    manager.stopAsync().awaitStopped();
    assertFalse(manager.isHealthy());
    assertTrue(listener.stoppedCalled);
    assertTrue(listener.failedServices.isEmpty());
    // check that our NoOpService is not directly observable via any of the inspection methods or
    // via logging.
    assertEquals("ServiceManager{services=[]}", manager.toString());
    assertTrue(manager.servicesByState().isEmpty());
    assertTrue(manager.startupTimes().isEmpty());
    Formatter logFormatter =
        new Formatter() {
          @Override
          public String format(LogRecord record) {
            return formatMessage(record);
          }
        };
    for (LogRecord record : logHandler.getStoredLogRecords()) {
      assertThat(logFormatter.format(record)).doesNotContain("NoOpService");
    }
  }

  /**
   * Tests that a ServiceManager can be fully shut down if one of its failure listeners is slow or
   * even permanently blocked.
   */

  public void testListenerDeadlock() throws InterruptedException {
    final CountDownLatch failEnter = new CountDownLatch(1);
    final CountDownLatch failLeave = new CountDownLatch(1);
    final CountDownLatch afterStarted = new CountDownLatch(1);
    Service failRunService =
        new AbstractService() {
          @Override
          protected void doStart() {
            new Thread() {
              @Override
              public void run() {
                notifyStarted();
                // We need to wait for the main thread to leave the ServiceManager.startAsync call
                // to
                // ensure that the thread running the failure callbacks is not the main thread.
                Uninterruptibles.awaitUninterruptibly(afterStarted);
                notifyFailed(new Exception("boom"));
              }
            }.start();
          }

          @Override
          protected void doStop() {
            notifyStopped();
          }
        };
    final ServiceManager manager =
        new ServiceManager(Arrays.asList(failRunService, new NoOpService()));
    manager.addListener(
        new ServiceManager.Listener() {
          @Override
          public void failure(Service service) {
            failEnter.countDown();
            // block until after the service manager is shutdown
            Uninterruptibles.awaitUninterruptibly(failLeave);
          }
        });
    manager.startAsync();
    afterStarted.countDown();
    // We do not call awaitHealthy because, due to races, that method may throw an exception.  But
    // we really just want to wait for the thread to be in the failure callback so we wait for that
    // explicitly instead.
    failEnter.await();
    assertFalse("State should be updated before calling listeners", manager.isHealthy());
    // now we want to stop the services.
    Thread stoppingThread =
        new Thread() {
          @Override
          public void run() {
            manager.stopAsync().awaitStopped();
          }
        };
    stoppingThread.start();
    // this should be super fast since the only non stopped service is a NoOpService
    stoppingThread.join(1000);
    assertFalse("stopAsync has deadlocked!.", stoppingThread.isAlive());
    failLeave.countDown(); // release the background thread
  }

  /**
   * Catches a bug where when constructing a service manager failed, later interactions with the
   * service could cause IllegalStateExceptions inside the partially constructed ServiceManager.
   * This ISE wouldn't actually bubble up but would get logged by ExecutionQueue. This obfuscated
   * the original error (which was not constructing ServiceManager correctly).
   */
  public void testPartiallyConstructedManager() {
    Logger logger = Logger.getLogger("global");
    logger.setLevel(Level.FINEST);
    TestLogHandler logHandler = new TestLogHandler();
    logger.addHandler(logHandler);
    NoOpService service = new NoOpService();
    service.startAsync();
    try {
      new ServiceManager(Arrays.asList(service));
      fail();
    } catch (IllegalArgumentException expected) {
    }
    service.stopAsync();
    // Nothing was logged!
    assertEquals(0, logHandler.getStoredLogRecords().size());
  }

  public void testPartiallyConstructedManager_transitionAfterAddListenerBeforeStateIsReady() {
    // The implementation of this test is pretty sensitive to the implementation :( but we want to
    // ensure that if weird things happen during construction then we get exceptions.
    final NoOpService service1 = new NoOpService();
    // This service will start service1 when addListener is called.  This simulates service1 being
    // started asynchronously.
    Service service2 =
        new Service() {
          final NoOpService delegate = new NoOpService();

          @Override
          public final void addListener(Listener listener, Executor executor) {
            service1.startAsync();
            delegate.addListener(listener, executor);
          }
          // Delegates from here on down
          @Override
          public final Service startAsync() {
            return delegate.startAsync();
          }

          @Override
          public final Service stopAsync() {
            return delegate.stopAsync();
          }

          @Override
          public final void awaitRunning() {
            delegate.awaitRunning();
          }

          @Override
          public final void awaitRunning(long timeout, TimeUnit unit) throws TimeoutException {
            delegate.awaitRunning(timeout, unit);
          }

          @Override
          public final void awaitTerminated() {
            delegate.awaitTerminated();
          }

          @Override
          public final void awaitTerminated(long timeout, TimeUnit unit) throws TimeoutException {
            delegate.awaitTerminated(timeout, unit);
          }

          @Override
          public final boolean isRunning() {
            return delegate.isRunning();
          }

          @Override
          public final State state() {
            return delegate.state();
          }

          @Override
          public final Throwable failureCause() {
            return delegate.failureCause();
          }
        };
    try {
      new ServiceManager(Arrays.asList(service1, service2));
      fail();
    } catch (IllegalArgumentException expected) {
      assertThat(expected.getMessage()).contains("started transitioning asynchronously");
    }
  }

  /**
   * This test is for a case where two Service.Listener callbacks for the same service would call
   * transitionService in the wrong order due to a race. Due to the fact that it is a race this test
   * isn't guaranteed to expose the issue, but it is at least likely to become flaky if the race
   * sneaks back in, and in this case flaky means something is definitely wrong.
   *
   * <p>Before the bug was fixed this test would fail at least 30% of the time.
   */

  public void testTransitionRace() throws TimeoutException {
    for (int k = 0; k < 1000; k++) {
      List<Service> services = Lists.newArrayList();
      for (int i = 0; i < 5; i++) {
        services.add(new SnappyShutdownService(i));
      }
      ServiceManager manager = new ServiceManager(services);
      manager.startAsync().awaitHealthy();
      manager.stopAsync().awaitStopped(1, TimeUnit.SECONDS);
    }
  }

  /**
   * This service will shutdown very quickly after stopAsync is called and uses a background thread
   * so that we know that the stopping() listeners will execute on a different thread than the
   * terminated() listeners.
   */
  private static class SnappyShutdownService extends AbstractExecutionThreadService {
    final int index;
    final CountDownLatch latch = new CountDownLatch(1);

    SnappyShutdownService(int index) {
      this.index = index;
    }

    @Override
    protected void run() throws Exception {
      latch.await();
    }

    @Override
    protected void triggerShutdown() {
      latch.countDown();
    }

    @Override
    protected String serviceName() {
      return this.getClass().getSimpleName() + "[" + index + "]";
    }
  }

  public void testNulls() {
    ServiceManager manager = new ServiceManager(Arrays.<Service>asList());
    new NullPointerTester()
        .setDefault(ServiceManager.Listener.class, new RecordingListener())
        .testAllPublicInstanceMethods(manager);
  }

  private static final class RecordingListener extends ServiceManager.Listener {
    volatile boolean healthyCalled;
    volatile boolean stoppedCalled;
    final Set<Service> failedServices = Sets.newConcurrentHashSet();

    @Override
    public void healthy() {
      healthyCalled = true;
    }

    @Override
    public void stopped() {
      stoppedCalled = true;
    }

    @Override
    public void failure(Service service) {
      failedServices.add(service);
    }
  }
}
