// Copyright 2020 The Bazel Authors. All rights reserved.
//
// 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.devtools.build.lib.metrics;

import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth8.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.argThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.withSettings;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.bugreport.BugReporter;
import com.google.devtools.build.lib.metrics.PostGCMemoryUseRecorder.PeakHeap;
import com.google.devtools.build.lib.testutil.ManualClock;
import com.sun.management.GarbageCollectionNotificationInfo;
import com.sun.management.GcInfo;
import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.MemoryUsage;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
import javax.management.Notification;
import javax.management.NotificationEmitter;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/** Unit tests for {@link PostGCMemoryUseRecorder}. */
@RunWith(JUnit4.class)
public final class PostGCMemoryUseRecorderTest {

  private final ManualClock clock = new ManualClock();

  @Test
  public void listenToSingleNonCopyGC() {
    List<GarbageCollectorMXBean> beans = createGCBeans(new String[] {"FooGC"});

    PostGCMemoryUseRecorder rec = new PostGCMemoryUseRecorder(beans, BugReporter.defaultInstance());
    verify((NotificationEmitter) beans.get(0), times(1)).addNotificationListener(rec, null, null);
  }

  @Test
  public void listenToMultipleNonCopyGCs() {
    List<GarbageCollectorMXBean> beans = createGCBeans(new String[] {"FooGC", "BarGC"});

    PostGCMemoryUseRecorder rec = new PostGCMemoryUseRecorder(beans, BugReporter.defaultInstance());
    verify((NotificationEmitter) beans.get(0), times(1)).addNotificationListener(rec, null, null);
    verify((NotificationEmitter) beans.get(1), times(1)).addNotificationListener(rec, null, null);
  }

  @Test
  public void dontListenToCopyGC() {
    List<GarbageCollectorMXBean> beans = createGCBeans(new String[] {"FooGC", "Copy"});

    PostGCMemoryUseRecorder rec = new PostGCMemoryUseRecorder(beans, BugReporter.defaultInstance());
    verify((NotificationEmitter) beans.get(0), times(1)).addNotificationListener(rec, null, null);
    verify((NotificationEmitter) beans.get(1), never())
        .addNotificationListener(
            any(NotificationListener.class), any(NotificationFilter.class), any());
  }

  @Test
  public void peakHeapsStartAbsent() {
    PostGCMemoryUseRecorder rec =
        new PostGCMemoryUseRecorder(new ArrayList<>(), BugReporter.defaultInstance());
    assertThat(rec.getPeakPostGcHeap()).isEmpty();
    assertThat(rec.getPeakPostGcHeapTenuredSpace()).isEmpty();
  }

  @Test
  public void peakHeapsAbsentAfterReset() {
    PostGCMemoryUseRecorder rec =
        new PostGCMemoryUseRecorder(new ArrayList<>(), BugReporter.defaultInstance());
    rec.handleNotification(
        createOneTenuredSpaceOneNonTenuredSpaceMajorGCNotifications(1000L), null);
    rec.reset();
    assertThat(rec.getPeakPostGcHeap()).isEmpty();
    assertThat(rec.getPeakPostGcHeapTenuredSpace()).isEmpty();
  }

  @Test
  public void noGcCauseEventsNotIgnored() {
    PostGCMemoryUseRecorder underTest =
        new PostGCMemoryUseRecorder(ImmutableList.of(), BugReporter.defaultInstance());
    Notification notificationWithNoGcCause =
        createMockNotification(
            GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION,
            "end of major GC",
            /*cause=*/ "No GC",
            ImmutableMap.of("somepool", 100L),
            /*memUsedBefore=*/ null);

    underTest.handleNotification(notificationWithNoGcCause, /*handback=*/ null);

    assertThat(underTest.getPeakPostGcHeap())
        .hasValue(PeakHeap.create(100, clock.currentTimeMillis()));
    assertThat(underTest.getPeakPostGcHeapTenuredSpace())
        .hasValue(PeakHeap.create(0, clock.currentTimeMillis()));
  }

  @Test
  public void peakHeapsIncreaseWhenBigger() {
    PostGCMemoryUseRecorder rec =
        new PostGCMemoryUseRecorder(new ArrayList<>(), BugReporter.defaultInstance());

    clock.advanceMillis(1);
    rec.handleNotification(
        createOneTenuredSpaceOneNonTenuredSpaceMajorGCNotifications(1000L), null);
    assertThat(rec.getPeakPostGcHeap()).hasValue(PeakHeap.create(2000, clock.currentTimeMillis()));
    assertThat(rec.getPeakPostGcHeapTenuredSpace())
        .hasValue(PeakHeap.create(1000, clock.currentTimeMillis()));

    clock.advanceMillis(1);
    rec.handleNotification(
        createOneTenuredSpaceOneNonTenuredSpaceMajorGCNotifications(1001L), null);
    assertThat(rec.getPeakPostGcHeap()).hasValue(PeakHeap.create(2002, clock.currentTimeMillis()));
    assertThat(rec.getPeakPostGcHeapTenuredSpace())
        .hasValue(PeakHeap.create(1001, clock.currentTimeMillis()));

    clock.advanceMillis(1);
    rec.handleNotification(
        createOneTenuredSpaceOneNonTenuredSpaceMajorGCNotifications(1002L), null);
    assertThat(rec.getPeakPostGcHeap()).hasValue(PeakHeap.create(2004, clock.currentTimeMillis()));
    assertThat(rec.getPeakPostGcHeapTenuredSpace())
        .hasValue(PeakHeap.create(1002, clock.currentTimeMillis()));
  }

  @Test
  public void peakHeapsDontDecrease() {
    PostGCMemoryUseRecorder rec =
        new PostGCMemoryUseRecorder(new ArrayList<>(), BugReporter.defaultInstance());

    clock.advanceMillis(1);
    rec.handleNotification(createOneTenuredSpaceOneNonTenuredSpaceMajorGCNotifications(1000), null);
    PeakHeap expectedTotal = PeakHeap.create(2000, clock.currentTimeMillis());
    PeakHeap expectedTenuredSpace = PeakHeap.create(1000, clock.currentTimeMillis());

    clock.advanceMillis(1);
    rec.handleNotification(createOneTenuredSpaceOneNonTenuredSpaceMajorGCNotifications(500), null);
    assertThat(rec.getPeakPostGcHeap()).hasValue(expectedTotal);
    assertThat(rec.getPeakPostGcHeapTenuredSpace()).hasValue(expectedTenuredSpace);

    clock.advanceMillis(1);
    rec.handleNotification(createOneTenuredSpaceOneNonTenuredSpaceMajorGCNotifications(999), null);
    assertThat(rec.getPeakPostGcHeap()).hasValue(expectedTotal);
    assertThat(rec.getPeakPostGcHeapTenuredSpace()).hasValue(expectedTenuredSpace);
  }

  @Test
  public void ignoreNonGCNotification() {
    PostGCMemoryUseRecorder rec =
        new PostGCMemoryUseRecorder(new ArrayList<>(), BugReporter.defaultInstance());
    rec.handleNotification(
        createMockNotification(
            "some other notification", "end of major GC", ImmutableMap.of("Foo", 1000L)),
        null);
    assertThat(rec.getPeakPostGcHeap()).isEmpty();
    assertThat(rec.getPeakPostGcHeapTenuredSpace()).isEmpty();
  }

  @Test
  public void ignoreNonMajorGCNotification() {
    PostGCMemoryUseRecorder rec =
        new PostGCMemoryUseRecorder(new ArrayList<>(), BugReporter.defaultInstance());
    rec.handleNotification(
        createMockNotification(
            GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION,
            "end of minor GC",
            ImmutableMap.of("Foo", 1000L)),
        null);
    assertThat(rec.getPeakPostGcHeap()).isEmpty();
    assertThat(rec.getPeakPostGcHeapTenuredSpace()).isEmpty();
  }

  @Test
  public void sumMemUsageInfo() {
    PostGCMemoryUseRecorder rec =
        new PostGCMemoryUseRecorder(new ArrayList<>(), BugReporter.defaultInstance());
    rec.handleNotification(
        createMajorGCNotification(
            ImmutableMap.of("Foo", 111L, "Bar", 222L, "Qux", 333L, "CMS Old Gen", 111L)),
        null);
    assertThat(rec.getPeakPostGcHeap()).hasValue(PeakHeap.create(777, clock.currentTimeMillis()));
    assertThat(rec.getPeakPostGcHeapTenuredSpace())
        .hasValue(PeakHeap.create(111, clock.currentTimeMillis()));
  }

  @Test
  public void memoryUsageReportedZeroGetsSetAndStaysSet() {
    PostGCMemoryUseRecorder rec =
        new PostGCMemoryUseRecorder(new ArrayList<>(), BugReporter.defaultInstance());
    assertThat(rec.wasMemoryUsageReportedZero()).isFalse();
    rec.handleNotification(
        createMajorGCNotification(ImmutableMap.of("Foo", 0L, "Bar", 0L, "Qux", 0L)), null);
    assertThat(rec.wasMemoryUsageReportedZero()).isTrue();
    rec.handleNotification(
        createMajorGCNotification(ImmutableMap.of("Foo", 123L, "Bar", 456L, "Qux", 789L)), null);
    assertThat(rec.wasMemoryUsageReportedZero()).isTrue();
  }

  @Test
  public void memoryUsageReportedZeroDoesntGetSet() {
    PostGCMemoryUseRecorder rec =
        new PostGCMemoryUseRecorder(new ArrayList<>(), BugReporter.defaultInstance());
    assertThat(rec.wasMemoryUsageReportedZero()).isFalse();
    rec.handleNotification(
        createMajorGCNotification(ImmutableMap.of("Foo", 123L, "Bar", 456L, "Qux", 789L)), null);
    assertThat(rec.wasMemoryUsageReportedZero()).isFalse();
  }

  @Test
  public void totalGarbageReported() {
    PostGCMemoryUseRecorder rec =
        new PostGCMemoryUseRecorder(new ArrayList<>(), BugReporter.defaultInstance());
    assertThat(rec.getGarbageStats()).isEmpty();

    rec.handleNotification(
        createMockNotification(
            GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION,
            "action",
            "cause",
            ImmutableMap.of("old", 1000L, "young", 2000L),
            ImmutableMap.of("old", 5000L, "young", 10000L)),
        /* handback= */ null);
    assertThat(rec.getGarbageStats()).containsExactly("old", 4000L, "young", 8000L);
    rec.handleNotification(
        createMockNotification(
            GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION,
            "action",
            "cause",
            ImmutableMap.of("young", 15000L),
            ImmutableMap.of("young", 20000L)),
        /* handback= */ null);
    assertThat(rec.getGarbageStats()).containsExactly("old", 4000L, "young", 13000L);

    rec.reset();
    assertThat(rec.getGarbageStats()).isEmpty();
  }

  @Test
  public void moreThanOneTenuredSpaceEventReportsBug() {
    BugReporter bugReporter = mock(BugReporter.class);
    PostGCMemoryUseRecorder rec = new PostGCMemoryUseRecorder(new ArrayList<>(), bugReporter);
    rec.handleNotification(
        createMajorGCNotification(ImmutableMap.of("CMS Old Gen", 111L, "PS Old Gen", 111L)), null);
    verify(bugReporter)
        .sendBugReport(
            argThat(
                e ->
                    e.getMessage()
                        .contains(
                            "More than one tenured space event was recorded during garbage"
                                + " collection.")));
  }

  private static GarbageCollectorMXBean createMXBeanWithName(String name) {
    GarbageCollectorMXBean b =
        mock(
            GarbageCollectorMXBean.class,
            withSettings().extraInterfaces(NotificationEmitter.class));
    when(b.getName()).thenReturn(name);
    return b;
  }

  private static List<GarbageCollectorMXBean> createGCBeans(String[] names) {
    List<GarbageCollectorMXBean> beans = new ArrayList<>();
    for (String n : names) {
      beans.add(createMXBeanWithName(n));
    }
    return beans;
  }

  private static MemoryUsage createMockMemoryUsage(long used) {
    MemoryUsage mu = mock(MemoryUsage.class);
    when(mu.getUsed()).thenReturn(used);
    return mu;
  }

  private static ImmutableMap<String, MemoryUsage> createMemoryUsageMap(Map<String, Long> memUsed) {
    ImmutableMap.Builder<String, MemoryUsage> memUsageMap = ImmutableMap.builder();
    for (Map.Entry<String, Long> e : memUsed.entrySet()) {
      memUsageMap.put(e.getKey(), createMockMemoryUsage(e.getValue()));
    }
    return memUsageMap.build();
  }

  private Notification createMockNotification(
      String type, String action, Map<String, Long> memUsed) {
    return createMockNotification(type, action, "dummycause", memUsed, /* memUsedBefore= */ null);
  }

  private Notification createMockNotification(
      String type,
      String action,
      String cause,
      Map<String, Long> memUsed,
      @Nullable Map<String, Long> memUsedBefore) {
    GcInfo gcInfo = mock(GcInfo.class);
    ImmutableMap<String, MemoryUsage> memoryUsageMap = createMemoryUsageMap(memUsed);
    when(gcInfo.getMemoryUsageAfterGc()).thenReturn(memoryUsageMap);
    if (memUsedBefore != null) {
      ImmutableMap<String, MemoryUsage> memoryUsageBeforeMap = createMemoryUsageMap(memUsedBefore);
      when(gcInfo.getMemoryUsageBeforeGc()).thenReturn(memoryUsageBeforeMap);
    }

    GarbageCollectionNotificationInfo notInfo =
        new GarbageCollectionNotificationInfo("DummyGCName", action, cause, gcInfo);

    Notification n = mock(Notification.class);
    when(n.getType()).thenReturn(type);
    when(n.getUserData()).thenReturn(notInfo.toCompositeData(null));
    when(n.getTimeStamp()).thenReturn(clock.currentTimeMillis());
    return n;
  }

  private Notification createMajorGCNotification(Map<String, Long> memUsed) {
    return createMockNotification(
        GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION,
        "end of major GC",
        memUsed);
  }

  private Notification createOneTenuredSpaceOneNonTenuredSpaceMajorGCNotifications(long used) {
    return createMajorGCNotification(ImmutableMap.of("Foo", used, "CMS Old Gen", used));
  }
}
