/**
 * Copyright 2017 Palantir Technologies
 *
 * Licensed under the BSD-3 License (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://opensource.org/licenses/BSD-3-Clause
 *
 * 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.palantir.atlasdb.util;

import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;

import com.codahale.metrics.MetricRegistry;
import com.codahale.metrics.SharedMetricRegistries;
import com.palantir.tritium.metrics.MetricRegistries;

public class AtlasDbMetricsTest {

    @Rule
    public MetricsRule metricsRule = new MetricsRule();

    @Before
    public void before() throws Exception {
        AtlasDbMetrics.metrics = null;
    }

    @Test
    public void metricsIsDefaultWhenNotSet() {
        AtlasDbMetrics.metrics = null;
        assertThat(AtlasDbMetrics.getMetricRegistry(),
                is(equalTo(SharedMetricRegistries.getOrCreate(AtlasDbMetrics.DEFAULT_REGISTRY_NAME))));
    }

    @Test
    public void metricsIsNotDefaultWhenSet() {
        MetricRegistry metricRegistry = mock(MetricRegistry.class);
        AtlasDbMetrics.setMetricRegistry(metricRegistry);
        assertThat(AtlasDbMetrics.getMetricRegistry(), is(equalTo(metricRegistry)));
    }

    @Test(expected = NullPointerException.class)
    public void nullMetricsCannotBeSet() {
        AtlasDbMetrics.setMetricRegistry(null);
    }

    @Test
    public void instrumentWithDefaultName() throws Exception {
        MetricRegistry metrics = MetricRegistries.createWithHdrHistogramReservoirs();
        AtlasDbMetrics.setMetricRegistry(metrics);
        TestService service = AtlasDbMetrics.instrument(TestService.class, () -> "pong");

        String methodTimerName = MetricRegistry.name(TestService.class, "ping");

        assertThat(metrics.timer(methodTimerName).getCount(), is(equalTo(0L)));

        assertThat(service.ping(), is(equalTo("pong")));

        assertThat(metrics.timer(methodTimerName).getCount(), is(equalTo(1L)));
    }

    @Test
    public void instrumentWithCustomName() throws Exception {
        MetricRegistry metrics = MetricRegistries.createWithHdrHistogramReservoirs();
        AtlasDbMetrics.setMetricRegistry(metrics);
        TestService service = AtlasDbMetrics.instrument(TestService.class, () -> "pong", "foo");

        String methodTimerName = "foo.ping";

        assertThat(metrics.timer(methodTimerName).getCount(), is(equalTo(0L)));

        assertThat(service.ping(), is(equalTo("pong")));

        assertThat(metrics.timer(methodTimerName).getCount(), is(equalTo(1L)));
    }

    public interface TestService {
        String ping();
    }

}

@@ -1045,16 +1045,188 @@
 Test %7B%0A%0A
+    private static final String CUSTOM_METRIC_NAME = %22foo%22;%0A    private static final String PING_REQUEST = %22ping%22;%0A    private static final String PING_RESPONSE = %22pong%22;%0A%0A
     @Rul
@@ -2180,84 +2180,8 @@
 s = 
-MetricRegistries.createWithHdrHistogramReservoirs();%0A        AtlasDbMetrics.
 setM
@@ -2186,39 +2186,32 @@
 tMetricRegistry(
-metrics
 );%0A        TestS
@@ -2278,22 +2278,29 @@
 , () -%3E 
-%22pong%22
+PING_RESPONSE
 );%0A%0A    
@@ -2367,22 +2367,28 @@
 .class, 
-%22ping%22
+PING_REQUEST
 );%0A%0A    
@@ -2401,141 +2401,216 @@
 sert
-That(metrics.timer(methodTimerName).getCount(), is(equalTo(0L)));%0A%0A        assertThat(service.ping(), is(equalTo(%22pong%22))
+MetricCountIncrementsAfterPing(metrics, service, methodTimerName);%0A    %7D%0A%0A    @Test%0A    public void instrumentWithCustomName() throws Exception %7B%0A        MetricRegistry metrics = setMetricRegistry(
 );%0A
-%0A
         
 asse
@@ -2609,156 +2609,341 @@
     
-assertThat(metrics.timer(methodTimerName).getCount(), is(equalTo(1L))
+TestService service = AtlasDbMetrics.instrument(TestService.class, () -%3E PING_RESPONSE, CUSTOM_METRIC_NAME);%0A%0A        String methodTimerName = MetricRegistry.name(CUSTOM_METRIC_NAME, PING_REQUEST
 );%0A
+%0A
     
-%7D%0A%0A
     
-@Test%0A    public void instrumentWithCustomName() throws Exception
+assertMetricCountIncrementsAfterPing(metrics, service, methodTimerName);%0A    %7D%0A%0A    private MetricRegistry setMetricRegistry()
  %7B%0A 
@@ -3090,98 +3090,159 @@
     
-TestService service = AtlasDbMetrics.instrument(TestService.class, () -%3E %22pong%22, %22foo%22);%0A%0A
+return metrics;%0A    %7D%0A%0A    private void assertMetricCountIncrementsAfterPing(%0A            MetricRegistry metrics,%0A            TestService service,%0A    
     
@@ -3271,23 +3271,11 @@
 Name
- = %22foo.ping%22;%0A
+) %7B
 %0A   
@@ -3398,22 +3398,29 @@
 equalTo(
-%22pong%22
+PING_RESPONSE
 )));%0A%0A  

Refactor AtlasDBMetricsTest