package org.apache.helix.monitoring.mbeans;

/*
 * 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.
 */

import java.lang.management.ManagementFactory;
import java.util.HashSet;
import java.util.Set;
import javax.management.AttributeNotFoundException;
import javax.management.JMException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;

import org.apache.helix.PropertyType;
import org.testng.Assert;
import org.testng.annotations.Test;

public class TestRoutingTableProviderMonitor {

  private MBeanServer _beanServer = ManagementFactory.getPlatformMBeanServer();

  private final String TEST_CLUSTER = "test_cluster";

  private ObjectName buildObjectName(PropertyType type, String cluster)
      throws MalformedObjectNameException {
    return MBeanRegistrar.buildObjectName(MonitorDomainNames.RoutingTableProvider.name(),
        RoutingTableProviderMonitor.CLUSTER_KEY, cluster, RoutingTableProviderMonitor.DATA_TYPE_KEY,
        type.name());
  }

  private ObjectName buildObjectName(PropertyType type, String cluster, int num)
      throws MalformedObjectNameException {
    ObjectName objectName = buildObjectName(type, cluster);
    if (num > 0) {
      return new ObjectName(String
          .format("%s,%s=%s", objectName.toString(), MBeanRegistrar.DUPLICATE,
              String.valueOf(num)));
    } else {
      return objectName;
    }
  }

  @Test
  public void testMBeanRegisteration() throws JMException {
    Set<RoutingTableProviderMonitor> monitors = new HashSet<>();
    for (PropertyType type : PropertyType.values()) {
      monitors.add(new RoutingTableProviderMonitor(type, TEST_CLUSTER).register());
      Assert.assertTrue(_beanServer.isRegistered(buildObjectName(type, TEST_CLUSTER)));
    }

    for (PropertyType type : PropertyType.values()) {
      monitors.add(new RoutingTableProviderMonitor(type, TEST_CLUSTER).register());
      Assert.assertTrue(_beanServer.isRegistered(buildObjectName(type, TEST_CLUSTER, 1)));
    }

    for (PropertyType type : PropertyType.values()) {
      monitors.add(new RoutingTableProviderMonitor(type, TEST_CLUSTER).register());
      Assert.assertTrue(_beanServer.isRegistered(buildObjectName(type, TEST_CLUSTER, 2)));
    }

    // Un-register all monitors
    for (RoutingTableProviderMonitor monitor : monitors) {
      monitor.unregister();
    }

    for (PropertyType type : PropertyType.values()) {
      Assert.assertFalse(_beanServer.isRegistered(buildObjectName(type, TEST_CLUSTER)));
      Assert.assertFalse(_beanServer.isRegistered(buildObjectName(type, TEST_CLUSTER, 1)));
      Assert.assertFalse(_beanServer.isRegistered(buildObjectName(type, TEST_CLUSTER, 2)));
    }
  }

  @Test
  public void testMetrics() throws JMException, InterruptedException {
    PropertyType type = PropertyType.EXTERNALVIEW;
    RoutingTableProviderMonitor monitor = new RoutingTableProviderMonitor(type, TEST_CLUSTER);
    monitor.register();
    ObjectName name = buildObjectName(type, TEST_CLUSTER);

    monitor.increaseCallbackCounters(10);
    Assert.assertEquals((long) _beanServer.getAttribute(name, "CallbackCounter"), 1);
    Assert.assertEquals((long) _beanServer.getAttribute(name, "EventQueueSizeGauge"), 10);
    monitor.increaseCallbackCounters(15);
    Assert.assertEquals((long) _beanServer.getAttribute(name, "CallbackCounter"), 2);
    Assert.assertEquals((long) _beanServer.getAttribute(name, "EventQueueSizeGauge"), 15);
    Assert.assertEquals((long) _beanServer.getAttribute(name, "DataRefreshLatencyGauge.Max"), 0);
    Assert.assertEquals((long) _beanServer.getAttribute(name, "DataRefreshCounter"), 0);

    // StatePropagationLatencyGauge only apply for current state
    try {
      _beanServer.getAttribute(name, "StatePropagationLatencyGauge.Max");
      Assert.fail();
    } catch (AttributeNotFoundException ex) {
      // Expected AttributeNotFoundException because the metric does not exist in
      // MBean server.
    }

    long startTime = System.currentTimeMillis();
    Thread.sleep(5);
    monitor.increaseDataRefreshCounters(startTime);
    long latency = (long) _beanServer.getAttribute(name, "DataRefreshLatencyGauge.Max");
    Assert.assertTrue(latency >= 5 && latency <= System.currentTimeMillis() - startTime);
    Assert.assertEquals((long) _beanServer.getAttribute(name, "DataRefreshCounter"), 1);

    monitor.increaseDataRefreshCounters(startTime);
    long newLatency = (long) _beanServer.getAttribute(name, "DataRefreshLatencyGauge.Max");
    Assert.assertTrue(newLatency >= latency);
    Assert.assertEquals((long) _beanServer.getAttribute(name, "DataRefreshCounter"), 2);

    monitor.unregister();
  }

  public void testCurrentStateMetrics() throws JMException, InterruptedException {
    PropertyType type = PropertyType.CURRENTSTATES;
    RoutingTableProviderMonitor monitor = new RoutingTableProviderMonitor(type, TEST_CLUSTER);
    monitor.register();
    ObjectName name = buildObjectName(type, TEST_CLUSTER);

    monitor.increaseCallbackCounters(10);
    Assert.assertEquals((long) _beanServer.getAttribute(name, "StatePropagationLatencyGauge.Max"), 0);

    monitor.recordStatePropagationLatency(5);
    long statelatency = (long) _beanServer.getAttribute(name, "StatePropagationLatencyGauge.Max");
    Assert.assertEquals(statelatency, 5);
    monitor.recordStatePropagationLatency(10);
    statelatency = (long) _beanServer.getAttribute(name, "StatePropagationLatencyGauge.Max");
    Assert.assertEquals(statelatency, 10);

    monitor.unregister();
  }
}
