@Test
  public void modulesShouldBeDelegatedToInRandomOrderWhenOrderClashes()
      throws InterruptedException {
    GraphDatabaseService database =
        builder()
            .setConfig(
                "com.graphaware.module.test1.1",
                TestModuleBootstrapper.MODULE_ENABLED.getDefaultValue())
            .setConfig(
                "com.graphaware.module.test3.1",
                TestModuleBootstrapper.MODULE_ENABLED.getDefaultValue())
            .setConfig(
                "com.graphaware.module.test2.1",
                TestModuleBootstrapper.MODULE_ENABLED.getDefaultValue())
            .newGraphDatabase();

    registerShutdownHook(database);

    try (Transaction tx = database.beginTx()) {
      database.createNode();
      tx.success();
    }

    assertEquals(3, TEST_RUNTIME_MODULES.size());
    Set<String> remaining = new HashSet<>(Arrays.asList("test1", "test2", "test3"));
    assertTrue(remaining.remove(TEST_RUNTIME_MODULES.get(0).getId()));
    assertTrue(remaining.remove(TEST_RUNTIME_MODULES.get(1).getId()));
    assertTrue(remaining.remove(TEST_RUNTIME_MODULES.get(2).getId()));
    assertTrue(remaining.isEmpty());
  }
  @Test
  public void modulesShouldBeDelegatedToInCorrectOrder() throws InterruptedException {
    GraphDatabaseService database =
        builder()
            .setConfig(
                "com.graphaware.module.test1.1",
                TestModuleBootstrapper.MODULE_ENABLED.getDefaultValue())
            .setConfig(
                "com.graphaware.module.test3.3",
                TestModuleBootstrapper.MODULE_ENABLED.getDefaultValue())
            .setConfig(
                "com.graphaware.module.test2.2",
                TestModuleBootstrapper.MODULE_ENABLED.getDefaultValue())
            .newGraphDatabase();

    registerShutdownHook(database);

    try (Transaction tx = database.beginTx()) {
      database.createNode();
      tx.success();
    }

    assertEquals(3, TEST_RUNTIME_MODULES.size());
    assertEquals("test1", TEST_RUNTIME_MODULES.get(0).getId());
    assertEquals("test2", TEST_RUNTIME_MODULES.get(1).getId());
    assertEquals("test3", TEST_RUNTIME_MODULES.get(2).getId());
  }
  @Test
  public void moduleShouldBeInitializedWhenAnotherModuleIsMisConfigured()
      throws InterruptedException {
    GraphDatabaseService database =
        builder()
            .setConfig("com.graphaware.module.wrong1.enabled", "com.not.existent.Bootstrapper")
            .setConfig("com.graphaware.module.wrong2.2", "com.not.existent.Bootstrapper")
            .setConfig(
                TestModuleBootstrapper.MODULE_ENABLED,
                TestModuleBootstrapper.MODULE_ENABLED.getDefaultValue())
            .setConfig(
                TestModuleBootstrapper.MODULE_CONFIG,
                TestModuleBootstrapper.MODULE_CONFIG.getDefaultValue())
            .newGraphDatabase();

    registerShutdownHook(database);

    try (Transaction tx = database.beginTx()) {
      database.createNode();
      tx.success();
    }

    assertEquals(1, TEST_RUNTIME_MODULES.size());
    assertTrue(TEST_RUNTIME_MODULES.get(0).isInitialized());
    assertEquals("configValue", TEST_RUNTIME_MODULES.get(0).getConfig().get("configKey"));

    database.shutdown();

    assertFalse(TEST_RUNTIME_MODULES.get(0).isInitialized());
  }
  @Test
  public void moduleShouldBeInitializedWhenRuntimeIsEnabledWithoutAnyTransactions()
      throws InterruptedException {
    GraphDatabaseService database =
        builder()
            .setConfig(
                TestModuleBootstrapper.MODULE_ENABLED,
                TestModuleBootstrapper.MODULE_ENABLED.getDefaultValue())
            .setConfig(
                TestModuleBootstrapper.MODULE_CONFIG,
                TestModuleBootstrapper.MODULE_CONFIG.getDefaultValue())
            .newGraphDatabase();

    registerShutdownHook(database);

    Thread.sleep(1000);

    assertEquals(1, TEST_RUNTIME_MODULES.size());
    assertTrue(TEST_RUNTIME_MODULES.get(0).isInitialized());
    assertEquals("configValue", TEST_RUNTIME_MODULES.get(0).getConfig().get("configKey"));

    database.shutdown();

    assertFalse(TEST_RUNTIME_MODULES.get(0).isInitialized());
  }
  @Test
  public void moduleShouldBeInitializedWhenRuntimeIsEnabled() throws InterruptedException {
    GraphDatabaseService database =
        builder()
            .setConfig(
                TestModuleBootstrapper.MODULE_ENABLED,
                TestModuleBootstrapper.MODULE_ENABLED.getDefaultValue())
            .setConfig(
                TestModuleBootstrapper.MODULE_CONFIG,
                TestModuleBootstrapper.MODULE_CONFIG.getDefaultValue())
            .newGraphDatabase();

    registerShutdownHook(database);

    try (Transaction tx = database.beginTx()) {
      database.createNode(); // tx just to kick off Runtime init
      tx.success();
    }

    assertEquals(1, TEST_RUNTIME_MODULES.size());
    assertTrue(TEST_RUNTIME_MODULES.get(0).isInitialized());
    assertEquals("configValue", TEST_RUNTIME_MODULES.get(0).getConfig().get("configKey"));

    database.shutdown();

    assertFalse(TEST_RUNTIME_MODULES.get(0).isInitialized());
  }
  @Test
  public void moduleShouldNotBeInitializedWhenRuntimeIsDisabled3() throws InterruptedException {
    GraphDatabaseService database =
        builder()
            .setConfig(RUNTIME_ENABLED, null)
            .setConfig(
                TestModuleBootstrapper.MODULE_ENABLED,
                TestModuleBootstrapper.MODULE_ENABLED.getDefaultValue())
            .newGraphDatabase();

    registerShutdownHook(database);

    assertTrue(TEST_RUNTIME_MODULES.isEmpty());

    database.shutdown();

    assertTrue(TEST_RUNTIME_MODULES.isEmpty());
  }
  @Test(expected = InvalidSettingException.class)
  public void misconfiguredRuntimeShouldFailStartup() throws InterruptedException {
    GraphDatabaseService database =
        builder()
            .setConfig(RUNTIME_ENABLED, "whatever")
            .setConfig(
                TestModuleBootstrapper.MODULE_ENABLED,
                TestModuleBootstrapper.MODULE_ENABLED.getDefaultValue())
            .newGraphDatabase();

    registerShutdownHook(database);

    assertTrue(TEST_RUNTIME_MODULES.isEmpty());

    database.shutdown();

    assertTrue(TEST_RUNTIME_MODULES.isEmpty());
  }