@Test
public void timer() throws Exception {

  InstrumentationService.Timer timer = new InstrumentationService.Timer(2);
  InstrumentationService.Cron cron = new InstrumentationService.Cron();
  long ownStart;
  long ownEnd;
  long totalStart;
  long totalEnd;
  long ownDelta;
  long totalDelta;
  long avgTotal;
  long avgOwn;
  cron.start();
  ownStart = Time.now();
  totalStart = ownStart;
  ownDelta = 0;
  sleep(100);
  cron.stop();
  ownEnd = Time.now();
  ownDelta += ownEnd - ownStart;
  sleep(100);
  cron.start();
  ownStart = Time.now();
  sleep(100);
  cron.stop();
  ownEnd = Time.now();
  ownDelta += ownEnd - ownStart;
  totalEnd = ownEnd;
  totalDelta = totalEnd - totalStart;
  avgTotal = totalDelta;
  avgOwn = ownDelta;
  timer.addCron(cron);
  long[] values = timer.getValues();
  assertEquals(values[InstrumentationService.Timer.LAST_TOTAL], totalDelta, 20);
  assertEquals(values[InstrumentationService.Timer.LAST_OWN], ownDelta, 20);
  assertEquals(values[InstrumentationService.Timer.AVG_TOTAL], avgTotal, 20);
  assertEquals(values[InstrumentationService.Timer.AVG_OWN], avgOwn, 20);
  cron = new InstrumentationService.Cron();
  cron.start();
  ownStart = Time.now();
  totalStart = ownStart;
  ownDelta = 0;
  sleep(200);
  cron.stop();
  ownEnd = Time.now();
  ownDelta += ownEnd - ownStart;
  sleep(200);
  cron.start();
  ownStart = Time.now();
  sleep(200);
  cron.stop();
  ownEnd = Time.now();
  ownDelta += ownEnd - ownStart;
  totalEnd = ownEnd;
  totalDelta = totalEnd - totalStart;
  avgTotal = (avgTotal * 1 + totalDelta) / 2;
  avgOwn = (avgOwn * 1 + ownDelta) / 2;
  timer.addCron(cron);
  values = timer.getValues();
  assertEquals(values[InstrumentationService.Timer.LAST_TOTAL], totalDelta, 20);
  assertEquals(values[InstrumentationService.Timer.LAST_OWN], ownDelta, 20);
  assertEquals(values[InstrumentationService.Timer.AVG_TOTAL], avgTotal, 20);
  assertEquals(values[InstrumentationService.Timer.AVG_OWN], avgOwn, 20);
  avgTotal = totalDelta;
  avgOwn = ownDelta;
  cron = new InstrumentationService.Cron();
  cron.start();
  ownStart = Time.now();
  totalStart = ownStart;
  ownDelta = 0;
  sleep(300);
  cron.stop();
  ownEnd = Time.now();
  ownDelta += ownEnd - ownStart;
  sleep(300);
  cron.start();
  ownStart = Time.now();
  sleep(300);
  cron.stop();
  ownEnd = Time.now();
  ownDelta += ownEnd - ownStart;
  totalEnd = ownEnd;
  totalDelta = totalEnd - totalStart;
  avgTotal = (avgTotal * 1 + totalDelta) / 2;
  avgOwn = (avgOwn * 1 + ownDelta) / 2;
  cron.stop();
  timer.addCron(cron);
  values = timer.getValues();
  assertEquals(values[InstrumentationService.Timer.LAST_TOTAL], totalDelta, 20);
  assertEquals(values[InstrumentationService.Timer.LAST_OWN], ownDelta, 20);
  assertEquals(values[InstrumentationService.Timer.AVG_TOTAL], avgTotal, 20);
  assertEquals(values[InstrumentationService.Timer.AVG_OWN], avgOwn, 20);
  JSONObject json = (JSONObject) new JSONParser().parse(timer.toJSONString());
  assertEquals(json.size(), 4);
  assertEquals(json.get("lastTotal"), values[InstrumentationService.Timer.LAST_TOTAL]);
  assertEquals(json.get("lastOwn"), values[InstrumentationService.Timer.LAST_OWN]);
  assertEquals(json.get("avgTotal"), values[InstrumentationService.Timer.AVG_TOTAL]);
  assertEquals(json.get("avgOwn"), values[InstrumentationService.Timer.AVG_OWN]);
  StringWriter writer = new StringWriter();
  timer.writeJSONString(writer);
  writer.close();
  json = (JSONObject) new JSONParser().parse(writer.toString());
  assertEquals(json.size(), 4);
  assertEquals(json.get("lastTotal"), values[InstrumentationService.Timer.LAST_TOTAL]);
  assertEquals(json.get("lastOwn"), values[InstrumentationService.Timer.LAST_OWN]);
  assertEquals(json.get("avgTotal"), values[InstrumentationService.Timer.AVG_TOTAL]);
  assertEquals(json.get("avgOwn"), values[InstrumentationService.Timer.AVG_OWN]);
}