/*
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for additional information regarding
 * copyright ownership. The ASF licenses this file to You 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 org.apache.geode.internal.metrics;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.ArgumentMatchers.same;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.composite.CompositeMeterRegistry;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
import org.junit.After;
import org.junit.Test;

import org.apache.geode.internal.cache.GemFireCacheImpl;
import org.apache.geode.internal.cache.InternalCache;
import org.apache.geode.internal.metrics.CacheLifecycleMetricsSession.CacheLifecycle;
import org.apache.geode.internal.metrics.CacheLifecycleMetricsSession.ErrorLogger;
import org.apache.geode.metrics.MetricsPublishingService;

public class CacheLifecycleMetricsSessionTest {

  private final CompositeMeterRegistry compositeRegistry = new CompositeMeterRegistry();

  private CacheLifecycleMetricsSession metricsSession;

  @After
  public void tearDown() {
    if (metricsSession != null) {
      GemFireCacheImpl.removeCacheLifecycleListener(metricsSession);
    }
  }

  @Test
  public void startsWithNoDownstreamRegistries() {
    metricsSession = new CacheLifecycleMetricsSession(mock(CacheLifecycle.class), compositeRegistry,
        Collections.emptyList());

    Set<MeterRegistry> downstreamRegistries = compositeRegistry.getRegistries();

    assertThat(downstreamRegistries)
        .isEmpty();
  }

  @Test
  public void remembersConnectedDownstreamRegistries() {
    metricsSession = new CacheLifecycleMetricsSession(mock(CacheLifecycle.class), compositeRegistry,
        Collections.emptyList());

    MeterRegistry downstreamRegistry = new SimpleMeterRegistry();

    metricsSession.addSubregistry(downstreamRegistry);

    assertThat(compositeRegistry.getRegistries())
        .contains(downstreamRegistry);
  }

  @Test
  public void forgetsDisconnectedDownstreamRegistries() {
    metricsSession = new CacheLifecycleMetricsSession(mock(CacheLifecycle.class), compositeRegistry,
        Collections.emptyList());

    MeterRegistry downstreamRegistry = new SimpleMeterRegistry();
    metricsSession.addSubregistry(downstreamRegistry);

    metricsSession.removeSubregistry(downstreamRegistry);

    assertThat(compositeRegistry.getRegistries())
        .doesNotContain(downstreamRegistry);
  }

  @Test
  public void connectsExistingMetersToNewDownstreamRegistries() {
    metricsSession = new CacheLifecycleMetricsSession(mock(CacheLifecycle.class), compositeRegistry,
        Collections.emptyList());

    String counterName = "the.counter";
    Counter primaryCounter = compositeRegistry.counter(counterName);

    double amountIncrementedBeforeConnectingDownstreamRegistry = 3.0;
    primaryCounter.increment(amountIncrementedBeforeConnectingDownstreamRegistry);

    MeterRegistry downstreamRegistry = new SimpleMeterRegistry();
    metricsSession.addSubregistry(downstreamRegistry);

    Counter downstreamCounter = downstreamRegistry.find(counterName).counter();
    assertThat(downstreamCounter)
        .as("downstream counter after connecting, before incrementing")
        .isNotNull();

    // Note that the newly-created downstream counter starts at zero, ignoring
    // any increments that happened before the downstream registry was added.
    assertThat(downstreamCounter.count())
        .as("downstream counter value after connecting, before incrementing")
        .isNotEqualTo(amountIncrementedBeforeConnectingDownstreamRegistry)
        .isEqualTo(0);

    double amountIncrementedAfterConnectingDownstreamRegistry = 42.0;
    primaryCounter.increment(amountIncrementedAfterConnectingDownstreamRegistry);

    assertThat(downstreamCounter.count())
        .as("downstream counter value after incrementing")
        .isEqualTo(amountIncrementedAfterConnectingDownstreamRegistry);
  }

  @Test
  public void connectsNewMetersToExistingDownstreamRegistries() {
    metricsSession = new CacheLifecycleMetricsSession(mock(CacheLifecycle.class), compositeRegistry,
        Collections.emptyList());

    MeterRegistry downstreamRegistry = new SimpleMeterRegistry();
    metricsSession.addSubregistry(downstreamRegistry);

    String counterName = "the.counter";
    Counter newCounter = compositeRegistry.counter(counterName);

    Counter downstreamCounter = downstreamRegistry.find(counterName).counter();
    assertThat(downstreamCounter)
        .as("downstream counter before incrementing")
        .isNotNull();

    assertThat(downstreamCounter.count())
        .as("downstream counter value before incrementing")
        .isEqualTo(newCounter.count())
        .isEqualTo(0);

    double amountIncrementedAfterConnectingDownstreamRegistry = 93.0;
    newCounter.increment(amountIncrementedAfterConnectingDownstreamRegistry);

    assertThat(downstreamCounter.count())
        .as("downstream counter value after incrementing")
        .isEqualTo(newCounter.count());
  }

  @Test
  public void cacheCreatedStartsEachMetricsPublishingService() {
    List<MetricsPublishingService> metricsPublishingServices = Arrays.asList(
        metricsPublishingService("metricsPublishingService1"),
        metricsPublishingService("metricsPublishingService2"),
        metricsPublishingService("metricsPublishingService3"));

    metricsSession = new CacheLifecycleMetricsSession(mock(CacheLifecycle.class), compositeRegistry,
        metricsPublishingServices);

    metricsSession.cacheCreated(mock(InternalCache.class));

    for (MetricsPublishingService metricsPublishingService : metricsPublishingServices) {
      verify(metricsPublishingService).start(same(metricsSession));
    }
  }

  @Test
  public void cacheClosedStopsEachMetricsPublishingService() {
    List<MetricsPublishingService> metricsPublishingServices = Arrays.asList(
        metricsPublishingService("metricsPublishingService1"),
        metricsPublishingService("metricsPublishingService2"),
        metricsPublishingService("metricsPublishingService3"));

    metricsSession = new CacheLifecycleMetricsSession(mock(CacheLifecycle.class), compositeRegistry,
        metricsPublishingServices);

    metricsSession.cacheClosed(mock(InternalCache.class));

    for (MetricsPublishingService metricsPublishingService : metricsPublishingServices) {
      verify(metricsPublishingService).stop();
    }
  }

  @Test
  public void cacheClosedDisconnectsAllDownstreamRegistries() {
    metricsSession = new CacheLifecycleMetricsSession(mock(CacheLifecycle.class), compositeRegistry,
        Collections.emptyList());

    MeterRegistry downstreamMeterRegistry1 = new SimpleMeterRegistry();
    MeterRegistry downstreamMeterRegistry2 = new SimpleMeterRegistry();
    MeterRegistry downstreamMeterRegistry3 = new SimpleMeterRegistry();

    metricsSession.addSubregistry(downstreamMeterRegistry1);
    metricsSession.addSubregistry(downstreamMeterRegistry2);
    metricsSession.addSubregistry(downstreamMeterRegistry3);

    metricsSession.cacheClosed(mock(InternalCache.class));

    assertThat(compositeRegistry.getRegistries()).isEmpty();
  }

  @Test
  public void cacheClosedRemovesSessionAsCacheLifecycleListener() {
    CacheLifecycle theCacheLifecycle = mock(CacheLifecycle.class);
    metricsSession =
        new CacheLifecycleMetricsSession(theCacheLifecycle, compositeRegistry,
            Collections.emptyList());

    metricsSession.cacheClosed(mock(InternalCache.class));

    verify(theCacheLifecycle).removeListener(same(metricsSession));
  }

  @Test
  public void cacheCreated_logsErrorMessage_ifMetricsPublishingServiceStartThrowsRuntimeException() {
    MetricsPublishingService metricsPublishingService =
        metricsPublishingService("metricsPublishingService");
    String theClassName = metricsPublishingService.getClass().getName();
    RuntimeException theException = new RuntimeException("theExceptionMessage");
    doThrow(theException).when(metricsPublishingService).start(any());
    List<MetricsPublishingService> metricsPublishingServices =
        Collections.singletonList(metricsPublishingService);
    ErrorLogger errorLogger = mock(ErrorLogger.class);
    metricsSession = new CacheLifecycleMetricsSession(mock(CacheLifecycle.class), compositeRegistry,
        metricsPublishingServices, errorLogger);

    metricsSession.cacheCreated(mock(InternalCache.class));

    verify(errorLogger).logError(anyString(), eq("start"), same(theClassName), same(theException));
  }

  @Test
  public void cacheCreated_logsErrorMessage_ifMetricsPublishingServiceStartThrowsError() {
    MetricsPublishingService metricsPublishingService =
        metricsPublishingService("metricsPublishingService");
    String theClassName = metricsPublishingService.getClass().getName();
    Error theError = new Error("theErrorMessage");
    doThrow(theError).when(metricsPublishingService).start(any());
    List<MetricsPublishingService> metricsPublishingServices =
        Collections.singletonList(metricsPublishingService);
    ErrorLogger errorLogger = mock(ErrorLogger.class);
    metricsSession = new CacheLifecycleMetricsSession(mock(CacheLifecycle.class), compositeRegistry,
        metricsPublishingServices, errorLogger);

    metricsSession.cacheCreated(mock(InternalCache.class));

    verify(errorLogger).logError(anyString(), eq("start"), same(theClassName), same(theError));
  }

  @Test
  public void cacheClosed_logsErrorMessage_ifMetricsPublishingServiceStopThrowsRuntimeException() {
    MetricsPublishingService metricsPublishingService =
        metricsPublishingService("metricsPublishingService");
    String theClassName = metricsPublishingService.getClass().getName();
    RuntimeException theException = new RuntimeException("theExceptionMessage");
    doThrow(theException).when(metricsPublishingService).stop();
    List<MetricsPublishingService> metricsPublishingServices =
        Collections.singletonList(metricsPublishingService);
    ErrorLogger errorLogger = mock(ErrorLogger.class);
    metricsSession = new CacheLifecycleMetricsSession(mock(CacheLifecycle.class), compositeRegistry,
        metricsPublishingServices, errorLogger);

    metricsSession.cacheClosed(mock(InternalCache.class));

    verify(errorLogger).logError(anyString(), eq("stop"), same(theClassName), same(theException));
  }

  @Test
  public void cacheClosed_logsErrorMessage_ifMetricsPublishingServiceStopThrowsError() {
    MetricsPublishingService metricsPublishingService =
        metricsPublishingService("metricsPublishingService");
    String theClassName = metricsPublishingService.getClass().getName();
    Error theError = new Error("theErrorMessage");
    doThrow(theError).when(metricsPublishingService).stop();
    List<MetricsPublishingService> metricsPublishingServices =
        Collections.singletonList(metricsPublishingService);
    ErrorLogger errorLogger = mock(ErrorLogger.class);
    metricsSession = new CacheLifecycleMetricsSession(mock(CacheLifecycle.class), compositeRegistry,
        metricsPublishingServices, errorLogger);

    metricsSession.cacheClosed(mock(InternalCache.class));

    verify(errorLogger).logError(anyString(), eq("stop"), same(theClassName), same(theError));
  }

  private MetricsPublishingService metricsPublishingService(String name) {
    return mock(MetricsPublishingService.class, name);
  }
}
