/*
 * 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.cache.control;

import static org.apache.geode.distributed.ConfigurationProperties.MCAST_PORT;
import static org.apache.geode.distributed.ConfigurationProperties.OFF_HEAP_MEMORY_SIZE;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.util.Properties;

import org.apache.logging.log4j.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import org.apache.geode.cache.CacheFactory;
import org.apache.geode.cache.EvictionAlgorithm;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.RegionFactory;
import org.apache.geode.cache.RegionShortcut;
import org.apache.geode.distributed.DistributedSystem;
import org.apache.geode.internal.cache.EvictionAttributesImpl;
import org.apache.geode.internal.cache.GemFireCacheImpl;
import org.apache.geode.internal.cache.control.InternalResourceManager.ResourceType;
import org.apache.geode.logging.internal.log4j.api.LogService;

public class MemoryMonitorOffHeapJUnitTest {
  private static final Logger logger = LogService.getLogger();
  private static final int SYSTEM_LISTENERS = 1;

  DistributedSystem ds;
  GemFireCacheImpl cache;

  @Before
  public void setUp() throws Exception {
    Properties p = new Properties();
    p.setProperty(MCAST_PORT, "0");
    p.setProperty(OFF_HEAP_MEMORY_SIZE, "1m");
    this.ds = DistributedSystem.connect(p);
    this.cache = (GemFireCacheImpl) CacheFactory.create(this.ds);
    logger.info(addExpectedAbove);
    logger.info(addExpectedBelow);
  }

  @After
  public void tearDown() throws Exception {
    try {
      this.cache.close();
      this.ds.disconnect();
    } finally {
      logger.info(removeExpectedAbove);
      logger.info(removeExpectedBelow);
    }
  }

  static final String expectedEx = "Member: .*? above .*? critical threshold";
  public static final String addExpectedAbove =
      "<ExpectedException action=add>" + expectedEx + "</ExpectedException>";
  public static final String removeExpectedAbove =
      "<ExpectedException action=remove>" + expectedEx + "</ExpectedException>";

  static final String expectedBelow = "Member: .*? below .*? critical threshold";
  public static final String addExpectedBelow =
      "<ExpectedException action=add>" + expectedBelow + "</ExpectedException>";
  public static final String removeExpectedBelow =
      "<ExpectedException action=remove>" + expectedBelow + "</ExpectedException>";

  @Test
  public void testGeneratingEvents() throws Exception {
    InternalResourceManager internalManager = this.cache.getInternalResourceManager();
    OffHeapMemoryMonitor monitor = internalManager.getOffHeapMonitor();

    monitor.setEvictionThreshold(50.0f);
    monitor.setCriticalThreshold(75.0f);
    monitor.stopMonitoring(true);

    assertEquals(524288, internalManager.getStats().getOffHeapEvictionThreshold());
    assertEquals(786432, internalManager.getStats().getOffHeapCriticalThreshold());

    // Register a bunch of listeners
    for (int i = 0; i < 10; i++) {
      ResourceListener listener = new TestMemoryThresholdListener();
      internalManager.addResourceListener(ResourceType.OFFHEAP_MEMORY, listener);
    }
    assertEquals(10 + SYSTEM_LISTENERS,
        internalManager.getResourceListeners(ResourceType.OFFHEAP_MEMORY).size());

    // Start at normal
    setThenTestListenersAndStats(400000, 0, 0, 0, 0, 0, 0, 0);

    // Move to eviction
    setThenTestListenersAndStats(550000, 0, 1, 0, 0, 1, 0, 0);

    // Stay at eviction
    setThenTestListenersAndStats(560000, 0, 1, 0, 0, 1, 0, 0);

    // Move to critical
    setThenTestListenersAndStats(850000, 0, 1, 0, 1, 2, 1, 0);

    // Stay at critical (above critical clear margin)
    setThenTestListenersAndStats(786431, 0, 1, 0, 1, 2, 1, 0);
    setThenTestListenersAndStats(765465, 0, 1, 0, 1, 2, 1, 0);

    // Move to eviction
    setThenTestListenersAndStats(765454, 0, 1, 1, 1, 3, 1, 0);

    // Stay at eviction (above eviction clear margin)
    setThenTestListenersAndStats(524281, 0, 1, 1, 1, 3, 1, 0);
    setThenTestListenersAndStats(503321, 0, 1, 1, 1, 3, 1, 0);

    // Move to normal
    setThenTestListenersAndStats(503310, 1, 1, 1, 1, 3, 1, 1);

    // Disable eviction and verify normal event
    monitor.setEvictionThreshold(0f);
    setThenTestListenersAndStats(503315, 1, 1, 1, 1, 3, 1, 2);

    // Enable eviction verify normal event
    monitor.setEvictionThreshold(50f);
    setThenTestListenersAndStats(503315, 1, 1, 1, 1, 3, 1, 3);

    // Disable critical verify normal event
    monitor.setCriticalThreshold(0f);
    setThenTestListenersAndStats(503315, 1, 1, 1, 1, 3, 1, 4);

    // Enable critical verify normal event
    monitor.setCriticalThreshold(75f);
    setThenTestListenersAndStats(503315, 1, 1, 1, 1, 3, 1, 5);
  }

  private void setThenTestListenersAndStats(final long memUsed, final int evictionStop,
      final int evictionStart, final int safe, final int critical, final int evictionEvents,
      final int criticalEvents, final int normalEvents) {
    this.cache.getInternalResourceManager().getOffHeapMonitor().updateStateAndSendEvent(memUsed);
    ResourceManagerStats stats = this.cache.getInternalResourceManager().getStats();

    assertEquals(evictionStop, stats.getOffHeapEvictionStopEvents());
    assertEquals(evictionStart, stats.getOffHeapEvictionStartEvents());
    assertEquals(critical, stats.getOffHeapCriticalEvents());
    assertEquals(safe, stats.getOffHeapSafeEvents());

    for (ResourceListener listener : this.cache.getInternalResourceManager()
        .getResourceListeners(ResourceType.OFFHEAP_MEMORY)) {
      if (listener instanceof TestMemoryThresholdListener) {
        assertEquals(evictionEvents,
            ((TestMemoryThresholdListener) listener).getEvictionThresholdCalls());
        assertEquals(criticalEvents,
            ((TestMemoryThresholdListener) listener).getCriticalThresholdCalls());
        assertEquals(normalEvents, ((TestMemoryThresholdListener) listener).getNormalCalls());
      }
    }
  }

  @Test
  public void testDisabledThresholds() throws Exception {
    final InternalResourceManager irm = this.cache.getInternalResourceManager();
    final OffHeapMemoryMonitor monitor = irm.getOffHeapMonitor();

    final RegionFactory regionFactory = this.cache.createRegionFactory(RegionShortcut.LOCAL);
    regionFactory.setOffHeap(true);
    final EvictionAttributesImpl evictionAttrs = new EvictionAttributesImpl();
    evictionAttrs.setAlgorithm(EvictionAlgorithm.NONE);
    regionFactory.setEvictionAttributes(evictionAttrs);
    final Region region = regionFactory.create("testDefaultThresholdsRegion");
    TestMemoryThresholdListener listener = new TestMemoryThresholdListener();
    irm.addResourceListener(ResourceType.OFFHEAP_MEMORY, listener);

    region.put("1", new Byte[550000]);
    region.put("2", new Byte[200000]);
    assertEquals(0, irm.getStats().getOffHeapEvictionStartEvents());
    assertEquals(0, irm.getStats().getOffHeapEvictionStopEvents());
    assertEquals(0, irm.getStats().getOffHeapCriticalEvents());
    assertEquals(0, irm.getStats().getOffHeapSafeEvents());
    assertEquals(0, listener.getEvictionThresholdCalls());
    assertEquals(0, listener.getCriticalThresholdCalls());

    // Enable eviction threshold and make sure event is generated
    monitor.setEvictionThreshold(50f);
    assertEquals(1, irm.getStats().getOffHeapEvictionStartEvents());
    assertEquals(0, irm.getStats().getOffHeapCriticalEvents());
    assertEquals(1, listener.getEvictionThresholdCalls());
    assertEquals(0, listener.getCriticalThresholdCalls());

    // Enable critical threshold and make sure event is generated
    region.put("3", new Byte[200000]);
    monitor.setCriticalThreshold(70f);
    assertEquals(1, irm.getStats().getOffHeapEvictionStartEvents());
    assertEquals(1, irm.getStats().getOffHeapCriticalEvents());
    assertEquals(2, listener.getEvictionThresholdCalls());
    assertEquals(1, listener.getCriticalThresholdCalls());

    // Disable thresholds and verify events
    monitor.setEvictionThreshold(0f);
    monitor.setCriticalThreshold(0f);

    assertEquals(1, irm.getStats().getOffHeapEvictionStartEvents());
    assertEquals(1, irm.getStats().getOffHeapEvictionStopEvents());
    assertEquals(1, irm.getStats().getOffHeapCriticalEvents());
    assertEquals(1, irm.getStats().getOffHeapSafeEvents());

    assertEquals(2, listener.getEvictionThresholdCalls());
    assertEquals(2, listener.getCriticalThresholdCalls());
    assertEquals(0, listener.getNormalCalls());
    assertEquals(2, listener.getEvictionDisabledCalls());
    assertEquals(2, listener.getCriticalDisabledCalls());
  }

  @Test
  public void testAllowedThreholds() {
    final OffHeapMemoryMonitor monitor =
        this.cache.getInternalResourceManager().getOffHeapMonitor();

    // Test eviction bounds
    try {
      monitor.setEvictionThreshold(100.1f);
      fail("Too high value allowed for setEvictionThreshold");
    } catch (IllegalArgumentException expected) {
      // Expected
    }

    try {
      monitor.setEvictionThreshold(-0.1f);
      fail("Too low value allowed for setEvictionThreshold");
    } catch (IllegalArgumentException expected) {
      // Expected
    }

    monitor.setEvictionThreshold(13f);
    monitor.setEvictionThreshold(0f);
    monitor.setEvictionThreshold(92f);
    monitor.setEvictionThreshold(100f);
    monitor.setEvictionThreshold(0f);

    // Test critical bounds
    try {
      monitor.setCriticalThreshold(100.1f);
      fail("Too high value allowed for setCriticalThreshold");
    } catch (IllegalArgumentException expected) {
      // Expected
    }

    try {
      monitor.setCriticalThreshold(-0.1f);
      fail("Too low value allowed for setCriticalThreshold");
    } catch (IllegalArgumentException expected) {
      // Expected
    }

    monitor.setCriticalThreshold(13f);
    monitor.setCriticalThreshold(0f);
    monitor.setCriticalThreshold(92f);
    monitor.setCriticalThreshold(100f);
    monitor.setCriticalThreshold(0f);

    // Test values relative to each other
    monitor.setEvictionThreshold(1f);
    monitor.setCriticalThreshold(1.1f);
    monitor.setCriticalThreshold(0);
    monitor.setCriticalThreshold(1.1f);
    monitor.setEvictionThreshold(0);
    monitor.setEvictionThreshold(1.0f);
    monitor.setCriticalThreshold(100f);
    monitor.setEvictionThreshold(99.9f);
    monitor.setCriticalThreshold(0f);
    monitor.setEvictionThreshold(0f);
    monitor.setEvictionThreshold(64.1f);
    monitor.setCriticalThreshold(64.2f);

    try {
      monitor.setCriticalThreshold(50f);
      monitor.setEvictionThreshold(50.1f);
      fail("Allowed eviction threshold to be set higher than critical threshold");
    } catch (IllegalArgumentException expected) {
      // Expected
    }
  }

  @Test
  public void testMonitorRunning() {
    final OffHeapMemoryMonitor monitor =
        this.cache.getInternalResourceManager().getOffHeapMonitor();

    assertFalse("Off-heap monitor is not running", monitor.started);

    monitor.setEvictionThreshold(1f);
    assertTrue("Off-heap monitor is running", monitor.started);
    monitor.setEvictionThreshold(0f);
    assertFalse("Off-heap monitor is not running", monitor.started);

    monitor.setCriticalThreshold(1f);
    assertTrue("Off-heap monitor is running", monitor.started);
    monitor.setCriticalThreshold(0f);
    assertFalse("Off-heap monitor is not running", monitor.started);

    monitor.setEvictionThreshold(1f);
    monitor.setCriticalThreshold(1.1f);
    assertTrue("Off-heap monitor is running", monitor.started);

    monitor.setEvictionThreshold(0f);
    monitor.setCriticalThreshold(0f);
    assertFalse("Off-heap monitor is not running", monitor.started);
  }

  @Test
  public void testGettersAndSetters() {
    final OffHeapMemoryMonitor monitor =
        this.cache.getInternalResourceManager().getOffHeapMonitor();

    assertEquals(0f, monitor.getEvictionThreshold(), 0.01);
    assertEquals(0f, monitor.getCriticalThreshold(), 0.01);

    monitor.setEvictionThreshold(35);
    assertEquals(35f, monitor.getEvictionThreshold(), 0.01);
    assertEquals(0f, monitor.getCriticalThreshold(), 0.01);

    monitor.setCriticalThreshold(45);
    assertEquals(35f, monitor.getEvictionThreshold(), 0.01);
    assertEquals(45f, monitor.getCriticalThreshold(), 0.01);

    monitor.setEvictionThreshold(0);
    monitor.setCriticalThreshold(0);
    assertEquals(0f, monitor.getEvictionThreshold(), 0.01);
    assertEquals(0f, monitor.getCriticalThreshold(), 0.01);
  }
}
