@Test
  public void testFormatDurationHMS() {
    long time = 0;
    assertEquals("0:00:00.000", DurationFormatUtils.formatDurationHMS(time));

    time = 1;
    assertEquals("0:00:00.001", DurationFormatUtils.formatDurationHMS(time));

    time = 15;
    assertEquals("0:00:00.015", DurationFormatUtils.formatDurationHMS(time));

    time = 165;
    assertEquals("0:00:00.165", DurationFormatUtils.formatDurationHMS(time));

    time = 1675;
    assertEquals("0:00:01.675", DurationFormatUtils.formatDurationHMS(time));

    time = 13465;
    assertEquals("0:00:13.465", DurationFormatUtils.formatDurationHMS(time));

    time = 72789;
    assertEquals("0:01:12.789", DurationFormatUtils.formatDurationHMS(time));

    time = 12789 + 32 * 60000;
    assertEquals("0:32:12.789", DurationFormatUtils.formatDurationHMS(time));

    time = 12789 + 62 * 60000;
    assertEquals("1:02:12.789", DurationFormatUtils.formatDurationHMS(time));
  }
  public Result test(@Param("query") String query) throws SQLException {
    long _start = System.currentTimeMillis();

    HikariDataSource hds = null;
    if (ds instanceof HikariDataSource) {
      hds = (HikariDataSource) ds;
    } else {
      hds = ((P6DataSource) ds).unwrap(HikariDataSource.class);
    }

    if (query != null) {
      //            try(Connection con = DriverManager.getConnection(hds.getJdbcUrl()); Statement
      // stmt = con.createStatement() ){
      try (Connection con = ds.getConnection();
          Statement stmt = con.createStatement()) {
        stmt.execute(query);
      }
    }

    String duration = DurationFormatUtils.formatDurationHMS(System.currentTimeMillis() - _start);

    LOG.info(duration);

    return Results.ok().text().render(duration);
  }
  public Map<String, String> getProperties() {
    Map<String, String> map = new TreeMap<String, String>();
    RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();

    List<String> aList = runtimeMXBean.getInputArguments();
    String parameters = "";
    for (int i = 0; i < aList.size(); i++) {
      parameters = parameters + " " + aList.get(i);
    }
    map.put("params", parameters);

    map.put("name", runtimeMXBean.getVmName());
    map.put("vendor", runtimeMXBean.getVmVendor());
    map.put("version", runtimeMXBean.getVmVersion());
    map.put("specification", runtimeMXBean.getSpecVersion());
    map.put("uptime", DurationFormatUtils.formatDurationHMS(runtimeMXBean.getUptime()));

    Date date = new Date(runtimeMXBean.getStartTime());
    SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
    map.put("start time", sdf.format(date));

    MemoryMXBean memory = ManagementFactory.getMemoryMXBean();

    MemoryUsage heap = memory.getHeapMemoryUsage();
    map.put(
        "memory. (heap)",
        readableFileSize(heap.getUsed())
            + "/"
            + readableFileSize(heap.getCommitted())
            + " min:"
            + readableFileSize(heap.getInit())
            + " max:"
            + readableFileSize(heap.getMax()));
    MemoryUsage nonheap = memory.getNonHeapMemoryUsage();
    map.put(
        "memory (non heap)",
        readableFileSize(nonheap.getUsed())
            + "/"
            + readableFileSize(nonheap.getCommitted())
            + " min:"
            + readableFileSize(nonheap.getInit())
            + " max:"
            + readableFileSize(nonheap.getMax()));

    return map;
  }
  @FilterWith(XSRFFilter.class)
  public Result dryRun(
      Context context, @Param("startDate") String start, @Param("endDate") String end) {
    long _start = System.currentTimeMillis();
    FlashScope flash = context.getFlashScope();

    LocalDate startDate = null;
    LocalDate endDate = null;

    try {
      startDate = LocalDate.parse(start);
      endDate = LocalDate.parse(end);
    } catch (Exception ex) {
    }

    if (startDate == null || endDate == null || startDate.isAfter(endDate)) {
      flash.error("error.invalidDate");
      return Results.redirect(router.getReverseRoute(DebugController.class, "debug"));
    }

    Run lastRun = baseDB.run.findLast(Module.GOOGLE, null, null);
    if (lastRun != null && lastRun.getDay().isAfter(startDate)) {
      flash.error("error.invalidDate");
      return Results.redirect(router.getReverseRoute(DebugController.class, "debug"));
    }

    LocalDate date = LocalDate.from(startDate);

    GoogleSettings ggOptions = googleDB.options.get();

    int minPauseBetweenPageSec = ggOptions.getMinPauseBetweenPageSec();
    int maxPauseBetweenPageSec = ggOptions.getMaxPauseBetweenPageSec();
    ggOptions.setMinPauseBetweenPageSec(0);
    ggOptions.setMaxPauseBetweenPageSec(0);
    googleDB.options.update(ggOptions);

    try {
      while (date.isBefore(endDate)) {
        LOG.debug("dry run {}", date);
        if (!taskManager.startGoogleTask(
            new Run(Run.Mode.MANUAL, Module.GOOGLE, date.atTime(13, 37, 00)))) {
          LOG.error("can't startGoogleTask");
          flash.error("can't startGoogleTask");
          return Results.redirect(router.getReverseRoute(DebugController.class, "debug"));
        }
        taskManager.joinGoogleTask();
        date = date.plusDays(1);
      }
    } catch (Exception ex) {
      LOG.error("an error occured", ex);
      flash.error("an error occured");
      return Results.redirect(router.getReverseRoute(DebugController.class, "debug"));
    } finally {
      ggOptions.setMinPauseBetweenPageSec(minPauseBetweenPageSec);
      ggOptions.setMaxPauseBetweenPageSec(maxPauseBetweenPageSec);
      googleDB.options.update(ggOptions);
    }

    LOG.debug(
        "dry run timing : {}",
        DurationFormatUtils.formatDurationHMS(System.currentTimeMillis() - _start));
    flash.success("ok");
    return Results.redirect(router.getReverseRoute(DebugController.class, "debug"));
  }