From 88eddc8c515f7e859b4078e081f37df1af3511c4 Mon Sep 17 00:00:00 2001 From: Martin Simka Date: Tue, 4 Jun 2024 17:07:53 +0200 Subject: [PATCH] [WFLY-15366] split and simplify DataSourceMultipleConnStatsTestCase https://issues.redhat.com/browse/WFLY-15366 The test case was unstable because of missing `ExecutorService.awaitTermination` in the first test so there could still be active requests that could interfere with the second test. Also tests in this test case tested different scenarios with different configurations so I split them into two test cases with two setup tasks. I also removed the asynchronous calls to the servlet. The second test doesn't need an asynchronous call, and the first test only need to add a connection request to queue. --- ...tractDataSourcePoolStatisticsTestCase.java | 66 ++++++ ...ourceMultipleConnStatsServerSetupTask.java | 55 ----- .../DataSourceMultipleConnStatsTestCase.java | 189 ------------------ ...DataSourcePoolClearStatisticsTestCase.java | 127 ++++++++++++ ...rcePoolStatisticsMaxWaitCountTestCase.java | 137 +++++++++++++ .../jca/statistics/SleepServlet.java | 52 ----- 6 files changed, 330 insertions(+), 296 deletions(-) create mode 100644 testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/jca/statistics/AbstractDataSourcePoolStatisticsTestCase.java delete mode 100644 testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/jca/statistics/DataSourceMultipleConnStatsServerSetupTask.java delete mode 100644 testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/jca/statistics/DataSourceMultipleConnStatsTestCase.java create mode 100644 testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/jca/statistics/DataSourcePoolClearStatisticsTestCase.java create mode 100644 testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/jca/statistics/DataSourcePoolStatisticsMaxWaitCountTestCase.java delete mode 100644 testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/jca/statistics/SleepServlet.java diff --git a/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/jca/statistics/AbstractDataSourcePoolStatisticsTestCase.java b/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/jca/statistics/AbstractDataSourcePoolStatisticsTestCase.java new file mode 100644 index 000000000000..0458011d474d --- /dev/null +++ b/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/jca/statistics/AbstractDataSourcePoolStatisticsTestCase.java @@ -0,0 +1,66 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.jboss.as.test.integration.jca.statistics; + +import static org.hamcrest.CoreMatchers.is; +import static org.hamcrest.MatcherAssert.assertThat; + +import java.sql.Connection; +import java.sql.SQLException; +import java.util.Set; +import java.util.concurrent.CopyOnWriteArraySet; +import javax.sql.DataSource; + +import jakarta.annotation.Resource; +import org.jboss.arquillian.test.api.ArquillianResource; +import org.jboss.as.arquillian.container.ManagementClient; +import org.jboss.as.controller.PathAddress; +import org.jboss.as.controller.client.helpers.Operations; +import org.jboss.as.controller.operations.common.Util; +import org.jboss.dmr.ModelNode; + +public abstract class AbstractDataSourcePoolStatisticsTestCase { + + private Set connections = new CopyOnWriteArraySet<>(); + + @ArquillianResource + protected ManagementClient managementClient; + + @Resource(lookup = "java:jboss/datasources/ExampleDS") + private DataSource dataSource; + + // /subsystem=datasources/data-source=ExampleDS/statistics=pool:read-attribute(name=AvailableCount) + protected int readStatisticsAttribute(String attributeName) throws Exception { + PathAddress statisticsPathAddress = PathAddress.parseCLIStyleAddress("/subsystem=datasources/data-source=ExampleDS/statistics=pool"); + ModelNode readAttributeOperation = Util.getReadAttributeOperation(statisticsPathAddress, attributeName); + + ModelNode result = managementClient.getControllerClient().execute(readAttributeOperation); + assertThat("Failed to read statistics: " + result, Operations.isSuccessfulOutcome(result), is(true)); + return Operations.readResult(result).asInt(); + } + + // /subsystem=datasources/data-source=ExampleDS/statistics=pool/clear-statistics + protected void clearStatistics() throws Exception { + PathAddress statisticsPathAddress = PathAddress.parseCLIStyleAddress("/subsystem=datasources/data-source=ExampleDS/statistics=pool/"); + ModelNode operation = Util.createOperation("clear-statistics", statisticsPathAddress); + ModelNode result = managementClient.getControllerClient().execute(operation); + assertThat("Failed to configure connection pool: " + result, Operations.isSuccessfulOutcome(result), is(true)); + } + + protected void allocateConnection() throws SQLException { + connections.add(dataSource.getConnection()); + } + + protected void clearConnections() { + connections.forEach(connection -> { + try { + connection.close(); + } catch (SQLException sqle) { + throw new RuntimeException(sqle); + } + }); + } +} diff --git a/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/jca/statistics/DataSourceMultipleConnStatsServerSetupTask.java b/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/jca/statistics/DataSourceMultipleConnStatsServerSetupTask.java deleted file mode 100644 index 1d9524c2becf..000000000000 --- a/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/jca/statistics/DataSourceMultipleConnStatsServerSetupTask.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright The WildFly Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.jboss.as.test.integration.jca.statistics; - -import org.jboss.as.arquillian.container.ManagementClient; -import org.jboss.as.controller.descriptions.ModelDescriptionConstants; -import org.jboss.as.controller.operations.common.Util; -import org.jboss.as.test.shared.ServerReload; -import org.jboss.as.test.integration.security.common.CoreUtils; -import org.jboss.as.test.shared.SnapshotRestoreSetupTask; -import org.jboss.dmr.ModelNode; - -import java.util.List; - -import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ALLOW_RESOURCE_SERVICE_RESTART; -import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OPERATION_HEADERS; -import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ROLLBACK_ON_RUNTIME_FAILURE; -import static org.jboss.as.test.integration.management.util.ModelUtil.createOpNode; - -/** - * - * Server setup task for the test case DataSourceMultipleConnStatsTestCase. - * Enables statistics and sets min/max pool size on the ExampleDS datasource. - * - * @author Daniel Cihak - */ -public class DataSourceMultipleConnStatsServerSetupTask extends SnapshotRestoreSetupTask { - - @Override - public void doSetup(ManagementClient managementClient, String s) throws Exception { - - ModelNode enableStatsOp = createOpNode("subsystem=datasources/data-source=ExampleDS", ModelDescriptionConstants.WRITE_ATTRIBUTE_OPERATION); - enableStatsOp.get(ModelDescriptionConstants.NAME).set("statistics-enabled"); - enableStatsOp.get(ModelDescriptionConstants.VALUE).set(true); - - ModelNode maxPoolSizeOp = createOpNode("subsystem=datasources/data-source=ExampleDS", ModelDescriptionConstants.WRITE_ATTRIBUTE_OPERATION); - maxPoolSizeOp.get(ModelDescriptionConstants.NAME).set("max-pool-size"); - maxPoolSizeOp.get(ModelDescriptionConstants.VALUE).set(1); - - ModelNode minPoolSizeOp = createOpNode("subsystem=datasources/data-source=ExampleDS", ModelDescriptionConstants.WRITE_ATTRIBUTE_OPERATION); - minPoolSizeOp.get(ModelDescriptionConstants.NAME).set("min-pool-size"); - minPoolSizeOp.get(ModelDescriptionConstants.VALUE).set(1); - - ModelNode updateOp = Util.createCompositeOperation(List.of(enableStatsOp, maxPoolSizeOp, minPoolSizeOp)); - updateOp.get(OPERATION_HEADERS, ROLLBACK_ON_RUNTIME_FAILURE).set(false); - updateOp.get(OPERATION_HEADERS, ALLOW_RESOURCE_SERVICE_RESTART).set(true); - CoreUtils.applyUpdate(updateOp, managementClient.getControllerClient()); - - ServerReload.reloadIfRequired(managementClient); - } - -} diff --git a/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/jca/statistics/DataSourceMultipleConnStatsTestCase.java b/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/jca/statistics/DataSourceMultipleConnStatsTestCase.java deleted file mode 100644 index b2fe6ed4dc4c..000000000000 --- a/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/jca/statistics/DataSourceMultipleConnStatsTestCase.java +++ /dev/null @@ -1,189 +0,0 @@ -/* - * Copyright The WildFly Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.jboss.as.test.integration.jca.statistics; - -import org.jboss.arquillian.container.test.api.Deployment; -import org.jboss.arquillian.container.test.api.RunAsClient; -import org.jboss.arquillian.junit.Arquillian; -import org.jboss.arquillian.junit.InSequence; -import org.jboss.arquillian.test.api.ArquillianResource; -import org.jboss.as.arquillian.api.ContainerResource; -import org.jboss.as.arquillian.api.ServerSetup; -import org.jboss.as.arquillian.container.ManagementClient; -import org.jboss.as.controller.operations.common.Util; -import org.jboss.as.test.shared.ServerReload; -import org.jboss.as.test.integration.common.HttpRequest; -import org.jboss.as.test.integration.management.ManagementOperations; -import org.jboss.as.test.integration.security.common.CoreUtils; -import org.jboss.dmr.ModelNode; -import org.jboss.logging.Logger; -import org.jboss.shrinkwrap.api.ShrinkWrap; -import org.jboss.shrinkwrap.api.asset.StringAsset; -import org.jboss.shrinkwrap.api.spec.WebArchive; -import org.junit.Assert; -import org.junit.Assume; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.net.URL; -import java.util.List; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -import static java.util.concurrent.TimeUnit.SECONDS; -import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ALLOW_RESOURCE_SERVICE_RESTART; -import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.OPERATION_HEADERS; -import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.READ_ATTRIBUTE_OPERATION; -import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.NAME; -import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.ROLLBACK_ON_RUNTIME_FAILURE; -import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.VALUE; -import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.WRITE_ATTRIBUTE_OPERATION; -import static org.jboss.as.test.integration.management.util.ModelUtil.createOpNode; -import static org.junit.Assert.assertEquals; - -/** - * Tests jdbc statistics of a data source with multiple connections. - * - * Test for [ WFLY-14691 ] - * Test for [ WFLY-14789 ] - * - * @author Daniel Cihak - * - */ -@RunWith(Arquillian.class) -@ServerSetup(DataSourceMultipleConnStatsServerSetupTask.class) -@RunAsClient -public class DataSourceMultipleConnStatsTestCase { - - private static final String DEPLOYMENT = "DS_STATISTICS"; - static final Logger LOGGER = Logger.getLogger(DataSourceMultipleConnStatsTestCase.class); - - @ContainerResource - private ManagementClient managementClient; - - @ArquillianResource - private URL url; - - private Runnable sleepServletCall = () -> { - try { - LOGGER.debug("About to call from " + Thread.currentThread().getName()); - String response = HttpRequest.get(url.toExternalForm() + "sleep/", 30, SECONDS); - LOGGER.debug("Finished call from " + Thread.currentThread().getName()); - Assert.assertTrue("Unexpected message from the servlet.", response.contains("Servlet result OK")); - } catch (Exception e) { - throw new RuntimeException("Servlet request processing failed due to " + e.getMessage()); - } - }; - - @Deployment(name = DEPLOYMENT) - public static WebArchive appDeployment1() { - WebArchive war = ShrinkWrap.create(WebArchive.class, DEPLOYMENT + ".war"); - war.addClass(SleepServlet.class); - war.addAsManifestResource(new StringAsset("Dependencies: com.h2database.h2\n"),"MANIFEST.MF"); - return war; - } - - /** - * Tests the data source statistics attribute MaxWaitCount during waiting requests. - * - * Test for [ WFLY-14691 ] - * - * @throws Exception - */ - @InSequence(1) - @Test - public void testDataSourceStatistics() throws Exception { - ExecutorService executor = Executors.newFixedThreadPool(3); - - int maxWaitCount = readAttribute("MaxWaitCount").asInt(); - assertEquals(0, maxWaitCount); - - try { - executor.execute(sleepServletCall); - Thread.sleep(1000L); - executor.execute(sleepServletCall); - Thread.sleep(1000L); - maxWaitCount = readAttribute("MaxWaitCount").asInt(); - assertEquals(1, maxWaitCount); - executor.execute(sleepServletCall); - Thread.sleep(1000L); - maxWaitCount = readAttribute("MaxWaitCount").asInt(); - assertEquals(2, maxWaitCount); - } finally { - executor.shutdown(); - } - } - - /** - * Tests data source statistics after clearStatistics operation was executed. - * - * Test for [ WFLY-14789 ] - * - * @throws Exception - */ - @InSequence(2) - @Test - public void testClearedDataSourceStatistics() throws Exception { - - // Disable for now on Windows until WFLY-15336 is sorted - Assume.assumeTrue("WFLY-15336", System.getProperty("os.name").equalsIgnoreCase("Linux")); - - ExecutorService executor = Executors.newFixedThreadPool(1); - - this.setConnectionPool(); - executor.execute(sleepServletCall); - Thread.sleep(1000L); - this.clearStatistics(); - - int activeCount = readAttribute("ActiveCount").asInt(); - int availableCount = readAttribute("AvailableCount").asInt(); - int createdCount = readAttribute("CreatedCount").asInt(); - int idleCount = readAttribute("IdleCount").asInt(); - int inUseCount = readAttribute("InUseCount").asInt(); - assertEquals(5, activeCount); - assertEquals(4, availableCount); - assertEquals(5, createdCount); - assertEquals(4, idleCount); - assertEquals(1, inUseCount); - } - - // /subsystem=datasources/data-source=ExampleDS/statistics=pool:read-attribute(name=AvailableCount) - private ModelNode readAttribute(String attributeName) throws Exception { - ModelNode operation = createOpNode("subsystem=datasources/data-source=ExampleDS/statistics=pool/", READ_ATTRIBUTE_OPERATION); - operation.get(NAME).set(attributeName); - return ManagementOperations.executeOperation(managementClient.getControllerClient(), operation); - } - - // /subsystem=datasources/data-source=ExampleDS:write-attribute(name=max-pool-size, value=5) - // /subsystem=datasources/data-source=ExampleDS:write-attribute(name=min-pool-size, value=5) - // /subsystem=datasources/data-source=ExampleDS:write-attribute(name=pool-prefill, value=true) - private void setConnectionPool() throws Exception { - ModelNode maxPoolSizeOp = createOpNode("subsystem=datasources/data-source=ExampleDS", WRITE_ATTRIBUTE_OPERATION); - maxPoolSizeOp.get(NAME).set("max-pool-size"); - maxPoolSizeOp.get(VALUE).set(5); - - ModelNode minPoolSizeOp = createOpNode("subsystem=datasources/data-source=ExampleDS", WRITE_ATTRIBUTE_OPERATION); - minPoolSizeOp.get(NAME).set("min-pool-size"); - minPoolSizeOp.get(VALUE).set(5); - - ModelNode prefillOp = createOpNode("subsystem=datasources/data-source=ExampleDS", WRITE_ATTRIBUTE_OPERATION); - prefillOp.get(NAME).set("pool-prefill"); - prefillOp.get(VALUE).set(true); - - ModelNode updateOp = Util.createCompositeOperation(List.of(maxPoolSizeOp, minPoolSizeOp, prefillOp)); - updateOp.get(OPERATION_HEADERS, ROLLBACK_ON_RUNTIME_FAILURE).set(false); - updateOp.get(OPERATION_HEADERS, ALLOW_RESOURCE_SERVICE_RESTART).set(true); - CoreUtils.applyUpdate(updateOp, managementClient.getControllerClient()); - - ServerReload.reloadIfRequired(managementClient); - } - - // /subsystem=datasources/data-source=ExampleDS/statistics=pool/clear-statistics - private void clearStatistics() throws Exception { - ModelNode operation = createOpNode("subsystem=datasources/data-source=ExampleDS/statistics=pool/", "clear-statistics"); - ManagementOperations.executeOperation(managementClient.getControllerClient(), operation); - } -} diff --git a/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/jca/statistics/DataSourcePoolClearStatisticsTestCase.java b/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/jca/statistics/DataSourcePoolClearStatisticsTestCase.java new file mode 100644 index 000000000000..4a7cc8439b70 --- /dev/null +++ b/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/jca/statistics/DataSourcePoolClearStatisticsTestCase.java @@ -0,0 +1,127 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.jboss.as.test.integration.jca.statistics; + +import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.*; +import static org.jboss.as.test.integration.management.util.ModelUtil.createOpNode; +import static org.jboss.as.test.shared.PermissionUtils.createPermissionsXmlAsset; +import static org.junit.Assert.assertEquals; + +import java.io.FilePermission; +import java.util.List; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.as.arquillian.api.ServerSetup; +import org.jboss.as.arquillian.container.ManagementClient; +import org.jboss.as.controller.descriptions.ModelDescriptionConstants; +import org.jboss.as.controller.operations.common.Util; +import org.jboss.as.test.integration.security.common.CoreUtils; +import org.jboss.as.test.shared.ServerReload; +import org.jboss.as.test.shared.SnapshotRestoreSetupTask; +import org.jboss.dmr.ModelNode; +import org.jboss.remoting3.security.RemotingPermission; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * + * Test for WFLY-14789 + *

+ * Tests that the clearStatistics operation on a datasource pool doesn't clear some attributes that are not supposed to be cleared. + * + * @author Daniel Cihak + */ +@RunWith(Arquillian.class) +@ServerSetup(DataSourcePoolClearStatisticsTestCase.FixedSizePrefillPoolServerSetupTask.class) +public class DataSourcePoolClearStatisticsTestCase extends AbstractDataSourcePoolStatisticsTestCase { + + @Deployment(name = DEPLOYMENT) + public static WebArchive appDeployment() { + WebArchive war = ShrinkWrap.create(WebArchive.class, DataSourcePoolClearStatisticsTestCase.class.getName() + ".war"); + war.addAsManifestResource(new StringAsset("Dependencies: org.jboss.as.controller," + + // Needed for RemotingPermission class if security manager is enabled + (System.getProperty("security.manager") == null ? "" : "org.jboss.remoting,") + + "org.jboss.dmr\n"), "MANIFEST.MF"); + war.addAsManifestResource(createPermissionsXmlAsset( + new RemotingPermission("createEndpoint"), + new RemotingPermission("connect"), + new FilePermission(System.getProperty("jboss.inst") + "/standalone/tmp/auth/*", "read") + ), "permissions.xml"); + war.addClass(AbstractDataSourcePoolStatisticsTestCase.class); + return war; + } + + /** + * Tests data source statistics after clearStatistics operation was executed. + *

+ * Test for WFLY-14789 + * + * @throws Exception + */ + @Test + public void testClearedDataSourceStatistics() throws Exception { + try { + allocateConnection(); + + clearStatistics(); + + int activeCount = readStatisticsAttribute("ActiveCount"); + int availableCount = readStatisticsAttribute("AvailableCount"); + int createdCount = readStatisticsAttribute("CreatedCount"); + int idleCount = readStatisticsAttribute("IdleCount"); + int inUseCount = readStatisticsAttribute("InUseCount"); + assertEquals(5, activeCount); + assertEquals(4, availableCount); + assertEquals(5, createdCount); + assertEquals(4, idleCount); + assertEquals(1, inUseCount); + } finally { + clearConnections(); + } + } + + /** + * Server setup task for the test case DataSourcePoolClearStatisticsTestCase. + * Enables statistics and pool-prefill, and sets min-pool-size=max-pool-size=5 on the ExampleDS datasource. + */ + public static class FixedSizePrefillPoolServerSetupTask extends SnapshotRestoreSetupTask { + + @Override + public void doSetup(ManagementClient managementClient, String s) throws Exception { + // /subsystem=datasources/data-source=ExampleDS:write-attribute(name=statistics-enabled, value=true) + // /subsystem=datasources/data-source=ExampleDS:write-attribute(name=max-pool-size, value=5) + // /subsystem=datasources/data-source=ExampleDS:write-attribute(name=min-pool-size, value=5) + // /subsystem=datasources/data-source=ExampleDS:write-attribute(name=pool-prefill, value=true) + + ModelNode enableStatsOp = createOpNode("subsystem=datasources/data-source=ExampleDS", ModelDescriptionConstants.WRITE_ATTRIBUTE_OPERATION); + enableStatsOp.get(ModelDescriptionConstants.NAME).set("statistics-enabled"); + enableStatsOp.get(ModelDescriptionConstants.VALUE).set(true); + + ModelNode maxPoolSizeOp = createOpNode("subsystem=datasources/data-source=ExampleDS", WRITE_ATTRIBUTE_OPERATION); + maxPoolSizeOp.get(NAME).set("max-pool-size"); + maxPoolSizeOp.get(VALUE).set(5); + + ModelNode minPoolSizeOp = createOpNode("subsystem=datasources/data-source=ExampleDS", WRITE_ATTRIBUTE_OPERATION); + minPoolSizeOp.get(NAME).set("min-pool-size"); + minPoolSizeOp.get(VALUE).set(5); + + ModelNode prefillOp = createOpNode("subsystem=datasources/data-source=ExampleDS", WRITE_ATTRIBUTE_OPERATION); + prefillOp.get(NAME).set("pool-prefill"); + prefillOp.get(VALUE).set(true); + + ModelNode updateOp = Util.createCompositeOperation(List.of(enableStatsOp, maxPoolSizeOp, minPoolSizeOp, prefillOp)); + updateOp.get(OPERATION_HEADERS, ROLLBACK_ON_RUNTIME_FAILURE).set(false); + updateOp.get(OPERATION_HEADERS, ALLOW_RESOURCE_SERVICE_RESTART).set(true); + CoreUtils.applyUpdate(updateOp, managementClient.getControllerClient()); + + ServerReload.reloadIfRequired(managementClient); + } + } +} diff --git a/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/jca/statistics/DataSourcePoolStatisticsMaxWaitCountTestCase.java b/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/jca/statistics/DataSourcePoolStatisticsMaxWaitCountTestCase.java new file mode 100644 index 000000000000..c9b662a2b53e --- /dev/null +++ b/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/jca/statistics/DataSourcePoolStatisticsMaxWaitCountTestCase.java @@ -0,0 +1,137 @@ +/* + * Copyright The WildFly Authors + * SPDX-License-Identifier: Apache-2.0 + */ + +package org.jboss.as.test.integration.jca.statistics; + +import static org.jboss.as.controller.descriptions.ModelDescriptionConstants.*; +import static org.jboss.as.test.integration.management.util.ModelUtil.createOpNode; +import static org.jboss.as.test.shared.PermissionUtils.createPermissionsXmlAsset; +import static org.junit.Assert.assertEquals; + +import java.io.FilePermission; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +import org.jboss.arquillian.container.test.api.Deployment; +import org.jboss.arquillian.junit.Arquillian; +import org.jboss.as.arquillian.api.ServerSetup; +import org.jboss.as.arquillian.container.ManagementClient; +import org.jboss.as.controller.descriptions.ModelDescriptionConstants; +import org.jboss.as.controller.operations.common.Util; +import org.jboss.as.test.integration.security.common.CoreUtils; +import org.jboss.as.test.shared.ServerReload; +import org.jboss.as.test.shared.SnapshotRestoreSetupTask; +import org.jboss.dmr.ModelNode; +import org.jboss.remoting3.security.RemotingPermission; +import org.jboss.shrinkwrap.api.ShrinkWrap; +import org.jboss.shrinkwrap.api.asset.StringAsset; +import org.jboss.shrinkwrap.api.spec.WebArchive; +import org.junit.Test; +import org.junit.runner.RunWith; + +/** + * Test for WFLY-14691 + *

+ * Tests that MaxWaitCount pool statistics attribute is correct. + * + * @author Daniel Cihak + */ +@RunWith(Arquillian.class) +@ServerSetup(DataSourcePoolStatisticsMaxWaitCountTestCase.MinimalPoolServerSetupTask.class) +public class DataSourcePoolStatisticsMaxWaitCountTestCase extends AbstractDataSourcePoolStatisticsTestCase { + + @Deployment(name = DEPLOYMENT) + public static WebArchive appDeployment() { + WebArchive war = ShrinkWrap.create(WebArchive.class, DataSourcePoolStatisticsMaxWaitCountTestCase.class.getName() + ".war"); + war.addAsManifestResource(new StringAsset("Dependencies: org.jboss.as.controller," + + // Needed for RemotingPermission class if security manager is enabled + (System.getProperty("security.manager") == null ? "" : "org.jboss.remoting,") + + "org.jboss.dmr\n"), "MANIFEST.MF"); + war.addAsManifestResource(createPermissionsXmlAsset( + new RemotingPermission("createEndpoint"), + new RemotingPermission("connect"), + new FilePermission(System.getProperty("jboss.inst") + "/standalone/tmp/auth/*", "read"), + new RuntimePermission("modifyThread") + ), "permissions.xml"); + war.addClass(AbstractDataSourcePoolStatisticsTestCase.class); + return war; + } + + private Runnable allocateConnectionsCall = () -> { + try { + allocateConnection(); + } catch (Exception e) { + throw new RuntimeException(e); + } + }; + + /** + * Tests the data source statistics attribute MaxWaitCount during waiting requests. + *

+ * Test for WFLY-14691 + * + * @throws Exception + */ + @Test + public void testDataSourceStatistics() throws Exception { + ExecutorService executor = Executors.newFixedThreadPool(3); + + int maxWaitCount = readStatisticsAttribute("MaxWaitCount"); + assertEquals(0, maxWaitCount); + + try { + executor.execute(allocateConnectionsCall); + Thread.sleep(1000L); + executor.execute(allocateConnectionsCall); + Thread.sleep(1000L); + maxWaitCount = readStatisticsAttribute("MaxWaitCount"); + assertEquals(1, maxWaitCount); + executor.execute(allocateConnectionsCall); + Thread.sleep(1000L); + maxWaitCount = readStatisticsAttribute("MaxWaitCount"); + assertEquals(2, maxWaitCount); + } finally { + executor.shutdownNow(); + executor.awaitTermination(10, TimeUnit.SECONDS); + clearConnections(); + } + } + + + /** + * Server setup task for the test case DataSourcePoolStatisticsMaxWaitCountTestCase. + * Enables statistics and sets min-pool-size=max-pool-size=1 on the ExampleDS datasource. + */ + public static class MinimalPoolServerSetupTask extends SnapshotRestoreSetupTask { + + @Override + public void doSetup(ManagementClient managementClient, String s) throws Exception { + // /subsystem=datasources/data-source=ExampleDS:write-attribute(name=statistics-enabled, value=true) + // /subsystem=datasources/data-source=ExampleDS:write-attribute(name=max-pool-size, value=1) + // /subsystem=datasources/data-source=ExampleDS:write-attribute(name=min-pool-size, value=1) + + ModelNode enableStatsOp = createOpNode("subsystem=datasources/data-source=ExampleDS", ModelDescriptionConstants.WRITE_ATTRIBUTE_OPERATION); + enableStatsOp.get(ModelDescriptionConstants.NAME).set("statistics-enabled"); + enableStatsOp.get(ModelDescriptionConstants.VALUE).set(true); + + ModelNode maxPoolSizeOp = createOpNode("subsystem=datasources/data-source=ExampleDS", ModelDescriptionConstants.WRITE_ATTRIBUTE_OPERATION); + maxPoolSizeOp.get(ModelDescriptionConstants.NAME).set("max-pool-size"); + maxPoolSizeOp.get(ModelDescriptionConstants.VALUE).set(1); + + ModelNode minPoolSizeOp = createOpNode("subsystem=datasources/data-source=ExampleDS", ModelDescriptionConstants.WRITE_ATTRIBUTE_OPERATION); + minPoolSizeOp.get(ModelDescriptionConstants.NAME).set("min-pool-size"); + minPoolSizeOp.get(ModelDescriptionConstants.VALUE).set(1); + + ModelNode updateOp = Util.createCompositeOperation(List.of(enableStatsOp, maxPoolSizeOp, minPoolSizeOp)); + updateOp.get(OPERATION_HEADERS, ROLLBACK_ON_RUNTIME_FAILURE).set(false); + updateOp.get(OPERATION_HEADERS, ALLOW_RESOURCE_SERVICE_RESTART).set(true); + CoreUtils.applyUpdate(updateOp, managementClient.getControllerClient()); + + ServerReload.reloadIfRequired(managementClient); + } + } +} diff --git a/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/jca/statistics/SleepServlet.java b/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/jca/statistics/SleepServlet.java deleted file mode 100644 index 20b952d94967..000000000000 --- a/testsuite/integration/basic/src/test/java/org/jboss/as/test/integration/jca/statistics/SleepServlet.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright The WildFly Authors - * SPDX-License-Identifier: Apache-2.0 - */ - -package org.jboss.as.test.integration.jca.statistics; - -import org.jboss.logging.Logger; - -import jakarta.annotation.Resource; -import jakarta.servlet.ServletException; -import jakarta.servlet.annotation.WebServlet; -import jakarta.servlet.http.HttpServlet; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import javax.sql.DataSource; -import java.io.IOException; -import java.io.PrintWriter; -import java.sql.Connection; - -@SuppressWarnings("serial") -@WebServlet(name = "sleep", urlPatterns = {"/sleep/"}, loadOnStartup = 1) -public class SleepServlet extends HttpServlet { - - private Logger LOGGER = Logger.getLogger("SleepServlet"); - - @Resource(lookup = "java:jboss/datasources/ExampleDS") - private DataSource dataSource; - - @Override - protected void doGet(HttpServletRequest request, HttpServletResponse response) - throws ServletException, IOException { - Connection con = null; - - try { - dataSource.getConnection(); - - LOGGER.debug("## SLEEP START"); - Thread.sleep(3000L); - LOGGER.debug("## SLEEP END"); - } catch (Exception e) { - LOGGER.debug("Exception occured " + e.getMessage()); - } finally { - try { con.close(); } catch (Exception ee) {} - } - - response.setContentType("text/plain"); - final PrintWriter writer = response.getWriter(); - writer.write("Servlet result OK"); - writer.close(); - } -}