Skip to content

Commit

Permalink
Test runtime configuration property quarkus.datasource.active
Browse files Browse the repository at this point in the history
  • Loading branch information
yrodiere committed Jan 17, 2024
1 parent 5bbae6f commit 4f63e89
Show file tree
Hide file tree
Showing 32 changed files with 2,431 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package io.quarkus.agroal.test;

import jakarta.inject.Inject;

import org.eclipse.microprofile.metrics.Counter;
import org.eclipse.microprofile.metrics.Gauge;
import org.eclipse.microprofile.metrics.MetricID;
import org.eclipse.microprofile.metrics.MetricRegistry;
import org.eclipse.microprofile.metrics.Tag;
import org.eclipse.microprofile.metrics.annotation.RegistryType;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.test.QuarkusUnitTest;

public class AgroalMetricsConfigActiveFalseTest {

@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.withConfigurationResource("application-metrics-enabled.properties")
.overrideConfigKey("quarkus.datasource.active", "false")
.overrideConfigKey("quarkus.datasource.ds1.active", "false");

@Inject
@RegistryType(type = MetricRegistry.Type.VENDOR)
MetricRegistry registry;

@Test
public void testMetricsOfDefaultDS() {
Counter acquireCount = registry.getCounters()
.get(new MetricID("agroal.acquire.count", new Tag("datasource", "default")));
Gauge<?> maxUsed = registry.getGauges()
.get(new MetricID("agroal.max.used.count", new Tag("datasource", "default")));

Assertions.assertNull(acquireCount, "Agroal metrics should not be registered for deactivated datasources eagerly");
Assertions.assertNull(maxUsed, "Agroal metrics should not be registered for deactivated datasources eagerly");
}

@Test
public void testMetricsOfDs1() {
Counter acquireCount = registry.getCounters().get(new MetricID("agroal.acquire.count",
new Tag("datasource", "ds1")));
Gauge<?> maxUsed = registry.getGauges().get(new MetricID("agroal.max.used.count",
new Tag("datasource", "ds1")));

Assertions.assertNull(acquireCount, "Agroal metrics should not be registered for deactivated datasources eagerly");
Assertions.assertNull(maxUsed, "Agroal metrics should not be registered for deactivated datasources eagerly");
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package io.quarkus.agroal.test;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

import java.sql.SQLException;

import javax.sql.DataSource;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.CreationException;
import jakarta.inject.Inject;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.agroal.api.AgroalDataSource;
import io.quarkus.arc.Arc;
import io.quarkus.runtime.configuration.ConfigurationException;
import io.quarkus.test.QuarkusUnitTest;

public class ConfigActiveFalseDefaultDatasourceTest {

@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.overrideConfigKey("quarkus.datasource.active", "false");

@Inject
MyBean myBean;

@Test
public void dataSource() {
DataSource ds = Arc.container().instance(DataSource.class).get();

// The bean is always available to be injected during static init
// since we don't know whether the datasource will be active at runtime.
// So the bean cannot be null.
assertThat(ds).isNotNull();
// However, any attempt to use it at runtime will fail.
assertThatThrownBy(() -> ds.getConnection())
.isInstanceOf(RuntimeException.class)
.cause()
.isInstanceOf(ConfigurationException.class)
.hasMessageContainingAll("Datasource '<default>' was deactivated through configuration properties.",
"To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).",
"Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.active'"
+ " to 'true' and configure datasource '<default>'",
"Refer to https://quarkus.io/guides/datasource for guidance.");
}

@Test
public void agroalDataSource() {
AgroalDataSource ds = Arc.container().instance(AgroalDataSource.class).get();

// The bean is always available to be injected during static init
// since we don't know whether the datasource will be active at runtime.
// So the bean cannot be null.
assertThat(ds).isNotNull();
// However, any attempt to use it at runtime will fail.
assertThatThrownBy(() -> ds.getConnection())
.isInstanceOf(RuntimeException.class)
.cause()
.isInstanceOf(ConfigurationException.class)
.hasMessageContainingAll("Datasource '<default>' was deactivated through configuration properties.",
"To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).",
"Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.active'"
+ " to 'true' and configure datasource '<default>'",
"Refer to https://quarkus.io/guides/datasource for guidance.");
}

@Test
public void injectedBean() {
assertThatThrownBy(() -> myBean.useDatasource())
.isInstanceOf(CreationException.class)
.hasMessageContainingAll("Datasource '<default>' was deactivated through configuration properties.",
"To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).",
"Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.active'"
+ " to 'true' and configure datasource '<default>'",
"Refer to https://quarkus.io/guides/datasource for guidance.");
}

@ApplicationScoped
public static class MyBean {
@Inject
DataSource ds;

public void useDatasource() throws SQLException {
ds.getConnection();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package io.quarkus.agroal.test;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

import java.sql.SQLException;

import javax.sql.DataSource;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.CreationException;
import jakarta.inject.Inject;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.arc.Arc;
import io.quarkus.runtime.configuration.ConfigurationException;
import io.quarkus.test.QuarkusUnitTest;

public class ConfigActiveFalseNamedDatasourceTest {

@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.overrideConfigKey("quarkus.datasource.users.active", "false")
// We need at least one build-time property for the datasource,
// otherwise it's considered unconfigured at build time...
.overrideConfigKey("quarkus.datasource.users.db-kind", "h2");

@Inject
MyBean myBean;

@Test
public void dataSource() {
DataSource ds = Arc.container().instance(DataSource.class,
new io.quarkus.agroal.DataSource.DataSourceLiteral("users")).get();

// The bean is always available to be injected during static init
// since we don't know whether the datasource will be active at runtime.
// So the bean cannot be null.
assertThat(ds).isNotNull();
// However, any attempt to use it at runtime will fail.
assertThatThrownBy(() -> ds.getConnection())
.isInstanceOf(RuntimeException.class)
.cause()
.isInstanceOf(ConfigurationException.class)
.hasMessageContainingAll("Datasource 'users' was deactivated through configuration properties.",
"To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).",
"Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.\"users\".active'"
+ " to 'true' and configure datasource 'users'",
"Refer to https://quarkus.io/guides/datasource for guidance.");
}

@Test
public void agroalDataSource() {
DataSource ds = Arc.container().instance(DataSource.class,
new io.quarkus.agroal.DataSource.DataSourceLiteral("users")).get();

// The bean is always available to be injected during static init
// since we don't know whether the datasource will be active at runtime.
// So the bean cannot be null.
assertThat(ds).isNotNull();
// However, any attempt to use it at runtime will fail.
assertThatThrownBy(() -> ds.getConnection())
.isInstanceOf(RuntimeException.class)
.cause()
.isInstanceOf(ConfigurationException.class)
.hasMessageContainingAll("Datasource 'users' was deactivated through configuration properties.",
"To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).",
"Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.\"users\".active'"
+ " to 'true' and configure datasource 'users'",
"Refer to https://quarkus.io/guides/datasource for guidance.");
}

@Test
public void injectedBean() {
assertThatThrownBy(() -> myBean.useDatasource())
.isInstanceOf(CreationException.class)
.hasMessageContainingAll("Datasource 'users' was deactivated through configuration properties.",
"To solve this, avoid accessing this datasource at runtime, for instance by deactivating consumers (persistence units, ...).",
"Alternatively, activate the datasource by setting configuration property 'quarkus.datasource.\"users\".active'"
+ " to 'true' and configure datasource 'users'",
"Refer to https://quarkus.io/guides/datasource for guidance.");
}

@ApplicationScoped
public static class MyBean {
@Inject
@io.quarkus.agroal.DataSource("users")
DataSource ds;

public void useDatasource() throws SQLException {
ds.getConnection();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package io.quarkus.agroal.test;

import org.hamcrest.CoreMatchers;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.quarkus.test.QuarkusUnitTest;
import io.restassured.RestAssured;

public class DataSourceHealthCheckConfigActiveFalseTest {

@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.withEmptyApplication()
.withConfigurationResource("application-default-datasource.properties")
.overrideConfigKey("quarkus.datasource.health.enabled", "true")
// this data source is broken, but will be deactivated,
// so the overall check should pass
.overrideConfigKey("quarkus.datasource.brokenDS.db-kind", "h2")
.overrideConfigKey("quarkus.datasource.brokenDS.jdbc.url", "BROKEN")
.overrideConfigKey("quarkus.datasource.brokenDS.active", "false");

@Test
public void testDataSourceHealthCheckExclusion() {
RestAssured.when().get("/q/health/ready")
.then()
.body("status", CoreMatchers.equalTo("UP"));
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package io.quarkus.agroal.test;

import static org.assertj.core.api.Assertions.assertThatCode;
import static org.assertj.core.api.Assertions.assertThatThrownBy;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.Produces;
import jakarta.inject.Inject;

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

import io.agroal.api.AgroalDataSource;
import io.quarkus.agroal.DataSource;
import io.quarkus.datasource.runtime.DataSourceSupport;
import io.quarkus.test.QuarkusUnitTest;

/**
* Tests a use case where multiple datasources are defined at build time,
* but only one is used at runtime.
* <p>
* This is mostly useful when each datasource has a distinct db-kind, but in theory that shouldn't matter,
* so we use the h2 db-kind everywhere here to keep test dependencies simpler.
* <p>
* See {@link MultipleDataSourcesAsAlternativesWithActiveDS1Test} for the counterpart where PU2 is used at runtime.
*/
public class MultipleDataSourcesAsAlternativesWithActiveDS1Test {

@RegisterExtension
static QuarkusUnitTest runner = new QuarkusUnitTest()
.withApplicationRoot((jar) -> jar
.addClass(MyProducer.class))
.overrideConfigKey("quarkus.datasource.ds-1.db-kind", "h2")
.overrideConfigKey("quarkus.datasource.ds-1.active", "false")
.overrideConfigKey("quarkus.datasource.ds-2.db-kind", "h2")
.overrideConfigKey("quarkus.datasource.ds-2.active", "false")
// This is where we select datasource 1
.overrideRuntimeConfigKey("quarkus.datasource.ds-1.active", "true")
.overrideRuntimeConfigKey("quarkus.datasource.ds-1.jdbc.url", "jdbc:h2:mem:testds1");

@Inject
@DataSource("ds-1")
AgroalDataSource explicitDatasourceBean;

@Inject
AgroalDataSource customIndirectDatasourceBean;

@Inject
@DataSource("ds-2")
AgroalDataSource inactiveDatasourceBean;

@Test
public void testExplicitDatasourceBeanUsable() {
doTestDatasource(explicitDatasourceBean);
}

@Test
public void testCustomIndirectDatasourceBeanUsable() {
doTestDatasource(customIndirectDatasourceBean);
}

@Test
public void testInactiveDatasourceBeanUnusable() {
assertThatThrownBy(() -> inactiveDatasourceBean.getConnection())
.hasMessageContaining("Datasource 'ds-2' was deactivated through configuration properties.");
}

private static void doTestDatasource(AgroalDataSource dataSource) {
assertThatCode(() -> {
try (var connection = dataSource.getConnection()) {
}
})
.doesNotThrowAnyException();
}

private static class MyProducer {
@Inject
DataSourceSupport dataSourceSupport;

@Inject
@DataSource("ds-1")
AgroalDataSource dataSource1Bean;

@Inject
@DataSource("ds-2")
AgroalDataSource dataSource2Bean;

@Produces
@ApplicationScoped
public AgroalDataSource dataSource() {
if (dataSourceSupport.getInactiveNames().contains("ds-1")) {
return dataSource2Bean;
} else {
return dataSource1Bean;
}
}
}
}
Loading

0 comments on commit 4f63e89

Please sign in to comment.