Skip to content

Commit

Permalink
Merge pull request #43537 from yrodiere/datasource-more-tests
Browse files Browse the repository at this point in the history
Datasource-related refactorings of tests (and some utils)
  • Loading branch information
gsmet authored Sep 28, 2024
2 parents cb455a3 + 2633fb6 commit 2811eec
Show file tree
Hide file tree
Showing 129 changed files with 3,771 additions and 1,769 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package io.quarkus.agroal.deployment;

import jakarta.enterprise.inject.Default;

import org.jboss.jandex.AnnotationInstance;

import io.quarkus.agroal.DataSource;
import io.quarkus.arc.processor.DotNames;
import io.quarkus.datasource.common.runtime.DataSourceUtil;

public final class AgroalDataSourceBuildUtil {
private AgroalDataSourceBuildUtil() {
}

public static AnnotationInstance qualifier(String dataSourceName) {
if (DataSourceUtil.isDefault(dataSourceName)) {
return AnnotationInstance.builder(Default.class).build();
} else {
return AnnotationInstance.builder(DataSource.class).value(dataSourceName).build();
}
}

public static AnnotationInstance[] qualifiers(String dataSourceName) {
if (DataSourceUtil.isDefault(dataSourceName)) {
return new AnnotationInstance[] { AnnotationInstance.builder(Default.class).build() };
} else {
return new AnnotationInstance[] {
AnnotationInstance.builder(DotNames.NAMED).value(dataSourceName).build(),
AnnotationInstance.builder(DataSource.class).value(dataSourceName).build(),
};
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.quarkus.agroal.deployment;

import static io.quarkus.agroal.deployment.AgroalDataSourceBuildUtil.qualifiers;
import static io.quarkus.deployment.Capability.OPENTELEMETRY_TRACER;

import java.sql.Driver;
Expand All @@ -16,7 +17,6 @@
import javax.sql.XADataSource;

import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.inject.Default;

import org.jboss.jandex.ClassType;
import org.jboss.jandex.DotName;
Expand Down Expand Up @@ -284,22 +284,18 @@ void generateDataSourceBeans(AgroalRecorder recorder,
.addType(DATA_SOURCE)
.addType(AGROAL_DATA_SOURCE)
.scope(ApplicationScoped.class)
.qualifiers(qualifiers(dataSourceName))
.setRuntimeInit()
.unremovable()
.addInjectionPoint(ClassType.create(DotName.createSimple(DataSources.class)))
// pass the runtime config into the recorder to ensure that the DataSource related beans
// are created after runtime configuration has been set up
.createWith(recorder.agroalDataSourceSupplier(dataSourceName, dataSourcesRuntimeConfig));

if (aggregatedBuildTimeConfigBuildItem.isDefault()) {
configurator.addQualifier(Default.class);
} else {
if (!DataSourceUtil.isDefault(dataSourceName)) {
// this definitely not ideal, but 'elytron-jdbc-security' uses it (although it could be easily changed)
// which means that perhaps other extensions might depend on this as well...
configurator.name(dataSourceName);

configurator.addQualifier().annotation(DotNames.NAMED).addValue("value", dataSourceName).done();
configurator.addQualifier().annotation(DataSource.class).addValue("value", dataSourceName).done();
}

syntheticBeanBuildItemBuildProducer.produce(configurator.done());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package io.quarkus.agroal.test;

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

import javax.sql.DataSource;

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.InjectableInstance;
import io.quarkus.runtime.configuration.ConfigurationException;
import io.quarkus.test.QuarkusUnitTest;

public class ConfigActiveFalseDefaultDatasourceDynamicInjectionTest {

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

@Inject
InjectableInstance<DataSource> dataSource;

@Inject
InjectableInstance<AgroalDataSource> agroalDataSource;

@Test
public void dataSource() {
doTest(dataSource);
}

@Test
public void agroalDataSource() {
doTest(agroalDataSource);
}

private void doTest(InjectableInstance<? extends DataSource> instance) {
// 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 proxy cannot be null.
var ds = instance.get();
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.");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,24 +7,23 @@
import io.quarkus.test.QuarkusUnitTest;
import io.restassured.RestAssured;

public class DataSourceHealthCheckConfigActiveFalseTest {
public class ConfigActiveFalseDefaultDatasourceHealthCheckTest {

@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.withEmptyApplication()
.withConfigurationResource("application-default-datasource.properties")
.overrideConfigKey("quarkus.datasource.health.enabled", "true")
.overrideConfigKey("quarkus.datasource.active", "false")
// 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");
.overrideConfigKey("quarkus.datasource.jdbc.url", "BROKEN");

@Test
public void testDataSourceHealthCheckExclusion() {
RestAssured.when().get("/q/health/ready")
.then()
.body("status", CoreMatchers.equalTo("UP"));
.body("status", CoreMatchers.equalTo("UP"))
// If the datasource is inactive, there should not be a health check
.body("checks[0].data.\"<default>\"", CoreMatchers.nullValue());
}

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

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.test.QuarkusUnitTest;

public class ConfigActiveFalseDefaultDatasourceStaticInjectionTest {

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

@Inject
MyBean myBean;

@Test
public void test() {
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();
}
}
}

This file was deleted.

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

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

import javax.sql.DataSource;

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.InjectableInstance;
import io.quarkus.runtime.configuration.ConfigurationException;
import io.quarkus.test.QuarkusUnitTest;

public class ConfigActiveFalseNamedDatasourceDynamicInjectionTest {

@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
@io.quarkus.agroal.DataSource("users")
InjectableInstance<DataSource> dataSource;

@Inject
@io.quarkus.agroal.DataSource("users")
InjectableInstance<AgroalDataSource> agroalDataSource;

@Test
public void dataSource() {
doTest(dataSource);
}

@Test
public void agroalDataSource() {
doTest(agroalDataSource);
}

private void doTest(InjectableInstance<? extends DataSource> instance) {
// 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.
var ds = instance.get();
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.");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
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 ConfigActiveFalseNamedDatasourceHealthCheckTest {

@RegisterExtension
static final QuarkusUnitTest config = new QuarkusUnitTest()
.overrideConfigKey("quarkus.datasource.health.enabled", "true")
.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")
// this data source is broken, but will be deactivated,
// so the overall check should pass
.overrideConfigKey("quarkus.datasource.users.jdbc.url", "BROKEN");

@Test
public void testDataSourceHealthCheckExclusion() {
RestAssured.when().get("/q/health/ready")
.then()
.body("status", CoreMatchers.equalTo("UP"))
// If the datasource is inactive, there should not be a health check
.body("checks[0].data.\"users\"", CoreMatchers.nullValue());
}

}
Loading

0 comments on commit 2811eec

Please sign in to comment.