/**
 * Copyright 2015 Netflix, Inc.
 *
 * 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.netflix.spectator.api;

import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;

@RunWith(JUnit4.class)
public class DefaultTimerTest {

  private final ManualClock clock = new ManualClock();

  @Test
  public void testInit() {
    Timer t = new DefaultTimer(clock, NoopId.INSTANCE);
    Assert.assertEquals(t.count(), 0L);
    Assert.assertEquals(t.totalTime(), 0L);
  }

  @Test
  public void testRecord() {
    Timer t = new DefaultTimer(clock, NoopId.INSTANCE);
    t.record(42, TimeUnit.MILLISECONDS);
    Assert.assertEquals(t.count(), 1L);
    Assert.assertEquals(t.totalTime(), 42000000L);
  }

  @Test
  public void testRecordNegative() {
    Timer t = new DefaultTimer(clock, NoopId.INSTANCE);
    t.record(-42, TimeUnit.MILLISECONDS);
    Assert.assertEquals(t.count(), 0L);
    Assert.assertEquals(t.totalTime(), 0L);
  }

  @Test
  public void testRecordZero() {
    Timer t = new DefaultTimer(clock, NoopId.INSTANCE);
    t.record(0, TimeUnit.MILLISECONDS);
    Assert.assertEquals(t.count(), 1L);
    Assert.assertEquals(t.totalTime(), 0L);
  }

  @Test
  public void testRecordCallable() throws Exception {
    Timer t = new DefaultTimer(clock, NoopId.INSTANCE);
    clock.setMonotonicTime(100L);
    int v = t.record(new Callable<Integer>() {
      public Integer call() throws Exception {
        clock.setMonotonicTime(500L);
        return 42;
      }
    });
    Assert.assertEquals(v, 42);
    Assert.assertEquals(t.count(), 1L);
    Assert.assertEquals(t.totalTime(), 400L);
  }

  @Test
  public void testRecordCallableException() throws Exception {
    Timer t = new DefaultTimer(clock, NoopId.INSTANCE);
    clock.setMonotonicTime(100L);
    boolean seen = false;
    try {
      t.record(new Callable<Integer>() {
        public Integer call() throws Exception {
          clock.setMonotonicTime(500L);
          throw new RuntimeException("foo");
        }
      });
    } catch (Exception e) {
      seen = true;
    }
    Assert.assertTrue(seen);
    Assert.assertEquals(t.count(), 1L);
    Assert.assertEquals(t.totalTime(), 400L);
  }

  @Test
  public void testRecordRunnable() throws Exception {
    Timer t = new DefaultTimer(clock, NoopId.INSTANCE);
    clock.setMonotonicTime(100L);
    t.record(new Runnable() {
      public void run() {
        clock.setMonotonicTime(500L);
      }
    });
    Assert.assertEquals(t.count(), 1L);
    Assert.assertEquals(t.totalTime(), 400L);
  }

  @Test
  public void testRecordRunnableException() throws Exception {
    Timer t = new DefaultTimer(clock, NoopId.INSTANCE);
    clock.setMonotonicTime(100L);
    boolean seen = false;
    try {
      t.record(new Runnable() {
        public void run() {
          clock.setMonotonicTime(500L);
          throw new RuntimeException("foo");
        }
      });
    } catch (Exception e) {
      seen = true;
    }
    Assert.assertTrue(seen);
    Assert.assertEquals(t.count(), 1L);
    Assert.assertEquals(t.totalTime(), 400L);
  }

  @Test
  public void testMeasure() {
    Timer t = new DefaultTimer(clock, new DefaultId("foo"));
    t.record(42, TimeUnit.MILLISECONDS);
    clock.setWallTime(3712345L);
    for (Measurement m : t.measure()) {
      Assert.assertEquals(m.timestamp(), 3712345L);
      if (m.id().equals(t.id().withTag(Statistic.count))) {
        Assert.assertEquals(m.value(), 1.0, 0.1e-12);
      } else if (m.id().equals(t.id().withTag(Statistic.totalTime))) {
        Assert.assertEquals(m.value(), 42e6, 0.1e-12);
      } else {
        Assert.fail("unexpected id: " + m.id());
      }
    }
  }

}

@@ -746,46 +746,8 @@
 4;%0A%0A
-import java.util.concurrent.Callable;%0A
 impo
@@ -780,16 +780,16 @@
 meUnit;%0A
+
 %0A@RunWit
@@ -1938,83 +1938,16 @@
 ord(
-new Callable%3CInteger%3E() %7B%0A      public Integer call() throws Exception
+() -%3E
  %7B%0A
-  
     
@@ -1984,18 +1984,16 @@
 ;%0A      
-  
 return 4
@@ -1995,24 +1995,16 @@
 urn 42;%0A
-      %7D%0A
     %7D);%0A
@@ -2342,85 +2342,16 @@
 ord(
-new Callable%3CInteger%3E() %7B%0A        public Integer call() throws Exception
+() -%3E
  %7B%0A
-  
     
@@ -2384,34 +2384,32 @@
 (500L);%0A        
-  
 throw new Runtim
@@ -2394,39 +2394,32 @@
       throw new 
-Runtime
 Exception(%22foo%22)
@@ -2416,34 +2416,24 @@
 ion(%22foo%22);%0A
-        %7D%0A
       %7D);%0A  
@@ -2772,58 +2772,13 @@
 ord(
-new Runnable() %7B%0A      public void run() %7B%0A       
+() -%3E
  clo
@@ -2802,31 +2802,16 @@
 me(500L)
-;%0A      %7D%0A    %7D
 );%0A    A
@@ -3112,50 +3112,13 @@
 ord(
-new Runnable() %7B%0A        public void run()
+() -%3E
  %7B%0A 
@@ -3120,26 +3120,24 @@
 %3E %7B%0A        
- 
- 
 clock.setMon
@@ -3150,26 +3150,24 @@
 Time(500L);%0A
-  
         thro
@@ -3201,18 +3201,8 @@
 %22);%0A
-        %7D%0A
     

add example for using lambda with timer