package io.vertx.ext.healthchecks;

import io.vertx.core.json.JsonObject;
import io.vertx.ext.jdbc.JDBCClient;
import io.vertx.servicediscovery.ServiceDiscovery;
import io.vertx.servicediscovery.types.HttpEndpoint;
import org.junit.Test;

import java.util.concurrent.atomic.AtomicBoolean;

import static com.jayway.awaitility.Awaitility.await;
import static io.vertx.ext.healthchecks.HealthCheckTest.get;
import static org.hamcrest.Matchers.is;

/**
 * @author <a href="http://escoffier.me">Clement Escoffier</a>
 */
public class CommonHealthChecksTest extends HealthCheckTestBase {

  @Test
  public void testJDBC_OK() {
    JsonObject config = new JsonObject()
      .put("url", "jdbc:hsqldb:mem:test?shutdown=true")
      .put("driver_class", "org.hsqldb.jdbcDriver");
    JDBCClient client = JDBCClient.createShared(vertx, config);

    registerJDBCProcedure(client);
    get(200);
  }

  private void registerJDBCProcedure(JDBCClient client) {
    handler.register("database",
      future -> client.getConnection(connection -> {
        if (connection.failed()) {
          future.fail(connection.cause());
        } else {
          connection.result().close();
          future.complete(Status.OK());
        }
      }));
  }


  @Test
  public void testJDBC_KO() {
    JsonObject config = new JsonObject()
      .put("url", "jdbc:missing:mem:test?shutdown=true")
      .put("driver_class", "org.hsqldb.jdbcDriver");
    JDBCClient client = JDBCClient.createShared(vertx, config);

    registerJDBCProcedure(client);

    // We use 'fail'
    get(500);
  }


  @Test
  public void testServiceAvailability_OK() {
    ServiceDiscovery discovery = ServiceDiscovery.create(vertx);
    AtomicBoolean done = new AtomicBoolean();
    discovery.publish(HttpEndpoint.createRecord("my-service", "localhost"), ar -> {
      done.set(ar.succeeded());
    });
    await().untilAtomic(done, is(true));

    registerServiceProcedure(discovery);
    get(200);
  }

  private void registerServiceProcedure(ServiceDiscovery discovery) {
    handler.register("service",
      future -> HttpEndpoint.getClient(discovery,
        (rec) -> "my-service".equals(rec.getName()),
        client -> {
          if (client.failed()) {
            future.fail(client.cause());
          } else {
            client.result().close();
            future.complete(Status.OK());
          }
        }));
  }

  @Test
  public void testServiceAvailability_KO() {
    ServiceDiscovery discovery = ServiceDiscovery.create(vertx);
    registerServiceProcedure(discovery);
    get(503);
  }

  @Test
  public void testOnEventBus_OK() {
    vertx.eventBus().consumer("health", ar -> {
      ar.reply("pong");
    });

    registerEventBusProcedure();

    get(200);

  }

  private void registerEventBusProcedure() {
    handler.register("receiver",
      future ->
        vertx.eventBus().send("health", "ping", response -> {
          if (response.succeeded()) {
            future.complete(Status.OK());
          } else {
            future.complete(Status.KO());
          }
        })
    );
  }

  @Test
  public void testOnEventBus_KO() {
    vertx.eventBus().consumer("health", ar -> {
      ar.fail(500, "BOOM !");
    });
    registerEventBusProcedure();
    get(503);

  }

  @Test
  public void testOnEventBus_KO_no_receiver() {
    registerEventBusProcedure();
    get(503);

  }


}

@@ -100,24 +100,154 @@
 JDBCClient;%0A
+import io.vertx.ext.unit.junit.Repeat;%0Aimport io.vertx.ext.unit.junit.RepeatRule;%0Aimport io.vertx.ext.unit.junit.VertxUnitRunner;%0A
 import io.ve
@@ -355,20 +355,76 @@
 g.junit.
-Test
+Rule;%0Aimport org.junit.Test;%0Aimport org.junit.runner.RunWith
 ;%0A%0Aimpor
@@ -527,69 +527,8 @@
 it;%0A
-import static io.vertx.ext.healthchecks.HealthCheckTest.get;%0A
 impo
@@ -635,16 +635,48 @@
 /a%3E%0A */%0A
+@RunWith(VertxUnitRunner.class)%0A
 public c
@@ -733,28 +733,96 @@
 tBase %7B%0A%0A  @
-Test
+Rule%0A  public RepeatRule rule = new RepeatRule();%0A%0A  @Test%0A  @Repeat(10)
 %0A  public vo
@@ -1090,31 +1090,156 @@
 lient);%0A    
-get(200
+await().until(() -%3E %7B%0A      try %7B%0A        return get(200) != null;%0A      %7D catch (Exception e) %7B%0A        return false;%0A      %7D%0A    %7D
 );%0A  %7D%0A%0A  pr

Fix tests and add repeat on it.